📄 e1000.c
字号:
static voidset_icr(E1000State *s, int index, uint32_t val){ DBGOUT(INTERRUPT, "set_icr %x\n", val); set_interrupt_cause(s, 0, s->mac_reg[ICR] & ~val);}static voidset_imc(E1000State *s, int index, uint32_t val){ s->mac_reg[IMS] &= ~val; set_ics(s, 0, 0);}static voidset_ims(E1000State *s, int index, uint32_t val){ s->mac_reg[IMS] |= val; set_ics(s, 0, 0);}#define getreg(x) [x] = mac_readregstatic uint32_t (*macreg_readops[])(E1000State *, int) = { getreg(PBA), getreg(RCTL), getreg(TDH), getreg(TXDCTL), getreg(WUFC), getreg(TDT), getreg(CTRL), getreg(LEDCTL), getreg(MANC), getreg(MDIC), getreg(SWSM), getreg(STATUS), getreg(TORL), getreg(TOTL), getreg(IMS), getreg(TCTL), getreg(RDH), getreg(RDT), [TOTH] = mac_read_clr8, [TORH] = mac_read_clr8, [GPRC] = mac_read_clr4, [GPTC] = mac_read_clr4, [TPR] = mac_read_clr4, [TPT] = mac_read_clr4, [ICR] = mac_icr_read, [EECD] = get_eecd, [EERD] = flash_eerd_read, [CRCERRS ... MPC] = &mac_readreg, [RA ... RA+31] = &mac_readreg, [MTA ... MTA+127] = &mac_readreg,};enum { NREADOPS = sizeof(macreg_readops) / sizeof(*macreg_readops) };#define putreg(x) [x] = mac_writeregstatic void (*macreg_writeops[])(E1000State *, int, uint32_t) = { putreg(PBA), putreg(EERD), putreg(SWSM), putreg(WUFC), putreg(TDBAL), putreg(TDBAH), putreg(TXDCTL), putreg(RDBAH), putreg(RDBAL), putreg(LEDCTL), [TDLEN] = set_dlen, [RDLEN] = set_dlen, [TCTL] = set_tctl, [TDT] = set_tctl, [MDIC] = set_mdic, [ICS] = set_ics, [TDH] = set_16bit, [RDH] = set_16bit, [RDT] = set_rdt, [IMC] = set_imc, [IMS] = set_ims, [ICR] = set_icr, [EECD] = set_eecd, [RCTL] = set_rx_control, [RA ... RA+31] = &mac_writereg, [MTA ... MTA+127] = &mac_writereg,};enum { NWRITEOPS = sizeof(macreg_writeops) / sizeof(*macreg_writeops) };static voide1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val){ E1000State *s = opaque; unsigned int index = ((addr - s->mmio_base) & 0x1ffff) >> 2; if (index < NWRITEOPS && macreg_writeops[index]) macreg_writeops[index](s, index, le32_to_cpu(val)); else if (index < NREADOPS && macreg_readops[index]) DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04x\n", index<<2, val); else DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08x\n", index<<2, val);}static voide1000_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val){ // emulate hw without byte enables: no RMW e1000_mmio_writel(opaque, addr & ~3, cpu_to_le32(le16_to_cpu(val & 0xffff) << (8*(addr & 3))));}static voide1000_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val){ // emulate hw without byte enables: no RMW e1000_mmio_writel(opaque, addr & ~3, cpu_to_le32((val & 0xff) << (8*(addr & 3))));}static uint32_te1000_mmio_readl(void *opaque, target_phys_addr_t addr){ E1000State *s = opaque; unsigned int index = ((addr - s->mmio_base) & 0x1ffff) >> 2; if (index < NREADOPS && macreg_readops[index]) return cpu_to_le32(macreg_readops[index](s, index)); DBGOUT(UNKNOWN, "MMIO unknown read addr=0x%08x\n", index<<2); return 0;}static uint32_te1000_mmio_readb(void *opaque, target_phys_addr_t addr){ return (le32_to_cpu(e1000_mmio_readl(opaque, addr & ~3)) >> (8 * (addr & 3))) & 0xff;}static uint32_te1000_mmio_readw(void *opaque, target_phys_addr_t addr){ return cpu_to_le16((le32_to_cpu(e1000_mmio_readl(opaque, addr & ~3)) >> (8 * (addr & 3))) & 0xffff);}int mac_regtosave[] = { CTRL, EECD, EERD, GPRC, GPTC, ICR, ICS, IMC, IMS, LEDCTL, MANC, MDIC, MPC, PBA, RCTL, RDBAH, RDBAL, RDH, RDLEN, RDT, STATUS, SWSM, TCTL, TDBAH, TDBAL, TDH, TDLEN, TDT, TORH, TORL, TOTH, TOTL, TPR, TPT, TXDCTL, WUFC,};enum { MAC_NSAVE = sizeof mac_regtosave/sizeof *mac_regtosave };struct { int size; int array0;} mac_regarraystosave[] = { {32, RA}, {128, MTA} };enum { MAC_NARRAYS = sizeof mac_regarraystosave/sizeof *mac_regarraystosave };static voidnic_save(QEMUFile *f, void *opaque){ E1000State *s = (E1000State *)opaque; int i, j; pci_device_save(&s->dev, f); qemu_put_be32s(f, &s->instance); qemu_put_be32s(f, &s->mmio_base); qemu_put_be32s(f, &s->rxbuf_size); qemu_put_be32s(f, &s->rxbuf_min_shift); qemu_put_be32s(f, &s->eecd_state.val_in); qemu_put_be16s(f, &s->eecd_state.bitnum_in); qemu_put_be16s(f, &s->eecd_state.bitnum_out); qemu_put_be16s(f, &s->eecd_state.reading); qemu_put_be32s(f, &s->eecd_state.old_eecd); qemu_put_8s(f, &s->tx.ipcss); qemu_put_8s(f, &s->tx.ipcso); qemu_put_be16s(f, &s->tx.ipcse); qemu_put_8s(f, &s->tx.tucss); qemu_put_8s(f, &s->tx.tucso); qemu_put_be16s(f, &s->tx.tucse); qemu_put_be32s(f, &s->tx.paylen); qemu_put_8s(f, &s->tx.hdr_len); qemu_put_be16s(f, &s->tx.mss); qemu_put_be16s(f, &s->tx.size); qemu_put_be16s(f, &s->tx.tso_frames); qemu_put_8s(f, &s->tx.sum_needed); qemu_put_8s(f, &s->tx.ip); qemu_put_8s(f, &s->tx.tcp); qemu_put_buffer(f, s->tx.header, sizeof s->tx.header); qemu_put_buffer(f, s->tx.data, sizeof s->tx.data); for (i = 0; i < 64; i++) qemu_put_be16s(f, s->eeprom_data + i); for (i = 0; i < 0x20; i++) qemu_put_be16s(f, s->phy_reg + i); for (i = 0; i < MAC_NSAVE; i++) qemu_put_be32s(f, s->mac_reg + mac_regtosave[i]); for (i = 0; i < MAC_NARRAYS; i++) for (j = 0; j < mac_regarraystosave[i].size; j++) qemu_put_be32s(f, s->mac_reg + mac_regarraystosave[i].array0 + j);}static intnic_load(QEMUFile *f, void *opaque, int version_id){ E1000State *s = (E1000State *)opaque; int i, j, ret; if ((ret = pci_device_load(&s->dev, f)) < 0) return ret; qemu_get_be32s(f, &s->instance); qemu_get_be32s(f, &s->mmio_base); qemu_get_be32s(f, &s->rxbuf_size); qemu_get_be32s(f, &s->rxbuf_min_shift); qemu_get_be32s(f, &s->eecd_state.val_in); qemu_get_be16s(f, &s->eecd_state.bitnum_in); qemu_get_be16s(f, &s->eecd_state.bitnum_out); qemu_get_be16s(f, &s->eecd_state.reading); qemu_get_be32s(f, &s->eecd_state.old_eecd); qemu_get_8s(f, &s->tx.ipcss); qemu_get_8s(f, &s->tx.ipcso); qemu_get_be16s(f, &s->tx.ipcse); qemu_get_8s(f, &s->tx.tucss); qemu_get_8s(f, &s->tx.tucso); qemu_get_be16s(f, &s->tx.tucse); qemu_get_be32s(f, &s->tx.paylen); qemu_get_8s(f, &s->tx.hdr_len); qemu_get_be16s(f, &s->tx.mss); qemu_get_be16s(f, &s->tx.size); qemu_get_be16s(f, &s->tx.tso_frames); qemu_get_8s(f, &s->tx.sum_needed); qemu_get_8s(f, &s->tx.ip); qemu_get_8s(f, &s->tx.tcp); qemu_get_buffer(f, s->tx.header, sizeof s->tx.header); qemu_get_buffer(f, s->tx.data, sizeof s->tx.data); for (i = 0; i < 64; i++) qemu_get_be16s(f, s->eeprom_data + i); for (i = 0; i < 0x20; i++) qemu_get_be16s(f, s->phy_reg + i); for (i = 0; i < MAC_NSAVE; i++) qemu_get_be32s(f, s->mac_reg + mac_regtosave[i]); for (i = 0; i < MAC_NARRAYS; i++) for (j = 0; j < mac_regarraystosave[i].size; j++) qemu_get_be32s(f, s->mac_reg + mac_regarraystosave[i].array0 + j); return 0;}static uint16_t e1000_eeprom_template[64] = { 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040, 0x0008, 0x2000, 0x7e14, 0x0048, 0x1000, 0x00d8, 0x0000, 0x2700, 0x6cc9, 0x3150, 0x0722, 0x040b, 0x0984, 0x0000, 0xc000, 0x0706, 0x1008, 0x0000, 0x0f04, 0x7fff, 0x4d01, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0100, 0x4000, 0x121c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000,};static uint16_t phy_reg_init[] = { [PHY_CTRL] = 0x1140, [PHY_STATUS] = 0x796d, // link initially up [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT, [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360, [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1, [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00,};static uint32_t mac_reg_init[] = { [PBA] = 0x00100030, [LEDCTL] = 0x602, [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 | E1000_CTRL_SPD_1000 | E1000_CTRL_SLU, [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE | E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK | E1000_STATUS_SPEED_1000 | E1000_STATUS_FD | E1000_STATUS_LU, [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN | E1000_MANC_ARP_EN | E1000_MANC_0298_EN | E1000_MANC_RMCP_EN,};/* PCI interface */static CPUWriteMemoryFunc *e1000_mmio_write[] = { e1000_mmio_writeb, e1000_mmio_writew, e1000_mmio_writel};static CPUReadMemoryFunc *e1000_mmio_read[] = { e1000_mmio_readb, e1000_mmio_readw, e1000_mmio_readl};static voide1000_mmio_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type){ E1000State *d = (E1000State *)pci_dev; DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size); d->mmio_base = addr; cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);}voidpci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn){ E1000State *d; uint8_t *pci_conf; static int instance; uint16_t checksum = 0; char *info_str = "e1000"; int i; d = (E1000State *)pci_register_device(bus, "e1000", sizeof(E1000State), devfn, NULL, NULL); pci_conf = d->dev.config; memset(pci_conf, 0, 256); *(uint16_t *)(pci_conf+0x00) = cpu_to_le16(0x8086); *(uint16_t *)(pci_conf+0x02) = cpu_to_le16(E1000_DEVID); *(uint16_t *)(pci_conf+0x04) = cpu_to_le16(0x0407); *(uint16_t *)(pci_conf+0x06) = cpu_to_le16(0x0010); pci_conf[0x08] = 0x03; pci_conf[0x0a] = 0x00; // ethernet network controller pci_conf[0x0b] = 0x02; pci_conf[0x0c] = 0x10; pci_conf[0x3d] = 1; // interrupt pin 0 d->mmio_index = cpu_register_io_memory(0, e1000_mmio_read, e1000_mmio_write, d); pci_register_io_region((PCIDevice *)d, 0, PNPMMIO_SIZE, PCI_ADDRESS_SPACE_MEM, e1000_mmio_map); pci_register_io_region((PCIDevice *)d, 1, IOPORT_SIZE, PCI_ADDRESS_SPACE_IO, ioport_map); d->instance = instance++; d->nd = nd; memmove(d->eeprom_data, e1000_eeprom_template, sizeof e1000_eeprom_template); for (i = 0; i < 3; i++) d->eeprom_data[i] = (nd->macaddr[2*i+1]<<8) | nd->macaddr[2*i]; for (i = 0; i < EEPROM_CHECKSUM_REG; i++) checksum += d->eeprom_data[i]; checksum = (uint16_t) EEPROM_SUM - checksum; d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum; memset(d->phy_reg, 0, sizeof d->phy_reg); memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init); memset(d->mac_reg, 0, sizeof d->mac_reg); memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init); d->rxbuf_min_shift = 1; memset(&d->tx, 0, sizeof d->tx); d->vc = qemu_new_vlan_client(nd->vlan, e1000_receive, e1000_can_receive, d); snprintf(d->vc->info_str, sizeof(d->vc->info_str), "%s macaddr=%02x:%02x:%02x:%02x:%02x:%02x", info_str, d->nd->macaddr[0], d->nd->macaddr[1], d->nd->macaddr[2], d->nd->macaddr[3], d->nd->macaddr[4], d->nd->macaddr[5]); register_savevm(info_str, d->instance, 1, nic_save, nic_load, d);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -