|
1 /** |
|
2 * QEMU RTL8139 emulation |
|
3 * |
|
4 * Copyright (c) 2006 Igor Kovalenko |
|
5 * |
|
6 * Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 * of this software and associated documentation files (the "Software"), to deal |
|
8 * in the Software without restriction, including without limitation the rights |
|
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 * copies of the Software, and to permit persons to whom the Software is |
|
11 * furnished to do so, subject to the following conditions: |
|
12 * |
|
13 * The above copyright notice and this permission notice shall be included in |
|
14 * all copies or substantial portions of the Software. |
|
15 * |
|
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 * THE SOFTWARE. |
|
23 |
|
24 * Modifications: |
|
25 * 2006-Jan-28 Mark Malakanov : TSAD and CSCR implementation (for Windows driver) |
|
26 * |
|
27 * 2006-Apr-28 Juergen Lock : EEPROM emulation changes for FreeBSD driver |
|
28 * HW revision ID changes for FreeBSD driver |
|
29 * |
|
30 * 2006-Jul-01 Igor Kovalenko : Implemented loopback mode for FreeBSD driver |
|
31 * Corrected packet transfer reassembly routine for 8139C+ mode |
|
32 * Rearranged debugging print statements |
|
33 * Implemented PCI timer interrupt (disabled by default) |
|
34 * Implemented Tally Counters, increased VM load/save version |
|
35 * Implemented IP/TCP/UDP checksum task offloading |
|
36 * |
|
37 * 2006-Jul-04 Igor Kovalenko : Implemented TCP segmentation offloading |
|
38 * Fixed MTU=1500 for produced ethernet frames |
|
39 * |
|
40 * 2006-Jul-09 Igor Kovalenko : Fixed TCP header length calculation while processing |
|
41 * segmentation offloading |
|
42 * Removed slirp.h dependency |
|
43 * Added rx/tx buffer reset when enabling rx/tx operation |
|
44 */ |
|
45 |
|
46 #include "hw.h" |
|
47 #include "pci.h" |
|
48 #include "qemu-timer.h" |
|
49 #include "net.h" |
|
50 |
|
51 /* debug RTL8139 card */ |
|
52 //#define DEBUG_RTL8139 1 |
|
53 |
|
54 #define PCI_FREQUENCY 33000000L |
|
55 |
|
56 /* debug RTL8139 card C+ mode only */ |
|
57 //#define DEBUG_RTL8139CP 1 |
|
58 |
|
59 /* Calculate CRCs properly on Rx packets */ |
|
60 #define RTL8139_CALCULATE_RXCRC 1 |
|
61 |
|
62 /* Uncomment to enable on-board timer interrupts */ |
|
63 //#define RTL8139_ONBOARD_TIMER 1 |
|
64 |
|
65 #if defined(RTL8139_CALCULATE_RXCRC) |
|
66 /* For crc32 */ |
|
67 #include <zlib.h> |
|
68 #endif |
|
69 |
|
70 #define SET_MASKED(input, mask, curr) \ |
|
71 ( ( (input) & ~(mask) ) | ( (curr) & (mask) ) ) |
|
72 |
|
73 /* arg % size for size which is a power of 2 */ |
|
74 #define MOD2(input, size) \ |
|
75 ( ( input ) & ( size - 1 ) ) |
|
76 |
|
77 #if defined (DEBUG_RTL8139) |
|
78 # define DEBUG_PRINT(x) do { printf x ; } while (0) |
|
79 #else |
|
80 # define DEBUG_PRINT(x) |
|
81 #endif |
|
82 |
|
83 /* Symbolic offsets to registers. */ |
|
84 enum RTL8139_registers { |
|
85 MAC0 = 0, /* Ethernet hardware address. */ |
|
86 MAR0 = 8, /* Multicast filter. */ |
|
87 TxStatus0 = 0x10,/* Transmit status (Four 32bit registers). C mode only */ |
|
88 /* Dump Tally Conter control register(64bit). C+ mode only */ |
|
89 TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ |
|
90 RxBuf = 0x30, |
|
91 ChipCmd = 0x37, |
|
92 RxBufPtr = 0x38, |
|
93 RxBufAddr = 0x3A, |
|
94 IntrMask = 0x3C, |
|
95 IntrStatus = 0x3E, |
|
96 TxConfig = 0x40, |
|
97 RxConfig = 0x44, |
|
98 Timer = 0x48, /* A general-purpose counter. */ |
|
99 RxMissed = 0x4C, /* 24 bits valid, write clears. */ |
|
100 Cfg9346 = 0x50, |
|
101 Config0 = 0x51, |
|
102 Config1 = 0x52, |
|
103 FlashReg = 0x54, |
|
104 MediaStatus = 0x58, |
|
105 Config3 = 0x59, |
|
106 Config4 = 0x5A, /* absent on RTL-8139A */ |
|
107 HltClk = 0x5B, |
|
108 MultiIntr = 0x5C, |
|
109 PCIRevisionID = 0x5E, |
|
110 TxSummary = 0x60, /* TSAD register. Transmit Status of All Descriptors*/ |
|
111 BasicModeCtrl = 0x62, |
|
112 BasicModeStatus = 0x64, |
|
113 NWayAdvert = 0x66, |
|
114 NWayLPAR = 0x68, |
|
115 NWayExpansion = 0x6A, |
|
116 /* Undocumented registers, but required for proper operation. */ |
|
117 FIFOTMS = 0x70, /* FIFO Control and test. */ |
|
118 CSCR = 0x74, /* Chip Status and Configuration Register. */ |
|
119 PARA78 = 0x78, |
|
120 PARA7c = 0x7c, /* Magic transceiver parameter register. */ |
|
121 Config5 = 0xD8, /* absent on RTL-8139A */ |
|
122 /* C+ mode */ |
|
123 TxPoll = 0xD9, /* Tell chip to check Tx descriptors for work */ |
|
124 RxMaxSize = 0xDA, /* Max size of an Rx packet (8169 only) */ |
|
125 CpCmd = 0xE0, /* C+ Command register (C+ mode only) */ |
|
126 IntrMitigate = 0xE2, /* rx/tx interrupt mitigation control */ |
|
127 RxRingAddrLO = 0xE4, /* 64-bit start addr of Rx ring */ |
|
128 RxRingAddrHI = 0xE8, /* 64-bit start addr of Rx ring */ |
|
129 TxThresh = 0xEC, /* Early Tx threshold */ |
|
130 }; |
|
131 |
|
132 enum ClearBitMasks { |
|
133 MultiIntrClear = 0xF000, |
|
134 ChipCmdClear = 0xE2, |
|
135 Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), |
|
136 }; |
|
137 |
|
138 enum ChipCmdBits { |
|
139 CmdReset = 0x10, |
|
140 CmdRxEnb = 0x08, |
|
141 CmdTxEnb = 0x04, |
|
142 RxBufEmpty = 0x01, |
|
143 }; |
|
144 |
|
145 /* C+ mode */ |
|
146 enum CplusCmdBits { |
|
147 CPlusRxVLAN = 0x0040, /* enable receive VLAN detagging */ |
|
148 CPlusRxChkSum = 0x0020, /* enable receive checksum offloading */ |
|
149 CPlusRxEnb = 0x0002, |
|
150 CPlusTxEnb = 0x0001, |
|
151 }; |
|
152 |
|
153 /* Interrupt register bits, using my own meaningful names. */ |
|
154 enum IntrStatusBits { |
|
155 PCIErr = 0x8000, |
|
156 PCSTimeout = 0x4000, |
|
157 RxFIFOOver = 0x40, |
|
158 RxUnderrun = 0x20, |
|
159 RxOverflow = 0x10, |
|
160 TxErr = 0x08, |
|
161 TxOK = 0x04, |
|
162 RxErr = 0x02, |
|
163 RxOK = 0x01, |
|
164 |
|
165 RxAckBits = RxFIFOOver | RxOverflow | RxOK, |
|
166 }; |
|
167 |
|
168 enum TxStatusBits { |
|
169 TxHostOwns = 0x2000, |
|
170 TxUnderrun = 0x4000, |
|
171 TxStatOK = 0x8000, |
|
172 TxOutOfWindow = 0x20000000, |
|
173 TxAborted = 0x40000000, |
|
174 TxCarrierLost = 0x80000000, |
|
175 }; |
|
176 enum RxStatusBits { |
|
177 RxMulticast = 0x8000, |
|
178 RxPhysical = 0x4000, |
|
179 RxBroadcast = 0x2000, |
|
180 RxBadSymbol = 0x0020, |
|
181 RxRunt = 0x0010, |
|
182 RxTooLong = 0x0008, |
|
183 RxCRCErr = 0x0004, |
|
184 RxBadAlign = 0x0002, |
|
185 RxStatusOK = 0x0001, |
|
186 }; |
|
187 |
|
188 /* Bits in RxConfig. */ |
|
189 enum rx_mode_bits { |
|
190 AcceptErr = 0x20, |
|
191 AcceptRunt = 0x10, |
|
192 AcceptBroadcast = 0x08, |
|
193 AcceptMulticast = 0x04, |
|
194 AcceptMyPhys = 0x02, |
|
195 AcceptAllPhys = 0x01, |
|
196 }; |
|
197 |
|
198 /* Bits in TxConfig. */ |
|
199 enum tx_config_bits { |
|
200 |
|
201 /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ |
|
202 TxIFGShift = 24, |
|
203 TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ |
|
204 TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ |
|
205 TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ |
|
206 TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ |
|
207 |
|
208 TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ |
|
209 TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ |
|
210 TxClearAbt = (1 << 0), /* Clear abort (WO) */ |
|
211 TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ |
|
212 TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ |
|
213 |
|
214 TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ |
|
215 }; |
|
216 |
|
217 |
|
218 /* Transmit Status of All Descriptors (TSAD) Register */ |
|
219 enum TSAD_bits { |
|
220 TSAD_TOK3 = 1<<15, // TOK bit of Descriptor 3 |
|
221 TSAD_TOK2 = 1<<14, // TOK bit of Descriptor 2 |
|
222 TSAD_TOK1 = 1<<13, // TOK bit of Descriptor 1 |
|
223 TSAD_TOK0 = 1<<12, // TOK bit of Descriptor 0 |
|
224 TSAD_TUN3 = 1<<11, // TUN bit of Descriptor 3 |
|
225 TSAD_TUN2 = 1<<10, // TUN bit of Descriptor 2 |
|
226 TSAD_TUN1 = 1<<9, // TUN bit of Descriptor 1 |
|
227 TSAD_TUN0 = 1<<8, // TUN bit of Descriptor 0 |
|
228 TSAD_TABT3 = 1<<07, // TABT bit of Descriptor 3 |
|
229 TSAD_TABT2 = 1<<06, // TABT bit of Descriptor 2 |
|
230 TSAD_TABT1 = 1<<05, // TABT bit of Descriptor 1 |
|
231 TSAD_TABT0 = 1<<04, // TABT bit of Descriptor 0 |
|
232 TSAD_OWN3 = 1<<03, // OWN bit of Descriptor 3 |
|
233 TSAD_OWN2 = 1<<02, // OWN bit of Descriptor 2 |
|
234 TSAD_OWN1 = 1<<01, // OWN bit of Descriptor 1 |
|
235 TSAD_OWN0 = 1<<00, // OWN bit of Descriptor 0 |
|
236 }; |
|
237 |
|
238 |
|
239 /* Bits in Config1 */ |
|
240 enum Config1Bits { |
|
241 Cfg1_PM_Enable = 0x01, |
|
242 Cfg1_VPD_Enable = 0x02, |
|
243 Cfg1_PIO = 0x04, |
|
244 Cfg1_MMIO = 0x08, |
|
245 LWAKE = 0x10, /* not on 8139, 8139A */ |
|
246 Cfg1_Driver_Load = 0x20, |
|
247 Cfg1_LED0 = 0x40, |
|
248 Cfg1_LED1 = 0x80, |
|
249 SLEEP = (1 << 1), /* only on 8139, 8139A */ |
|
250 PWRDN = (1 << 0), /* only on 8139, 8139A */ |
|
251 }; |
|
252 |
|
253 /* Bits in Config3 */ |
|
254 enum Config3Bits { |
|
255 Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ |
|
256 Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ |
|
257 Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ |
|
258 Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ |
|
259 Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ |
|
260 Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ |
|
261 Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ |
|
262 Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ |
|
263 }; |
|
264 |
|
265 /* Bits in Config4 */ |
|
266 enum Config4Bits { |
|
267 LWPTN = (1 << 2), /* not on 8139, 8139A */ |
|
268 }; |
|
269 |
|
270 /* Bits in Config5 */ |
|
271 enum Config5Bits { |
|
272 Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ |
|
273 Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ |
|
274 Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ |
|
275 Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ |
|
276 Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ |
|
277 Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ |
|
278 Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ |
|
279 }; |
|
280 |
|
281 enum RxConfigBits { |
|
282 /* rx fifo threshold */ |
|
283 RxCfgFIFOShift = 13, |
|
284 RxCfgFIFONone = (7 << RxCfgFIFOShift), |
|
285 |
|
286 /* Max DMA burst */ |
|
287 RxCfgDMAShift = 8, |
|
288 RxCfgDMAUnlimited = (7 << RxCfgDMAShift), |
|
289 |
|
290 /* rx ring buffer length */ |
|
291 RxCfgRcv8K = 0, |
|
292 RxCfgRcv16K = (1 << 11), |
|
293 RxCfgRcv32K = (1 << 12), |
|
294 RxCfgRcv64K = (1 << 11) | (1 << 12), |
|
295 |
|
296 /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ |
|
297 RxNoWrap = (1 << 7), |
|
298 }; |
|
299 |
|
300 /* Twister tuning parameters from RealTek. |
|
301 Completely undocumented, but required to tune bad links on some boards. */ |
|
302 /* |
|
303 enum CSCRBits { |
|
304 CSCR_LinkOKBit = 0x0400, |
|
305 CSCR_LinkChangeBit = 0x0800, |
|
306 CSCR_LinkStatusBits = 0x0f000, |
|
307 CSCR_LinkDownOffCmd = 0x003c0, |
|
308 CSCR_LinkDownCmd = 0x0f3c0, |
|
309 */ |
|
310 enum CSCRBits { |
|
311 CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */ |
|
312 CSCR_LD = 1<<9, /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/ |
|
313 CSCR_HEART_BIT = 1<<8, /* 1 = HEART BEAT enable, 0 = HEART BEAT disable. HEART BEAT function is only valid in 10Mbps mode. def 1*/ |
|
314 CSCR_JBEN = 1<<7, /* 1 = enable jabber function. 0 = disable jabber function, def 1*/ |
|
315 CSCR_F_LINK_100 = 1<<6, /* Used to login force good link in 100Mbps for diagnostic purposes. 1 = DISABLE, 0 = ENABLE. def 1*/ |
|
316 CSCR_F_Connect = 1<<5, /* Assertion of this bit forces the disconnect function to be bypassed. def 0*/ |
|
317 CSCR_Con_status = 1<<3, /* This bit indicates the status of the connection. 1 = valid connected link detected; 0 = disconnected link detected. RO def 0*/ |
|
318 CSCR_Con_status_En = 1<<2, /* Assertion of this bit configures LED1 pin to indicate connection status. def 0*/ |
|
319 CSCR_PASS_SCR = 1<<0, /* Bypass Scramble, def 0*/ |
|
320 }; |
|
321 |
|
322 enum Cfg9346Bits { |
|
323 Cfg9346_Lock = 0x00, |
|
324 Cfg9346_Unlock = 0xC0, |
|
325 }; |
|
326 |
|
327 typedef enum { |
|
328 CH_8139 = 0, |
|
329 CH_8139_K, |
|
330 CH_8139A, |
|
331 CH_8139A_G, |
|
332 CH_8139B, |
|
333 CH_8130, |
|
334 CH_8139C, |
|
335 CH_8100, |
|
336 CH_8100B_8139D, |
|
337 CH_8101, |
|
338 } chip_t; |
|
339 |
|
340 enum chip_flags { |
|
341 HasHltClk = (1 << 0), |
|
342 HasLWake = (1 << 1), |
|
343 }; |
|
344 |
|
345 #define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ |
|
346 (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) |
|
347 #define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) |
|
348 |
|
349 #define RTL8139_PCI_REVID_8139 0x10 |
|
350 #define RTL8139_PCI_REVID_8139CPLUS 0x20 |
|
351 |
|
352 #define RTL8139_PCI_REVID RTL8139_PCI_REVID_8139CPLUS |
|
353 |
|
354 /* Size is 64 * 16bit words */ |
|
355 #define EEPROM_9346_ADDR_BITS 6 |
|
356 #define EEPROM_9346_SIZE (1 << EEPROM_9346_ADDR_BITS) |
|
357 #define EEPROM_9346_ADDR_MASK (EEPROM_9346_SIZE - 1) |
|
358 |
|
359 enum Chip9346Operation |
|
360 { |
|
361 Chip9346_op_mask = 0xc0, /* 10 zzzzzz */ |
|
362 Chip9346_op_read = 0x80, /* 10 AAAAAA */ |
|
363 Chip9346_op_write = 0x40, /* 01 AAAAAA D(15)..D(0) */ |
|
364 Chip9346_op_ext_mask = 0xf0, /* 11 zzzzzz */ |
|
365 Chip9346_op_write_enable = 0x30, /* 00 11zzzz */ |
|
366 Chip9346_op_write_all = 0x10, /* 00 01zzzz */ |
|
367 Chip9346_op_write_disable = 0x00, /* 00 00zzzz */ |
|
368 }; |
|
369 |
|
370 enum Chip9346Mode |
|
371 { |
|
372 Chip9346_none = 0, |
|
373 Chip9346_enter_command_mode, |
|
374 Chip9346_read_command, |
|
375 Chip9346_data_read, /* from output register */ |
|
376 Chip9346_data_write, /* to input register, then to contents at specified address */ |
|
377 Chip9346_data_write_all, /* to input register, then filling contents */ |
|
378 }; |
|
379 |
|
380 typedef struct EEprom9346 |
|
381 { |
|
382 uint16_t contents[EEPROM_9346_SIZE]; |
|
383 int mode; |
|
384 uint32_t tick; |
|
385 uint8_t address; |
|
386 uint16_t input; |
|
387 uint16_t output; |
|
388 |
|
389 uint8_t eecs; |
|
390 uint8_t eesk; |
|
391 uint8_t eedi; |
|
392 uint8_t eedo; |
|
393 } EEprom9346; |
|
394 |
|
395 typedef struct RTL8139TallyCounters |
|
396 { |
|
397 /* Tally counters */ |
|
398 uint64_t TxOk; |
|
399 uint64_t RxOk; |
|
400 uint64_t TxERR; |
|
401 uint32_t RxERR; |
|
402 uint16_t MissPkt; |
|
403 uint16_t FAE; |
|
404 uint32_t Tx1Col; |
|
405 uint32_t TxMCol; |
|
406 uint64_t RxOkPhy; |
|
407 uint64_t RxOkBrd; |
|
408 uint32_t RxOkMul; |
|
409 uint16_t TxAbt; |
|
410 uint16_t TxUndrn; |
|
411 } RTL8139TallyCounters; |
|
412 |
|
413 /* Clears all tally counters */ |
|
414 static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters); |
|
415 |
|
416 /* Writes tally counters to specified physical memory address */ |
|
417 static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t tc_addr, RTL8139TallyCounters* counters); |
|
418 |
|
419 /* Loads values of tally counters from VM state file */ |
|
420 static void RTL8139TallyCounters_load(QEMUFile* f, RTL8139TallyCounters *tally_counters); |
|
421 |
|
422 /* Saves values of tally counters to VM state file */ |
|
423 static void RTL8139TallyCounters_save(QEMUFile* f, RTL8139TallyCounters *tally_counters); |
|
424 |
|
425 typedef struct RTL8139State { |
|
426 uint8_t phys[8]; /* mac address */ |
|
427 uint8_t mult[8]; /* multicast mask array */ |
|
428 |
|
429 uint32_t TxStatus[4]; /* TxStatus0 in C mode*/ /* also DTCCR[0] and DTCCR[1] in C+ mode */ |
|
430 uint32_t TxAddr[4]; /* TxAddr0 */ |
|
431 uint32_t RxBuf; /* Receive buffer */ |
|
432 uint32_t RxBufferSize;/* internal variable, receive ring buffer size in C mode */ |
|
433 uint32_t RxBufPtr; |
|
434 uint32_t RxBufAddr; |
|
435 |
|
436 uint16_t IntrStatus; |
|
437 uint16_t IntrMask; |
|
438 |
|
439 uint32_t TxConfig; |
|
440 uint32_t RxConfig; |
|
441 uint32_t RxMissed; |
|
442 |
|
443 uint16_t CSCR; |
|
444 |
|
445 uint8_t Cfg9346; |
|
446 uint8_t Config0; |
|
447 uint8_t Config1; |
|
448 uint8_t Config3; |
|
449 uint8_t Config4; |
|
450 uint8_t Config5; |
|
451 |
|
452 uint8_t clock_enabled; |
|
453 uint8_t bChipCmdState; |
|
454 |
|
455 uint16_t MultiIntr; |
|
456 |
|
457 uint16_t BasicModeCtrl; |
|
458 uint16_t BasicModeStatus; |
|
459 uint16_t NWayAdvert; |
|
460 uint16_t NWayLPAR; |
|
461 uint16_t NWayExpansion; |
|
462 |
|
463 uint16_t CpCmd; |
|
464 uint8_t TxThresh; |
|
465 |
|
466 PCIDevice *pci_dev; |
|
467 VLANClientState *vc; |
|
468 uint8_t macaddr[6]; |
|
469 int rtl8139_mmio_io_addr; |
|
470 |
|
471 /* C ring mode */ |
|
472 uint32_t currTxDesc; |
|
473 |
|
474 /* C+ mode */ |
|
475 uint32_t currCPlusRxDesc; |
|
476 uint32_t currCPlusTxDesc; |
|
477 |
|
478 uint32_t RxRingAddrLO; |
|
479 uint32_t RxRingAddrHI; |
|
480 |
|
481 EEprom9346 eeprom; |
|
482 |
|
483 uint32_t TCTR; |
|
484 uint32_t TimerInt; |
|
485 int64_t TCTR_base; |
|
486 |
|
487 /* Tally counters */ |
|
488 RTL8139TallyCounters tally_counters; |
|
489 |
|
490 /* Non-persistent data */ |
|
491 uint8_t *cplus_txbuffer; |
|
492 int cplus_txbuffer_len; |
|
493 int cplus_txbuffer_offset; |
|
494 |
|
495 /* PCI interrupt timer */ |
|
496 QEMUTimer *timer; |
|
497 |
|
498 } RTL8139State; |
|
499 |
|
500 static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) |
|
501 { |
|
502 DEBUG_PRINT(("RTL8139: eeprom command 0x%02x\n", command)); |
|
503 |
|
504 switch (command & Chip9346_op_mask) |
|
505 { |
|
506 case Chip9346_op_read: |
|
507 { |
|
508 eeprom->address = command & EEPROM_9346_ADDR_MASK; |
|
509 eeprom->output = eeprom->contents[eeprom->address]; |
|
510 eeprom->eedo = 0; |
|
511 eeprom->tick = 0; |
|
512 eeprom->mode = Chip9346_data_read; |
|
513 DEBUG_PRINT(("RTL8139: eeprom read from address 0x%02x data=0x%04x\n", |
|
514 eeprom->address, eeprom->output)); |
|
515 } |
|
516 break; |
|
517 |
|
518 case Chip9346_op_write: |
|
519 { |
|
520 eeprom->address = command & EEPROM_9346_ADDR_MASK; |
|
521 eeprom->input = 0; |
|
522 eeprom->tick = 0; |
|
523 eeprom->mode = Chip9346_none; /* Chip9346_data_write */ |
|
524 DEBUG_PRINT(("RTL8139: eeprom begin write to address 0x%02x\n", |
|
525 eeprom->address)); |
|
526 } |
|
527 break; |
|
528 default: |
|
529 eeprom->mode = Chip9346_none; |
|
530 switch (command & Chip9346_op_ext_mask) |
|
531 { |
|
532 case Chip9346_op_write_enable: |
|
533 DEBUG_PRINT(("RTL8139: eeprom write enabled\n")); |
|
534 break; |
|
535 case Chip9346_op_write_all: |
|
536 DEBUG_PRINT(("RTL8139: eeprom begin write all\n")); |
|
537 break; |
|
538 case Chip9346_op_write_disable: |
|
539 DEBUG_PRINT(("RTL8139: eeprom write disabled\n")); |
|
540 break; |
|
541 } |
|
542 break; |
|
543 } |
|
544 } |
|
545 |
|
546 static void prom9346_shift_clock(EEprom9346 *eeprom) |
|
547 { |
|
548 int bit = eeprom->eedi?1:0; |
|
549 |
|
550 ++ eeprom->tick; |
|
551 |
|
552 DEBUG_PRINT(("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo)); |
|
553 |
|
554 switch (eeprom->mode) |
|
555 { |
|
556 case Chip9346_enter_command_mode: |
|
557 if (bit) |
|
558 { |
|
559 eeprom->mode = Chip9346_read_command; |
|
560 eeprom->tick = 0; |
|
561 eeprom->input = 0; |
|
562 DEBUG_PRINT(("eeprom: +++ synchronized, begin command read\n")); |
|
563 } |
|
564 break; |
|
565 |
|
566 case Chip9346_read_command: |
|
567 eeprom->input = (eeprom->input << 1) | (bit & 1); |
|
568 if (eeprom->tick == 8) |
|
569 { |
|
570 prom9346_decode_command(eeprom, eeprom->input & 0xff); |
|
571 } |
|
572 break; |
|
573 |
|
574 case Chip9346_data_read: |
|
575 eeprom->eedo = (eeprom->output & 0x8000)?1:0; |
|
576 eeprom->output <<= 1; |
|
577 if (eeprom->tick == 16) |
|
578 { |
|
579 #if 1 |
|
580 // the FreeBSD drivers (rl and re) don't explicitly toggle |
|
581 // CS between reads (or does setting Cfg9346 to 0 count too?), |
|
582 // so we need to enter wait-for-command state here |
|
583 eeprom->mode = Chip9346_enter_command_mode; |
|
584 eeprom->input = 0; |
|
585 eeprom->tick = 0; |
|
586 |
|
587 DEBUG_PRINT(("eeprom: +++ end of read, awaiting next command\n")); |
|
588 #else |
|
589 // original behaviour |
|
590 ++eeprom->address; |
|
591 eeprom->address &= EEPROM_9346_ADDR_MASK; |
|
592 eeprom->output = eeprom->contents[eeprom->address]; |
|
593 eeprom->tick = 0; |
|
594 |
|
595 DEBUG_PRINT(("eeprom: +++ read next address 0x%02x data=0x%04x\n", |
|
596 eeprom->address, eeprom->output)); |
|
597 #endif |
|
598 } |
|
599 break; |
|
600 |
|
601 case Chip9346_data_write: |
|
602 eeprom->input = (eeprom->input << 1) | (bit & 1); |
|
603 if (eeprom->tick == 16) |
|
604 { |
|
605 DEBUG_PRINT(("RTL8139: eeprom write to address 0x%02x data=0x%04x\n", |
|
606 eeprom->address, eeprom->input)); |
|
607 |
|
608 eeprom->contents[eeprom->address] = eeprom->input; |
|
609 eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */ |
|
610 eeprom->tick = 0; |
|
611 eeprom->input = 0; |
|
612 } |
|
613 break; |
|
614 |
|
615 case Chip9346_data_write_all: |
|
616 eeprom->input = (eeprom->input << 1) | (bit & 1); |
|
617 if (eeprom->tick == 16) |
|
618 { |
|
619 int i; |
|
620 for (i = 0; i < EEPROM_9346_SIZE; i++) |
|
621 { |
|
622 eeprom->contents[i] = eeprom->input; |
|
623 } |
|
624 DEBUG_PRINT(("RTL8139: eeprom filled with data=0x%04x\n", |
|
625 eeprom->input)); |
|
626 |
|
627 eeprom->mode = Chip9346_enter_command_mode; |
|
628 eeprom->tick = 0; |
|
629 eeprom->input = 0; |
|
630 } |
|
631 break; |
|
632 |
|
633 default: |
|
634 break; |
|
635 } |
|
636 } |
|
637 |
|
638 static int prom9346_get_wire(RTL8139State *s) |
|
639 { |
|
640 EEprom9346 *eeprom = &s->eeprom; |
|
641 if (!eeprom->eecs) |
|
642 return 0; |
|
643 |
|
644 return eeprom->eedo; |
|
645 } |
|
646 |
|
647 /* FIXME: This should be merged into/replaced by eeprom93xx.c. */ |
|
648 static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) |
|
649 { |
|
650 EEprom9346 *eeprom = &s->eeprom; |
|
651 uint8_t old_eecs = eeprom->eecs; |
|
652 uint8_t old_eesk = eeprom->eesk; |
|
653 |
|
654 eeprom->eecs = eecs; |
|
655 eeprom->eesk = eesk; |
|
656 eeprom->eedi = eedi; |
|
657 |
|
658 DEBUG_PRINT(("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", |
|
659 eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo)); |
|
660 |
|
661 if (!old_eecs && eecs) |
|
662 { |
|
663 /* Synchronize start */ |
|
664 eeprom->tick = 0; |
|
665 eeprom->input = 0; |
|
666 eeprom->output = 0; |
|
667 eeprom->mode = Chip9346_enter_command_mode; |
|
668 |
|
669 DEBUG_PRINT(("=== eeprom: begin access, enter command mode\n")); |
|
670 } |
|
671 |
|
672 if (!eecs) |
|
673 { |
|
674 DEBUG_PRINT(("=== eeprom: end access\n")); |
|
675 return; |
|
676 } |
|
677 |
|
678 if (!old_eesk && eesk) |
|
679 { |
|
680 /* SK front rules */ |
|
681 prom9346_shift_clock(eeprom); |
|
682 } |
|
683 } |
|
684 |
|
685 static void rtl8139_update_irq(RTL8139State *s) |
|
686 { |
|
687 int isr; |
|
688 isr = (s->IntrStatus & s->IntrMask) & 0xffff; |
|
689 |
|
690 DEBUG_PRINT(("RTL8139: Set IRQ to %d (%04x %04x)\n", |
|
691 isr ? 1 : 0, s->IntrStatus, s->IntrMask)); |
|
692 |
|
693 qemu_set_irq(s->pci_dev->irq[0], (isr != 0)); |
|
694 } |
|
695 |
|
696 #define POLYNOMIAL 0x04c11db6 |
|
697 |
|
698 /* From FreeBSD */ |
|
699 /* XXX: optimize */ |
|
700 static int compute_mcast_idx(const uint8_t *ep) |
|
701 { |
|
702 uint32_t crc; |
|
703 int carry, i, j; |
|
704 uint8_t b; |
|
705 |
|
706 crc = 0xffffffff; |
|
707 for (i = 0; i < 6; i++) { |
|
708 b = *ep++; |
|
709 for (j = 0; j < 8; j++) { |
|
710 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); |
|
711 crc <<= 1; |
|
712 b >>= 1; |
|
713 if (carry) |
|
714 crc = ((crc ^ POLYNOMIAL) | carry); |
|
715 } |
|
716 } |
|
717 return (crc >> 26); |
|
718 } |
|
719 |
|
720 static int rtl8139_RxWrap(RTL8139State *s) |
|
721 { |
|
722 /* wrapping enabled; assume 1.5k more buffer space if size < 65536 */ |
|
723 return (s->RxConfig & (1 << 7)); |
|
724 } |
|
725 |
|
726 static int rtl8139_receiver_enabled(RTL8139State *s) |
|
727 { |
|
728 return s->bChipCmdState & CmdRxEnb; |
|
729 } |
|
730 |
|
731 static int rtl8139_transmitter_enabled(RTL8139State *s) |
|
732 { |
|
733 return s->bChipCmdState & CmdTxEnb; |
|
734 } |
|
735 |
|
736 static int rtl8139_cp_receiver_enabled(RTL8139State *s) |
|
737 { |
|
738 return s->CpCmd & CPlusRxEnb; |
|
739 } |
|
740 |
|
741 static int rtl8139_cp_transmitter_enabled(RTL8139State *s) |
|
742 { |
|
743 return s->CpCmd & CPlusTxEnb; |
|
744 } |
|
745 |
|
746 static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) |
|
747 { |
|
748 if (s->RxBufAddr + size > s->RxBufferSize) |
|
749 { |
|
750 int wrapped = MOD2(s->RxBufAddr + size, s->RxBufferSize); |
|
751 |
|
752 /* write packet data */ |
|
753 if (wrapped && !(s->RxBufferSize < 65536 && rtl8139_RxWrap(s))) |
|
754 { |
|
755 DEBUG_PRINT((">>> RTL8139: rx packet wrapped in buffer at %d\n", size-wrapped)); |
|
756 |
|
757 if (size > wrapped) |
|
758 { |
|
759 cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, |
|
760 buf, size-wrapped ); |
|
761 } |
|
762 |
|
763 /* reset buffer pointer */ |
|
764 s->RxBufAddr = 0; |
|
765 |
|
766 cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, |
|
767 buf + (size-wrapped), wrapped ); |
|
768 |
|
769 s->RxBufAddr = wrapped; |
|
770 |
|
771 return; |
|
772 } |
|
773 } |
|
774 |
|
775 /* non-wrapping path or overwrapping enabled */ |
|
776 cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, buf, size ); |
|
777 |
|
778 s->RxBufAddr += size; |
|
779 } |
|
780 |
|
781 #define MIN_BUF_SIZE 60 |
|
782 static inline target_phys_addr_t rtl8139_addr64(uint32_t low, uint32_t high) |
|
783 { |
|
784 #if TARGET_PHYS_ADDR_BITS > 32 |
|
785 return low | ((target_phys_addr_t)high << 32); |
|
786 #else |
|
787 return low; |
|
788 #endif |
|
789 } |
|
790 |
|
791 static int rtl8139_can_receive(void *opaque) |
|
792 { |
|
793 RTL8139State *s = opaque; |
|
794 int avail; |
|
795 |
|
796 /* Receive (drop) packets if card is disabled. */ |
|
797 if (!s->clock_enabled) |
|
798 return 1; |
|
799 if (!rtl8139_receiver_enabled(s)) |
|
800 return 1; |
|
801 |
|
802 if (rtl8139_cp_receiver_enabled(s)) { |
|
803 /* ??? Flow control not implemented in c+ mode. |
|
804 This is a hack to work around slirp deficiencies anyway. */ |
|
805 return 1; |
|
806 } else { |
|
807 avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, |
|
808 s->RxBufferSize); |
|
809 return (avail == 0 || avail >= 1514); |
|
810 } |
|
811 } |
|
812 |
|
813 static void rtl8139_do_receive(void *opaque, const uint8_t *buf, int size, int do_interrupt) |
|
814 { |
|
815 RTL8139State *s = opaque; |
|
816 |
|
817 uint32_t packet_header = 0; |
|
818 |
|
819 uint8_t buf1[60]; |
|
820 static const uint8_t broadcast_macaddr[6] = |
|
821 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
|
822 |
|
823 DEBUG_PRINT((">>> RTL8139: received len=%d\n", size)); |
|
824 |
|
825 /* test if board clock is stopped */ |
|
826 if (!s->clock_enabled) |
|
827 { |
|
828 DEBUG_PRINT(("RTL8139: stopped ==========================\n")); |
|
829 return; |
|
830 } |
|
831 |
|
832 /* first check if receiver is enabled */ |
|
833 |
|
834 if (!rtl8139_receiver_enabled(s)) |
|
835 { |
|
836 DEBUG_PRINT(("RTL8139: receiver disabled ================\n")); |
|
837 return; |
|
838 } |
|
839 |
|
840 /* XXX: check this */ |
|
841 if (s->RxConfig & AcceptAllPhys) { |
|
842 /* promiscuous: receive all */ |
|
843 DEBUG_PRINT((">>> RTL8139: packet received in promiscuous mode\n")); |
|
844 |
|
845 } else { |
|
846 if (!memcmp(buf, broadcast_macaddr, 6)) { |
|
847 /* broadcast address */ |
|
848 if (!(s->RxConfig & AcceptBroadcast)) |
|
849 { |
|
850 DEBUG_PRINT((">>> RTL8139: broadcast packet rejected\n")); |
|
851 |
|
852 /* update tally counter */ |
|
853 ++s->tally_counters.RxERR; |
|
854 |
|
855 return; |
|
856 } |
|
857 |
|
858 packet_header |= RxBroadcast; |
|
859 |
|
860 DEBUG_PRINT((">>> RTL8139: broadcast packet received\n")); |
|
861 |
|
862 /* update tally counter */ |
|
863 ++s->tally_counters.RxOkBrd; |
|
864 |
|
865 } else if (buf[0] & 0x01) { |
|
866 /* multicast */ |
|
867 if (!(s->RxConfig & AcceptMulticast)) |
|
868 { |
|
869 DEBUG_PRINT((">>> RTL8139: multicast packet rejected\n")); |
|
870 |
|
871 /* update tally counter */ |
|
872 ++s->tally_counters.RxERR; |
|
873 |
|
874 return; |
|
875 } |
|
876 |
|
877 int mcast_idx = compute_mcast_idx(buf); |
|
878 |
|
879 if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) |
|
880 { |
|
881 DEBUG_PRINT((">>> RTL8139: multicast address mismatch\n")); |
|
882 |
|
883 /* update tally counter */ |
|
884 ++s->tally_counters.RxERR; |
|
885 |
|
886 return; |
|
887 } |
|
888 |
|
889 packet_header |= RxMulticast; |
|
890 |
|
891 DEBUG_PRINT((">>> RTL8139: multicast packet received\n")); |
|
892 |
|
893 /* update tally counter */ |
|
894 ++s->tally_counters.RxOkMul; |
|
895 |
|
896 } else if (s->phys[0] == buf[0] && |
|
897 s->phys[1] == buf[1] && |
|
898 s->phys[2] == buf[2] && |
|
899 s->phys[3] == buf[3] && |
|
900 s->phys[4] == buf[4] && |
|
901 s->phys[5] == buf[5]) { |
|
902 /* match */ |
|
903 if (!(s->RxConfig & AcceptMyPhys)) |
|
904 { |
|
905 DEBUG_PRINT((">>> RTL8139: rejecting physical address matching packet\n")); |
|
906 |
|
907 /* update tally counter */ |
|
908 ++s->tally_counters.RxERR; |
|
909 |
|
910 return; |
|
911 } |
|
912 |
|
913 packet_header |= RxPhysical; |
|
914 |
|
915 DEBUG_PRINT((">>> RTL8139: physical address matching packet received\n")); |
|
916 |
|
917 /* update tally counter */ |
|
918 ++s->tally_counters.RxOkPhy; |
|
919 |
|
920 } else { |
|
921 |
|
922 DEBUG_PRINT((">>> RTL8139: unknown packet\n")); |
|
923 |
|
924 /* update tally counter */ |
|
925 ++s->tally_counters.RxERR; |
|
926 |
|
927 return; |
|
928 } |
|
929 } |
|
930 |
|
931 /* if too small buffer, then expand it */ |
|
932 if (size < MIN_BUF_SIZE) { |
|
933 memcpy(buf1, buf, size); |
|
934 memset(buf1 + size, 0, MIN_BUF_SIZE - size); |
|
935 buf = buf1; |
|
936 size = MIN_BUF_SIZE; |
|
937 } |
|
938 |
|
939 if (rtl8139_cp_receiver_enabled(s)) |
|
940 { |
|
941 DEBUG_PRINT(("RTL8139: in C+ Rx mode ================\n")); |
|
942 |
|
943 /* begin C+ receiver mode */ |
|
944 |
|
945 /* w0 ownership flag */ |
|
946 #define CP_RX_OWN (1<<31) |
|
947 /* w0 end of ring flag */ |
|
948 #define CP_RX_EOR (1<<30) |
|
949 /* w0 bits 0...12 : buffer size */ |
|
950 #define CP_RX_BUFFER_SIZE_MASK ((1<<13) - 1) |
|
951 /* w1 tag available flag */ |
|
952 #define CP_RX_TAVA (1<<16) |
|
953 /* w1 bits 0...15 : VLAN tag */ |
|
954 #define CP_RX_VLAN_TAG_MASK ((1<<16) - 1) |
|
955 /* w2 low 32bit of Rx buffer ptr */ |
|
956 /* w3 high 32bit of Rx buffer ptr */ |
|
957 |
|
958 int descriptor = s->currCPlusRxDesc; |
|
959 target_phys_addr_t cplus_rx_ring_desc; |
|
960 |
|
961 cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI); |
|
962 cplus_rx_ring_desc += 16 * descriptor; |
|
963 |
|
964 DEBUG_PRINT(("RTL8139: +++ C+ mode reading RX descriptor %d from host memory at %08x %08x = %016" PRIx64 "\n", |
|
965 descriptor, s->RxRingAddrHI, s->RxRingAddrLO, (uint64_t)cplus_rx_ring_desc)); |
|
966 |
|
967 uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI; |
|
968 |
|
969 cpu_physical_memory_read(cplus_rx_ring_desc, (uint8_t *)&val, 4); |
|
970 rxdw0 = le32_to_cpu(val); |
|
971 cpu_physical_memory_read(cplus_rx_ring_desc+4, (uint8_t *)&val, 4); |
|
972 rxdw1 = le32_to_cpu(val); |
|
973 cpu_physical_memory_read(cplus_rx_ring_desc+8, (uint8_t *)&val, 4); |
|
974 rxbufLO = le32_to_cpu(val); |
|
975 cpu_physical_memory_read(cplus_rx_ring_desc+12, (uint8_t *)&val, 4); |
|
976 rxbufHI = le32_to_cpu(val); |
|
977 |
|
978 DEBUG_PRINT(("RTL8139: +++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", |
|
979 descriptor, |
|
980 rxdw0, rxdw1, rxbufLO, rxbufHI)); |
|
981 |
|
982 if (!(rxdw0 & CP_RX_OWN)) |
|
983 { |
|
984 DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d is owned by host\n", descriptor)); |
|
985 |
|
986 s->IntrStatus |= RxOverflow; |
|
987 ++s->RxMissed; |
|
988 |
|
989 /* update tally counter */ |
|
990 ++s->tally_counters.RxERR; |
|
991 ++s->tally_counters.MissPkt; |
|
992 |
|
993 rtl8139_update_irq(s); |
|
994 return; |
|
995 } |
|
996 |
|
997 uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK; |
|
998 |
|
999 /* TODO: scatter the packet over available receive ring descriptors space */ |
|
1000 |
|
1001 if (size+4 > rx_space) |
|
1002 { |
|
1003 DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d size %d received %d + 4\n", |
|
1004 descriptor, rx_space, size)); |
|
1005 |
|
1006 s->IntrStatus |= RxOverflow; |
|
1007 ++s->RxMissed; |
|
1008 |
|
1009 /* update tally counter */ |
|
1010 ++s->tally_counters.RxERR; |
|
1011 ++s->tally_counters.MissPkt; |
|
1012 |
|
1013 rtl8139_update_irq(s); |
|
1014 return; |
|
1015 } |
|
1016 |
|
1017 target_phys_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI); |
|
1018 |
|
1019 /* receive/copy to target memory */ |
|
1020 cpu_physical_memory_write( rx_addr, buf, size ); |
|
1021 |
|
1022 if (s->CpCmd & CPlusRxChkSum) |
|
1023 { |
|
1024 /* do some packet checksumming */ |
|
1025 } |
|
1026 |
|
1027 /* write checksum */ |
|
1028 #if defined (RTL8139_CALCULATE_RXCRC) |
|
1029 val = cpu_to_le32(crc32(0, buf, size)); |
|
1030 #else |
|
1031 val = 0; |
|
1032 #endif |
|
1033 cpu_physical_memory_write( rx_addr+size, (uint8_t *)&val, 4); |
|
1034 |
|
1035 /* first segment of received packet flag */ |
|
1036 #define CP_RX_STATUS_FS (1<<29) |
|
1037 /* last segment of received packet flag */ |
|
1038 #define CP_RX_STATUS_LS (1<<28) |
|
1039 /* multicast packet flag */ |
|
1040 #define CP_RX_STATUS_MAR (1<<26) |
|
1041 /* physical-matching packet flag */ |
|
1042 #define CP_RX_STATUS_PAM (1<<25) |
|
1043 /* broadcast packet flag */ |
|
1044 #define CP_RX_STATUS_BAR (1<<24) |
|
1045 /* runt packet flag */ |
|
1046 #define CP_RX_STATUS_RUNT (1<<19) |
|
1047 /* crc error flag */ |
|
1048 #define CP_RX_STATUS_CRC (1<<18) |
|
1049 /* IP checksum error flag */ |
|
1050 #define CP_RX_STATUS_IPF (1<<15) |
|
1051 /* UDP checksum error flag */ |
|
1052 #define CP_RX_STATUS_UDPF (1<<14) |
|
1053 /* TCP checksum error flag */ |
|
1054 #define CP_RX_STATUS_TCPF (1<<13) |
|
1055 |
|
1056 /* transfer ownership to target */ |
|
1057 rxdw0 &= ~CP_RX_OWN; |
|
1058 |
|
1059 /* set first segment bit */ |
|
1060 rxdw0 |= CP_RX_STATUS_FS; |
|
1061 |
|
1062 /* set last segment bit */ |
|
1063 rxdw0 |= CP_RX_STATUS_LS; |
|
1064 |
|
1065 /* set received packet type flags */ |
|
1066 if (packet_header & RxBroadcast) |
|
1067 rxdw0 |= CP_RX_STATUS_BAR; |
|
1068 if (packet_header & RxMulticast) |
|
1069 rxdw0 |= CP_RX_STATUS_MAR; |
|
1070 if (packet_header & RxPhysical) |
|
1071 rxdw0 |= CP_RX_STATUS_PAM; |
|
1072 |
|
1073 /* set received size */ |
|
1074 rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK; |
|
1075 rxdw0 |= (size+4); |
|
1076 |
|
1077 /* reset VLAN tag flag */ |
|
1078 rxdw1 &= ~CP_RX_TAVA; |
|
1079 |
|
1080 /* update ring data */ |
|
1081 val = cpu_to_le32(rxdw0); |
|
1082 cpu_physical_memory_write(cplus_rx_ring_desc, (uint8_t *)&val, 4); |
|
1083 val = cpu_to_le32(rxdw1); |
|
1084 cpu_physical_memory_write(cplus_rx_ring_desc+4, (uint8_t *)&val, 4); |
|
1085 |
|
1086 /* update tally counter */ |
|
1087 ++s->tally_counters.RxOk; |
|
1088 |
|
1089 /* seek to next Rx descriptor */ |
|
1090 if (rxdw0 & CP_RX_EOR) |
|
1091 { |
|
1092 s->currCPlusRxDesc = 0; |
|
1093 } |
|
1094 else |
|
1095 { |
|
1096 ++s->currCPlusRxDesc; |
|
1097 } |
|
1098 |
|
1099 DEBUG_PRINT(("RTL8139: done C+ Rx mode ----------------\n")); |
|
1100 |
|
1101 } |
|
1102 else |
|
1103 { |
|
1104 DEBUG_PRINT(("RTL8139: in ring Rx mode ================\n")); |
|
1105 |
|
1106 /* begin ring receiver mode */ |
|
1107 int avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); |
|
1108 |
|
1109 /* if receiver buffer is empty then avail == 0 */ |
|
1110 |
|
1111 if (avail != 0 && size + 8 >= avail) |
|
1112 { |
|
1113 DEBUG_PRINT(("rx overflow: rx buffer length %d head 0x%04x read 0x%04x === available 0x%04x need 0x%04x\n", |
|
1114 s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8)); |
|
1115 |
|
1116 s->IntrStatus |= RxOverflow; |
|
1117 ++s->RxMissed; |
|
1118 rtl8139_update_irq(s); |
|
1119 return; |
|
1120 } |
|
1121 |
|
1122 packet_header |= RxStatusOK; |
|
1123 |
|
1124 packet_header |= (((size+4) << 16) & 0xffff0000); |
|
1125 |
|
1126 /* write header */ |
|
1127 uint32_t val = cpu_to_le32(packet_header); |
|
1128 |
|
1129 rtl8139_write_buffer(s, (uint8_t *)&val, 4); |
|
1130 |
|
1131 rtl8139_write_buffer(s, buf, size); |
|
1132 |
|
1133 /* write checksum */ |
|
1134 #if defined (RTL8139_CALCULATE_RXCRC) |
|
1135 val = cpu_to_le32(crc32(0, buf, size)); |
|
1136 #else |
|
1137 val = 0; |
|
1138 #endif |
|
1139 |
|
1140 rtl8139_write_buffer(s, (uint8_t *)&val, 4); |
|
1141 |
|
1142 /* correct buffer write pointer */ |
|
1143 s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize); |
|
1144 |
|
1145 /* now we can signal we have received something */ |
|
1146 |
|
1147 DEBUG_PRINT((" received: rx buffer length %d head 0x%04x read 0x%04x\n", |
|
1148 s->RxBufferSize, s->RxBufAddr, s->RxBufPtr)); |
|
1149 } |
|
1150 |
|
1151 s->IntrStatus |= RxOK; |
|
1152 |
|
1153 if (do_interrupt) |
|
1154 { |
|
1155 rtl8139_update_irq(s); |
|
1156 } |
|
1157 } |
|
1158 |
|
1159 static void rtl8139_receive(void *opaque, const uint8_t *buf, int size) |
|
1160 { |
|
1161 rtl8139_do_receive(opaque, buf, size, 1); |
|
1162 } |
|
1163 |
|
1164 static void rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize) |
|
1165 { |
|
1166 s->RxBufferSize = bufferSize; |
|
1167 s->RxBufPtr = 0; |
|
1168 s->RxBufAddr = 0; |
|
1169 } |
|
1170 |
|
1171 static void rtl8139_reset(RTL8139State *s) |
|
1172 { |
|
1173 int i; |
|
1174 |
|
1175 /* restore MAC address */ |
|
1176 memcpy(s->phys, s->macaddr, 6); |
|
1177 |
|
1178 /* reset interrupt mask */ |
|
1179 s->IntrStatus = 0; |
|
1180 s->IntrMask = 0; |
|
1181 |
|
1182 rtl8139_update_irq(s); |
|
1183 |
|
1184 /* prepare eeprom */ |
|
1185 s->eeprom.contents[0] = 0x8129; |
|
1186 #if 1 |
|
1187 // PCI vendor and device ID should be mirrored here |
|
1188 s->eeprom.contents[1] = 0x10ec; |
|
1189 s->eeprom.contents[2] = 0x8139; |
|
1190 #endif |
|
1191 |
|
1192 s->eeprom.contents[7] = s->macaddr[0] | s->macaddr[1] << 8; |
|
1193 s->eeprom.contents[8] = s->macaddr[2] | s->macaddr[3] << 8; |
|
1194 s->eeprom.contents[9] = s->macaddr[4] | s->macaddr[5] << 8; |
|
1195 |
|
1196 /* mark all status registers as owned by host */ |
|
1197 for (i = 0; i < 4; ++i) |
|
1198 { |
|
1199 s->TxStatus[i] = TxHostOwns; |
|
1200 } |
|
1201 |
|
1202 s->currTxDesc = 0; |
|
1203 s->currCPlusRxDesc = 0; |
|
1204 s->currCPlusTxDesc = 0; |
|
1205 |
|
1206 s->RxRingAddrLO = 0; |
|
1207 s->RxRingAddrHI = 0; |
|
1208 |
|
1209 s->RxBuf = 0; |
|
1210 |
|
1211 rtl8139_reset_rxring(s, 8192); |
|
1212 |
|
1213 /* ACK the reset */ |
|
1214 s->TxConfig = 0; |
|
1215 |
|
1216 #if 0 |
|
1217 // s->TxConfig |= HW_REVID(1, 0, 0, 0, 0, 0, 0); // RTL-8139 HasHltClk |
|
1218 s->clock_enabled = 0; |
|
1219 #else |
|
1220 s->TxConfig |= HW_REVID(1, 1, 1, 0, 1, 1, 0); // RTL-8139C+ HasLWake |
|
1221 s->clock_enabled = 1; |
|
1222 #endif |
|
1223 |
|
1224 s->bChipCmdState = CmdReset; /* RxBufEmpty bit is calculated on read from ChipCmd */; |
|
1225 |
|
1226 /* set initial state data */ |
|
1227 s->Config0 = 0x0; /* No boot ROM */ |
|
1228 s->Config1 = 0xC; /* IO mapped and MEM mapped registers available */ |
|
1229 s->Config3 = 0x1; /* fast back-to-back compatible */ |
|
1230 s->Config5 = 0x0; |
|
1231 |
|
1232 s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD; |
|
1233 |
|
1234 s->CpCmd = 0x0; /* reset C+ mode */ |
|
1235 |
|
1236 // s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation |
|
1237 // s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex |
|
1238 s->BasicModeCtrl = 0x1000; // autonegotiation |
|
1239 |
|
1240 s->BasicModeStatus = 0x7809; |
|
1241 //s->BasicModeStatus |= 0x0040; /* UTP medium */ |
|
1242 s->BasicModeStatus |= 0x0020; /* autonegotiation completed */ |
|
1243 s->BasicModeStatus |= 0x0004; /* link is up */ |
|
1244 |
|
1245 s->NWayAdvert = 0x05e1; /* all modes, full duplex */ |
|
1246 s->NWayLPAR = 0x05e1; /* all modes, full duplex */ |
|
1247 s->NWayExpansion = 0x0001; /* autonegotiation supported */ |
|
1248 |
|
1249 /* also reset timer and disable timer interrupt */ |
|
1250 s->TCTR = 0; |
|
1251 s->TimerInt = 0; |
|
1252 s->TCTR_base = 0; |
|
1253 |
|
1254 /* reset tally counters */ |
|
1255 RTL8139TallyCounters_clear(&s->tally_counters); |
|
1256 } |
|
1257 |
|
1258 static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters) |
|
1259 { |
|
1260 counters->TxOk = 0; |
|
1261 counters->RxOk = 0; |
|
1262 counters->TxERR = 0; |
|
1263 counters->RxERR = 0; |
|
1264 counters->MissPkt = 0; |
|
1265 counters->FAE = 0; |
|
1266 counters->Tx1Col = 0; |
|
1267 counters->TxMCol = 0; |
|
1268 counters->RxOkPhy = 0; |
|
1269 counters->RxOkBrd = 0; |
|
1270 counters->RxOkMul = 0; |
|
1271 counters->TxAbt = 0; |
|
1272 counters->TxUndrn = 0; |
|
1273 } |
|
1274 |
|
1275 static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t tc_addr, RTL8139TallyCounters* tally_counters) |
|
1276 { |
|
1277 uint16_t val16; |
|
1278 uint32_t val32; |
|
1279 uint64_t val64; |
|
1280 |
|
1281 val64 = cpu_to_le64(tally_counters->TxOk); |
|
1282 cpu_physical_memory_write(tc_addr + 0, (uint8_t *)&val64, 8); |
|
1283 |
|
1284 val64 = cpu_to_le64(tally_counters->RxOk); |
|
1285 cpu_physical_memory_write(tc_addr + 8, (uint8_t *)&val64, 8); |
|
1286 |
|
1287 val64 = cpu_to_le64(tally_counters->TxERR); |
|
1288 cpu_physical_memory_write(tc_addr + 16, (uint8_t *)&val64, 8); |
|
1289 |
|
1290 val32 = cpu_to_le32(tally_counters->RxERR); |
|
1291 cpu_physical_memory_write(tc_addr + 24, (uint8_t *)&val32, 4); |
|
1292 |
|
1293 val16 = cpu_to_le16(tally_counters->MissPkt); |
|
1294 cpu_physical_memory_write(tc_addr + 28, (uint8_t *)&val16, 2); |
|
1295 |
|
1296 val16 = cpu_to_le16(tally_counters->FAE); |
|
1297 cpu_physical_memory_write(tc_addr + 30, (uint8_t *)&val16, 2); |
|
1298 |
|
1299 val32 = cpu_to_le32(tally_counters->Tx1Col); |
|
1300 cpu_physical_memory_write(tc_addr + 32, (uint8_t *)&val32, 4); |
|
1301 |
|
1302 val32 = cpu_to_le32(tally_counters->TxMCol); |
|
1303 cpu_physical_memory_write(tc_addr + 36, (uint8_t *)&val32, 4); |
|
1304 |
|
1305 val64 = cpu_to_le64(tally_counters->RxOkPhy); |
|
1306 cpu_physical_memory_write(tc_addr + 40, (uint8_t *)&val64, 8); |
|
1307 |
|
1308 val64 = cpu_to_le64(tally_counters->RxOkBrd); |
|
1309 cpu_physical_memory_write(tc_addr + 48, (uint8_t *)&val64, 8); |
|
1310 |
|
1311 val32 = cpu_to_le32(tally_counters->RxOkMul); |
|
1312 cpu_physical_memory_write(tc_addr + 56, (uint8_t *)&val32, 4); |
|
1313 |
|
1314 val16 = cpu_to_le16(tally_counters->TxAbt); |
|
1315 cpu_physical_memory_write(tc_addr + 60, (uint8_t *)&val16, 2); |
|
1316 |
|
1317 val16 = cpu_to_le16(tally_counters->TxUndrn); |
|
1318 cpu_physical_memory_write(tc_addr + 62, (uint8_t *)&val16, 2); |
|
1319 } |
|
1320 |
|
1321 /* Loads values of tally counters from VM state file */ |
|
1322 static void RTL8139TallyCounters_load(QEMUFile* f, RTL8139TallyCounters *tally_counters) |
|
1323 { |
|
1324 qemu_get_be64s(f, &tally_counters->TxOk); |
|
1325 qemu_get_be64s(f, &tally_counters->RxOk); |
|
1326 qemu_get_be64s(f, &tally_counters->TxERR); |
|
1327 qemu_get_be32s(f, &tally_counters->RxERR); |
|
1328 qemu_get_be16s(f, &tally_counters->MissPkt); |
|
1329 qemu_get_be16s(f, &tally_counters->FAE); |
|
1330 qemu_get_be32s(f, &tally_counters->Tx1Col); |
|
1331 qemu_get_be32s(f, &tally_counters->TxMCol); |
|
1332 qemu_get_be64s(f, &tally_counters->RxOkPhy); |
|
1333 qemu_get_be64s(f, &tally_counters->RxOkBrd); |
|
1334 qemu_get_be32s(f, &tally_counters->RxOkMul); |
|
1335 qemu_get_be16s(f, &tally_counters->TxAbt); |
|
1336 qemu_get_be16s(f, &tally_counters->TxUndrn); |
|
1337 } |
|
1338 |
|
1339 /* Saves values of tally counters to VM state file */ |
|
1340 static void RTL8139TallyCounters_save(QEMUFile* f, RTL8139TallyCounters *tally_counters) |
|
1341 { |
|
1342 qemu_put_be64s(f, &tally_counters->TxOk); |
|
1343 qemu_put_be64s(f, &tally_counters->RxOk); |
|
1344 qemu_put_be64s(f, &tally_counters->TxERR); |
|
1345 qemu_put_be32s(f, &tally_counters->RxERR); |
|
1346 qemu_put_be16s(f, &tally_counters->MissPkt); |
|
1347 qemu_put_be16s(f, &tally_counters->FAE); |
|
1348 qemu_put_be32s(f, &tally_counters->Tx1Col); |
|
1349 qemu_put_be32s(f, &tally_counters->TxMCol); |
|
1350 qemu_put_be64s(f, &tally_counters->RxOkPhy); |
|
1351 qemu_put_be64s(f, &tally_counters->RxOkBrd); |
|
1352 qemu_put_be32s(f, &tally_counters->RxOkMul); |
|
1353 qemu_put_be16s(f, &tally_counters->TxAbt); |
|
1354 qemu_put_be16s(f, &tally_counters->TxUndrn); |
|
1355 } |
|
1356 |
|
1357 static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val) |
|
1358 { |
|
1359 val &= 0xff; |
|
1360 |
|
1361 DEBUG_PRINT(("RTL8139: ChipCmd write val=0x%08x\n", val)); |
|
1362 |
|
1363 if (val & CmdReset) |
|
1364 { |
|
1365 DEBUG_PRINT(("RTL8139: ChipCmd reset\n")); |
|
1366 rtl8139_reset(s); |
|
1367 } |
|
1368 if (val & CmdRxEnb) |
|
1369 { |
|
1370 DEBUG_PRINT(("RTL8139: ChipCmd enable receiver\n")); |
|
1371 |
|
1372 s->currCPlusRxDesc = 0; |
|
1373 } |
|
1374 if (val & CmdTxEnb) |
|
1375 { |
|
1376 DEBUG_PRINT(("RTL8139: ChipCmd enable transmitter\n")); |
|
1377 |
|
1378 s->currCPlusTxDesc = 0; |
|
1379 } |
|
1380 |
|
1381 /* mask unwriteable bits */ |
|
1382 val = SET_MASKED(val, 0xe3, s->bChipCmdState); |
|
1383 |
|
1384 /* Deassert reset pin before next read */ |
|
1385 val &= ~CmdReset; |
|
1386 |
|
1387 s->bChipCmdState = val; |
|
1388 } |
|
1389 |
|
1390 static int rtl8139_RxBufferEmpty(RTL8139State *s) |
|
1391 { |
|
1392 int unread = MOD2(s->RxBufferSize + s->RxBufAddr - s->RxBufPtr, s->RxBufferSize); |
|
1393 |
|
1394 if (unread != 0) |
|
1395 { |
|
1396 DEBUG_PRINT(("RTL8139: receiver buffer data available 0x%04x\n", unread)); |
|
1397 return 0; |
|
1398 } |
|
1399 |
|
1400 DEBUG_PRINT(("RTL8139: receiver buffer is empty\n")); |
|
1401 |
|
1402 return 1; |
|
1403 } |
|
1404 |
|
1405 static uint32_t rtl8139_ChipCmd_read(RTL8139State *s) |
|
1406 { |
|
1407 uint32_t ret = s->bChipCmdState; |
|
1408 |
|
1409 if (rtl8139_RxBufferEmpty(s)) |
|
1410 ret |= RxBufEmpty; |
|
1411 |
|
1412 DEBUG_PRINT(("RTL8139: ChipCmd read val=0x%04x\n", ret)); |
|
1413 |
|
1414 return ret; |
|
1415 } |
|
1416 |
|
1417 static void rtl8139_CpCmd_write(RTL8139State *s, uint32_t val) |
|
1418 { |
|
1419 val &= 0xffff; |
|
1420 |
|
1421 DEBUG_PRINT(("RTL8139C+ command register write(w) val=0x%04x\n", val)); |
|
1422 |
|
1423 /* mask unwriteable bits */ |
|
1424 val = SET_MASKED(val, 0xff84, s->CpCmd); |
|
1425 |
|
1426 s->CpCmd = val; |
|
1427 } |
|
1428 |
|
1429 static uint32_t rtl8139_CpCmd_read(RTL8139State *s) |
|
1430 { |
|
1431 uint32_t ret = s->CpCmd; |
|
1432 |
|
1433 DEBUG_PRINT(("RTL8139C+ command register read(w) val=0x%04x\n", ret)); |
|
1434 |
|
1435 return ret; |
|
1436 } |
|
1437 |
|
1438 static void rtl8139_IntrMitigate_write(RTL8139State *s, uint32_t val) |
|
1439 { |
|
1440 DEBUG_PRINT(("RTL8139C+ IntrMitigate register write(w) val=0x%04x\n", val)); |
|
1441 } |
|
1442 |
|
1443 static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s) |
|
1444 { |
|
1445 uint32_t ret = 0; |
|
1446 |
|
1447 DEBUG_PRINT(("RTL8139C+ IntrMitigate register read(w) val=0x%04x\n", ret)); |
|
1448 |
|
1449 return ret; |
|
1450 } |
|
1451 |
|
1452 static int rtl8139_config_writeable(RTL8139State *s) |
|
1453 { |
|
1454 if (s->Cfg9346 & Cfg9346_Unlock) |
|
1455 { |
|
1456 return 1; |
|
1457 } |
|
1458 |
|
1459 DEBUG_PRINT(("RTL8139: Configuration registers are write-protected\n")); |
|
1460 |
|
1461 return 0; |
|
1462 } |
|
1463 |
|
1464 static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val) |
|
1465 { |
|
1466 val &= 0xffff; |
|
1467 |
|
1468 DEBUG_PRINT(("RTL8139: BasicModeCtrl register write(w) val=0x%04x\n", val)); |
|
1469 |
|
1470 /* mask unwriteable bits */ |
|
1471 uint32_t mask = 0x4cff; |
|
1472 |
|
1473 if (1 || !rtl8139_config_writeable(s)) |
|
1474 { |
|
1475 /* Speed setting and autonegotiation enable bits are read-only */ |
|
1476 mask |= 0x3000; |
|
1477 /* Duplex mode setting is read-only */ |
|
1478 mask |= 0x0100; |
|
1479 } |
|
1480 |
|
1481 val = SET_MASKED(val, mask, s->BasicModeCtrl); |
|
1482 |
|
1483 s->BasicModeCtrl = val; |
|
1484 } |
|
1485 |
|
1486 static uint32_t rtl8139_BasicModeCtrl_read(RTL8139State *s) |
|
1487 { |
|
1488 uint32_t ret = s->BasicModeCtrl; |
|
1489 |
|
1490 DEBUG_PRINT(("RTL8139: BasicModeCtrl register read(w) val=0x%04x\n", ret)); |
|
1491 |
|
1492 return ret; |
|
1493 } |
|
1494 |
|
1495 static void rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val) |
|
1496 { |
|
1497 val &= 0xffff; |
|
1498 |
|
1499 DEBUG_PRINT(("RTL8139: BasicModeStatus register write(w) val=0x%04x\n", val)); |
|
1500 |
|
1501 /* mask unwriteable bits */ |
|
1502 val = SET_MASKED(val, 0xff3f, s->BasicModeStatus); |
|
1503 |
|
1504 s->BasicModeStatus = val; |
|
1505 } |
|
1506 |
|
1507 static uint32_t rtl8139_BasicModeStatus_read(RTL8139State *s) |
|
1508 { |
|
1509 uint32_t ret = s->BasicModeStatus; |
|
1510 |
|
1511 DEBUG_PRINT(("RTL8139: BasicModeStatus register read(w) val=0x%04x\n", ret)); |
|
1512 |
|
1513 return ret; |
|
1514 } |
|
1515 |
|
1516 static void rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val) |
|
1517 { |
|
1518 val &= 0xff; |
|
1519 |
|
1520 DEBUG_PRINT(("RTL8139: Cfg9346 write val=0x%02x\n", val)); |
|
1521 |
|
1522 /* mask unwriteable bits */ |
|
1523 val = SET_MASKED(val, 0x31, s->Cfg9346); |
|
1524 |
|
1525 uint32_t opmode = val & 0xc0; |
|
1526 uint32_t eeprom_val = val & 0xf; |
|
1527 |
|
1528 if (opmode == 0x80) { |
|
1529 /* eeprom access */ |
|
1530 int eecs = (eeprom_val & 0x08)?1:0; |
|
1531 int eesk = (eeprom_val & 0x04)?1:0; |
|
1532 int eedi = (eeprom_val & 0x02)?1:0; |
|
1533 prom9346_set_wire(s, eecs, eesk, eedi); |
|
1534 } else if (opmode == 0x40) { |
|
1535 /* Reset. */ |
|
1536 val = 0; |
|
1537 rtl8139_reset(s); |
|
1538 } |
|
1539 |
|
1540 s->Cfg9346 = val; |
|
1541 } |
|
1542 |
|
1543 static uint32_t rtl8139_Cfg9346_read(RTL8139State *s) |
|
1544 { |
|
1545 uint32_t ret = s->Cfg9346; |
|
1546 |
|
1547 uint32_t opmode = ret & 0xc0; |
|
1548 |
|
1549 if (opmode == 0x80) |
|
1550 { |
|
1551 /* eeprom access */ |
|
1552 int eedo = prom9346_get_wire(s); |
|
1553 if (eedo) |
|
1554 { |
|
1555 ret |= 0x01; |
|
1556 } |
|
1557 else |
|
1558 { |
|
1559 ret &= ~0x01; |
|
1560 } |
|
1561 } |
|
1562 |
|
1563 DEBUG_PRINT(("RTL8139: Cfg9346 read val=0x%02x\n", ret)); |
|
1564 |
|
1565 return ret; |
|
1566 } |
|
1567 |
|
1568 static void rtl8139_Config0_write(RTL8139State *s, uint32_t val) |
|
1569 { |
|
1570 val &= 0xff; |
|
1571 |
|
1572 DEBUG_PRINT(("RTL8139: Config0 write val=0x%02x\n", val)); |
|
1573 |
|
1574 if (!rtl8139_config_writeable(s)) |
|
1575 return; |
|
1576 |
|
1577 /* mask unwriteable bits */ |
|
1578 val = SET_MASKED(val, 0xf8, s->Config0); |
|
1579 |
|
1580 s->Config0 = val; |
|
1581 } |
|
1582 |
|
1583 static uint32_t rtl8139_Config0_read(RTL8139State *s) |
|
1584 { |
|
1585 uint32_t ret = s->Config0; |
|
1586 |
|
1587 DEBUG_PRINT(("RTL8139: Config0 read val=0x%02x\n", ret)); |
|
1588 |
|
1589 return ret; |
|
1590 } |
|
1591 |
|
1592 static void rtl8139_Config1_write(RTL8139State *s, uint32_t val) |
|
1593 { |
|
1594 val &= 0xff; |
|
1595 |
|
1596 DEBUG_PRINT(("RTL8139: Config1 write val=0x%02x\n", val)); |
|
1597 |
|
1598 if (!rtl8139_config_writeable(s)) |
|
1599 return; |
|
1600 |
|
1601 /* mask unwriteable bits */ |
|
1602 val = SET_MASKED(val, 0xC, s->Config1); |
|
1603 |
|
1604 s->Config1 = val; |
|
1605 } |
|
1606 |
|
1607 static uint32_t rtl8139_Config1_read(RTL8139State *s) |
|
1608 { |
|
1609 uint32_t ret = s->Config1; |
|
1610 |
|
1611 DEBUG_PRINT(("RTL8139: Config1 read val=0x%02x\n", ret)); |
|
1612 |
|
1613 return ret; |
|
1614 } |
|
1615 |
|
1616 static void rtl8139_Config3_write(RTL8139State *s, uint32_t val) |
|
1617 { |
|
1618 val &= 0xff; |
|
1619 |
|
1620 DEBUG_PRINT(("RTL8139: Config3 write val=0x%02x\n", val)); |
|
1621 |
|
1622 if (!rtl8139_config_writeable(s)) |
|
1623 return; |
|
1624 |
|
1625 /* mask unwriteable bits */ |
|
1626 val = SET_MASKED(val, 0x8F, s->Config3); |
|
1627 |
|
1628 s->Config3 = val; |
|
1629 } |
|
1630 |
|
1631 static uint32_t rtl8139_Config3_read(RTL8139State *s) |
|
1632 { |
|
1633 uint32_t ret = s->Config3; |
|
1634 |
|
1635 DEBUG_PRINT(("RTL8139: Config3 read val=0x%02x\n", ret)); |
|
1636 |
|
1637 return ret; |
|
1638 } |
|
1639 |
|
1640 static void rtl8139_Config4_write(RTL8139State *s, uint32_t val) |
|
1641 { |
|
1642 val &= 0xff; |
|
1643 |
|
1644 DEBUG_PRINT(("RTL8139: Config4 write val=0x%02x\n", val)); |
|
1645 |
|
1646 if (!rtl8139_config_writeable(s)) |
|
1647 return; |
|
1648 |
|
1649 /* mask unwriteable bits */ |
|
1650 val = SET_MASKED(val, 0x0a, s->Config4); |
|
1651 |
|
1652 s->Config4 = val; |
|
1653 } |
|
1654 |
|
1655 static uint32_t rtl8139_Config4_read(RTL8139State *s) |
|
1656 { |
|
1657 uint32_t ret = s->Config4; |
|
1658 |
|
1659 DEBUG_PRINT(("RTL8139: Config4 read val=0x%02x\n", ret)); |
|
1660 |
|
1661 return ret; |
|
1662 } |
|
1663 |
|
1664 static void rtl8139_Config5_write(RTL8139State *s, uint32_t val) |
|
1665 { |
|
1666 val &= 0xff; |
|
1667 |
|
1668 DEBUG_PRINT(("RTL8139: Config5 write val=0x%02x\n", val)); |
|
1669 |
|
1670 /* mask unwriteable bits */ |
|
1671 val = SET_MASKED(val, 0x80, s->Config5); |
|
1672 |
|
1673 s->Config5 = val; |
|
1674 } |
|
1675 |
|
1676 static uint32_t rtl8139_Config5_read(RTL8139State *s) |
|
1677 { |
|
1678 uint32_t ret = s->Config5; |
|
1679 |
|
1680 DEBUG_PRINT(("RTL8139: Config5 read val=0x%02x\n", ret)); |
|
1681 |
|
1682 return ret; |
|
1683 } |
|
1684 |
|
1685 static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val) |
|
1686 { |
|
1687 if (!rtl8139_transmitter_enabled(s)) |
|
1688 { |
|
1689 DEBUG_PRINT(("RTL8139: transmitter disabled; no TxConfig write val=0x%08x\n", val)); |
|
1690 return; |
|
1691 } |
|
1692 |
|
1693 DEBUG_PRINT(("RTL8139: TxConfig write val=0x%08x\n", val)); |
|
1694 |
|
1695 val = SET_MASKED(val, TxVersionMask | 0x8070f80f, s->TxConfig); |
|
1696 |
|
1697 s->TxConfig = val; |
|
1698 } |
|
1699 |
|
1700 static void rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val) |
|
1701 { |
|
1702 DEBUG_PRINT(("RTL8139C TxConfig via write(b) val=0x%02x\n", val)); |
|
1703 |
|
1704 uint32_t tc = s->TxConfig; |
|
1705 tc &= 0xFFFFFF00; |
|
1706 tc |= (val & 0x000000FF); |
|
1707 rtl8139_TxConfig_write(s, tc); |
|
1708 } |
|
1709 |
|
1710 static uint32_t rtl8139_TxConfig_read(RTL8139State *s) |
|
1711 { |
|
1712 uint32_t ret = s->TxConfig; |
|
1713 |
|
1714 DEBUG_PRINT(("RTL8139: TxConfig read val=0x%04x\n", ret)); |
|
1715 |
|
1716 return ret; |
|
1717 } |
|
1718 |
|
1719 static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val) |
|
1720 { |
|
1721 DEBUG_PRINT(("RTL8139: RxConfig write val=0x%08x\n", val)); |
|
1722 |
|
1723 /* mask unwriteable bits */ |
|
1724 val = SET_MASKED(val, 0xf0fc0040, s->RxConfig); |
|
1725 |
|
1726 s->RxConfig = val; |
|
1727 |
|
1728 /* reset buffer size and read/write pointers */ |
|
1729 rtl8139_reset_rxring(s, 8192 << ((s->RxConfig >> 11) & 0x3)); |
|
1730 |
|
1731 DEBUG_PRINT(("RTL8139: RxConfig write reset buffer size to %d\n", s->RxBufferSize)); |
|
1732 } |
|
1733 |
|
1734 static uint32_t rtl8139_RxConfig_read(RTL8139State *s) |
|
1735 { |
|
1736 uint32_t ret = s->RxConfig; |
|
1737 |
|
1738 DEBUG_PRINT(("RTL8139: RxConfig read val=0x%08x\n", ret)); |
|
1739 |
|
1740 return ret; |
|
1741 } |
|
1742 |
|
1743 static void rtl8139_transfer_frame(RTL8139State *s, const uint8_t *buf, int size, int do_interrupt) |
|
1744 { |
|
1745 if (!size) |
|
1746 { |
|
1747 DEBUG_PRINT(("RTL8139: +++ empty ethernet frame\n")); |
|
1748 return; |
|
1749 } |
|
1750 |
|
1751 if (TxLoopBack == (s->TxConfig & TxLoopBack)) |
|
1752 { |
|
1753 DEBUG_PRINT(("RTL8139: +++ transmit loopback mode\n")); |
|
1754 rtl8139_do_receive(s, buf, size, do_interrupt); |
|
1755 } |
|
1756 else |
|
1757 { |
|
1758 qemu_send_packet(s->vc, buf, size); |
|
1759 } |
|
1760 } |
|
1761 |
|
1762 static int rtl8139_transmit_one(RTL8139State *s, int descriptor) |
|
1763 { |
|
1764 if (!rtl8139_transmitter_enabled(s)) |
|
1765 { |
|
1766 DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: transmitter disabled\n", |
|
1767 descriptor)); |
|
1768 return 0; |
|
1769 } |
|
1770 |
|
1771 if (s->TxStatus[descriptor] & TxHostOwns) |
|
1772 { |
|
1773 DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: owned by host (%08x)\n", |
|
1774 descriptor, s->TxStatus[descriptor])); |
|
1775 return 0; |
|
1776 } |
|
1777 |
|
1778 DEBUG_PRINT(("RTL8139: +++ transmitting from descriptor %d\n", descriptor)); |
|
1779 |
|
1780 int txsize = s->TxStatus[descriptor] & 0x1fff; |
|
1781 uint8_t txbuffer[0x2000]; |
|
1782 |
|
1783 DEBUG_PRINT(("RTL8139: +++ transmit reading %d bytes from host memory at 0x%08x\n", |
|
1784 txsize, s->TxAddr[descriptor])); |
|
1785 |
|
1786 cpu_physical_memory_read(s->TxAddr[descriptor], txbuffer, txsize); |
|
1787 |
|
1788 /* Mark descriptor as transferred */ |
|
1789 s->TxStatus[descriptor] |= TxHostOwns; |
|
1790 s->TxStatus[descriptor] |= TxStatOK; |
|
1791 |
|
1792 rtl8139_transfer_frame(s, txbuffer, txsize, 0); |
|
1793 |
|
1794 DEBUG_PRINT(("RTL8139: +++ transmitted %d bytes from descriptor %d\n", txsize, descriptor)); |
|
1795 |
|
1796 /* update interrupt */ |
|
1797 s->IntrStatus |= TxOK; |
|
1798 rtl8139_update_irq(s); |
|
1799 |
|
1800 return 1; |
|
1801 } |
|
1802 |
|
1803 /* structures and macros for task offloading */ |
|
1804 typedef struct ip_header |
|
1805 { |
|
1806 uint8_t ip_ver_len; /* version and header length */ |
|
1807 uint8_t ip_tos; /* type of service */ |
|
1808 uint16_t ip_len; /* total length */ |
|
1809 uint16_t ip_id; /* identification */ |
|
1810 uint16_t ip_off; /* fragment offset field */ |
|
1811 uint8_t ip_ttl; /* time to live */ |
|
1812 uint8_t ip_p; /* protocol */ |
|
1813 uint16_t ip_sum; /* checksum */ |
|
1814 uint32_t ip_src,ip_dst; /* source and dest address */ |
|
1815 } ip_header; |
|
1816 |
|
1817 #define IP_HEADER_VERSION_4 4 |
|
1818 #define IP_HEADER_VERSION(ip) ((ip->ip_ver_len >> 4)&0xf) |
|
1819 #define IP_HEADER_LENGTH(ip) (((ip->ip_ver_len)&0xf) << 2) |
|
1820 |
|
1821 typedef struct tcp_header |
|
1822 { |
|
1823 uint16_t th_sport; /* source port */ |
|
1824 uint16_t th_dport; /* destination port */ |
|
1825 uint32_t th_seq; /* sequence number */ |
|
1826 uint32_t th_ack; /* acknowledgement number */ |
|
1827 uint16_t th_offset_flags; /* data offset, reserved 6 bits, TCP protocol flags */ |
|
1828 uint16_t th_win; /* window */ |
|
1829 uint16_t th_sum; /* checksum */ |
|
1830 uint16_t th_urp; /* urgent pointer */ |
|
1831 } tcp_header; |
|
1832 |
|
1833 typedef struct udp_header |
|
1834 { |
|
1835 uint16_t uh_sport; /* source port */ |
|
1836 uint16_t uh_dport; /* destination port */ |
|
1837 uint16_t uh_ulen; /* udp length */ |
|
1838 uint16_t uh_sum; /* udp checksum */ |
|
1839 } udp_header; |
|
1840 |
|
1841 typedef struct ip_pseudo_header |
|
1842 { |
|
1843 uint32_t ip_src; |
|
1844 uint32_t ip_dst; |
|
1845 uint8_t zeros; |
|
1846 uint8_t ip_proto; |
|
1847 uint16_t ip_payload; |
|
1848 } ip_pseudo_header; |
|
1849 |
|
1850 #define IP_PROTO_TCP 6 |
|
1851 #define IP_PROTO_UDP 17 |
|
1852 |
|
1853 #define TCP_HEADER_DATA_OFFSET(tcp) (((be16_to_cpu(tcp->th_offset_flags) >> 12)&0xf) << 2) |
|
1854 #define TCP_FLAGS_ONLY(flags) ((flags)&0x3f) |
|
1855 #define TCP_HEADER_FLAGS(tcp) TCP_FLAGS_ONLY(be16_to_cpu(tcp->th_offset_flags)) |
|
1856 |
|
1857 #define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= cpu_to_be16(~TCP_FLAGS_ONLY(off))) |
|
1858 |
|
1859 #define TCP_FLAG_FIN 0x01 |
|
1860 #define TCP_FLAG_PUSH 0x08 |
|
1861 |
|
1862 /* produces ones' complement sum of data */ |
|
1863 static uint16_t ones_complement_sum(uint8_t *data, size_t len) |
|
1864 { |
|
1865 uint32_t result = 0; |
|
1866 |
|
1867 for (; len > 1; data+=2, len-=2) |
|
1868 { |
|
1869 result += *(uint16_t*)data; |
|
1870 } |
|
1871 |
|
1872 /* add the remainder byte */ |
|
1873 if (len) |
|
1874 { |
|
1875 uint8_t odd[2] = {*data, 0}; |
|
1876 result += *(uint16_t*)odd; |
|
1877 } |
|
1878 |
|
1879 while (result>>16) |
|
1880 result = (result & 0xffff) + (result >> 16); |
|
1881 |
|
1882 return result; |
|
1883 } |
|
1884 |
|
1885 static uint16_t ip_checksum(void *data, size_t len) |
|
1886 { |
|
1887 return ~ones_complement_sum((uint8_t*)data, len); |
|
1888 } |
|
1889 |
|
1890 static int rtl8139_cplus_transmit_one(RTL8139State *s) |
|
1891 { |
|
1892 if (!rtl8139_transmitter_enabled(s)) |
|
1893 { |
|
1894 DEBUG_PRINT(("RTL8139: +++ C+ mode: transmitter disabled\n")); |
|
1895 return 0; |
|
1896 } |
|
1897 |
|
1898 if (!rtl8139_cp_transmitter_enabled(s)) |
|
1899 { |
|
1900 DEBUG_PRINT(("RTL8139: +++ C+ mode: C+ transmitter disabled\n")); |
|
1901 return 0 ; |
|
1902 } |
|
1903 |
|
1904 int descriptor = s->currCPlusTxDesc; |
|
1905 |
|
1906 target_phys_addr_t cplus_tx_ring_desc = |
|
1907 rtl8139_addr64(s->TxAddr[0], s->TxAddr[1]); |
|
1908 |
|
1909 /* Normal priority ring */ |
|
1910 cplus_tx_ring_desc += 16 * descriptor; |
|
1911 |
|
1912 DEBUG_PRINT(("RTL8139: +++ C+ mode reading TX descriptor %d from host memory at %08x0x%08x = 0x%8lx\n", |
|
1913 descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc)); |
|
1914 |
|
1915 uint32_t val, txdw0,txdw1,txbufLO,txbufHI; |
|
1916 |
|
1917 cpu_physical_memory_read(cplus_tx_ring_desc, (uint8_t *)&val, 4); |
|
1918 txdw0 = le32_to_cpu(val); |
|
1919 cpu_physical_memory_read(cplus_tx_ring_desc+4, (uint8_t *)&val, 4); |
|
1920 txdw1 = le32_to_cpu(val); |
|
1921 cpu_physical_memory_read(cplus_tx_ring_desc+8, (uint8_t *)&val, 4); |
|
1922 txbufLO = le32_to_cpu(val); |
|
1923 cpu_physical_memory_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4); |
|
1924 txbufHI = le32_to_cpu(val); |
|
1925 |
|
1926 DEBUG_PRINT(("RTL8139: +++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", |
|
1927 descriptor, |
|
1928 txdw0, txdw1, txbufLO, txbufHI)); |
|
1929 |
|
1930 /* w0 ownership flag */ |
|
1931 #define CP_TX_OWN (1<<31) |
|
1932 /* w0 end of ring flag */ |
|
1933 #define CP_TX_EOR (1<<30) |
|
1934 /* first segment of received packet flag */ |
|
1935 #define CP_TX_FS (1<<29) |
|
1936 /* last segment of received packet flag */ |
|
1937 #define CP_TX_LS (1<<28) |
|
1938 /* large send packet flag */ |
|
1939 #define CP_TX_LGSEN (1<<27) |
|
1940 /* large send MSS mask, bits 16...25 */ |
|
1941 #define CP_TC_LGSEN_MSS_MASK ((1 << 12) - 1) |
|
1942 |
|
1943 /* IP checksum offload flag */ |
|
1944 #define CP_TX_IPCS (1<<18) |
|
1945 /* UDP checksum offload flag */ |
|
1946 #define CP_TX_UDPCS (1<<17) |
|
1947 /* TCP checksum offload flag */ |
|
1948 #define CP_TX_TCPCS (1<<16) |
|
1949 |
|
1950 /* w0 bits 0...15 : buffer size */ |
|
1951 #define CP_TX_BUFFER_SIZE (1<<16) |
|
1952 #define CP_TX_BUFFER_SIZE_MASK (CP_TX_BUFFER_SIZE - 1) |
|
1953 /* w1 tag available flag */ |
|
1954 #define CP_RX_TAGC (1<<17) |
|
1955 /* w1 bits 0...15 : VLAN tag */ |
|
1956 #define CP_TX_VLAN_TAG_MASK ((1<<16) - 1) |
|
1957 /* w2 low 32bit of Rx buffer ptr */ |
|
1958 /* w3 high 32bit of Rx buffer ptr */ |
|
1959 |
|
1960 /* set after transmission */ |
|
1961 /* FIFO underrun flag */ |
|
1962 #define CP_TX_STATUS_UNF (1<<25) |
|
1963 /* transmit error summary flag, valid if set any of three below */ |
|
1964 #define CP_TX_STATUS_TES (1<<23) |
|
1965 /* out-of-window collision flag */ |
|
1966 #define CP_TX_STATUS_OWC (1<<22) |
|
1967 /* link failure flag */ |
|
1968 #define CP_TX_STATUS_LNKF (1<<21) |
|
1969 /* excessive collisions flag */ |
|
1970 #define CP_TX_STATUS_EXC (1<<20) |
|
1971 |
|
1972 if (!(txdw0 & CP_TX_OWN)) |
|
1973 { |
|
1974 DEBUG_PRINT(("RTL8139: C+ Tx mode : descriptor %d is owned by host\n", descriptor)); |
|
1975 return 0 ; |
|
1976 } |
|
1977 |
|
1978 DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : transmitting from descriptor %d\n", descriptor)); |
|
1979 |
|
1980 if (txdw0 & CP_TX_FS) |
|
1981 { |
|
1982 DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is first segment descriptor\n", descriptor)); |
|
1983 |
|
1984 /* reset internal buffer offset */ |
|
1985 s->cplus_txbuffer_offset = 0; |
|
1986 } |
|
1987 |
|
1988 int txsize = txdw0 & CP_TX_BUFFER_SIZE_MASK; |
|
1989 target_phys_addr_t tx_addr = rtl8139_addr64(txbufLO, txbufHI); |
|
1990 |
|
1991 /* make sure we have enough space to assemble the packet */ |
|
1992 if (!s->cplus_txbuffer) |
|
1993 { |
|
1994 s->cplus_txbuffer_len = CP_TX_BUFFER_SIZE; |
|
1995 s->cplus_txbuffer = malloc(s->cplus_txbuffer_len); |
|
1996 s->cplus_txbuffer_offset = 0; |
|
1997 |
|
1998 DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer allocated space %d\n", s->cplus_txbuffer_len)); |
|
1999 } |
|
2000 |
|
2001 while (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len) |
|
2002 { |
|
2003 s->cplus_txbuffer_len += CP_TX_BUFFER_SIZE; |
|
2004 s->cplus_txbuffer = qemu_realloc(s->cplus_txbuffer, s->cplus_txbuffer_len); |
|
2005 |
|
2006 DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer space changed to %d\n", s->cplus_txbuffer_len)); |
|
2007 } |
|
2008 |
|
2009 if (!s->cplus_txbuffer) |
|
2010 { |
|
2011 /* out of memory */ |
|
2012 |
|
2013 DEBUG_PRINT(("RTL8139: +++ C+ mode transmiter failed to reallocate %d bytes\n", s->cplus_txbuffer_len)); |
|
2014 |
|
2015 /* update tally counter */ |
|
2016 ++s->tally_counters.TxERR; |
|
2017 ++s->tally_counters.TxAbt; |
|
2018 |
|
2019 return 0; |
|
2020 } |
|
2021 |
|
2022 /* append more data to the packet */ |
|
2023 |
|
2024 DEBUG_PRINT(("RTL8139: +++ C+ mode transmit reading %d bytes from host memory at %016" PRIx64 " to offset %d\n", |
|
2025 txsize, (uint64_t)tx_addr, s->cplus_txbuffer_offset)); |
|
2026 |
|
2027 cpu_physical_memory_read(tx_addr, s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize); |
|
2028 s->cplus_txbuffer_offset += txsize; |
|
2029 |
|
2030 /* seek to next Rx descriptor */ |
|
2031 if (txdw0 & CP_TX_EOR) |
|
2032 { |
|
2033 s->currCPlusTxDesc = 0; |
|
2034 } |
|
2035 else |
|
2036 { |
|
2037 ++s->currCPlusTxDesc; |
|
2038 if (s->currCPlusTxDesc >= 64) |
|
2039 s->currCPlusTxDesc = 0; |
|
2040 } |
|
2041 |
|
2042 /* transfer ownership to target */ |
|
2043 txdw0 &= ~CP_RX_OWN; |
|
2044 |
|
2045 /* reset error indicator bits */ |
|
2046 txdw0 &= ~CP_TX_STATUS_UNF; |
|
2047 txdw0 &= ~CP_TX_STATUS_TES; |
|
2048 txdw0 &= ~CP_TX_STATUS_OWC; |
|
2049 txdw0 &= ~CP_TX_STATUS_LNKF; |
|
2050 txdw0 &= ~CP_TX_STATUS_EXC; |
|
2051 |
|
2052 /* update ring data */ |
|
2053 val = cpu_to_le32(txdw0); |
|
2054 cpu_physical_memory_write(cplus_tx_ring_desc, (uint8_t *)&val, 4); |
|
2055 // val = cpu_to_le32(txdw1); |
|
2056 // cpu_physical_memory_write(cplus_tx_ring_desc+4, &val, 4); |
|
2057 |
|
2058 /* Now decide if descriptor being processed is holding the last segment of packet */ |
|
2059 if (txdw0 & CP_TX_LS) |
|
2060 { |
|
2061 DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is last segment descriptor\n", descriptor)); |
|
2062 |
|
2063 /* can transfer fully assembled packet */ |
|
2064 |
|
2065 uint8_t *saved_buffer = s->cplus_txbuffer; |
|
2066 int saved_size = s->cplus_txbuffer_offset; |
|
2067 int saved_buffer_len = s->cplus_txbuffer_len; |
|
2068 |
|
2069 /* reset the card space to protect from recursive call */ |
|
2070 s->cplus_txbuffer = NULL; |
|
2071 s->cplus_txbuffer_offset = 0; |
|
2072 s->cplus_txbuffer_len = 0; |
|
2073 |
|
2074 if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN)) |
|
2075 { |
|
2076 DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task checksum\n")); |
|
2077 |
|
2078 #define ETH_P_IP 0x0800 /* Internet Protocol packet */ |
|
2079 #define ETH_HLEN 14 |
|
2080 #define ETH_MTU 1500 |
|
2081 |
|
2082 /* ip packet header */ |
|
2083 ip_header *ip = 0; |
|
2084 int hlen = 0; |
|
2085 uint8_t ip_protocol = 0; |
|
2086 uint16_t ip_data_len = 0; |
|
2087 |
|
2088 uint8_t *eth_payload_data = 0; |
|
2089 size_t eth_payload_len = 0; |
|
2090 |
|
2091 int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12)); |
|
2092 if (proto == ETH_P_IP) |
|
2093 { |
|
2094 DEBUG_PRINT(("RTL8139: +++ C+ mode has IP packet\n")); |
|
2095 |
|
2096 /* not aligned */ |
|
2097 eth_payload_data = saved_buffer + ETH_HLEN; |
|
2098 eth_payload_len = saved_size - ETH_HLEN; |
|
2099 |
|
2100 ip = (ip_header*)eth_payload_data; |
|
2101 |
|
2102 if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { |
|
2103 DEBUG_PRINT(("RTL8139: +++ C+ mode packet has bad IP version %d expected %d\n", IP_HEADER_VERSION(ip), IP_HEADER_VERSION_4)); |
|
2104 ip = NULL; |
|
2105 } else { |
|
2106 hlen = IP_HEADER_LENGTH(ip); |
|
2107 ip_protocol = ip->ip_p; |
|
2108 ip_data_len = be16_to_cpu(ip->ip_len) - hlen; |
|
2109 } |
|
2110 } |
|
2111 |
|
2112 if (ip) |
|
2113 { |
|
2114 if (txdw0 & CP_TX_IPCS) |
|
2115 { |
|
2116 DEBUG_PRINT(("RTL8139: +++ C+ mode need IP checksum\n")); |
|
2117 |
|
2118 if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */ |
|
2119 /* bad packet header len */ |
|
2120 /* or packet too short */ |
|
2121 } |
|
2122 else |
|
2123 { |
|
2124 ip->ip_sum = 0; |
|
2125 ip->ip_sum = ip_checksum(ip, hlen); |
|
2126 DEBUG_PRINT(("RTL8139: +++ C+ mode IP header len=%d checksum=%04x\n", hlen, ip->ip_sum)); |
|
2127 } |
|
2128 } |
|
2129 |
|
2130 if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) |
|
2131 { |
|
2132 #if defined (DEBUG_RTL8139) |
|
2133 int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK; |
|
2134 #endif |
|
2135 DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task TSO MTU=%d IP data %d frame data %d specified MSS=%d\n", |
|
2136 ETH_MTU, ip_data_len, saved_size - ETH_HLEN, large_send_mss)); |
|
2137 |
|
2138 int tcp_send_offset = 0; |
|
2139 int send_count = 0; |
|
2140 |
|
2141 /* maximum IP header length is 60 bytes */ |
|
2142 uint8_t saved_ip_header[60]; |
|
2143 |
|
2144 /* save IP header template; data area is used in tcp checksum calculation */ |
|
2145 memcpy(saved_ip_header, eth_payload_data, hlen); |
|
2146 |
|
2147 /* a placeholder for checksum calculation routine in tcp case */ |
|
2148 uint8_t *data_to_checksum = eth_payload_data + hlen - 12; |
|
2149 // size_t data_to_checksum_len = eth_payload_len - hlen + 12; |
|
2150 |
|
2151 /* pointer to TCP header */ |
|
2152 tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen); |
|
2153 |
|
2154 int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr); |
|
2155 |
|
2156 /* ETH_MTU = ip header len + tcp header len + payload */ |
|
2157 int tcp_data_len = ip_data_len - tcp_hlen; |
|
2158 int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen; |
|
2159 |
|
2160 DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP data len %d TCP hlen %d TCP data len %d TCP chunk size %d\n", |
|
2161 ip_data_len, tcp_hlen, tcp_data_len, tcp_chunk_size)); |
|
2162 |
|
2163 /* note the cycle below overwrites IP header data, |
|
2164 but restores it from saved_ip_header before sending packet */ |
|
2165 |
|
2166 int is_last_frame = 0; |
|
2167 |
|
2168 for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size) |
|
2169 { |
|
2170 uint16_t chunk_size = tcp_chunk_size; |
|
2171 |
|
2172 /* check if this is the last frame */ |
|
2173 if (tcp_send_offset + tcp_chunk_size >= tcp_data_len) |
|
2174 { |
|
2175 is_last_frame = 1; |
|
2176 chunk_size = tcp_data_len - tcp_send_offset; |
|
2177 } |
|
2178 |
|
2179 DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP seqno %08x\n", be32_to_cpu(p_tcp_hdr->th_seq))); |
|
2180 |
|
2181 /* add 4 TCP pseudoheader fields */ |
|
2182 /* copy IP source and destination fields */ |
|
2183 memcpy(data_to_checksum, saved_ip_header + 12, 8); |
|
2184 |
|
2185 DEBUG_PRINT(("RTL8139: +++ C+ mode TSO calculating TCP checksum for packet with %d bytes data\n", tcp_hlen + chunk_size)); |
|
2186 |
|
2187 if (tcp_send_offset) |
|
2188 { |
|
2189 memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); |
|
2190 } |
|
2191 |
|
2192 /* keep PUSH and FIN flags only for the last frame */ |
|
2193 if (!is_last_frame) |
|
2194 { |
|
2195 TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN); |
|
2196 } |
|
2197 |
|
2198 /* recalculate TCP checksum */ |
|
2199 ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; |
|
2200 p_tcpip_hdr->zeros = 0; |
|
2201 p_tcpip_hdr->ip_proto = IP_PROTO_TCP; |
|
2202 p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size); |
|
2203 |
|
2204 p_tcp_hdr->th_sum = 0; |
|
2205 |
|
2206 int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12); |
|
2207 DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP checksum %04x\n", tcp_checksum)); |
|
2208 |
|
2209 p_tcp_hdr->th_sum = tcp_checksum; |
|
2210 |
|
2211 /* restore IP header */ |
|
2212 memcpy(eth_payload_data, saved_ip_header, hlen); |
|
2213 |
|
2214 /* set IP data length and recalculate IP checksum */ |
|
2215 ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size); |
|
2216 |
|
2217 /* increment IP id for subsequent frames */ |
|
2218 ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id)); |
|
2219 |
|
2220 ip->ip_sum = 0; |
|
2221 ip->ip_sum = ip_checksum(eth_payload_data, hlen); |
|
2222 DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP header len=%d checksum=%04x\n", hlen, ip->ip_sum)); |
|
2223 |
|
2224 int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size; |
|
2225 DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring packet size %d\n", tso_send_size)); |
|
2226 rtl8139_transfer_frame(s, saved_buffer, tso_send_size, 0); |
|
2227 |
|
2228 /* add transferred count to TCP sequence number */ |
|
2229 p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq)); |
|
2230 ++send_count; |
|
2231 } |
|
2232 |
|
2233 /* Stop sending this frame */ |
|
2234 saved_size = 0; |
|
2235 } |
|
2236 else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS)) |
|
2237 { |
|
2238 DEBUG_PRINT(("RTL8139: +++ C+ mode need TCP or UDP checksum\n")); |
|
2239 |
|
2240 /* maximum IP header length is 60 bytes */ |
|
2241 uint8_t saved_ip_header[60]; |
|
2242 memcpy(saved_ip_header, eth_payload_data, hlen); |
|
2243 |
|
2244 uint8_t *data_to_checksum = eth_payload_data + hlen - 12; |
|
2245 // size_t data_to_checksum_len = eth_payload_len - hlen + 12; |
|
2246 |
|
2247 /* add 4 TCP pseudoheader fields */ |
|
2248 /* copy IP source and destination fields */ |
|
2249 memcpy(data_to_checksum, saved_ip_header + 12, 8); |
|
2250 |
|
2251 if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) |
|
2252 { |
|
2253 DEBUG_PRINT(("RTL8139: +++ C+ mode calculating TCP checksum for packet with %d bytes data\n", ip_data_len)); |
|
2254 |
|
2255 ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; |
|
2256 p_tcpip_hdr->zeros = 0; |
|
2257 p_tcpip_hdr->ip_proto = IP_PROTO_TCP; |
|
2258 p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len); |
|
2259 |
|
2260 tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12); |
|
2261 |
|
2262 p_tcp_hdr->th_sum = 0; |
|
2263 |
|
2264 int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); |
|
2265 DEBUG_PRINT(("RTL8139: +++ C+ mode TCP checksum %04x\n", tcp_checksum)); |
|
2266 |
|
2267 p_tcp_hdr->th_sum = tcp_checksum; |
|
2268 } |
|
2269 else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) |
|
2270 { |
|
2271 DEBUG_PRINT(("RTL8139: +++ C+ mode calculating UDP checksum for packet with %d bytes data\n", ip_data_len)); |
|
2272 |
|
2273 ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum; |
|
2274 p_udpip_hdr->zeros = 0; |
|
2275 p_udpip_hdr->ip_proto = IP_PROTO_UDP; |
|
2276 p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len); |
|
2277 |
|
2278 udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12); |
|
2279 |
|
2280 p_udp_hdr->uh_sum = 0; |
|
2281 |
|
2282 int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); |
|
2283 DEBUG_PRINT(("RTL8139: +++ C+ mode UDP checksum %04x\n", udp_checksum)); |
|
2284 |
|
2285 p_udp_hdr->uh_sum = udp_checksum; |
|
2286 } |
|
2287 |
|
2288 /* restore IP header */ |
|
2289 memcpy(eth_payload_data, saved_ip_header, hlen); |
|
2290 } |
|
2291 } |
|
2292 } |
|
2293 |
|
2294 /* update tally counter */ |
|
2295 ++s->tally_counters.TxOk; |
|
2296 |
|
2297 DEBUG_PRINT(("RTL8139: +++ C+ mode transmitting %d bytes packet\n", saved_size)); |
|
2298 |
|
2299 rtl8139_transfer_frame(s, saved_buffer, saved_size, 1); |
|
2300 |
|
2301 /* restore card space if there was no recursion and reset offset */ |
|
2302 if (!s->cplus_txbuffer) |
|
2303 { |
|
2304 s->cplus_txbuffer = saved_buffer; |
|
2305 s->cplus_txbuffer_len = saved_buffer_len; |
|
2306 s->cplus_txbuffer_offset = 0; |
|
2307 } |
|
2308 else |
|
2309 { |
|
2310 free(saved_buffer); |
|
2311 } |
|
2312 } |
|
2313 else |
|
2314 { |
|
2315 DEBUG_PRINT(("RTL8139: +++ C+ mode transmission continue to next descriptor\n")); |
|
2316 } |
|
2317 |
|
2318 return 1; |
|
2319 } |
|
2320 |
|
2321 static void rtl8139_cplus_transmit(RTL8139State *s) |
|
2322 { |
|
2323 int txcount = 0; |
|
2324 |
|
2325 while (rtl8139_cplus_transmit_one(s)) |
|
2326 { |
|
2327 ++txcount; |
|
2328 } |
|
2329 |
|
2330 /* Mark transfer completed */ |
|
2331 if (!txcount) |
|
2332 { |
|
2333 DEBUG_PRINT(("RTL8139: C+ mode : transmitter queue stalled, current TxDesc = %d\n", |
|
2334 s->currCPlusTxDesc)); |
|
2335 } |
|
2336 else |
|
2337 { |
|
2338 /* update interrupt status */ |
|
2339 s->IntrStatus |= TxOK; |
|
2340 rtl8139_update_irq(s); |
|
2341 } |
|
2342 } |
|
2343 |
|
2344 static void rtl8139_transmit(RTL8139State *s) |
|
2345 { |
|
2346 int descriptor = s->currTxDesc, txcount = 0; |
|
2347 |
|
2348 /*while*/ |
|
2349 if (rtl8139_transmit_one(s, descriptor)) |
|
2350 { |
|
2351 ++s->currTxDesc; |
|
2352 s->currTxDesc %= 4; |
|
2353 ++txcount; |
|
2354 } |
|
2355 |
|
2356 /* Mark transfer completed */ |
|
2357 if (!txcount) |
|
2358 { |
|
2359 DEBUG_PRINT(("RTL8139: transmitter queue stalled, current TxDesc = %d\n", s->currTxDesc)); |
|
2360 } |
|
2361 } |
|
2362 |
|
2363 static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val) |
|
2364 { |
|
2365 |
|
2366 int descriptor = txRegOffset/4; |
|
2367 |
|
2368 /* handle C+ transmit mode register configuration */ |
|
2369 |
|
2370 if (rtl8139_cp_transmitter_enabled(s)) |
|
2371 { |
|
2372 DEBUG_PRINT(("RTL8139C+ DTCCR write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor)); |
|
2373 |
|
2374 /* handle Dump Tally Counters command */ |
|
2375 s->TxStatus[descriptor] = val; |
|
2376 |
|
2377 if (descriptor == 0 && (val & 0x8)) |
|
2378 { |
|
2379 target_phys_addr_t tc_addr = rtl8139_addr64(s->TxStatus[0] & ~0x3f, s->TxStatus[1]); |
|
2380 |
|
2381 /* dump tally counters to specified memory location */ |
|
2382 RTL8139TallyCounters_physical_memory_write( tc_addr, &s->tally_counters); |
|
2383 |
|
2384 /* mark dump completed */ |
|
2385 s->TxStatus[0] &= ~0x8; |
|
2386 } |
|
2387 |
|
2388 return; |
|
2389 } |
|
2390 |
|
2391 DEBUG_PRINT(("RTL8139: TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor)); |
|
2392 |
|
2393 /* mask only reserved bits */ |
|
2394 val &= ~0xff00c000; /* these bits are reset on write */ |
|
2395 val = SET_MASKED(val, 0x00c00000, s->TxStatus[descriptor]); |
|
2396 |
|
2397 s->TxStatus[descriptor] = val; |
|
2398 |
|
2399 /* attempt to start transmission */ |
|
2400 rtl8139_transmit(s); |
|
2401 } |
|
2402 |
|
2403 static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint32_t txRegOffset) |
|
2404 { |
|
2405 uint32_t ret = s->TxStatus[txRegOffset/4]; |
|
2406 |
|
2407 DEBUG_PRINT(("RTL8139: TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, ret)); |
|
2408 |
|
2409 return ret; |
|
2410 } |
|
2411 |
|
2412 static uint16_t rtl8139_TSAD_read(RTL8139State *s) |
|
2413 { |
|
2414 uint16_t ret = 0; |
|
2415 |
|
2416 /* Simulate TSAD, it is read only anyway */ |
|
2417 |
|
2418 ret = ((s->TxStatus[3] & TxStatOK )?TSAD_TOK3:0) |
|
2419 |((s->TxStatus[2] & TxStatOK )?TSAD_TOK2:0) |
|
2420 |((s->TxStatus[1] & TxStatOK )?TSAD_TOK1:0) |
|
2421 |((s->TxStatus[0] & TxStatOK )?TSAD_TOK0:0) |
|
2422 |
|
2423 |((s->TxStatus[3] & TxUnderrun)?TSAD_TUN3:0) |
|
2424 |((s->TxStatus[2] & TxUnderrun)?TSAD_TUN2:0) |
|
2425 |((s->TxStatus[1] & TxUnderrun)?TSAD_TUN1:0) |
|
2426 |((s->TxStatus[0] & TxUnderrun)?TSAD_TUN0:0) |
|
2427 |
|
2428 |((s->TxStatus[3] & TxAborted )?TSAD_TABT3:0) |
|
2429 |((s->TxStatus[2] & TxAborted )?TSAD_TABT2:0) |
|
2430 |((s->TxStatus[1] & TxAborted )?TSAD_TABT1:0) |
|
2431 |((s->TxStatus[0] & TxAborted )?TSAD_TABT0:0) |
|
2432 |
|
2433 |((s->TxStatus[3] & TxHostOwns )?TSAD_OWN3:0) |
|
2434 |((s->TxStatus[2] & TxHostOwns )?TSAD_OWN2:0) |
|
2435 |((s->TxStatus[1] & TxHostOwns )?TSAD_OWN1:0) |
|
2436 |((s->TxStatus[0] & TxHostOwns )?TSAD_OWN0:0) ; |
|
2437 |
|
2438 |
|
2439 DEBUG_PRINT(("RTL8139: TSAD read val=0x%04x\n", ret)); |
|
2440 |
|
2441 return ret; |
|
2442 } |
|
2443 |
|
2444 static uint16_t rtl8139_CSCR_read(RTL8139State *s) |
|
2445 { |
|
2446 uint16_t ret = s->CSCR; |
|
2447 |
|
2448 DEBUG_PRINT(("RTL8139: CSCR read val=0x%04x\n", ret)); |
|
2449 |
|
2450 return ret; |
|
2451 } |
|
2452 |
|
2453 static void rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val) |
|
2454 { |
|
2455 DEBUG_PRINT(("RTL8139: TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val)); |
|
2456 |
|
2457 s->TxAddr[txAddrOffset/4] = val; |
|
2458 } |
|
2459 |
|
2460 static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset) |
|
2461 { |
|
2462 uint32_t ret = s->TxAddr[txAddrOffset/4]; |
|
2463 |
|
2464 DEBUG_PRINT(("RTL8139: TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret)); |
|
2465 |
|
2466 return ret; |
|
2467 } |
|
2468 |
|
2469 static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val) |
|
2470 { |
|
2471 DEBUG_PRINT(("RTL8139: RxBufPtr write val=0x%04x\n", val)); |
|
2472 |
|
2473 /* this value is off by 16 */ |
|
2474 s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize); |
|
2475 |
|
2476 DEBUG_PRINT((" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n", |
|
2477 s->RxBufferSize, s->RxBufAddr, s->RxBufPtr)); |
|
2478 } |
|
2479 |
|
2480 static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s) |
|
2481 { |
|
2482 /* this value is off by 16 */ |
|
2483 uint32_t ret = s->RxBufPtr - 0x10; |
|
2484 |
|
2485 DEBUG_PRINT(("RTL8139: RxBufPtr read val=0x%04x\n", ret)); |
|
2486 |
|
2487 return ret; |
|
2488 } |
|
2489 |
|
2490 static uint32_t rtl8139_RxBufAddr_read(RTL8139State *s) |
|
2491 { |
|
2492 /* this value is NOT off by 16 */ |
|
2493 uint32_t ret = s->RxBufAddr; |
|
2494 |
|
2495 DEBUG_PRINT(("RTL8139: RxBufAddr read val=0x%04x\n", ret)); |
|
2496 |
|
2497 return ret; |
|
2498 } |
|
2499 |
|
2500 static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val) |
|
2501 { |
|
2502 DEBUG_PRINT(("RTL8139: RxBuf write val=0x%08x\n", val)); |
|
2503 |
|
2504 s->RxBuf = val; |
|
2505 |
|
2506 /* may need to reset rxring here */ |
|
2507 } |
|
2508 |
|
2509 static uint32_t rtl8139_RxBuf_read(RTL8139State *s) |
|
2510 { |
|
2511 uint32_t ret = s->RxBuf; |
|
2512 |
|
2513 DEBUG_PRINT(("RTL8139: RxBuf read val=0x%08x\n", ret)); |
|
2514 |
|
2515 return ret; |
|
2516 } |
|
2517 |
|
2518 static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val) |
|
2519 { |
|
2520 DEBUG_PRINT(("RTL8139: IntrMask write(w) val=0x%04x\n", val)); |
|
2521 |
|
2522 /* mask unwriteable bits */ |
|
2523 val = SET_MASKED(val, 0x1e00, s->IntrMask); |
|
2524 |
|
2525 s->IntrMask = val; |
|
2526 |
|
2527 rtl8139_update_irq(s); |
|
2528 } |
|
2529 |
|
2530 static uint32_t rtl8139_IntrMask_read(RTL8139State *s) |
|
2531 { |
|
2532 uint32_t ret = s->IntrMask; |
|
2533 |
|
2534 DEBUG_PRINT(("RTL8139: IntrMask read(w) val=0x%04x\n", ret)); |
|
2535 |
|
2536 return ret; |
|
2537 } |
|
2538 |
|
2539 static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val) |
|
2540 { |
|
2541 DEBUG_PRINT(("RTL8139: IntrStatus write(w) val=0x%04x\n", val)); |
|
2542 |
|
2543 #if 0 |
|
2544 |
|
2545 /* writing to ISR has no effect */ |
|
2546 |
|
2547 return; |
|
2548 |
|
2549 #else |
|
2550 uint16_t newStatus = s->IntrStatus & ~val; |
|
2551 |
|
2552 /* mask unwriteable bits */ |
|
2553 newStatus = SET_MASKED(newStatus, 0x1e00, s->IntrStatus); |
|
2554 |
|
2555 /* writing 1 to interrupt status register bit clears it */ |
|
2556 s->IntrStatus = 0; |
|
2557 rtl8139_update_irq(s); |
|
2558 |
|
2559 s->IntrStatus = newStatus; |
|
2560 rtl8139_update_irq(s); |
|
2561 #endif |
|
2562 } |
|
2563 |
|
2564 static uint32_t rtl8139_IntrStatus_read(RTL8139State *s) |
|
2565 { |
|
2566 uint32_t ret = s->IntrStatus; |
|
2567 |
|
2568 DEBUG_PRINT(("RTL8139: IntrStatus read(w) val=0x%04x\n", ret)); |
|
2569 |
|
2570 #if 0 |
|
2571 |
|
2572 /* reading ISR clears all interrupts */ |
|
2573 s->IntrStatus = 0; |
|
2574 |
|
2575 rtl8139_update_irq(s); |
|
2576 |
|
2577 #endif |
|
2578 |
|
2579 return ret; |
|
2580 } |
|
2581 |
|
2582 static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val) |
|
2583 { |
|
2584 DEBUG_PRINT(("RTL8139: MultiIntr write(w) val=0x%04x\n", val)); |
|
2585 |
|
2586 /* mask unwriteable bits */ |
|
2587 val = SET_MASKED(val, 0xf000, s->MultiIntr); |
|
2588 |
|
2589 s->MultiIntr = val; |
|
2590 } |
|
2591 |
|
2592 static uint32_t rtl8139_MultiIntr_read(RTL8139State *s) |
|
2593 { |
|
2594 uint32_t ret = s->MultiIntr; |
|
2595 |
|
2596 DEBUG_PRINT(("RTL8139: MultiIntr read(w) val=0x%04x\n", ret)); |
|
2597 |
|
2598 return ret; |
|
2599 } |
|
2600 |
|
2601 static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val) |
|
2602 { |
|
2603 RTL8139State *s = opaque; |
|
2604 |
|
2605 addr &= 0xff; |
|
2606 |
|
2607 switch (addr) |
|
2608 { |
|
2609 case MAC0 ... MAC0+5: |
|
2610 s->phys[addr - MAC0] = val; |
|
2611 break; |
|
2612 case MAC0+6 ... MAC0+7: |
|
2613 /* reserved */ |
|
2614 break; |
|
2615 case MAR0 ... MAR0+7: |
|
2616 s->mult[addr - MAR0] = val; |
|
2617 break; |
|
2618 case ChipCmd: |
|
2619 rtl8139_ChipCmd_write(s, val); |
|
2620 break; |
|
2621 case Cfg9346: |
|
2622 rtl8139_Cfg9346_write(s, val); |
|
2623 break; |
|
2624 case TxConfig: /* windows driver sometimes writes using byte-lenth call */ |
|
2625 rtl8139_TxConfig_writeb(s, val); |
|
2626 break; |
|
2627 case Config0: |
|
2628 rtl8139_Config0_write(s, val); |
|
2629 break; |
|
2630 case Config1: |
|
2631 rtl8139_Config1_write(s, val); |
|
2632 break; |
|
2633 case Config3: |
|
2634 rtl8139_Config3_write(s, val); |
|
2635 break; |
|
2636 case Config4: |
|
2637 rtl8139_Config4_write(s, val); |
|
2638 break; |
|
2639 case Config5: |
|
2640 rtl8139_Config5_write(s, val); |
|
2641 break; |
|
2642 case MediaStatus: |
|
2643 /* ignore */ |
|
2644 DEBUG_PRINT(("RTL8139: not implemented write(b) to MediaStatus val=0x%02x\n", val)); |
|
2645 break; |
|
2646 |
|
2647 case HltClk: |
|
2648 DEBUG_PRINT(("RTL8139: HltClk write val=0x%08x\n", val)); |
|
2649 if (val == 'R') |
|
2650 { |
|
2651 s->clock_enabled = 1; |
|
2652 } |
|
2653 else if (val == 'H') |
|
2654 { |
|
2655 s->clock_enabled = 0; |
|
2656 } |
|
2657 break; |
|
2658 |
|
2659 case TxThresh: |
|
2660 DEBUG_PRINT(("RTL8139C+ TxThresh write(b) val=0x%02x\n", val)); |
|
2661 s->TxThresh = val; |
|
2662 break; |
|
2663 |
|
2664 case TxPoll: |
|
2665 DEBUG_PRINT(("RTL8139C+ TxPoll write(b) val=0x%02x\n", val)); |
|
2666 if (val & (1 << 7)) |
|
2667 { |
|
2668 DEBUG_PRINT(("RTL8139C+ TxPoll high priority transmission (not implemented)\n")); |
|
2669 //rtl8139_cplus_transmit(s); |
|
2670 } |
|
2671 if (val & (1 << 6)) |
|
2672 { |
|
2673 DEBUG_PRINT(("RTL8139C+ TxPoll normal priority transmission\n")); |
|
2674 rtl8139_cplus_transmit(s); |
|
2675 } |
|
2676 |
|
2677 break; |
|
2678 |
|
2679 default: |
|
2680 DEBUG_PRINT(("RTL8139: not implemented write(b) addr=0x%x val=0x%02x\n", addr, val)); |
|
2681 break; |
|
2682 } |
|
2683 } |
|
2684 |
|
2685 static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val) |
|
2686 { |
|
2687 RTL8139State *s = opaque; |
|
2688 |
|
2689 addr &= 0xfe; |
|
2690 |
|
2691 switch (addr) |
|
2692 { |
|
2693 case IntrMask: |
|
2694 rtl8139_IntrMask_write(s, val); |
|
2695 break; |
|
2696 |
|
2697 case IntrStatus: |
|
2698 rtl8139_IntrStatus_write(s, val); |
|
2699 break; |
|
2700 |
|
2701 case MultiIntr: |
|
2702 rtl8139_MultiIntr_write(s, val); |
|
2703 break; |
|
2704 |
|
2705 case RxBufPtr: |
|
2706 rtl8139_RxBufPtr_write(s, val); |
|
2707 break; |
|
2708 |
|
2709 case BasicModeCtrl: |
|
2710 rtl8139_BasicModeCtrl_write(s, val); |
|
2711 break; |
|
2712 case BasicModeStatus: |
|
2713 rtl8139_BasicModeStatus_write(s, val); |
|
2714 break; |
|
2715 case NWayAdvert: |
|
2716 DEBUG_PRINT(("RTL8139: NWayAdvert write(w) val=0x%04x\n", val)); |
|
2717 s->NWayAdvert = val; |
|
2718 break; |
|
2719 case NWayLPAR: |
|
2720 DEBUG_PRINT(("RTL8139: forbidden NWayLPAR write(w) val=0x%04x\n", val)); |
|
2721 break; |
|
2722 case NWayExpansion: |
|
2723 DEBUG_PRINT(("RTL8139: NWayExpansion write(w) val=0x%04x\n", val)); |
|
2724 s->NWayExpansion = val; |
|
2725 break; |
|
2726 |
|
2727 case CpCmd: |
|
2728 rtl8139_CpCmd_write(s, val); |
|
2729 break; |
|
2730 |
|
2731 case IntrMitigate: |
|
2732 rtl8139_IntrMitigate_write(s, val); |
|
2733 break; |
|
2734 |
|
2735 default: |
|
2736 DEBUG_PRINT(("RTL8139: ioport write(w) addr=0x%x val=0x%04x via write(b)\n", addr, val)); |
|
2737 |
|
2738 rtl8139_io_writeb(opaque, addr, val & 0xff); |
|
2739 rtl8139_io_writeb(opaque, addr + 1, (val >> 8) & 0xff); |
|
2740 break; |
|
2741 } |
|
2742 } |
|
2743 |
|
2744 static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val) |
|
2745 { |
|
2746 RTL8139State *s = opaque; |
|
2747 |
|
2748 addr &= 0xfc; |
|
2749 |
|
2750 switch (addr) |
|
2751 { |
|
2752 case RxMissed: |
|
2753 DEBUG_PRINT(("RTL8139: RxMissed clearing on write\n")); |
|
2754 s->RxMissed = 0; |
|
2755 break; |
|
2756 |
|
2757 case TxConfig: |
|
2758 rtl8139_TxConfig_write(s, val); |
|
2759 break; |
|
2760 |
|
2761 case RxConfig: |
|
2762 rtl8139_RxConfig_write(s, val); |
|
2763 break; |
|
2764 |
|
2765 case TxStatus0 ... TxStatus0+4*4-1: |
|
2766 rtl8139_TxStatus_write(s, addr-TxStatus0, val); |
|
2767 break; |
|
2768 |
|
2769 case TxAddr0 ... TxAddr0+4*4-1: |
|
2770 rtl8139_TxAddr_write(s, addr-TxAddr0, val); |
|
2771 break; |
|
2772 |
|
2773 case RxBuf: |
|
2774 rtl8139_RxBuf_write(s, val); |
|
2775 break; |
|
2776 |
|
2777 case RxRingAddrLO: |
|
2778 DEBUG_PRINT(("RTL8139: C+ RxRing low bits write val=0x%08x\n", val)); |
|
2779 s->RxRingAddrLO = val; |
|
2780 break; |
|
2781 |
|
2782 case RxRingAddrHI: |
|
2783 DEBUG_PRINT(("RTL8139: C+ RxRing high bits write val=0x%08x\n", val)); |
|
2784 s->RxRingAddrHI = val; |
|
2785 break; |
|
2786 |
|
2787 case Timer: |
|
2788 DEBUG_PRINT(("RTL8139: TCTR Timer reset on write\n")); |
|
2789 s->TCTR = 0; |
|
2790 s->TCTR_base = qemu_get_clock(vm_clock); |
|
2791 break; |
|
2792 |
|
2793 case FlashReg: |
|
2794 DEBUG_PRINT(("RTL8139: FlashReg TimerInt write val=0x%08x\n", val)); |
|
2795 s->TimerInt = val; |
|
2796 break; |
|
2797 |
|
2798 default: |
|
2799 DEBUG_PRINT(("RTL8139: ioport write(l) addr=0x%x val=0x%08x via write(b)\n", addr, val)); |
|
2800 rtl8139_io_writeb(opaque, addr, val & 0xff); |
|
2801 rtl8139_io_writeb(opaque, addr + 1, (val >> 8) & 0xff); |
|
2802 rtl8139_io_writeb(opaque, addr + 2, (val >> 16) & 0xff); |
|
2803 rtl8139_io_writeb(opaque, addr + 3, (val >> 24) & 0xff); |
|
2804 break; |
|
2805 } |
|
2806 } |
|
2807 |
|
2808 static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr) |
|
2809 { |
|
2810 RTL8139State *s = opaque; |
|
2811 int ret; |
|
2812 |
|
2813 addr &= 0xff; |
|
2814 |
|
2815 switch (addr) |
|
2816 { |
|
2817 case MAC0 ... MAC0+5: |
|
2818 ret = s->phys[addr - MAC0]; |
|
2819 break; |
|
2820 case MAC0+6 ... MAC0+7: |
|
2821 ret = 0; |
|
2822 break; |
|
2823 case MAR0 ... MAR0+7: |
|
2824 ret = s->mult[addr - MAR0]; |
|
2825 break; |
|
2826 case ChipCmd: |
|
2827 ret = rtl8139_ChipCmd_read(s); |
|
2828 break; |
|
2829 case Cfg9346: |
|
2830 ret = rtl8139_Cfg9346_read(s); |
|
2831 break; |
|
2832 case Config0: |
|
2833 ret = rtl8139_Config0_read(s); |
|
2834 break; |
|
2835 case Config1: |
|
2836 ret = rtl8139_Config1_read(s); |
|
2837 break; |
|
2838 case Config3: |
|
2839 ret = rtl8139_Config3_read(s); |
|
2840 break; |
|
2841 case Config4: |
|
2842 ret = rtl8139_Config4_read(s); |
|
2843 break; |
|
2844 case Config5: |
|
2845 ret = rtl8139_Config5_read(s); |
|
2846 break; |
|
2847 |
|
2848 case MediaStatus: |
|
2849 ret = 0xd0; |
|
2850 DEBUG_PRINT(("RTL8139: MediaStatus read 0x%x\n", ret)); |
|
2851 break; |
|
2852 |
|
2853 case HltClk: |
|
2854 ret = s->clock_enabled; |
|
2855 DEBUG_PRINT(("RTL8139: HltClk read 0x%x\n", ret)); |
|
2856 break; |
|
2857 |
|
2858 case PCIRevisionID: |
|
2859 ret = RTL8139_PCI_REVID; |
|
2860 DEBUG_PRINT(("RTL8139: PCI Revision ID read 0x%x\n", ret)); |
|
2861 break; |
|
2862 |
|
2863 case TxThresh: |
|
2864 ret = s->TxThresh; |
|
2865 DEBUG_PRINT(("RTL8139C+ TxThresh read(b) val=0x%02x\n", ret)); |
|
2866 break; |
|
2867 |
|
2868 case 0x43: /* Part of TxConfig register. Windows driver tries to read it */ |
|
2869 ret = s->TxConfig >> 24; |
|
2870 DEBUG_PRINT(("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret)); |
|
2871 break; |
|
2872 |
|
2873 default: |
|
2874 DEBUG_PRINT(("RTL8139: not implemented read(b) addr=0x%x\n", addr)); |
|
2875 ret = 0; |
|
2876 break; |
|
2877 } |
|
2878 |
|
2879 return ret; |
|
2880 } |
|
2881 |
|
2882 static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr) |
|
2883 { |
|
2884 RTL8139State *s = opaque; |
|
2885 uint32_t ret; |
|
2886 |
|
2887 addr &= 0xfe; /* mask lower bit */ |
|
2888 |
|
2889 switch (addr) |
|
2890 { |
|
2891 case IntrMask: |
|
2892 ret = rtl8139_IntrMask_read(s); |
|
2893 break; |
|
2894 |
|
2895 case IntrStatus: |
|
2896 ret = rtl8139_IntrStatus_read(s); |
|
2897 break; |
|
2898 |
|
2899 case MultiIntr: |
|
2900 ret = rtl8139_MultiIntr_read(s); |
|
2901 break; |
|
2902 |
|
2903 case RxBufPtr: |
|
2904 ret = rtl8139_RxBufPtr_read(s); |
|
2905 break; |
|
2906 |
|
2907 case RxBufAddr: |
|
2908 ret = rtl8139_RxBufAddr_read(s); |
|
2909 break; |
|
2910 |
|
2911 case BasicModeCtrl: |
|
2912 ret = rtl8139_BasicModeCtrl_read(s); |
|
2913 break; |
|
2914 case BasicModeStatus: |
|
2915 ret = rtl8139_BasicModeStatus_read(s); |
|
2916 break; |
|
2917 case NWayAdvert: |
|
2918 ret = s->NWayAdvert; |
|
2919 DEBUG_PRINT(("RTL8139: NWayAdvert read(w) val=0x%04x\n", ret)); |
|
2920 break; |
|
2921 case NWayLPAR: |
|
2922 ret = s->NWayLPAR; |
|
2923 DEBUG_PRINT(("RTL8139: NWayLPAR read(w) val=0x%04x\n", ret)); |
|
2924 break; |
|
2925 case NWayExpansion: |
|
2926 ret = s->NWayExpansion; |
|
2927 DEBUG_PRINT(("RTL8139: NWayExpansion read(w) val=0x%04x\n", ret)); |
|
2928 break; |
|
2929 |
|
2930 case CpCmd: |
|
2931 ret = rtl8139_CpCmd_read(s); |
|
2932 break; |
|
2933 |
|
2934 case IntrMitigate: |
|
2935 ret = rtl8139_IntrMitigate_read(s); |
|
2936 break; |
|
2937 |
|
2938 case TxSummary: |
|
2939 ret = rtl8139_TSAD_read(s); |
|
2940 break; |
|
2941 |
|
2942 case CSCR: |
|
2943 ret = rtl8139_CSCR_read(s); |
|
2944 break; |
|
2945 |
|
2946 default: |
|
2947 DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x via read(b)\n", addr)); |
|
2948 |
|
2949 ret = rtl8139_io_readb(opaque, addr); |
|
2950 ret |= rtl8139_io_readb(opaque, addr + 1) << 8; |
|
2951 |
|
2952 DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x val=0x%04x\n", addr, ret)); |
|
2953 break; |
|
2954 } |
|
2955 |
|
2956 return ret; |
|
2957 } |
|
2958 |
|
2959 static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr) |
|
2960 { |
|
2961 RTL8139State *s = opaque; |
|
2962 uint32_t ret; |
|
2963 |
|
2964 addr &= 0xfc; /* also mask low 2 bits */ |
|
2965 |
|
2966 switch (addr) |
|
2967 { |
|
2968 case RxMissed: |
|
2969 ret = s->RxMissed; |
|
2970 |
|
2971 DEBUG_PRINT(("RTL8139: RxMissed read val=0x%08x\n", ret)); |
|
2972 break; |
|
2973 |
|
2974 case TxConfig: |
|
2975 ret = rtl8139_TxConfig_read(s); |
|
2976 break; |
|
2977 |
|
2978 case RxConfig: |
|
2979 ret = rtl8139_RxConfig_read(s); |
|
2980 break; |
|
2981 |
|
2982 case TxStatus0 ... TxStatus0+4*4-1: |
|
2983 ret = rtl8139_TxStatus_read(s, addr-TxStatus0); |
|
2984 break; |
|
2985 |
|
2986 case TxAddr0 ... TxAddr0+4*4-1: |
|
2987 ret = rtl8139_TxAddr_read(s, addr-TxAddr0); |
|
2988 break; |
|
2989 |
|
2990 case RxBuf: |
|
2991 ret = rtl8139_RxBuf_read(s); |
|
2992 break; |
|
2993 |
|
2994 case RxRingAddrLO: |
|
2995 ret = s->RxRingAddrLO; |
|
2996 DEBUG_PRINT(("RTL8139: C+ RxRing low bits read val=0x%08x\n", ret)); |
|
2997 break; |
|
2998 |
|
2999 case RxRingAddrHI: |
|
3000 ret = s->RxRingAddrHI; |
|
3001 DEBUG_PRINT(("RTL8139: C+ RxRing high bits read val=0x%08x\n", ret)); |
|
3002 break; |
|
3003 |
|
3004 case Timer: |
|
3005 ret = s->TCTR; |
|
3006 DEBUG_PRINT(("RTL8139: TCTR Timer read val=0x%08x\n", ret)); |
|
3007 break; |
|
3008 |
|
3009 case FlashReg: |
|
3010 ret = s->TimerInt; |
|
3011 DEBUG_PRINT(("RTL8139: FlashReg TimerInt read val=0x%08x\n", ret)); |
|
3012 break; |
|
3013 |
|
3014 default: |
|
3015 DEBUG_PRINT(("RTL8139: ioport read(l) addr=0x%x via read(b)\n", addr)); |
|
3016 |
|
3017 ret = rtl8139_io_readb(opaque, addr); |
|
3018 ret |= rtl8139_io_readb(opaque, addr + 1) << 8; |
|
3019 ret |= rtl8139_io_readb(opaque, addr + 2) << 16; |
|
3020 ret |= rtl8139_io_readb(opaque, addr + 3) << 24; |
|
3021 |
|
3022 DEBUG_PRINT(("RTL8139: read(l) addr=0x%x val=%08x\n", addr, ret)); |
|
3023 break; |
|
3024 } |
|
3025 |
|
3026 return ret; |
|
3027 } |
|
3028 |
|
3029 /* */ |
|
3030 |
|
3031 static void rtl8139_ioport_writeb(void *opaque, uint32_t addr, uint32_t val) |
|
3032 { |
|
3033 rtl8139_io_writeb(opaque, addr & 0xFF, val); |
|
3034 } |
|
3035 |
|
3036 static void rtl8139_ioport_writew(void *opaque, uint32_t addr, uint32_t val) |
|
3037 { |
|
3038 rtl8139_io_writew(opaque, addr & 0xFF, val); |
|
3039 } |
|
3040 |
|
3041 static void rtl8139_ioport_writel(void *opaque, uint32_t addr, uint32_t val) |
|
3042 { |
|
3043 rtl8139_io_writel(opaque, addr & 0xFF, val); |
|
3044 } |
|
3045 |
|
3046 static uint32_t rtl8139_ioport_readb(void *opaque, uint32_t addr) |
|
3047 { |
|
3048 return rtl8139_io_readb(opaque, addr & 0xFF); |
|
3049 } |
|
3050 |
|
3051 static uint32_t rtl8139_ioport_readw(void *opaque, uint32_t addr) |
|
3052 { |
|
3053 return rtl8139_io_readw(opaque, addr & 0xFF); |
|
3054 } |
|
3055 |
|
3056 static uint32_t rtl8139_ioport_readl(void *opaque, uint32_t addr) |
|
3057 { |
|
3058 return rtl8139_io_readl(opaque, addr & 0xFF); |
|
3059 } |
|
3060 |
|
3061 /* */ |
|
3062 |
|
3063 static void rtl8139_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
3064 { |
|
3065 rtl8139_io_writeb(opaque, addr & 0xFF, val); |
|
3066 } |
|
3067 |
|
3068 static void rtl8139_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
3069 { |
|
3070 #ifdef TARGET_WORDS_BIGENDIAN |
|
3071 val = bswap16(val); |
|
3072 #endif |
|
3073 rtl8139_io_writew(opaque, addr & 0xFF, val); |
|
3074 } |
|
3075 |
|
3076 static void rtl8139_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
3077 { |
|
3078 #ifdef TARGET_WORDS_BIGENDIAN |
|
3079 val = bswap32(val); |
|
3080 #endif |
|
3081 rtl8139_io_writel(opaque, addr & 0xFF, val); |
|
3082 } |
|
3083 |
|
3084 static uint32_t rtl8139_mmio_readb(void *opaque, target_phys_addr_t addr) |
|
3085 { |
|
3086 return rtl8139_io_readb(opaque, addr & 0xFF); |
|
3087 } |
|
3088 |
|
3089 static uint32_t rtl8139_mmio_readw(void *opaque, target_phys_addr_t addr) |
|
3090 { |
|
3091 uint32_t val = rtl8139_io_readw(opaque, addr & 0xFF); |
|
3092 #ifdef TARGET_WORDS_BIGENDIAN |
|
3093 val = bswap16(val); |
|
3094 #endif |
|
3095 return val; |
|
3096 } |
|
3097 |
|
3098 static uint32_t rtl8139_mmio_readl(void *opaque, target_phys_addr_t addr) |
|
3099 { |
|
3100 uint32_t val = rtl8139_io_readl(opaque, addr & 0xFF); |
|
3101 #ifdef TARGET_WORDS_BIGENDIAN |
|
3102 val = bswap32(val); |
|
3103 #endif |
|
3104 return val; |
|
3105 } |
|
3106 |
|
3107 /* */ |
|
3108 |
|
3109 static void rtl8139_save(QEMUFile* f,void* opaque) |
|
3110 { |
|
3111 RTL8139State* s=(RTL8139State*)opaque; |
|
3112 unsigned int i; |
|
3113 |
|
3114 pci_device_save(s->pci_dev, f); |
|
3115 |
|
3116 qemu_put_buffer(f, s->phys, 6); |
|
3117 qemu_put_buffer(f, s->mult, 8); |
|
3118 |
|
3119 for (i=0; i<4; ++i) |
|
3120 { |
|
3121 qemu_put_be32s(f, &s->TxStatus[i]); /* TxStatus0 */ |
|
3122 } |
|
3123 for (i=0; i<4; ++i) |
|
3124 { |
|
3125 qemu_put_be32s(f, &s->TxAddr[i]); /* TxAddr0 */ |
|
3126 } |
|
3127 |
|
3128 qemu_put_be32s(f, &s->RxBuf); /* Receive buffer */ |
|
3129 qemu_put_be32s(f, &s->RxBufferSize);/* internal variable, receive ring buffer size in C mode */ |
|
3130 qemu_put_be32s(f, &s->RxBufPtr); |
|
3131 qemu_put_be32s(f, &s->RxBufAddr); |
|
3132 |
|
3133 qemu_put_be16s(f, &s->IntrStatus); |
|
3134 qemu_put_be16s(f, &s->IntrMask); |
|
3135 |
|
3136 qemu_put_be32s(f, &s->TxConfig); |
|
3137 qemu_put_be32s(f, &s->RxConfig); |
|
3138 qemu_put_be32s(f, &s->RxMissed); |
|
3139 qemu_put_be16s(f, &s->CSCR); |
|
3140 |
|
3141 qemu_put_8s(f, &s->Cfg9346); |
|
3142 qemu_put_8s(f, &s->Config0); |
|
3143 qemu_put_8s(f, &s->Config1); |
|
3144 qemu_put_8s(f, &s->Config3); |
|
3145 qemu_put_8s(f, &s->Config4); |
|
3146 qemu_put_8s(f, &s->Config5); |
|
3147 |
|
3148 qemu_put_8s(f, &s->clock_enabled); |
|
3149 qemu_put_8s(f, &s->bChipCmdState); |
|
3150 |
|
3151 qemu_put_be16s(f, &s->MultiIntr); |
|
3152 |
|
3153 qemu_put_be16s(f, &s->BasicModeCtrl); |
|
3154 qemu_put_be16s(f, &s->BasicModeStatus); |
|
3155 qemu_put_be16s(f, &s->NWayAdvert); |
|
3156 qemu_put_be16s(f, &s->NWayLPAR); |
|
3157 qemu_put_be16s(f, &s->NWayExpansion); |
|
3158 |
|
3159 qemu_put_be16s(f, &s->CpCmd); |
|
3160 qemu_put_8s(f, &s->TxThresh); |
|
3161 |
|
3162 i = 0; |
|
3163 qemu_put_be32s(f, &i); /* unused. */ |
|
3164 qemu_put_buffer(f, s->macaddr, 6); |
|
3165 qemu_put_be32(f, s->rtl8139_mmio_io_addr); |
|
3166 |
|
3167 qemu_put_be32s(f, &s->currTxDesc); |
|
3168 qemu_put_be32s(f, &s->currCPlusRxDesc); |
|
3169 qemu_put_be32s(f, &s->currCPlusTxDesc); |
|
3170 qemu_put_be32s(f, &s->RxRingAddrLO); |
|
3171 qemu_put_be32s(f, &s->RxRingAddrHI); |
|
3172 |
|
3173 for (i=0; i<EEPROM_9346_SIZE; ++i) |
|
3174 { |
|
3175 qemu_put_be16s(f, &s->eeprom.contents[i]); |
|
3176 } |
|
3177 qemu_put_be32(f, s->eeprom.mode); |
|
3178 qemu_put_be32s(f, &s->eeprom.tick); |
|
3179 qemu_put_8s(f, &s->eeprom.address); |
|
3180 qemu_put_be16s(f, &s->eeprom.input); |
|
3181 qemu_put_be16s(f, &s->eeprom.output); |
|
3182 |
|
3183 qemu_put_8s(f, &s->eeprom.eecs); |
|
3184 qemu_put_8s(f, &s->eeprom.eesk); |
|
3185 qemu_put_8s(f, &s->eeprom.eedi); |
|
3186 qemu_put_8s(f, &s->eeprom.eedo); |
|
3187 |
|
3188 qemu_put_be32s(f, &s->TCTR); |
|
3189 qemu_put_be32s(f, &s->TimerInt); |
|
3190 qemu_put_be64(f, s->TCTR_base); |
|
3191 |
|
3192 RTL8139TallyCounters_save(f, &s->tally_counters); |
|
3193 } |
|
3194 |
|
3195 static int rtl8139_load(QEMUFile* f,void* opaque,int version_id) |
|
3196 { |
|
3197 RTL8139State* s=(RTL8139State*)opaque; |
|
3198 unsigned int i; |
|
3199 int ret; |
|
3200 |
|
3201 /* just 2 versions for now */ |
|
3202 if (version_id > 3) |
|
3203 return -EINVAL; |
|
3204 |
|
3205 if (version_id >= 3) { |
|
3206 ret = pci_device_load(s->pci_dev, f); |
|
3207 if (ret < 0) |
|
3208 return ret; |
|
3209 } |
|
3210 |
|
3211 /* saved since version 1 */ |
|
3212 qemu_get_buffer(f, s->phys, 6); |
|
3213 qemu_get_buffer(f, s->mult, 8); |
|
3214 |
|
3215 for (i=0; i<4; ++i) |
|
3216 { |
|
3217 qemu_get_be32s(f, &s->TxStatus[i]); /* TxStatus0 */ |
|
3218 } |
|
3219 for (i=0; i<4; ++i) |
|
3220 { |
|
3221 qemu_get_be32s(f, &s->TxAddr[i]); /* TxAddr0 */ |
|
3222 } |
|
3223 |
|
3224 qemu_get_be32s(f, &s->RxBuf); /* Receive buffer */ |
|
3225 qemu_get_be32s(f, &s->RxBufferSize);/* internal variable, receive ring buffer size in C mode */ |
|
3226 qemu_get_be32s(f, &s->RxBufPtr); |
|
3227 qemu_get_be32s(f, &s->RxBufAddr); |
|
3228 |
|
3229 qemu_get_be16s(f, &s->IntrStatus); |
|
3230 qemu_get_be16s(f, &s->IntrMask); |
|
3231 |
|
3232 qemu_get_be32s(f, &s->TxConfig); |
|
3233 qemu_get_be32s(f, &s->RxConfig); |
|
3234 qemu_get_be32s(f, &s->RxMissed); |
|
3235 qemu_get_be16s(f, &s->CSCR); |
|
3236 |
|
3237 qemu_get_8s(f, &s->Cfg9346); |
|
3238 qemu_get_8s(f, &s->Config0); |
|
3239 qemu_get_8s(f, &s->Config1); |
|
3240 qemu_get_8s(f, &s->Config3); |
|
3241 qemu_get_8s(f, &s->Config4); |
|
3242 qemu_get_8s(f, &s->Config5); |
|
3243 |
|
3244 qemu_get_8s(f, &s->clock_enabled); |
|
3245 qemu_get_8s(f, &s->bChipCmdState); |
|
3246 |
|
3247 qemu_get_be16s(f, &s->MultiIntr); |
|
3248 |
|
3249 qemu_get_be16s(f, &s->BasicModeCtrl); |
|
3250 qemu_get_be16s(f, &s->BasicModeStatus); |
|
3251 qemu_get_be16s(f, &s->NWayAdvert); |
|
3252 qemu_get_be16s(f, &s->NWayLPAR); |
|
3253 qemu_get_be16s(f, &s->NWayExpansion); |
|
3254 |
|
3255 qemu_get_be16s(f, &s->CpCmd); |
|
3256 qemu_get_8s(f, &s->TxThresh); |
|
3257 |
|
3258 qemu_get_be32s(f, &i); /* unused. */ |
|
3259 qemu_get_buffer(f, s->macaddr, 6); |
|
3260 s->rtl8139_mmio_io_addr=qemu_get_be32(f); |
|
3261 |
|
3262 qemu_get_be32s(f, &s->currTxDesc); |
|
3263 qemu_get_be32s(f, &s->currCPlusRxDesc); |
|
3264 qemu_get_be32s(f, &s->currCPlusTxDesc); |
|
3265 qemu_get_be32s(f, &s->RxRingAddrLO); |
|
3266 qemu_get_be32s(f, &s->RxRingAddrHI); |
|
3267 |
|
3268 for (i=0; i<EEPROM_9346_SIZE; ++i) |
|
3269 { |
|
3270 qemu_get_be16s(f, &s->eeprom.contents[i]); |
|
3271 } |
|
3272 s->eeprom.mode=qemu_get_be32(f); |
|
3273 qemu_get_be32s(f, &s->eeprom.tick); |
|
3274 qemu_get_8s(f, &s->eeprom.address); |
|
3275 qemu_get_be16s(f, &s->eeprom.input); |
|
3276 qemu_get_be16s(f, &s->eeprom.output); |
|
3277 |
|
3278 qemu_get_8s(f, &s->eeprom.eecs); |
|
3279 qemu_get_8s(f, &s->eeprom.eesk); |
|
3280 qemu_get_8s(f, &s->eeprom.eedi); |
|
3281 qemu_get_8s(f, &s->eeprom.eedo); |
|
3282 |
|
3283 /* saved since version 2 */ |
|
3284 if (version_id >= 2) |
|
3285 { |
|
3286 qemu_get_be32s(f, &s->TCTR); |
|
3287 qemu_get_be32s(f, &s->TimerInt); |
|
3288 s->TCTR_base=qemu_get_be64(f); |
|
3289 |
|
3290 RTL8139TallyCounters_load(f, &s->tally_counters); |
|
3291 } |
|
3292 else |
|
3293 { |
|
3294 /* not saved, use default */ |
|
3295 s->TCTR = 0; |
|
3296 s->TimerInt = 0; |
|
3297 s->TCTR_base = 0; |
|
3298 |
|
3299 RTL8139TallyCounters_clear(&s->tally_counters); |
|
3300 } |
|
3301 |
|
3302 return 0; |
|
3303 } |
|
3304 |
|
3305 /***********************************************************/ |
|
3306 /* PCI RTL8139 definitions */ |
|
3307 |
|
3308 typedef struct PCIRTL8139State { |
|
3309 PCIDevice dev; |
|
3310 RTL8139State rtl8139; |
|
3311 } PCIRTL8139State; |
|
3312 |
|
3313 static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num, |
|
3314 uint32_t addr, uint32_t size, int type) |
|
3315 { |
|
3316 PCIRTL8139State *d = (PCIRTL8139State *)pci_dev; |
|
3317 RTL8139State *s = &d->rtl8139; |
|
3318 |
|
3319 cpu_register_physical_memory(addr + 0, 0x100, s->rtl8139_mmio_io_addr); |
|
3320 } |
|
3321 |
|
3322 static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num, |
|
3323 uint32_t addr, uint32_t size, int type) |
|
3324 { |
|
3325 PCIRTL8139State *d = (PCIRTL8139State *)pci_dev; |
|
3326 RTL8139State *s = &d->rtl8139; |
|
3327 |
|
3328 register_ioport_write(addr, 0x100, 1, rtl8139_ioport_writeb, s); |
|
3329 register_ioport_read( addr, 0x100, 1, rtl8139_ioport_readb, s); |
|
3330 |
|
3331 register_ioport_write(addr, 0x100, 2, rtl8139_ioport_writew, s); |
|
3332 register_ioport_read( addr, 0x100, 2, rtl8139_ioport_readw, s); |
|
3333 |
|
3334 register_ioport_write(addr, 0x100, 4, rtl8139_ioport_writel, s); |
|
3335 register_ioport_read( addr, 0x100, 4, rtl8139_ioport_readl, s); |
|
3336 } |
|
3337 |
|
3338 static CPUReadMemoryFunc *rtl8139_mmio_read[3] = { |
|
3339 rtl8139_mmio_readb, |
|
3340 rtl8139_mmio_readw, |
|
3341 rtl8139_mmio_readl, |
|
3342 }; |
|
3343 |
|
3344 static CPUWriteMemoryFunc *rtl8139_mmio_write[3] = { |
|
3345 rtl8139_mmio_writeb, |
|
3346 rtl8139_mmio_writew, |
|
3347 rtl8139_mmio_writel, |
|
3348 }; |
|
3349 |
|
3350 static inline int64_t rtl8139_get_next_tctr_time(RTL8139State *s, int64_t current_time) |
|
3351 { |
|
3352 int64_t next_time = current_time + |
|
3353 muldiv64(1, ticks_per_sec, PCI_FREQUENCY); |
|
3354 if (next_time <= current_time) |
|
3355 next_time = current_time + 1; |
|
3356 return next_time; |
|
3357 } |
|
3358 |
|
3359 #ifdef RTL8139_ONBOARD_TIMER |
|
3360 static void rtl8139_timer(void *opaque) |
|
3361 { |
|
3362 RTL8139State *s = opaque; |
|
3363 |
|
3364 int is_timeout = 0; |
|
3365 |
|
3366 int64_t curr_time; |
|
3367 uint32_t curr_tick; |
|
3368 |
|
3369 if (!s->clock_enabled) |
|
3370 { |
|
3371 DEBUG_PRINT(("RTL8139: >>> timer: clock is not running\n")); |
|
3372 return; |
|
3373 } |
|
3374 |
|
3375 curr_time = qemu_get_clock(vm_clock); |
|
3376 |
|
3377 curr_tick = muldiv64(curr_time - s->TCTR_base, PCI_FREQUENCY, ticks_per_sec); |
|
3378 |
|
3379 if (s->TimerInt && curr_tick >= s->TimerInt) |
|
3380 { |
|
3381 if (s->TCTR < s->TimerInt || curr_tick < s->TCTR) |
|
3382 { |
|
3383 is_timeout = 1; |
|
3384 } |
|
3385 } |
|
3386 |
|
3387 s->TCTR = curr_tick; |
|
3388 |
|
3389 // DEBUG_PRINT(("RTL8139: >>> timer: tick=%08u\n", s->TCTR)); |
|
3390 |
|
3391 if (is_timeout) |
|
3392 { |
|
3393 DEBUG_PRINT(("RTL8139: >>> timer: timeout tick=%08u\n", s->TCTR)); |
|
3394 s->IntrStatus |= PCSTimeout; |
|
3395 rtl8139_update_irq(s); |
|
3396 } |
|
3397 |
|
3398 qemu_mod_timer(s->timer, |
|
3399 rtl8139_get_next_tctr_time(s,curr_time)); |
|
3400 } |
|
3401 #endif /* RTL8139_ONBOARD_TIMER */ |
|
3402 |
|
3403 void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn) |
|
3404 { |
|
3405 PCIRTL8139State *d; |
|
3406 RTL8139State *s; |
|
3407 uint8_t *pci_conf; |
|
3408 |
|
3409 d = (PCIRTL8139State *)pci_register_device(bus, |
|
3410 "RTL8139", sizeof(PCIRTL8139State), |
|
3411 devfn, |
|
3412 NULL, NULL); |
|
3413 pci_conf = d->dev.config; |
|
3414 pci_conf[0x00] = 0xec; /* Realtek 8139 */ |
|
3415 pci_conf[0x01] = 0x10; |
|
3416 pci_conf[0x02] = 0x39; |
|
3417 pci_conf[0x03] = 0x81; |
|
3418 pci_conf[0x04] = 0x05; /* command = I/O space, Bus Master */ |
|
3419 pci_conf[0x08] = RTL8139_PCI_REVID; /* PCI revision ID; >=0x20 is for 8139C+ */ |
|
3420 pci_conf[0x0a] = 0x00; /* ethernet network controller */ |
|
3421 pci_conf[0x0b] = 0x02; |
|
3422 pci_conf[0x0e] = 0x00; /* header_type */ |
|
3423 pci_conf[0x3d] = 1; /* interrupt pin 0 */ |
|
3424 pci_conf[0x34] = 0xdc; |
|
3425 |
|
3426 s = &d->rtl8139; |
|
3427 |
|
3428 /* I/O handler for memory-mapped I/O */ |
|
3429 s->rtl8139_mmio_io_addr = |
|
3430 cpu_register_io_memory(0, rtl8139_mmio_read, rtl8139_mmio_write, s); |
|
3431 |
|
3432 pci_register_io_region(&d->dev, 0, 0x100, |
|
3433 PCI_ADDRESS_SPACE_IO, rtl8139_ioport_map); |
|
3434 |
|
3435 pci_register_io_region(&d->dev, 1, 0x100, |
|
3436 PCI_ADDRESS_SPACE_MEM, rtl8139_mmio_map); |
|
3437 |
|
3438 s->pci_dev = (PCIDevice *)d; |
|
3439 memcpy(s->macaddr, nd->macaddr, 6); |
|
3440 rtl8139_reset(s); |
|
3441 s->vc = qemu_new_vlan_client(nd->vlan, rtl8139_receive, |
|
3442 rtl8139_can_receive, s); |
|
3443 |
|
3444 snprintf(s->vc->info_str, sizeof(s->vc->info_str), |
|
3445 "rtl8139 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x", |
|
3446 s->macaddr[0], |
|
3447 s->macaddr[1], |
|
3448 s->macaddr[2], |
|
3449 s->macaddr[3], |
|
3450 s->macaddr[4], |
|
3451 s->macaddr[5]); |
|
3452 |
|
3453 s->cplus_txbuffer = NULL; |
|
3454 s->cplus_txbuffer_len = 0; |
|
3455 s->cplus_txbuffer_offset = 0; |
|
3456 |
|
3457 register_savevm("rtl8139", -1, 3, rtl8139_save, rtl8139_load, s); |
|
3458 |
|
3459 #ifdef RTL8139_ONBOARD_TIMER |
|
3460 s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s); |
|
3461 |
|
3462 qemu_mod_timer(s->timer, |
|
3463 rtl8139_get_next_tctr_time(s,qemu_get_clock(vm_clock))); |
|
3464 #endif /* RTL8139_ONBOARD_TIMER */ |
|
3465 } |