?? pcnet.c
字號:
#ifdef PCNET_DEBUG_IO printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);#endif if (BCR_DWIO(s)) { switch (addr & 0x0f) { case 0x00: /* RDP */ pcnet_csr_writew(s, s->rap, val & 0xffff); break; case 0x04: s->rap = val & 0x7f; break; case 0x0c: pcnet_bcr_writew(s, s->rap, val & 0xffff); break; } } else if ((addr & 0x0f) == 0) { /* switch device to dword i/o mode */ pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);#ifdef PCNET_DEBUG_IO printf("device switched into dword i/o mode\n");#endif } pcnet_update_irq(s);}static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr){ PCNetState *s = opaque; uint32_t val = -1; pcnet_poll_timer(s); if (BCR_DWIO(s)) { switch (addr & 0x0f) { case 0x00: /* RDP */ val = pcnet_csr_readw(s, s->rap); break; case 0x04: val = s->rap; break; case 0x08: pcnet_s_reset(s); val = 0; break; case 0x0c: val = pcnet_bcr_readw(s, s->rap); break; } } pcnet_update_irq(s);#ifdef PCNET_DEBUG_IO printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);#endif return val;}static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type){ PCNetState *d = (PCNetState *)pci_dev;#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);}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%08x 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%08x 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%08x 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); }}static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr){ 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%08x val = 0x%04x\n", addr, val & 0xffff);#endif return val;}static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val){ PCNetState *d = opaque;#ifdef PCNET_DEBUG_IO printf("pcnet_mmio_writel addr=0x%08x 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); }}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%08x val=0x%08x\n", addr, val);#endif return val;}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_be32(f, s->rap); qemu_put_be32(f, s->isr); qemu_put_be32(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_be32(f, s->xmit_pos); qemu_put_be32(f, s->recv_pos); qemu_put_buffer(f, s->buffer, 4096); qemu_put_be32(f, s->tx_busy); qemu_put_timer(f, s->poll_timer);}static int pcnet_load(QEMUFile *f, void *opaque, int version_id){ PCNetState *s = opaque; int i, ret; if (version_id != 2) return -EINVAL; if (s->pci_dev) { ret = pci_device_load(s->pci_dev, f); if (ret < 0) return ret; } qemu_get_be32s(f, (uint32_t*)&s->rap); qemu_get_be32s(f, (uint32_t*)&s->isr); qemu_get_be32s(f, (uint32_t*)&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_be32s(f, (uint32_t*)&s->xmit_pos); qemu_get_be32s(f, (uint32_t*)&s->recv_pos); qemu_get_buffer(f, s->buffer, 4096); qemu_get_be32s(f, (uint32_t*)&s->tx_busy); qemu_get_timer(f, s->poll_timer); return 0;}static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str){ int instance; d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d); d->nd = nd; if (nd && nd->vlan) { d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, pcnet_can_receive, d); snprintf(d->vc->info_str, sizeof(d->vc->info_str), "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x", d->nd->macaddr[0], d->nd->macaddr[1], d->nd->macaddr[2], d->nd->macaddr[3], d->nd->macaddr[4], d->nd->macaddr[5]); } else { d->vc = NULL; } pcnet_h_reset(d); instance = pci_bus_num(d->dev.bus) << 8 | d->dev.devfn; register_savevm("pcnet", instance, 2, pcnet_save, pcnet_load, d);}/* 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){ PCNetState *d = (PCNetState *)pci_dev;#ifdef PCNET_DEBUG_IO printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);#endif cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->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);}void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn){ PCNetState *d; uint8_t *pci_conf;#if 0 printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));#endif d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState), devfn, NULL, NULL); pci_conf = d->dev.config; *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022); *(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000); *(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_conf[0x0a] = 0x00; // ethernet network controller pci_conf[0x0b] = 0x02; pci_conf[0x0e] = 0x00; // 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 */ d->mmio_index = cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d); pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, PCI_ADDRESS_SPACE_IO, pcnet_ioport_map); pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map); d->irq = d->dev.irq[0]; d->phys_mem_read = pci_physical_memory_read; d->phys_mem_write = pci_physical_memory_write; d->pci_dev = &d->dev; pcnet_common_init(d, nd, "pcnet");}/* 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){ if (level) pcnet_h_reset(opaque);}static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val){#ifdef PCNET_DEBUG_IO printf("lance_mem_writew addr=" TARGET_FMT_plx " val=0x%04x\n", addr, val & 0xffff);#endif pcnet_ioport_writew(opaque, addr & 7, val & 0xffff);}static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr){ uint32_t val; val = pcnet_ioport_readw(opaque, addr & 7);#ifdef PCNET_DEBUG_IO printf("pcnet_mmio_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,};void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque, qemu_irq irq, qemu_irq *reset){ PCNetState *d; int lance_io_memory; d = qemu_mallocz(sizeof(PCNetState)); if (!d) return; lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d); d->dma_opaque = dma_opaque; *reset = *qemu_allocate_irqs(parent_lance_reset, d, 1); cpu_register_physical_memory(leaddr, 4, lance_io_memory); d->irq = irq; d->phys_mem_read = ledma_memory_read; d->phys_mem_write = ledma_memory_write; pcnet_common_init(d, nd, "lance");}#endif /* TARGET_SPARC */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -