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

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 {
1.1.1.2   root      157:     VLANClientState *vc;
                    158:     uint8_t macaddr[6]; /* init mac address */
1.1       root      159:     uint32_t leptr;
                    160:     uint16_t addr;
                    161:     uint16_t regs[LE_NREGS];
                    162:     uint8_t phys[6]; /* mac address */
                    163:     int irq;
                    164:     unsigned int rxptr, txptr;
                    165:     uint32_t ledmaregs[LEDMA_REGS];
                    166: } LANCEState;
                    167: 
                    168: static void lance_send(void *opaque);
                    169: 
                    170: static void lance_reset(void *opaque)
                    171: {
                    172:     LANCEState *s = opaque;
1.1.1.2   root      173:     memcpy(s->phys, s->macaddr, 6);
1.1       root      174:     s->rxptr = 0;
                    175:     s->txptr = 0;
                    176:     memset(s->regs, 0, LE_NREGS * 2);
                    177:     s->regs[LE_CSR0] = LE_C0_STOP;
                    178:     memset(s->ledmaregs, 0, LEDMA_REGS * 4);
                    179: }
                    180: 
                    181: static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
                    182: {
                    183:     LANCEState *s = opaque;
                    184:     uint32_t saddr;
                    185: 
                    186:     saddr = addr & LE_MAXREG;
                    187:     switch (saddr >> 1) {
                    188:     case LE_RDP:
                    189:        DPRINTF("read dreg[%d] = %4.4x\n", s->addr, s->regs[s->addr]);
                    190:        return s->regs[s->addr];
                    191:     case LE_RAP:
                    192:        DPRINTF("read areg = %4.4x\n", s->addr);
                    193:        return s->addr;
                    194:     default:
                    195:        DPRINTF("read unknown(%d)\n", saddr>>1);
                    196:        break;
                    197:     }
                    198:     return 0;
                    199: }
                    200: 
                    201: static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
                    202: {
                    203:     LANCEState *s = opaque;
                    204:     uint32_t saddr;
                    205:     uint16_t reg;
                    206: 
                    207:     saddr = addr & LE_MAXREG;
                    208:     switch (saddr >> 1) {
                    209:     case LE_RDP:
                    210:        DPRINTF("write dreg[%d] = %4.4x\n", s->addr, val);
                    211:        switch(s->addr) {
                    212:        case LE_CSR0:
                    213:            if (val & LE_C0_STOP) {
                    214:                s->regs[LE_CSR0] = LE_C0_STOP;
                    215:                break;
                    216:            }
                    217: 
                    218:            reg = s->regs[LE_CSR0];
                    219: 
                    220:            // 1 = clear for some bits
                    221:            reg &= ~(val & 0x7f00);
                    222: 
                    223:            // generated bits
                    224:            reg &= ~(LE_C0_ERR | LE_C0_INTR);
                    225:            if (reg & 0x7100)
                    226:                reg |= LE_C0_ERR;
                    227:            if (reg & 0x7f00)
                    228:                reg |= LE_C0_INTR;
                    229: 
                    230:            // direct bit
                    231:            reg &= ~LE_C0_INEA;
                    232:            reg |= val & LE_C0_INEA;
                    233: 
                    234:            // exclusive bits
                    235:            if (val & LE_C0_INIT) {
                    236:                reg |= LE_C0_IDON | LE_C0_INIT;
                    237:                reg &= ~LE_C0_STOP;
                    238:            }
                    239:            else if (val & LE_C0_STRT) {
                    240:                reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON;
                    241:                reg &= ~LE_C0_STOP;
                    242:            }
                    243: 
                    244:            s->regs[LE_CSR0] = reg;
                    245:            break;
                    246:        case LE_CSR1:
                    247:            s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff);
                    248:            s->regs[s->addr] = val;
                    249:            break;
                    250:        case LE_CSR2:
                    251:            s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16);
                    252:            s->regs[s->addr] = val;
                    253:            break;
                    254:        case LE_CSR3:
                    255:            s->regs[s->addr] = val;
                    256:            break;
                    257:        }
                    258:        break;
                    259:     case LE_RAP:
                    260:        DPRINTF("write areg = %4.4x\n", val);
                    261:        if (val < LE_NREGS)
                    262:            s->addr = val;
                    263:        break;
                    264:     default:
                    265:        DPRINTF("write unknown(%d) = %4.4x\n", saddr>>1, val);
                    266:        break;
                    267:     }
                    268:     lance_send(s);
                    269: }
                    270: 
                    271: static CPUReadMemoryFunc *lance_mem_read[3] = {
                    272:     lance_mem_readw,
                    273:     lance_mem_readw,
                    274:     lance_mem_readw,
                    275: };
                    276: 
                    277: static CPUWriteMemoryFunc *lance_mem_write[3] = {
                    278:     lance_mem_writew,
                    279:     lance_mem_writew,
                    280:     lance_mem_writew,
                    281: };
                    282: 
                    283: 
                    284: #define MIN_BUF_SIZE 60
                    285: 
