MINI2440: Code cleanup
[qemu/mini2440.git] / hw / dm9000.c
blob95faffa0304a595c8fa2c98a60d6d873b6dab661
1 /* hw/dm9000.c
3 * DM9000 Ethernet interface
5 * Copyright Daniel Silverstone and Vincent Sanders
6 * Copyright Michel Pollet <buserror@gmail.com>
8 * This file is under the terms of the GNU General Public
9 * License Version 2
12 #include <string.h>
13 #include "qemu-common.h"
14 #include "hw/irq.h"
15 #include "hw.h"
16 #include "net.h"
17 #include "dm9000.h"
19 /* Comment this out if you don't want register debug on stderr */
20 //#define DM9000_DEBUG
22 /* Comment this out if you don't want a packet dump */
23 //#define DM9000_DUMP_FILENAME "/tmp/dm9k_dump"
25 #ifdef DM9000_DEBUG
26 #define DM9000_DBF(X...) fprintf(stderr, X)
27 #else
28 #define DM9000_DBF(X...) if(0) fprintf(stderr, X)
29 #endif
31 #define DM9000_REG_NCR 0x00
32 #define DM9000_NCR_RESET (1 << 0)
34 #define DM9000_NCR_EXT_PHY (1<<7)
35 #define DM9000_NCR_WAKEEN (1<<6)
36 #define DM9000_NCR_FCOL (1<<4)
37 #define DM9000_NCR_FDX (1<<3)
38 #define DM9000_NCR_LBK (3<<1)
40 #define DM9000_NCR_RESETPROTECT (DM9000_NCR_EXT_PHY | DM9000_NCR_WAKEEN)
42 #define DM9000_REG_NSR 0x01
44 #define DM9000_NSR_SPEED (1<<7)
45 #define DM9000_NSR_LINKST (1<<6)
46 #define DM9000_NSR_WAKEST (1<<5)
47 #define DM9000_NSR_TX2END (1<<3)
48 #define DM9000_NSR_TX1END (1<<2)
49 #define DM9000_NSR_RXOV (1<<1)
51 #define DM9000_NSR_RESETPROTECT (DM9000_NSR_WAKEST)
52 #define DM9000_NSR_READONLY (DM9000_NSR_SPEED|DM9000_NSR_LINKST|(1<<4)|DM9000_NSR_RXOV|(1<<0))
54 #define DM9000_REG_TCR 0x02
55 #define DM9000_TCR_TXREQ (1 << 0)
57 #define DM9000_REG_TSR1 0x03
58 #define DM9000_REG_TSR2 0x04
59 #define DM9000_REG_RCR 0x05
60 #define DM9000_RCR_DIS_LONG (1 << 5) /* RX Discard long frames (>1522) */
61 #define DM9000_RCR_DIS_CRC (1 << 4) /* RX Discard bad CRC */
62 #define DM9000_RCR_ALL (1 << 3) /* RX Pass All Multicast */
63 #define DM9000_RCR_RUNT (1 << 2) /* RX Pass Runt Frames (frame < 64 bytes) */
64 #define DM9000_RCR_PRMSC (1 << 1) /* RX Promiscuous Mode */
65 #define DM9000_RCR_RXEN (1 << 0) /* RX Enabled */
67 #define DM9000_REG_RSR 0x06
68 #define DM9000_RSR_RF (1 << 7) /* RX Runt Frame (frame < 64 bytes) */
69 #define DM9000_RSR_MF (1 << 6) /* RX Multicast Frame */
70 #define DM9000_RSR_FOE (1 << 0) /* RX FIFO overflow */
72 #define DM9000_REG_ROCR 0x07
73 #define DM9000_REG_BPTR 0x08
74 #define DM9000_REG_FCTR 0x09
75 #define DM9000_REG_FCR 0x0A
76 #define DM9000_FCR_TXP0 (1 << 7) /* TX Pause Packet (when empty) */
77 #define DM9000_FCR_TXPF (1 << 6) /* TX Pause Packet (when full) */
78 #define DM9000_FCR_TXPEN (1 << 5) /* Force pause/unpause packets */
79 #define DM9000_FCR_BKPA (1 << 4)
80 #define DM9000_FCR_BKPM (1 << 3)
81 #define DM9000_FCR_RXPS (1 << 2) /* RX Pause Packet Status, latch and read to clear */
82 #define DM9000_FCR_RXPCS (1 << 1) /* RX Pause Packet Current Status */
83 #define DM9000_FCR_FLCE (1 << 0) /* Flow Control Enable */
85 #define DM9000_REG_EPCR 0x0B
86 #define DM9000_REG_EPAR 0x0C
87 #define DM9000_REG_EPDRL 0x0D
88 #define DM9000_REG_EPDRH 0x0E
89 #define DM9000_REG_WCR 0x0F
90 #define DM9000_REG_PAR0 0x10
91 #define DM9000_REG_PAR1 0x11
92 #define DM9000_REG_PAR2 0x12
93 #define DM9000_REG_PAR3 0x13
94 #define DM9000_REG_PAR4 0x14
95 #define DM9000_REG_PAR5 0x15
96 #define DM9000_REG_MAR0 0x16
97 #define DM9000_REG_MAR1 0x17
98 #define DM9000_REG_MAR2 0x18
99 #define DM9000_REG_MAR3 0x19
100 #define DM9000_REG_MAR4 0x1A
101 #define DM9000_REG_MAR5 0x1B
102 #define DM9000_REG_MAR6 0x1C
103 #define DM9000_REG_MAR7 0x1D
104 #define DM9000_REG_GPCR 0x1E
105 #define DM9000_REG_GPR 0x1F
106 #define DM9000_REG_TRPAL 0x22
107 #define DM9000_REG_TRPAH 0x23
108 #define DM9000_REG_RWPAL 0x24
109 #define DM9000_REG_RWPAH 0x25
110 #define DM9000_REG_VIDL 0x28
111 #define DM9000_REG_VIDH 0x29
112 #define DM9000_REG_PIDL 0x2A
113 #define DM9000_REG_PIDH 0x2B
114 #define DM9000_REG_CHIPR 0x2C
115 #define DM9000_REG_SMCR 0x2F
116 #define DM9000_REG_MRCMDX 0xF0
117 #define DM9000_REG_MRCMD 0xF2
118 #define DM9000_REG_MRRL 0xF4
119 #define DM9000_REG_MRRH 0xF5
120 #define DM9000_REG_MWCMDX 0xF6
121 #define DM9000_REG_MWCMD 0xF8
122 #define DM9000_REG_MWRL 0xFA
123 #define DM9000_REG_MWRH 0xFB
124 #define DM9000_REG_TXPLL 0xFC
125 #define DM9000_REG_TXPLH 0xFD
126 #define DM9000_REG_ISR 0xFE
127 #define DM9000_ISR_ROOS (1<<3)
128 #define DM9000_ISR_ROS (1<<2)
129 #define DM9000_ISR_PTS (1<<1)
130 #define DM9000_ISR_PRS (1<<0)
131 #define DM9000_ISR_CLR_STATUS (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)
133 #define DM9000_REG_IMR 0xFF
134 #define DM9000_IMR_AUTOWRAP 0x80
137 #define DM9000_MII_READ 0x0C
138 #define DM9000_MII_WRITE 0x0A
140 #define DM9000_MII_REG_BMCR 0x00
141 #define DM9000_MII_REG_STATUS 0x01
142 #define DM9000_MII_REG_PHYID1 0x02
143 #define DM9000_MII_REG_PHYID2 0x03
144 #define DM9000_MII_REG_ANAR 0x04
145 #define DM9000_MII_REG_ANLPAR 0x05
146 #define DM9000_MII_REG_ANER 0x06
147 #define DM9000_MII_REG_DSCR 0x10
148 #define DM9000_MII_REG_DSCSR 0x11
149 #define DM9000_MII_REG_10BTCSR 0x12
151 enum {
152 DM9K_TX_FIFO_START = 0,
153 DM9K_TX_FIFO_SIZE = (3 * 1024),
155 DM9K_RX_FIFO_START = DM9K_TX_FIFO_SIZE,
156 DM9K_RX_FIFO_SIZE = (13 * 1024),
158 DM9K_FIFO_SIZE = (DM9K_TX_FIFO_SIZE + DM9K_RX_FIFO_SIZE)
161 #define DM9K_WRAP_TX_INDEX(_v) ((_v >= DM9K_TX_FIFO_SIZE) ? (_v) - DM9K_TX_FIFO_SIZE : (_v))
162 #define DM9K_WRAP_RX_INDEX(_v) ((_v >= DM9K_FIFO_SIZE) ? (_v) - DM9K_RX_FIFO_SIZE : (_v))
163 /* DM9KNOTE: Assumes 16bit wiring */
164 #define DM9K_CLIP_TX_INDEX(_v) ((_v) & 1 ? DM9K_WRAP_TX_INDEX((_v)+1) : (_v))
165 #define DM9K_CLIP_RX_INDEX(_v) ((_v) & 1 ? DM9K_WRAP_RX_INDEX((_v)+1) : (_v))
167 typedef struct {
168 uint32_t addr; /* address port */
169 uint32_t data; /* data port */
170 VLANClientState *vc;
171 qemu_irq irq;
172 uint8_t macaddr[6]; /* MAC address -- default to qemu, can/will be overridden by guest driver */
173 uint8_t mult[8]; /* multicast filtering fields */
175 uint8_t address; /* The internal magical register address */
178 * Transmit buffer is the first 3KB,
179 * followed by the receive buffer
181 uint8_t packet_buffer[DM9K_FIFO_SIZE];
183 uint16_t dm9k_trpa;
184 uint16_t dm9k_rwpa; /* TX Read ptr address, RX write ptr address */
186 uint8_t fctr, fcr;
187 uint16_t fc_high_mark;
188 uint16_t fc_low_mark;
190 uint16_t dm9k_mrr;
191 uint16_t dm9k_mwr; /* Read and write address registers */
192 uint16_t dm9k_txpl; /* TX packet length */
194 uint8_t dm9k_imr, dm9k_isr; /* Interrupt mask register and status register*/
195 uint8_t dm9k_ncr, dm9k_nsr; /* Network control register, network status register */
196 uint8_t dm9k_rcr; /* RX Control Register */
197 uint8_t dm9k_rsr; /* RX Status Register */
198 uint8_t dm9k_wcr; /* Wakeup control */
199 uint8_t dm9k_tcr; /* Transmission control register */
200 uint8_t packet_copy_buffer[DM9K_TX_FIFO_SIZE]; /* realigned packet copy buffer */
201 unsigned int packet_index:1; /* 0 == packet I, 1 == packet II */
203 /* Internal MII PHY state */
204 uint8_t dm9k_epcr; /* EEPROM/PHY control register */
205 uint8_t dm9k_epar; /* EEPROM/PHY address register */
206 uint16_t dm9k_epdr; /* EEPROM/PHY data register */
207 /* MII Regs */
208 uint16_t dm9k_mii_bmcr;
209 uint16_t dm9k_mii_anar;
210 uint16_t dm9k_mii_dscr;
212 } dm9000_state;
214 static void dm9000_save(QEMUFile *f, void *opaque)
216 dm9000_state *s = (dm9000_state *)opaque;
218 qemu_put_be32s(f, &s->addr);
219 qemu_put_be32s(f, &s->data);
220 qemu_put_8s(f, &s->address);
221 qemu_put_buffer(f, s->macaddr, sizeof(s->macaddr));
222 qemu_put_buffer(f, s->mult, sizeof(s->mult));
223 qemu_put_buffer(f, s->packet_buffer, sizeof(s->packet_buffer));
224 qemu_put_buffer(f, s->packet_copy_buffer, sizeof(s->packet_copy_buffer));
225 qemu_put_be16s(f, &s->dm9k_trpa);
226 qemu_put_be16s(f, &s->dm9k_rwpa);
227 qemu_put_8s(f, &s->fctr);
228 qemu_put_8s(f, &s->fcr);
229 qemu_put_be16s(f, &s->fc_high_mark);
230 qemu_put_be16s(f, &s->fc_low_mark);
231 qemu_put_be16s(f, &s->dm9k_mrr);
232 qemu_put_be16s(f, &s->dm9k_mwr);
233 qemu_put_be16s(f, &s->dm9k_txpl);
234 qemu_put_8s(f, &s->dm9k_imr);
235 qemu_put_8s(f, &s->dm9k_isr);
236 qemu_put_8s(f, &s->dm9k_ncr);
237 qemu_put_8s(f, &s->dm9k_nsr);
238 qemu_put_8s(f, &s->dm9k_rcr);
239 qemu_put_8s(f, &s->dm9k_rsr);
240 qemu_put_8s(f, &s->dm9k_wcr);
241 qemu_put_8s(f, &s->dm9k_tcr);
242 qemu_put_8s(f, &s->dm9k_epcr);
243 qemu_put_8s(f, &s->dm9k_epar);
244 qemu_put_be16s(f, &s->dm9k_epdr);
245 qemu_put_be16s(f, &s->dm9k_mii_bmcr);
246 qemu_put_be16s(f, &s->dm9k_mii_anar);
247 qemu_put_be16s(f, &s->dm9k_mii_dscr);
250 static int dm9000_load(QEMUFile *f, void *opaque, int version_id)
252 dm9000_state *s = (dm9000_state *)opaque;
253 qemu_get_be32s(f, &s->addr);
254 qemu_get_be32s(f, &s->data);
255 qemu_get_8s(f, &s->address);
256 qemu_get_buffer(f, s->macaddr, sizeof(s->macaddr));
257 qemu_get_buffer(f, s->mult, sizeof(s->mult));
258 qemu_get_buffer(f, s->packet_buffer, sizeof(s->packet_buffer));
259 qemu_get_buffer(f, s->packet_copy_buffer, sizeof(s->packet_copy_buffer));
260 qemu_get_be16s(f, &s->dm9k_trpa);
261 qemu_get_be16s(f, &s->dm9k_rwpa);
262 qemu_get_8s(f, &s->fctr);
263 qemu_get_8s(f, &s->fcr);
264 qemu_get_be16s(f, &s->fc_high_mark);
265 qemu_get_be16s(f, &s->fc_low_mark);
266 qemu_get_be16s(f, &s->dm9k_mrr);
267 qemu_get_be16s(f, &s->dm9k_mwr);
268 qemu_get_be16s(f, &s->dm9k_txpl);
269 qemu_get_8s(f, &s->dm9k_imr);
270 qemu_get_8s(f, &s->dm9k_isr);
271 qemu_get_8s(f, &s->dm9k_ncr);
272 qemu_get_8s(f, &s->dm9k_nsr);
273 qemu_get_8s(f, &s->dm9k_rcr);
274 qemu_get_8s(f, &s->dm9k_rsr);
275 qemu_get_8s(f, &s->dm9k_wcr);
276 qemu_get_8s(f, &s->dm9k_tcr);
277 qemu_get_8s(f, &s->dm9k_epcr);
278 qemu_get_8s(f, &s->dm9k_epar);
279 qemu_get_be16s(f, &s->dm9k_epdr);
280 qemu_get_be16s(f, &s->dm9k_mii_bmcr);
281 qemu_get_be16s(f, &s->dm9k_mii_anar);
282 qemu_get_be16s(f, &s->dm9k_mii_dscr);
283 return 0;
287 #ifdef DM9000_DUMP_FILENAME
288 #include <arpa/inet.h>
289 static uint8_t pcap_header[24] = {
290 0xA1, 0xB2, 0xC3, 0xD4, /* TCPDUMP Magic */
291 0x00, 0x02, 0x00, 0x04, /* Major 2, Minor 4 */
292 0x00, 0x00, 0x00, 0x00, /* Timezone offset */
293 0x00, 0x00, 0x00, 0x01, /* Accuracy of timestamps */
294 0x00, 0x00, 0x0C, 0x00, /* Snaplen 3KiB */
295 0x00, 0x00, 0x00, 0x01, /* Ethernet frames */
297 static uint8_t nulls[8] = {0, 0, 0, 0, 0, 0, 0, 0};
298 static void dm9k_dump_packet(uint8_t *buf, uint32_t size)
300 FILE* dm9k_fileh = fopen(DM9000_DUMP_FILENAME, "ab+");
301 unsigned long bsize = htonl(size);
302 DM9000_DBF("Dumping packet at %08x (%d bytes)\n", buf, size);
303 fseek(dm9k_fileh, 0, SEEK_END);
304 if(ftell(dm9k_fileh)==0) fwrite(pcap_header, 1, 24, dm9k_fileh);
305 fwrite(nulls, 1, 8, dm9k_fileh);
306 fwrite(&bsize, 1, 4, dm9k_fileh);
307 fwrite(&bsize, 1, 4, dm9k_fileh);
308 fwrite(buf, 1, size, dm9k_fileh);
309 fclose(dm9k_fileh);
311 #else
312 #define dm9k_dump_packet(X...) do { } while(0)
313 #endif
316 static void dm9000_raise_irq(dm9000_state *s)
318 int level = ((s->dm9k_isr & s->dm9k_imr) & 0x0f) != 0;
319 //DM9000_DBF("DM9000: Set IRQ level %d (isr = %02x imr %02x\n", level, s->dm9k_isr, s->dm9k_imr);
320 qemu_set_irq(s->irq, level);
323 static void dm9000_soft_reset_mii(dm9000_state *s)
325 s->dm9k_mii_bmcr = 0x3100; /* 100Mbps, AUTONEG, FULL DUPLEX */
326 s->dm9k_mii_anar = 0x01E1;
327 s->dm9k_mii_dscr = 0x0410;
330 static void dm9000_soft_reset(dm9000_state *s)
332 DM9000_DBF("DM9000: Soft Reset\n");
333 s->dm9k_txpl = 0;
334 s->dm9k_mwr = s->dm9k_trpa = DM9K_TX_FIFO_START;
335 s->dm9k_mrr = s->dm9k_rwpa = DM9K_RX_FIFO_START;
336 s->dm9k_imr = 0;
337 s->dm9k_isr = 0; /* 16 bit mode, no interrupts asserted */
338 s->dm9k_tcr = 0;
339 s->dm9k_rcr = 0;
340 s->dm9k_rsr = 0;
341 s->fcr = 0;
342 s->fctr = (3 << 4) | (8 << 0); // flow control high/low marks
343 s->fc_high_mark = 3 * 1024;
344 s->fc_low_mark = 8 * 1024;
346 s->packet_index = 0;
347 memset(s->packet_buffer, 0, sizeof(s->packet_buffer));
348 memset(s->packet_copy_buffer, 0, sizeof(s->packet_copy_buffer));
349 /* These registers have some bits "unaffected by software reset" */
350 /* Clear the reset bits */
351 s->dm9k_ncr &= DM9000_NCR_RESETPROTECT;
352 s->dm9k_nsr &= DM9000_NSR_RESETPROTECT;
353 /* Claim full duplex */
354 s->dm9k_ncr |= DM9000_NCR_FDX;
355 /* Set link status to 1 */
356 s->dm9k_nsr |= DM9000_NSR_LINKST;
357 /* dm9k_wcr is unaffected or reserved, never reset */
358 /* MII control regs */
359 s->dm9k_epcr = 0x00;
360 s->dm9k_epar = 0x40;
361 /* reset the MII */
362 dm9000_soft_reset_mii(s);
363 dm9000_raise_irq(s); /* Clear any potentially pending IRQ */
366 static void dm9000_hard_reset(dm9000_state *s)
368 s->dm9k_ncr = 0x00;
369 s->dm9k_nsr = 0x00;
370 s->dm9k_wcr = 0x00;
371 dm9000_soft_reset(s);
374 static uint16_t dm9000_get_rx_fifo_fill_state(dm9000_state *s)
376 uint16_t res;
377 if (s->dm9k_mrr > s->dm9k_rwpa)
378 res = (DM9K_FIFO_SIZE-s->dm9k_rwpa) + (s->dm9k_mrr-DM9K_RX_FIFO_START);
379 else
380 res = s->dm9k_rwpa - s->dm9k_mrr;
381 return res;
384 static void dm9000_do_transmit(dm9000_state *s) {
385 uint16_t idx, cnt, tptr;
386 idx = s->dm9k_trpa;
388 cnt = s->dm9k_txpl;
389 if (cnt > DM9K_TX_FIFO_SIZE)
390 cnt = DM9K_TX_FIFO_SIZE; /* HARD CAP AT 3KiB */
392 tptr = 0;
393 while (cnt--) {
394 s->packet_copy_buffer[tptr++] = s->packet_buffer[idx];
395 idx = DM9K_WRAP_TX_INDEX(idx+1);
398 #ifdef DM9000_DEBUG
400 uint8_t *buf = &s->packet_copy_buffer[6];
401 DM9000_DBF("TX_Packet: %02x:%02x:%02x:%02x:%02x:%02x %d bytes from %04x\n",
402 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],
403 tptr, idx);
404 // hexdump(s->packet_copy_buffer, tptr);
406 #endif
408 s->dm9k_trpa = DM9K_CLIP_TX_INDEX(idx);
409 dm9k_dump_packet(s->packet_copy_buffer, s->dm9k_txpl);
410 /* We have the copy buffer, now we do the transmit */
411 qemu_send_packet(s->vc, s->packet_copy_buffer, s->dm9k_txpl);
413 /* Clear the "please xmit" bit */
414 s->dm9k_tcr &= ~DM9000_TCR_TXREQ;
415 /* Set the TXEND bit */
416 s->dm9k_nsr |= 1 << (2 + s->packet_index);
417 DM9000_DBF("TX: NSR=%02x PI=%d\n", s->dm9k_nsr, s->packet_index);
418 /* Claim a TX complete IRQ */
419 s->dm9k_isr |= DM9000_ISR_PTS; /* Packet transmitted latch */
420 /* And flip the next-packet bit */
421 s->packet_index++;
423 dm9000_raise_irq(s);
426 static void dm9000_mii_read(dm9000_state *s)
428 int mii_reg = (s->dm9k_epar) & 0x3f;
429 uint16_t ret = 0;
430 switch(mii_reg) {
431 case DM9000_MII_REG_BMCR:
432 ret = s->dm9k_mii_bmcr;
433 break;
434 case DM9000_MII_REG_STATUS:
435 ret = 0x782D; /* No 100/T4, Can 100/FD, Can 100/HD, Can 10/FD, Can 10/HD,
436 * No Preamble suppression, Autoneg complete, No remote fault,
437 * Can autoneg, link up, no jabber, extended capability */
438 break;
439 case DM9000_MII_REG_PHYID1:
440 ret = 0x0181;
441 break;
442 case DM9000_MII_REG_PHYID2:
443 ret = 0xB8C0;
444 break;
445 case DM9000_MII_REG_ANAR:
446 ret = s->dm9k_mii_anar;
447 break;
448 case DM9000_MII_REG_ANLPAR:
449 ret = 0x0400;
450 break;
451 case DM9000_MII_REG_ANER:
452 ret = 0x0001;
453 break;
454 case DM9000_MII_REG_DSCR:
455 ret = s->dm9k_mii_dscr;
456 break;
457 case DM9000_MII_REG_DSCSR:
458 ret = 0xF008;
459 break;
460 case DM9000_MII_REG_10BTCSR:
461 ret = 0x7800;
462 default:
463 printf("%s: Bad register 0x%lx\n", __FUNCTION__, (unsigned long)mii_reg);
465 s->dm9k_epdr = ret;
466 // DM9000_DBF("DM9000:MIIPHY: Read of MII reg %d gives %04x\n", mii_reg, s->dm9k_epdr);
469 static void dm9000_mii_write(dm9000_state *s)
471 int mii_reg = (s->dm9k_epar) & 0x3f;
472 DM9000_DBF("DM9000:MIIPHY: Write of MII reg %d value %04x\n", mii_reg, s->dm9k_epdr);
473 switch(mii_reg) {
474 case DM9000_MII_REG_BMCR:
475 s->dm9k_mii_bmcr = (s->dm9k_epdr &~0x8000);
476 if( s->dm9k_epdr & 0x8000 ) dm9000_soft_reset_mii(s);
477 break;
478 case DM9000_MII_REG_ANAR:
479 s->dm9k_mii_anar = s->dm9k_epdr;
480 break;
481 case DM9000_MII_REG_DSCR:
482 s->dm9k_mii_dscr = s->dm9k_epdr & ~0x0008;
483 break;
484 default:
485 printf("%s: Bad register 0x%lx=%4x\n", __FUNCTION__, (unsigned long)mii_reg, s->dm9k_epdr);
489 static void dm9000_write(void *opaque, target_phys_addr_t address,
490 uint32_t value)
492 dm9000_state *s = (dm9000_state *)opaque;
493 #ifdef DM9000_DEBUG
494 int suppress_debug = 0;
495 #endif
497 if (address == s->addr) {
498 // if( (value != DM9000_REG_MRCMD) && (value != DM9000_REG_MWCMD) )
499 // DM9000_DBF("DM9000: Address set to 0x%02x\n", value);
500 s->address = value;
501 return;
504 switch(s->address) {
505 case DM9000_REG_NCR:
506 DM9000_DBF("DM9000_REG_NCR: %02x=%04x\n", s->address, value);
507 s->dm9k_ncr = value | DM9000_NCR_FDX;
508 if (s->dm9k_ncr & DM9000_NCR_RESET)
509 dm9000_soft_reset(s);
510 break;
511 case DM9000_REG_NSR:
512 s->dm9k_nsr &= ~(value & ~DM9000_NSR_READONLY);
513 break;
514 case DM9000_REG_TCR:
515 s->dm9k_tcr = value & 0xFF;
516 if ( value & DM9000_TCR_TXREQ )
517 dm9000_do_transmit(s);
518 break;
519 case DM9000_REG_EPCR:
520 s->dm9k_epcr = value & 0xFF;
521 if( value & DM9000_MII_READ )
522 dm9000_mii_read(s);
523 else if( value & DM9000_MII_WRITE )
524 dm9000_mii_write(s);
525 break;
526 case DM9000_REG_RCR:
527 s->dm9k_rcr = value & 0xFF;
528 break;
530 case DM9000_REG_BPTR: /* can be ignored */
531 break;
533 case DM9000_REG_FCTR: {/* 0x09 Flow Control Threshold Register */
534 s->fc_high_mark = ((value >> 4) & 0xf) * 1024; // emit a pause packet time=0xffff
535 s->fc_low_mark = ((value) & 0xf) * 1024; // emit an unpause packet time=0x0000
536 s->fctr = value;
537 } break;
539 case DM9000_REG_FCR: /* 0x0a Flow Control Register */
540 s->fcr = value;
541 break;
543 case DM9000_REG_EPAR:
544 s->dm9k_epar = value & 0xFF;
545 break;
546 case DM9000_REG_EPDRL:
547 s->dm9k_epdr &= 0xFF00;
548 s->dm9k_epdr |= value & 0xFF;
549 break;
550 case DM9000_REG_EPDRH:
551 s->dm9k_epdr &= 0xFF;
552 s->dm9k_epdr |= (value & 0xFF) << 8;
553 break;
554 case DM9000_REG_PAR0 ... DM9000_REG_PAR5:
555 /* MAC address is set by the QEMU Nic */
556 s->macaddr[s->address - DM9000_REG_PAR0] = value;
557 break;
558 case DM9000_REG_MAR0 ... DM9000_REG_MAR7:
559 /* Multicast address is ignored */
560 s->mult[s->address - DM9000_REG_MAR0] = value;
561 break;
562 case DM9000_REG_GPCR:
563 case DM9000_REG_GPR: /* General purpose reg (GPIOs, LED?) */
564 break;
565 case DM9000_REG_SMCR:
566 if (value)
567 printf("%s: something playing with special mode ? 0x%lx=%x\n", __FUNCTION__, (unsigned long)s->address, value);
568 break;
569 case DM9000_REG_MRRL:
570 s->dm9k_mrr &= 0xFF00;
571 s->dm9k_mrr |= value & 0xFF;
572 break;
573 case DM9000_REG_MRRH:
574 s->dm9k_mrr &= 0xFF;
575 s->dm9k_mrr |= (value & 0xFF) << 8;
576 break;
577 case DM9000_REG_MWCMDX:
578 case DM9000_REG_MWCMD:
579 /* DM9KNOTE: This assumes a 16bit wide wiring */
580 s->packet_buffer[s->dm9k_mwr] = value & 0xFF;
581 s->packet_buffer[s->dm9k_mwr + 1] = (value >> 8) & 0xFF;
582 if (s->address == DM9000_REG_MWCMD) {
583 if (s->dm9k_imr & DM9000_IMR_AUTOWRAP)
584 s->dm9k_mwr = DM9K_WRAP_TX_INDEX(s->dm9k_mwr + 2);
585 else if (s->dm9k_mwr + 2 < DM9K_TX_FIFO_SIZE) // clip it
586 s->dm9k_mwr += 2;
588 #ifdef DM9000_DEBUG
589 suppress_debug = 1;
590 #endif
591 break;
592 case DM9000_REG_MWRL:
593 s->dm9k_mwr &= 0xFF00;
594 s->dm9k_mwr |= value & 0xFF;
595 break;
596 case DM9000_REG_MWRH:
597 s->dm9k_mwr &= 0xFF;
598 s->dm9k_mwr |= (value & 0xFF) << 8;
599 break;
600 case DM9000_REG_TXPLL:
601 s->dm9k_txpl &= 0xFF00;
602 s->dm9k_txpl |= value & 0xFF;
603 break;
604 case DM9000_REG_TXPLH:
605 s->dm9k_txpl &= 0xFF;
606 s->dm9k_txpl |= (value & 0xFF) << 8;
607 break;
608 case DM9000_REG_ISR:
609 s->dm9k_isr &= ~(value & 0x0F);
610 dm9000_raise_irq(s);
611 break;
612 case DM9000_REG_IMR:
613 if( !(s->dm9k_imr & DM9000_IMR_AUTOWRAP) && (value & DM9000_IMR_AUTOWRAP) )
614 s->dm9k_mrr = 0x0C00 | (s->dm9k_mrr & 0xFF);
615 s->dm9k_imr = value & 0xFF;
616 dm9000_raise_irq(s);
617 break;
618 default:
619 printf("%s: Bad register 0x%lx=%x\n", __FUNCTION__, (unsigned long)s->address, value);
621 #if 0 // def DM9000_DEBUG
622 if(!suppress_debug) DM9000_DBF("DM9000: Write value %02x=%04x\n", s->address, value);
623 #endif
626 static uint32_t dm9000_read(void *opaque, target_phys_addr_t address)
628 dm9000_state *s = (dm9000_state *)opaque;
629 uint32_t ret = 0;
630 #ifdef DM9000_DEBUG
631 int suppress_debug = 0;
632 #endif
634 if (address == s->addr)
635 return s->address;
636 switch(s->address) {
637 case DM9000_REG_NCR:
638 ret = s->dm9k_ncr;
639 break;
640 case DM9000_REG_NSR:
641 ret = s->dm9k_nsr;
642 /* Note, TX1END and TX2END are *CLEAR ON READ* */
643 s->dm9k_nsr &= ~(DM9000_NSR_TX1END | DM9000_NSR_TX2END);
644 break;
645 case DM9000_REG_TCR:
646 ret = s->dm9k_tcr;
647 break;
648 case DM9000_REG_TSR1:
649 case DM9000_REG_TSR2:
650 ret = 0x00; /* No error, yay! */
651 break;
652 case DM9000_REG_EPCR:
653 ret = s->dm9k_epcr;
654 break;
655 case DM9000_REG_RCR:
656 ret = s->dm9k_rcr;
657 break;
658 case DM9000_REG_RSR:
659 ret = s->dm9k_rsr;
660 break;
661 case DM9000_REG_EPAR:
662 ret = s->dm9k_epar;
663 break;
664 case DM9000_REG_EPDRL:
665 ret = s->dm9k_epdr & 0xFF;
666 break;
667 case DM9000_REG_EPDRH:
668 ret = (s->dm9k_epdr >> 8) & 0xFF;
669 break;
670 case DM9000_REG_PAR0...DM9000_REG_PAR5:
671 ret = s->macaddr[s->address - DM9000_REG_PAR0];
672 break;
673 case DM9000_REG_MAR0...DM9000_REG_MAR7:
674 ret = s->mult[s->address - DM9000_REG_MAR0];
675 break;
676 case DM9000_REG_TRPAL:
677 ret = s->dm9k_trpa & 0xFF;
678 break;
679 case DM9000_REG_TRPAH:
680 ret = s->dm9k_trpa >> 8;
681 break;
682 case DM9000_REG_RWPAL:
683 ret = s->dm9k_rwpa & 0xFF;
684 break;
685 case DM9000_REG_RWPAH:
686 ret = s->dm9k_rwpa >> 8;
687 break;
688 case DM9000_REG_VIDL:
689 ret = 0x46;
690 break;
691 case DM9000_REG_VIDH:
692 ret = 0x0A;
693 break;
694 case DM9000_REG_PIDL:
695 ret = 0x00;
696 break;
697 case DM9000_REG_PIDH:
698 ret = 0x90;
699 break;
700 case DM9000_REG_CHIPR:
701 ret = 0x00;
702 break;
703 case DM9000_REG_MRCMDX:
704 case DM9000_REG_MRCMD:
705 // drivers read the fifo looking for a 0x01 to indicate a packet is there,
706 // so we just return it a zero if there is nothing to read
707 if (s->dm9k_mrr == s->dm9k_rwpa)
708 ret = 0;
709 else {
710 /* DM9KNOTE: This assumes a 16bit wide wiring */
711 ret = s->packet_buffer[s->dm9k_mrr];
712 ret |= s->packet_buffer[s->dm9k_mrr + 1] << 8;
713 if( s->address == DM9000_REG_MRCMD ) {
714 if( s->dm9k_imr & DM9000_IMR_AUTOWRAP )
715 s->dm9k_mrr = DM9K_WRAP_RX_INDEX(s->dm9k_mrr + 2);
716 else if (s->dm9k_mrr + 2 < DM9K_FIFO_SIZE) // clip it
717 s->dm9k_mrr += 2;
720 #ifdef DM9000_DEBUG
721 if (s->address==DM9000_REG_MRCMD)
722 suppress_debug = 1;
723 #endif
724 break;
725 case DM9000_REG_MRRL:
726 ret = s->dm9k_mrr & 0xFF;
727 break;
728 case DM9000_REG_MRRH:
729 ret = s->dm9k_mrr >> 8;
730 break;
731 case DM9000_REG_MWRL:
732 ret = s->dm9k_mwr & 0xFF;
733 break;
734 case DM9000_REG_MWRH:
735 ret = s->dm9k_mwr >> 8;
736 break;
737 case DM9000_REG_TXPLL:
738 ret = s->dm9k_txpl & 0xFF;
739 break;
740 case DM9000_REG_TXPLH:
741 ret = s->dm9k_txpl >> 8;
742 break;
743 case DM9000_REG_ISR:
744 ret = s->dm9k_isr;
745 break;
746 case DM9000_REG_IMR:
747 ret = s->dm9k_imr;
748 break;
749 default:
750 ret = 0;
753 #if 0 // def DM9000_DEBUG
754 if(!suppress_debug) DM9000_DBF("DM9000: Read gives: %04x\n", ret);
755 #endif
756 return ret;
760 static int dm9000_can_receive(void *opaque)
762 dm9000_state *s = (dm9000_state *)opaque;
763 uint16_t rx_space = dm9000_get_rx_fifo_fill_state(s);
764 DM9000_DBF("DM9000:RX_Packet: Asked about RX, rwpa=%d mrr=%d => space is %d bytes\n",
765 s->dm9k_rwpa, s->dm9k_mrr, rx_space);
766 return rx_space > 1522;
769 #define POLYNOMINAL 0x04c11db6
771 /* From FreeBSD */
772 /* XXX: optimize */
773 static int compute_mcast_idx(const uint8_t *ep)
775 uint32_t crc;
776 int carry, i, j;
777 uint8_t b;
779 crc = 0xffffffff;
780 for (i = 0; i < 6; i++) {
781 b = *ep++;
782 for (j = 0; j < 8; j++) {
783 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
784 crc <<= 1;
785 b >>= 1;
786 if (carry)
787 crc = ((crc ^ POLYNOMINAL) | carry);
790 return (crc >> 26);
793 static void dm9000_receive(void *opaque, const uint8_t *buf, int size)
795 dm9000_state *s = (dm9000_state *)opaque;
796 uint16_t rxptr = s->dm9k_rwpa;
797 unsigned int mcast_idx = 0;
798 int pad = 4;
800 if (!(s->dm9k_rcr & DM9000_RCR_RXEN))
801 return;
802 s->dm9k_rsr = 0;
804 if (!(s->dm9k_rcr & DM9000_RCR_PRMSC)) {
805 if (buf[0] & 0x01) {
806 /* multi/broadcast */
807 if (!(s->dm9k_rcr & DM9000_RCR_ALL)) {
808 mcast_idx = compute_mcast_idx(buf);
809 if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
810 return;
811 s->dm9k_rsr |= DM9000_RSR_MF;
813 } else if (!memcmp(buf, s->macaddr, 6)) {
814 /* match */
815 } else {
816 return;
818 if (size < 64 && !(s->dm9k_rcr & DM9000_RCR_RUNT)) {
819 // printf("rcr %02x RUNT %d\n", s->dm9k_rcr, size);
820 s->dm9k_rsr |= DM9000_RSR_RF;
821 // return;
823 if (size > 1522 && (s->dm9k_rcr & DM9000_RCR_DIS_LONG))
824 return;
827 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",
828 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],
829 buf[6],buf[7],buf[8],buf[9],buf[10],buf[11],
830 size, rxptr, s->dm9k_rcr);
831 dm9k_dump_packet(buf, size);
834 * apparently even runt frames are padded to 64
836 if (size < 64)
837 pad = 64 - size;
839 rxptr = DM9K_CLIP_RX_INDEX(rxptr);
840 /* store header */
841 s->packet_buffer[rxptr] = 0x01; /* Packet read */
842 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
843 s->packet_buffer[rxptr] = 0x00; /* Status OK */
844 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
845 s->packet_buffer[rxptr] = (size+pad) & 0xFF; /* Size LOW */
846 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
847 s->packet_buffer[rxptr] = ((size+pad) >> 8) & 0xff; /* Size HIGH */
848 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
850 if (DM9K_FIFO_SIZE - rxptr > size) {
851 memcpy(s->packet_buffer + rxptr, buf, size);
852 rxptr += size;
853 } else {
854 int p1 = DM9K_FIFO_SIZE - rxptr;
855 memcpy(s->packet_buffer + rxptr, buf, p1);
856 buf += p1;
857 rxptr = DM9K_RX_FIFO_START; /* wrap */
858 p1 = size - p1; /* remaining */
859 memcpy(s->packet_buffer + rxptr, buf, p1);
860 rxptr += p1;
862 /* obligatory padding */
863 while (pad--) {
864 s->packet_buffer[rxptr] = 0;
865 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
868 s->dm9k_rwpa = DM9K_CLIP_RX_INDEX(rxptr);
869 s->dm9k_isr |= DM9000_ISR_PRS; /* RX interrupt, yay */
870 dm9000_raise_irq(s);
874 static CPUReadMemoryFunc *dm9000_readfn[] = {
875 dm9000_read,
876 dm9000_read,
877 dm9000_read
880 static CPUWriteMemoryFunc *dm9000_writefn[] = {
881 dm9000_write,
882 dm9000_write,
883 dm9000_write
886 /* initialises a dm9000 ethernet controller
887 * The dm9k has a single 16bit wide address and data port through which all
888 * operations are multiplexed, there is a single IRQ
890 void dm9000_init(NICInfo *nd, target_phys_addr_t base_addr,
891 uint32_t addr_offset, uint32_t data_offset,
892 qemu_irq irq)
894 dm9000_state *s;
895 int iomemtype;
897 s = (dm9000_state *)qemu_mallocz(sizeof(dm9000_state));
898 iomemtype = cpu_register_io_memory(0, dm9000_readfn,
899 dm9000_writefn, s);
900 cpu_register_physical_memory(base_addr, MAX(addr_offset, data_offset) + 4, iomemtype);
901 s->addr = addr_offset;
902 s->data = data_offset;
903 s->irq = irq;
904 memcpy(s->macaddr, nd->macaddr, 6);
905 memset(s->mult, 0xff, 8);
908 uint8_t * buf = s->macaddr;
909 printf("DM9000: INIT QEMU MAC : %02x:%02x:%02x:%02x:%02x:%02x\n",
910 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);
913 register_savevm("dm9000", 0, 0, dm9000_save, dm9000_load, s);
915 dm9000_hard_reset(s);
917 s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
918 dm9000_receive, dm9000_can_receive, s);
919 qemu_format_nic_info_str(s->vc, s->macaddr);