⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne2000.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
        case EN1_MULT ... EN1_MULT + 7:            s->mult[offset - EN1_MULT] = val;            break;        }    }}static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr){    NE2000State *s = opaque;    int offset, page, ret;    addr &= 0xf;    if (addr == E8390_CMD) {        ret = s->cmd;    } else {        page = s->cmd >> 6;        offset = addr | (page << 4);        switch(offset) {        case EN0_TSR:            ret = s->tsr;            break;        case EN0_BOUNDARY:            ret = s->boundary;            break;        case EN0_ISR:            ret = s->isr;            break;	case EN0_RSARLO:	    ret = s->rsar & 0x00ff;	    break;	case EN0_RSARHI:	    ret = s->rsar >> 8;	    break;        case EN1_PHYS ... EN1_PHYS + 5:            ret = s->phys[offset - EN1_PHYS];            break;        case EN1_CURPAG:            ret = s->curpag;            break;        case EN1_MULT ... EN1_MULT + 7:            ret = s->mult[offset - EN1_MULT];            break;        case EN0_RSR:            ret = s->rsr;            break;        case EN2_STARTPG:            ret = s->start >> 8;            break;        case EN2_STOPPG:            ret = s->stop >> 8;            break;	case EN0_RTL8029ID0:	    ret = 0x50;	    break;	case EN0_RTL8029ID1:	    ret = 0x43;	    break;	case EN3_CONFIG0:	    ret = 0;		/* 10baseT media */	    break;	case EN3_CONFIG2:	    ret = 0x40;		/* 10baseT active */	    break;	case EN3_CONFIG3:	    ret = 0x40;		/* Full duplex */	    break;        default:            ret = 0x00;            break;        }    }#ifdef DEBUG_NE2000    printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);#endif    return ret;}static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr,                                      uint32_t val){    if (addr < 32 ||         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {        s->mem[addr] = val;    }}static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr,                                      uint32_t val){    addr &= ~1; /* XXX: check exact behaviour if not even */    if (addr < 32 ||         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {        *(uint16_t *)(s->mem + addr) = cpu_to_le16(val);    }}static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr,                                      uint32_t val){    addr &= ~1; /* XXX: check exact behaviour if not even */    if (addr < 32 ||         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {        cpu_to_le32wu((uint32_t *)(s->mem + addr), val);    }}static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr){    if (addr < 32 ||         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {        return s->mem[addr];    } else {        return 0xff;    }}static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr){    addr &= ~1; /* XXX: check exact behaviour if not even */    if (addr < 32 ||         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {        return le16_to_cpu(*(uint16_t *)(s->mem + addr));    } else {        return 0xffff;    }}static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr){    addr &= ~1; /* XXX: check exact behaviour if not even */    if (addr < 32 ||         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {        return le32_to_cpupu((uint32_t *)(s->mem + addr));    } else {        return 0xffffffff;    }}static inline void ne2000_dma_update(NE2000State *s, int len){    s->rsar += len;    /* wrap */    /* XXX: check what to do if rsar > stop */    if (s->rsar == s->stop)        s->rsar = s->start;    if (s->rcnt <= len) {        s->rcnt = 0;        /* signal end of transfert */        s->isr |= ENISR_RDC;        ne2000_update_irq(s);    } else {        s->rcnt -= len;    }}static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val){    NE2000State *s = opaque;#ifdef DEBUG_NE2000    printf("NE2000: asic write val=0x%04x\n", val);#endif    if (s->rcnt == 0)        return;    if (s->dcfg & 0x01) {        /* 16 bit access */        ne2000_mem_writew(s, s->rsar, val);        ne2000_dma_update(s, 2);    } else {        /* 8 bit access */        ne2000_mem_writeb(s, s->rsar, val);        ne2000_dma_update(s, 1);    }}static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr){    NE2000State *s = opaque;    int ret;    if (s->dcfg & 0x01) {        /* 16 bit access */        ret = ne2000_mem_readw(s, s->rsar);        ne2000_dma_update(s, 2);    } else {        /* 8 bit access */        ret = ne2000_mem_readb(s, s->rsar);        ne2000_dma_update(s, 1);    }#ifdef DEBUG_NE2000    printf("NE2000: asic read val=0x%04x\n", ret);#endif    return ret;}static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val){    NE2000State *s = opaque;#ifdef DEBUG_NE2000    printf("NE2000: asic writel val=0x%04x\n", val);#endif    if (s->rcnt == 0)        return;    /* 32 bit access */    ne2000_mem_writel(s, s->rsar, val);    ne2000_dma_update(s, 4);}static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr){    NE2000State *s = opaque;    int ret;    /* 32 bit access */    ret = ne2000_mem_readl(s, s->rsar);    ne2000_dma_update(s, 4);#ifdef DEBUG_NE2000    printf("NE2000: asic readl val=0x%04x\n", ret);#endif    return ret;}static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val){    /* nothing to do (end of reset pulse) */}static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr){    NE2000State *s = opaque;    ne2000_reset(s);    return 0;}static void ne2000_save(QEMUFile* f,void* opaque){	NE2000State* s=(NE2000State*)opaque;        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_be32s(f, &s->irq);	qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE);}static int ne2000_load(QEMUFile* f,void* opaque,int version_id){	NE2000State* s=(NE2000State*)opaque;        if (version_id == 2) {            qemu_get_8s(f, &s->rxcr);        } else if (version_id == 1) {            s->rxcr = 0x0c;        } else {            return -EINVAL;        }	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_be32s(f, &s->irq);	qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE);	return 0;}void isa_ne2000_init(int base, int irq, NICInfo *nd){    NE2000State *s;        s = qemu_mallocz(sizeof(NE2000State));    if (!s)        return;        register_ioport_write(base, 16, 1, ne2000_ioport_write, s);    register_ioport_read(base, 16, 1, ne2000_ioport_read, s);    register_ioport_write(base + 0x10, 1, 1, ne2000_asic_ioport_write, s);    register_ioport_read(base + 0x10, 1, 1, ne2000_asic_ioport_read, s);    register_ioport_write(base + 0x10, 2, 2, ne2000_asic_ioport_write, s);    register_ioport_read(base + 0x10, 2, 2, ne2000_asic_ioport_read, s);    register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s);    register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);    s->irq = irq;    memcpy(s->macaddr, nd->macaddr, 6);    ne2000_reset(s);    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,                                 ne2000_can_receive, s);    snprintf(s->vc->info_str, sizeof(s->vc->info_str),             "ne2000 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]);                 register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);}/***********************************************************//* PCI NE2000 definitions */typedef struct PCINE2000State {    PCIDevice dev;    NE2000State ne2000;} PCINE2000State;static void ne2000_map(PCIDevice *pci_dev, int region_num,                        uint32_t addr, uint32_t size, int type){    PCINE2000State *d = (PCINE2000State *)pci_dev;    NE2000State *s = &d->ne2000;    register_ioport_write(addr, 16, 1, ne2000_ioport_write, s);    register_ioport_read(addr, 16, 1, ne2000_ioport_read, s);    register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s);    register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s);    register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s);    register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s);    register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s);    register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s);    register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s);    register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);}void pci_ne2000_init(PCIBus *bus, NICInfo *nd){    PCINE2000State *d;    NE2000State *s;    uint8_t *pci_conf;        d = (PCINE2000State *)pci_register_device(bus,                                              "NE2000", sizeof(PCINE2000State),                                              -1,                                               NULL, NULL);    pci_conf = d->dev.config;    pci_conf[0x00] = 0xec; // Realtek 8029    pci_conf[0x01] = 0x10;    pci_conf[0x02] = 0x29;    pci_conf[0x03] = 0x80;    pci_conf[0x0a] = 0x00; // ethernet network controller     pci_conf[0x0b] = 0x02;    pci_conf[0x0e] = 0x00; // header_type    pci_conf[0x3d] = 1; // interrupt pin 0        pci_register_io_region(&d->dev, 0, 0x100,                            PCI_ADDRESS_SPACE_IO, ne2000_map);    s = &d->ne2000;    s->irq = 16; // PCI interrupt    s->pci_dev = (PCIDevice *)d;    memcpy(s->macaddr, nd->macaddr, 6);    ne2000_reset(s);    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,                                 ne2000_can_receive, s);    snprintf(s->vc->info_str, sizeof(s->vc->info_str),             "ne2000 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]);                 /* XXX: instance number ? */    register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);    register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load,                     &d->dev);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -