(linenum→info "unix/slp.c:2238")

qemu/0.9.1/hw/ne2000.c

    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 "hw.h"
   25: #include "pci.h"
   26: #include "pc.h"
   27: #include "net.h"
   28: 
   29: /* debug NE2000 card */
   30: //#define DEBUG_NE2000
   31: 
   32: #define MAX_ETH_FRAME_SIZE 1514
   33: 
   34: #define E8390_CMD       0x00  /* The command register (for all pages) */
   35: /* Page 0 register offsets. */
   36: #define EN0_CLDALO      0x01 /* Low byte of current local dma addr  RD */
   37: #define EN0_STARTPG     0x01        /* Starting page of ring bfr WR */
   38: #define EN0_CLDAHI      0x02 /* High byte of current local dma addr  RD */
   39: #define EN0_STOPPG      0x02 /* Ending page +1 of ring bfr WR */
   40: #define EN0_BOUNDARY    0x03       /* Boundary page of ring bfr RD WR */
   41: #define EN0_TSR         0x04   /* Transmit status reg RD */
   42: #define EN0_TPSR        0x04   /* Transmit starting page WR */
   43: #define EN0_NCR         0x05   /* Number of collision reg RD */
   44: #define EN0_TCNTLO      0x05 /* Low  byte of tx byte count WR */
   45: #define EN0_FIFO        0x06   /* FIFO RD */
   46: #define EN0_TCNTHI      0x06 /* High byte of tx byte count WR */
   47: #define EN0_ISR         0x07   /* Interrupt status reg RD WR */
   48: #define EN0_CRDALO      0x08 /* low byte of current remote dma address RD */
   49: #define EN0_RSARLO      0x08 /* Remote start address reg 0 */
   50: #define EN0_CRDAHI      0x09 /* high byte, current remote dma address RD */
   51: #define EN0_RSARHI      0x09 /* Remote start address reg 1 */
   52: #define EN0_RCNTLO      0x0a /* Remote byte count reg WR */
   53: #define EN0_RTL8029ID0  0x0a     /* Realtek ID byte #1 RD */
   54: #define EN0_RCNTHI      0x0b /* Remote byte count reg WR */
   55: #define EN0_RTL8029ID1  0x0b     /* Realtek ID byte #2 RD */
   56: #define EN0_RSR         0x0c   /* rx status reg RD */
   57: #define EN0_RXCR        0x0c   /* RX configuration reg WR */
   58: #define EN0_TXCR        0x0d   /* TX configuration reg WR */
   59: #define EN0_COUNTER0    0x0d       /* Rcv alignment error counter RD */
   60: #define EN0_DCFG        0x0e   /* Data configuration reg WR */
   61: #define EN0_COUNTER1    0x0e       /* Rcv CRC error counter RD */
   62: #define EN0_IMR         0x0f   /* Interrupt mask reg WR */
   63: #define EN0_COUNTER2    0x0f       /* Rcv missed frame error counter RD */
   64: 
   65: #define EN1_PHYS        0x11
   66: #define EN1_CURPAG      0x17
   67: #define EN1_MULT        0x18
   68: 
   69: #define EN2_STARTPG     0x21        /* Starting page of ring bfr RD */
   70: #define EN2_STOPPG      0x22 /* Ending page +1 of ring bfr RD */
   71: 
   72: #define EN3_CONFIG0     0x33
   73: #define EN3_CONFIG1     0x34
   74: #define EN3_CONFIG2     0x35
   75: #define EN3_CONFIG3     0x36
   76: 
   77: /*  Register accessed at EN_CMD, the 8390 base addr.  */
   78: #define E8390_STOP      0x01 /* Stop and reset the chip */
   79: #define E8390_START     0x02        /* Start the chip, clear reset */
   80: #define E8390_TRANS     0x04        /* Transmit a frame */
   81: #define E8390_RREAD     0x08        /* Remote read */
   82: #define E8390_RWRITE    0x10       /* Remote write  */
   83: #define E8390_NODMA     0x20        /* Remote DMA */
   84: #define E8390_PAGE0     0x00        /* Select page chip registers */
   85: #define E8390_PAGE1     0x40        /* using the two high-order bits */
   86: #define E8390_PAGE2     0x80        /* Page 3 is invalid. */
   87: 
   88: /* Bits in EN0_ISR - Interrupt status register */
   89: #define ENISR_RX        0x01   /* Receiver, no error */
   90: #define ENISR_TX        0x02   /* Transmitter, no error */
   91: #define ENISR_RX_ERR    0x04       /* Receiver, with error */
   92: #define ENISR_TX_ERR    0x08       /* Transmitter, with error */
   93: #define ENISR_OVER      0x10 /* Receiver overwrote the ring */
   94: #define ENISR_COUNTERS  0x20     /* Counters need emptying */
   95: #define ENISR_RDC       0x40  /* remote dma complete */
   96: #define ENISR_RESET     0x80        /* Reset completed */
   97: #define ENISR_ALL       0x3f  /* Interrupts we will enable */
   98: 
   99: /* Bits in received packet status byte and EN0_RSR*/
  100: #define ENRSR_RXOK      0x01 /* Received a good packet */
  101: #define ENRSR_CRC       0x02  /* CRC error */
  102: #define ENRSR_FAE       0x04  /* frame alignment error */
  103: #define ENRSR_FO        0x08   /* FIFO overrun */
  104: #define ENRSR_MPA       0x10  /* missed pkt */
  105: #define ENRSR_PHY       0x20  /* physical/multicast address */
  106: #define ENRSR_DIS       0x40  /* receiver disable. set in monitor mode */
  107: #define ENRSR_DEF       0x80  /* deferring */
  108: 
  109: /* Transmitted packet status, EN0_TSR. */
  110: #define ENTSR_PTX 0x01  /* Packet transmitted without error */
  111: #define ENTSR_ND  0x02  /* The transmit wasn't deferred. */
  112: #define ENTSR_COL 0x04  /* The transmit collided at least once. */
  113: #define ENTSR_ABT 0x08  /* The transmit collided 16 times, and was deferred. */
  114: #define ENTSR_CRS 0x10  /* The carrier sense was lost. */
  115: #define ENTSR_FU  0x20  /* A "FIFO underrun" occurred during transmit. */
  116: #define ENTSR_CDH 0x40  /* The collision detect "heartbeat" signal was lost. */
  117: #define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
  118: 
  119: #define NE2000_PMEM_SIZE    (32*1024)
  120: #define NE2000_PMEM_START   (16*1024)
  121: #define NE2000_PMEM_END     (NE2000_PMEM_SIZE+NE2000_PMEM_START)
  122: #define NE2000_MEM_SIZE     NE2000_PMEM_END
  123: 
  124: typedef struct NE2000State {
  125:     uint8_t cmd;
  126:     uint32_t start;
  127:     uint32_t stop;
  128:     uint8_t boundary;
  129:     uint8_t tsr;
  130:     uint8_t tpsr;
  131:     uint16_t tcnt;
  132:     uint16_t rcnt;
  133:     uint32_t rsar;
  134:     uint8_t rsr;
  135:     uint8_t rxcr;
  136:     uint8_t isr;
  137:     uint8_t dcfg;
  138:     uint8_t imr;
  139:     uint8_t phys[6]; /* mac address */
  140:     uint8_t curpag;
  141:     uint8_t mult[8]; /* multicast mask array */
  142:     qemu_irq irq;
  143:     PCIDevice *pci_dev;
  144:     VLANClientState *vc;
  145:     uint8_t macaddr[6];
  146:     uint8_t mem[NE2000_MEM_SIZE];
  147: } NE2000State;
  148: 
  149: static void ne2000_reset(NE2000State *s)
  150: {
  151:     int i;
  152: 
  153:     s->isr = ENISR_RESET;
  154:     memcpy(s->mem, s->macaddr, 6);
  155:     s->mem[14] = 0x57;
  156:     s->mem[15] = 0x57;
  157: 
  158:     /* duplicate prom data */
  159:     for(i = 15;i >= 0; i--) {
  160:         s->mem[2 * i] = s->mem[i];
  161:         s->mem[2 * i + 1] = s->mem[i];
  162:     }
  163: }
  164: 
  165: static void ne2000_update_irq(NE2000State *s)
  166: {
  167:     int isr;
  168:     isr = (s->isr & s->imr) & 0x7f;
  169: #if defined(DEBUG_NE2000)
  170:     printf("NE2000: Set IRQ to %d (%02x %02x)\n",
  171:            isr ? 1 : 0, s->isr, s->imr);
  172: #endif
  173:     qemu_set_irq(s->irq, (isr != 0));
  174: }
  175: 
  176: #define POLYNOMIAL 0x04c11db6
  177: 
  178: /* From FreeBSD */
  179: /* XXX: optimize */
  180: static int compute_mcast_idx(const uint8_t *ep)
  181: {
  182:     uint32_t crc;
  183:     int carry, i, j;
  184:     uint8_t b;
  185: 
  186:     crc = 0xffffffff;
  187:     for (i = 0; i < 6; i++) {
  188:         b = *ep++;
  189:         for (j = 0; j < 8; j++) {
  190:             carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
  191:             crc <<= 1;
  192:             b >>= 1;
  193:             if (carry)
  194:                 crc = ((crc ^ POLYNOMIAL) | carry);
  195:         }
  196:     }
  197:     return (crc >> 26);
  198: }
  199: 
  200: static int ne2000_buffer_full(NE2000State *s)
  201: {
  202:     int avail, index, boundary;
  203: 
  204:     index = s->curpag << 8;
  205:     boundary = s->boundary << 8;
  206:     if (index < boundary)
  207:         avail = boundary - index;
  208:     else
  209:         avail = (s->stop - s->start) - (index - boundary);
  210:     if (avail < (MAX_ETH_FRAME_SIZE + 4))
  211:         return 1;
  212:     return 0;
  213: }
  214: 
  215: static int ne2000_can_receive(void *opaque)
  216: {
  217:     NE2000State *s = opaque;
  218: 
  219:     if (s->cmd & E8390_STOP)
  220:         return 1;
  221:     return !ne2000_buffer_full(s);
  222: }
  223: 
  224: #define MIN_BUF_SIZE 60
  225: 
  226: static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
  227: {
  228:     NE2000State *s = opaque;
  229:     uint8_t *p;
  230:     unsigned int total_len, next, avail, len, index, mcast_idx;
  231:     uint8_t buf1[60];
  232:     static const uint8_t broadcast_macaddr[6] =
  233:         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  234: 
  235: #if defined(DEBUG_NE2000)
  236:     printf("NE2000: received len=%d\n", size);
  237: #endif
  238: 
  239:     if (s->cmd & E8390_STOP || ne2000_buffer_full(s))
  240:         return;
  241: 
  242:     /* XXX: check this */
  243:     if (s->rxcr & 0x10) {
  244:         /* promiscuous: receive all */
  245:     } else {
  246:         if (!memcmp(buf,  broadcast_macaddr, 6)) {
  247:             /* broadcast address */
  248:             if (!(s->rxcr & 0x04))
  249:                 return;
  250:         } else if (buf[0] & 0x01) {
  251:             /* multicast */
  252:             if (!(s->rxcr & 0x08))
  253:                 return;
  254:             mcast_idx = compute_mcast_idx(buf);
  255:             if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
  256:                 return;
  257:         } else if (s->mem[0] == buf[0] &&
  258:                    s->mem[2] == buf[1] &&
  259:                    s->mem[4] == buf[2] &&
  260:                    s->mem[6] == buf[3] &&
  261:                    s->mem[8] == buf[4] &&
  262:                    s->mem[10] == buf[5]) {
  263:             /* match */
  264:         } else {
  265:             return;
  266:         }
  267:     }
  268: 
  269: 
  270:     /* if too small buffer, then expand it */
  271:     if (size < MIN_BUF_SIZE) {
  272:         memcpy(buf1, buf, size);
  273:         memset(buf1 + size, 0, MIN_BUF_SIZE - size);
  274:         buf = buf1;
  275:         size = MIN_BUF_SIZE;
  276:     }
  277: 
  278:     index = s->curpag << 8;
  279:     /* 4 bytes for header */
  280:     total_len = size + 4;
  281:     /* address for next packet (4 bytes for CRC) */
  282:     next = index + ((total_len + 4 + 255) & ~0xff);
  283:     if (next >= s->stop)
  284:         next -= (s->stop - s->start);
  285:     /* prepare packet header */
  286:     p = s->mem + index;
  287:     s->rsr = ENRSR_RXOK; /* receive status */
  288:     /* XXX: check this */
  289:     if (buf[0] & 0x01)
  290:         s->rsr |= ENRSR_PHY;
  291:     p[0] = s->rsr;
  292:     p[1] = next >> 8;
  293:     p[2] = total_len;
  294:     p[3] = total_len >> 8;
  295:     index += 4;
  296: 
  297:     /* write packet data */
  298:     while (size > 0) {
  299:         if (index <= s->stop)
  300:             avail = s->stop - index;
  301:         else
  302:             avail = 0;
  303:         len = size;
  304:         if (len > avail)
  305:             len = avail;
  306:         memcpy(s->mem + index, buf, len);
  307:         buf += len;
  308:         index += len;
  309:         if (index == s->stop)
  310:             index = s->start;
  311:         size -= len;
  312:     }
  313:     s->curpag = next >> 8;
  314: 
  315:     /* now we can signal we have received something */
  316:     s->isr |= ENISR_RX;
  317:     ne2000_update_irq(s);
  318: }
  319: 
  320: static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  321: {
  322:     NE2000State *s = opaque;
  323:     int offset, page, index;
  324: 
  325:     addr &= 0xf;
  326: #ifdef DEBUG_NE2000
  327:     printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
  328: #endif
  329:     if (addr == E8390_CMD) {
  330:         /* control register */
  331:         s->cmd = val;
  332:         if (!(val & E8390_STOP)) { /* START bit makes no sense on RTL8029... */
  333:             s->isr &= ~ENISR_RESET;
  334:             /* test specific case: zero length transfer */
  335:             if ((val & (E8390_RREAD | E8390_RWRITE)) &&
  336:                 s->rcnt == 0) {
  337:                 s->isr |= ENISR_RDC;
  338:                 ne2000_update_irq(s);
  339:             }
  340:             if (val & E8390_TRANS) {
  341:                 index = (s->tpsr << 8);
  342:                 /* XXX: next 2 lines are a hack to make netware 3.11 work */
  343:                 if (index >= NE2000_PMEM_END)
  344:                     index -= NE2000_PMEM_SIZE;
  345:                 /* fail safe: check range on the transmitted length  */
  346:                 if (index + s->tcnt <= NE2000_PMEM_END) {
  347:                     qemu_send_packet(s->vc, s->mem + index, s->tcnt);
  348:                 }
  349:                 /* signal end of transfer */
  350:                 s->tsr = ENTSR_PTX;
  351:                 s->isr |= ENISR_TX;
  352:                 s->cmd &= ~E8390_TRANS;
  353:                 ne2000_update_irq(s);
  354:             }
  355:         }
  356:     } else {
  357:         page = s->cmd >> 6;
  358:         offset = addr | (page << 4);
  359:         switch(offset) {
  360:         case EN0_STARTPG:
  361:             s->start = val << 8;
  362:             break;
  363:         case EN0_STOPPG:
  364:             s->stop = val << 8;
  365:             break;
  366:         case EN0_BOUNDARY:
  367:             s->boundary = val;
  368:             break;
  369:         case EN0_IMR:
  370:             s->imr = val;
  371:             ne2000_update_irq(s);
  372:             break;
  373:         case EN0_TPSR:
  374:             s->tpsr = val;
  375:             break;
  376:         case EN0_TCNTLO:
  377:             s->tcnt = (s->tcnt & 0xff00) | val;
  378:             break;
  379:         case EN0_TCNTHI:
  380:             s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
  381:             break;
  382:         case EN0_RSARLO:
  383:             s->rsar = (s->rsar & 0xff00) | val;
  384:             break;
  385:         case EN0_RSARHI:
  386:             s->rsar = (s->rsar & 0x00ff) | (val << 8);
  387:             break;
  388:         case EN0_RCNTLO:
  389:             s->rcnt = (s->rcnt & 0xff00) | val;
  390:             break;
  391:         case EN0_RCNTHI:
  392:             s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
  393:             break;
  394:         case EN0_RXCR:
  395:             s->rxcr = val;
  396:             break;
  397:         case EN0_DCFG:
  398:             s->dcfg = val;
  399:             break;
  400:         case EN0_ISR:
  401:             s->isr &= ~(val & 0x7f);
  402:             ne2000_update_irq(s);
  403:             break;
  404:         case EN1_PHYS ... EN1_PHYS + 5:
  405:             s->phys[offset - EN1_PHYS] = val;
  406:             break;
  407:         case EN1_CURPAG:
  408:             s->curpag = val;
  409:             break;
  410:         case EN1_MULT ... EN1_MULT + 7:
  411:             s->mult[offset - EN1_MULT] = val;
  412:             break;
  413:         }
  414:     }
  415: }
  416: 
  417: static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
  418: {
  419:     NE2000State *s = opaque;
  420:     int offset, page, ret;
  421: 
  422:     addr &= 0xf;
  423:     if (addr == E8390_CMD) {
  424:         ret = s->cmd;
  425:     } else {
  426:         page = s->cmd >> 6;
  427:         offset = addr | (page << 4);
  428:         switch(offset) {
  429:         case EN0_TSR:
  430:             ret = s->tsr;
  431:             break;
  432:         case EN0_BOUNDARY:
  433:             ret = s->boundary;
  434:             break;
  435:         case EN0_ISR:
  436:             ret = s->isr;
  437:             break;
  438:         case EN0_RSARLO:
  439:             ret = s->rsar & 0x00ff;
  440:             break;
  441:         case EN0_RSARHI:
  442:             ret = s->rsar >> 8;
  443:             break;
  444:         case EN1_PHYS ... EN1_PHYS + 5:
  445:             ret = s->phys[offset - EN1_PHYS];
  446:             break;
  447:         case EN1_CURPAG:
  448:             ret = s->curpag;
  449:             break;
  450:         case EN1_MULT ... EN1_MULT + 7:
  451:             ret = s->mult[offset - EN1_MULT];
  452:             break;
  453:         case EN0_RSR:
  454:             ret = s->rsr;
  455:             break;
  456:         case EN2_STARTPG:
  457:             ret = s->start >> 8;
  458:             break;
  459:         case EN2_STOPPG:
  460:             ret = s->stop >> 8;
  461:             break;
  462:         case EN0_RTL8029ID0:
  463:             ret = 0x50;
  464:             break;
  465:         case EN0_RTL8029ID1:
  466:             ret = 0x43;
  467:             break;
  468:         case EN3_CONFIG0:
  469:             ret = 0;           /* 10baseT media */
  470:             break;
  471:         case EN3_CONFIG2:
  472:             ret = 0x40;                /* 10baseT active */
  473:             break;
  474:         case EN3_CONFIG3:
  475:             ret = 0x40;                /* Full duplex */
  476:             break;
  477:         default:
  478:             ret = 0x00;
  479:             break;
  480:         }
  481:     }
  482: #ifdef DEBUG_NE2000
  483:     printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
  484: #endif
  485:     return ret;
  486: }
  487: 
  488: static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr,
  489:                                      uint32_t val)
  490: {
  491:     if (addr < 32 ||
  492:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
  493:         s->mem[addr] = val;
  494:     }
  495: }
  496: 
  497: static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr,
  498:                                      uint32_t val)
  499: {
  500:     addr &= ~1; /* XXX: check exact behaviour if not even */
  501:     if (addr < 32 ||
  502:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
  503:         *(uint16_t *)(s->mem + addr) = cpu_to_le16(val);
  504:     }
  505: }
  506: 
  507: static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr,
  508:                                      uint32_t val)
  509: {
  510:     addr &= ~1; /* XXX: check exact behaviour if not even */
  511:     if (addr < 32 ||
  512:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
  513:         cpu_to_le32wu((uint32_t *)(s->mem + addr), val);
  514:     }
  515: }
  516: 
  517: static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr)
  518: {
  519:     if (addr < 32 ||
  520:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
  521:         return s->mem[addr];
  522:     } else {
  523:         return 0xff;
  524:     }
  525: }
  526: 
  527: static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr)
  528: {
  529:     addr &= ~1; /* XXX: check exact behaviour if not even */
  530:     if (addr < 32 ||
  531:         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
  532:         return le16_to_cpu(*(uint16_t *)(s->mem + addr));
  533:     } else {
  534:         return 0xffff;
  535:     }