Annotation of qemu/hw/ne2000.c, revision 1.1

1.1     ! root        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_RCNTHI     0x0b    /* Remote byte count reg WR */
        !            51: #define EN0_RSR                0x0c    /* rx status reg RD */
        !            52: #define EN0_RXCR       0x0c    /* RX configuration reg WR */
        !            53: #define EN0_TXCR       0x0d    /* TX configuration reg WR */
        !            54: #define EN0_COUNTER0   0x0d    /* Rcv alignment error counter RD */
        !            55: #define EN0_DCFG       0x0e    /* Data configuration reg WR */
        !            56: #define EN0_COUNTER1   0x0e    /* Rcv CRC error counter RD */
        !            57: #define EN0_IMR                0x0f    /* Interrupt mask reg WR */
        !            58: #define EN0_COUNTER2   0x0f    /* Rcv missed frame error counter RD */
        !            59: 
        !            60: #define EN1_PHYS        0x11
        !            61: #define EN1_CURPAG      0x17
        !            62: #define EN1_MULT        0x18
        !            63: 
        !            64: #define EN2_STARTPG    0x21    /* Starting page of ring bfr RD */
        !            65: #define EN2_STOPPG     0x22    /* Ending page +1 of ring bfr RD */
        !            66: 
        !            67: /*  Register accessed at EN_CMD, the 8390 base addr.  */
        !            68: #define E8390_STOP     0x01    /* Stop and reset the chip */
        !            69: #define E8390_START    0x02    /* Start the chip, clear reset */
        !            70: #define E8390_TRANS    0x04    /* Transmit a frame */
        !            71: #define E8390_RREAD    0x08    /* Remote read */
        !            72: #define E8390_RWRITE   0x10    /* Remote write  */
        !            73: #define E8390_NODMA    0x20    /* Remote DMA */
        !            74: #define E8390_PAGE0    0x00    /* Select page chip registers */
        !            75: #define E8390_PAGE1    0x40    /* using the two high-order bits */
        !            76: #define E8390_PAGE2    0x80    /* Page 3 is invalid. */
        !            77: 
        !            78: /* Bits in EN0_ISR - Interrupt status register */
        !            79: #define ENISR_RX       0x01    /* Receiver, no error */
        !            80: #define ENISR_TX       0x02    /* Transmitter, no error */
        !            81: #define ENISR_RX_ERR   0x04    /* Receiver, with error */
        !            82: #define ENISR_TX_ERR   0x08    /* Transmitter, with error */
        !            83: #define ENISR_OVER     0x10    /* Receiver overwrote the ring */
        !            84: #define ENISR_COUNTERS 0x20    /* Counters need emptying */
        !            85: #define ENISR_RDC      0x40    /* remote dma complete */
        !            86: #define ENISR_RESET    0x80    /* Reset completed */
        !            87: #define ENISR_ALL      0x3f    /* Interrupts we will enable */
        !            88: 
        !            89: /* Bits in received packet status byte and EN0_RSR*/
        !            90: #define ENRSR_RXOK     0x01    /* Received a good packet */
        !            91: #define ENRSR_CRC      0x02    /* CRC error */
        !            92: #define ENRSR_FAE      0x04    /* frame alignment error */
        !            93: #define ENRSR_FO       0x08    /* FIFO overrun */
        !            94: #define ENRSR_MPA      0x10    /* missed pkt */
        !            95: #define ENRSR_PHY      0x20    /* physical/multicast address */
        !            96: #define ENRSR_DIS      0x40    /* receiver disable. set in monitor mode */
        !            97: #define ENRSR_DEF      0x80    /* deferring */
        !            98: 
        !            99: /* Transmitted packet status, EN0_TSR. */
        !           100: #define ENTSR_PTX 0x01 /* Packet transmitted without error */
        !           101: #define ENTSR_ND  0x02 /* The transmit wasn't deferred. */
        !           102: #define ENTSR_COL 0x04 /* The transmit collided at least once. */
        !           103: #define ENTSR_ABT 0x08  /* The transmit collided 16 times, and was deferred. */
        !           104: #define ENTSR_CRS 0x10 /* The carrier sense was lost. */
        !           105: #define ENTSR_FU  0x20  /* A "FIFO underrun" occurred during transmit. */
        !           106: #define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
        !           107: #define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
        !           108: 
        !           109: #define NE2000_PMEM_SIZE    (32*1024)
        !           110: #define NE2000_PMEM_START   (16*1024)
        !           111: #define NE2000_PMEM_END     (NE2000_PMEM_SIZE+NE2000_PMEM_START)
        !           112: #define NE2000_MEM_SIZE     NE2000_PMEM_END
        !           113: 
        !           114: typedef struct NE2000State {
        !           115:     uint8_t cmd;
        !           116:     uint32_t start;
        !           117:     uint32_t stop;
        !           118:     uint8_t boundary;
        !           119:     uint8_t tsr;
        !           120:     uint8_t tpsr;
        !           121:     uint16_t tcnt;
        !           122:     uint16_t rcnt;
        !           123:     uint32_t rsar;
        !           124:     uint8_t rsr;
        !           125:     uint8_t isr;
        !           126:     uint8_t dcfg;
        !           127:     uint8_t imr;
        !           128:     uint8_t phys[6]; /* mac address */
        !           129:     uint8_t curpag;
        !           130:     uint8_t mult[8]; /* multicast mask array */
        !           131:     int irq;
        !           132:     PCIDevice *pci_dev;
        !           133:     NetDriverState *nd;
        !           134:     uint8_t mem[NE2000_MEM_SIZE];
        !           135: } NE2000State;
        !           136: 
        !           137: static void ne2000_reset(NE2000State *s)
        !           138: {
        !           139:     int i;
        !           140: 
        !           141:     s->isr = ENISR_RESET;
        !           142:     memcpy(s->mem, s->nd->macaddr, 6);
        !           143:     s->mem[14] = 0x57;
        !           144:     s->mem[15] = 0x57;
        !           145: 
        !           146:     /* duplicate prom data */
        !           147:     for(i = 15;i >= 0; i--) {
        !           148:         s->mem[2 * i] = s->mem[i];
        !           149:         s->mem[2 * i + 1] = s->mem[i];
        !           150:     }
        !           151: }
        !           152: 
        !           153: static void ne2000_update_irq(NE2000State *s)
        !           154: {
        !           155:     int isr;
        !           156:     isr = (s->isr & s->imr) & 0x7f;
        !           157: #if defined(DEBUG_NE2000)
        !           158:     printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
        !           159:           s->irq, isr ? 1 : 0, s->isr, s->imr);
        !           160: #endif
        !           161:     if (s->irq == 16) {
        !           162:         /* PCI irq */
        !           163:         pci_set_irq(s->pci_dev, 0, (isr != 0));
        !           164:     } else {
        !           165:         /* ISA irq */
        !           166:         pic_set_irq(s->irq, (isr != 0));
        !           167:     }
        !           168: }
        !           169: 
        !           170: /* return the max buffer size if the NE2000 can receive more data */
        !           171: static int ne2000_can_receive(void *opaque)
        !           172: {
        !           173:     NE2000State *s = opaque;
        !           174:     int avail, index, boundary;
        !           175:     
        !           176:     if (s->cmd & E8390_STOP)
        !           177:         return 0;
        !           178:     index = s->curpag << 8;
        !           179:     boundary = s->boundary << 8;
        !           180:     if (index < boundary)
        !           181:         avail = boundary - index;
        !           182:     else
        !           183:         avail = (s->stop - s->start) - (index - boundary);
        !           184:     if (avail < (MAX_ETH_FRAME_SIZE + 4))
        !           185:         return 0;
        !           186:     return MAX_ETH_FRAME_SIZE;
        !           187: }
        !           188: 
        !           189: #define MIN_BUF_SIZE 60
        !           190: 
        !           191: static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
        !           192: {
        !           193:     NE2000State *s = opaque;
        !           194:     uint8_t *p;
        !           195:     int total_len, next, avail, len, index;
        !           196:     uint8_t buf1[60];
        !           197:     
        !           198: #if defined(DEBUG_NE2000)
        !           199:     printf("NE2000: received len=%d\n", size);
        !           200: #endif
        !           201: 
        !           202:     /* if too small buffer, then expand it */
        !           203:     if (size < MIN_BUF_SIZE) {
        !           204:         memcpy(buf1, buf, size);
        !           205:         memset(buf1 + size, 0, MIN_BUF_SIZE - size);
        !           206:         buf = buf1;
        !           207:         size = MIN_BUF_SIZE;
        !           208:     }
        !           209: 
        !           210:     index = s->curpag << 8;
        !           211:     /* 4 bytes for header */
        !           212:     total_len = size + 4;
        !           213:     /* address for next packet (4 bytes for CRC) */
        !           214:     next = index + ((total_len + 4 + 255) & ~0xff);
        !           215:     if (next >= s->stop)
        !           216:         next -= (s->stop - s->start);
        !           217:     /* prepare packet header */
        !           218:     p = s->mem + index;
        !           219:     s->rsr = ENRSR_RXOK; /* receive status */
        !           220:     /* XXX: check this */
        !           221:     if (buf[0] & 0x01)
        !           222:         s->rsr |= ENRSR_PHY;
        !           223:     p[0] = s->rsr;
        !           224:     p[1] = next >> 8;
        !           225:     p[2] = total_len;
        !           226:     p[3] = total_len >> 8;
        !           227:     index += 4;
        !           228: 
        !           229:     /* write packet data */
        !           230:     while (size > 0) {
        !           231:         avail = s->stop - index;
        !           232:         len = size;
        !           233:         if (len > avail)
        !           234:             len = avail;
        !           235:         memcpy(s->mem + index, buf, len);
        !           236:         buf += len;
        !           237:         index += len;
        !           238:         if (index == s->stop)
        !           239:             index = s->start;
        !           240:         size -= len;
        !           241:     }
        !           242:     s->curpag = next >> 8;
        !           243: 
        !           244:     /* now we can signal we have receive something */
        !           245:     s->isr |= ENISR_RX;
        !           246:     ne2000_update_irq(s);
        !           247: }
        !           248: 
        !           249: static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
        !           250: {
        !           251:     NE2000State *s = opaque;
        !           252:     int offset, page, index;
        !           253: 
        !           254:     addr &= 0xf;
        !           255: #ifdef DEBUG_NE2000
        !           256:     printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
        !           257: #endif
        !           258:     if (addr == E8390_CMD) {
        !           259:         /* control register */
        !           260:         s->cmd = val;
        !           261:         if (!(val & E8390_STOP)) { /* START bit makes no sense on RTL8029... */
        !           262:             s->isr &= ~ENISR_RESET;
        !           263:             /* test specific case: zero length transfert */
        !           264:             if ((val & (E8390_RREAD | E8390_RWRITE)) &&
        !           265:                 s->rcnt == 0) {
        !           266:                 s->isr |= ENISR_RDC;
        !           267:                 ne2000_update_irq(s);
        !           268:             }
        !           269:             if (val & E8390_TRANS) {
        !           270:                 index = (s->tpsr << 8);
        !           271:                 /* XXX: next 2 lines are a hack to make netware 3.11 work */ 
        !           272:                 if (index >= NE2000_PMEM_END)
        !           273:                     index -= NE2000_PMEM_SIZE;
        !           274:                 /* fail safe: check range on the transmitted length  */
        !           275:                 if (index + s->tcnt <= NE2000_PMEM_END) {
        !           276:                     qemu_send_packet(s->nd, s->mem + index, s->tcnt);
        !           277:                 }
        !           278:                 /* signal end of transfert */
        !           279:                 s->tsr = ENTSR_PTX;
        !           280:                 s->isr |= ENISR_TX;
        !           281:                 s->cmd &= ~E8390_TRANS; 
        !           282:                 ne2000_update_irq(s);
        !           283:             }
        !           284:         }
        !           285:     } else {
        !           286:         page = s->cmd >> 6;
        !           287:         offset = addr | (page << 4);
        !           288:         switch(offset) {
        !           289:         case EN0_STARTPG:
        !           290:             s->start = val << 8;
        !           291:             break;
        !           292:         case EN0_STOPPG:
        !           293:             s->stop = val << 8;
        !           294:             break;
        !           295:         case EN0_BOUNDARY:
        !           296:             s->boundary = val;
        !           297:             break;
        !           298:         case EN0_IMR:
        !           299:             s->imr = val;
        !           300:             ne2000_update_irq(s);
        !           301:             break;
        !           302:         case EN0_TPSR:
        !           303:             s->tpsr = val;
        !           304:             break;
        !           305:         case EN0_TCNTLO:
        !           306:             s->tcnt = (s->tcnt & 0xff00) | val;
        !           307:             break;
        !           308:         case EN0_TCNTHI:
        !           309:             s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
        !           310:             break;
        !           311:         case EN0_RSARLO:
        !           312:             s->rsar = (s->rsar & 0xff00) | val;
        !           313:             break;
        !           314:         case EN0_RSARHI:
        !           315:             s->rsar = (s->rsar & 0x00ff) | (val << 8);
        !           316:             break;
        !           317:         case EN0_RCNTLO:
        !           318:             s->rcnt = (s->rcnt & 0xff00) | val;
        !           319:             break;
        !           320:         case EN0_RCNTHI:
        !           321:             s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
        !           322:             break;
        !           323:         case EN0_DCFG:
        !           324:             s->dcfg = val;
        !           325:             break;
        !           326:         case EN0_ISR:
        !           327:             s->isr &= ~(val & 0x7f);
        !           328:             ne2000_update_irq(s);
        !           329:             break;
        !           330:         case EN1_PHYS ... EN1_PHYS + 5:
        !           331:             s->phys[offset - EN1_PHYS] = val;
        !           332:             break;
        !           333:         case EN1_CURPAG:
        !           334:             s->curpag = val;
        !           335:             break;
        !           336:         case EN1_MULT ... EN1_MULT + 7:
        !           337:             s->mult[offset - EN1_MULT] = val;
        !           338:             break;
        !           339:         }
        !           340:     }
        !           341: }
        !           342: 
        !           343: static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
        !           344: {
        !           345:     NE2000State *s = opaque;
        !           346:     int offset, page, ret;
        !           347: 
        !           348:     addr &= 0xf;
        !           349:     if (addr == E8390_CMD) {
        !           350:         ret = s->cmd;
        !           351:     } else {
        !           352:         page = s->cmd >> 6;
        !           353:         offset = addr | (page << 4);
        !           354:         switch(offset) {
        !           355:         case EN0_TSR:
        !           356:             ret = s->tsr;
        !           357:             break;
        !           358:         case EN0_BOUNDARY:
        !           359:             ret = s->boundary;
        !           360:             break;
        !           361:         case EN0_ISR:
        !           362:             ret = s->isr;
        !           363:             break;
        !           364:        case EN0_RSARLO:
        !           365:            ret = s->rsar & 0x00ff;
        !           366:            break;
        !           367:        case EN0_RSARHI:
        !           368:            ret = s->rsar >> 8;
        !           369:            break;
        !           370:         case EN1_PHYS ... EN1_PHYS + 5:
        !           371:             ret = s->phys[offset - EN1_PHYS];
        !           372:             break;
        !           373:         case EN1_CURPAG:
        !           374:             ret = s->curpag;
        !           375:             break;
        !           376:         case EN1_MULT ... EN1_MULT + 7:
        !           377:             ret = s->mult[offset - EN1_MULT];
        !           378:             break;
        !           379:         case EN0_RSR:
        !           380:             ret = s->rsr;
        !           381:             break;
        !           382:         case EN2_STARTPG:
        !           383:             ret = s->start >> 8;
        !           384:             break;
        !           385:         case EN2_STOPPG:
        !           386:             ret = s->stop >> 8;
        !           387:             break;
        !           388:         default:
        !           389:             ret = 0x00;
        !           390:             break;
        !           391:         }
        !           392:     }
        !           393: #ifdef DEBUG_NE2000
        !           394:     printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
        !           395: #endif
        !           396:     return ret;
        !           397: }
        !           398: 
        !           399: static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr, 
        !           400:                                      uint32_t val)
        !           401: {
        !           402:     if (addr < 32 || 
        !           403:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
        !           404:         s->mem[addr] = val;
        !           405:     }
        !           406: }
        !           407: 
        !           408: static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr, 
        !           409:                                      uint32_t val)
        !           410: {
        !           411:     addr &= ~1; /* XXX: check exact behaviour if not even */
        !           412:     if (addr < 32 || 
        !           413:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
        !           414:         *(uint16_t *)(s->mem + addr) = cpu_to_le16(val);
        !           415:     }
        !           416: }
        !           417: 
        !           418: static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr, 
        !           419:                                      uint32_t val)
        !           420: {
        !           421:     addr &= ~1; /* XXX: check exact behaviour if not even */
        !           422:     if (addr < 32 || 
        !           423:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
        !           424:         cpu_to_le32wu((uint32_t *)(s->mem + addr), val);
        !           425:     }
        !           426: }
        !           427: 
        !           428: static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr)
        !           429: {
        !           430:     if (addr < 32 || 
        !           431:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
        !           432:         return s->mem[addr];
        !           433:     } else {
        !           434:         return 0xff;
        !           435:     }
        !           436: }
        !           437: 
        !           438: static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr)
        !           439: {
        !           440:     addr &= ~1; /* XXX: check exact behaviour if not even */
        !           441:     if (addr < 32 || 
        !           442:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
        !           443:         return le16_to_cpu(*(uint16_t *)(s->mem + addr));
        !           444:     } else {
        !           445:         return 0xffff;
        !           446:     }
        !           447: }
        !           448: 
        !           449: static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr)
        !           450: {
        !           451:     addr &= ~1; /* XXX: check exact behaviour if not even */
        !           452:     if (addr < 32 || 
        !           453:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
        !           454:         return le32_to_cpupu((uint32_t *)(s->mem + addr));
        !           455:     } else {
        !           456:         return 0xffffffff;
        !           457:     }
        !           458: }
        !           459: 
        !           460: static inline void ne2000_dma_update(NE2000State *s, int len)
        !           461: {
        !           462:     s->rsar += len;
        !           463:     /* wrap */
        !           464:     /* XXX: check what to do if rsar > stop */
        !           465:     if (s->rsar == s->stop)
        !           466:         s->rsar = s->start;
        !           467: 
        !           468:     if (s->rcnt <= len) {
        !           469:         s->rcnt = 0;
        !           470:         /* signal end of transfert */
        !           471:         s->isr |= ENISR_RDC;
        !           472:         ne2000_update_irq(s);
        !           473:     } else {
        !           474:         s->rcnt -= len;
        !           475:     }
        !           476: }
        !           477: 
        !           478: static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
        !           479: {
        !           480:     NE2000State *s = opaque;
        !           481: 
        !           482: #ifdef DEBUG_NE2000
        !           483:     printf("NE2000: asic write val=0x%04x\n", val);
        !           484: #endif
        !           485:     if (s->rcnt == 0)
        !           486:         return;
        !           487:     if (s->dcfg & 0x01) {
        !           488:         /* 16 bit access */
        !           489:         ne2000_mem_writew(s, s->rsar, val);
        !           490:         ne2000_dma_update(s, 2);
        !           491:     } else {
        !           492:         /* 8 bit access */
        !           493:         ne2000_mem_writeb(s, s->rsar, val);
        !           494:         ne2000_dma_update(s, 1);
        !           495:     }
        !           496: }
        !           497: 
        !           498: static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
        !           499: {
        !           500:     NE2000State *s = opaque;
        !           501:     int ret;
        !           502: 
        !           503:     if (s->dcfg & 0x01) {
        !           504:         /* 16 bit access */
        !           505:         ret = ne2000_mem_readw(s, s->rsar);
        !           506:         ne2000_dma_update(s, 2);
        !           507:     } else {
        !           508:         /* 8 bit access */
        !           509:         ret = ne2000_mem_readb(s, s->rsar);
        !           510:         ne2000_dma_update(s, 1);
        !           511:     }
        !           512: #ifdef DEBUG_NE2000
        !           513:     printf("NE2000: asic read val=0x%04x\n", ret);
        !           514: #endif
        !           515:     return ret;
        !           516: }
        !           517: 
        !           518: static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
        !           519: {
        !           520:     NE2000State *s = opaque;
        !           521: 
        !           522: #ifdef DEBUG_NE2000
        !           523:     printf("NE2000: asic writel val=0x%04x\n", val);
        !           524: #endif
        !           525:     if (s->rcnt == 0)
        !           526:         return;
        !           527:     /* 32 bit access */
        !           528:     ne2000_mem_writel(s, s->rsar, val);
        !           529:     ne2000_dma_update(s, 4);
        !           530: }
        !           531: 
        !           532: static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr)
        !           533: {
        !           534:     NE2000State *s = opaque;
        !           535:     int ret;
        !           536: 
        !           537:     /* 32 bit access */
        !           538:     ret = ne2000_mem_readl(s, s->rsar);
        !           539:     ne2000_dma_update(s, 4);
        !           540: #ifdef DEBUG_NE2000
        !           541:     printf("NE2000: asic readl val=0x%04x\n", ret);
        !           542: #endif
        !           543:     return ret;
        !           544: }
        !           545: 
        !           546: static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val)
        !           547: {
        !           548:     /* nothing to do (end of reset pulse) */
        !           549: }
        !           550: 
        !           551: static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr)
        !           552: {
        !           553:     NE2000State *s = opaque;
        !           554:     ne2000_reset(s);
        !           555:     return 0;
        !           556: }
        !           557: 
        !           558: static void ne2000_save(QEMUFile* f,void* opaque)
        !           559: {
        !           560:        NE2000State* s=(NE2000State*)opaque;
        !           561: 
        !           562:        qemu_put_8s(f, &s->cmd);
        !           563:        qemu_put_be32s(f, &s->start);
        !           564:        qemu_put_be32s(f, &s->stop);
        !           565:        qemu_put_8s(f, &s->boundary);
        !           566:        qemu_put_8s(f, &s->tsr);
        !           567:        qemu_put_8s(f, &s->tpsr);
        !           568:        qemu_put_be16s(f, &s->tcnt);
        !           569:        qemu_put_be16s(f, &s->rcnt);
        !           570:        qemu_put_be32s(f, &s->rsar);
        !           571:        qemu_put_8s(f, &s->rsr);
        !           572:        qemu_put_8s(f, &s->isr);
        !           573:        qemu_put_8s(f, &s->dcfg);
        !           574:        qemu_put_8s(f, &s->imr);
        !           575:        qemu_put_buffer(f, s->phys, 6);
        !           576:        qemu_put_8s(f, &s->curpag);
        !           577:        qemu_put_buffer(f, s->mult, 8);
        !           578:        qemu_put_be32s(f, &s->irq);
        !           579:        qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE);
        !           580: }
        !           581: 
        !           582: static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
        !           583: {
        !           584:        NE2000State* s=(NE2000State*)opaque;
        !           585: 
        !           586:        if (version_id != 1)
        !           587:             return -EINVAL;
        !           588: 
        !           589:        qemu_get_8s(f, &s->cmd);
        !           590:        qemu_get_be32s(f, &s->start);
        !           591:        qemu_get_be32s(f, &s->stop);
        !           592:        qemu_get_8s(f, &s->boundary);
        !           593:        qemu_get_8s(f, &s->tsr);
        !           594:        qemu_get_8s(f, &s->tpsr);
        !           595:        qemu_get_be16s(f, &s->tcnt);
        !           596:        qemu_get_be16s(f, &s->rcnt);
        !           597:        qemu_get_be32s(f, &s->rsar);
        !           598:        qemu_get_8s(f, &s->rsr);
        !           599:        qemu_get_8s(f, &s->isr);
        !           600:        qemu_get_8s(f, &s->dcfg);
        !           601:        qemu_get_8s(f, &s->imr);
        !           602:        qemu_get_buffer(f, s->phys, 6);
        !           603:        qemu_get_8s(f, &s->curpag);
        !           604:        qemu_get_buffer(f, s->mult, 8);
        !           605:        qemu_get_be32s(f, &s->irq);
        !           606:        qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE);
        !           607: 
        !           608:        return 0;
        !           609: }
        !           610: 
        !           611: void isa_ne2000_init(int base, int irq, NetDriverState *nd)
        !           612: {
        !           613:     NE2000State *s;
        !           614: 
        !           615:     s = qemu_mallocz(sizeof(NE2000State));
        !           616:     if (!s)
        !           617:         return;
        !           618:     
        !           619:     register_ioport_write(base, 16, 1, ne2000_ioport_write, s);
        !           620:     register_ioport_read(base, 16, 1, ne2000_ioport_read, s);
        !           621: 
        !           622:     register_ioport_write(base + 0x10, 1, 1, ne2000_asic_ioport_write, s);
        !           623:     register_ioport_read(base + 0x10, 1, 1, ne2000_asic_ioport_read, s);
        !           624:     register_ioport_write(base + 0x10, 2, 2, ne2000_asic_ioport_write, s);
        !           625:     register_ioport_read(base + 0x10, 2, 2, ne2000_asic_ioport_read, s);
        !           626: 
        !           627:     register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
        !           628:     register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
        !           629:     s->irq = irq;
        !           630:     s->nd = nd;
        !           631: 
        !           632:     ne2000_reset(s);
        !           633: 
        !           634:     qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s);
        !           635: 
        !           636:     register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
        !           637: 
        !           638: }
        !           639: 
        !           640: /***********************************************************/
        !           641: /* PCI NE2000 definitions */
        !           642: 
        !           643: typedef struct PCINE2000State {
        !           644:     PCIDevice dev;
        !           645:     NE2000State ne2000;
        !           646: } PCINE2000State;
        !           647: 
        !           648: static void ne2000_map(PCIDevice *pci_dev, int region_num, 
        !           649:                        uint32_t addr, uint32_t size, int type)
        !           650: {
        !           651:     PCINE2000State *d = (PCINE2000State *)pci_dev;
        !           652:     NE2000State *s = &d->ne2000;
        !           653: 
        !           654:     register_ioport_write(addr, 16, 1, ne2000_ioport_write, s);
        !           655:     register_ioport_read(addr, 16, 1, ne2000_ioport_read, s);
        !           656: 
        !           657:     register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s);
        !           658:     register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s);
        !           659:     register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s);
        !           660:     register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s);
        !           661:     register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s);
        !           662:     register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s);
        !           663: 
        !           664:     register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
        !           665:     register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
        !           666: }
        !           667: 
        !           668: void pci_ne2000_init(PCIBus *bus, NetDriverState *nd)
        !           669: {
        !           670:     PCINE2000State *d;
        !           671:     NE2000State *s;
        !           672:     uint8_t *pci_conf;
        !           673:     
        !           674:     d = (PCINE2000State *)pci_register_device(bus,
        !           675:                                               "NE2000", sizeof(PCINE2000State),
        !           676:                                               -1, 
        !           677:                                               NULL, NULL);
        !           678:     pci_conf = d->dev.config;
        !           679:     pci_conf[0x00] = 0xec; // Realtek 8029
        !           680:     pci_conf[0x01] = 0x10;
        !           681:     pci_conf[0x02] = 0x29;
        !           682:     pci_conf[0x03] = 0x80;
        !           683:     pci_conf[0x0a] = 0x00; // ethernet network controller 
        !           684:     pci_conf[0x0b] = 0x02;
        !           685:     pci_conf[0x0e] = 0x00; // header_type
        !           686:     pci_conf[0x3d] = 1; // interrupt pin 0
        !           687:     
        !           688:     pci_register_io_region(&d->dev, 0, 0x100, 
        !           689:                            PCI_ADDRESS_SPACE_IO, ne2000_map);
        !           690:     s = &d->ne2000;
        !           691:     s->irq = 16; // PCI interrupt
        !           692:     s->pci_dev = (PCIDevice *)d;
        !           693:     s->nd = nd;
        !           694:     ne2000_reset(s);
        !           695:     qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s);
        !           696: 
        !           697:     /* XXX: instance number ? */
        !           698:     register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
        !           699:     register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, 
        !           700:                     &d->dev);
        !           701: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.