📄 pci.c
字号:
register_ioport_write(0xcfc, 4, 1, pci_data_writeb, s); register_ioport_write(0xcfc, 4, 2, pci_data_writew, s); register_ioport_write(0xcfc, 4, 4, pci_data_writel, s); register_ioport_read(0xcfc, 4, 1, pci_data_readb, s); register_ioport_read(0xcfc, 4, 2, pci_data_readw, s); register_ioport_read(0xcfc, 4, 4, pci_data_readl, s); d = pci_register_device(s, "i440FX", sizeof(PCIDevice), 0, NULL, NULL); d->config[0x00] = 0x86; // vendor_id d->config[0x01] = 0x80; d->config[0x02] = 0x37; // device_id d->config[0x03] = 0x12; d->config[0x08] = 0x02; // revision d->config[0x0a] = 0x00; // class_sub = host2pci d->config[0x0b] = 0x06; // class_base = PCI_bridge d->config[0x0e] = 0x00; // header_type return s;}/* PIIX3 PCI to ISA bridge */typedef struct PIIX3State { PCIDevice dev;} PIIX3State;PIIX3State *piix3_state;/* return the global irq number corresponding to a given device irq pin. We could also use the bus number to have a more precise mapping. */static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num){ int slot_addend; slot_addend = (pci_dev->devfn >> 3) - 1; return (irq_num + slot_addend) & 3;}static inline int get_pci_irq_level(int irq_num){ int pic_level;#if (PCI_IRQ_WORDS == 2) pic_level = ((pci_irq_levels[irq_num][0] | pci_irq_levels[irq_num][1]) != 0);#else { int i; pic_level = 0; for(i = 0; i < PCI_IRQ_WORDS; i++) { if (pci_irq_levels[irq_num][i]) { pic_level = 1; break; } } }#endif return pic_level;}static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level){ int irq_index, shift, pic_irq, pic_level; uint32_t *p; irq_num = pci_slot_get_pirq(pci_dev, irq_num); irq_index = pci_dev->irq_index; p = &pci_irq_levels[irq_num][irq_index >> 5]; shift = (irq_index & 0x1f); *p = (*p & ~(1 << shift)) | (level << shift); /* now we change the pic irq level according to the piix irq mappings */ /* XXX: optimize */ pic_irq = piix3_state->dev.config[0x60 + irq_num]; if (pic_irq < 16) { /* the pic level is the logical OR of all the PCI irqs mapped to it */ pic_level = 0; if (pic_irq == piix3_state->dev.config[0x60]) pic_level |= get_pci_irq_level(0); if (pic_irq == piix3_state->dev.config[0x61]) pic_level |= get_pci_irq_level(1); if (pic_irq == piix3_state->dev.config[0x62]) pic_level |= get_pci_irq_level(2); if (pic_irq == piix3_state->dev.config[0x63]) pic_level |= get_pci_irq_level(3); pic_set_irq(pic_irq, pic_level); }}static void piix3_reset(PIIX3State *d){ uint8_t *pci_conf = d->dev.config; pci_conf[0x04] = 0x07; // master, memory and I/O pci_conf[0x05] = 0x00; pci_conf[0x06] = 0x00; pci_conf[0x07] = 0x02; // PCI_status_devsel_medium pci_conf[0x4c] = 0x4d; pci_conf[0x4e] = 0x03; pci_conf[0x4f] = 0x00; pci_conf[0x60] = 0x80; pci_conf[0x69] = 0x02; pci_conf[0x70] = 0x80; pci_conf[0x76] = 0x0c; pci_conf[0x77] = 0x0c; pci_conf[0x78] = 0x02; pci_conf[0x79] = 0x00; pci_conf[0x80] = 0x00; pci_conf[0x82] = 0x00; pci_conf[0xa0] = 0x08; pci_conf[0xa0] = 0x08; pci_conf[0xa2] = 0x00; pci_conf[0xa3] = 0x00; pci_conf[0xa4] = 0x00; pci_conf[0xa5] = 0x00; pci_conf[0xa6] = 0x00; pci_conf[0xa7] = 0x00; pci_conf[0xa8] = 0x0f; pci_conf[0xaa] = 0x00; pci_conf[0xab] = 0x00; pci_conf[0xac] = 0x00; pci_conf[0xae] = 0x00;}void piix3_init(PCIBus *bus){ PIIX3State *d; uint8_t *pci_conf; d = (PIIX3State *)pci_register_device(bus, "PIIX3", sizeof(PIIX3State), -1, NULL, NULL); register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d); piix3_state = d; pci_conf = d->dev.config; pci_conf[0x00] = 0x86; // Intel pci_conf[0x01] = 0x80; pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1) pci_conf[0x03] = 0x70; pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA pci_conf[0x0b] = 0x06; // class_base = PCI_bridge pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic piix3_reset(d);}/* PREP pci init */static inline void set_config(PCIBus *s, target_phys_addr_t addr){ int devfn, i; for(i = 0; i < 11; i++) { if ((addr & (1 << (11 + i))) != 0) break; } devfn = ((addr >> 8) & 7) | (i << 3); s->config_reg = 0x80000000 | (addr & 0xfc) | (devfn << 8);}static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t val){ PCIBus *s = opaque; set_config(s, addr); pci_data_write(s, addr, val, 1);}static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t val){ PCIBus *s = opaque; set_config(s, addr);#ifdef TARGET_WORDS_BIGENDIAN val = bswap16(val);#endif pci_data_write(s, addr, val, 2);}static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t val){ PCIBus *s = opaque; set_config(s, addr);#ifdef TARGET_WORDS_BIGENDIAN val = bswap32(val);#endif pci_data_write(s, addr, val, 4);}static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr){ PCIBus *s = opaque; uint32_t val; set_config(s, addr); val = pci_data_read(s, addr, 1); return val;}static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr){ PCIBus *s = opaque; uint32_t val; set_config(s, addr); val = pci_data_read(s, addr, 2);#ifdef TARGET_WORDS_BIGENDIAN val = bswap16(val);#endif return val;}static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr){ PCIBus *s = opaque; uint32_t val; set_config(s, addr); val = pci_data_read(s, addr, 4);#ifdef TARGET_WORDS_BIGENDIAN val = bswap32(val);#endif return val;}static CPUWriteMemoryFunc *PPC_PCIIO_write[] = { &PPC_PCIIO_writeb, &PPC_PCIIO_writew, &PPC_PCIIO_writel,};static CPUReadMemoryFunc *PPC_PCIIO_read[] = { &PPC_PCIIO_readb, &PPC_PCIIO_readw, &PPC_PCIIO_readl,};static void prep_set_irq(PCIDevice *d, int irq_num, int level){ /* XXX: we do not simulate the hardware - we rely on the BIOS to set correctly for irq line field */ pic_set_irq(d->config[PCI_INTERRUPT_LINE], level);}PCIBus *pci_prep_init(void){ PCIBus *s; PCIDevice *d; int PPC_io_memory; s = pci_register_bus(); s->set_irq = prep_set_irq; register_ioport_write(0xcf8, 4, 4, pci_addr_writel, s); register_ioport_read(0xcf8, 4, 4, pci_addr_readl, s); register_ioport_write(0xcfc, 4, 1, pci_data_writeb, s); register_ioport_write(0xcfc, 4, 2, pci_data_writew, s); register_ioport_write(0xcfc, 4, 4, pci_data_writel, s); register_ioport_read(0xcfc, 4, 1, pci_data_readb, s); register_ioport_read(0xcfc, 4, 2, pci_data_readw, s); register_ioport_read(0xcfc, 4, 4, pci_data_readl, s); PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read, PPC_PCIIO_write, s); cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory); /* PCI host bridge */ d = pci_register_device(s, "PREP Host Bridge - Motorola Raven", sizeof(PCIDevice), 0, NULL, NULL); d->config[0x00] = 0x57; // vendor_id : Motorola d->config[0x01] = 0x10; d->config[0x02] = 0x01; // device_id : Raven d->config[0x03] = 0x48; d->config[0x08] = 0x00; // revision d->config[0x0A] = 0x00; // class_sub = pci host d->config[0x0B] = 0x06; // class_base = PCI_bridge d->config[0x0C] = 0x08; // cache_line_size d->config[0x0D] = 0x10; // latency_timer d->config[0x0E] = 0x00; // header_type d->config[0x34] = 0x00; // capabilities_pointer return s;}/* Grackle PCI host */static void pci_grackle_config_writel (void *opaque, target_phys_addr_t addr, uint32_t val){ PCIBus *s = opaque;#ifdef TARGET_WORDS_BIGENDIAN val = bswap32(val);#endif s->config_reg = val;}static uint32_t pci_grackle_config_readl (void *opaque, target_phys_addr_t addr){ PCIBus *s = opaque; uint32_t val; val = s->config_reg;#ifdef TARGET_WORDS_BIGENDIAN val = bswap32(val);#endif return val;}static CPUWriteMemoryFunc *pci_grackle_config_write[] = { &pci_grackle_config_writel, &pci_grackle_config_writel, &pci_grackle_config_writel,};static CPUReadMemoryFunc *pci_grackle_config_read[] = { &pci_grackle_config_readl, &pci_grackle_config_readl, &pci_grackle_config_readl,};static void pci_grackle_writeb (void *opaque, target_phys_addr_t addr, uint32_t val){ PCIBus *s = opaque; pci_data_write(s, addr, val, 1);}static void pci_grackle_writew (void *opaque, target_phys_addr_t addr, uint32_t val){ PCIBus *s = opaque;#ifdef TARGET_WORDS_BIGENDIAN val = bswap16(val);#endif pci_data_write(s, addr, val, 2);}static void pci_grackle_writel (void *opaque, target_phys_addr_t addr, uint32_t val){ PCIBus *s = opaque;#ifdef TARGET_WORDS_BIGENDIAN val = bswap32(val);#endif pci_data_write(s, addr, val, 4);}static uint32_t pci_grackle_readb (void *opaque, target_phys_addr_t addr){ PCIBus *s = opaque; uint32_t val; val = pci_data_read(s, addr, 1); return val;}static uint32_t pci_grackle_readw (void *opaque, target_phys_addr_t addr){ PCIBus *s = opaque; uint32_t val; val = pci_data_read(s, addr, 2);#ifdef TARGET_WORDS_BIGENDIAN val = bswap16(val);#endif return val;}static uint32_t pci_grackle_readl (void *opaque, target_phys_addr_t addr){ PCIBus *s = opaque; uint32_t val; val = pci_data_read(s, addr, 4);#ifdef TARGET_WORDS_BIGENDIAN val = bswap32(val);#endif return val;}static CPUWriteMemoryFunc *pci_grackle_write[] = { &pci_grackle_writeb, &pci_grackle_writew, &pci_grackle_writel,};static CPUReadMemoryFunc *pci_grackle_read[] = { &pci_grackle_readb, &pci_grackle_readw, &pci_grackle_readl,};void pci_set_pic(PCIBus *bus, SetIRQFunc *set_irq, void *irq_opaque){ bus->low_set_irq = set_irq; bus->irq_opaque = irq_opaque;}/* XXX: we do not simulate the hardware - we rely on the BIOS to set correctly for irq line field */static void pci_set_irq_simple(PCIDevice *d, int irq_num, int level){ PCIBus *s = d->bus; s->low_set_irq(s->irq_opaque, d->config[PCI_INTERRUPT_LINE], level);}PCIBus *pci_grackle_init(uint32_t base){ PCIBus *s; PCIDevice *d; int pci_mem_config, pci_mem_data; s = pci_register_bus(); s->set_irq = pci_set_irq_simple; pci_mem_config = cpu_register_io_memory(0, pci_grackle_config_read, pci_grackle_config_write, s); pci_mem_data = cpu_register_io_memory(0, pci_grackle_read, pci_grackle_write, s); cpu_register_physical_memory(base, 0x1000, pci_mem_config); cpu_register_physical_memory(base + 0x00200000, 0x1000, pci_mem_data); d = pci_register_device(s, "Grackle host bridge", sizeof(PCIDevice), 0, NULL, NULL); d->config[0x00] = 0x57; // vendor_id d->config[0x01] = 0x10; d->config[0x02] = 0x02; // device_id d->config[0x03] = 0x00; d->config[0x08] = 0x00; // revision d->config[0x09] = 0x01; d->config[0x0a] = 0x00; // class_sub = host d->config[0x0b] = 0x06; // class_base = PCI_bridge d->config[0x0e] = 0x00; // header_type d->config[0x18] = 0x00; // primary_bus d->config[0x19] = 0x01; // secondary_bus d->config[0x1a] = 0x00; // subordinate_bus d->config[0x1c] = 0x00; d->config[0x1d] = 0x00; d->config[0x20] = 0x00; // memory_base d->config[0x21] = 0x00; d->config[0x22] = 0x01; // memory_limit d->config[0x23] = 0x00; d->config[0x24] = 0x00; // prefetchable_memory_base d->config[0x25] = 0x00; d->config[0x26] = 0x00; // prefetchable_memory_limit d->config[0x27] = 0x00;#if 0 /* PCI2PCI bridge same values as PearPC - check this */ d->config[0x00] = 0x11; // vendor_id d->config[0x01] = 0x10; d->config[0x02] = 0x26; // device_id d->config[0x03] = 0x00; d->config[0x08] = 0x02; // revision d->config[0x0a] = 0x04; // class_sub = pci2pci d->config[0x0b] = 0x06; // class_base = PCI_bridge d->config[0x0e] = 0x01; // header_type d->config[0x18] = 0x0; // primary_bus d->config[0x19] = 0x1; // secondary_bus d->config[0x1a] = 0x1; // subordinate_bus d->config[0x1c] = 0x10; // io_base d->config[0x1d] = 0x20; // io_limit d->config[0x20] = 0x80; // memory_base
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -