Annotation of qemu/hw/lance.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU Lance emulation
                      3:  * 
                      4:  * Copyright (c) 2003-2005 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 LANCE card */
                     27: //#define DEBUG_LANCE
                     28: 
                     29: #ifdef DEBUG_LANCE
                     30: #define DPRINTF(fmt, args...) \
                     31: do { printf("LANCE: " fmt , ##args); } while (0)
                     32: #else
                     33: #define DPRINTF(fmt, args...)
                     34: #endif
                     35: 
                     36: #ifndef LANCE_LOG_TX_BUFFERS
                     37: #define LANCE_LOG_TX_BUFFERS 4
                     38: #define LANCE_LOG_RX_BUFFERS 4
                     39: #endif
                     40: 
                     41: #define LE_CSR0 0
                     42: #define LE_CSR1 1
                     43: #define LE_CSR2 2
                     44: #define LE_CSR3 3
                     45: #define LE_NREGS (LE_CSR3 + 1)
                     46: #define LE_MAXREG LE_CSR3
                     47: 
                     48: #define LE_RDP  0
                     49: #define LE_RAP  1
                     50: 
                     51: #define LE_MO_PROM      0x8000  /* Enable promiscuous mode */
                     52: 
                     53: #define        LE_C0_ERR       0x8000  /* Error: set if BAB, SQE, MISS or ME is set */
                     54: #define        LE_C0_BABL      0x4000  /* BAB:  Babble: tx timeout. */
                     55: #define        LE_C0_CERR      0x2000  /* SQE:  Signal quality error */
                     56: #define        LE_C0_MISS      0x1000  /* MISS: Missed a packet */
                     57: #define        LE_C0_MERR      0x0800  /* ME:   Memory error */
                     58: #define        LE_C0_RINT      0x0400  /* Received interrupt */
                     59: #define        LE_C0_TINT      0x0200  /* Transmitter Interrupt */
                     60: #define        LE_C0_IDON      0x0100  /* IFIN: Init finished. */
                     61: #define        LE_C0_INTR      0x0080  /* Interrupt or error */
                     62: #define        LE_C0_INEA      0x0040  /* Interrupt enable */
                     63: #define        LE_C0_RXON      0x0020  /* Receiver on */
                     64: #define        LE_C0_TXON      0x0010  /* Transmitter on */
                     65: #define        LE_C0_TDMD      0x0008  /* Transmitter demand */
                     66: #define        LE_C0_STOP      0x0004  /* Stop the card */
                     67: #define        LE_C0_STRT      0x0002  /* Start the card */
                     68: #define        LE_C0_INIT      0x0001  /* Init the card */
                     69: 
                     70: #define        LE_C3_BSWP      0x4     /* SWAP */
                     71: #define        LE_C3_ACON      0x2     /* ALE Control */
                     72: #define        LE_C3_BCON      0x1     /* Byte control */
                     73: 
                     74: /* Receive message descriptor 1 */
                     75: #define LE_R1_OWN       0x80    /* Who owns the entry */
                     76: #define LE_R1_ERR       0x40    /* Error: if FRA, OFL, CRC or BUF is set */
                     77: #define LE_R1_FRA       0x20    /* FRA: Frame error */
                     78: #define LE_R1_OFL       0x10    /* OFL: Frame overflow */
                     79: #define LE_R1_CRC       0x08    /* CRC error */
                     80: #define LE_R1_BUF       0x04    /* BUF: Buffer error */
                     81: #define LE_R1_SOP       0x02    /* Start of packet */
                     82: #define LE_R1_EOP       0x01    /* End of packet */
                     83: #define LE_R1_POK       0x03    /* Packet is complete: SOP + EOP */
                     84: 
                     85: #define LE_T1_OWN       0x80    /* Lance owns the packet */
                     86: #define LE_T1_ERR       0x40    /* Error summary */
                     87: #define LE_T1_EMORE     0x10    /* Error: more than one retry needed */
                     88: #define LE_T1_EONE      0x08    /* Error: one retry needed */
                     89: #define LE_T1_EDEF      0x04    /* Error: deferred */
                     90: #define LE_T1_SOP       0x02    /* Start of packet */
                     91: #define LE_T1_EOP       0x01    /* End of packet */
                     92: #define LE_T1_POK      0x03    /* Packet is complete: SOP + EOP */
                     93: 
                     94: #define LE_T3_BUF       0x8000  /* Buffer error */
                     95: #define LE_T3_UFL       0x4000  /* Error underflow */
                     96: #define LE_T3_LCOL      0x1000  /* Error late collision */
                     97: #define LE_T3_CLOS      0x0800  /* Error carrier loss */
                     98: #define LE_T3_RTY       0x0400  /* Error retry */
                     99: #define LE_T3_TDR       0x03ff  /* Time Domain Reflectometry counter */
                    100: 
                    101: #define TX_RING_SIZE                   (1 << (LANCE_LOG_TX_BUFFERS))
                    102: #define TX_RING_MOD_MASK               (TX_RING_SIZE - 1)
                    103: #define TX_RING_LEN_BITS               ((LANCE_LOG_TX_BUFFERS) << 29)
                    104: 
                    105: #define RX_RING_SIZE                   (1 << (LANCE_LOG_RX_BUFFERS))
                    106: #define RX_RING_MOD_MASK               (RX_RING_SIZE - 1)
                    107: #define RX_RING_LEN_BITS               ((LANCE_LOG_RX_BUFFERS) << 29)
                    108: 
                    109: #define PKT_BUF_SZ             1544
                    110: #define RX_BUFF_SIZE            PKT_BUF_SZ
                    111: #define TX_BUFF_SIZE            PKT_BUF_SZ
                    112: 
                    113: struct lance_rx_desc {
                    114:        unsigned short rmd0;        /* low address of packet */
                    115:        unsigned char  rmd1_bits;   /* descriptor bits */
                    116:        unsigned char  rmd1_hadr;   /* high address of packet */
                    117:        short    length;            /* This length is 2s complement (negative)!
                    118:                                     * Buffer length
                    119:                                     */
                    120:        unsigned short mblength;    /* This is the actual number of bytes received */
                    121: };
                    122: 
                    123: struct lance_tx_desc {
                    124:        unsigned short tmd0;        /* low address of packet */
                    125:        unsigned char  tmd1_bits;   /* descriptor bits */
                    126:        unsigned char  tmd1_hadr;   /* high address of packet */
                    127:        short length;               /* Length is 2s complement (negative)! */
                    128:        unsigned short misc;
                    129: };
                    130: 
                    131: /* The LANCE initialization block, described in databook. */
                    132: /* On the Sparc, this block should be on a DMA region     */
                    133: struct lance_init_block {
                    134:        unsigned short mode;            /* Pre-set mode (reg. 15) */
                    135:        unsigned char phys_addr[6];     /* Physical ethernet address */
                    136:        unsigned filter[2];             /* Multicast filter. */
                    137: 
                    138:        /* Receive and transmit ring base, along with extra bits. */
                    139:        unsigned short rx_ptr;          /* receive descriptor addr */
                    140:        unsigned short rx_len;          /* receive len and high addr */
                    141:        unsigned short tx_ptr;          /* transmit descriptor addr */
                    142:        unsigned short tx_len;          /* transmit len and high addr */
                    143:     
                    144:        /* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
                    145:        struct lance_rx_desc brx_ring[RX_RING_SIZE];
                    146:        struct lance_tx_desc btx_ring[TX_RING_SIZE];
                    147:     
                    148:        char   tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
                    149:        char   pad[2];                  /* align rx_buf for copy_and_sum(). */
                    150:        char   rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
                    151: };
                    152: 
                    153: #define LEDMA_REGS 4
                    154: #define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1)
                    155: 
                    156: typedef struct LANCEState {
                    157:     NetDriverState *nd;
                    158:     uint32_t leptr;
                    159:     uint16_t addr;
                    160:     uint16_t regs[LE_NREGS];
                    161:     uint8_t phys[6]; /* mac address */
                    162:     int irq;
                    163:     unsigned int rxptr, txptr;
                    164:     uint32_t ledmaregs[LEDMA_REGS];
                    165: } LANCEState;
                    166: 
                    167: static void lance_send(void *opaque);
                    168: 
                    169: static void lance_reset(void *opaque)
                    170: {
                    171:     LANCEState *s = opaque;
                    172:     memcpy(s->phys, s->nd->macaddr, 6);
                    173:     s->rxptr = 0;
                    174:     s->txptr = 0;
                    175:     memset(s->regs, 0, LE_NREGS * 2);
                    176:     s->regs[LE_CSR0] = LE_C0_STOP;
                    177:     memset(s->ledmaregs, 0, LEDMA_REGS * 4);
                    178: }
                    179: 
                    180: static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
                    181: {
                    182:     LANCEState *s = opaque;
                    183:     uint32_t saddr;
                    184: 
                    185:     saddr = addr & LE_MAXREG;
                    186:     switch (saddr >> 1) {
                    187:     case LE_RDP:
                    188:        DPRINTF("read dreg[%d] = %4.4x\n", s->addr, s->regs[s->addr]);
                    189:        return s->regs[s->addr];
                    190:     case LE_RAP:
                    191:        DPRINTF("read areg = %4.4x\n", s->addr);
                    192:        return s->addr;
                    193:     default:
                    194:        DPRINTF("read unknown(%d)\n", saddr>>1);
                    195:        break;
                    196:     }
                    197:     return 0;
                    198: }
                    199: 
                    200: static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
                    201: {
                    202:     LANCEState *s = opaque;
                    203:     uint32_t saddr;
                    204:     uint16_t reg;
                    205: 
                    206:     saddr = addr & LE_MAXREG;
                    207:     switch (saddr >> 1) {
                    208:     case LE_RDP:
                    209:        DPRINTF("write dreg[%d] = %4.4x\n", s->addr, val);
                    210:        switch(s->addr) {
                    211:        case LE_CSR0:
                    212:            if (val & LE_C0_STOP) {
                    213:                s->regs[LE_CSR0] = LE_C0_STOP;
                    214:                break;
                    215:            }
                    216: 
                    217:            reg = s->regs[LE_CSR0];
                    218: 
                    219:            // 1 = clear for some bits
                    220:            reg &= ~(val & 0x7f00);
                    221: 
                    222:            // generated bits
                    223:            reg &= ~(LE_C0_ERR | LE_C0_INTR);
                    224:            if (reg & 0x7100)
                    225:                reg |= LE_C0_ERR;
                    226:            if (reg & 0x7f00)
                    227:                reg |= LE_C0_INTR;
                    228: 
                    229:            // direct bit
                    230:            reg &= ~LE_C0_INEA;
                    231:            reg |= val & LE_C0_INEA;
                    232: 
                    233:            // exclusive bits
                    234:            if (val & LE_C0_INIT) {
                    235:                reg |= LE_C0_IDON | LE_C0_INIT;
                    236:                reg &= ~LE_C0_STOP;
                    237:            }
                    238:            else if (val & LE_C0_STRT) {
                    239:                reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON;
                    240:                reg &= ~LE_C0_STOP;
                    241:            }
                    242: 
                    243:            s->regs[LE_CSR0] = reg;
                    244:            break;
                    245:        case LE_CSR1:
                    246:            s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff);
                    247:            s->regs[s->addr] = val;
                    248:            break;
                    249:        case LE_CSR2:
                    250:            s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16);
                    251:            s->regs[s->addr] = val;
                    252:            break;
                    253:        case LE_CSR3:
                    254:            s->regs[s->addr] = val;
                    255:            break;
                    256:        }
                    257:        break;
                    258:     case LE_RAP:
                    259:        DPRINTF("write areg = %4.4x\n", val);
                    260:        if (val < LE_NREGS)
                    261:            s->addr = val;
                    262:        break;
                    263:     default:
                    264:        DPRINTF("write unknown(%d) = %4.4x\n", saddr>>1, val);
                    265:        break;
                    266:     }
                    267:     lance_send(s);
                    268: }
                    269: 
                    270: static CPUReadMemoryFunc *lance_mem_read[3] = {
                    271:     lance_mem_readw,
                    272:     lance_mem_readw,
                    273:     lance_mem_readw,
                    274: };
                    275: 
                    276: static CPUWriteMemoryFunc *lance_mem_write[3] = {
                    277:     lance_mem_writew,
                    278:     lance_mem_writew,
                    279:     lance_mem_writew,
                    280: };
                    281: 
                    282: 
                    283: /* return the max buffer size if the LANCE can receive more data */
                    284: static int lance_can_receive(void *opaque)
                    285: {
                    286:     LANCEState *s = opaque;
                    287:     uint32_t dmaptr = s->leptr + s->ledmaregs[3];
                    288:     struct lance_init_block *ib;
                    289:     int i;
                    290:     uint8_t temp8;
                    291: 
                    292:     if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
                    293:        return 0;
                    294: 
                    295:     ib = (void *) iommu_translate(dmaptr);
                    296: 
                    297:     for (i = 0; i < RX_RING_SIZE; i++) {
                    298:        cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
                    299:        if (temp8 == (LE_R1_OWN)) {
                    300:            DPRINTF("can receive %d\n", RX_BUFF_SIZE);
                    301:            return RX_BUFF_SIZE;
                    302:        }
                    303:     }
                    304:     DPRINTF("cannot receive\n");
                    305:     return 0;
                    306: }
                    307: 
                    308: #define MIN_BUF_SIZE 60
                    309: 
                    310: static void lance_receive(void *opaque, const uint8_t *buf, int size)
                    311: {
                    312:     LANCEState *s = opaque;
                    313:     uint32_t dmaptr = s->leptr + s->ledmaregs[3];
                    314:     struct lance_init_block *ib;
                    315:     unsigned int i, old_rxptr;
                    316:     uint16_t temp16;
                    317:     uint8_t temp8;
                    318: 
                    319:     DPRINTF("receive size %d\n", size);
                    320:     if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
                    321:        return;
                    322: 
                    323:     ib = (void *) iommu_translate(dmaptr);
                    324: 
                    325:     old_rxptr = s->rxptr;
                    326:     for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
                    327:        cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
                    328:        if (temp8 == (LE_R1_OWN)) {
                    329:            s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK;
                    330:            temp16 = size + 4;
                    331:            bswap16s(&temp16);
                    332:            cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp16, 2);
                    333:            cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size);
                    334:            temp8 = LE_R1_POK;
                    335:            cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
                    336:            s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
                    337:            if (s->regs[LE_CSR0] & LE_C0_INEA)
                    338:                pic_set_irq(s->irq, 1);
                    339:            DPRINTF("got packet, len %d\n", size);
                    340:            return;
                    341:        }
                    342:     }
                    343: }
                    344: 
                    345: static void lance_send(void *opaque)
                    346: {
                    347:     LANCEState *s = opaque;
                    348:     uint32_t dmaptr = s->leptr + s->ledmaregs[3];
                    349:     struct lance_init_block *ib;
                    350:     unsigned int i, old_txptr;
                    351:     uint16_t temp16;
                    352:     uint8_t temp8;
                    353:     char pkt_buf[PKT_BUF_SZ];
                    354: 
                    355:     DPRINTF("sending packet? (csr0 %4.4x)\n", s->regs[LE_CSR0]);
                    356:     if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
                    357:        return;
                    358: 
                    359:     ib = (void *) iommu_translate(dmaptr);
                    360: 
                    361:     DPRINTF("sending packet? (dmaptr %8.8x) (ib %p) (btx_ring %p)\n", dmaptr, ib, &ib->btx_ring);
                    362:     old_txptr = s->txptr;
                    363:     for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
                    364:        cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
                    365:        if (temp8 == (LE_T1_POK|LE_T1_OWN)) {
                    366:            cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp16, 2);
                    367:            bswap16s(&temp16);
                    368:            temp16 = (~temp16) + 1;
                    369:            cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16);
                    370:            DPRINTF("sending packet, len %d\n", temp16);
                    371:            qemu_send_packet(s->nd, pkt_buf, temp16);
                    372:            temp8 = LE_T1_POK;
                    373:            cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
                    374:            s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK;
                    375:            s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
                    376:        }
                    377:     }
                    378:     if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
                    379:        pic_set_irq(s->irq, 1);
                    380: }
                    381: 
                    382: static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
                    383: {
                    384:     LANCEState *s = opaque;
                    385:     uint32_t saddr;
                    386: 
                    387:     saddr = (addr & LEDMA_MAXADDR) >> 2;
                    388:     return s->ledmaregs[saddr];
                    389: }
                    390: 
                    391: static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
                    392: {
                    393:     LANCEState *s = opaque;
                    394:     uint32_t saddr;
                    395: 
                    396:     saddr = (addr & LEDMA_MAXADDR) >> 2;
                    397:     s->ledmaregs[saddr] = val;
                    398: }
                    399: 
                    400: static CPUReadMemoryFunc *ledma_mem_read[3] = {
                    401:     ledma_mem_readl,
                    402:     ledma_mem_readl,
                    403:     ledma_mem_readl,
                    404: };
                    405: 
                    406: static CPUWriteMemoryFunc *ledma_mem_write[3] = {
                    407:     ledma_mem_writel,
                    408:     ledma_mem_writel,
                    409:     ledma_mem_writel,
                    410: };
                    411: 
                    412: static void lance_save(QEMUFile *f, void *opaque)
                    413: {
                    414:     LANCEState *s = opaque;
                    415:     int i;
                    416:     
                    417:     qemu_put_be32s(f, &s->leptr);
                    418:     qemu_put_be16s(f, &s->addr);
                    419:     for (i = 0; i < LE_NREGS; i ++)
                    420:        qemu_put_be16s(f, &s->regs[i]);
                    421:     qemu_put_buffer(f, s->phys, 6);
                    422:     qemu_put_be32s(f, &s->irq);
                    423:     for (i = 0; i < LEDMA_REGS; i ++)
                    424:        qemu_put_be32s(f, &s->ledmaregs[i]);
                    425: }
                    426: 
                    427: static int lance_load(QEMUFile *f, void *opaque, int version_id)
                    428: {
                    429:     LANCEState *s = opaque;
                    430:     int i;
                    431:     
                    432:     if (version_id != 1)
                    433:         return -EINVAL;
                    434: 
                    435:     qemu_get_be32s(f, &s->leptr);
                    436:     qemu_get_be16s(f, &s->addr);
                    437:     for (i = 0; i < LE_NREGS; i ++)
                    438:        qemu_get_be16s(f, &s->regs[i]);
                    439:     qemu_get_buffer(f, s->phys, 6);
                    440:     qemu_get_be32s(f, &s->irq);
                    441:     for (i = 0; i < LEDMA_REGS; i ++)
                    442:        qemu_get_be32s(f, &s->ledmaregs[i]);
                    443:     return 0;
                    444: }
                    445: 
                    446: void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
                    447: {
                    448:     LANCEState *s;
                    449:     int lance_io_memory, ledma_io_memory;
                    450: 
                    451:     s = qemu_mallocz(sizeof(LANCEState));
                    452:     if (!s)
                    453:         return;
                    454: 
                    455:     s->nd = nd;
                    456:     s->irq = irq;
                    457: 
                    458:     lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
                    459:     cpu_register_physical_memory(leaddr, 4, lance_io_memory);
                    460: 
                    461:     ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s);
                    462:     cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
                    463: 
                    464:     lance_reset(s);
                    465:     qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
                    466:     register_savevm("lance", leaddr, 1, lance_save, lance_load, s);
                    467:     qemu_register_reset(lance_reset, s);
                    468: }
                    469: 

unix.superglobalmegacorp.com

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