+ if (pci_region_align(&pci_bios_prefmem_region,
+ PCI_PREF_MEMORY_ALIGN) == 0) {
+ pci_region_disable(&pci_bios_prefmem_region);
+ }
+
+ u32 io_base = pci_region_addr(&pci_bios_io_region);
+ u32 mem_base = pci_region_addr(&pci_bios_mem_region);
+ u32 prefmem_base = pci_region_addr(&pci_bios_prefmem_region);
+
+ u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
+ if (secbus > 0) {
+ pci_bios_init_device_in_bus(secbus);
+ }
+
+ u32 io_end = pci_region_align(&pci_bios_io_region, PCI_IO_ALIGN);
+ if (io_end == 0) {
+ pci_region_revert(&pci_bios_io_region, io_old);
+ io_base = 0xffff;
+ io_end = 1;
+ }
+ pci_config_writeb(bdf, PCI_IO_BASE, io_base >> PCI_IO_SHIFT);
+ pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
+ pci_config_writeb(bdf, PCI_IO_LIMIT, (io_end - 1) >> PCI_IO_SHIFT);
+ pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
+
+ u32 mem_end = pci_region_align(&pci_bios_mem_region, PCI_MEMORY_ALIGN);
+ if (mem_end == 0) {
+ pci_region_revert(&pci_bios_mem_region, mem_old);
+ mem_base = 0xffffffff;
+ mem_end = 1;
+ }
+ pci_config_writew(bdf, PCI_MEMORY_BASE, mem_base >> PCI_MEMORY_SHIFT);
+ pci_config_writew(bdf, PCI_MEMORY_LIMIT, (mem_end -1) >> PCI_MEMORY_SHIFT);
+
+ u32 prefmem_end = pci_region_align(&pci_bios_prefmem_region,
+ PCI_PREF_MEMORY_ALIGN);
+ if (prefmem_end == 0) {
+ pci_region_revert(&pci_bios_prefmem_region, prefmem_old);
+ prefmem_base = 0xffffffff;
+ prefmem_end = 1;
+ }
+ pci_config_writew(bdf, PCI_PREF_MEMORY_BASE,
+ prefmem_base >> PCI_PREF_MEMORY_SHIFT);
+ pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT,
+ (prefmem_end - 1) >> PCI_PREF_MEMORY_SHIFT);
+ pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, 0);
+ pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, 0);
+
+ dprintf(1, "PCI: br io = [0x%x, 0x%x)\n", io_base, io_end);
+ dprintf(1, "PCI: br mem = [0x%x, 0x%x)\n", mem_base, mem_end);
+ dprintf(1, "PCI: br pref = [0x%x, 0x%x)\n", prefmem_base, prefmem_end);
+
+ u16 cmd = pci_config_readw(bdf, PCI_COMMAND);
+ cmd &= ~PCI_COMMAND_IO;
+ if (io_end > io_base) {
+ cmd |= PCI_COMMAND_IO;
+ }
+ cmd &= ~PCI_COMMAND_MEMORY;
+ if (mem_end > mem_base || prefmem_end > prefmem_base) {
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ cmd |= PCI_COMMAND_MASTER;
+ pci_config_writew(bdf, PCI_COMMAND, cmd);
+
+ pci_config_maskw(bdf, PCI_BRIDGE_CONTROL, 0, PCI_BRIDGE_CTL_SERR);
+}
+
+static void storage_ide_init(struct pci_device *pci, void *arg)
+{
+ u16 bdf = pci->bdf;
+ /* IDE: we map it as in ISA mode */
+ pci_set_io_region_addr(bdf, 0, PORT_ATA1_CMD_BASE);
+ pci_set_io_region_addr(bdf, 1, PORT_ATA1_CTRL_BASE);
+ pci_set_io_region_addr(bdf, 2, PORT_ATA2_CMD_BASE);
+ pci_set_io_region_addr(bdf, 3, PORT_ATA2_CTRL_BASE);
+}
+
+/* PIIX3/PIIX4 IDE */
+static void piix_ide_init(struct pci_device *pci, void *arg)
+{
+ u16 bdf = pci->bdf;
+ pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
+ pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
+ pci_bios_allocate_regions(pci, NULL);
+}
+
+static void pic_ibm_init(struct pci_device *pci, void *arg)
+{
+ /* PIC, IBM, MPIC & MPIC2 */
+ pci_set_io_region_addr(pci->bdf, 0, 0x80800000 + 0x00040000);
+}
+
+static void apple_macio_init(struct pci_device *pci, void *arg)
+{
+ /* macio bridge */
+ pci_set_io_region_addr(pci->bdf, 0, 0x80800000);
+}
+
+static const struct pci_device_id pci_class_tbl[] = {
+ /* STORAGE IDE */
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1,
+ PCI_CLASS_STORAGE_IDE, piix_ide_init),
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
+ PCI_CLASS_STORAGE_IDE, piix_ide_init),
+ PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
+ storage_ide_init),
+
+ /* PIC, IBM, MIPC & MPIC2 */
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0x0046, PCI_CLASS_SYSTEM_PIC,
+ pic_ibm_init),
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0xFFFF, PCI_CLASS_SYSTEM_PIC,
+ pic_ibm_init),
+
+ /* 0xff00 */
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_init),
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_init),
+
+ /* PCI bridge */
+ PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_BRIDGE_PCI,
+ pci_bios_init_device_bridge),
+
+ /* default */
+ PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID, pci_bios_allocate_regions),
+
+ PCI_DEVICE_END,
+};
+
+/* PIIX4 Power Management device (for ACPI) */
+static void piix4_pm_init(struct pci_device *pci, void *arg)
+{
+ u16 bdf = pci->bdf;
+ // acpi sci is hardwired to 9
+ pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
+
+ pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
+ pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
+ pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
+ pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
+}
+
+static const struct pci_device_id pci_device_tbl[] = {
+ /* PIIX4 Power Management device (for ACPI) */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
+ piix4_pm_init),
+
+ PCI_DEVICE_END,
+};
+
+static void pci_bios_init_device(struct pci_device *pci)
+{
+ u16 bdf = pci->bdf;
+ int pin, pic_irq;
+
+ dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n"
+ , pci_bdf_to_bus(bdf), pci_bdf_to_devfn(bdf)
+ , pci->vendor, pci->device);
+ pci_init_device(pci_class_tbl, pci, NULL);
+
+ /* enable memory mappings */
+ pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);