X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/2152390dca9975b1aaaa6f0518ebdd359477905b..dbf352ad6e55dc7b40c62b402289164265a4f17c:/hw/pcnet.c diff --git a/hw/pcnet.c b/hw/pcnet.c index 4519780cf8..cf16fd4d01 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -35,11 +35,13 @@ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt */ -#include "sysbus.h" -#include "pci.h" +#include "qdev.h" #include "net.h" #include "qemu-timer.h" #include "qemu_socket.h" +#include "sysemu.h" + +#include "pcnet.h" //#define PCNET_DEBUG //#define PCNET_DEBUG_IO @@ -50,48 +52,6 @@ //#define PCNET_DEBUG_MATCH -#define PCNET_IOPORT_SIZE 0x20 -#define PCNET_PNPMMIO_SIZE 0x20 - -#define PCNET_LOOPTEST_CRC 1 -#define PCNET_LOOPTEST_NOCRC 2 - - -typedef struct PCNetState_st PCNetState; - -struct PCNetState_st { - PCIDevice *pci_dev; - VLANClientState *vc; - uint8_t macaddr[6]; - QEMUTimer *poll_timer; - int rap, isr, lnkst; - uint32_t rdra, tdra; - uint8_t prom[16]; - uint16_t csr[128]; - uint16_t bcr[32]; - uint64_t timer; - int mmio_index, xmit_pos, recv_pos; - uint8_t buffer[4096]; - int tx_busy; - qemu_irq irq; - void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr, - uint8_t *buf, int len, int do_bswap); - void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr, - uint8_t *buf, int len, int do_bswap); - void *dma_opaque; - int looptest; -}; - -typedef struct { - PCIDevice pci_dev; - PCNetState state; -} PCIPCNetState; - -typedef struct { - SysBusDevice busdev; - PCNetState state; -} SysBusPCNetState; - struct qemu_ether_header { uint8_t ether_dhost[6]; uint8_t ether_shost[6]; @@ -153,23 +113,23 @@ struct qemu_ether_header { #define CSR_XMTRL(S) ((S)->csr[78]) #define CSR_MISSC(S) ((S)->csr[112]) -#define CSR_IADR(S) ((S)->csr[ 1] | ((S)->csr[ 2] << 16)) -#define CSR_CRBA(S) ((S)->csr[18] | ((S)->csr[19] << 16)) -#define CSR_CXBA(S) ((S)->csr[20] | ((S)->csr[21] << 16)) -#define CSR_NRBA(S) ((S)->csr[22] | ((S)->csr[23] << 16)) -#define CSR_BADR(S) ((S)->csr[24] | ((S)->csr[25] << 16)) -#define CSR_NRDA(S) ((S)->csr[26] | ((S)->csr[27] << 16)) -#define CSR_CRDA(S) ((S)->csr[28] | ((S)->csr[29] << 16)) -#define CSR_BADX(S) ((S)->csr[30] | ((S)->csr[31] << 16)) -#define CSR_NXDA(S) ((S)->csr[32] | ((S)->csr[33] << 16)) -#define CSR_CXDA(S) ((S)->csr[34] | ((S)->csr[35] << 16)) -#define CSR_NNRD(S) ((S)->csr[36] | ((S)->csr[37] << 16)) -#define CSR_NNXD(S) ((S)->csr[38] | ((S)->csr[39] << 16)) -#define CSR_PXDA(S) ((S)->csr[60] | ((S)->csr[61] << 16)) -#define CSR_NXBA(S) ((S)->csr[64] | ((S)->csr[65] << 16)) +#define CSR_IADR(S) ((S)->csr[ 1] | ((uint32_t)(S)->csr[ 2] << 16)) +#define CSR_CRBA(S) ((S)->csr[18] | ((uint32_t)(S)->csr[19] << 16)) +#define CSR_CXBA(S) ((S)->csr[20] | ((uint32_t)(S)->csr[21] << 16)) +#define CSR_NRBA(S) ((S)->csr[22] | ((uint32_t)(S)->csr[23] << 16)) +#define CSR_BADR(S) ((S)->csr[24] | ((uint32_t)(S)->csr[25] << 16)) +#define CSR_NRDA(S) ((S)->csr[26] | ((uint32_t)(S)->csr[27] << 16)) +#define CSR_CRDA(S) ((S)->csr[28] | ((uint32_t)(S)->csr[29] << 16)) +#define CSR_BADX(S) ((S)->csr[30] | ((uint32_t)(S)->csr[31] << 16)) +#define CSR_NXDA(S) ((S)->csr[32] | ((uint32_t)(S)->csr[33] << 16)) +#define CSR_CXDA(S) ((S)->csr[34] | ((uint32_t)(S)->csr[35] << 16)) +#define CSR_NNRD(S) ((S)->csr[36] | ((uint32_t)(S)->csr[37] << 16)) +#define CSR_NNXD(S) ((S)->csr[38] | ((uint32_t)(S)->csr[39] << 16)) +#define CSR_PXDA(S) ((S)->csr[60] | ((uint32_t)(S)->csr[61] << 16)) +#define CSR_NXBA(S) ((S)->csr[64] | ((uint32_t)(S)->csr[65] << 16)) #define PHYSADDR(S,A) \ - (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16)) + (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(S)->csr[2])<<16)) struct pcnet_initblk16 { uint16_t mode; @@ -727,7 +687,7 @@ static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_ti { int64_t next_time = current_time + muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)), - ticks_per_sec, 33000000L); + get_ticks_per_sec(), 33000000L); if (next_time <= current_time) next_time = current_time + 1; return next_time; @@ -739,7 +699,6 @@ static void pcnet_poll_timer(void *opaque); static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap); static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value); static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val); -static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap); static void pcnet_s_reset(PCNetState *s) { @@ -936,6 +895,7 @@ static void pcnet_start(PCNetState *s) s->csr[0] &= ~0x0004; /* clear STOP bit */ s->csr[0] |= 0x0002; + pcnet_poll_timer(s); } static void pcnet_stop(PCNetState *s) @@ -1062,32 +1022,30 @@ static int pcnet_tdte_poll(PCNetState *s) return !!(CSR_CXST(s) & 0x8000); } -static int pcnet_can_receive(VLANClientState *vc) +int pcnet_can_receive(VLANClientState *nc) { - PCNetState *s = vc->opaque; + PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; if (CSR_STOP(s) || CSR_SPND(s)) return 0; - if (s->recv_pos > 0) - return 0; - return sizeof(s->buffer)-16; } #define MIN_BUF_SIZE 60 -static ssize_t pcnet_receive(VLANClientState *vc, const uint8_t *buf, size_t size_) +ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_) { - PCNetState *s = vc->opaque; + PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; int is_padr = 0, is_bcast = 0, is_ladr = 0; uint8_t buf1[60]; int remaining; int crc_err = 0; int size = size_; - if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size) + if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size || + (CSR_LOOP(s) && !s->looptest)) { return -1; - + } #ifdef PCNET_DEBUG printf("pcnet_receive size=%d\n", size); #endif @@ -1305,11 +1263,11 @@ static void pcnet_transmit(PCNetState *s) if (BCR_SWSTYLE(s) == 1) add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS); s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC; - pcnet_receive(s->vc, s->buffer, s->xmit_pos); + pcnet_receive(&s->nic->nc, s->buffer, s->xmit_pos); s->looptest = 0; } else - if (s->vc) - qemu_send_packet(s->vc, s->buffer, s->xmit_pos); + if (s->nic) + qemu_send_packet(&s->nic->nc, s->buffer, s->xmit_pos); s->csr[0] &= ~0x0008; /* clear TDMD */ s->csr[4] |= 0x0004; /* set TXSTRT */ @@ -1378,7 +1336,7 @@ static void pcnet_poll_timer(void *opaque) pcnet_update_irq(s); if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) { - uint64_t now = qemu_get_clock(vm_clock) * 33; + uint64_t now = qemu_get_clock_ns(vm_clock) * 33; if (!s->timer || !now) s->timer = now; else { @@ -1390,7 +1348,7 @@ static void pcnet_poll_timer(void *opaque) CSR_POLL(s) = t; } qemu_mod_timer(s->poll_timer, - pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock))); + pcnet_get_next_poll_time(s,qemu_get_clock_ns(vm_clock))); } } @@ -1574,7 +1532,7 @@ static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val) } } -static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap) +uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap) { uint32_t val; rap &= 127; @@ -1596,22 +1554,9 @@ static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap) return val; } -static void pcnet_h_reset(void *opaque) +void pcnet_h_reset(void *opaque) { PCNetState *s = opaque; - int i; - uint16_t checksum; - - /* Initialize the PROM */ - - memcpy(s->prom, s->macaddr, 6); - s->prom[12] = s->prom[13] = 0x00; - s->prom[14] = s->prom[15] = 0x57; - - for (i = 0,checksum = 0; i < 16; i++) - checksum += s->prom[i]; - *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum); - s->bcr[BCR_MSRDA] = 0x0005; s->bcr[BCR_MSWRA] = 0x0005; @@ -1627,30 +1572,11 @@ static void pcnet_h_reset(void *opaque) s->bcr[BCR_PLAT ] = 0xff06; pcnet_s_reset(s); + pcnet_update_irq(s); + pcnet_poll_timer(s); } -static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val) -{ - PCNetState *s = opaque; -#ifdef PCNET_DEBUG - printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val); -#endif - /* Check APROMWE bit to enable write access */ - if (pcnet_bcr_readw(s,2) & 0x80) - s->prom[addr & 15] = val; -} - -static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr) -{ - PCNetState *s = opaque; - uint32_t val = s->prom[addr &= 15]; -#ifdef PCNET_DEBUG - printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val); -#endif - return val; -} - -static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val) +void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val) { PCNetState *s = opaque; pcnet_poll_timer(s); @@ -1673,7 +1599,7 @@ static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val) pcnet_update_irq(s); } -static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr) +uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr) { PCNetState *s = opaque; uint32_t val = -1; @@ -1702,7 +1628,7 @@ static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr) return val; } -static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val) +void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val) { PCNetState *s = opaque; pcnet_poll_timer(s); @@ -1732,7 +1658,7 @@ static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val) pcnet_update_irq(s); } -static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr) +uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr) { PCNetState *s = opaque; uint32_t val = -1; @@ -1761,400 +1687,79 @@ static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr) return val; } -static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num, - uint32_t addr, uint32_t size, int type) +static bool is_version_2(void *opaque, int version_id) { - PCNetState *d = &((PCIPCNetState *)pci_dev)->state; - -#ifdef PCNET_DEBUG_IO - printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size); -#endif - - register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d); - register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d); - - register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d); - register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d); - register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d); - register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d); + return version_id == 2; } -static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) -{ - PCNetState *d = opaque; -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_writeb addr=0x" TARGET_FMT_plx" val=0x%02x\n", addr, - val); -#endif - if (!(addr & 0x10)) - pcnet_aprom_writeb(d, addr & 0x0f, val); -} - -static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr) -{ - PCNetState *d = opaque; - uint32_t val = -1; - if (!(addr & 0x10)) - val = pcnet_aprom_readb(d, addr & 0x0f); -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_readb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr, - val & 0xff); -#endif - return val; -} - -static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) -{ - PCNetState *d = opaque; -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr, - val); -#endif - if (addr & 0x10) - pcnet_ioport_writew(d, addr & 0x0f, val); - else { - addr &= 0x0f; - pcnet_aprom_writeb(d, addr, val & 0xff); - pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8); +const VMStateDescription vmstate_pcnet = { + .name = "pcnet", + .version_id = 3, + .minimum_version_id = 2, + .minimum_version_id_old = 2, + .fields = (VMStateField []) { + VMSTATE_INT32(rap, PCNetState), + VMSTATE_INT32(isr, PCNetState), + VMSTATE_INT32(lnkst, PCNetState), + VMSTATE_UINT32(rdra, PCNetState), + VMSTATE_UINT32(tdra, PCNetState), + VMSTATE_BUFFER(prom, PCNetState), + VMSTATE_UINT16_ARRAY(csr, PCNetState, 128), + VMSTATE_UINT16_ARRAY(bcr, PCNetState, 32), + VMSTATE_UINT64(timer, PCNetState), + VMSTATE_INT32(xmit_pos, PCNetState), + VMSTATE_BUFFER(buffer, PCNetState), + VMSTATE_UNUSED_TEST(is_version_2, 4), + VMSTATE_INT32(tx_busy, PCNetState), + VMSTATE_TIMER(poll_timer, PCNetState), + VMSTATE_END_OF_LIST() } -} +}; -static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr) +void pcnet_common_cleanup(PCNetState *d) { - PCNetState *d = opaque; - uint32_t val = -1; - if (addr & 0x10) - val = pcnet_ioport_readw(d, addr & 0x0f); - else { - addr &= 0x0f; - val = pcnet_aprom_readb(d, addr+1); - val <<= 8; - val |= pcnet_aprom_readb(d, addr); - } -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_readw addr=0x" TARGET_FMT_plx" val = 0x%04x\n", addr, - val & 0xffff); -#endif - return val; + d->nic = NULL; } -static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) { - PCNetState *d = opaque; -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_writel addr=0x" TARGET_FMT_plx" val=0x%08x\n", addr, - val); -#endif - if (addr & 0x10) - pcnet_ioport_writel(d, addr & 0x0f, val); - else { - addr &= 0x0f; - pcnet_aprom_writeb(d, addr, val & 0xff); - pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8); - pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16); - pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24); - } -} + int i; + uint16_t checksum; -static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) -{ - PCNetState *d = opaque; - uint32_t val; - if (addr & 0x10) - val = pcnet_ioport_readl(d, addr & 0x0f); - else { - addr &= 0x0f; - val = pcnet_aprom_readb(d, addr+3); - val <<= 8; - val |= pcnet_aprom_readb(d, addr+2); - val <<= 8; - val |= pcnet_aprom_readb(d, addr+1); - val <<= 8; - val |= pcnet_aprom_readb(d, addr); - } -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, - val); -#endif - return val; -} + s->poll_timer = qemu_new_timer_ns(vm_clock, pcnet_poll_timer, s); + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(info, &s->conf, dev->info->name, dev->id, s); + qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); -static void pcnet_save(QEMUFile *f, void *opaque) -{ - PCNetState *s = opaque; - unsigned int i; - - if (s->pci_dev) - pci_device_save(s->pci_dev, f); - - qemu_put_sbe32(f, s->rap); - qemu_put_sbe32(f, s->isr); - qemu_put_sbe32(f, s->lnkst); - qemu_put_be32s(f, &s->rdra); - qemu_put_be32s(f, &s->tdra); - qemu_put_buffer(f, s->prom, 16); - for (i = 0; i < 128; i++) - qemu_put_be16s(f, &s->csr[i]); - for (i = 0; i < 32; i++) - qemu_put_be16s(f, &s->bcr[i]); - qemu_put_be64s(f, &s->timer); - qemu_put_sbe32(f, s->xmit_pos); - qemu_put_sbe32(f, s->recv_pos); - qemu_put_buffer(f, s->buffer, 4096); - qemu_put_sbe32(f, s->tx_busy); - qemu_put_timer(f, s->poll_timer); -} + add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0"); -static int pcnet_load(QEMUFile *f, void *opaque, int version_id) -{ - PCNetState *s = opaque; - int i, ret; + /* Initialize the PROM */ - if (version_id != 2) - return -EINVAL; + /* + Datasheet: http://pdfdata.datasheetsite.com/web/24528/AM79C970A.pdf + page 95 + */ + memcpy(s->prom, s->conf.macaddr.a, 6); + /* Reserved Location: must be 00h */ + s->prom[6] = s->prom[7] = 0x00; + /* Reserved Location: must be 00h */ + s->prom[8] = 0x00; + /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */ + s->prom[9] = 0x11; + /* User programmable space, init with 0 */ + s->prom[10] = s->prom[11] = 0x00; + /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh + and bytes 0Eh and 0Fh, must therefore be initialized with 0! */ + s->prom[12] = s->prom[13] = 0x00; + /* Must be ASCII W (57h) if compatibility to AMD + driver software is desired */ + s->prom[14] = s->prom[15] = 0x57; - if (s->pci_dev) { - ret = pci_device_load(s->pci_dev, f); - if (ret < 0) - return ret; + for (i = 0, checksum = 0; i < 16; i++) { + checksum += s->prom[i]; } - - qemu_get_sbe32s(f, &s->rap); - qemu_get_sbe32s(f, &s->isr); - qemu_get_sbe32s(f, &s->lnkst); - qemu_get_be32s(f, &s->rdra); - qemu_get_be32s(f, &s->tdra); - qemu_get_buffer(f, s->prom, 16); - for (i = 0; i < 128; i++) - qemu_get_be16s(f, &s->csr[i]); - for (i = 0; i < 32; i++) - qemu_get_be16s(f, &s->bcr[i]); - qemu_get_be64s(f, &s->timer); - qemu_get_sbe32s(f, &s->xmit_pos); - qemu_get_sbe32s(f, &s->recv_pos); - qemu_get_buffer(f, s->buffer, 4096); - qemu_get_sbe32s(f, &s->tx_busy); - qemu_get_timer(f, s->poll_timer); - - return 0; -} - -static void pcnet_common_cleanup(PCNetState *d) -{ - unregister_savevm("pcnet", d); - - qemu_del_timer(d->poll_timer); - qemu_free_timer(d->poll_timer); -} - -static void pcnet_common_init(DeviceState *dev, PCNetState *s, - NetCleanup *cleanup) -{ - s->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, s); - - qdev_get_macaddr(dev, s->macaddr); - s->vc = qdev_get_vlan_client(dev, - pcnet_can_receive, pcnet_receive, NULL, - cleanup, s); - pcnet_h_reset(s); - register_savevm("pcnet", -1, 2, pcnet_save, pcnet_load, s); -} - -/* PCI interface */ - -static CPUWriteMemoryFunc *pcnet_mmio_write[] = { - (CPUWriteMemoryFunc *)&pcnet_mmio_writeb, - (CPUWriteMemoryFunc *)&pcnet_mmio_writew, - (CPUWriteMemoryFunc *)&pcnet_mmio_writel -}; - -static CPUReadMemoryFunc *pcnet_mmio_read[] = { - (CPUReadMemoryFunc *)&pcnet_mmio_readb, - (CPUReadMemoryFunc *)&pcnet_mmio_readw, - (CPUReadMemoryFunc *)&pcnet_mmio_readl -}; - -static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, - uint32_t addr, uint32_t size, int type) -{ - PCIPCNetState *d = (PCIPCNetState *)pci_dev; - -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_map addr=0x%08x 0x%08x\n", addr, size); -#endif - - cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index); -} - -static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr, - uint8_t *buf, int len, int do_bswap) -{ - cpu_physical_memory_write(addr, buf, len); -} - -static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, - uint8_t *buf, int len, int do_bswap) -{ - cpu_physical_memory_read(addr, buf, len); -} - -static void pci_pcnet_cleanup(VLANClientState *vc) -{ - PCNetState *d = vc->opaque; - - pcnet_common_cleanup(d); -} - -static int pci_pcnet_uninit(PCIDevice *dev) -{ - PCIPCNetState *d = (PCIPCNetState *)dev; - - cpu_unregister_io_memory(d->state.mmio_index); + *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum); return 0; } - -static void pci_pcnet_init(PCIDevice *pci_dev) -{ - PCIPCNetState *d = (PCIPCNetState *)pci_dev; - PCNetState *s = &d->state; - uint8_t *pci_conf; - -#if 0 - printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", - sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD)); -#endif - - pci_dev->unregister = pci_pcnet_uninit; - - pci_conf = pci_dev->config; - - pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD); - pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AMD_LANCE); - *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007); - *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280); - pci_conf[0x08] = 0x10; - pci_conf[0x09] = 0x00; - pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET); - pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type - - *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001); - *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000); - - pci_conf[0x3d] = 1; // interrupt pin 0 - pci_conf[0x3e] = 0x06; - pci_conf[0x3f] = 0xff; - - /* Handler for memory-mapped I/O */ - s->mmio_index = - cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state); - - pci_register_bar((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, - PCI_ADDRESS_SPACE_IO, pcnet_ioport_map); - - pci_register_bar((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, - PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map); - - s->irq = pci_dev->irq[0]; - s->phys_mem_read = pci_physical_memory_read; - s->phys_mem_write = pci_physical_memory_write; - s->pci_dev = pci_dev; - - pcnet_common_init(&pci_dev->qdev, s, pci_pcnet_cleanup); -} - -/* SPARC32 interface */ - -#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) // Avoid compile failure -#include "sun4m.h" - -static void parent_lance_reset(void *opaque, int irq, int level) -{ - SysBusPCNetState *d = opaque; - if (level) - pcnet_h_reset(&d->state); -} - -static void lance_mem_writew(void *opaque, target_phys_addr_t addr, - uint32_t val) -{ - SysBusPCNetState *d = opaque; -#ifdef PCNET_DEBUG_IO - printf("lance_mem_writew addr=" TARGET_FMT_plx " val=0x%04x\n", addr, - val & 0xffff); -#endif - pcnet_ioport_writew(&d->state, addr, val & 0xffff); -} - -static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr) -{ - SysBusPCNetState *d = opaque; - uint32_t val; - - val = pcnet_ioport_readw(&d->state, addr); -#ifdef PCNET_DEBUG_IO - printf("lance_mem_readw addr=" TARGET_FMT_plx " val = 0x%04x\n", addr, - val & 0xffff); -#endif - - return val & 0xffff; -} - -static CPUReadMemoryFunc *lance_mem_read[3] = { - NULL, - lance_mem_readw, - NULL, -}; - -static CPUWriteMemoryFunc *lance_mem_write[3] = { - NULL, - lance_mem_writew, - NULL, -}; - -static void lance_cleanup(VLANClientState *vc) -{ - PCNetState *d = vc->opaque; - - pcnet_common_cleanup(d); -} - -static void lance_init(SysBusDevice *dev) -{ - SysBusPCNetState *d = FROM_SYSBUS(SysBusPCNetState, dev); - PCNetState *s = &d->state; - - s->mmio_index = - cpu_register_io_memory(lance_mem_read, lance_mem_write, d); - - s->dma_opaque = qdev_get_prop_ptr(&dev->qdev, "dma"); - - qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1); - - sysbus_init_mmio(dev, 4, s->mmio_index); - - sysbus_init_irq(dev, &s->irq); - - s->phys_mem_read = ledma_memory_read; - s->phys_mem_write = ledma_memory_write; - - pcnet_common_init(&dev->qdev, s, lance_cleanup); -} -#endif /* TARGET_SPARC */ - -static PCIDeviceInfo pcnet_info = { - .qdev.name = "pcnet", - .qdev.size = sizeof(PCIPCNetState), - .init = pci_pcnet_init, -}; - -static void pcnet_register_devices(void) -{ - pci_qdev_register(&pcnet_info); -#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) - sysbus_register_dev("lance", sizeof(SysBusPCNetState), lance_init); -#endif -} - -device_init(pcnet_register_devices)