nand: boot code cleanup
[qemu/mini2440.git] / hw / dm9000.c
blobedc3a248de4f24fcecfd2b77741c5f89d6c1d56c
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_mrr = s->dm9k_mwr = 0;
335 s->dm9k_trpa = 0;
336 s->dm9k_rwpa = DM9K_RX_FIFO_START;
337 s->dm9k_imr = 0;
338 s->dm9k_isr = 0; /* 16 bit mode, no interrupts asserted */
339 s->dm9k_tcr = 0;
340 s->dm9k_rcr = 0;
341 s->dm9k_rsr = 0;
342 s->fcr = 0x38;
343 s->fctr = (3 << 4) | (7 << 0); // flow control high/low marks
344 s->fc_high_mark = 3 * 1024;
345 s->fc_low_mark = 8 * 1024;
347 s->packet_index = 0;
348 memset(s->packet_buffer, 0, sizeof(s->packet_buffer));
349 memset(s->packet_copy_buffer, 0, sizeof(s->packet_copy_buffer));
350 /* These registers have some bits "unaffected by software reset" */
351 /* Clear the reset bits */
352 s->dm9k_ncr &= DM9000_NCR_RESETPROTECT;
353 s->dm9k_nsr &= DM9000_NSR_RESETPROTECT;
354 /* Claim full duplex */
355 s->dm9k_ncr |= DM9000_NCR_FDX;
356 /* Set link status to 1 */
357 s->dm9k_nsr |= DM9000_NSR_LINKST;
358 /* dm9k_wcr is unaffected or reserved, never reset */
359 /* MII control regs */
360 s->dm9k_epcr = 0x00;
361 s->dm9k_epar = 0x40;
362 /* reset the MII */
363 dm9000_soft_reset_mii(s);
364 dm9000_raise_irq(s); /* Clear any potentially pending IRQ */
367 static void dm9000_hard_reset(dm9000_state *s)
369 s->dm9k_ncr = 0x00;
370 s->dm9k_nsr = 0x00;
371 s->dm9k_wcr = 0x00;
372 dm9000_soft_reset(s);
375 static uint16_t dm9000_get_rx_fifo_fill_state(dm9000_state *s)
377 uint16_t res;
378 if (s->dm9k_mrr >= s->dm9k_rwpa)
379 res = (DM9K_FIFO_SIZE-s->dm9k_rwpa) + (s->dm9k_mrr-DM9K_RX_FIFO_START);
380 else
381 res = s->dm9k_rwpa - s->dm9k_mrr;
382 return res;
385 static void dm9000_do_transmit(dm9000_state *s) {
386 uint16_t idx, cnt, tptr;
387 idx = s->dm9k_trpa;
389 cnt = s->dm9k_txpl;
390 if (cnt > DM9K_TX_FIFO_SIZE)
391 cnt = DM9K_TX_FIFO_SIZE; /* HARD CAP AT 3KiB */
393 tptr = 0;
394 while (cnt--) {
395 s->packet_copy_buffer[tptr++] = s->packet_buffer[idx];
396 idx = DM9K_WRAP_TX_INDEX(idx+1);
399 #ifdef DM9000_DEBUG
401 uint8_t *buf = &s->packet_copy_buffer[6];
402 DM9000_DBF("TX_Packet: %02x:%02x:%02x:%02x:%02x:%02x %d bytes from %04x\n",
403 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],
404 tptr, idx);
405 // hexdump(s->packet_copy_buffer, tptr);
407 #endif
409 s->dm9k_trpa = DM9K_CLIP_TX_INDEX(idx);
410 dm9k_dump_packet(s->packet_copy_buffer, s->dm9k_txpl);
411 /* We have the copy buffer, now we do the transmit */
412 qemu_send_packet(s->vc, s->packet_copy_buffer, s->dm9k_txpl);
414 /* Clear the "please xmit" bit */
415 s->dm9k_tcr &= ~DM9000_TCR_TXREQ;
416 /* Set the TXEND bit */
417 s->dm9k_nsr |= 1 << (2 + s->packet_index);
418 DM9000_DBF("TX: NSR=%02x PI=%d\n", s->dm9k_nsr, s->packet_index);
419 /* Claim a TX complete IRQ */
420 s->dm9k_isr |= DM9000_ISR_PTS; /* Packet transmitted latch */
421 /* And flip the next-packet bit */
422 s->packet_index++;
424 dm9000_raise_irq(s);
427 static void dm9000_mii_read(dm9000_state *s)
429 int mii_reg = (s->dm9k_epar) & 0x3f;
430 uint16_t ret = 0;
431 switch(mii_reg) {
432 case DM9000_MII_REG_BMCR:
433 ret = s->dm9k_mii_bmcr;
434 break;
435 case DM9000_MII_REG_STATUS:
436 ret = 0x782D; /* No 100/T4, Can 100/FD, Can 100/HD, Can 10/FD, Can 10/HD,
437 * No Preamble suppression, Autoneg complete, No remote fault,
438 * Can autoneg, link up, no jabber, extended capability */
439 break;
440 case DM9000_MII_REG_PHYID1:
441 ret = 0x0181;
442 break;
443 case DM9000_MII_REG_PHYID2:
444 ret = 0xB8C0;
445 break;
446 case DM9000_MII_REG_ANAR:
447 ret = s->dm9k_mii_anar;
448 break;
449 case DM9000_MII_REG_ANLPAR:
450 ret = 0x0400;
451 break;
452 case DM9000_MII_REG_ANER:
453 ret = 0x0001;
454 break;
455 case DM9000_MII_REG_DSCR:
456 ret = s->dm9k_mii_dscr;
457 break;
458 case DM9000_MII_REG_DSCSR:
459 ret = 0xF008;
460 break;
461 case DM9000_MII_REG_10BTCSR:
462 ret = 0x7800;
463 default:
464 printf("%s: Bad register 0x%lx\n", __FUNCTION__, (unsigned long)mii_reg);
466 s->dm9k_epdr = ret;
467 // DM9000_DBF("DM9000:MIIPHY: Read of MII reg %d gives %04x\n", mii_reg, s->dm9k_epdr);
470 static void dm9000_mii_write(dm9000_state *s)
472 int mii_reg = (s->dm9k_epar) & 0x3f;
473 DM9000_DBF("DM9000:MIIPHY: Write of MII reg %d value %04x\n", mii_reg, s->dm9k_epdr);
474 switch(mii_reg) {
475 case DM9000_MII_REG_BMCR:
476 s->dm9k_mii_bmcr = (s->dm9k_epdr &~0x8000);
477 if( s->dm9k_epdr & 0x8000 ) dm9000_soft_reset_mii(s);
478 break;
479 case DM9000_MII_REG_ANAR:
480 s->dm9k_mii_anar = s->dm9k_epdr;
481 break;
482 case DM9000_MII_REG_DSCR:
483 s->dm9k_mii_dscr = s->dm9k_epdr & ~0x0008;
484 break;
485 default:
486 printf("%s: Bad register 0x%lx=%4x\n", __FUNCTION__, (unsigned long)mii_reg, s->dm9k_epdr);
490 static void dm9000_write(void *opaque, target_phys_addr_t address,
491 uint32_t value)
493 dm9000_state *s = (dm9000_state *)opaque;
494 #ifdef DM9000_DEBUG
495 int suppress_debug = 0;
496 #endif
498 if (address == s->addr) {
499 // if( (value != DM9000_REG_MRCMD) && (value != DM9000_REG_MWCMD) )
500 // DM9000_DBF("DM9000: Address set to 0x%02x\n", value);
501 s->address = value;
502 return;
505 switch(s->address) {
506 case DM9000_REG_NCR:
507 DM9000_DBF("DM9000_REG_NCR: %02x=%04x\n", s->address, value);
508 s->dm9k_ncr = value | DM9000_NCR_FDX;
509 if (s->dm9k_ncr & DM9000_NCR_RESET)
510 dm9000_soft_reset(s);
511 break;
512 case DM9000_REG_NSR:
513 s->dm9k_nsr &= ~(value & ~DM9000_NSR_READONLY);
514 break;
515 case DM9000_REG_TCR:
516 s->dm9k_tcr = value & 0xFF;
517 if ( value & DM9000_TCR_TXREQ )
518 dm9000_do_transmit(s);
519 break;
520 case DM9000_REG_EPCR:
521 s->dm9k_epcr = value & 0xFF;
522 if( value & DM9000_MII_READ )
523 dm9000_mii_read(s);
524 else if( value & DM9000_MII_WRITE )
525 dm9000_mii_write(s);
526 break;
527 case DM9000_REG_RCR:
528 s->dm9k_rcr = value & 0xFF;
529 break;
531 case DM9000_REG_BPTR: /* can be ignored */
532 break;
534 case DM9000_REG_FCTR: {/* 0x09 Flow Control Threshold Register */
535 s->fc_high_mark = ((value >> 4) & 0xf) * 1024; // emit a pause packet time=0xffff
536 s->fc_low_mark = ((value) & 0xf) * 1024; // emit an unpause packet time=0x0000
537 s->fctr = value;
538 } break;
540 case DM9000_REG_FCR: /* 0x0a Flow Control Register */
541 s->fcr = value;
542 break;
544 case DM9000_REG_EPAR:
545 s->dm9k_epar = value & 0xFF;
546 break;
547 case DM9000_REG_EPDRL:
548 s->dm9k_epdr &= 0xFF00;
549 s->dm9k_epdr |= value & 0xFF;
550 break;
551 case DM9000_REG_EPDRH:
552 s->dm9k_epdr &= 0xFF;
553 s->dm9k_epdr |= (value & 0xFF) << 8;
554 break;
555 case DM9000_REG_PAR0 ... DM9000_REG_PAR5:
556 /* MAC address is set by the QEMU Nic */
557 s->macaddr[s->address - DM9000_REG_PAR0] = value;
558 break;
559 case DM9000_REG_MAR0 ... DM9000_REG_MAR7:
560 /* Multicast address is ignored */
561 s->mult[s->address - DM9000_REG_MAR0] = value;
562 break;
563 case DM9000_REG_GPCR:
564 case DM9000_REG_GPR: /* General purpose reg (GPIOs, LED?) */
565 break;
566 case DM9000_REG_SMCR:
567 if (value)
568 printf("%s: something playing with special mode ? 0x%lx=%x\n", __FUNCTION__, (unsigned long)s->address, value);
569 break;
570 case DM9000_REG_MRRL:
571 s->dm9k_mrr &= 0xFF00;
572 s->dm9k_mrr |= value & 0xFF;
573 break;
574 case DM9000_REG_MRRH:
575 s->dm9k_mrr &= 0xFF;
576 s->dm9k_mrr |= (value & 0xFF) << 8;
577 break;
578 case DM9000_REG_MWCMDX:
579 case DM9000_REG_MWCMD:
580 /* DM9KNOTE: This assumes a 16bit wide wiring */
581 s->packet_buffer[s->dm9k_mwr] = value & 0xFF;
582 s->packet_buffer[s->dm9k_mwr + 1] = (value >> 8) & 0xFF;
583 if (s->address == DM9000_REG_MWCMD) {
584 if (s->dm9k_imr & DM9000_IMR_AUTOWRAP)
585 s->dm9k_mwr = DM9K_WRAP_TX_INDEX(s->dm9k_mwr + 2);
586 else if (s->dm9k_mwr + 2 < DM9K_TX_FIFO_SIZE) // clip it
587 s->dm9k_mwr += 2;
589 #ifdef DM9000_DEBUG
590 suppress_debug = 1;
591 #endif
592 break;
593 case DM9000_REG_MWRL:
594 s->dm9k_mwr &= 0xFF00;
595 s->dm9k_mwr |= value & 0xFF;
596 break;
597 case DM9000_REG_MWRH:
598 s->dm9k_mwr &= 0xFF;
599 s->dm9k_mwr |= (value & 0xFF) << 8;
600 break;
601 case DM9000_REG_TXPLL:
602 s->dm9k_txpl &= 0xFF00;
603 s->dm9k_txpl |= value & 0xFF;
604 break;
605 case DM9000_REG_TXPLH:
606 s->dm9k_txpl &= 0xFF;
607 s->dm9k_txpl |= (value & 0xFF) << 8;
608 break;
609 case DM9000_REG_ISR:
610 s->dm9k_isr &= ~(value & 0x0F);
611 dm9000_raise_irq(s);
612 break;
613 case DM9000_REG_IMR:
614 if( !(s->dm9k_imr & DM9000_IMR_AUTOWRAP) && (value & DM9000_IMR_AUTOWRAP) )
615 s->dm9k_mrr = 0x0C00 | (s->dm9k_mrr & 0xFF);
616 s->dm9k_imr = value & 0xFF;
617 dm9000_raise_irq(s);
618 break;
619 default:
620 printf("%s: Bad register 0x%lx=%x\n", __FUNCTION__, (unsigned long)s->address, value);
622 #if 0 // def DM9000_DEBUG
623 if(!suppress_debug) DM9000_DBF("DM9000: Write value %02x=%04x\n", s->address, value);
624 #endif
627 static uint32_t dm9000_read(void *opaque, target_phys_addr_t address)
629 dm9000_state *s = (dm9000_state *)opaque;
630 uint32_t ret = 0;
631 #ifdef DM9000_DEBUG
632 int suppress_debug = 0;
633 #endif
635 if (address == s->addr)
636 return s->address;
637 switch(s->address) {
638 case DM9000_REG_NCR:
639 ret = s->dm9k_ncr;
640 break;
641 case DM9000_REG_NSR:
642 ret = s->dm9k_nsr;
643 /* Note, TX1END and TX2END are *CLEAR ON READ* */
644 s->dm9k_nsr &= ~(DM9000_NSR_TX1END | DM9000_NSR_TX2END);
645 break;
646 case DM9000_REG_TCR:
647 ret = s->dm9k_tcr;
648 break;
649 case DM9000_REG_TSR1:
650 case DM9000_REG_TSR2:
651 ret = 0x00; /* No error, yay! */
652 break;
653 case DM9000_REG_EPCR:
654 ret = s->dm9k_epcr;
655 break;
656 case DM9000_REG_RCR:
657 ret = s->dm9k_rcr;
658 break;
659 case DM9000_REG_RSR:
660 ret = s->dm9k_rsr;
661 break;
662 case DM9000_REG_EPAR:
663 ret = s->dm9k_epar;
664 break;
665 case DM9000_REG_EPDRL:
666 ret = s->dm9k_epdr & 0xFF;
667 break;
668 case DM9000_REG_EPDRH:
669 ret = (s->dm9k_epdr >> 8) & 0xFF;
670 break;
671 case DM9000_REG_PAR0...DM9000_REG_PAR5:
672 ret = s->macaddr[s->address - DM9000_REG_PAR0];
673 break;
674 case DM9000_REG_MAR0...DM9000_REG_MAR7:
675 ret = s->mult[s->address - DM9000_REG_MAR0];
676 break;
677 case DM9000_REG_TRPAL:
678 ret = s->dm9k_trpa & 0xFF;
679 break;
680 case DM9000_REG_TRPAH:
681 ret = s->dm9k_trpa >> 8;
682 break;
683 case DM9000_REG_RWPAL:
684 ret = s->dm9k_rwpa & 0xFF;
685 break;
686 case DM9000_REG_RWPAH:
687 ret = s->dm9k_rwpa >> 8;
688 break;
689 case DM9000_REG_VIDL:
690 ret = 0x46;
691 break;
692 case DM9000_REG_VIDH:
693 ret = 0x0A;
694 break;
695 case DM9000_REG_PIDL:
696 ret = 0x00;
697 break;
698 case DM9000_REG_PIDH:
699 ret = 0x90;
700 break;
701 case DM9000_REG_CHIPR:
702 ret = 0x00;
703 break;
704 case DM9000_REG_MRCMDX:
705 case DM9000_REG_MRCMD:
706 // drivers read the fifo looking for a 0x01 to indicate a packet is there,
707 // so we just return it a zero if there is nothing to read
708 if (s->dm9k_mrr == s->dm9k_rwpa)
709 ret = 0;
710 else {
711 /* DM9KNOTE: This assumes a 16bit wide wiring */
712 ret = s->packet_buffer[s->dm9k_mrr];
713 ret |= s->packet_buffer[s->dm9k_mrr + 1] << 8;
714 if( s->address == DM9000_REG_MRCMD ) {
715 if( s->dm9k_imr & DM9000_IMR_AUTOWRAP )
716 s->dm9k_mrr = DM9K_WRAP_RX_INDEX(s->dm9k_mrr + 2);
717 else if (s->dm9k_mrr + 2 < DM9K_FIFO_SIZE) // clip it
718 s->dm9k_mrr += 2;
721 #ifdef DM9000_DEBUG
722 if (s->address==DM9000_REG_MRCMD)
723 suppress_debug = 1;
724 #endif
725 break;
726 case DM9000_REG_MRRL:
727 ret = s->dm9k_mrr & 0xFF;
728 break;
729 case DM9000_REG_MRRH:
730 ret = s->dm9k_mrr >> 8;
731 break;
732 case DM9000_REG_MWRL:
733 ret = s->dm9k_mwr & 0xFF;
734 break;
735 case DM9000_REG_MWRH:
736 ret = s->dm9k_mwr >> 8;
737 break;
738 case DM9000_REG_TXPLL:
739 ret = s->dm9k_txpl & 0xFF;
740 break;
741 case DM9000_REG_TXPLH:
742 ret = s->dm9k_txpl >> 8;
743 break;
744 case DM9000_REG_ISR:
745 ret = s->dm9k_isr;
746 break;
747 case DM9000_REG_IMR:
748 ret = s->dm9k_imr;
749 break;
750 default:
751 ret = 0;
754 #if 0 // def DM9000_DEBUG
755 if(!suppress_debug) DM9000_DBF("DM9000: Read gives: %04x\n", ret);
756 #endif
757 return ret;
761 static int dm9000_can_receive(void *opaque)
763 dm9000_state *s = (dm9000_state *)opaque;
764 uint16_t rx_space = dm9000_get_rx_fifo_fill_state(s);
765 DM9000_DBF("DM9000:RX_Packet: Asked about RX, rwpa=%d mrr=%d => space is %d bytes\n",
766 s->dm9k_rwpa, s->dm9k_mrr, rx_space);
767 return rx_space > 1522;
770 #define POLYNOMINAL 0x04c11db6
772 /* From FreeBSD */
773 /* XXX: optimize */
774 static int compute_mcast_idx(const uint8_t *ep)
776 uint32_t crc;
777 int carry, i, j;
778 uint8_t b;
780 crc = 0xffffffff;
781 for (i = 0; i < 6; i++) {
782 b = *ep++;
783 for (j = 0; j < 8; j++) {
784 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
785 crc <<= 1;
786 b >>= 1;
787 if (carry)
788 crc = ((crc ^ POLYNOMINAL) | carry);
791 return (crc >> 26);
794 static void dm9000_receive(void *opaque, const uint8_t *buf, int size)
796 dm9000_state *s = (dm9000_state *)opaque;
797 uint16_t rxptr = s->dm9k_rwpa;
798 unsigned int mcast_idx = 0;
799 int pad = 4;
801 if (!(s->dm9k_rcr & DM9000_RCR_RXEN))
802 return;
803 s->dm9k_rsr = 0;
805 if (!(s->dm9k_rcr & DM9000_RCR_PRMSC)) {
806 if (buf[0] & 0x01) {
807 /* multi/broadcast */
808 if (!(s->dm9k_rcr & DM9000_RCR_ALL)) {
809 mcast_idx = compute_mcast_idx(buf);
810 if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
811 return;
812 s->dm9k_rsr |= DM9000_RSR_MF;
814 } else if (!memcmp(buf, s->macaddr, 6)) {
815 /* match */
816 } else {
817 return;
819 if (size < 64 && !(s->dm9k_rcr & DM9000_RCR_RUNT)) {
820 // printf("rcr %02x RUNT %d\n", s->dm9k_rcr, size);
821 s->dm9k_rsr |= DM9000_RSR_RF;
822 // return;
824 if (size > 1522 && (s->dm9k_rcr & DM9000_RCR_DIS_LONG))
825 return;
828 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",
829 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],
830 buf[6],buf[7],buf[8],buf[9],buf[10],buf[11],
831 size, rxptr, s->dm9k_rcr);
832 dm9k_dump_packet(buf, size);
835 * apparently even runt frames are padded to 64
837 if (size < 64)
838 pad = 64 - size;
840 rxptr = DM9K_CLIP_RX_INDEX(rxptr);
841 /* store header */
842 s->packet_buffer[rxptr] = 0x01; /* Packet read */
843 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
844 s->packet_buffer[rxptr] = 0x00; /* Status OK */
845 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
846 s->packet_buffer[rxptr] = (size+pad) & 0xFF; /* Size LOW */
847 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
848 s->packet_buffer[rxptr] = ((size+pad) >> 8) & 0xff; /* Size HIGH */
849 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
851 if (DM9K_FIFO_SIZE - rxptr > size) {
852 memcpy(s->packet_buffer + rxptr, buf, size);
853 rxptr += size;
854 } else {
855 int p1 = DM9K_FIFO_SIZE - rxptr;
856 memcpy(s->packet_buffer + rxptr, buf, p1);
857 buf += p1;
858 rxptr = DM9K_RX_FIFO_START; /* wrap */
859 p1 = size - p1; /* remaining */
860 memcpy(s->packet_buffer + rxptr, buf, p1);
861 rxptr += p1;
863 /* obligatory padding */
864 while (pad--) {
865 s->packet_buffer[rxptr] = 0;
866 rxptr = DM9K_WRAP_RX_INDEX(rxptr+1);
869 s->dm9k_rwpa = DM9K_CLIP_RX_INDEX(rxptr);
870 s->dm9k_isr |= DM9000_ISR_PRS; /* RX interrupt, yay */
871 dm9000_raise_irq(s);
875 static CPUReadMemoryFunc *dm9000_readfn[] = {
876 dm9000_read,
877 dm9000_read,
878 dm9000_read
881 static CPUWriteMemoryFunc *dm9000_writefn[] = {
882 dm9000_write,
883 dm9000_write,
884 dm9000_write
887 static void dm9000_cleanup(VLANClientState *vc)
889 /* dm9000_state *s = (dm9000_state *)vc->opaque; */
892 /* initialises a dm9000 ethernet controller
893 * The dm9k has a single 16bit wide address and data port through which all
894 * operations are multiplexed, there is a single IRQ
896 void dm9000_init(NICInfo *nd, target_phys_addr_t base_addr,
897 uint32_t addr_offset, uint32_t data_offset,
898 qemu_irq irq)
900 dm9000_state *s;
901 int iomemtype;
903 s = (dm9000_state *)qemu_mallocz(sizeof(dm9000_state));
904 iomemtype = cpu_register_io_memory(0, dm9000_readfn,
905 dm9000_writefn, s);
906 cpu_register_physical_memory(base_addr, MAX(addr_offset, data_offset) + 4, iomemtype);
907 s->addr = addr_offset;
908 s->data = data_offset;
909 s->irq = irq;
910 memcpy(s->macaddr, nd->macaddr, 6);
911 memset(s->mult, 0xff, 8);
914 uint8_t * buf = s->macaddr;
915 printf("DM9000: INIT QEMU MAC : %02x:%02x:%02x:%02x:%02x:%02x\n",
916 buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);
919 register_savevm("dm9000", 0, 0, dm9000_save, dm9000_load, s);
921 dm9000_hard_reset(s);
923 s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
924 dm9000_receive, dm9000_can_receive,
925 dm9000_cleanup, s);
926 qemu_format_nic_info_str(s->vc, s->macaddr);