1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
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>
43: #include "hw.h"
44: #include "pci.h"
45: #include "net.h"
46: #include "eeprom93xx.h"
47:
48:
49:
50: #define PCI_VENDOR_ID 0x00
51: #define PCI_DEVICE_ID 0x02
52: #define PCI_COMMAND 0x04
53: #define PCI_STATUS 0x06
54:
55: #define PCI_REVISION_ID 0x08
56: #define PCI_CLASS_CODE 0x0b
57: #define PCI_SUBCLASS_CODE 0x0a
58: #define PCI_HEADER_TYPE 0x0e
59:
60: #define PCI_BASE_ADDRESS_0 0x10
61: #define PCI_BASE_ADDRESS_1 0x14
62: #define PCI_BASE_ADDRESS_2 0x18
63: #define PCI_BASE_ADDRESS_3 0x1c
64: #define PCI_BASE_ADDRESS_4 0x20
65: #define PCI_BASE_ADDRESS_5 0x24
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:
77:
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:
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:
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:
113: #define CU_NOP 0x0000
114: #define CU_START 0x0010
115: #define CU_RESUME 0x0020
116: #define CU_STATSADDR 0x0040
117: #define CU_SHOWSTATS 0x0050
118: #define CU_CMD_BASE 0x0060
119: #define CU_DUMPSTATS 0x0070
120: #define CU_SRESUME 0x00a0
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
130:
131: typedef unsigned char bool;
132:
133:
134:
135: enum speedo_offsets {
136: SCBStatus = 0,
137: SCBAck = 1,
138: SCBCmd = 2,
139: SCBIntmask = 3,
140: SCBPointer = 4,
141: SCBPort = 8,
142: SCBflash = 12, SCBeeprom = 14,
143: SCBCtrlMDI = 16,
144: SCBEarlyRx = 20,
145: SCBFlow = 24,
146: };
147:
148:
149: typedef struct {
150: uint16_t status;
151: uint16_t command;
152: uint32_t link;
153: uint32_t tx_desc_addr;
154: uint16_t tcb_bytes;
155: uint8_t tx_threshold;
156: uint8_t tbd_count;
157:
158:
159:
160:
161:
162: } eepro100_tx_t;
163:
164:
165: typedef struct {
166: int16_t status;
167: uint16_t command;
168: uint32_t link;
169: uint32_t rx_buf_addr;
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];
225: uint8_t curpag;
226: uint8_t mult[8];
227: int mmio_index;
228: PCIDevice *pci_dev;
229: VLANClientState *vc;
230: #endif
231: uint8_t scb_stat;
232: uint8_t int_stat;
233: uint32_t region[3];
234: uint8_t macaddr[6];
235: uint32_t statcounter[19];
236: uint16_t mdimem[32];
237: eeprom_t *eeprom;
238: uint32_t device;
239: uint32_t pointer;
240:
241: uint32_t cu_base;
242: uint32_t cu_offset;
243:
244: uint32_t ru_base;
245: uint32_t ru_offset;
246: uint32_t statsaddr;
247: eepro100_stats_t statistics;
248: #if 0
249: uint16_t status;
250: #endif
251:
252:
253: uint8_t configuration[22];
254:
255:
256: uint8_t mem[PCI_MEM_SIZE];
257: } EEPRO100State;
258:
259:
260: static const uint16_t eepro100_mdi_default[] = {
261:
262: 0x3000, 0x780d, 0x02a8, 0x0154, 0x05e1, 0x0000, 0x0000, 0x0000,
263:
264: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
265:
266: 0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
267: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
268: };
269:
270:
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:
281:
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
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:
362: if (stat && (mask & 0x01)) {
363:
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:
373:
374: eepro100_interrupt(s, 0x80);
375: }
376:
377: static void eepro100_cna_interrupt(EEPRO100State * s)
378: {
379:
380: eepro100_interrupt(s, 0x20);
381: }
382:
383: static void eepro100_fr_interrupt(EEPRO100State * s)
384: {
385:
386: eepro100_interrupt(s, 0x40);
387: }
388:
389: #if 0
390: static void eepro100_rnr_interrupt(EEPRO100State * s)
391: {
392:
393: eepro100_interrupt(s, 0x10);
394: }
395: #endif
396:
397: static void eepro100_mdi_interrupt(EEPRO100State * s)
398: {
399:
400: eepro100_interrupt(s, 0x08);
401: }
402:
403: static void eepro100_swi_interrupt(EEPRO100State * s)
404: {
405:
406: eepro100_interrupt(s, 0x04);
407: }
408:
409: #if 0
410: static void eepro100_fcp_interrupt(EEPRO100State * s)
411: {
412:
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:
425: PCI_CONFIG_16(PCI_VENDOR_ID, 0x8086);
426:
427: PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);
428:
429: PCI_CONFIG_16(PCI_COMMAND, 0x0000);
430:
431: PCI_CONFIG_16(PCI_STATUS, 0x2800);
432:
433: PCI_CONFIG_8(PCI_REVISION_ID, 0x08);
434:
435: PCI_CONFIG_8(0x09, 0x00);
436: PCI_CONFIG_8(PCI_SUBCLASS_CODE, 0x00);
437: PCI_CONFIG_8(PCI_CLASS_CODE, 0x02);
438:
439:
440:
441:
442: PCI_CONFIG_8(0x0d, 0x20);
443:
444:
445: #if defined(TARGET_I386)
446:
447:
448: #endif
449: #if 0
450:
451:
452: PCI_CONFIG_32(PCI_BASE_ADDRESS_0,
453: PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_MEM_PREFETCH);
454:
455: PCI_CONFIG_32(PCI_BASE_ADDRESS_1, PCI_ADDRESS_SPACE_IO);
456: #if 0
457:
458: PCI_CONFIG_32(PCI_BASE_ADDRESS_2, 0xfffe0000 | PCI_ADDRESS_SPACE_MEM);
459: #endif
460: #endif
461:
462: PCI_CONFIG_32(0x30, 0x00000000);
463:
464: PCI_CONFIG_8(0x34, 0xdc);
465:
466: PCI_CONFIG_8(0x3d, 1);
467:
468: PCI_CONFIG_8(0x3e, 0x08);
469:
470: PCI_CONFIG_8(0x3f, 0x18);
471:
472: PCI_CONFIG_32(0xdc, 0x7e210001);
473:
474: switch (device) {
475: case i82551:
476:
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:
496: break;
497: case i82559ER:
498:
499: PCI_CONFIG_16(PCI_STATUS, 0x2810);
500: PCI_CONFIG_8(PCI_REVISION_ID, 0x09);
501: break;
502:
503:
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:
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: