[DM9000] Rewrote FIFO, buffering etc
[qemu/mini2440.git] / hw / dm9000.c
blob064cacb5de42be4c548ad99bb53f811a51c035e9
1 /* hw/dm9000.c
3 * DM9000 Ethernet interface
5 * Copyright Daniel Silverstone and Vincent Sanders
7 * This file is under the terms of the GNU General Public
8 * License Version 2
9 */
11 #include <string.h>
12 #include "qemu-common.h"
13 #include "hw/irq.h"
14 #include "net.h"
15 #include "dm9000.h"
17 /* Comment this out if you don't want register debug on stderr */
18 //#define DM9000_DEBUG
20 /* Comment this out if you don't want a packet dump */
21 //#define DM9000_DUMP_FILENAME "/tmp/dm9k_dump"
23 #ifdef DM9000_DEBUG
24 #define DM9000_DBF(X...) fprintf(stderr, X)
25 #else
26 #define DM9000_DBF(X...) if(0) fprintf(stderr, X)
27 #endif
29 #define DM9000_REG_NCR 0x00
30 #define DM9000_NCR_RESET (1 << 0)
32 #define DM9000_REG_NSR 0x01
33 #define DM9000_NSR_TX1END (1 << 2)
34 #define DM9000_NSR_TX2END (1 << 3)
35 #define DM9000_REG_TCR 0x02
36 #define DM9000_TCR_TXREQ (1 << 0)
38 #define DM9000_REG_TSR1 0x03
39 #define DM9000_REG_TSR2 0x04
40 #define DM9000_REG_RCR 0x05
41 #define DM9000_RCR_DIS_LONG (1 << 5) /* RX Discard long frames (>1522) */
42 #define DM9000_RCR_DIS_CRC (1 << 4) /* RX Discard bad CRC */
43 #define DM9000_RCR_ALL (1 << 3) /* RX Pass All Multicast */
44 #define DM9000_RCR_RUNT (1 << 2) /* RX Pass Runt Frames (frame < 64 bytes) */
45 #define DM9000_RCR_PRMSC (1 << 1) /* RX Promiscuous Mode */
46 #define DM9000_RCR_RXEN (1 << 0) /* RX Enabled */
48 #define DM9000_REG_RSR 0x06
49 #define DM9000_RSR_RF (1 << 7) /* RX Runt Frame (frame < 64 bytes) */
50 #define DM9000_RSR_MF (1 << 6) /* RX Multicast Frame */
51 #define DM9000_RSR_FOE (1 << 0) /* RX FIFO overflow */
53 #define DM9000_REG_ROCR 0x07
54 #define DM9000_REG_BPTR 0x08
55 #define DM9000_REG_FCTR 0x09
56 #define DM9000_REG_FCR 0x0A
57 #define DM9000_FCR_TXP0 (1 << 7) /* TX Pause Packet (when empty) */
58 #define DM9000_FCR_TXPF (1 << 6) /* TX Pause Packet (when full) */
59 #define DM9000_FCR_TXPEN (1 << 5) /* Force pause/unpause packets */
60 #define DM9000_FCR_BKPA (1 << 4)
61 #define DM9000_FCR_BKPM (1 << 3)
62 #define DM9000_FCR_RXPS (1 << 2) /* RX Pause Packet Status, latch and read to clear */
63 #define DM9000_FCR_RXPCS (1 << 1) /* RX Pause Packet Current Status */
64 #define DM9000_FCR_FLCE (1 << 0) /* Flow Control Enable */
66 #define DM9000_REG_EPCR 0x0B
67 #define DM9000_REG_EPAR 0x0C
68 #define DM9000_REG_EPDRL 0x0D
69 #define DM9000_REG_EPDRH 0x0E
70 #define DM9000_REG_WCR 0x0F
71 #define DM9000_REG_PAR0 0x10
72 #define DM9000_REG_PAR1 0x11
73 #define DM9000_REG_PAR2 0x12
74 #define DM9000_REG_PAR3 0x13
75 #define DM9000_REG_PAR4 0x14
76 #define DM9000_REG_PAR5 0x15
77 #define DM9000_REG_MAR0 0x16
78 #define DM9000_REG_MAR1 0x17
79 #define DM9000_REG_MAR2 0x18
80 #define DM9000_REG_MAR3 0x19
81 #define DM9000_REG_MAR4 0x1A
82 #define DM9000_REG_MAR5 0x1B
83 #define DM9000_REG_MAR6 0x1C
84 #define DM9000_REG_MAR7 0x1D
85 #define DM9000_REG_GPCR 0x1E
86 #define DM9000_REG_GPR 0x1F
87 #define DM9000_REG_TRPAL 0x22
88 #define DM9000_REG_TRPAH 0x23
89 #define DM9000_REG_RWPAL 0x24
90 #define DM9000_REG_RWPAH 0x25
91 #define DM9000_REG_VIDL 0x28
92 #define DM9000_REG_VIDH 0x29
93 #define DM9000_REG_PIDL 0x2A
94 #define DM9000_REG_PIDH 0x2B
95 #define DM9000_REG_CHIPR 0x2C
96 #define DM9000_REG_SMCR 0x2F
97 #define DM9000_REG_MRCMDX 0xF0
98 #define DM9000_REG_MRCMD 0xF2
99 #define DM9000_REG_MRRL 0xF4
100 #define DM9000_REG_MRRH 0xF5
101 #define DM9000_REG_MWCMDX 0xF6
102 #define DM9000_REG_MWCMD 0xF8
103 #define DM9000_REG_MWRL 0xFA
104 #define DM9000_REG_MWRH 0xFB
105 #define DM9000_REG_TXPLL 0xFC
106 #define DM9000_REG_TXPLH 0xFD
107 #define DM9000_REG_ISR 0xFE
108 #define DM9000_REG_IMR 0xFF
109 #define DM9000_IMR_AUTOWRAP 0x80
112 #define DM9000_MII_READ 0x0C
113 #define DM9000_MII_WRITE 0x0A
115 #define DM9000_MII_REG_BMCR 0x00
116 #define DM9000_MII_REG_STATUS 0x01
117 #define DM9000_MII_REG_PHYID1 0x02
118 #define DM9000_MII_REG_PHYID2 0x03
119 #define DM9000_MII_REG_ANAR 0x04
120 #define DM9000_MII_REG_ANLPAR 0x05
121 #define DM9000_MII_REG_ANER 0x06
122 #define DM9000_MII_REG_DSCR 0x10
123 #define DM9000_MII_REG_DSCSR 0x11
124 #define DM9000_MII_REG_10BTCSR 0x12
126 enum {
127 DM9K_TX_FIFO_START = 0,
128 DM9K_TX_FIFO_SIZE = (3 * 1024),
130 DM9K_RX_FIFO_START = DM9K_TX_FIFO_SIZE,
131 DM9K_RX_FIFO_SIZE = (13 * 1024),
133 DM9K_FIFO_SIZE = (DM9K_TX_FIFO_SIZE + DM9K_RX_FIFO_SIZE)
136 #define DM9K_WRAP_TX_INDEX(_v) ((_v >= DM9K_TX_FIFO_SIZE) ? (_v) - DM9K_TX_FIFO_SIZE : (_v))
137 #define DM9K_WRAP_RX_INDEX(_v) ((_v >= DM9K_FIFO_SIZE) ? (_v) - DM9K_RX_FIFO_SIZE : (_v))
138 /* DM9KNOTE: Assumes 16bit wiring */
139 #define DM9K_CLIP_TX_INDEX(_v) ((_v) & 1 ? DM9K_WRAP_TX_INDEX((_v)+1) : (_v))
140 #define DM9K_CLIP_RX_INDEX(_v) ((_v) & 1 ? DM9K_WRAP_RX_INDEX((_v)+1) : (_v))
142 typedef struct {
143 uint32_t addr; /* address port */
144 uint32_t data; /* data port */
145 VLANClientState *vc;
146 qemu_irq irq;
147 uint8_t macaddr[6];
148 uint8_t mult[8];
150 uint8_t address; /* The internal magical address */
153 * Transmit buffer is the first 3KB,
154 * followed by the receive buffer
156 uint8_t packet_buffer[DM9K_FIFO_SIZE];
158 uint16_t dm9k_trpa;
159 uint16_t dm9k_rwpa; /* TX Read ptr address, RX write ptr address */
161 uint8_t fctr, fcr;
162 uint16_t fc_high_mark;
163 uint16_t fc_low_mark;
165 uint16_t dm9k_mrr;
166 uint16_t dm9k_mwr; /* Read and write address registers */
167 uint16_t dm9k_txpl; /* TX packet length */
169 uint8_t dm9k_imr, dm9k_isr; /* Interrupt mask register and status register*/
170 uint8_t dm9k_ncr, dm9k_nsr; /* Network control register, network status register */
171 uint8_t dm9k_rcr; /* RX Control Register */
172 uint8_t dm9k_rsr; /* RX Status Register */
173 uint8_t dm9k_wcr; /* Wakeup control */
174 uint8_t dm9k_tcr; /* Transmission control register */
175 uint8_t packet_copy_buffer[3 * 1024]; /* packet copy buffer */
176 unsigned int packet_index:1; /* 0 == packet I, 1 == packet II */
178 /* Internal MII PHY state */
179 uint8_t dm9k_epcr; /* EEPROM/PHY control register */
180 uint8_t dm9k_epar; /* EEPROM/PHY address register */
181 uint16_t dm9k_epdr; /* EEPROM/PHY data register */
182 /* MII Regs */
183 uint16_t dm9k_mii_bmcr;
184 uint16_t dm9k_mii_anar;
185 uint16_t dm9k_mii_dscr;
187 } dm9000_state;
190 #ifdef DM9000_DUMP_FILENAME
191 #include <arpa/inet.h>
192 static uint8_t pcap_header[24] = {
193 0xA1, 0xB2, 0xC3, 0xD4, /* TCPDUMP Magic */
194 0x00, 0x02, 0x00, 0x04, /* Major 2, Minor 4 */
195 0x00, 0x00, 0x00, 0x00, /* Timezone offset */
196 0x00, 0x00, 0x00, 0x01, /* Accuracy of timestamps */
197 0x00, 0x00, 0x0C, 0x00, /* Snaplen 3KiB */
198 0x00, 0x00, 0x00, 0x01, /* Ethernet frames */
200 static uint8_t nulls[8] = {0, 0, 0, 0, 0, 0, 0, 0};
201 static void dm9k_dump_packet(uint8_t *buf, uint32_t size)
203 FILE* dm9k_fileh = fopen(DM9000_DUMP_FILENAME, "ab+");
204 unsigned long bsize = htonl(size);
205 DM9000_DBF("Dumping packet at %08x (%d bytes)\n", buf, size);
206 fseek(dm9k_fileh, 0, SEEK_END);
207 if(ftell(dm9k_fileh)==0) fwrite(pcap_header, 1, 24, dm9k_fileh);
208 fwrite(nulls, 1, 8, dm9k_fileh);
209 fwrite(&bsize, 1, 4, dm9k_fileh);
210 fwrite(&bsize, 1, 4, dm9k_fileh);
211 fwrite(buf, 1, size, dm9k_fileh);
212 fclose(dm9k_fileh);
214 #else
215 #define dm9k_dump_packet(X...) do { } while(0)
216 #endif
218 static void hexdump(const void* address, uint32_t len)
220 const unsigned char* p = address;
221 int i, j;
223 for (i = 0; i < len; i += 16) {
224 for (j = 0; j < 16 && i + j < len; j++)
225 fprintf(stderr, "%02x ", p[i + j]);
226 for (; j < 16; j++)
227 fprintf(stderr, " ");
228 fprintf(stderr, " ");
229 for (j = 0; j < 16 && i + j < len; j++)
230 fprintf(stderr, "%c", (p[i + j] < ' ' || p[i + j] > 0x7f) ? '.' : p[i + j]);
231 fprintf(stderr, "\n");
235 static void dm9000_raise_irq(dm9000_state *s)
237 int level = ((s->dm9k_isr & s->dm9k_imr) & 0x03) != 0;
238 // DM9000_DBF("DM9000: Set IRQ level %d\n", level);
239 qemu_set_irq(s->irq, level);
242 static void dm9000_soft_reset_mii(dm9000_state *s)
244 s->dm9k_mii_bmcr = 0x3100; /* 100Mbps, AUTONEG, FULL DUPLEX */
245 s->dm9k_mii_anar = 0x01E1;
246 s->dm9k_mii_dscr = 0x0410;
249 static void dm9000_soft_reset(dm9000_state *s)
251 DM9000_DBF("DM9000: Soft Reset\n");
252 s->dm9k_txpl = 0;
253 s->dm9k_mwr = s->dm9k_trpa = DM9K_TX_FIFO_START;
254 s->dm9k_mrr = s->dm9k_rwpa = DM9K_RX_FIFO_START;
255 s->dm9k_imr = 0;
256 s->dm9k_isr = 0; /* 16 bit mode, no interrupts asserted */
257 s->dm9k_tcr = 0;
258 s->dm9k_rcr = 0;
259 s->dm9k_rsr = 0;
260 s->fcr = 0;
261 s->fctr = (3 << 4) | (8 << 0); // flow control high/low marks
262 s->fc_high_mark = 3 * 1024;
263 s->fc_low_mark = 8 * 1024;
265 s->packet_index = 0;
266 memset(s->packet_buffer, 0, sizeof(s->packet_buffer));
267 memset(s->packet_copy_buffer, 0, sizeof(s->packet_copy_buffer));
268 /* These registers have some bits "unaffected by software reset" */
269 /* Clear the reset bits */
270 s->dm9k_ncr &= 0xA0;
271 s->dm9k_nsr &= 0xD0;
272 /* Claim full duplex */
273 s->dm9k_ncr |= 1<<3;
274 /* Set link status to 1 */
275 s->dm9k_nsr |= 1<<6;
276 /* dm9k_wcr is unaffected or reserved, never reset */
277 /* MII control regs */
278 s->dm9k_epcr = 0x00;
279 s->dm9k_epar = 0x40;
280 /* reset the MII */
281 dm9000_soft_reset_mii(s);
282 dm9000_raise_irq(s); /* Clear any potentially pending IRQ */
285 static void dm9000_hard_reset(dm9000_state *s)
287 s->dm9k_ncr = 0x00;
288 s->dm9k_nsr = 0x00;
289 s->dm9k_wcr = 0x00;
290 dm9000_soft_reset(s);
293 static void dm9000_do_transmit(dm9000_state *s) {
294 uint16_t idx, cnt, tptr;
295 idx = s->dm9k_trpa;
297 cnt = s->dm9k_txpl;
298 if (cnt > DM9K_TX_FIFO_SIZE)
299 cnt = DM9K_TX_FIFO_SIZE; /* HARD CAP AT 3KiB */
301 tptr = 0;
302 while (cnt--) {
303 s->packet_copy_buffer[tptr++] = s->packet_buffer[idx];
304 idx = DM9K_WRAP_TX_INDEX(idx+1);
307 #ifdef DM9000_DEBUG
309 uint8_t *buf = &s->packet_copy_buffer[6];
310 DM9000_DBF("TX_Packet: %02x:%02x:%02x:%02x:%02x:%02x %d bytes from %04x\n",
311 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],
312 tptr, idx);
313 // hexdump(s->packet_copy_buffer, tptr);
315 #endif
317 s->dm9k_trpa = DM9K_CLIP_TX_INDEX(idx);
318 dm9k_dump_packet(s->packet_copy_buffer, s->dm9k_txpl);
319 /* We have the copy buffer, now we do the transmit */
320 qemu_send_packet(s->vc, s->packet_copy_buffer, s->dm9k_txpl);
322 /* Clear the "please xmit" bit */
323 s->dm9k_tcr &= ~DM9000_TCR_TXREQ;
324 /* Set the TXEND bit */
325 s->dm9k_nsr |= 1 << (2 + s->packet_index);
326 DM9000_DBF("TX: NSR=%02x PI=%d\n", s->dm9k_nsr, s->packet_index);
327 /* Claim a TX complete IRQ */
328 s->dm9k_isr |= 0x02; /* Packet transmitted latch */
329 /* And flip the next-packet bit */
330 s->packet_index++;
332 dm9000_raise_irq(s);
335 static void dm9000_mii_read(dm9000_state *s)
337 int mii_reg = (s->dm9k_epar) & 0x3f;
338 uint16_t ret = 0;
339 switch(mii_reg) {
340 case DM9000_MII_REG_BMCR:
341 ret = s->dm9k_mii_bmcr;
342 break;
343 case DM9000_MII_REG_STATUS:
344 ret = 0x782D; /* No 100/T4, Can 100/FD, Can 100/HD, Can 10/FD, Can 10/HD,
345 * No Preamble suppression, Autoneg complete, No remote fault,
346 * Can autoneg, link up, no jabber, extended capability */
347 break;
348 case DM9000_MII_REG_PHYID1:
349 ret = 0x0181;
350 break;
351 case DM9000_MII_REG_PHYID2:
352 ret = 0xB8C0;
353 break;
354 case DM9000_MII_REG_ANAR:
355 ret = s->dm9k_mii_anar;
356 break;
357 case DM9000_MII_REG_ANLPAR:
358 ret = 0x0400;
359 break;
360 case DM9000_MII_REG_ANER:
361 ret = 0x0001;
362 break;
363 case DM9000_MII_REG_DSCR:
364 ret = s->dm9k_mii_dscr;
365 break;
366 case DM9000_MII_REG_DSCSR:
367 ret = 0xF008;
368 break;
369 case DM9000_MII_REG_10BTCSR:
370 ret = 0x7800;
371 default:
372 printf("%s: Bad register 0x%lx\n", __FUNCTION__, (unsigned long)mii_reg);
374 s->dm9k_epdr = ret;
375 // DM9000_DBF("DM9000:MIIPHY: Read of MII reg %d gives %04x\n", mii_reg, s->dm9k_epdr);
378 static void dm9000_mii_write(dm9000_state *s)
380 int mii_reg = (s->dm9k_epar) & 0x3f;
381 DM9000_DBF("DM9000:MIIPHY: Write of MII reg %d value %04x\n", mii_reg, s->dm9k_epdr);
382 switch(mii_reg) {
383 case DM9000_MII_REG_BMCR:
384 s->dm9k_mii_bmcr = (s->dm9k_epdr &~0x8000);
385 if( s->dm9k_epdr & 0x8000 ) dm9000_soft_reset_mii(s);
386 break;
387 case DM9000_MII_REG_ANAR:
388 s->dm9k_mii_anar = s->dm9k_epdr;
389 break;
390 case DM9000_MII_REG_DSCR:
391 s->dm9k_mii_dscr = s->dm9k_epdr & ~0x0008;
392 break;
393 default:
394 printf("%s: Bad register 0x%lx=%4x\n", __FUNCTION__, (unsigned long)mii_reg, s->dm9k_epdr);
398 static void dm9000_write(void *opaque, target_phys_addr_t address,
399 uint32_t value)
401 dm9000_state *s = (dm9000_state *)opaque;
402 #ifdef DM9000_DEBUG
403 int suppress_debug = 0;
404 #endif
406 if (address == s->addr) {
407 // if( (value != DM9000_REG_MRCMD) && (value != DM9000_REG_MWCMD) )
408 // DM9000_DBF("DM9000: Address set to 0x%02x\n", value);
409 s->address = value;
410 return;
413 switch(s->address) {
414 case DM9000_REG_NCR:
415 s->dm9k_ncr = value & 0xDF;
416 if (s->dm9k_ncr & DM9000_NCR_RESET)
417 dm9000_soft_reset(s);
418 break;
419 case DM9000_REG_NSR:
420 s->dm9k_nsr &= ~(value & 0x2C);
421 break;
422 case DM9000_REG_TCR:
423 s->dm9k_tcr = value & 0xFF;
424 if ( value & DM9000_TCR_TXREQ )
425 dm9000_do_transmit(s);
426 break;
427 case DM9000_REG_EPCR:
428 s->dm9k_epcr = value & 0xFF;
429 if( value & DM9000_MII_READ )
430 dm9000_mii_read(s);
431 else if( value & DM9000_MII_WRITE )
432 dm9000_mii_write(s);
433 break;
434 case DM9000_REG_RCR:
435 s->dm9k_rcr = value & 0xFF;
436 break;
438 case DM9000_REG_BPTR: /* can be ignored */
439 break;
441 case DM9000_REG_FCTR: {/* 0x09 Flow Control Threshold Register */
442 s->fc_high_mark = ((value >> 4) & 0xf) * 1024; // emit a pause packet time=0xffff
443 s->fc_low_mark = ((value) & 0xf) * 1024; // emit an unpause packet time=0x0000
444 s->fctr = value;
445 } break;
447 case DM9000_REG_FCR: /* 0x0a Flow Control Register */
448 s->fcr = value;
449 break;
451 case DM9000_REG_EPAR:
452 s->dm9k_epar = value & 0xFF;
453 break;
454 case DM9000_REG_EPDRL:
455 s->dm9k_epdr &= 0xFF00;
456 s->dm9k_epdr |= value & 0xFF;
457 break;
458 case DM9000_REG_EPDRH:
459 s->dm9k_epdr &= 0xFF;
460 s->dm9k_epdr |= (value & 0xFF) << 8;
461 break;
462 case DM9000_REG_PAR0 ... DM9000_REG_PAR5:
463 /* MAC address is set by the QEMU Nic */
464 s->macaddr[s->address - DM9000_REG_PAR0] = value;
465 break;
466 case DM9000_REG_MAR0 ... DM9000_REG_MAR7:
467 /* Multicast address is ignored */
468 s->mult[s->address - DM9000_REG_MAR0] = value;
469 break;
470 case DM9000_REG_GPCR:
471 case DM9000_REG_GPR: /* General purpose reg (GPIOs, LED?) */
472 break;
473 case DM9000_REG_SMCR:
474 if (value)
475 printf("%s: something playing with special mode ? 0x%lx=%x\n", __FUNCTION__, (unsigned long)s->address, value);
476 break;
477 case DM9000_REG_MRRL:
478 s->dm9k_mrr &= 0xFF00;
479 s->dm9k_mrr |= value & 0xFF;
480 break;
481 case DM9000_REG_MRRH:
482 s->dm9k_mrr &= 0xFF;
483 s->dm9k_mrr |= (value & 0xFF) << 8;
484 break;
485 case DM9000_REG_MWCMDX:
486 case DM9000_REG_MWCMD:
487 /* DM9KNOTE: This assumes a 16bit wide wiring */
488 s->packet_buffer[s->dm9k_mwr] = value & 0xFF;
489 s->packet_buffer[s->dm9k_mwr + 1] = (value >> 8) & 0xFF;
490 if (s->address == DM9000_REG_MWCMD) {
491 if (s->dm9k_imr & DM9000_IMR_AUTOWRAP)
492 s->dm9k_mwr = DM9K_WRAP_TX_INDEX(s->dm9k_mwr + 2);
493 else if (s->dm9k_mwr + 2 < DM9K_TX_FIFO_SIZE) // clip it
494 s->dm9k_mwr += 2;
496 #ifdef DM9000_DEBUG
497 suppress_debug = 1;
498 #endif
499 break;
500 case DM9000_REG_MWRL:
501 s->dm9k_mwr &= 0xFF00;
502 s->dm9k_mwr |= value & 0xFF;
503 break;
504 case DM9000_REG_MWRH:
505 s->dm9k_mwr &= 0xFF;
506 s->dm9k_mwr |= (value & 0xFF) << 8;
507 break;
508 case DM9000_REG_TXPLL:
509 s->dm9k_txpl &= 0xFF00;
510 s->dm9k_txpl |= value & 0xFF;
511 break;
512 case DM9000_REG_TXPLH:
513 s->dm9k_txpl &= 0xFF;
514 s->dm9k_txpl |= (value & 0xFF) << 8;
515 break;
516 case DM9000_REG_ISR:
517 s->dm9k_isr &= ~(value & 0x0F);
518 dm9000_raise_irq(s);
519 break;
520 case DM9000_REG_IMR:
521 if( !(s->dm9k_imr & DM9000_IMR_AUTOWRAP) && (value & DM9000_IMR_AUTOWRAP) )
522 s->dm9k_mrr = 0x0C00 | (s->dm9k_mrr & 0xFF);
523 s->dm9k_imr = value & 0xFF;
524 dm9000_raise_irq(s);
525 break;
526 default:
527 printf("%s: Bad register 0x%lx=%x\n", __FUNCTION__, (unsigned long)s->address, value);
529 #if 0 // def DM9000_DEBUG
530 if(!suppress_debug) DM9000_DBF("DM9000: Write value %02x=%04x\n", s->address, value);
531 #endif
534 static uint32_t dm9000_read(void *opaque, target_phys_addr_t address)
536 dm9000_state *s = (dm9000_state *)opaque;
537 uint32_t ret = 0;
538 #ifdef DM9000_DEBUG
539 int suppress_debug = 0;
540 #endif
542 if (address == s->addr)
543 return s->address;
544 switch(s->address) {
545 case DM9000_REG_NCR:
546 ret = s->dm9k_ncr;
547 break;
548 case DM9000_REG_NSR:
549 ret = s->dm9k_nsr;
550 /* Note, TX1END and TX2END are *CLEAR ON READ* */
551 s->dm9k_nsr &= ~(DM9000_NSR_TX1END | DM9000_NSR_TX2END);
552 break;
553 case DM9000_REG_TCR:
554 ret = s->dm9k_tcr;
555 break;
556 case DM9000_REG_TSR1:
557 case DM9000_REG_TSR2:
558 ret = 0x00; /* No error, yay! */
559 break;
560 case DM9000_REG_EPCR:
561 ret = s->dm9k_epcr;
562 break;
563 case DM9000_REG_RCR:
564 ret = s->dm9k_rcr;
565 break;
566 case DM9000_REG_RSR:
567 ret = s->dm9k_rsr;
568 break;
569 case DM9000_REG_EPAR:
570 ret = s->dm9k_epar;
571 break;
572 case DM9000_REG_EPDRL:
573 ret = s->dm9k_epdr & 0xFF;
574 break;
575 case DM9000_REG_EPDRH:
576 ret = (s->dm9k_epdr >> 8) & 0xFF;
577 break;
578 case DM9000_REG_PAR0...DM9000_REG_PAR5:
579 ret = s->macaddr[s->address - DM9000_REG_PAR0];
580 break;
581 case DM9000_REG_MAR0...DM9000_REG_MAR7:
582 /* Multicast address is ignored */
583 break;
584 case DM9000_REG_TRPAL:
585 ret = s->dm9k_trpa & 0xFF;
586 break;
587 case DM9000_REG_TRPAH:
588 ret = s->dm9k_trpa >> 8;
589 break;
590 case DM9000_REG_RWPAL:
591 ret = s->dm9k_rwpa & 0xFF;
592 break;
593 case DM9000_REG_RWPAH:
594 ret = s->dm9k_rwpa >> 8;
595 break;
596 case DM9000_REG_VIDL:
597 ret = 0x46;
598 break;
599 case DM9000_REG_VIDH:
600 ret = 0x0A;
601 break;
602 case DM9000_REG_PIDL:
603 ret = 0x00;
604 break;
605 case DM9000_REG_PIDH:
606 ret = 0x90;
607 break;
608 case DM9000_REG_CHIPR:
609 ret = 0x00;
610 break;
611 case DM9000_REG_MRCMDX:
612 case DM9000_REG_MRCMD:
613 /* DM9KNOTE: This assumes a 16bit wide wiring */
614 ret = s->packet_buffer[s->dm9k_mrr];
615 ret |= s->packet_buffer[s->dm9k_mrr + 1] << 8;
616 #if 0
617 if (s->dm9k_mrr == s->dm9k_rwpa)
618 printf("(%04x=%04x) ", s->dm9k_mrr, ret);
619 else
620 printf("[%04x=%04x] ", s->dm9k_mrr, ret);
621 fflush(stdout);
622 #endif
623 if( s->address == DM9000_REG_MRCMD ) {
624 if( s->dm9k_imr & DM9000_IMR_AUTOWRAP )
625 s->dm9k_mrr = DM9K_WRAP_RX_INDEX(s->dm9k_mrr + 2);
626 else if (s->dm9k_mrr + 2 < DM9K_FIFO_SIZE) // clip it
627 s->dm9k_mrr += 2;
628 } else {
629 // drive read the fifo looking for a 0x01 to indicate a packet is there, so we just return
630 // it a zero if there is nothing to read
631 if (s->dm9k_mrr == s->dm9k_rwpa)
632 ret = 0;
634 #ifdef DM9000_DEBUG
635 if (s->address==DM9000_REG_MRCMD)
636 suppress_debug = 1;
637 #endif
638 break;
639 case DM9000_REG_MRRL:
640 ret = s->dm9k_mrr & 0xFF;
641 break;
642 case DM9000_REG_MRRH:
643 ret = s->dm9k_mrr >> 8;
644 break;
645 case DM9000_REG_MWRL:
646 ret = s->dm9k_mwr & 0xFF;
647 break;
648 case DM9000_REG_MWRH:
649 ret = s->dm9k_mwr >> 8;
650 break;
651 case DM9000_REG_TXPLL:
652 ret = s->dm9k_txpl & 0xFF;
653 break;
654 case DM9000_REG_TXPLH:
655 ret = s->dm9k_txpl >> 8;
656 break;
657 case DM9000_REG_ISR:
658 ret = s->dm9k_isr;
659 break;
660 case DM9000_REG_IMR:
661 ret = s->dm9k_imr;
662 break;
663 default:
664 ret = 0;
667 #if 0 // def DM9000_DEBUG
668 if(!suppress_debug) DM9000_DBF("DM9000: Read gives: %04x\n", ret);
669 #endif
670 return ret;
675 static int dm9000_can_receive(void *opaque)
677 dm9000_state *s = (dm9000_state *)opaque;
678 uint16_t rx_space;
679 if( s->dm9k_rwpa < s->dm9k_mrr )
680 rx_space = s->dm9k_mrr - s->dm9k_rwpa;
681 else
682 rx_space = DM9K_RX_FIFO_SIZE - (s->dm9k_rwpa - s->dm9k_mrr);
683 DM9000_DBF("DM9000:RX_Packet: Asked about RX, rwpa=%d mrr=%d => space is %d bytes\n",
684 s->dm9k_rwpa, s->dm9k_mrr, rx_space);
685 if (rx_space > 2048) return 1;
686 return 0;
689 #define POLYNOMIAL 0x04c11db6
691 /* From FreeBSD */
692 /* XXX: optimize */
693 static int compute_mcast_idx(const uint8_t *ep)
695 uint32_t crc;
696 int carry, i, j;
697 uint8_t b;
699 crc = 0xffffffff;
700 for (i = 0; i < 6; i++) {
701 b = *ep++;
702 for (j = 0; j < 8; j++) {
703 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
704 crc <<= 1;
705 b >>= 1;
706 if (carry)
707 crc = ((crc ^ POLYNOMIAL) | carry);
710 return (crc >> 26);
713 static void dm9000_receive(void *opaque, const uint8_t *buf, int size)
715 dm9000_state *s = (dm9000_state *)opaque;
716 uint16_t rxptr = s->dm9k_rwpa, idx;
717 unsigned int mcast_idx = 0;
718 int pad = 0;
720 if (!(s->dm9k_rcr & DM9000_RCR_RXEN))
721 return;
722 s->dm9k_rsr = 0;
724 if (!(s->dm9k_rcr & DM9000_RCR_PRMSC)) {
725 if (buf[0] & 0x01) {
726 /* multi/broadcast */
727 if (!(s->dm9k_rcr & DM9000_RCR_ALL)) {
728 mcast_idx = compute_mcast_idx(buf);
729 if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
730 return;
731 s->dm9k_rsr |= DM9000_RSR_MF;
733 } else if (!memcmp(buf, s->macaddr, 6)) {
734 /* match */
735 } else {
736 return;
738 if (size < 64 && !(s->dm9k_rcr & DM9000_RCR_RUNT)) {
739 // printf("rcr %02x RUNT %d\n", s->dm9k_rcr, size);
740 s->dm9k_rsr |= DM9000_RSR_RF;
741 // return;
743 if (size > 1522 && (s->dm9k_rcr & DM9000_RCR_DIS_LONG))
744 return;
747 DM9000_DBF("DM9000:RX_Packet: %02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x : %d bytes into buffer at %04x [RCR %02x]\n",
748 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],
749 buf[6],buf[7],buf[8],buf[9],buf[10],buf[11],
750 size, rxptr, s->dm9k_rcr);
751 dm9k_dump_packet(buf, size);
754 * apparently even runt frames are padded to 64
756 if (size < 64)
757 pad = 64 - size;
759 rxptr = DM9K_CLIP_RX_INDEX(rxptr);
760 /* store header */
761 s->packet_buffer[rxptr] = 0x01; /* Packet read */
762 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
763 s->packet_buffer[rxptr] = 0x00; /* Status OK */
764 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
765 s->packet_buffer[rxptr] = (size+pad) & 0xFF; /* Size LOW */
766 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
767 s->packet_buffer[rxptr] = ((size+pad) >> 8) & 0xff; /* Size HIGH */
768 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
770 for (idx = 0; idx < size; idx++) {
771 s->packet_buffer[rxptr] = *buf++;
772 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
774 while (pad--) {
775 s->packet_buffer[rxptr] = 0;
776 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
779 s->dm9k_rwpa = DM9K_CLIP_RX_INDEX(rxptr);
780 s->dm9k_isr |= 0x01; /* RX interrupt, yay */
781 dm9000_raise_irq(s);
785 static CPUReadMemoryFunc *dm9000_readfn[] = {
786 dm9000_read,
787 dm9000_read,
788 dm9000_read
791 static CPUWriteMemoryFunc *dm9000_writefn[] = {
792 dm9000_write,
793 dm9000_write,
794 dm9000_write
797 /* initialises a dm9000 ethernet controller
798 * The dm9k has a single 16bit wide address and data port through which all
799 * operations are multiplexed, there is a single IRQ
801 void dm9000_init(NICInfo *nd, target_phys_addr_t base_addr,
802 uint32_t addr_offset, uint32_t data_offset,
803 qemu_irq irq)
805 dm9000_state *s;
806 int iomemtype;
808 s = (dm9000_state *)qemu_mallocz(sizeof(dm9000_state));
809 iomemtype = cpu_register_io_memory(0, dm9000_readfn,
810 dm9000_writefn, s);
811 cpu_register_physical_memory(base_addr, MAX(addr_offset, data_offset) + 4, iomemtype);
812 s->addr = addr_offset;
813 s->data = data_offset;
814 s->irq = irq;
815 memcpy(s->macaddr, nd->macaddr, 6);
816 memset(s->mult, 0xff, 8);
819 uint8_t * buf = s->macaddr;
820 printf("DM9000: INIT QEMU MAC : %02x:%02x:%02x:%02x:%02x:%02x\n",
821 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);
824 dm9000_hard_reset(s);
826 s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
827 dm9000_receive, dm9000_can_receive, s);
828 qemu_format_nic_info_str(s->vc, s->macaddr);