|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.