[DM9000] Fixed interupts, now fully working
[qemu/mini2440.git] / hw / dm9000.c
blobd608cba6872f259356d495b943a09342446996ec
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_NCR_EXT_PHY (1<<7)
33 #define DM9000_NCR_WAKEEN (1<<6)
34 #define DM9000_NCR_FCOL (1<<4)
35 #define DM9000_NCR_FDX (1<<3)
36 #define DM9000_NCR_LBK (3<<1)
38 #define DM9000_NCR_RESETPROTECT (DM9000_NCR_EXT_PHY | DM9000_NCR_WAKEEN)
40 #define DM9000_REG_NSR 0x01
42 #define DM9000_NSR_SPEED (1<<7)
43 #define DM9000_NSR_LINKST (1<<6)
44 #define DM9000_NSR_WAKEST (1<<5)
45 #define DM9000_NSR_TX2END (1<<3)
46 #define DM9000_NSR_TX1END (1<<2)
47 #define DM9000_NSR_RXOV (1<<1)
49 #define DM9000_NSR_RESETPROTECT (DM9000_NSR_WAKEST)
50 #define DM9000_NSR_READONLY (DM9000_NSR_SPEED|DM9000_NSR_LINKST|(1<<4)|DM9000_NSR_RXOV|(1<<0))
52 #define DM9000_REG_TCR 0x02
53 #define DM9000_TCR_TXREQ (1 << 0)
55 #define DM9000_REG_TSR1 0x03
56 #define DM9000_REG_TSR2 0x04
57 #define DM9000_REG_RCR 0x05
58 #define DM9000_RCR_DIS_LONG (1 << 5) /* RX Discard long frames (>1522) */
59 #define DM9000_RCR_DIS_CRC (1 << 4) /* RX Discard bad CRC */
60 #define DM9000_RCR_ALL (1 << 3) /* RX Pass All Multicast */
61 #define DM9000_RCR_RUNT (1 << 2) /* RX Pass Runt Frames (frame < 64 bytes) */
62 #define DM9000_RCR_PRMSC (1 << 1) /* RX Promiscuous Mode */
63 #define DM9000_RCR_RXEN (1 << 0) /* RX Enabled */
65 #define DM9000_REG_RSR 0x06
66 #define DM9000_RSR_RF (1 << 7) /* RX Runt Frame (frame < 64 bytes) */
67 #define DM9000_RSR_MF (1 << 6) /* RX Multicast Frame */
68 #define DM9000_RSR_FOE (1 << 0) /* RX FIFO overflow */
70 #define DM9000_REG_ROCR 0x07
71 #define DM9000_REG_BPTR 0x08
72 #define DM9000_REG_FCTR 0x09
73 #define DM9000_REG_FCR 0x0A
74 #define DM9000_FCR_TXP0 (1 << 7) /* TX Pause Packet (when empty) */
75 #define DM9000_FCR_TXPF (1 << 6) /* TX Pause Packet (when full) */
76 #define DM9000_FCR_TXPEN (1 << 5) /* Force pause/unpause packets */
77 #define DM9000_FCR_BKPA (1 << 4)
78 #define DM9000_FCR_BKPM (1 << 3)
79 #define DM9000_FCR_RXPS (1 << 2) /* RX Pause Packet Status, latch and read to clear */
80 #define DM9000_FCR_RXPCS (1 << 1) /* RX Pause Packet Current Status */
81 #define DM9000_FCR_FLCE (1 << 0) /* Flow Control Enable */
83 #define DM9000_REG_EPCR 0x0B
84 #define DM9000_REG_EPAR 0x0C
85 #define DM9000_REG_EPDRL 0x0D
86 #define DM9000_REG_EPDRH 0x0E
87 #define DM9000_REG_WCR 0x0F
88 #define DM9000_REG_PAR0 0x10
89 #define DM9000_REG_PAR1 0x11
90 #define DM9000_REG_PAR2 0x12
91 #define DM9000_REG_PAR3 0x13
92 #define DM9000_REG_PAR4 0x14
93 #define DM9000_REG_PAR5 0x15
94 #define DM9000_REG_MAR0 0x16
95 #define DM9000_REG_MAR1 0x17
96 #define DM9000_REG_MAR2 0x18
97 #define DM9000_REG_MAR3 0x19
98 #define DM9000_REG_MAR4 0x1A
99 #define DM9000_REG_MAR5 0x1B
100 #define DM9000_REG_MAR6 0x1C
101 #define DM9000_REG_MAR7 0x1D
102 #define DM9000_REG_GPCR 0x1E
103 #define DM9000_REG_GPR 0x1F
104 #define DM9000_REG_TRPAL 0x22
105 #define DM9000_REG_TRPAH 0x23
106 #define DM9000_REG_RWPAL 0x24
107 #define DM9000_REG_RWPAH 0x25
108 #define DM9000_REG_VIDL 0x28
109 #define DM9000_REG_VIDH 0x29
110 #define DM9000_REG_PIDL 0x2A
111 #define DM9000_REG_PIDH 0x2B
112 #define DM9000_REG_CHIPR 0x2C
113 #define DM9000_REG_SMCR 0x2F
114 #define DM9000_REG_MRCMDX 0xF0
115 #define DM9000_REG_MRCMD 0xF2
116 #define DM9000_REG_MRRL 0xF4
117 #define DM9000_REG_MRRH 0xF5
118 #define DM9000_REG_MWCMDX 0xF6
119 #define DM9000_REG_MWCMD 0xF8
120 #define DM9000_REG_MWRL 0xFA
121 #define DM9000_REG_MWRH 0xFB
122 #define DM9000_REG_TXPLL 0xFC
123 #define DM9000_REG_TXPLH 0xFD
124 #define DM9000_REG_ISR 0xFE
125 #define DM9000_ISR_ROOS (1<<3)
126 #define DM9000_ISR_ROS (1<<2)
127 #define DM9000_ISR_PTS (1<<1)
128 #define DM9000_ISR_PRS (1<<0)
129 #define DM9000_ISR_CLR_STATUS (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)
131 #define DM9000_REG_IMR 0xFF
132 #define DM9000_IMR_AUTOWRAP 0x80
135 #define DM9000_MII_READ 0x0C
136 #define DM9000_MII_WRITE 0x0A
138 #define DM9000_MII_REG_BMCR 0x00
139 #define DM9000_MII_REG_STATUS 0x01
140 #define DM9000_MII_REG_PHYID1 0x02
141 #define DM9000_MII_REG_PHYID2 0x03
142 #define DM9000_MII_REG_ANAR 0x04
143 #define DM9000_MII_REG_ANLPAR 0x05
144 #define DM9000_MII_REG_ANER 0x06
145 #define DM9000_MII_REG_DSCR 0x10
146 #define DM9000_MII_REG_DSCSR 0x11
147 #define DM9000_MII_REG_10BTCSR 0x12
149 enum {
150 DM9K_TX_FIFO_START = 0,
151 DM9K_TX_FIFO_SIZE = (3 * 1024),
153 DM9K_RX_FIFO_START = DM9K_TX_FIFO_SIZE,
154 DM9K_RX_FIFO_SIZE = (13 * 1024),
156 DM9K_FIFO_SIZE = (DM9K_TX_FIFO_SIZE + DM9K_RX_FIFO_SIZE)
159 #define DM9K_WRAP_TX_INDEX(_v) ((_v >= DM9K_TX_FIFO_SIZE) ? (_v) - DM9K_TX_FIFO_SIZE : (_v))
160 #define DM9K_WRAP_RX_INDEX(_v) ((_v >= DM9K_FIFO_SIZE) ? (_v) - DM9K_RX_FIFO_SIZE : (_v))
161 /* DM9KNOTE: Assumes 16bit wiring */
162 #define DM9K_CLIP_TX_INDEX(_v) ((_v) & 1 ? DM9K_WRAP_TX_INDEX((_v)+1) : (_v))
163 #define DM9K_CLIP_RX_INDEX(_v) ((_v) & 1 ? DM9K_WRAP_RX_INDEX((_v)+1) : (_v))
165 typedef struct {
166 uint32_t addr; /* address port */
167 uint32_t data; /* data port */
168 VLANClientState *vc;
169 qemu_irq irq;
170 uint8_t macaddr[6];
171 uint8_t mult[8];
173 uint8_t address; /* The internal magical address */
176 * Transmit buffer is the first 3KB,
177 * followed by the receive buffer
179 uint8_t packet_buffer[DM9K_FIFO_SIZE];
181 uint16_t dm9k_trpa;
182 uint16_t dm9k_rwpa; /* TX Read ptr address, RX write ptr address */
184 uint8_t fctr, fcr;
185 uint16_t fc_high_mark;
186 uint16_t fc_low_mark;
188 uint16_t dm9k_mrr;
189 uint16_t dm9k_mwr; /* Read and write address registers */
190 uint16_t dm9k_txpl; /* TX packet length */
192 uint8_t dm9k_imr, dm9k_isr; /* Interrupt mask register and status register*/
193 uint8_t dm9k_ncr, dm9k_nsr; /* Network control register, network status register */
194 uint8_t dm9k_rcr; /* RX Control Register */
195 uint8_t dm9k_rsr; /* RX Status Register */
196 uint8_t dm9k_wcr; /* Wakeup control */
197 uint8_t dm9k_tcr; /* Transmission control register */
198 uint8_t packet_copy_buffer[3 * 1024]; /* packet copy buffer */
199 unsigned int packet_index:1; /* 0 == packet I, 1 == packet II */
201 /* Internal MII PHY state */
202 uint8_t dm9k_epcr; /* EEPROM/PHY control register */
203 uint8_t dm9k_epar; /* EEPROM/PHY address register */
204 uint16_t dm9k_epdr; /* EEPROM/PHY data register */
205 /* MII Regs */
206 uint16_t dm9k_mii_bmcr;
207 uint16_t dm9k_mii_anar;
208 uint16_t dm9k_mii_dscr;
210 } dm9000_state;
213 #ifdef DM9000_DUMP_FILENAME
214 #include <arpa/inet.h>
215 static uint8_t pcap_header[24] = {
216 0xA1, 0xB2, 0xC3, 0xD4, /* TCPDUMP Magic */
217 0x00, 0x02, 0x00, 0x04, /* Major 2, Minor 4 */
218 0x00, 0x00, 0x00, 0x00, /* Timezone offset */
219 0x00, 0x00, 0x00, 0x01, /* Accuracy of timestamps */
220 0x00, 0x00, 0x0C, 0x00, /* Snaplen 3KiB */
221 0x00, 0x00, 0x00, 0x01, /* Ethernet frames */
223 static uint8_t nulls[8] = {0, 0, 0, 0, 0, 0, 0, 0};
224 static void dm9k_dump_packet(uint8_t *buf, uint32_t size)
226 FILE* dm9k_fileh = fopen(DM9000_DUMP_FILENAME, "ab+");
227 unsigned long bsize = htonl(size);
228 DM9000_DBF("Dumping packet at %08x (%d bytes)\n", buf, size);
229 fseek(dm9k_fileh, 0, SEEK_END);
230 if(ftell(dm9k_fileh)==0) fwrite(pcap_header, 1, 24, dm9k_fileh);
231 fwrite(nulls, 1, 8, dm9k_fileh);
232 fwrite(&bsize, 1, 4, dm9k_fileh);
233 fwrite(&bsize, 1, 4, dm9k_fileh);
234 fwrite(buf, 1, size, dm9k_fileh);
235 fclose(dm9k_fileh);
237 #else
238 #define dm9k_dump_packet(X...) do { } while(0)
239 #endif
241 static void hexdump(const void* address, uint32_t len)
243 const unsigned char* p = address;
244 int i, j;
246 for (i = 0; i < len; i += 16) {
247 for (j = 0; j < 16 && i + j < len; j++)
248 fprintf(stderr, "%02x ", p[i + j]);
249 for (; j < 16; j++)
250 fprintf(stderr, " ");
251 fprintf(stderr, " ");
252 for (j = 0; j < 16 && i + j < len; j++)
253 fprintf(stderr, "%c", (p[i + j] < ' ' || p[i + j] > 0x7f) ? '.' : p[i + j]);
254 fprintf(stderr, "\n");
258 static void dm9000_raise_irq(dm9000_state *s)
260 int level = ((s->dm9k_isr & s->dm9k_imr) & 0x0f) != 0;
261 //DM9000_DBF("DM9000: Set IRQ level %d (isr = %02x imr %02x\n", level, s->dm9k_isr, s->dm9k_imr);
262 qemu_set_irq(s->irq, level);
265 static void dm9000_soft_reset_mii(dm9000_state *s)
267 s->dm9k_mii_bmcr = 0x3100; /* 100Mbps, AUTONEG, FULL DUPLEX */
268 s->dm9k_mii_anar = 0x01E1;
269 s->dm9k_mii_dscr = 0x0410;
272 static void dm9000_soft_reset(dm9000_state *s)
274 DM9000_DBF("DM9000: Soft Reset\n");
275 s->dm9k_txpl = 0;
276 s->dm9k_mwr = s->dm9k_trpa = DM9K_TX_FIFO_START;
277 s->dm9k_mrr = s->dm9k_rwpa = DM9K_RX_FIFO_START;
278 s->dm9k_imr = 0;
279 s->dm9k_isr = 0; /* 16 bit mode, no interrupts asserted */
280 s->dm9k_tcr = 0;
281 s->dm9k_rcr = 0;
282 s->dm9k_rsr = 0;
283 s->fcr = 0;
284 s->fctr = (3 << 4) | (8 << 0); // flow control high/low marks
285 s->fc_high_mark = 3 * 1024;
286 s->fc_low_mark = 8 * 1024;
288 s->packet_index = 0;
289 memset(s->packet_buffer, 0, sizeof(s->packet_buffer));
290 memset(s->packet_copy_buffer, 0, sizeof(s->packet_copy_buffer));
291 /* These registers have some bits "unaffected by software reset" */
292 /* Clear the reset bits */
293 s->dm9k_ncr &= DM9000_NCR_RESETPROTECT;
294 s->dm9k_nsr &= DM9000_NSR_RESETPROTECT;
295 /* Claim full duplex */
296 s->dm9k_ncr |= DM9000_NCR_FDX;
297 /* Set link status to 1 */
298 s->dm9k_nsr |= DM9000_NSR_LINKST;
299 /* dm9k_wcr is unaffected or reserved, never reset */
300 /* MII control regs */
301 s->dm9k_epcr = 0x00;
302 s->dm9k_epar = 0x40;
303 /* reset the MII */
304 dm9000_soft_reset_mii(s);
305 dm9000_raise_irq(s); /* Clear any potentially pending IRQ */
308 static void dm9000_hard_reset(dm9000_state *s)
310 s->dm9k_ncr = 0x00;
311 s->dm9k_nsr = 0x00;
312 s->dm9k_wcr = 0x00;
313 dm9000_soft_reset(s);
316 static void dm9000_do_transmit(dm9000_state *s) {
317 uint16_t idx, cnt, tptr;
318 idx = s->dm9k_trpa;
320 cnt = s->dm9k_txpl;
321 if (cnt > DM9K_TX_FIFO_SIZE)
322 cnt = DM9K_TX_FIFO_SIZE; /* HARD CAP AT 3KiB */
324 tptr = 0;
325 while (cnt--) {
326 s->packet_copy_buffer[tptr++] = s->packet_buffer[idx];
327 idx = DM9K_WRAP_TX_INDEX(idx+1);
330 #ifdef DM9000_DEBUG
332 uint8_t *buf = &s->packet_copy_buffer[6];
333 DM9000_DBF("TX_Packet: %02x:%02x:%02x:%02x:%02x:%02x %d bytes from %04x\n",
334 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],
335 tptr, idx);
336 // hexdump(s->packet_copy_buffer, tptr);
338 #endif
340 s->dm9k_trpa = DM9K_CLIP_TX_INDEX(idx);
341 dm9k_dump_packet(s->packet_copy_buffer, s->dm9k_txpl);
342 /* We have the copy buffer, now we do the transmit */
343 qemu_send_packet(s->vc, s->packet_copy_buffer, s->dm9k_txpl);
345 /* Clear the "please xmit" bit */
346 s->dm9k_tcr &= ~DM9000_TCR_TXREQ;
347 /* Set the TXEND bit */
348 s->dm9k_nsr |= 1 << (2 + s->packet_index);
349 DM9000_DBF("TX: NSR=%02x PI=%d\n", s->dm9k_nsr, s->packet_index);
350 /* Claim a TX complete IRQ */
351 s->dm9k_isr |= DM9000_ISR_PTS; /* Packet transmitted latch */
352 /* And flip the next-packet bit */
353 s->packet_index++;
355 dm9000_raise_irq(s);
358 static void dm9000_mii_read(dm9000_state *s)
360 int mii_reg = (s->dm9k_epar) & 0x3f;
361 uint16_t ret = 0;
362 switch(mii_reg) {
363 case DM9000_MII_REG_BMCR:
364 ret = s->dm9k_mii_bmcr;
365 break;
366 case DM9000_MII_REG_STATUS:
367 ret = 0x782D; /* No 100/T4, Can 100/FD, Can 100/HD, Can 10/FD, Can 10/HD,
368 * No Preamble suppression, Autoneg complete, No remote fault,
369 * Can autoneg, link up, no jabber, extended capability */
370 break;
371 case DM9000_MII_REG_PHYID1:
372 ret = 0x0181;
373 break;
374 case DM9000_MII_REG_PHYID2:
375 ret = 0xB8C0;
376 break;
377 case DM9000_MII_REG_ANAR:
378 ret = s->dm9k_mii_anar;
379 break;
380 case DM9000_MII_REG_ANLPAR:
381 ret = 0x0400;
382 break;
383 case DM9000_MII_REG_ANER:
384 ret = 0x0001;
385 break;
386 case DM9000_MII_REG_DSCR:
387 ret = s->dm9k_mii_dscr;
388 break;
389 case DM9000_MII_REG_DSCSR:
390 ret = 0xF008;
391 break;
392 case DM9000_MII_REG_10BTCSR:
393 ret = 0x7800;
394 default:
395 printf("%s: Bad register 0x%lx\n", __FUNCTION__, (unsigned long)mii_reg);
397 s->dm9k_epdr = ret;
398 // DM9000_DBF("DM9000:MIIPHY: Read of MII reg %d gives %04x\n", mii_reg, s->dm9k_epdr);
401 static void dm9000_mii_write(dm9000_state *s)
403 int mii_reg = (s->dm9k_epar) & 0x3f;
404 DM9000_DBF("DM9000:MIIPHY: Write of MII reg %d value %04x\n", mii_reg, s->dm9k_epdr);
405 switch(mii_reg) {
406 case DM9000_MII_REG_BMCR:
407 s->dm9k_mii_bmcr = (s->dm9k_epdr &~0x8000);
408 if( s->dm9k_epdr & 0x8000 ) dm9000_soft_reset_mii(s);
409 break;
410 case DM9000_MII_REG_ANAR:
411 s->dm9k_mii_anar = s->dm9k_epdr;
412 break;
413 case DM9000_MII_REG_DSCR:
414 s->dm9k_mii_dscr = s->dm9k_epdr & ~0x0008;
415 break;
416 default:
417 printf("%s: Bad register 0x%lx=%4x\n", __FUNCTION__, (unsigned long)mii_reg, s->dm9k_epdr);
421 static void dm9000_write(void *opaque, target_phys_addr_t address,
422 uint32_t value)
424 dm9000_state *s = (dm9000_state *)opaque;
425 #ifdef DM9000_DEBUG
426 int suppress_debug = 0;
427 #endif
429 if (address == s->addr) {
430 // if( (value != DM9000_REG_MRCMD) && (value != DM9000_REG_MWCMD) )
431 // DM9000_DBF("DM9000: Address set to 0x%02x\n", value);
432 s->address = value;
433 return;
436 switch(s->address) {
437 case DM9000_REG_NCR:
438 DM9000_DBF("DM9000_REG_NCR: %02x=%04x\n", s->address, value);
439 s->dm9k_ncr = value | DM9000_NCR_FDX;
440 if (s->dm9k_ncr & DM9000_NCR_RESET)
441 dm9000_soft_reset(s);
442 break;
443 case DM9000_REG_NSR:
444 s->dm9k_nsr &= ~(value & ~DM9000_NSR_READONLY);
445 break;
446 case DM9000_REG_TCR:
447 s->dm9k_tcr = value & 0xFF;
448 if ( value & DM9000_TCR_TXREQ )
449 dm9000_do_transmit(s);
450 break;
451 case DM9000_REG_EPCR:
452 s->dm9k_epcr = value & 0xFF;
453 if( value & DM9000_MII_READ )
454 dm9000_mii_read(s);
455 else if( value & DM9000_MII_WRITE )
456 dm9000_mii_write(s);
457 break;
458 case DM9000_REG_RCR:
459 s->dm9k_rcr = value & 0xFF;
460 break;
462 case DM9000_REG_BPTR: /* can be ignored */
463 break;
465 case DM9000_REG_FCTR: {/* 0x09 Flow Control Threshold Register */
466 s->fc_high_mark = ((value >> 4) & 0xf) * 1024; // emit a pause packet time=0xffff
467 s->fc_low_mark = ((value) & 0xf) * 1024; // emit an unpause packet time=0x0000
468 s->fctr = value;
469 } break;
471 case DM9000_REG_FCR: /* 0x0a Flow Control Register */
472 s->fcr = value;
473 break;
475 case DM9000_REG_EPAR:
476 s->dm9k_epar = value & 0xFF;
477 break;
478 case DM9000_REG_EPDRL:
479 s->dm9k_epdr &= 0xFF00;
480 s->dm9k_epdr |= value & 0xFF;
481 break;
482 case DM9000_REG_EPDRH:
483 s->dm9k_epdr &= 0xFF;
484 s->dm9k_epdr |= (value & 0xFF) << 8;
485 break;
486 case DM9000_REG_PAR0 ... DM9000_REG_PAR5:
487 /* MAC address is set by the QEMU Nic */
488 s->macaddr[s->address - DM9000_REG_PAR0] = value;
489 break;
490 case DM9000_REG_MAR0 ... DM9000_REG_MAR7:
491 /* Multicast address is ignored */
492 s->mult[s->address - DM9000_REG_MAR0] = value;
493 break;
494 case DM9000_REG_GPCR:
495 case DM9000_REG_GPR: /* General purpose reg (GPIOs, LED?) */
496 break;
497 case DM9000_REG_SMCR:
498 if (value)
499 printf("%s: something playing with special mode ? 0x%lx=%x\n", __FUNCTION__, (unsigned long)s->address, value);
500 break;
501 case DM9000_REG_MRRL:
502 s->dm9k_mrr &= 0xFF00;
503 s->dm9k_mrr |= value & 0xFF;
504 break;
505 case DM9000_REG_MRRH:
506 s->dm9k_mrr &= 0xFF;
507 s->dm9k_mrr |= (value & 0xFF) << 8;
508 break;
509 case DM9000_REG_MWCMDX:
510 case DM9000_REG_MWCMD:
511 /* DM9KNOTE: This assumes a 16bit wide wiring */
512 s->packet_buffer[s->dm9k_mwr] = value & 0xFF;
513 s->packet_buffer[s->dm9k_mwr + 1] = (value >> 8) & 0xFF;
514 if (s->address == DM9000_REG_MWCMD) {
515 if (s->dm9k_imr & DM9000_IMR_AUTOWRAP)
516 s->dm9k_mwr = DM9K_WRAP_TX_INDEX(s->dm9k_mwr + 2);
517 else if (s->dm9k_mwr + 2 < DM9K_TX_FIFO_SIZE) // clip it
518 s->dm9k_mwr += 2;
520 #ifdef DM9000_DEBUG
521 suppress_debug = 1;
522 #endif
523 break;
524 case DM9000_REG_MWRL:
525 s->dm9k_mwr &= 0xFF00;
526 s->dm9k_mwr |= value & 0xFF;
527 break;
528 case DM9000_REG_MWRH:
529 s->dm9k_mwr &= 0xFF;
530 s->dm9k_mwr |= (value & 0xFF) << 8;
531 break;
532 case DM9000_REG_TXPLL:
533 s->dm9k_txpl &= 0xFF00;
534 s->dm9k_txpl |= value & 0xFF;
535 break;
536 case DM9000_REG_TXPLH:
537 s->dm9k_txpl &= 0xFF;
538 s->dm9k_txpl |= (value & 0xFF) << 8;
539 break;
540 case DM9000_REG_ISR:
541 s->dm9k_isr &= ~(value & 0x0F);
542 dm9000_raise_irq(s);
543 break;
544 case DM9000_REG_IMR:
545 if( !(s->dm9k_imr & DM9000_IMR_AUTOWRAP) && (value & DM9000_IMR_AUTOWRAP) )
546 s->dm9k_mrr = 0x0C00 | (s->dm9k_mrr & 0xFF);
547 s->dm9k_imr = value & 0xFF;
548 dm9000_raise_irq(s);
549 break;
550 default:
551 printf("%s: Bad register 0x%lx=%x\n", __FUNCTION__, (unsigned long)s->address, value);
553 #if 0 // def DM9000_DEBUG
554 if(!suppress_debug) DM9000_DBF("DM9000: Write value %02x=%04x\n", s->address, value);
555 #endif
558 static uint32_t dm9000_read(void *opaque, target_phys_addr_t address)
560 dm9000_state *s = (dm9000_state *)opaque;
561 uint32_t ret = 0;
562 #ifdef DM9000_DEBUG
563 int suppress_debug = 0;
564 #endif
566 if (address == s->addr)
567 return s->address;
568 switch(s->address) {
569 case DM9000_REG_NCR:
570 ret = s->dm9k_ncr;
571 break;
572 case DM9000_REG_NSR:
573 ret = s->dm9k_nsr;
574 /* Note, TX1END and TX2END are *CLEAR ON READ* */
575 s->dm9k_nsr &= ~(DM9000_NSR_TX1END | DM9000_NSR_TX2END);
576 break;
577 case DM9000_REG_TCR:
578 ret = s->dm9k_tcr;
579 break;
580 case DM9000_REG_TSR1:
581 case DM9000_REG_TSR2:
582 ret = 0x00; /* No error, yay! */
583 break;
584 case DM9000_REG_EPCR:
585 ret = s->dm9k_epcr;
586 break;
587 case DM9000_REG_RCR:
588 ret = s->dm9k_rcr;
589 break;
590 case DM9000_REG_RSR:
591 ret = s->dm9k_rsr;
592 break;
593 case DM9000_REG_EPAR:
594 ret = s->dm9k_epar;
595 break;
596 case DM9000_REG_EPDRL:
597 ret = s->dm9k_epdr & 0xFF;
598 break;
599 case DM9000_REG_EPDRH:
600 ret = (s->dm9k_epdr >> 8) & 0xFF;
601 break;
602 case DM9000_REG_PAR0...DM9000_REG_PAR5:
603 ret = s->macaddr[s->address - DM9000_REG_PAR0];
604 break;
605 case DM9000_REG_MAR0...DM9000_REG_MAR7:
606 /* Multicast address is ignored */
607 break;
608 case DM9000_REG_TRPAL:
609 ret = s->dm9k_trpa & 0xFF;
610 break;
611 case DM9000_REG_TRPAH:
612 ret = s->dm9k_trpa >> 8;
613 break;
614 case DM9000_REG_RWPAL:
615 ret = s->dm9k_rwpa & 0xFF;
616 break;
617 case DM9000_REG_RWPAH:
618 ret = s->dm9k_rwpa >> 8;
619 break;
620 case DM9000_REG_VIDL:
621 ret = 0x46;
622 break;
623 case DM9000_REG_VIDH:
624 ret = 0x0A;
625 break;
626 case DM9000_REG_PIDL:
627 ret = 0x00;
628 break;
629 case DM9000_REG_PIDH:
630 ret = 0x90;
631 break;
632 case DM9000_REG_CHIPR:
633 ret = 0x00;
634 break;
635 case DM9000_REG_MRCMDX:
636 case DM9000_REG_MRCMD:
637 /* DM9KNOTE: This assumes a 16bit wide wiring */
638 ret = s->packet_buffer[s->dm9k_mrr];
639 ret |= s->packet_buffer[s->dm9k_mrr + 1] << 8;
640 #if 0
641 if (s->dm9k_mrr == s->dm9k_rwpa)
642 printf("(%04x=%04x) ", s->dm9k_mrr, ret);
643 else
644 printf("[%04x=%04x] ", s->dm9k_mrr, ret);
645 fflush(stdout);
646 #endif
647 if( s->address == DM9000_REG_MRCMD ) {
648 if( s->dm9k_imr & DM9000_IMR_AUTOWRAP )
649 s->dm9k_mrr = DM9K_WRAP_RX_INDEX(s->dm9k_mrr + 2);
650 else if (s->dm9k_mrr + 2 < DM9K_FIFO_SIZE) // clip it
651 s->dm9k_mrr += 2;
652 } else {
653 // drive read the fifo looking for a 0x01 to indicate a packet is there, so we just return
654 // it a zero if there is nothing to read
655 if (s->dm9k_mrr == s->dm9k_rwpa)
656 ret = 0;
658 #ifdef DM9000_DEBUG
659 if (s->address==DM9000_REG_MRCMD)
660 suppress_debug = 1;
661 #endif
662 break;
663 case DM9000_REG_MRRL:
664 ret = s->dm9k_mrr & 0xFF;
665 break;
666 case DM9000_REG_MRRH:
667 ret = s->dm9k_mrr >> 8;
668 break;
669 case DM9000_REG_MWRL:
670 ret = s->dm9k_mwr & 0xFF;
671 break;
672 case DM9000_REG_MWRH:
673 ret = s->dm9k_mwr >> 8;
674 break;
675 case DM9000_REG_TXPLL:
676 ret = s->dm9k_txpl & 0xFF;
677 break;
678 case DM9000_REG_TXPLH:
679 ret = s->dm9k_txpl >> 8;
680 break;
681 case DM9000_REG_ISR:
682 ret = s->dm9k_isr;
683 break;
684 case DM9000_REG_IMR:
685 ret = s->dm9k_imr;
686 break;
687 default:
688 ret = 0;
691 #if 0 // def DM9000_DEBUG
692 if(!suppress_debug) DM9000_DBF("DM9000: Read gives: %04x\n", ret);
693 #endif
694 return ret;
699 static int dm9000_can_receive(void *opaque)
701 dm9000_state *s = (dm9000_state *)opaque;
702 uint16_t rx_space;
703 if( s->dm9k_rwpa < s->dm9k_mrr )
704 rx_space = s->dm9k_mrr - s->dm9k_rwpa;
705 else
706 rx_space = DM9K_RX_FIFO_SIZE - (s->dm9k_rwpa - s->dm9k_mrr);
707 DM9000_DBF("DM9000:RX_Packet: Asked about RX, rwpa=%d mrr=%d => space is %d bytes\n",
708 s->dm9k_rwpa, s->dm9k_mrr, rx_space);
709 if (rx_space > 2048) return 1;
710 return 0;
713 #define POLYNOMIAL 0x04c11db6
715 /* From FreeBSD */
716 /* XXX: optimize */
717 static int compute_mcast_idx(const uint8_t *ep)
719 uint32_t crc;
720 int carry, i, j;
721 uint8_t b;
723 crc = 0xffffffff;
724 for (i = 0; i < 6; i++) {
725 b = *ep++;
726 for (j = 0; j < 8; j++) {
727 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
728 crc <<= 1;
729 b >>= 1;
730 if (carry)
731 crc = ((crc ^ POLYNOMIAL) | carry);
734 return (crc >> 26);
737 static void dm9000_receive(void *opaque, const uint8_t *buf, int size)
739 dm9000_state *s = (dm9000_state *)opaque;
740 uint16_t rxptr = s->dm9k_rwpa, idx;
741 unsigned int mcast_idx = 0;
742 int pad = 4;
744 if (!(s->dm9k_rcr & DM9000_RCR_RXEN))
745 return;
746 s->dm9k_rsr = 0;
748 if (!(s->dm9k_rcr & DM9000_RCR_PRMSC)) {
749 if (buf[0] & 0x01) {
750 /* multi/broadcast */
751 if (!(s->dm9k_rcr & DM9000_RCR_ALL)) {
752 mcast_idx = compute_mcast_idx(buf);
753 if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
754 return;
755 s->dm9k_rsr |= DM9000_RSR_MF;
757 } else if (!memcmp(buf, s->macaddr, 6)) {
758 /* match */
759 } else {
760 return;
762 if (size < 64 && !(s->dm9k_rcr & DM9000_RCR_RUNT)) {
763 // printf("rcr %02x RUNT %d\n", s->dm9k_rcr, size);
764 s->dm9k_rsr |= DM9000_RSR_RF;
765 // return;
767 if (size > 1522 && (s->dm9k_rcr & DM9000_RCR_DIS_LONG))
768 return;
771 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",
772 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],
773 buf[6],buf[7],buf[8],buf[9],buf[10],buf[11],
774 size, rxptr, s->dm9k_rcr);
775 dm9k_dump_packet(buf, size);
778 * apparently even runt frames are padded to 64
780 if (size < 64)
781 pad = 64 - size;
783 rxptr = DM9K_CLIP_RX_INDEX(rxptr);
784 /* store header */
785 s->packet_buffer[rxptr] = 0x01; /* Packet read */
786 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
787 s->packet_buffer[rxptr] = 0x00; /* Status OK */
788 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
789 s->packet_buffer[rxptr] = (size+pad) & 0xFF; /* Size LOW */
790 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
791 s->packet_buffer[rxptr] = ((size+pad) >> 8) & 0xff; /* Size HIGH */
792 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
794 for (idx = 0; idx < size; idx++) {
795 s->packet_buffer[rxptr] = *buf++;
796 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
798 while (pad--) {
799 s->packet_buffer[rxptr] = 0;
800 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
803 s->dm9k_rwpa = DM9K_CLIP_RX_INDEX(rxptr);
804 s->dm9k_isr |= DM9000_ISR_PRS; /* RX interrupt, yay */
805 dm9000_raise_irq(s);
809 static CPUReadMemoryFunc *dm9000_readfn[] = {
810 dm9000_read,
811 dm9000_read,
812 dm9000_read
815 static CPUWriteMemoryFunc *dm9000_writefn[] = {
816 dm9000_write,
817 dm9000_write,
818 dm9000_write
821 /* initialises a dm9000 ethernet controller
822 * The dm9k has a single 16bit wide address and data port through which all
823 * operations are multiplexed, there is a single IRQ
825 void dm9000_init(NICInfo *nd, target_phys_addr_t base_addr,
826 uint32_t addr_offset, uint32_t data_offset,
827 qemu_irq irq)
829 dm9000_state *s;
830 int iomemtype;
832 s = (dm9000_state *)qemu_mallocz(sizeof(dm9000_state));
833 iomemtype = cpu_register_io_memory(0, dm9000_readfn,
834 dm9000_writefn, s);
835 cpu_register_physical_memory(base_addr, MAX(addr_offset, data_offset) + 4, iomemtype);
836 s->addr = addr_offset;
837 s->data = data_offset;
838 s->irq = irq;
839 memcpy(s->macaddr, nd->macaddr, 6);
840 memset(s->mult, 0xff, 8);
843 uint8_t * buf = s->macaddr;
844 printf("DM9000: INIT QEMU MAC : %02x:%02x:%02x:%02x:%02x:%02x\n",
845 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);
848 dm9000_hard_reset(s);
850 s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
851 dm9000_receive, dm9000_can_receive, s);
852 qemu_format_nic_info_str(s->vc, s->macaddr);