1.1.1.3 ! root      286: static int lance_can_receive(void *opaque)
        !           287: {
        !           288:     return 1;
        !           289: }
        !           290: 
1.1       root      291: static void lance_receive(void *opaque, const uint8_t *buf, int size)
                    292: {
                    293:     LANCEState *s = opaque;
                    294:     uint32_t dmaptr = s->leptr + s->ledmaregs[3];
                    295:     struct lance_init_block *ib;
                    296:     unsigned int i, old_rxptr;
                    297:     uint16_t temp16;
                    298:     uint8_t temp8;
                    299: 
                    300:     DPRINTF("receive size %d\n", size);
                    301:     if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
                    302:        return;
                    303: 
                    304:     ib = (void *) iommu_translate(dmaptr);
                    305: 
                    306:     old_rxptr = s->rxptr;
                    307:     for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
                    308:        cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
                    309:        if (temp8 == (LE_R1_OWN)) {
                    310:            s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK;
                    311:            temp16 = size + 4;
                    312:            bswap16s(&temp16);
                    313:            cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp16, 2);
                    314:            cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size);
                    315:            temp8 = LE_R1_POK;
                    316:            cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
                    317:            s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
                    318:            if (s->regs[LE_CSR0] & LE_C0_INEA)
                    319:                pic_set_irq(s->irq, 1);
                    320:            DPRINTF("got packet, len %d\n", size);
                    321:            return;
                    322:        }
                    323:     }
                    324: }
                    325: 
                    326: static void lance_send(void *opaque)
                    327: {
                    328:     LANCEState *s = opaque;
                    329:     uint32_t dmaptr = s->leptr + s->ledmaregs[3];
                    330:     struct lance_init_block *ib;
                    331:     unsigned int i, old_txptr;
                    332:     uint16_t temp16;
                    333:     uint8_t temp8;
                    334:     char pkt_buf[PKT_BUF_SZ];
                    335: 
                    336:     DPRINTF("sending packet? (csr0 %4.4x)\n", s->regs[LE_CSR0]);
                    337:     if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
                    338:        return;
                    339: 
                    340:     ib = (void *) iommu_translate(dmaptr);
                    341: 
                    342:     DPRINTF("sending packet? (dmaptr %8.8x) (ib %p) (btx_ring %p)\n", dmaptr, ib, &ib->btx_ring);
                    343:     old_txptr = s->txptr;
                    344:     for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
                    345:        cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
                    346:        if (temp8 == (LE_T1_POK|LE_T1_OWN)) {
                    347:            cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp16, 2);
                    348:            bswap16s(&temp16);
                    349:            temp16 = (~temp16) + 1;
                    350:            cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16);
                    351:            DPRINTF("sending packet, len %d\n", temp16);
