|
1 /* |
|
2 * QEMU i8255x (PRO100) emulation |
|
3 * |
|
4 * Copyright (c) 2006-2007 Stefan Weil |
|
5 * |
|
6 * Portions of the code are copies from grub / etherboot eepro100.c |
|
7 * and linux e100.c. |
|
8 * |
|
9 * This program is free software; you can redistribute it and/or modify |
|
10 * it under the terms of the GNU General Public License as published by |
|
11 * the Free Software Foundation; either version 2 of the License, or |
|
12 * (at your option) any later version. |
|
13 * |
|
14 * This program is distributed in the hope that it will be useful, |
|
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 * GNU General Public License for more details. |
|
18 * |
|
19 * You should have received a copy of the GNU General Public License |
|
20 * along with this program; if not, write to the Free Software |
|
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
22 * |
|
23 * Tested features (i82559): |
|
24 * PXE boot (i386) no valid link |
|
25 * Linux networking (i386) ok |
|
26 * |
|
27 * Untested: |
|
28 * non-i386 platforms |
|
29 * Windows networking |
|
30 * |
|
31 * References: |
|
32 * |
|
33 * Intel 8255x 10/100 Mbps Ethernet Controller Family |
|
34 * Open Source Software Developer Manual |
|
35 */ |
|
36 |
|
37 #if defined(TARGET_I386) |
|
38 # warning "PXE boot still not working!" |
|
39 #endif |
|
40 |
|
41 #include <assert.h> |
|
42 #include <stddef.h> /* offsetof */ |
|
43 #include "hw.h" |
|
44 #include "pci.h" |
|
45 #include "net.h" |
|
46 #include "eeprom93xx.h" |
|
47 |
|
48 /* Common declarations for all PCI devices. */ |
|
49 |
|
50 #define PCI_VENDOR_ID 0x00 /* 16 bits */ |
|
51 #define PCI_DEVICE_ID 0x02 /* 16 bits */ |
|
52 #define PCI_COMMAND 0x04 /* 16 bits */ |
|
53 #define PCI_STATUS 0x06 /* 16 bits */ |
|
54 |
|
55 #define PCI_REVISION_ID 0x08 /* 8 bits */ |
|
56 #define PCI_CLASS_CODE 0x0b /* 8 bits */ |
|
57 #define PCI_SUBCLASS_CODE 0x0a /* 8 bits */ |
|
58 #define PCI_HEADER_TYPE 0x0e /* 8 bits */ |
|
59 |
|
60 #define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ |
|
61 #define PCI_BASE_ADDRESS_1 0x14 /* 32 bits */ |
|
62 #define PCI_BASE_ADDRESS_2 0x18 /* 32 bits */ |
|
63 #define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ |
|
64 #define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ |
|
65 #define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ |
|
66 |
|
67 #define PCI_CONFIG_8(offset, value) \ |
|
68 (pci_conf[offset] = (value)) |
|
69 #define PCI_CONFIG_16(offset, value) \ |
|
70 (*(uint16_t *)&pci_conf[offset] = cpu_to_le16(value)) |
|
71 #define PCI_CONFIG_32(offset, value) \ |
|
72 (*(uint32_t *)&pci_conf[offset] = cpu_to_le32(value)) |
|
73 |
|
74 #define KiB 1024 |
|
75 |
|
76 /* debug EEPRO100 card */ |
|
77 //~ #define DEBUG_EEPRO100 |
|
78 |
|
79 #ifdef DEBUG_EEPRO100 |
|
80 #define logout(fmt, args...) fprintf(stderr, "EE100\t%-24s" fmt, __func__, ##args) |
|
81 #else |
|
82 #define logout(fmt, args...) ((void)0) |
|
83 #endif |
|
84 |
|
85 /* Set flags to 0 to disable debug output. */ |
|
86 #define MDI 0 |
|
87 |
|
88 #define TRACE(flag, command) ((flag) ? (command) : (void)0) |
|
89 |
|
90 #define missing(text) assert(!"feature is missing in this emulation: " text) |
|
91 |
|
92 #define MAX_ETH_FRAME_SIZE 1514 |
|
93 |
|
94 /* This driver supports several different devices which are declared here. */ |
|
95 #define i82551 0x82551 |
|
96 #define i82557B 0x82557b |
|
97 #define i82557C 0x82557c |
|
98 #define i82558B 0x82558b |
|
99 #define i82559C 0x82559c |
|
100 #define i82559ER 0x82559e |
|
101 #define i82562 0x82562 |
|
102 |
|
103 #define EEPROM_SIZE 64 |
|
104 |
|
105 #define PCI_MEM_SIZE (4 * KiB) |
|
106 #define PCI_IO_SIZE 64 |
|
107 #define PCI_FLASH_SIZE (128 * KiB) |
|
108 |
|
109 #define BIT(n) (1 << (n)) |
|
110 #define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m) |
|
111 |
|
112 /* The SCB accepts the following controls for the Tx and Rx units: */ |
|
113 #define CU_NOP 0x0000 /* No operation. */ |
|
114 #define CU_START 0x0010 /* CU start. */ |
|
115 #define CU_RESUME 0x0020 /* CU resume. */ |
|
116 #define CU_STATSADDR 0x0040 /* Load dump counters address. */ |
|
117 #define CU_SHOWSTATS 0x0050 /* Dump statistical counters. */ |
|
118 #define CU_CMD_BASE 0x0060 /* Load CU base address. */ |
|
119 #define CU_DUMPSTATS 0x0070 /* Dump and reset statistical counters. */ |
|
120 #define CU_SRESUME 0x00a0 /* CU static resume. */ |
|
121 |
|
122 #define RU_NOP 0x0000 |
|
123 #define RX_START 0x0001 |
|
124 #define RX_RESUME 0x0002 |
|
125 #define RX_ABORT 0x0004 |
|
126 #define RX_ADDR_LOAD 0x0006 |
|
127 #define RX_RESUMENR 0x0007 |
|
128 #define INT_MASK 0x0100 |
|
129 #define DRVR_INT 0x0200 /* Driver generated interrupt. */ |
|
130 |
|
131 typedef unsigned char bool; |
|
132 |
|
133 /* Offsets to the various registers. |
|
134 All accesses need not be longword aligned. */ |
|
135 enum speedo_offsets { |
|
136 SCBStatus = 0, |
|
137 SCBAck = 1, |
|
138 SCBCmd = 2, /* Rx/Command Unit command and status. */ |
|
139 SCBIntmask = 3, |
|
140 SCBPointer = 4, /* General purpose pointer. */ |
|
141 SCBPort = 8, /* Misc. commands and operands. */ |
|
142 SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */ |
|
143 SCBCtrlMDI = 16, /* MDI interface control. */ |
|
144 SCBEarlyRx = 20, /* Early receive byte count. */ |
|
145 SCBFlow = 24, |
|
146 }; |
|
147 |
|
148 /* A speedo3 transmit buffer descriptor with two buffers... */ |
|
149 typedef struct { |
|
150 uint16_t status; |
|
151 uint16_t command; |
|
152 uint32_t link; /* void * */ |
|
153 uint32_t tx_desc_addr; /* transmit buffer decsriptor array address. */ |
|
154 uint16_t tcb_bytes; /* transmit command block byte count (in lower 14 bits */ |
|
155 uint8_t tx_threshold; /* transmit threshold */ |
|
156 uint8_t tbd_count; /* TBD number */ |
|
157 //~ /* This constitutes two "TBD" entries: hdr and data */ |
|
158 //~ uint32_t tx_buf_addr0; /* void *, header of frame to be transmitted. */ |
|
159 //~ int32_t tx_buf_size0; /* Length of Tx hdr. */ |
|
160 //~ uint32_t tx_buf_addr1; /* void *, data to be transmitted. */ |
|
161 //~ int32_t tx_buf_size1; /* Length of Tx data. */ |
|
162 } eepro100_tx_t; |
|
163 |
|
164 /* Receive frame descriptor. */ |
|
165 typedef struct { |
|
166 int16_t status; |
|
167 uint16_t command; |
|
168 uint32_t link; /* struct RxFD * */ |
|
169 uint32_t rx_buf_addr; /* void * */ |
|
170 uint16_t count; |
|
171 uint16_t size; |
|
172 char packet[MAX_ETH_FRAME_SIZE + 4]; |
|
173 } eepro100_rx_t; |
|
174 |
|
175 typedef struct { |
|
176 uint32_t tx_good_frames, tx_max_collisions, tx_late_collisions, |
|
177 tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, |
|
178 tx_multiple_collisions, tx_total_collisions; |
|
179 uint32_t rx_good_frames, rx_crc_errors, rx_alignment_errors, |
|
180 rx_resource_errors, rx_overrun_errors, rx_cdt_errors, |
|
181 rx_short_frame_errors; |
|
182 uint32_t fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; |
|
183 uint16_t xmt_tco_frames, rcv_tco_frames; |
|
184 uint32_t complete; |
|
185 } eepro100_stats_t; |
|
186 |
|
187 typedef enum { |
|
188 cu_idle = 0, |
|
189 cu_suspended = 1, |
|
190 cu_active = 2, |
|
191 cu_lpq_active = 2, |
|
192 cu_hqp_active = 3 |
|
193 } cu_state_t; |
|
194 |
|
195 typedef enum { |
|
196 ru_idle = 0, |
|
197 ru_suspended = 1, |
|
198 ru_no_resources = 2, |
|
199 ru_ready = 4 |
|
200 } ru_state_t; |
|
201 |
|
202 #if defined(__BIG_ENDIAN_BITFIELD) |
|
203 #define X(a,b) b,a |
|
204 #else |
|
205 #define X(a,b) a,b |
|
206 #endif |
|
207 |
|
208 typedef struct { |
|
209 #if 1 |
|
210 uint8_t cmd; |
|
211 uint32_t start; |
|
212 uint32_t stop; |
|
213 uint8_t boundary; |
|
214 uint8_t tsr; |
|
215 uint8_t tpsr; |
|
216 uint16_t tcnt; |
|
217 uint16_t rcnt; |
|
218 uint32_t rsar; |
|
219 uint8_t rsr; |
|
220 uint8_t rxcr; |
|
221 uint8_t isr; |
|
222 uint8_t dcfg; |
|
223 uint8_t imr; |
|
224 uint8_t phys[6]; /* mac address */ |
|
225 uint8_t curpag; |
|
226 uint8_t mult[8]; /* multicast mask array */ |
|
227 int mmio_index; |
|
228 PCIDevice *pci_dev; |
|
229 VLANClientState *vc; |
|
230 #endif |
|
231 uint8_t scb_stat; /* SCB stat/ack byte */ |
|
232 uint8_t int_stat; /* PCI interrupt status */ |
|
233 uint32_t region[3]; /* PCI region addresses */ |
|
234 uint8_t macaddr[6]; |
|
235 uint32_t statcounter[19]; |
|
236 uint16_t mdimem[32]; |
|
237 eeprom_t *eeprom; |
|
238 uint32_t device; /* device variant */ |
|
239 uint32_t pointer; |
|
240 /* (cu_base + cu_offset) address the next command block in the command block list. */ |
|
241 uint32_t cu_base; /* CU base address */ |
|
242 uint32_t cu_offset; /* CU address offset */ |
|
243 /* (ru_base + ru_offset) address the RFD in the Receive Frame Area. */ |
|
244 uint32_t ru_base; /* RU base address */ |
|
245 uint32_t ru_offset; /* RU address offset */ |
|
246 uint32_t statsaddr; /* pointer to eepro100_stats_t */ |
|
247 eepro100_stats_t statistics; /* statistical counters */ |
|
248 #if 0 |
|
249 uint16_t status; |
|
250 #endif |
|
251 |
|
252 /* Configuration bytes. */ |
|
253 uint8_t configuration[22]; |
|
254 |
|
255 /* Data in mem is always in the byte order of the controller (le). */ |
|
256 uint8_t mem[PCI_MEM_SIZE]; |
|
257 } EEPRO100State; |
|
258 |
|
259 /* Default values for MDI (PHY) registers */ |
|
260 static const uint16_t eepro100_mdi_default[] = { |
|
261 /* MDI Registers 0 - 6, 7 */ |
|
262 0x3000, 0x780d, 0x02a8, 0x0154, 0x05e1, 0x0000, 0x0000, 0x0000, |
|
263 /* MDI Registers 8 - 15 */ |
|
264 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
265 /* MDI Registers 16 - 31 */ |
|
266 0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
267 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
268 }; |
|
269 |
|
270 /* Readonly mask for MDI (PHY) registers */ |
|
271 static const uint16_t eepro100_mdi_mask[] = { |
|
272 0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000, |
|
273 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
274 0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, |
|
275 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
276 }; |
|
277 |
|
278 #define POLYNOMIAL 0x04c11db6 |
|
279 |
|
280 /* From FreeBSD */ |
|
281 /* XXX: optimize */ |
|
282 static int compute_mcast_idx(const uint8_t * ep) |
|
283 { |
|
284 uint32_t crc; |
|
285 int carry, i, j; |
|
286 uint8_t b; |
|
287 |
|
288 crc = 0xffffffff; |
|
289 for (i = 0; i < 6; i++) { |
|
290 b = *ep++; |
|
291 for (j = 0; j < 8; j++) { |
|
292 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); |
|
293 crc <<= 1; |
|
294 b >>= 1; |
|
295 if (carry) |
|
296 crc = ((crc ^ POLYNOMIAL) | carry); |
|
297 } |
|
298 } |
|
299 return (crc >> 26); |
|
300 } |
|
301 |
|
302 #if defined(DEBUG_EEPRO100) |
|
303 static const char *nic_dump(const uint8_t * buf, unsigned size) |
|
304 { |
|
305 static char dump[3 * 16 + 1]; |
|
306 char *p = &dump[0]; |
|
307 if (size > 16) |
|
308 size = 16; |
|
309 while (size-- > 0) { |
|
310 p += sprintf(p, " %02x", *buf++); |
|
311 } |
|
312 return dump; |
|
313 } |
|
314 #endif /* DEBUG_EEPRO100 */ |
|
315 |
|
316 enum scb_stat_ack { |
|
317 stat_ack_not_ours = 0x00, |
|
318 stat_ack_sw_gen = 0x04, |
|
319 stat_ack_rnr = 0x10, |
|
320 stat_ack_cu_idle = 0x20, |
|
321 stat_ack_frame_rx = 0x40, |
|
322 stat_ack_cu_cmd_done = 0x80, |
|
323 stat_ack_not_present = 0xFF, |
|
324 stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), |
|
325 stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), |
|
326 }; |
|
327 |
|
328 static void disable_interrupt(EEPRO100State * s) |
|
329 { |
|
330 if (s->int_stat) { |
|
331 logout("interrupt disabled\n"); |
|
332 qemu_irq_lower(s->pci_dev->irq[0]); |
|
333 s->int_stat = 0; |
|
334 } |
|
335 } |
|
336 |
|
337 static void enable_interrupt(EEPRO100State * s) |
|
338 { |
|
339 if (!s->int_stat) { |
|
340 logout("interrupt enabled\n"); |
|
341 qemu_irq_raise(s->pci_dev->irq[0]); |
|
342 s->int_stat = 1; |
|
343 } |
|
344 } |
|
345 |
|
346 static void eepro100_acknowledge(EEPRO100State * s) |
|
347 { |
|
348 s->scb_stat &= ~s->mem[SCBAck]; |
|
349 s->mem[SCBAck] = s->scb_stat; |
|
350 if (s->scb_stat == 0) { |
|
351 disable_interrupt(s); |
|
352 } |
|
353 } |
|
354 |
|
355 static void eepro100_interrupt(EEPRO100State * s, uint8_t stat) |
|
356 { |
|
357 uint8_t mask = ~s->mem[SCBIntmask]; |
|
358 s->mem[SCBAck] |= stat; |
|
359 stat = s->scb_stat = s->mem[SCBAck]; |
|
360 stat &= (mask | 0x0f); |
|
361 //~ stat &= (~s->mem[SCBIntmask] | 0x0xf); |
|
362 if (stat && (mask & 0x01)) { |
|
363 /* SCB mask and SCB Bit M do not disable interrupt. */ |
|
364 enable_interrupt(s); |
|
365 } else if (s->int_stat) { |
|
366 disable_interrupt(s); |
|
367 } |
|
368 } |
|
369 |
|
370 static void eepro100_cx_interrupt(EEPRO100State * s) |
|
371 { |
|
372 /* CU completed action command. */ |
|
373 /* Transmit not ok (82557 only, not in emulation). */ |
|
374 eepro100_interrupt(s, 0x80); |
|
375 } |
|
376 |
|
377 static void eepro100_cna_interrupt(EEPRO100State * s) |
|
378 { |
|
379 /* CU left the active state. */ |
|
380 eepro100_interrupt(s, 0x20); |
|
381 } |
|
382 |
|
383 static void eepro100_fr_interrupt(EEPRO100State * s) |
|
384 { |
|
385 /* RU received a complete frame. */ |
|
386 eepro100_interrupt(s, 0x40); |
|
387 } |
|
388 |
|
389 #if 0 |
|
390 static void eepro100_rnr_interrupt(EEPRO100State * s) |
|
391 { |
|
392 /* RU is not ready. */ |
|
393 eepro100_interrupt(s, 0x10); |
|
394 } |
|
395 #endif |
|
396 |
|
397 static void eepro100_mdi_interrupt(EEPRO100State * s) |
|
398 { |
|
399 /* MDI completed read or write cycle. */ |
|
400 eepro100_interrupt(s, 0x08); |
|
401 } |
|
402 |
|
403 static void eepro100_swi_interrupt(EEPRO100State * s) |
|
404 { |
|
405 /* Software has requested an interrupt. */ |
|
406 eepro100_interrupt(s, 0x04); |
|
407 } |
|
408 |
|
409 #if 0 |
|
410 static void eepro100_fcp_interrupt(EEPRO100State * s) |
|
411 { |
|
412 /* Flow control pause interrupt (82558 and later). */ |
|
413 eepro100_interrupt(s, 0x01); |
|
414 } |
|
415 #endif |
|
416 |
|
417 static void pci_reset(EEPRO100State * s) |
|
418 { |
|
419 uint32_t device = s->device; |
|
420 uint8_t *pci_conf = s->pci_dev->config; |
|
421 |
|
422 logout("%p\n", s); |
|
423 |
|
424 /* PCI Vendor ID */ |
|
425 PCI_CONFIG_16(PCI_VENDOR_ID, 0x8086); |
|
426 /* PCI Device ID */ |
|
427 PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209); |
|
428 /* PCI Command */ |
|
429 PCI_CONFIG_16(PCI_COMMAND, 0x0000); |
|
430 /* PCI Status */ |
|
431 PCI_CONFIG_16(PCI_STATUS, 0x2800); |
|
432 /* PCI Revision ID */ |
|
433 PCI_CONFIG_8(PCI_REVISION_ID, 0x08); |
|
434 /* PCI Class Code */ |
|
435 PCI_CONFIG_8(0x09, 0x00); |
|
436 PCI_CONFIG_8(PCI_SUBCLASS_CODE, 0x00); // ethernet network controller |
|
437 PCI_CONFIG_8(PCI_CLASS_CODE, 0x02); // network controller |
|
438 /* PCI Cache Line Size */ |
|
439 /* check cache line size!!! */ |
|
440 //~ PCI_CONFIG_8(0x0c, 0x00); |
|
441 /* PCI Latency Timer */ |
|
442 PCI_CONFIG_8(0x0d, 0x20); // latency timer = 32 clocks |
|
443 /* PCI Header Type */ |
|
444 /* BIST (built-in self test) */ |
|
445 #if defined(TARGET_I386) |
|
446 // !!! workaround for buggy bios |
|
447 //~ #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0 |
|
448 #endif |
|
449 #if 0 |
|
450 /* PCI Base Address Registers */ |
|
451 /* CSR Memory Mapped Base Address */ |
|
452 PCI_CONFIG_32(PCI_BASE_ADDRESS_0, |
|
453 PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_MEM_PREFETCH); |
|
454 /* CSR I/O Mapped Base Address */ |
|
455 PCI_CONFIG_32(PCI_BASE_ADDRESS_1, PCI_ADDRESS_SPACE_IO); |
|
456 #if 0 |
|
457 /* Flash Memory Mapped Base Address */ |
|
458 PCI_CONFIG_32(PCI_BASE_ADDRESS_2, 0xfffe0000 | PCI_ADDRESS_SPACE_MEM); |
|
459 #endif |
|
460 #endif |
|
461 /* Expansion ROM Base Address (depends on boot disable!!!) */ |
|
462 PCI_CONFIG_32(0x30, 0x00000000); |
|
463 /* Capability Pointer */ |
|
464 PCI_CONFIG_8(0x34, 0xdc); |
|
465 /* Interrupt Pin */ |
|
466 PCI_CONFIG_8(0x3d, 1); // interrupt pin 0 |
|
467 /* Minimum Grant */ |
|
468 PCI_CONFIG_8(0x3e, 0x08); |
|
469 /* Maximum Latency */ |
|
470 PCI_CONFIG_8(0x3f, 0x18); |
|
471 /* Power Management Capabilities / Next Item Pointer / Capability ID */ |
|
472 PCI_CONFIG_32(0xdc, 0x7e210001); |
|
473 |
|
474 switch (device) { |
|
475 case i82551: |
|
476 //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209); |
|
477 PCI_CONFIG_8(PCI_REVISION_ID, 0x0f); |
|
478 break; |
|
479 case i82557B: |
|
480 PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229); |
|
481 PCI_CONFIG_8(PCI_REVISION_ID, 0x02); |
|
482 break; |
|
483 case i82557C: |
|
484 PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229); |
|
485 PCI_CONFIG_8(PCI_REVISION_ID, 0x03); |
|
486 break; |
|
487 case i82558B: |
|
488 PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229); |
|
489 PCI_CONFIG_16(PCI_STATUS, 0x2810); |
|
490 PCI_CONFIG_8(PCI_REVISION_ID, 0x05); |
|
491 break; |
|
492 case i82559C: |
|
493 PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229); |
|
494 PCI_CONFIG_16(PCI_STATUS, 0x2810); |
|
495 //~ PCI_CONFIG_8(PCI_REVISION_ID, 0x08); |
|
496 break; |
|
497 case i82559ER: |
|
498 //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209); |
|
499 PCI_CONFIG_16(PCI_STATUS, 0x2810); |
|
500 PCI_CONFIG_8(PCI_REVISION_ID, 0x09); |
|
501 break; |
|
502 //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1029); |
|
503 //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1030); /* 82559 InBusiness 10/100 */ |
|
504 default: |
|
505 logout("Device %X is undefined!\n", device); |
|
506 } |
|
507 |
|
508 if (device == i82557C || device == i82558B || device == i82559C) { |
|
509 logout("Get device id and revision from EEPROM!!!\n"); |
|
510 } |
|
511 } |
|
512 |
|
513 static void nic_selective_reset(EEPRO100State * s) |
|
514 { |
|
515 size_t i; |
|
516 uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom); |
|
517 //~ eeprom93xx_reset(s->eeprom); |
|
518 memcpy(eeprom_contents, s->macaddr, 6); |
|
519 eeprom_contents[0xa] = 0x4000; |
|
520 uint16_t sum = 0; |
|
521 for (i = 0; i < EEPROM_SIZE - 1; i++) { |
|
522 sum += eeprom_contents[i]; |
|
523 } |
|
524 eeprom_contents[EEPROM_SIZE - 1] = 0xbaba - sum; |
|
525 |
|
526 memset(s->mem, 0, sizeof(s->mem)); |
|
527 uint32_t val = BIT(21); |
|
528 memcpy(&s->mem[SCBCtrlMDI], &val, sizeof(val)); |
|
529 |
|
530 assert(sizeof(s->mdimem) == sizeof(eepro100_mdi_default)); |
|
531 memcpy(&s->mdimem[0], &eepro100_mdi_default[0], sizeof(s->mdimem)); |
|
532 } |
|
533 |
|
534 static void nic_reset(void *opaque) |
|
535 { |
|
536 EEPRO100State *s = (EEPRO100State *) opaque; |
|
537 logout("%p\n", s); |
|
538 static int first; |
|
539 if (!first) { |
|
540 first = 1; |
|
541 } |
|
542 nic_selective_reset(s); |
|
543 } |
|
544 |
|
545 #if defined(DEBUG_EEPRO100) |
|
546 static const char *reg[PCI_IO_SIZE / 4] = { |
|
547 "Command/Status", |
|
548 "General Pointer", |
|
549 "Port", |
|
550 "EEPROM/Flash Control", |
|
551 "MDI Control", |
|
552 "Receive DMA Byte Count", |
|
553 "Flow control register", |
|
554 "General Status/Control" |
|
555 }; |
|
556 |
|
557 static char *regname(uint32_t addr) |
|
558 { |
|
559 static char buf[16]; |
|
560 if (addr < PCI_IO_SIZE) { |
|
561 const char *r = reg[addr / 4]; |
|
562 if (r != 0) { |
|
563 sprintf(buf, "%s+%u", r, addr % 4); |
|
564 } else { |
|
565 sprintf(buf, "0x%02x", addr); |
|
566 } |
|
567 } else { |
|
568 sprintf(buf, "??? 0x%08x", addr); |
|
569 } |
|
570 return buf; |
|
571 } |
|
572 #endif /* DEBUG_EEPRO100 */ |
|
573 |
|
574 #if 0 |
|
575 static uint16_t eepro100_read_status(EEPRO100State * s) |
|
576 { |
|
577 uint16_t val = s->status; |
|
578 logout("val=0x%04x\n", val); |
|
579 return val; |
|
580 } |
|
581 |
|
582 static void eepro100_write_status(EEPRO100State * s, uint16_t val) |
|
583 { |
|
584 logout("val=0x%04x\n", val); |
|
585 s->status = val; |
|
586 } |
|
587 #endif |
|
588 |
|
589 /***************************************************************************** |
|
590 * |
|
591 * Command emulation. |
|
592 * |
|
593 ****************************************************************************/ |
|
594 |
|
595 #if 0 |
|
596 static uint16_t eepro100_read_command(EEPRO100State * s) |
|
597 { |
|
598 uint16_t val = 0xffff; |
|
599 //~ logout("val=0x%04x\n", val); |
|
600 return val; |
|
601 } |
|
602 #endif |
|
603 |
|
604 /* Commands that can be put in a command list entry. */ |
|
605 enum commands { |
|
606 CmdNOp = 0, |
|
607 CmdIASetup = 1, |
|
608 CmdConfigure = 2, |
|
609 CmdMulticastList = 3, |
|
610 CmdTx = 4, |
|
611 CmdTDR = 5, /* load microcode */ |
|
612 CmdDump = 6, |
|
613 CmdDiagnose = 7, |
|
614 |
|
615 /* And some extra flags: */ |
|
616 CmdSuspend = 0x4000, /* Suspend after completion. */ |
|
617 CmdIntr = 0x2000, /* Interrupt after completion. */ |
|
618 CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */ |
|
619 }; |
|
620 |
|
621 static cu_state_t get_cu_state(EEPRO100State * s) |
|
622 { |
|
623 return ((s->mem[SCBStatus] >> 6) & 0x03); |
|
624 } |
|
625 |
|
626 static void set_cu_state(EEPRO100State * s, cu_state_t state) |
|
627 { |
|
628 s->mem[SCBStatus] = (s->mem[SCBStatus] & 0x3f) + (state << 6); |
|
629 } |
|
630 |
|
631 static ru_state_t get_ru_state(EEPRO100State * s) |
|
632 { |
|
633 return ((s->mem[SCBStatus] >> 2) & 0x0f); |
|
634 } |
|
635 |
|
636 static void set_ru_state(EEPRO100State * s, ru_state_t state) |
|
637 { |
|
638 s->mem[SCBStatus] = (s->mem[SCBStatus] & 0xc3) + (state << 2); |
|
639 } |
|
640 |
|
641 static void dump_statistics(EEPRO100State * s) |
|
642 { |
|
643 /* Dump statistical data. Most data is never changed by the emulation |
|
644 * and always 0, so we first just copy the whole block and then those |
|
645 * values which really matter. |
|
646 * Number of data should check configuration!!! |
|
647 */ |
|
648 cpu_physical_memory_write(s->statsaddr, (uint8_t *) & s->statistics, 64); |
|
649 stl_phys(s->statsaddr + 0, s->statistics.tx_good_frames); |
|
650 stl_phys(s->statsaddr + 36, s->statistics.rx_good_frames); |
|
651 stl_phys(s->statsaddr + 48, s->statistics.rx_resource_errors); |
|
652 stl_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors); |
|
653 //~ stw_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames); |
|
654 //~ stw_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames); |
|
655 //~ missing("CU dump statistical counters"); |
|
656 } |
|
657 |
|
658 static void eepro100_cu_command(EEPRO100State * s, uint8_t val) |
|
659 { |
|
660 eepro100_tx_t tx; |
|
661 uint32_t cb_address; |
|
662 switch (val) { |
|
663 case CU_NOP: |
|
664 /* No operation. */ |
|
665 break; |
|
666 case CU_START: |
|
667 if (get_cu_state(s) != cu_idle) { |
|
668 /* Intel documentation says that CU must be idle for the CU |
|
669 * start command. Intel driver for Linux also starts the CU |
|
670 * from suspended state. */ |
|
671 logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle); |
|
672 //~ assert(!"wrong CU state"); |
|
673 } |
|
674 set_cu_state(s, cu_active); |
|
675 s->cu_offset = s->pointer; |
|
676 next_command: |
|
677 cb_address = s->cu_base + s->cu_offset; |
|
678 cpu_physical_memory_read(cb_address, (uint8_t *) & tx, sizeof(tx)); |
|
679 uint16_t status = le16_to_cpu(tx.status); |
|
680 uint16_t command = le16_to_cpu(tx.command); |
|
681 logout |
|
682 ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n", |
|
683 val, status, command, tx.link); |
|
684 bool bit_el = ((command & 0x8000) != 0); |
|
685 bool bit_s = ((command & 0x4000) != 0); |
|
686 bool bit_i = ((command & 0x2000) != 0); |
|
687 bool bit_nc = ((command & 0x0010) != 0); |
|
688 //~ bool bit_sf = ((command & 0x0008) != 0); |
|
689 uint16_t cmd = command & 0x0007; |
|
690 s->cu_offset = le32_to_cpu(tx.link); |
|
691 switch (cmd) { |
|
692 case CmdNOp: |
|
693 /* Do nothing. */ |
|
694 break; |
|
695 case CmdIASetup: |
|
696 cpu_physical_memory_read(cb_address + 8, &s->macaddr[0], 6); |
|
697 logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6)); |
|
698 break; |
|
699 case CmdConfigure: |
|
700 cpu_physical_memory_read(cb_address + 8, &s->configuration[0], |
|
701 sizeof(s->configuration)); |
|
702 logout("configuration: %s\n", nic_dump(&s->configuration[0], 16)); |
|
703 break; |
|
704 case CmdMulticastList: |
|
705 //~ missing("multicast list"); |
|
706 break; |
|
707 case CmdTx: |
|
708 (void)0; |
|
709 uint32_t tbd_array = le32_to_cpu(tx.tx_desc_addr); |
|
710 uint16_t tcb_bytes = (le16_to_cpu(tx.tcb_bytes) & 0x3fff); |
|
711 logout |
|
712 ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n", |
|
713 tbd_array, tcb_bytes, tx.tbd_count); |
|
714 assert(!bit_nc); |
|
715 //~ assert(!bit_sf); |
|
716 assert(tcb_bytes <= 2600); |
|
717 /* Next assertion fails for local configuration. */ |
|
718 //~ assert((tcb_bytes > 0) || (tbd_array != 0xffffffff)); |
|
719 if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) { |
|
720 logout |
|
721 ("illegal values of TBD array address and TCB byte count!\n"); |
|
722 } |
|
723 uint8_t buf[MAX_ETH_FRAME_SIZE + 4]; |
|
724 uint16_t size = 0; |
|
725 uint32_t tbd_address = cb_address + 0x10; |
|
726 assert(tcb_bytes <= sizeof(buf)); |
|
727 while (size < tcb_bytes) { |
|
728 uint32_t tx_buffer_address = ldl_phys(tbd_address); |
|
729 uint16_t tx_buffer_size = lduw_phys(tbd_address + 4); |
|
730 //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6); |
|
731 tbd_address += 8; |
|
732 logout |
|
733 ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n", |
|
734 tx_buffer_address, tx_buffer_size); |
|
735 cpu_physical_memory_read(tx_buffer_address, &buf[size], |
|
736 tx_buffer_size); |
|
737 size += tx_buffer_size; |
|
738 } |
|
739 if (tbd_array == 0xffffffff) { |
|
740 /* Simplified mode. Was already handled by code above. */ |
|
741 } else { |
|
742 /* Flexible mode. */ |
|
743 uint8_t tbd_count = 0; |
|
744 if (!(s->configuration[6] & BIT(4))) { |
|
745 /* Extended TCB. */ |
|
746 assert(tcb_bytes == 0); |
|
747 for (; tbd_count < 2; tbd_count++) { |
|
748 uint32_t tx_buffer_address = ldl_phys(tbd_address); |
|
749 uint16_t tx_buffer_size = lduw_phys(tbd_address + 4); |
|
750 uint16_t tx_buffer_el = lduw_phys(tbd_address + 6); |
|
751 tbd_address += 8; |
|
752 logout |
|
753 ("TBD (extended mode): buffer address 0x%08x, size 0x%04x\n", |
|
754 tx_buffer_address, tx_buffer_size); |
|
755 cpu_physical_memory_read(tx_buffer_address, &buf[size], |
|
756 tx_buffer_size); |
|
757 size += tx_buffer_size; |
|
758 if (tx_buffer_el & 1) { |
|
759 break; |
|
760 } |
|
761 } |
|
762 } |
|
763 tbd_address = tbd_array; |
|
764 for (; tbd_count < tx.tbd_count; tbd_count++) { |
|
765 uint32_t tx_buffer_address = ldl_phys(tbd_address); |
|
766 uint16_t tx_buffer_size = lduw_phys(tbd_address + 4); |
|
767 uint16_t tx_buffer_el = lduw_phys(tbd_address + 6); |
|
768 tbd_address += 8; |
|
769 logout |
|
770 ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n", |
|
771 tx_buffer_address, tx_buffer_size); |
|
772 cpu_physical_memory_read(tx_buffer_address, &buf[size], |
|
773 tx_buffer_size); |
|
774 size += tx_buffer_size; |
|
775 if (tx_buffer_el & 1) { |
|
776 break; |
|
777 } |
|
778 } |
|
779 } |
|
780 qemu_send_packet(s->vc, buf, size); |
|
781 s->statistics.tx_good_frames++; |
|
782 /* Transmit with bad status would raise an CX/TNO interrupt. |
|
783 * (82557 only). Emulation never has bad status. */ |
|
784 //~ eepro100_cx_interrupt(s); |
|
785 break; |
|
786 case CmdTDR: |
|
787 logout("load microcode\n"); |
|
788 /* Starting with offset 8, the command contains |
|
789 * 64 dwords microcode which we just ignore here. */ |
|
790 break; |
|
791 default: |
|
792 missing("undefined command"); |
|
793 } |
|
794 /* Write new status (success). */ |
|
795 stw_phys(cb_address, status | 0x8000 | 0x2000); |
|
796 if (bit_i) { |
|
797 /* CU completed action. */ |
|
798 eepro100_cx_interrupt(s); |
|
799 } |
|
800 if (bit_el) { |
|
801 /* CU becomes idle. */ |
|
802 set_cu_state(s, cu_idle); |
|
803 eepro100_cna_interrupt(s); |
|
804 } else if (bit_s) { |
|
805 /* CU becomes suspended. */ |
|
806 set_cu_state(s, cu_suspended); |
|
807 eepro100_cna_interrupt(s); |
|
808 } else { |
|
809 /* More entries in list. */ |
|
810 logout("CU list with at least one more entry\n"); |
|
811 goto next_command; |
|
812 } |
|
813 logout("CU list empty\n"); |
|
814 /* List is empty. Now CU is idle or suspended. */ |
|
815 break; |
|
816 case CU_RESUME: |
|
817 if (get_cu_state(s) != cu_suspended) { |
|
818 logout("bad CU resume from CU state %u\n", get_cu_state(s)); |
|
819 /* Workaround for bad Linux eepro100 driver which resumes |
|
820 * from idle state. */ |
|
821 //~ missing("cu resume"); |
|
822 set_cu_state(s, cu_suspended); |
|
823 } |
|
824 if (get_cu_state(s) == cu_suspended) { |
|
825 logout("CU resuming\n"); |
|
826 set_cu_state(s, cu_active); |
|
827 goto next_command; |
|
828 } |
|
829 break; |
|
830 case CU_STATSADDR: |
|
831 /* Load dump counters address. */ |
|
832 s->statsaddr = s->pointer; |
|
833 logout("val=0x%02x (status address)\n", val); |
|
834 break; |
|
835 case CU_SHOWSTATS: |
|
836 /* Dump statistical counters. */ |
|
837 dump_statistics(s); |
|
838 break; |
|
839 case CU_CMD_BASE: |
|
840 /* Load CU base. */ |
|
841 logout("val=0x%02x (CU base address)\n", val); |
|
842 s->cu_base = s->pointer; |
|
843 break; |
|
844 case CU_DUMPSTATS: |
|
845 /* Dump and reset statistical counters. */ |
|
846 dump_statistics(s); |
|
847 memset(&s->statistics, 0, sizeof(s->statistics)); |
|
848 break; |
|
849 case CU_SRESUME: |
|
850 /* CU static resume. */ |
|
851 missing("CU static resume"); |
|
852 break; |
|
853 default: |
|
854 missing("Undefined CU command"); |
|
855 } |
|
856 } |
|
857 |
|
858 static void eepro100_ru_command(EEPRO100State * s, uint8_t val) |
|
859 { |
|
860 switch (val) { |
|
861 case RU_NOP: |
|
862 /* No operation. */ |
|
863 break; |
|
864 case RX_START: |
|
865 /* RU start. */ |
|
866 if (get_ru_state(s) != ru_idle) { |
|
867 logout("RU state is %u, should be %u\n", get_ru_state(s), ru_idle); |
|
868 //~ assert(!"wrong RU state"); |
|
869 } |
|
870 set_ru_state(s, ru_ready); |
|
871 s->ru_offset = s->pointer; |
|
872 logout("val=0x%02x (rx start)\n", val); |
|
873 break; |
|
874 case RX_RESUME: |
|
875 /* Restart RU. */ |
|
876 if (get_ru_state(s) != ru_suspended) { |
|
877 logout("RU state is %u, should be %u\n", get_ru_state(s), |
|
878 ru_suspended); |
|
879 //~ assert(!"wrong RU state"); |
|
880 } |
|
881 set_ru_state(s, ru_ready); |
|
882 break; |
|
883 case RX_ADDR_LOAD: |
|
884 /* Load RU base. */ |
|
885 logout("val=0x%02x (RU base address)\n", val); |
|
886 s->ru_base = s->pointer; |
|
887 break; |
|
888 default: |
|
889 logout("val=0x%02x (undefined RU command)\n", val); |
|
890 missing("Undefined SU command"); |
|
891 } |
|
892 } |
|
893 |
|
894 static void eepro100_write_command(EEPRO100State * s, uint8_t val) |
|
895 { |
|
896 eepro100_ru_command(s, val & 0x0f); |
|
897 eepro100_cu_command(s, val & 0xf0); |
|
898 if ((val) == 0) { |
|
899 logout("val=0x%02x\n", val); |
|
900 } |
|
901 /* Clear command byte after command was accepted. */ |
|
902 s->mem[SCBCmd] = 0; |
|
903 } |
|
904 |
|
905 /***************************************************************************** |
|
906 * |
|
907 * EEPROM emulation. |
|
908 * |
|
909 ****************************************************************************/ |
|
910 |
|
911 #define EEPROM_CS 0x02 |
|
912 #define EEPROM_SK 0x01 |
|
913 #define EEPROM_DI 0x04 |
|
914 #define EEPROM_DO 0x08 |
|
915 |
|
916 static uint16_t eepro100_read_eeprom(EEPRO100State * s) |
|
917 { |
|
918 uint16_t val; |
|
919 memcpy(&val, &s->mem[SCBeeprom], sizeof(val)); |
|
920 if (eeprom93xx_read(s->eeprom)) { |
|
921 val |= EEPROM_DO; |
|
922 } else { |
|
923 val &= ~EEPROM_DO; |
|
924 } |
|
925 return val; |
|
926 } |
|
927 |
|
928 static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val) |
|
929 { |
|
930 logout("write val=0x%02x\n", val); |
|
931 |
|
932 /* mask unwriteable bits */ |
|
933 //~ val = SET_MASKED(val, 0x31, eeprom->value); |
|
934 |
|
935 int eecs = ((val & EEPROM_CS) != 0); |
|
936 int eesk = ((val & EEPROM_SK) != 0); |
|
937 int eedi = ((val & EEPROM_DI) != 0); |
|
938 eeprom93xx_write(eeprom, eecs, eesk, eedi); |
|
939 } |
|
940 |
|
941 static void eepro100_write_pointer(EEPRO100State * s, uint32_t val) |
|
942 { |
|
943 s->pointer = le32_to_cpu(val); |
|
944 logout("val=0x%08x\n", val); |
|
945 } |
|
946 |
|
947 /***************************************************************************** |
|
948 * |
|
949 * MDI emulation. |
|
950 * |
|
951 ****************************************************************************/ |
|
952 |
|
953 #if defined(DEBUG_EEPRO100) |
|
954 static const char *mdi_op_name[] = { |
|
955 "opcode 0", |
|
956 "write", |
|
957 "read", |
|
958 "opcode 3" |
|
959 }; |
|
960 |
|
961 static const char *mdi_reg_name[] = { |
|
962 "Control", |
|
963 "Status", |
|
964 "PHY Identification (Word 1)", |
|
965 "PHY Identification (Word 2)", |
|
966 "Auto-Negotiation Advertisement", |
|
967 "Auto-Negotiation Link Partner Ability", |
|
968 "Auto-Negotiation Expansion" |
|
969 }; |
|
970 #endif /* DEBUG_EEPRO100 */ |
|
971 |
|
972 static uint32_t eepro100_read_mdi(EEPRO100State * s) |
|
973 { |
|
974 uint32_t val; |
|
975 memcpy(&val, &s->mem[0x10], sizeof(val)); |
|
976 |
|
977 #ifdef DEBUG_EEPRO100 |
|
978 uint8_t raiseint = (val & BIT(29)) >> 29; |
|
979 uint8_t opcode = (val & BITS(27, 26)) >> 26; |
|
980 uint8_t phy = (val & BITS(25, 21)) >> 21; |
|
981 uint8_t reg = (val & BITS(20, 16)) >> 16; |
|
982 uint16_t data = (val & BITS(15, 0)); |
|
983 #endif |
|
984 /* Emulation takes no time to finish MDI transaction. */ |
|
985 val |= BIT(28); |
|
986 TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n", |
|
987 val, raiseint, mdi_op_name[opcode], phy, |
|
988 mdi_reg_name[reg], data)); |
|
989 return val; |
|
990 } |
|
991 |
|
992 //~ #define BITS(val, upper, lower) (val & ???) |
|
993 static void eepro100_write_mdi(EEPRO100State * s, uint32_t val) |
|
994 { |
|
995 uint8_t raiseint = (val & BIT(29)) >> 29; |
|
996 uint8_t opcode = (val & BITS(27, 26)) >> 26; |
|
997 uint8_t phy = (val & BITS(25, 21)) >> 21; |
|
998 uint8_t reg = (val & BITS(20, 16)) >> 16; |
|
999 uint16_t data = (val & BITS(15, 0)); |
|
1000 if (phy != 1) { |
|
1001 /* Unsupported PHY address. */ |
|
1002 //~ logout("phy must be 1 but is %u\n", phy); |
|
1003 data = 0; |
|
1004 } else if (opcode != 1 && opcode != 2) { |
|
1005 /* Unsupported opcode. */ |
|
1006 logout("opcode must be 1 or 2 but is %u\n", opcode); |
|
1007 data = 0; |
|
1008 } else if (reg > 6) { |
|
1009 /* Unsupported register. */ |
|
1010 logout("register must be 0...6 but is %u\n", reg); |
|
1011 data = 0; |
|
1012 } else { |
|
1013 TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n", |
|
1014 val, raiseint, mdi_op_name[opcode], phy, |
|
1015 mdi_reg_name[reg], data)); |
|
1016 if (opcode == 1) { |
|
1017 /* MDI write */ |
|
1018 switch (reg) { |
|
1019 case 0: /* Control Register */ |
|
1020 if (data & 0x8000) { |
|
1021 /* Reset status and control registers to default. */ |
|
1022 s->mdimem[0] = eepro100_mdi_default[0]; |
|
1023 s->mdimem[1] = eepro100_mdi_default[1]; |
|
1024 data = s->mdimem[reg]; |
|
1025 } else { |
|
1026 /* Restart Auto Configuration = Normal Operation */ |
|
1027 data &= ~0x0200; |
|
1028 } |
|
1029 break; |
|
1030 case 1: /* Status Register */ |
|
1031 missing("not writable"); |
|
1032 data = s->mdimem[reg]; |
|
1033 break; |
|
1034 case 2: /* PHY Identification Register (Word 1) */ |
|
1035 case 3: /* PHY Identification Register (Word 2) */ |
|
1036 missing("not implemented"); |
|
1037 break; |
|
1038 case 4: /* Auto-Negotiation Advertisement Register */ |
|
1039 case 5: /* Auto-Negotiation Link Partner Ability Register */ |
|
1040 break; |
|
1041 case 6: /* Auto-Negotiation Expansion Register */ |
|
1042 default: |
|
1043 missing("not implemented"); |
|
1044 } |
|
1045 s->mdimem[reg] = data; |
|
1046 } else if (opcode == 2) { |
|
1047 /* MDI read */ |
|
1048 switch (reg) { |
|
1049 case 0: /* Control Register */ |
|
1050 if (data & 0x8000) { |
|
1051 /* Reset status and control registers to default. */ |
|
1052 s->mdimem[0] = eepro100_mdi_default[0]; |
|
1053 s->mdimem[1] = eepro100_mdi_default[1]; |
|
1054 } |
|
1055 break; |
|
1056 case 1: /* Status Register */ |
|
1057 s->mdimem[reg] |= 0x0020; |
|
1058 break; |
|
1059 case 2: /* PHY Identification Register (Word 1) */ |
|
1060 case 3: /* PHY Identification Register (Word 2) */ |
|
1061 case 4: /* Auto-Negotiation Advertisement Register */ |
|
1062 break; |
|
1063 case 5: /* Auto-Negotiation Link Partner Ability Register */ |
|
1064 s->mdimem[reg] = 0x41fe; |
|
1065 break; |
|
1066 case 6: /* Auto-Negotiation Expansion Register */ |
|
1067 s->mdimem[reg] = 0x0001; |
|
1068 break; |
|
1069 } |
|
1070 data = s->mdimem[reg]; |
|
1071 } |
|
1072 /* Emulation takes no time to finish MDI transaction. |
|
1073 * Set MDI bit in SCB status register. */ |
|
1074 s->mem[SCBAck] |= 0x08; |
|
1075 val |= BIT(28); |
|
1076 if (raiseint) { |
|
1077 eepro100_mdi_interrupt(s); |
|
1078 } |
|
1079 } |
|
1080 val = (val & 0xffff0000) + data; |
|
1081 memcpy(&s->mem[0x10], &val, sizeof(val)); |
|
1082 } |
|
1083 |
|
1084 /***************************************************************************** |
|
1085 * |
|
1086 * Port emulation. |
|
1087 * |
|
1088 ****************************************************************************/ |
|
1089 |
|
1090 #define PORT_SOFTWARE_RESET 0 |
|
1091 #define PORT_SELFTEST 1 |
|
1092 #define PORT_SELECTIVE_RESET 2 |
|
1093 #define PORT_DUMP 3 |
|
1094 #define PORT_SELECTION_MASK 3 |
|
1095 |
|
1096 typedef struct { |
|
1097 uint32_t st_sign; /* Self Test Signature */ |
|
1098 uint32_t st_result; /* Self Test Results */ |
|
1099 } eepro100_selftest_t; |
|
1100 |
|
1101 static uint32_t eepro100_read_port(EEPRO100State * s) |
|
1102 { |
|
1103 return 0; |
|
1104 } |
|
1105 |
|
1106 static void eepro100_write_port(EEPRO100State * s, uint32_t val) |
|
1107 { |
|
1108 val = le32_to_cpu(val); |
|
1109 uint32_t address = (val & ~PORT_SELECTION_MASK); |
|
1110 uint8_t selection = (val & PORT_SELECTION_MASK); |
|
1111 switch (selection) { |
|
1112 case PORT_SOFTWARE_RESET: |
|
1113 nic_reset(s); |
|
1114 break; |
|
1115 case PORT_SELFTEST: |
|
1116 logout("selftest address=0x%08x\n", address); |
|
1117 eepro100_selftest_t data; |
|
1118 cpu_physical_memory_read(address, (uint8_t *) & data, sizeof(data)); |
|
1119 data.st_sign = 0xffffffff; |
|
1120 data.st_result = 0; |
|
1121 cpu_physical_memory_write(address, (uint8_t *) & data, sizeof(data)); |
|
1122 break; |
|
1123 case PORT_SELECTIVE_RESET: |
|
1124 logout("selective reset, selftest address=0x%08x\n", address); |
|
1125 nic_selective_reset(s); |
|
1126 break; |
|
1127 default: |
|
1128 logout("val=0x%08x\n", val); |
|
1129 missing("unknown port selection"); |
|
1130 } |
|
1131 } |
|
1132 |
|
1133 /***************************************************************************** |
|
1134 * |
|
1135 * General hardware emulation. |
|
1136 * |
|
1137 ****************************************************************************/ |
|
1138 |
|
1139 static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr) |
|
1140 { |
|
1141 uint8_t val; |
|
1142 if (addr <= sizeof(s->mem) - sizeof(val)) { |
|
1143 memcpy(&val, &s->mem[addr], sizeof(val)); |
|
1144 } |
|
1145 |
|
1146 switch (addr) { |
|
1147 case SCBStatus: |
|
1148 //~ val = eepro100_read_status(s); |
|
1149 logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1150 break; |
|
1151 case SCBAck: |
|
1152 //~ val = eepro100_read_status(s); |
|
1153 logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1154 break; |
|
1155 case SCBCmd: |
|
1156 logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1157 //~ val = eepro100_read_command(s); |
|
1158 break; |
|
1159 case SCBIntmask: |
|
1160 logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1161 break; |
|
1162 case SCBPort + 3: |
|
1163 logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1164 break; |
|
1165 case SCBeeprom: |
|
1166 val = eepro100_read_eeprom(s); |
|
1167 break; |
|
1168 case 0x1b: /* PMDR (power management driver register) */ |
|
1169 val = 0; |
|
1170 logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1171 break; |
|
1172 case 0x1d: /* general status register */ |
|
1173 /* 100 Mbps full duplex, valid link */ |
|
1174 val = 0x07; |
|
1175 logout("addr=General Status val=%02x\n", val); |
|
1176 break; |
|
1177 default: |
|
1178 logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1179 missing("unknown byte read"); |
|
1180 } |
|
1181 return val; |
|
1182 } |
|
1183 |
|
1184 static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr) |
|
1185 { |
|
1186 uint16_t val; |
|
1187 if (addr <= sizeof(s->mem) - sizeof(val)) { |
|
1188 memcpy(&val, &s->mem[addr], sizeof(val)); |
|
1189 } |
|
1190 |
|
1191 logout("addr=%s val=0x%04x\n", regname(addr), val); |
|
1192 |
|
1193 switch (addr) { |
|
1194 case SCBStatus: |
|
1195 //~ val = eepro100_read_status(s); |
|
1196 break; |
|
1197 case SCBeeprom: |
|
1198 val = eepro100_read_eeprom(s); |
|
1199 break; |
|
1200 default: |
|
1201 logout("addr=%s val=0x%04x\n", regname(addr), val); |
|
1202 missing("unknown word read"); |
|
1203 } |
|
1204 return val; |
|
1205 } |
|
1206 |
|
1207 static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr) |
|
1208 { |
|
1209 uint32_t val; |
|
1210 if (addr <= sizeof(s->mem) - sizeof(val)) { |
|
1211 memcpy(&val, &s->mem[addr], sizeof(val)); |
|
1212 } |
|
1213 |
|
1214 switch (addr) { |
|
1215 case SCBStatus: |
|
1216 //~ val = eepro100_read_status(s); |
|
1217 logout("addr=%s val=0x%08x\n", regname(addr), val); |
|
1218 break; |
|
1219 case SCBPointer: |
|
1220 //~ val = eepro100_read_pointer(s); |
|
1221 logout("addr=%s val=0x%08x\n", regname(addr), val); |
|
1222 break; |
|
1223 case SCBPort: |
|
1224 val = eepro100_read_port(s); |
|
1225 logout("addr=%s val=0x%08x\n", regname(addr), val); |
|
1226 break; |
|
1227 case SCBCtrlMDI: |
|
1228 val = eepro100_read_mdi(s); |
|
1229 break; |
|
1230 default: |
|
1231 logout("addr=%s val=0x%08x\n", regname(addr), val); |
|
1232 missing("unknown longword read"); |
|
1233 } |
|
1234 return val; |
|
1235 } |
|
1236 |
|
1237 static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val) |
|
1238 { |
|
1239 if (addr <= sizeof(s->mem) - sizeof(val)) { |
|
1240 memcpy(&s->mem[addr], &val, sizeof(val)); |
|
1241 } |
|
1242 |
|
1243 logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1244 |
|
1245 switch (addr) { |
|
1246 case SCBStatus: |
|
1247 //~ eepro100_write_status(s, val); |
|
1248 break; |
|
1249 case SCBAck: |
|
1250 eepro100_acknowledge(s); |
|
1251 break; |
|
1252 case SCBCmd: |
|
1253 eepro100_write_command(s, val); |
|
1254 break; |
|
1255 case SCBIntmask: |
|
1256 if (val & BIT(1)) { |
|
1257 eepro100_swi_interrupt(s); |
|
1258 } |
|
1259 eepro100_interrupt(s, 0); |
|
1260 break; |
|
1261 case SCBPort + 3: |
|
1262 case SCBFlow: |
|
1263 case SCBFlow + 1: |
|
1264 case SCBFlow + 2: |
|
1265 case SCBFlow + 3: |
|
1266 logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1267 break; |
|
1268 case SCBeeprom: |
|
1269 eepro100_write_eeprom(s->eeprom, val); |
|
1270 break; |
|
1271 default: |
|
1272 logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1273 missing("unknown byte write"); |
|
1274 } |
|
1275 } |
|
1276 |
|
1277 static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val) |
|
1278 { |
|
1279 if (addr <= sizeof(s->mem) - sizeof(val)) { |
|
1280 memcpy(&s->mem[addr], &val, sizeof(val)); |
|
1281 } |
|
1282 |
|
1283 logout("addr=%s val=0x%04x\n", regname(addr), val); |
|
1284 |
|
1285 switch (addr) { |
|
1286 case SCBStatus: |
|
1287 //~ eepro100_write_status(s, val); |
|
1288 eepro100_acknowledge(s); |
|
1289 break; |
|
1290 case SCBCmd: |
|
1291 eepro100_write_command(s, val); |
|
1292 eepro100_write1(s, SCBIntmask, val >> 8); |
|
1293 break; |
|
1294 case SCBeeprom: |
|
1295 eepro100_write_eeprom(s->eeprom, val); |
|
1296 break; |
|
1297 default: |
|
1298 logout("addr=%s val=0x%04x\n", regname(addr), val); |
|
1299 missing("unknown word write"); |
|
1300 } |
|
1301 } |
|
1302 |
|
1303 static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val) |
|
1304 { |
|
1305 if (addr <= sizeof(s->mem) - sizeof(val)) { |
|
1306 memcpy(&s->mem[addr], &val, sizeof(val)); |
|
1307 } |
|
1308 |
|
1309 switch (addr) { |
|
1310 case SCBPointer: |
|
1311 eepro100_write_pointer(s, val); |
|
1312 break; |
|
1313 case SCBPort: |
|
1314 logout("addr=%s val=0x%08x\n", regname(addr), val); |
|
1315 eepro100_write_port(s, val); |
|
1316 break; |
|
1317 case SCBCtrlMDI: |
|
1318 eepro100_write_mdi(s, val); |
|
1319 break; |
|
1320 default: |
|
1321 logout("addr=%s val=0x%08x\n", regname(addr), val); |
|
1322 missing("unknown longword write"); |
|
1323 } |
|
1324 } |
|
1325 |
|
1326 static uint32_t ioport_read1(void *opaque, uint32_t addr) |
|
1327 { |
|
1328 EEPRO100State *s = opaque; |
|
1329 //~ logout("addr=%s\n", regname(addr)); |
|
1330 return eepro100_read1(s, addr - s->region[1]); |
|
1331 } |
|
1332 |
|
1333 static uint32_t ioport_read2(void *opaque, uint32_t addr) |
|
1334 { |
|
1335 EEPRO100State *s = opaque; |
|
1336 return eepro100_read2(s, addr - s->region[1]); |
|
1337 } |
|
1338 |
|
1339 static uint32_t ioport_read4(void *opaque, uint32_t addr) |
|
1340 { |
|
1341 EEPRO100State *s = opaque; |
|
1342 return eepro100_read4(s, addr - s->region[1]); |
|
1343 } |
|
1344 |
|
1345 static void ioport_write1(void *opaque, uint32_t addr, uint32_t val) |
|
1346 { |
|
1347 EEPRO100State *s = opaque; |
|
1348 //~ logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1349 eepro100_write1(s, addr - s->region[1], val); |
|
1350 } |
|
1351 |
|
1352 static void ioport_write2(void *opaque, uint32_t addr, uint32_t val) |
|
1353 { |
|
1354 EEPRO100State *s = opaque; |
|
1355 eepro100_write2(s, addr - s->region[1], val); |
|
1356 } |
|
1357 |
|
1358 static void ioport_write4(void *opaque, uint32_t addr, uint32_t val) |
|
1359 { |
|
1360 EEPRO100State *s = opaque; |
|
1361 eepro100_write4(s, addr - s->region[1], val); |
|
1362 } |
|
1363 |
|
1364 /***********************************************************/ |
|
1365 /* PCI EEPRO100 definitions */ |
|
1366 |
|
1367 typedef struct PCIEEPRO100State { |
|
1368 PCIDevice dev; |
|
1369 EEPRO100State eepro100; |
|
1370 } PCIEEPRO100State; |
|
1371 |
|
1372 static void pci_map(PCIDevice * pci_dev, int region_num, |
|
1373 uint32_t addr, uint32_t size, int type) |
|
1374 { |
|
1375 PCIEEPRO100State *d = (PCIEEPRO100State *) pci_dev; |
|
1376 EEPRO100State *s = &d->eepro100; |
|
1377 |
|
1378 logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n", |
|
1379 region_num, addr, size, type); |
|
1380 |
|
1381 assert(region_num == 1); |
|
1382 register_ioport_write(addr, size, 1, ioport_write1, s); |
|
1383 register_ioport_read(addr, size, 1, ioport_read1, s); |
|
1384 register_ioport_write(addr, size, 2, ioport_write2, s); |
|
1385 register_ioport_read(addr, size, 2, ioport_read2, s); |
|
1386 register_ioport_write(addr, size, 4, ioport_write4, s); |
|
1387 register_ioport_read(addr, size, 4, ioport_read4, s); |
|
1388 |
|
1389 s->region[region_num] = addr; |
|
1390 } |
|
1391 |
|
1392 static void pci_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
1393 { |
|
1394 EEPRO100State *s = opaque; |
|
1395 //~ logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1396 eepro100_write1(s, addr, val); |
|
1397 } |
|
1398 |
|
1399 static void pci_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
1400 { |
|
1401 EEPRO100State *s = opaque; |
|
1402 //~ logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1403 eepro100_write2(s, addr, val); |
|
1404 } |
|
1405 |
|
1406 static void pci_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
1407 { |
|
1408 EEPRO100State *s = opaque; |
|
1409 //~ logout("addr=%s val=0x%02x\n", regname(addr), val); |
|
1410 eepro100_write4(s, addr, val); |
|
1411 } |
|
1412 |
|
1413 static uint32_t pci_mmio_readb(void *opaque, target_phys_addr_t addr) |
|
1414 { |
|
1415 EEPRO100State *s = opaque; |
|
1416 //~ logout("addr=%s\n", regname(addr)); |
|
1417 return eepro100_read1(s, addr); |
|
1418 } |
|
1419 |
|
1420 static uint32_t pci_mmio_readw(void *opaque, target_phys_addr_t addr) |
|
1421 { |
|
1422 EEPRO100State *s = opaque; |
|
1423 //~ logout("addr=%s\n", regname(addr)); |
|
1424 return eepro100_read2(s, addr); |
|
1425 } |
|
1426 |
|
1427 static uint32_t pci_mmio_readl(void *opaque, target_phys_addr_t addr) |
|
1428 { |
|
1429 EEPRO100State *s = opaque; |
|
1430 //~ logout("addr=%s\n", regname(addr)); |
|
1431 return eepro100_read4(s, addr); |
|
1432 } |
|
1433 |
|
1434 static CPUWriteMemoryFunc *pci_mmio_write[] = { |
|
1435 pci_mmio_writeb, |
|
1436 pci_mmio_writew, |
|
1437 pci_mmio_writel |
|
1438 }; |
|
1439 |
|
1440 static CPUReadMemoryFunc *pci_mmio_read[] = { |
|
1441 pci_mmio_readb, |
|
1442 pci_mmio_readw, |
|
1443 pci_mmio_readl |
|
1444 }; |
|
1445 |
|
1446 static void pci_mmio_map(PCIDevice * pci_dev, int region_num, |
|
1447 uint32_t addr, uint32_t size, int type) |
|
1448 { |
|
1449 PCIEEPRO100State *d = (PCIEEPRO100State *) pci_dev; |
|
1450 |
|
1451 logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n", |
|
1452 region_num, addr, size, type); |
|
1453 |
|
1454 if (region_num == 0) { |
|
1455 /* Map control / status registers. */ |
|
1456 cpu_register_physical_memory(addr, size, d->eepro100.mmio_index); |
|
1457 d->eepro100.region[region_num] = addr; |
|
1458 } |
|
1459 } |
|
1460 |
|
1461 static int nic_can_receive(void *opaque) |
|
1462 { |
|
1463 EEPRO100State *s = opaque; |
|
1464 logout("%p\n", s); |
|
1465 return get_ru_state(s) == ru_ready; |
|
1466 //~ return !eepro100_buffer_full(s); |
|
1467 } |
|
1468 |
|
1469 #define MIN_BUF_SIZE 60 |
|
1470 |
|
1471 static void nic_receive(void *opaque, const uint8_t * buf, int size) |
|
1472 { |
|
1473 /* TODO: |
|
1474 * - Magic packets should set bit 30 in power management driver register. |
|
1475 * - Interesting packets should set bit 29 in power management driver register. |
|
1476 */ |
|
1477 EEPRO100State *s = opaque; |
|
1478 uint16_t rfd_status = 0xa000; |
|
1479 static const uint8_t broadcast_macaddr[6] = |
|
1480 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
|
1481 |
|
1482 /* TODO: check multiple IA bit. */ |
|
1483 assert(!(s->configuration[20] & BIT(6))); |
|
1484 |
|
1485 if (s->configuration[8] & 0x80) { |
|
1486 /* CSMA is disabled. */ |
|
1487 logout("%p received while CSMA is disabled\n", s); |
|
1488 return; |
|
1489 } else if (size < 64 && (s->configuration[7] & 1)) { |
|
1490 /* Short frame and configuration byte 7/0 (discard short receive) set: |
|
1491 * Short frame is discarded */ |
|
1492 logout("%p received short frame (%d byte)\n", s, size); |
|
1493 s->statistics.rx_short_frame_errors++; |
|
1494 //~ return; |
|
1495 } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & 8)) { |
|
1496 /* Long frame and configuration byte 18/3 (long receive ok) not set: |
|
1497 * Long frames are discarded. */ |
|
1498 logout("%p received long frame (%d byte), ignored\n", s, size); |
|
1499 return; |
|
1500 } else if (memcmp(buf, s->macaddr, 6) == 0) { // !!! |
|
1501 /* Frame matches individual address. */ |
|
1502 /* TODO: check configuration byte 15/4 (ignore U/L). */ |
|
1503 logout("%p received frame for me, len=%d\n", s, size); |
|
1504 } else if (memcmp(buf, broadcast_macaddr, 6) == 0) { |
|
1505 /* Broadcast frame. */ |
|
1506 logout("%p received broadcast, len=%d\n", s, size); |
|
1507 rfd_status |= 0x0002; |
|
1508 } else if (buf[0] & 0x01) { // !!! |
|
1509 /* Multicast frame. */ |
|
1510 logout("%p received multicast, len=%d\n", s, size); |
|
1511 /* TODO: check multicast all bit. */ |
|
1512 assert(!(s->configuration[21] & BIT(3))); |
|
1513 int mcast_idx = compute_mcast_idx(buf); |
|
1514 if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) { |
|
1515 return; |
|
1516 } |
|
1517 rfd_status |= 0x0002; |
|
1518 } else if (s->configuration[15] & 1) { |
|
1519 /* Promiscuous: receive all. */ |
|
1520 logout("%p received frame in promiscuous mode, len=%d\n", s, size); |
|
1521 rfd_status |= 0x0004; |
|
1522 } else { |
|
1523 logout("%p received frame, ignored, len=%d,%s\n", s, size, |
|
1524 nic_dump(buf, size)); |
|
1525 return; |
|
1526 } |
|
1527 |
|
1528 if (get_ru_state(s) != ru_ready) { |
|
1529 /* No ressources available. */ |
|
1530 logout("no ressources, state=%u\n", get_ru_state(s)); |
|
1531 s->statistics.rx_resource_errors++; |
|
1532 //~ assert(!"no ressources"); |
|
1533 return; |
|
1534 } |
|
1535 //~ !!! |
|
1536 //~ $3 = {status = 0x0, command = 0xc000, link = 0x2d220, rx_buf_addr = 0x207dc, count = 0x0, size = 0x5f8, packet = {0x0 <repeats 1518 times>}} |
|
1537 eepro100_rx_t rx; |
|
1538 cpu_physical_memory_read(s->ru_base + s->ru_offset, (uint8_t *) & rx, |
|
1539 offsetof(eepro100_rx_t, packet)); |
|
1540 uint16_t rfd_command = le16_to_cpu(rx.command); |
|
1541 uint16_t rfd_size = le16_to_cpu(rx.size); |
|
1542 assert(size <= rfd_size); |
|
1543 if (size < 64) { |
|
1544 rfd_status |= 0x0080; |
|
1545 } |
|
1546 logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n", rfd_command, |
|
1547 rx.link, rx.rx_buf_addr, rfd_size); |
|
1548 stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status), |
|
1549 rfd_status); |
|
1550 stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size); |
|
1551 /* Early receive interrupt not supported. */ |
|
1552 //~ eepro100_er_interrupt(s); |
|
1553 /* Receive CRC Transfer not supported. */ |
|
1554 assert(!(s->configuration[18] & 4)); |
|
1555 /* TODO: check stripping enable bit. */ |
|
1556 //~ assert(!(s->configuration[17] & 1)); |
|
1557 cpu_physical_memory_write(s->ru_base + s->ru_offset + |
|
1558 offsetof(eepro100_rx_t, packet), buf, size); |
|
1559 s->statistics.rx_good_frames++; |
|
1560 eepro100_fr_interrupt(s); |
|
1561 s->ru_offset = le32_to_cpu(rx.link); |
|
1562 if (rfd_command & 0x8000) { |
|
1563 /* EL bit is set, so this was the last frame. */ |
|
1564 assert(0); |
|
1565 } |
|
1566 if (rfd_command & 0x4000) { |
|
1567 /* S bit is set. */ |
|
1568 set_ru_state(s, ru_suspended); |
|
1569 } |
|
1570 } |
|
1571 |
|
1572 static int nic_load(QEMUFile * f, void *opaque, int version_id) |
|
1573 { |
|
1574 EEPRO100State *s = (EEPRO100State *) opaque; |
|
1575 int i; |
|
1576 int ret; |
|
1577 |
|
1578 if (version_id > 3) |
|
1579 return -EINVAL; |
|
1580 |
|
1581 if (s->pci_dev && version_id >= 3) { |
|
1582 ret = pci_device_load(s->pci_dev, f); |
|
1583 if (ret < 0) |
|
1584 return ret; |
|
1585 } |
|
1586 |
|
1587 if (version_id >= 2) { |
|
1588 qemu_get_8s(f, &s->rxcr); |
|
1589 } else { |
|
1590 s->rxcr = 0x0c; |
|
1591 } |
|
1592 |
|
1593 qemu_get_8s(f, &s->cmd); |
|
1594 qemu_get_be32s(f, &s->start); |
|
1595 qemu_get_be32s(f, &s->stop); |
|
1596 qemu_get_8s(f, &s->boundary); |
|
1597 qemu_get_8s(f, &s->tsr); |
|
1598 qemu_get_8s(f, &s->tpsr); |
|
1599 qemu_get_be16s(f, &s->tcnt); |
|
1600 qemu_get_be16s(f, &s->rcnt); |
|
1601 qemu_get_be32s(f, &s->rsar); |
|
1602 qemu_get_8s(f, &s->rsr); |
|
1603 qemu_get_8s(f, &s->isr); |
|
1604 qemu_get_8s(f, &s->dcfg); |
|
1605 qemu_get_8s(f, &s->imr); |
|
1606 qemu_get_buffer(f, s->phys, 6); |
|
1607 qemu_get_8s(f, &s->curpag); |
|
1608 qemu_get_buffer(f, s->mult, 8); |
|
1609 qemu_get_buffer(f, s->mem, sizeof(s->mem)); |
|
1610 |
|
1611 /* Restore all members of struct between scv_stat and mem */ |
|
1612 qemu_get_8s(f, &s->scb_stat); |
|
1613 qemu_get_8s(f, &s->int_stat); |
|
1614 for (i = 0; i < 3; i++) |
|
1615 qemu_get_be32s(f, &s->region[i]); |
|
1616 qemu_get_buffer(f, s->macaddr, 6); |
|
1617 for (i = 0; i < 19; i++) |
|
1618 qemu_get_be32s(f, &s->statcounter[i]); |
|
1619 for (i = 0; i < 32; i++) |
|
1620 qemu_get_be16s(f, &s->mdimem[i]); |
|
1621 /* The eeprom should be saved and restored by its own routines */ |
|
1622 qemu_get_be32s(f, &s->device); |
|
1623 qemu_get_be32s(f, &s->pointer); |
|
1624 qemu_get_be32s(f, &s->cu_base); |
|
1625 qemu_get_be32s(f, &s->cu_offset); |
|
1626 qemu_get_be32s(f, &s->ru_base); |
|
1627 qemu_get_be32s(f, &s->ru_offset); |
|
1628 qemu_get_be32s(f, &s->statsaddr); |
|
1629 /* Restore epro100_stats_t statistics */ |
|
1630 qemu_get_be32s(f, &s->statistics.tx_good_frames); |
|
1631 qemu_get_be32s(f, &s->statistics.tx_max_collisions); |
|
1632 qemu_get_be32s(f, &s->statistics.tx_late_collisions); |
|
1633 qemu_get_be32s(f, &s->statistics.tx_underruns); |
|
1634 qemu_get_be32s(f, &s->statistics.tx_lost_crs); |
|
1635 qemu_get_be32s(f, &s->statistics.tx_deferred); |
|
1636 qemu_get_be32s(f, &s->statistics.tx_single_collisions); |
|
1637 qemu_get_be32s(f, &s->statistics.tx_multiple_collisions); |
|
1638 qemu_get_be32s(f, &s->statistics.tx_total_collisions); |
|
1639 qemu_get_be32s(f, &s->statistics.rx_good_frames); |
|
1640 qemu_get_be32s(f, &s->statistics.rx_crc_errors); |
|
1641 qemu_get_be32s(f, &s->statistics.rx_alignment_errors); |
|
1642 qemu_get_be32s(f, &s->statistics.rx_resource_errors); |
|
1643 qemu_get_be32s(f, &s->statistics.rx_overrun_errors); |
|
1644 qemu_get_be32s(f, &s->statistics.rx_cdt_errors); |
|
1645 qemu_get_be32s(f, &s->statistics.rx_short_frame_errors); |
|
1646 qemu_get_be32s(f, &s->statistics.fc_xmt_pause); |
|
1647 qemu_get_be32s(f, &s->statistics.fc_rcv_pause); |
|
1648 qemu_get_be32s(f, &s->statistics.fc_rcv_unsupported); |
|
1649 qemu_get_be16s(f, &s->statistics.xmt_tco_frames); |
|
1650 qemu_get_be16s(f, &s->statistics.rcv_tco_frames); |
|
1651 qemu_get_be32s(f, &s->statistics.complete); |
|
1652 #if 0 |
|
1653 qemu_get_be16s(f, &s->status); |
|
1654 #endif |
|
1655 |
|
1656 /* Configuration bytes. */ |
|
1657 qemu_get_buffer(f, s->configuration, sizeof(s->configuration)); |
|
1658 |
|
1659 return 0; |
|
1660 } |
|
1661 |
|
1662 static void nic_save(QEMUFile * f, void *opaque) |
|
1663 { |
|
1664 EEPRO100State *s = (EEPRO100State *) opaque; |
|
1665 int i; |
|
1666 |
|
1667 if (s->pci_dev) |
|
1668 pci_device_save(s->pci_dev, f); |
|
1669 |
|
1670 qemu_put_8s(f, &s->rxcr); |
|
1671 |
|
1672 qemu_put_8s(f, &s->cmd); |
|
1673 qemu_put_be32s(f, &s->start); |
|
1674 qemu_put_be32s(f, &s->stop); |
|
1675 qemu_put_8s(f, &s->boundary); |
|
1676 qemu_put_8s(f, &s->tsr); |
|
1677 qemu_put_8s(f, &s->tpsr); |
|
1678 qemu_put_be16s(f, &s->tcnt); |
|
1679 qemu_put_be16s(f, &s->rcnt); |
|
1680 qemu_put_be32s(f, &s->rsar); |
|
1681 qemu_put_8s(f, &s->rsr); |
|
1682 qemu_put_8s(f, &s->isr); |
|
1683 qemu_put_8s(f, &s->dcfg); |
|
1684 qemu_put_8s(f, &s->imr); |
|
1685 qemu_put_buffer(f, s->phys, 6); |
|
1686 qemu_put_8s(f, &s->curpag); |
|
1687 qemu_put_buffer(f, s->mult, 8); |
|
1688 qemu_put_buffer(f, s->mem, sizeof(s->mem)); |
|
1689 |
|
1690 /* Save all members of struct between scv_stat and mem */ |
|
1691 qemu_put_8s(f, &s->scb_stat); |
|
1692 qemu_put_8s(f, &s->int_stat); |
|
1693 for (i = 0; i < 3; i++) |
|
1694 qemu_put_be32s(f, &s->region[i]); |
|
1695 qemu_put_buffer(f, s->macaddr, 6); |
|
1696 for (i = 0; i < 19; i++) |
|
1697 qemu_put_be32s(f, &s->statcounter[i]); |
|
1698 for (i = 0; i < 32; i++) |
|
1699 qemu_put_be16s(f, &s->mdimem[i]); |
|
1700 /* The eeprom should be saved and restored by its own routines */ |
|
1701 qemu_put_be32s(f, &s->device); |
|
1702 qemu_put_be32s(f, &s->pointer); |
|
1703 qemu_put_be32s(f, &s->cu_base); |
|
1704 qemu_put_be32s(f, &s->cu_offset); |
|
1705 qemu_put_be32s(f, &s->ru_base); |
|
1706 qemu_put_be32s(f, &s->ru_offset); |
|
1707 qemu_put_be32s(f, &s->statsaddr); |
|
1708 /* Save epro100_stats_t statistics */ |
|
1709 qemu_put_be32s(f, &s->statistics.tx_good_frames); |
|
1710 qemu_put_be32s(f, &s->statistics.tx_max_collisions); |
|
1711 qemu_put_be32s(f, &s->statistics.tx_late_collisions); |
|
1712 qemu_put_be32s(f, &s->statistics.tx_underruns); |
|
1713 qemu_put_be32s(f, &s->statistics.tx_lost_crs); |
|
1714 qemu_put_be32s(f, &s->statistics.tx_deferred); |
|
1715 qemu_put_be32s(f, &s->statistics.tx_single_collisions); |
|
1716 qemu_put_be32s(f, &s->statistics.tx_multiple_collisions); |
|
1717 qemu_put_be32s(f, &s->statistics.tx_total_collisions); |
|
1718 qemu_put_be32s(f, &s->statistics.rx_good_frames); |
|
1719 qemu_put_be32s(f, &s->statistics.rx_crc_errors); |
|
1720 qemu_put_be32s(f, &s->statistics.rx_alignment_errors); |
|
1721 qemu_put_be32s(f, &s->statistics.rx_resource_errors); |
|
1722 qemu_put_be32s(f, &s->statistics.rx_overrun_errors); |
|
1723 qemu_put_be32s(f, &s->statistics.rx_cdt_errors); |
|
1724 qemu_put_be32s(f, &s->statistics.rx_short_frame_errors); |
|
1725 qemu_put_be32s(f, &s->statistics.fc_xmt_pause); |
|
1726 qemu_put_be32s(f, &s->statistics.fc_rcv_pause); |
|
1727 qemu_put_be32s(f, &s->statistics.fc_rcv_unsupported); |
|
1728 qemu_put_be16s(f, &s->statistics.xmt_tco_frames); |
|
1729 qemu_put_be16s(f, &s->statistics.rcv_tco_frames); |
|
1730 qemu_put_be32s(f, &s->statistics.complete); |
|
1731 #if 0 |
|
1732 qemu_put_be16s(f, &s->status); |
|
1733 #endif |
|
1734 |
|
1735 /* Configuration bytes. */ |
|
1736 qemu_put_buffer(f, s->configuration, sizeof(s->configuration)); |
|
1737 } |
|
1738 |
|
1739 static void nic_init(PCIBus * bus, NICInfo * nd, |
|
1740 const char *name, uint32_t device) |
|
1741 { |
|
1742 PCIEEPRO100State *d; |
|
1743 EEPRO100State *s; |
|
1744 |
|
1745 logout("\n"); |
|
1746 |
|
1747 d = (PCIEEPRO100State *) pci_register_device(bus, name, |
|
1748 sizeof(PCIEEPRO100State), -1, |
|
1749 NULL, NULL); |
|
1750 |
|
1751 s = &d->eepro100; |
|
1752 s->device = device; |
|
1753 s->pci_dev = &d->dev; |
|
1754 |
|
1755 pci_reset(s); |
|
1756 |
|
1757 /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM, |
|
1758 * i82559 and later support 64 or 256 word EEPROM. */ |
|
1759 s->eeprom = eeprom93xx_new(EEPROM_SIZE); |
|
1760 |
|
1761 /* Handler for memory-mapped I/O */ |
|
1762 d->eepro100.mmio_index = |
|
1763 cpu_register_io_memory(0, pci_mmio_read, pci_mmio_write, s); |
|
1764 |
|
1765 pci_register_io_region(&d->dev, 0, PCI_MEM_SIZE, |
|
1766 PCI_ADDRESS_SPACE_MEM | |
|
1767 PCI_ADDRESS_SPACE_MEM_PREFETCH, pci_mmio_map); |
|
1768 pci_register_io_region(&d->dev, 1, PCI_IO_SIZE, PCI_ADDRESS_SPACE_IO, |
|
1769 pci_map); |
|
1770 pci_register_io_region(&d->dev, 2, PCI_FLASH_SIZE, PCI_ADDRESS_SPACE_MEM, |
|
1771 pci_mmio_map); |
|
1772 |
|
1773 memcpy(s->macaddr, nd->macaddr, 6); |
|
1774 logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6)); |
|
1775 assert(s->region[1] == 0); |
|
1776 |
|
1777 nic_reset(s); |
|
1778 |
|
1779 s->vc = qemu_new_vlan_client(nd->vlan, nic_receive, nic_can_receive, s); |
|
1780 |
|
1781 snprintf(s->vc->info_str, sizeof(s->vc->info_str), |
|
1782 "eepro100 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x", |
|
1783 s->macaddr[0], |
|
1784 s->macaddr[1], |
|
1785 s->macaddr[2], s->macaddr[3], s->macaddr[4], s->macaddr[5]); |
|
1786 |
|
1787 qemu_register_reset(nic_reset, s); |
|
1788 |
|
1789 register_savevm(name, -1, 3, nic_save, nic_load, s); |
|
1790 } |
|
1791 |
|
1792 void pci_i82551_init(PCIBus * bus, NICInfo * nd, int devfn) |
|
1793 { |
|
1794 nic_init(bus, nd, "i82551", i82551); |
|
1795 //~ uint8_t *pci_conf = d->dev.config; |
|
1796 } |
|
1797 |
|
1798 void pci_i82557b_init(PCIBus * bus, NICInfo * nd, int devfn) |
|
1799 { |
|
1800 nic_init(bus, nd, "i82557b", i82557B); |
|
1801 } |
|
1802 |
|
1803 void pci_i82559er_init(PCIBus * bus, NICInfo * nd, int devfn) |
|
1804 { |
|
1805 nic_init(bus, nd, "i82559er", i82559ER); |
|
1806 } |
|
1807 |
|
1808 /* eof */ |