source: trunk/packages/xen-3.1/xen-3.1/tools/ioemu/hw/ne2000.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 24.7 KB
Line 
1/*
2 * QEMU NE2000 emulation
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#include "vl.h"
25
26/* debug NE2000 card */
27//#define DEBUG_NE2000
28
29#define MAX_ETH_FRAME_SIZE 1514
30
31#define E8390_CMD       0x00  /* The command register (for all pages) */
32/* Page 0 register offsets. */
33#define EN0_CLDALO      0x01    /* Low byte of current local dma addr  RD */
34#define EN0_STARTPG     0x01    /* Starting page of ring bfr WR */
35#define EN0_CLDAHI      0x02    /* High byte of current local dma addr  RD */
36#define EN0_STOPPG      0x02    /* Ending page +1 of ring bfr WR */
37#define EN0_BOUNDARY    0x03    /* Boundary page of ring bfr RD WR */
38#define EN0_TSR         0x04    /* Transmit status reg RD */
39#define EN0_TPSR        0x04    /* Transmit starting page WR */
40#define EN0_NCR         0x05    /* Number of collision reg RD */
41#define EN0_TCNTLO      0x05    /* Low  byte of tx byte count WR */
42#define EN0_FIFO        0x06    /* FIFO RD */
43#define EN0_TCNTHI      0x06    /* High byte of tx byte count WR */
44#define EN0_ISR         0x07    /* Interrupt status reg RD WR */
45#define EN0_CRDALO      0x08    /* low byte of current remote dma address RD */
46#define EN0_RSARLO      0x08    /* Remote start address reg 0 */
47#define EN0_CRDAHI      0x09    /* high byte, current remote dma address RD */
48#define EN0_RSARHI      0x09    /* Remote start address reg 1 */
49#define EN0_RCNTLO      0x0a    /* Remote byte count reg WR */
50#define EN0_RTL8029ID0  0x0a    /* Realtek ID byte #1 RD */
51#define EN0_RCNTHI      0x0b    /* Remote byte count reg WR */
52#define EN0_RTL8029ID1  0x0b    /* Realtek ID byte #2 RD */
53#define EN0_RSR         0x0c    /* rx status reg RD */
54#define EN0_RXCR        0x0c    /* RX configuration reg WR */
55#define EN0_TXCR        0x0d    /* TX configuration reg WR */
56#define EN0_COUNTER0    0x0d    /* Rcv alignment error counter RD */
57#define EN0_DCFG        0x0e    /* Data configuration reg WR */
58#define EN0_COUNTER1    0x0e    /* Rcv CRC error counter RD */
59#define EN0_IMR         0x0f    /* Interrupt mask reg WR */
60#define EN0_COUNTER2    0x0f    /* Rcv missed frame error counter RD */
61
62#define EN1_PHYS        0x11
63#define EN1_CURPAG      0x17
64#define EN1_MULT        0x18
65
66#define EN2_STARTPG     0x21    /* Starting page of ring bfr RD */
67#define EN2_STOPPG      0x22    /* Ending page +1 of ring bfr RD */
68
69#define EN3_CONFIG0     0x33
70#define EN3_CONFIG1     0x34
71#define EN3_CONFIG2     0x35
72#define EN3_CONFIG3     0x36
73
74/*  Register accessed at EN_CMD, the 8390 base addr.  */
75#define E8390_STOP      0x01    /* Stop and reset the chip */
76#define E8390_START     0x02    /* Start the chip, clear reset */
77#define E8390_TRANS     0x04    /* Transmit a frame */
78#define E8390_RREAD     0x08    /* Remote read */
79#define E8390_RWRITE    0x10    /* Remote write  */
80#define E8390_NODMA     0x20    /* Remote DMA */
81#define E8390_PAGE0     0x00    /* Select page chip registers */
82#define E8390_PAGE1     0x40    /* using the two high-order bits */
83#define E8390_PAGE2     0x80    /* Page 3 is invalid. */
84
85/* Bits in EN0_ISR - Interrupt status register */
86#define ENISR_RX        0x01    /* Receiver, no error */
87#define ENISR_TX        0x02    /* Transmitter, no error */
88#define ENISR_RX_ERR    0x04    /* Receiver, with error */
89#define ENISR_TX_ERR    0x08    /* Transmitter, with error */
90#define ENISR_OVER      0x10    /* Receiver overwrote the ring */
91#define ENISR_COUNTERS  0x20    /* Counters need emptying */
92#define ENISR_RDC       0x40    /* remote dma complete */
93#define ENISR_RESET     0x80    /* Reset completed */
94#define ENISR_ALL       0x3f    /* Interrupts we will enable */
95
96/* Bits in received packet status byte and EN0_RSR*/
97#define ENRSR_RXOK      0x01    /* Received a good packet */
98#define ENRSR_CRC       0x02    /* CRC error */
99#define ENRSR_FAE       0x04    /* frame alignment error */
100#define ENRSR_FO        0x08    /* FIFO overrun */
101#define ENRSR_MPA       0x10    /* missed pkt */
102#define ENRSR_PHY       0x20    /* physical/multicast address */
103#define ENRSR_DIS       0x40    /* receiver disable. set in monitor mode */
104#define ENRSR_DEF       0x80    /* deferring */
105
106/* Transmitted packet status, EN0_TSR. */
107#define ENTSR_PTX 0x01  /* Packet transmitted without error */
108#define ENTSR_ND  0x02  /* The transmit wasn't deferred. */
109#define ENTSR_COL 0x04  /* The transmit collided at least once. */
110#define ENTSR_ABT 0x08  /* The transmit collided 16 times, and was deferred. */
111#define ENTSR_CRS 0x10  /* The carrier sense was lost. */
112#define ENTSR_FU  0x20  /* A "FIFO underrun" occurred during transmit. */
113#define ENTSR_CDH 0x40  /* The collision detect "heartbeat" signal was lost. */
114#define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
115
116#define NE2000_PMEM_SIZE    (32*1024)
117#define NE2000_PMEM_START   (16*1024)
118#define NE2000_PMEM_END     (NE2000_PMEM_SIZE+NE2000_PMEM_START)
119#define NE2000_MEM_SIZE     NE2000_PMEM_END
120
121typedef struct NE2000State {
122    uint8_t cmd;
123    uint32_t start;
124    uint32_t stop;
125    uint8_t boundary;
126    uint8_t tsr;
127    uint8_t tpsr;
128    uint16_t tcnt;
129    uint16_t rcnt;
130    uint32_t rsar;
131    uint8_t rsr;
132    uint8_t rxcr;
133    uint8_t isr;
134    uint8_t dcfg;
135    uint8_t imr;
136    uint8_t phys[6]; /* mac address */
137    uint8_t curpag;
138    uint8_t mult[8]; /* multicast mask array */
139    int irq;
140    int tainted;
141    PCIDevice *pci_dev;
142    VLANClientState *vc;
143    uint8_t macaddr[6];
144    uint8_t mem[NE2000_MEM_SIZE];
145} NE2000State;
146
147static void ne2000_reset(NE2000State *s)
148{
149    int i;
150
151    s->isr = ENISR_RESET;
152    memcpy(s->mem, s->macaddr, 6);
153    s->mem[14] = 0x57;
154    s->mem[15] = 0x57;
155
156    /* duplicate prom data */
157    for(i = 15;i >= 0; i--) {
158        s->mem[2 * i] = s->mem[i];
159        s->mem[2 * i + 1] = s->mem[i];
160    }
161}
162
163static void ne2000_update_irq(NE2000State *s)
164{
165    int isr;
166    isr = (s->isr & s->imr) & 0x7f;
167#if defined(DEBUG_NE2000)
168    printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
169           s->irq, isr ? 1 : 0, s->isr, s->imr);
170#endif
171    if (s->irq == 16) {
172        /* PCI irq */
173        pci_set_irq(s->pci_dev, 0, (isr != 0));
174    } else {
175        /* ISA irq */
176        pic_set_irq(s->irq, (isr != 0));
177    }
178}
179
180#define POLYNOMIAL 0x04c11db6
181
182/* From FreeBSD */
183/* XXX: optimize */
184static int compute_mcast_idx(const uint8_t *ep)
185{
186    uint32_t crc;
187    int carry, i, j;
188    uint8_t b;
189
190    crc = 0xffffffff;
191    for (i = 0; i < 6; i++) {
192        b = *ep++;
193        for (j = 0; j < 8; j++) {
194            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
195            crc <<= 1;
196            b >>= 1;
197            if (carry)
198                crc = ((crc ^ POLYNOMIAL) | carry);
199        }
200    }
201    return (crc >> 26);
202}
203
204static int ne2000_buffer_full(NE2000State *s)
205{
206    int avail, index, boundary;
207
208    index = s->curpag << 8;
209    boundary = s->boundary << 8;
210    if (index <= boundary)
211        avail = boundary - index;
212    else
213        avail = (s->stop - s->start) - (index - boundary);
214    if (avail < (MAX_ETH_FRAME_SIZE + 4))
215        return 1;
216    return 0;
217}
218
219static int ne2000_can_receive(void *opaque)
220{
221    NE2000State *s = opaque;
222   
223    if (s->cmd & E8390_STOP)
224        return 1;
225    return !ne2000_buffer_full(s);
226}
227
228#define MIN_BUF_SIZE 60
229
230static inline int ne2000_valid_ring_addr(NE2000State *s, unsigned int addr)
231{
232    addr <<= 8;
233    return addr < s->stop && addr >= s->start;
234}
235
236static inline int ne2000_check_state(NE2000State *s)
237{
238    if (!s->tainted)
239        return 0;
240
241    if (s->start >= s->stop || s->stop > NE2000_MEM_SIZE)
242        return -EINVAL;
243
244    if (!ne2000_valid_ring_addr(s, s->curpag))
245        return -EINVAL;
246
247    s->tainted = 0;
248    return 0;
249}
250
251static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
252{
253    NE2000State *s = opaque;
254    uint8_t *p;
255    int total_len, next, avail, len, index, mcast_idx;
256    uint8_t buf1[60];
257    static const uint8_t broadcast_macaddr[6] = 
258        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
259   
260#if defined(DEBUG_NE2000)
261    printf("NE2000: received len=%d\n", size);
262#endif
263
264    if (ne2000_check_state(s))
265        return;
266
267    if (!ne2000_valid_ring_addr(s, s->boundary))
268        return;
269
270    if (s->cmd & E8390_STOP || ne2000_buffer_full(s))
271        return;
272   
273    /* XXX: check this */
274    if (s->rxcr & 0x10) {
275        /* promiscuous: receive all */
276    } else {
277        if (!memcmp(buf,  broadcast_macaddr, 6)) {
278            /* broadcast address */
279            if (!(s->rxcr & 0x04))
280                return;
281        } else if (buf[0] & 0x01) {
282            /* multicast */
283            if (!(s->rxcr & 0x08))
284                return;
285            mcast_idx = compute_mcast_idx(buf);
286            if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
287                return;
288        } else if (s->mem[0] == buf[0] &&
289                   s->mem[2] == buf[1] &&                   
290                   s->mem[4] == buf[2] &&           
291                   s->mem[6] == buf[3] &&           
292                   s->mem[8] == buf[4] &&           
293                   s->mem[10] == buf[5]) {
294            /* match */
295        } else {
296            return;
297        }
298    }
299
300
301    /* if too small buffer, then expand it */
302    if (size < MIN_BUF_SIZE) {
303        memcpy(buf1, buf, size);
304        memset(buf1 + size, 0, MIN_BUF_SIZE - size);
305        buf = buf1;
306        size = MIN_BUF_SIZE;
307    }
308
309    index = s->curpag << 8;
310    /* 4 bytes for header */
311    total_len = size + 4;
312    /* address for next packet (4 bytes for CRC) */
313    next = index + ((total_len + 4 + 255) & ~0xff);
314    if (next >= s->stop)
315        next -= (s->stop - s->start);
316    /* prepare packet header */
317    p = s->mem + index;
318    s->rsr = ENRSR_RXOK; /* receive status */
319    /* XXX: check this */
320    if (buf[0] & 0x01)
321        s->rsr |= ENRSR_PHY;
322    p[0] = s->rsr;
323    p[1] = next >> 8;
324    p[2] = total_len;
325    p[3] = total_len >> 8;
326    index += 4;
327
328    /* write packet data */
329    while (size > 0) {
330        avail = s->stop - index;
331        len = size;
332        if (len > avail)
333            len = avail;
334        memcpy(s->mem + index, buf, len);
335        buf += len;
336        index += len;
337        if (index == s->stop)
338            index = s->start;
339        size -= len;
340    }
341    s->curpag = next >> 8;
342
343    /* now we can signal we have receive something */
344    s->isr |= ENISR_RX;
345    ne2000_update_irq(s);
346}
347
348static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
349{
350    NE2000State *s = opaque;
351    int offset, page, index;
352
353    addr &= 0xf;
354#ifdef DEBUG_NE2000
355    printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
356#endif
357    if (addr == E8390_CMD) {
358        /* control register */
359        s->cmd = val;
360        if (!(val & E8390_STOP)) { /* START bit makes no sense on RTL8029... */
361            s->isr &= ~ENISR_RESET;
362            /* test specific case: zero length transfert */
363            if ((val & (E8390_RREAD | E8390_RWRITE)) &&
364                s->rcnt == 0) {
365                s->isr |= ENISR_RDC;
366                ne2000_update_irq(s);
367            }
368            if (val & E8390_TRANS) {
369                index = (s->tpsr << 8);
370                /* XXX: next 2 lines are a hack to make netware 3.11 work */ 
371                if (index >= NE2000_PMEM_END)
372                    index -= NE2000_PMEM_SIZE;
373                /* fail safe: check range on the transmitted length  */
374                if (index + s->tcnt <= NE2000_PMEM_END) {
375                    qemu_send_packet(s->vc, s->mem + index, s->tcnt);
376                }
377                /* signal end of transfert */
378                s->tsr = ENTSR_PTX;
379                s->isr |= ENISR_TX;
380                s->cmd &= ~E8390_TRANS; 
381                ne2000_update_irq(s);
382            }
383        }
384    } else {
385        page = s->cmd >> 6;
386        offset = addr | (page << 4);
387        switch(offset) {
388        case EN0_STARTPG:
389            s->start = val << 8;
390            s->tainted = 1;
391            break;
392        case EN0_STOPPG:
393            s->stop = val << 8;
394            s->tainted = 1;
395            break;
396        case EN0_BOUNDARY:
397            s->boundary = val;
398            break;
399        case EN0_IMR:
400            s->imr = val;
401            ne2000_update_irq(s);
402            break;
403        case EN0_TPSR:
404            s->tpsr = val;
405            break;
406        case EN0_TCNTLO:
407            s->tcnt = (s->tcnt & 0xff00) | val;
408            break;
409        case EN0_TCNTHI:
410            s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
411            break;
412        case EN0_RSARLO:
413            s->rsar = (s->rsar & 0xff00) | val;
414            break;
415        case EN0_RSARHI:
416            s->rsar = (s->rsar & 0x00ff) | (val << 8);
417            break;
418        case EN0_RCNTLO:
419            s->rcnt = (s->rcnt & 0xff00) | val;
420            break;
421        case EN0_RCNTHI:
422            s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
423            break;
424        case EN0_RXCR:
425            s->rxcr = val;
426            break;
427        case EN0_DCFG:
428            s->dcfg = val;
429            break;
430        case EN0_ISR:
431            s->isr &= ~(val & 0x7f);
432            ne2000_update_irq(s);
433            break;
434        case EN1_PHYS ... EN1_PHYS + 5:
435            s->phys[offset - EN1_PHYS] = val;
436            break;
437        case EN1_CURPAG:
438            s->curpag = val;
439            s->tainted = 1;
440            break;
441        case EN1_MULT ... EN1_MULT + 7:
442            s->mult[offset - EN1_MULT] = val;
443            break;
444        }
445    }
446}
447
448static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
449{
450    NE2000State *s = opaque;
451    int offset, page, ret;
452
453    addr &= 0xf;
454    if (addr == E8390_CMD) {
455        ret = s->cmd;
456    } else {
457        page = s->cmd >> 6;
458        offset = addr | (page << 4);
459        switch(offset) {
460        case EN0_TSR:
461            ret = s->tsr;
462            break;
463        case EN0_BOUNDARY:
464            ret = s->boundary;
465            break;
466        case EN0_ISR:
467            ret = s->isr;
468            break;
469        case EN0_RSARLO:
470            ret = s->rsar & 0x00ff;
471            break;
472        case EN0_RSARHI:
473            ret = s->rsar >> 8;
474            break;
475        case EN1_PHYS ... EN1_PHYS + 5:
476            ret = s->phys[offset - EN1_PHYS];
477            break;
478        case EN1_CURPAG:
479            ret = s->curpag;
480            break;
481        case EN1_MULT ... EN1_MULT + 7:
482            ret = s->mult[offset - EN1_MULT];
483            break;
484        case EN0_RSR:
485            ret = s->rsr;
486            break;
487        case EN2_STARTPG:
488            ret = s->start >> 8;
489            break;
490        case EN2_STOPPG:
491            ret = s->stop >> 8;
492            break;
493        case EN0_RTL8029ID0:
494            ret = 0x50;
495            break;
496        case EN0_RTL8029ID1:
497            ret = 0x43;
498            break;
499        case EN3_CONFIG0:
500            ret = 0;            /* 10baseT media */
501            break;
502        case EN3_CONFIG2:
503            ret = 0x40;         /* 10baseT active */
504            break;
505        case EN3_CONFIG3:
506            ret = 0x40;         /* Full duplex */
507            break;
508        default:
509            ret = 0x00;
510            break;
511        }
512    }
513#ifdef DEBUG_NE2000
514    printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
515#endif
516    return ret;
517}
518
519static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr, 
520                                     uint32_t val)
521{
522    if (addr < 32 || 
523        (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
524        s->mem[addr] = val;
525    }
526}
527
528static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr, 
529                                     uint32_t val)
530{
531    addr &= ~1; /* XXX: check exact behaviour if not even */
532    if (addr < 32 || 
533        (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
534        *(uint16_t *)(s->mem + addr) = cpu_to_le16(val);
535    }
536}
537
538static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr, 
539                                     uint32_t val)
540{
541    addr &= ~1; /* XXX: check exact behaviour if not even */
542    if (addr < 32 || 
543        (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE - 2)) {
544        cpu_to_le32wu((uint32_t *)(s->mem + addr), val);
545    }
546}
547
548static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr)
549{
550    if (addr < 32 || 
551        (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
552        return s->mem[addr];
553    } else {
554        return 0xff;
555    }
556}
557
558static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr)
559{
560    addr &= ~1; /* XXX: check exact behaviour if not even */
561    if (addr < 32 || 
562        (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
563        return le16_to_cpu(*(uint16_t *)(s->mem + addr));
564    } else {
565        return 0xffff;
566    }
567}
568
569static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr)
570{
571    addr &= ~1; /* XXX: check exact behaviour if not even */
572    if (addr < 32 || 
573        (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE - 2)) {
574        return le32_to_cpupu((uint32_t *)(s->mem + addr));
575    } else {
576        return 0xffffffff;
577    }
578}
579
580static inline void ne2000_dma_update(NE2000State *s, int len)
581{
582    s->rsar += len;
583    /* wrap */
584    /* XXX: check what to do if rsar > stop */
585    if (s->rsar == s->stop)
586        s->rsar = s->start;
587
588    if (s->rcnt <= len) {
589        s->rcnt = 0;
590        /* signal end of transfert */
591        s->isr |= ENISR_RDC;
592        ne2000_update_irq(s);
593    } else {
594        s->rcnt -= len;
595    }
596}
597
598static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
599{
600    NE2000State *s = opaque;
601
602#ifdef DEBUG_NE2000
603    printf("NE2000: asic write val=0x%04x\n", val);
604#endif
605    if (s->rcnt == 0)
606        return;
607    if (s->dcfg & 0x01) {
608        /* 16 bit access */
609        ne2000_mem_writew(s, s->rsar, val);
610        ne2000_dma_update(s, 2);
611    } else {
612        /* 8 bit access */
613        ne2000_mem_writeb(s, s->rsar, val);
614        ne2000_dma_update(s, 1);
615    }
616}
617
618static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
619{
620    NE2000State *s = opaque;
621    int ret;
622
623    if (s->dcfg & 0x01) {
624        /* 16 bit access */
625        ret = ne2000_mem_readw(s, s->rsar);
626        ne2000_dma_update(s, 2);
627    } else {
628        /* 8 bit access */
629        ret = ne2000_mem_readb(s, s->rsar);
630        ne2000_dma_update(s, 1);
631    }
632#ifdef DEBUG_NE2000
633    printf("NE2000: asic read val=0x%04x\n", ret);
634#endif
635    return ret;
636}
637
638static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
639{
640    NE2000State *s = opaque;
641
642#ifdef DEBUG_NE2000
643    printf("NE2000: asic writel val=0x%04x\n", val);
644#endif
645    if (s->rcnt == 0)
646        return;
647    /* 32 bit access */
648    ne2000_mem_writel(s, s->rsar, val);
649    ne2000_dma_update(s, 4);
650}
651
652static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr)
653{
654    NE2000State *s = opaque;
655    int ret;
656
657    /* 32 bit access */
658    ret = ne2000_mem_readl(s, s->rsar);
659    ne2000_dma_update(s, 4);
660#ifdef DEBUG_NE2000
661    printf("NE2000: asic readl val=0x%04x\n", ret);
662#endif
663    return ret;
664}
665
666static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val)
667{
668    /* nothing to do (end of reset pulse) */
669}
670
671static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr)
672{
673    NE2000State *s = opaque;
674    ne2000_reset(s);
675    return 0;
676}
677
678static void ne2000_save(QEMUFile* f,void* opaque)
679{
680        NE2000State* s=(NE2000State*)opaque;
681
682        qemu_put_8s(f, &s->rxcr);
683
684        qemu_put_8s(f, &s->cmd);
685        qemu_put_be32s(f, &s->start);
686        qemu_put_be32s(f, &s->stop);
687        qemu_put_8s(f, &s->boundary);
688        qemu_put_8s(f, &s->tsr);
689        qemu_put_8s(f, &s->tpsr);
690        qemu_put_be16s(f, &s->tcnt);
691        qemu_put_be16s(f, &s->rcnt);
692        qemu_put_be32s(f, &s->rsar);
693        qemu_put_8s(f, &s->rsr);
694        qemu_put_8s(f, &s->isr);
695        qemu_put_8s(f, &s->dcfg);
696        qemu_put_8s(f, &s->imr);
697        qemu_put_buffer(f, s->phys, 6);
698        qemu_put_8s(f, &s->curpag);
699        qemu_put_buffer(f, s->mult, 8);
700        qemu_put_be32s(f, &s->irq);
701        qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE);
702}
703
704static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
705{
706        NE2000State* s=(NE2000State*)opaque;
707
708        if (version_id == 2) {
709            qemu_get_8s(f, &s->rxcr);
710        } else if (version_id == 1) {
711            s->rxcr = 0x0c;
712        } else {
713            return -EINVAL;
714        }
715
716        qemu_get_8s(f, &s->cmd);
717        qemu_get_be32s(f, &s->start);
718        qemu_get_be32s(f, &s->stop);
719        qemu_get_8s(f, &s->boundary);
720        qemu_get_8s(f, &s->tsr);
721        qemu_get_8s(f, &s->tpsr);
722        qemu_get_be16s(f, &s->tcnt);
723        qemu_get_be16s(f, &s->rcnt);
724        qemu_get_be32s(f, &s->rsar);
725        qemu_get_8s(f, &s->rsr);
726        qemu_get_8s(f, &s->isr);
727        qemu_get_8s(f, &s->dcfg);
728        qemu_get_8s(f, &s->imr);
729        qemu_get_buffer(f, s->phys, 6);
730        qemu_get_8s(f, &s->curpag);
731        qemu_get_buffer(f, s->mult, 8);
732        qemu_get_be32s(f, &s->irq);
733        qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE);
734
735        return 0;
736}
737
738void isa_ne2000_init(int base, int irq, NICInfo *nd)
739{
740    NE2000State *s;
741   
742    s = qemu_mallocz(sizeof(NE2000State));
743    if (!s)
744        return;
745   
746    register_ioport_write(base, 16, 1, ne2000_ioport_write, s);
747    register_ioport_read(base, 16, 1, ne2000_ioport_read, s);
748
749    register_ioport_write(base + 0x10, 1, 1, ne2000_asic_ioport_write, s);
750    register_ioport_read(base + 0x10, 1, 1, ne2000_asic_ioport_read, s);
751    register_ioport_write(base + 0x10, 2, 2, ne2000_asic_ioport_write, s);
752    register_ioport_read(base + 0x10, 2, 2, ne2000_asic_ioport_read, s);
753
754    register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
755    register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
756    s->irq = irq;
757    memcpy(s->macaddr, nd->macaddr, 6);
758
759    ne2000_reset(s);
760
761    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
762                                 ne2000_can_receive, s);
763
764    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
765             "ne2000 macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
766             s->macaddr[0],
767             s->macaddr[1],
768             s->macaddr[2],
769             s->macaddr[3],
770             s->macaddr[4],
771             s->macaddr[5]);
772             
773    register_savevm("ne2000", base, 2, ne2000_save, ne2000_load, s);
774}
775
776/***********************************************************/
777/* PCI NE2000 definitions */
778
779typedef struct PCINE2000State {
780    PCIDevice dev;
781    NE2000State ne2000;
782} PCINE2000State;
783
784static void ne2000_map(PCIDevice *pci_dev, int region_num, 
785                       uint32_t addr, uint32_t size, int type)
786{
787    PCINE2000State *d = (PCINE2000State *)pci_dev;
788    NE2000State *s = &d->ne2000;
789
790    register_ioport_write(addr, 16, 1, ne2000_ioport_write, s);
791    register_ioport_read(addr, 16, 1, ne2000_ioport_read, s);
792
793    register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s);
794    register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s);
795    register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s);
796    register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s);
797    register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s);
798    register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s);
799
800    register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
801    register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
802}
803
804void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
805{
806    PCINE2000State *d;
807    NE2000State *s;
808    uint8_t *pci_conf;
809    int instance;
810   
811    d = (PCINE2000State *)pci_register_device(bus,
812                                              "NE2000", sizeof(PCINE2000State),
813                                              -1, 
814                                              NULL, NULL);
815    pci_conf = d->dev.config;
816    pci_conf[0x00] = 0xec; // Realtek 8029
817    pci_conf[0x01] = 0x10;
818    pci_conf[0x02] = 0x29;
819    pci_conf[0x03] = 0x80;
820    pci_conf[0x0a] = 0x00; // ethernet network controller
821    pci_conf[0x0b] = 0x02;
822    pci_conf[0x0e] = 0x00; // header_type
823    pci_conf[0x3d] = 1; // interrupt pin 0
824   
825    pci_register_io_region(&d->dev, 0, 0x100, 
826                           PCI_ADDRESS_SPACE_IO, ne2000_map);
827    s = &d->ne2000;
828    s->irq = 16; // PCI interrupt
829    s->pci_dev = (PCIDevice *)d;
830    memcpy(s->macaddr, nd->macaddr, 6);
831    ne2000_reset(s);
832    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
833                                 ne2000_can_receive, s);
834
835    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
836             "ne2000 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
837             s->macaddr[0],
838             s->macaddr[1],
839             s->macaddr[2],
840             s->macaddr[3],
841             s->macaddr[4],
842             s->macaddr[5]);
843             
844    instance = pci_bus_num(bus) << 8 | s->pci_dev->devfn;
845    register_savevm("ne2000", instance, 2, ne2000_save, ne2000_load, s);
846    register_savevm("ne2000_pci", instance, 1, generic_pci_save, 
847                    generic_pci_load, &d->dev);
848}
Note: See TracBrowser for help on using the repository browser.