1.1.1.2   root      352:            qemu_send_packet(s->vc, pkt_buf, temp16);
1.1       root      353:            temp8 = LE_T1_POK;
                    354:            cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
                    355:            s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK;
                    356:            s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
                    357:        }
                    358:     }
                    359:     if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
                    360:        pic_set_irq(s->irq, 1);
                    361: }
                    362: 
                    363: static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
                    364: {
                    365:     LANCEState *s = opaque;
                    366:     uint32_t saddr;
                    367: 
                    368:     saddr = (addr & LEDMA_MAXADDR) >> 2;
                    369:     return s->ledmaregs[saddr];
                    370: }
                    371: 
                    372: static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
                    373: {
                    374:     LANCEState *s = opaque;
                    375:     uint32_t saddr;
                    376: 
                    377:     saddr = (addr & LEDMA_MAXADDR) >> 2;
                    378:     s->ledmaregs[saddr] = val;
                    379: }
                    380: 
                    381: static CPUReadMemoryFunc *ledma_mem_read[3] = {
                    382:     ledma_mem_readl,
                    383:     ledma_mem_readl,
                    384:     ledma_mem_readl,
                    385: };
                    386: 
                    387: static CPUWriteMemoryFunc *ledma_mem_write[3] = {
                    388:     ledma_mem_writel,
                    389:     ledma_mem_writel,
                    390:     ledma_mem_writel,
                    391: };
                    392: 
                    393: static void lance_save(QEMUFile *f, void *opaque)
                    394: {
                    395:     LANCEState *s = opaque;
                    396:     int i;
                    397:     
                    398:     qemu_put_be32s(f, &s->leptr);
                    399:     qemu_put_be16s(f, &s->addr);
                    400:     for (i = 0; i < LE_NREGS; i ++)
                    401:        qemu_put_be16s(f, &s->regs[i]);
                    402:     qemu_put_buffer(f, s->phys, 6);
                    403:     qemu_put_be32s(f, &s->irq);
                    404:     for (i = 0; i < LEDMA_REGS; i ++)
                    405:        qemu_put_be32s(f, &s->ledmaregs[i]);
                    406: }
                    407: 
                    408: static int lance_load(QEMUFile *f, void *opaque, int version_id)
                    409: {
                    410:     LANCEState *s = opaque;
                    411:     int i;
                    412:     
                    413:     if (version_id != 1)
                    414:         return -EINVAL;
                    415: 
                    416:     qemu_get_be32s(f, &s->leptr);
                    417:     qemu_get_be16s(f, &s->addr);
                    418:     for (i = 0; i < LE_NREGS; i ++)
                    419:        qemu_get_be16s(f, &s->regs[i]);
                    420:     qemu_get_buffer(f, s->phys, 6);
                    421:     qemu_get_be32s(f, &s->irq);
                    422:     for (i = 0; i < LEDMA_REGS; i ++)
                    423:        qemu_get_be32s(f, &s->ledmaregs[i]);
                    424:     return 0;
                    425: }
                    426: 
1.1.1.2   root      427: void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
1.1       root      428: {
                    429:     LANCEState *s;
                    430:     int lance_io_memory, ledma_io_memory;
                    431: 
                    432:     s = qemu_mallocz(sizeof(LANCEState));
                    433:     if (!s)
                    434:         return;
                    435: 
                    436:     s->irq = irq;
                    437: 
                    438:     lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
                    439:     cpu_register_physical_memory(leaddr, 4, lance_io_memory);
                    440: 
                    441:     ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s);
                    442:     cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
                    443: 
1.1.1.2   root      444:     memcpy(s->macaddr, nd->macaddr, 6);
                    445: 
1.1       root      446:     lance_reset(s);
1.1.1.2   root      447: 
1.1.1.3 ! root      448:     s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, lance_can_receive, s);
1.1.1.2   root      449: 
                    450:     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
                    451:              "lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
                    452:              s->macaddr[0],
                    453:              s->macaddr[1],
                    454:              s->macaddr[2],
                    455:              s->macaddr[3],
                    456:              s->macaddr[4],
                    457:              s->macaddr[5]);
                    458: 
1.1       root      459:     register_savevm("lance", leaddr, 1, lance_save, lance_load, s);
                    460:     qemu_register_reset(lance_reset, s);
                    461: }
                    462: 

unix.superglobalmegacorp.com

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