3 * DM9000 Ethernet interface
5 * Copyright Daniel Silverstone and Vincent Sanders
7 * This file is under the terms of the GNU General Public
12 #include "qemu-common.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"
24 #define DM9000_DBF(X...) fprintf(stderr, X)
26 #define DM9000_DBF(X...) if(0) fprintf(stderr, X)
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
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))
143 uint32_t addr
; /* address port */
144 uint32_t data
; /* data port */
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
];
159 uint16_t dm9k_rwpa
; /* TX Read ptr address, RX write ptr address */
162 uint16_t fc_high_mark
;
163 uint16_t fc_low_mark
;
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 */
183 uint16_t dm9k_mii_bmcr
;
184 uint16_t dm9k_mii_anar
;
185 uint16_t dm9k_mii_dscr
;
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
);
215 #define dm9k_dump_packet(X...) do { } while(0)
218 static void hexdump(const void* address
, uint32_t len
)
220 const unsigned char* p
= address
;
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
]);
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");
253 s
->dm9k_mwr
= s
->dm9k_trpa
= DM9K_TX_FIFO_START
;
254 s
->dm9k_mrr
= s
->dm9k_rwpa
= DM9K_RX_FIFO_START
;
256 s
->dm9k_isr
= 0; /* 16 bit mode, no interrupts asserted */
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;
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 */
272 /* Claim full duplex */
274 /* Set link status to 1 */
276 /* dm9k_wcr is unaffected or reserved, never reset */
277 /* MII control regs */
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
)
290 dm9000_soft_reset(s
);
293 static void dm9000_do_transmit(dm9000_state
*s
) {
294 uint16_t idx
, cnt
, tptr
;
298 if (cnt
> DM9K_TX_FIFO_SIZE
)
299 cnt
= DM9K_TX_FIFO_SIZE
; /* HARD CAP AT 3KiB */
303 s
->packet_copy_buffer
[tptr
++] = s
->packet_buffer
[idx
];
304 idx
= DM9K_WRAP_TX_INDEX(idx
+1);
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],
313 // hexdump(s->packet_copy_buffer, tptr);
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 */
335 static void dm9000_mii_read(dm9000_state
*s
)
337 int mii_reg
= (s
->dm9k_epar
) & 0x3f;
340 case DM9000_MII_REG_BMCR
:
341 ret
= s
->dm9k_mii_bmcr
;
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 */
348 case DM9000_MII_REG_PHYID1
:
351 case DM9000_MII_REG_PHYID2
:
354 case DM9000_MII_REG_ANAR
:
355 ret
= s
->dm9k_mii_anar
;
357 case DM9000_MII_REG_ANLPAR
:
360 case DM9000_MII_REG_ANER
:
363 case DM9000_MII_REG_DSCR
:
364 ret
= s
->dm9k_mii_dscr
;
366 case DM9000_MII_REG_DSCSR
:
369 case DM9000_MII_REG_10BTCSR
:
372 printf("%s: Bad register 0x%lx\n", __FUNCTION__
, (unsigned long)mii_reg
);
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
);
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
);
387 case DM9000_MII_REG_ANAR
:
388 s
->dm9k_mii_anar
= s
->dm9k_epdr
;
390 case DM9000_MII_REG_DSCR
:
391 s
->dm9k_mii_dscr
= s
->dm9k_epdr
& ~0x0008;
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
,
401 dm9000_state
*s
= (dm9000_state
*)opaque
;
403 int suppress_debug
= 0;
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);
415 s
->dm9k_ncr
= value
& 0xDF;
416 if (s
->dm9k_ncr
& DM9000_NCR_RESET
)
417 dm9000_soft_reset(s
);
420 s
->dm9k_nsr
&= ~(value
& 0x2C);
423 s
->dm9k_tcr
= value
& 0xFF;
424 if ( value
& DM9000_TCR_TXREQ
)
425 dm9000_do_transmit(s
);
427 case DM9000_REG_EPCR
:
428 s
->dm9k_epcr
= value
& 0xFF;
429 if( value
& DM9000_MII_READ
)
431 else if( value
& DM9000_MII_WRITE
)
435 s
->dm9k_rcr
= value
& 0xFF;
438 case DM9000_REG_BPTR
: /* can be ignored */
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
447 case DM9000_REG_FCR
: /* 0x0a Flow Control Register */
451 case DM9000_REG_EPAR
:
452 s
->dm9k_epar
= value
& 0xFF;
454 case DM9000_REG_EPDRL
:
455 s
->dm9k_epdr
&= 0xFF00;
456 s
->dm9k_epdr
|= value
& 0xFF;
458 case DM9000_REG_EPDRH
:
459 s
->dm9k_epdr
&= 0xFF;
460 s
->dm9k_epdr
|= (value
& 0xFF) << 8;
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
;
466 case DM9000_REG_MAR0
... DM9000_REG_MAR7
:
467 /* Multicast address is ignored */
468 s
->mult
[s
->address
- DM9000_REG_MAR0
] = value
;
470 case DM9000_REG_GPCR
:
471 case DM9000_REG_GPR
: /* General purpose reg (GPIOs, LED?) */
473 case DM9000_REG_SMCR
:
475 printf("%s: something playing with special mode ? 0x%lx=%x\n", __FUNCTION__
, (unsigned long)s
->address
, value
);
477 case DM9000_REG_MRRL
:
478 s
->dm9k_mrr
&= 0xFF00;
479 s
->dm9k_mrr
|= value
& 0xFF;
481 case DM9000_REG_MRRH
:
483 s
->dm9k_mrr
|= (value
& 0xFF) << 8;
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
500 case DM9000_REG_MWRL
:
501 s
->dm9k_mwr
&= 0xFF00;
502 s
->dm9k_mwr
|= value
& 0xFF;
504 case DM9000_REG_MWRH
:
506 s
->dm9k_mwr
|= (value
& 0xFF) << 8;
508 case DM9000_REG_TXPLL
:
509 s
->dm9k_txpl
&= 0xFF00;
510 s
->dm9k_txpl
|= value
& 0xFF;
512 case DM9000_REG_TXPLH
:
513 s
->dm9k_txpl
&= 0xFF;
514 s
->dm9k_txpl
|= (value
& 0xFF) << 8;
517 s
->dm9k_isr
&= ~(value
& 0x0F);
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;
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
);
534 static uint32_t dm9000_read(void *opaque
, target_phys_addr_t address
)
536 dm9000_state
*s
= (dm9000_state
*)opaque
;
539 int suppress_debug
= 0;
542 if (address
== s
->addr
)
550 /* Note, TX1END and TX2END are *CLEAR ON READ* */
551 s
->dm9k_nsr
&= ~(DM9000_NSR_TX1END
| DM9000_NSR_TX2END
);
556 case DM9000_REG_TSR1
:
557 case DM9000_REG_TSR2
:
558 ret
= 0x00; /* No error, yay! */
560 case DM9000_REG_EPCR
:
569 case DM9000_REG_EPAR
:
572 case DM9000_REG_EPDRL
:
573 ret
= s
->dm9k_epdr
& 0xFF;
575 case DM9000_REG_EPDRH
:
576 ret
= (s
->dm9k_epdr
>> 8) & 0xFF;
578 case DM9000_REG_PAR0
...DM9000_REG_PAR5
:
579 ret
= s
->macaddr
[s
->address
- DM9000_REG_PAR0
];
581 case DM9000_REG_MAR0
...DM9000_REG_MAR7
:
582 /* Multicast address is ignored */
584 case DM9000_REG_TRPAL
:
585 ret
= s
->dm9k_trpa
& 0xFF;
587 case DM9000_REG_TRPAH
:
588 ret
= s
->dm9k_trpa
>> 8;
590 case DM9000_REG_RWPAL
:
591 ret
= s
->dm9k_rwpa
& 0xFF;
593 case DM9000_REG_RWPAH
:
594 ret
= s
->dm9k_rwpa
>> 8;
596 case DM9000_REG_VIDL
:
599 case DM9000_REG_VIDH
:
602 case DM9000_REG_PIDL
:
605 case DM9000_REG_PIDH
:
608 case DM9000_REG_CHIPR
:
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;
617 if (s
->dm9k_mrr
== s
->dm9k_rwpa
)
618 printf("(%04x=%04x) ", s
->dm9k_mrr
, ret
);
620 printf("[%04x=%04x] ", s
->dm9k_mrr
, ret
);
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
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
)
635 if (s
->address
==DM9000_REG_MRCMD
)
639 case DM9000_REG_MRRL
:
640 ret
= s
->dm9k_mrr
& 0xFF;
642 case DM9000_REG_MRRH
:
643 ret
= s
->dm9k_mrr
>> 8;
645 case DM9000_REG_MWRL
:
646 ret
= s
->dm9k_mwr
& 0xFF;
648 case DM9000_REG_MWRH
:
649 ret
= s
->dm9k_mwr
>> 8;
651 case DM9000_REG_TXPLL
:
652 ret
= s
->dm9k_txpl
& 0xFF;
654 case DM9000_REG_TXPLH
:
655 ret
= s
->dm9k_txpl
>> 8;
667 #if 0 // def DM9000_DEBUG
668 if(!suppress_debug
) DM9000_DBF("DM9000: Read gives: %04x\n", ret
);
675 static int dm9000_can_receive(void *opaque
)
677 dm9000_state
*s
= (dm9000_state
*)opaque
;
679 if( s
->dm9k_rwpa
< s
->dm9k_mrr
)
680 rx_space
= s
->dm9k_mrr
- s
->dm9k_rwpa
;
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;
689 #define POLYNOMIAL 0x04c11db6
693 static int compute_mcast_idx(const uint8_t *ep
)
700 for (i
= 0; i
< 6; i
++) {
702 for (j
= 0; j
< 8; j
++) {
703 carry
= ((crc
& 0x80000000L
) ? 1 : 0) ^ (b
& 0x01);
707 crc
= ((crc
^ POLYNOMIAL
) | carry
);
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;
720 if (!(s
->dm9k_rcr
& DM9000_RCR_RXEN
))
724 if (!(s
->dm9k_rcr
& DM9000_RCR_PRMSC
)) {
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))))
731 s
->dm9k_rsr
|= DM9000_RSR_MF
;
733 } else if (!memcmp(buf
, s
->macaddr
, 6)) {
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
;
743 if (size
> 1522 && (s
->dm9k_rcr
& DM9000_RCR_DIS_LONG
))
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
759 rxptr
= DM9K_CLIP_RX_INDEX(rxptr
);
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);
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 */
785 static CPUReadMemoryFunc
*dm9000_readfn
[] = {
791 static CPUWriteMemoryFunc
*dm9000_writefn
[] = {
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
,
808 s
= (dm9000_state
*)qemu_mallocz(sizeof(dm9000_state
));
809 iomemtype
= cpu_register_io_memory(0, dm9000_readfn
,
811 cpu_register_physical_memory(base_addr
, MAX(addr_offset
, data_offset
) + 4, iomemtype
);
812 s
->addr
= addr_offset
;
813 s
->data
= data_offset
;
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
);