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