📄 eepro100.c.svn-base
字号:
/***********************************************************//* PCI EEPRO100 definitions */typedef struct PCIEEPRO100State { PCIDevice dev; EEPRO100State eepro100;} PCIEEPRO100State;static void pci_map(PCIDevice * pci_dev, int region_num, uint32_t addr, uint32_t size, int type){ PCIEEPRO100State *d = (PCIEEPRO100State *) pci_dev; EEPRO100State *s = &d->eepro100; logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n", region_num, addr, size, type); assert(region_num == 1); register_ioport_write(addr, size, 1, ioport_write1, s); register_ioport_read(addr, size, 1, ioport_read1, s); register_ioport_write(addr, size, 2, ioport_write2, s); register_ioport_read(addr, size, 2, ioport_read2, s); register_ioport_write(addr, size, 4, ioport_write4, s); register_ioport_read(addr, size, 4, ioport_read4, s); s->region[region_num] = addr;}static void pci_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val){ EEPRO100State *s = opaque; addr -= s->region[0]; //~ logout("addr=%s val=0x%02x\n", regname(addr), val); eepro100_write1(s, addr, val);}static void pci_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val){ EEPRO100State *s = opaque; addr -= s->region[0]; //~ logout("addr=%s val=0x%02x\n", regname(addr), val); eepro100_write2(s, addr, val);}static void pci_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val){ EEPRO100State *s = opaque; addr -= s->region[0]; //~ logout("addr=%s val=0x%02x\n", regname(addr), val); eepro100_write4(s, addr, val);}static uint32_t pci_mmio_readb(void *opaque, target_phys_addr_t addr){ EEPRO100State *s = opaque; addr -= s->region[0]; //~ logout("addr=%s\n", regname(addr)); return eepro100_read1(s, addr);}static uint32_t pci_mmio_readw(void *opaque, target_phys_addr_t addr){ EEPRO100State *s = opaque; addr -= s->region[0]; //~ logout("addr=%s\n", regname(addr)); return eepro100_read2(s, addr);}static uint32_t pci_mmio_readl(void *opaque, target_phys_addr_t addr){ EEPRO100State *s = opaque; addr -= s->region[0]; //~ logout("addr=%s\n", regname(addr)); return eepro100_read4(s, addr);}static CPUWriteMemoryFunc *pci_mmio_write[] = { pci_mmio_writeb, pci_mmio_writew, pci_mmio_writel};static CPUReadMemoryFunc *pci_mmio_read[] = { pci_mmio_readb, pci_mmio_readw, pci_mmio_readl};static void pci_mmio_map(PCIDevice * pci_dev, int region_num, uint32_t addr, uint32_t size, int type){ PCIEEPRO100State *d = (PCIEEPRO100State *) pci_dev; logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n", region_num, addr, size, type); if (region_num == 0) { /* Map control / status registers. */ cpu_register_physical_memory(addr, size, d->eepro100.mmio_index); d->eepro100.region[region_num] = addr; }}static int nic_can_receive(void *opaque){ EEPRO100State *s = opaque; logout("%p\n", s); return get_ru_state(s) == ru_ready; //~ return !eepro100_buffer_full(s);}#define MIN_BUF_SIZE 60static void nic_receive(void *opaque, const uint8_t * buf, int size){ /* TODO: * - Magic packets should set bit 30 in power management driver register. * - Interesting packets should set bit 29 in power management driver register. */ EEPRO100State *s = opaque; uint16_t rfd_status = 0xa000; static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /* TODO: check multiple IA bit. */ assert(!(s->configuration[20] & BIT(6))); if (s->configuration[8] & 0x80) { /* CSMA is disabled. */ logout("%p received while CSMA is disabled\n", s); return; } else if (size < 64 && (s->configuration[7] & 1)) { /* Short frame and configuration byte 7/0 (discard short receive) set: * Short frame is discarded */ logout("%p received short frame (%d byte)\n", s, size); s->statistics.rx_short_frame_errors++; //~ return; } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & 8)) { /* Long frame and configuration byte 18/3 (long receive ok) not set: * Long frames are discarded. */ logout("%p received long frame (%d byte), ignored\n", s, size); return; } else if (memcmp(buf, s->macaddr, 6) == 0) { // !!! /* Frame matches individual address. */ /* TODO: check configuration byte 15/4 (ignore U/L). */ logout("%p received frame for me, len=%d\n", s, size); } else if (memcmp(buf, broadcast_macaddr, 6) == 0) { /* Broadcast frame. */ logout("%p received broadcast, len=%d\n", s, size); rfd_status |= 0x0002; } else if (buf[0] & 0x01) { // !!! /* Multicast frame. */ logout("%p received multicast, len=%d\n", s, size); /* TODO: check multicast all bit. */ assert(!(s->configuration[21] & BIT(3))); int mcast_idx = compute_mcast_idx(buf); if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) { return; } rfd_status |= 0x0002; } else if (s->configuration[15] & 1) { /* Promiscuous: receive all. */ logout("%p received frame in promiscuous mode, len=%d\n", s, size); rfd_status |= 0x0004; } else { logout("%p received frame, ignored, len=%d,%s\n", s, size, nic_dump(buf, size)); return; } if (get_ru_state(s) != ru_ready) { /* No ressources available. */ logout("no ressources, state=%u\n", get_ru_state(s)); s->statistics.rx_resource_errors++; //~ assert(!"no ressources"); return; } //~ !!!//~ $3 = {status = 0x0, command = 0xc000, link = 0x2d220, rx_buf_addr = 0x207dc, count = 0x0, size = 0x5f8, packet = {0x0 <repeats 1518 times>}} eepro100_rx_t rx; cpu_physical_memory_read(s->ru_base + s->ru_offset, (uint8_t *) & rx, offsetof(eepro100_rx_t, packet)); uint16_t rfd_command = le16_to_cpu(rx.command); uint16_t rfd_size = le16_to_cpu(rx.size); assert(size <= rfd_size); if (size < 64) { rfd_status |= 0x0080; } logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n", rfd_command, rx.link, rx.rx_buf_addr, rfd_size); stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status), rfd_status); stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size); /* Early receive interrupt not supported. */ //~ eepro100_er_interrupt(s); /* Receive CRC Transfer not supported. */ assert(!(s->configuration[18] & 4)); /* TODO: check stripping enable bit. */ //~ assert(!(s->configuration[17] & 1)); cpu_physical_memory_write(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, packet), buf, size); s->statistics.rx_good_frames++; eepro100_fr_interrupt(s); s->ru_offset = le32_to_cpu(rx.link); if (rfd_command & 0x8000) { /* EL bit is set, so this was the last frame. */ assert(0); } if (rfd_command & 0x4000) { /* S bit is set. */ set_ru_state(s, ru_suspended); }}static int nic_load(QEMUFile * f, void *opaque, int version_id){ EEPRO100State *s = (EEPRO100State *) opaque; int i; int ret; if (version_id > 3) return -EINVAL; if (s->pci_dev && version_id >= 3) { ret = pci_device_load(s->pci_dev, f); if (ret < 0) return ret; } if (version_id >= 2) { qemu_get_8s(f, &s->rxcr); } else { s->rxcr = 0x0c; } qemu_get_8s(f, &s->cmd); qemu_get_be32s(f, &s->start); qemu_get_be32s(f, &s->stop); qemu_get_8s(f, &s->boundary); qemu_get_8s(f, &s->tsr); qemu_get_8s(f, &s->tpsr); qemu_get_be16s(f, &s->tcnt); qemu_get_be16s(f, &s->rcnt); qemu_get_be32s(f, &s->rsar); qemu_get_8s(f, &s->rsr); qemu_get_8s(f, &s->isr); qemu_get_8s(f, &s->dcfg); qemu_get_8s(f, &s->imr); qemu_get_buffer(f, s->phys, 6); qemu_get_8s(f, &s->curpag); qemu_get_buffer(f, s->mult, 8); qemu_get_buffer(f, s->mem, sizeof(s->mem)); /* Restore all members of struct between scv_stat and mem */ qemu_get_8s(f, &s->scb_stat); qemu_get_8s(f, &s->int_stat); for (i = 0; i < 3; i++) qemu_get_be32s(f, &s->region[i]); qemu_get_buffer(f, s->macaddr, 6); for (i = 0; i < 19; i++) qemu_get_be32s(f, &s->statcounter[i]); for (i = 0; i < 32; i++) qemu_get_be16s(f, &s->mdimem[i]); /* The eeprom should be saved and restored by its own routines */ qemu_get_be32s(f, &s->device); qemu_get_be32s(f, &s->pointer); qemu_get_be32s(f, &s->cu_base); qemu_get_be32s(f, &s->cu_offset); qemu_get_be32s(f, &s->ru_base); qemu_get_be32s(f, &s->ru_offset); qemu_get_be32s(f, &s->statsaddr); /* Restore epro100_stats_t statistics */ qemu_get_be32s(f, &s->statistics.tx_good_frames); qemu_get_be32s(f, &s->statistics.tx_max_collisions); qemu_get_be32s(f, &s->statistics.tx_late_collisions); qemu_get_be32s(f, &s->statistics.tx_underruns); qemu_get_be32s(f, &s->statistics.tx_lost_crs); qemu_get_be32s(f, &s->statistics.tx_deferred); qemu_get_be32s(f, &s->statistics.tx_single_collisions); qemu_get_be32s(f, &s->statistics.tx_multiple_collisions); qemu_get_be32s(f, &s->statistics.tx_total_collisions); qemu_get_be32s(f, &s->statistics.rx_good_frames); qemu_get_be32s(f, &s->statistics.rx_crc_errors); qemu_get_be32s(f, &s->statistics.rx_alignment_errors); qemu_get_be32s(f, &s->statistics.rx_resource_errors); qemu_get_be32s(f, &s->statistics.rx_overrun_errors); qemu_get_be32s(f, &s->statistics.rx_cdt_errors); qemu_get_be32s(f, &s->statistics.rx_short_frame_errors); qemu_get_be32s(f, &s->statistics.fc_xmt_pause); qemu_get_be32s(f, &s->statistics.fc_rcv_pause); qemu_get_be32s(f, &s->statistics.fc_rcv_unsupported); qemu_get_be16s(f, &s->statistics.xmt_tco_frames); qemu_get_be16s(f, &s->statistics.rcv_tco_frames); qemu_get_be32s(f, &s->statistics.complete);#if 0 qemu_get_be16s(f, &s->status);#endif /* Configuration bytes. */ qemu_get_buffer(f, s->configuration, sizeof(s->configuration)); return 0;}static void nic_save(QEMUFile * f, void *opaque){ EEPRO100State *s = (EEPRO100State *) opaque; int i; if (s->pci_dev) pci_device_save(s->pci_dev, f); qemu_put_8s(f, &s->rxcr); qemu_put_8s(f, &s->cmd); qemu_put_be32s(f, &s->start); qemu_put_be32s(f, &s->stop); qemu_put_8s(f, &s->boundary); qemu_put_8s(f, &s->tsr); qemu_put_8s(f, &s->tpsr); qemu_put_be16s(f, &s->tcnt); qemu_put_be16s(f, &s->rcnt); qemu_put_be32s(f, &s->rsar); qemu_put_8s(f, &s->rsr); qemu_put_8s(f, &s->isr); qemu_put_8s(f, &s->dcfg); qemu_put_8s(f, &s->imr); qemu_put_buffer(f, s->phys, 6); qemu_put_8s(f, &s->curpag); qemu_put_buffer(f, s->mult, 8); qemu_put_buffer(f, s->mem, sizeof(s->mem)); /* Save all members of struct between scv_stat and mem */ qemu_put_8s(f, &s->scb_stat); qemu_put_8s(f, &s->int_stat); for (i = 0; i < 3; i++) qemu_put_be32s(f, &s->region[i]); qemu_put_buffer(f, s->macaddr, 6); for (i = 0; i < 19; i++) qemu_put_be32s(f, &s->statcounter[i]); for (i = 0; i < 32; i++) qemu_put_be16s(f, &s->mdimem[i]); /* The eeprom should be saved and restored by its own routines */ qemu_put_be32s(f, &s->device); qemu_put_be32s(f, &s->pointer); qemu_put_be32s(f, &s->cu_base); qemu_put_be32s(f, &s->cu_offset); qemu_put_be32s(f, &s->ru_base); qemu_put_be32s(f, &s->ru_offset); qemu_put_be32s(f, &s->statsaddr); /* Save epro100_stats_t statistics */ qemu_put_be32s(f, &s->statistics.tx_good_frames); qemu_put_be32s(f, &s->statistics.tx_max_collisions); qemu_put_be32s(f, &s->statistics.tx_late_collisions); qemu_put_be32s(f, &s->statistics.tx_underruns); qemu_put_be32s(f, &s->statistics.tx_lost_crs); qemu_put_be32s(f, &s->statistics.tx_deferred); qemu_put_be32s(f, &s->statistics.tx_single_collisions); qemu_put_be32s(f, &s->statistics.tx_multiple_collisions); qemu_put_be32s(f, &s->statistics.tx_total_collisions); qemu_put_be32s(f, &s->statistics.rx_good_frames); qemu_put_be32s(f, &s->statistics.rx_crc_errors); qemu_put_be32s(f, &s->statistics.rx_alignment_errors); qemu_put_be32s(f, &s->statistics.rx_resource_errors); qemu_put_be32s(f, &s->statistics.rx_overrun_errors); qemu_put_be32s(f, &s->statistics.rx_cdt_errors); qemu_put_be32s(f, &s->statistics.rx_short_frame_errors); qemu_put_be32s(f, &s->statistics.fc_xmt_pause); qemu_put_be32s(f, &s->statistics.fc_rcv_pause); qemu_put_be32s(f, &s->statistics.fc_rcv_unsupported); qemu_put_be16s(f, &s->statistics.xmt_tco_frames); qemu_put_be16s(f, &s->statistics.rcv_tco_frames); qemu_put_be32s(f, &s->statistics.complete);#if 0 qemu_put_be16s(f, &s->status);#endif /* Configuration bytes. */ qemu_put_buffer(f, s->configuration, sizeof(s->configuration));}static void nic_init(PCIBus * bus, NICInfo * nd, const char *name, uint32_t device){ PCIEEPRO100State *d; EEPRO100State *s; logout("\n"); d = (PCIEEPRO100State *) pci_register_device(bus, name, sizeof(PCIEEPRO100State), -1, NULL, NULL); s = &d->eepro100; s->device = device; s->pci_dev = &d->dev; pci_reset(s); /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM, * i82559 and later support 64 or 256 word EEPROM. */ s->eeprom = eeprom93xx_new(EEPROM_SIZE); /* Handler for memory-mapped I/O */ d->eepro100.mmio_index = cpu_register_io_memory(0, pci_mmio_read, pci_mmio_write, s); pci_register_io_region(&d->dev, 0, PCI_MEM_SIZE, PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_MEM_PREFETCH, pci_mmio_map); pci_register_io_region(&d->dev, 1, PCI_IO_SIZE, PCI_ADDRESS_SPACE_IO, pci_map); pci_register_io_region(&d->dev, 2, PCI_FLASH_SIZE, PCI_ADDRESS_SPACE_MEM, pci_mmio_map); memcpy(s->macaddr, nd->macaddr, 6); logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6)); assert(s->region[1] == 0); nic_reset(s); s->vc = qemu_new_vlan_client(nd->vlan, nic_receive, nic_can_receive, s); snprintf(s->vc->info_str, sizeof(s->vc->info_str), "eepro100 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x", s->macaddr[0], s->macaddr[1], s->macaddr[2], s->macaddr[3], s->macaddr[4], s->macaddr[5]); qemu_register_reset(nic_reset, s); /* XXX: instance number ? */ register_savevm(name, 0, 3, nic_save, nic_load, s);}void pci_i82551_init(PCIBus * bus, NICInfo * nd, int devfn){ nic_init(bus, nd, "i82551", i82551); //~ uint8_t *pci_conf = d->dev.config;}void pci_i82557b_init(PCIBus * bus, NICInfo * nd, int devfn){ nic_init(bus, nd, "i82557b", i82557B);}void pci_i82559er_init(PCIBus * bus, NICInfo * nd, int devfn){ nic_init(bus, nd, "i82559er", i82559ER);}/* eof */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -