blob: a406bbd7ff05f2b56fedb1caf5d972f50347787e [file] [log] [blame]
Kevin O'Connor0525d292008-07-04 06:18:30 -04001// Initialize PCI devices (on emulators)
2//
3// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4// Copyright (C) 2006 Fabrice Bellard
5//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05006// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connor0525d292008-07-04 06:18:30 -04007
8#include "util.h" // dprintf
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -05009#include "pci.h" // pci_config_readl
Kevin O'Connor2ed2f582008-11-08 15:53:36 -050010#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
11#include "pci_regs.h" // PCI_COMMAND
Kevin O'Connor4bc49972012-05-13 22:58:08 -040012#include "ioport.h" // PORT_ATA1_CMD_BASE
13#include "config.h" // CONFIG_*
Ian Campbell74c78782011-06-01 11:00:29 +010014#include "xen.h" // usingXen
Isaku Yamahata72a590e2012-11-28 10:17:33 +010015#include "memmap.h" // add_e820
16#include "dev-q35.h"
17
18/* PM Timer ticks per second (HZ) */
19#define PM_TIMER_FREQUENCY 3579545
Kevin O'Connor0525d292008-07-04 06:18:30 -040020
Alexey Korolev5fa24b52012-04-18 17:31:58 +120021#define PCI_DEVICE_MEM_MIN 0x1000
Gerd Hoffmann82b39b22011-07-11 09:20:28 +020022#define PCI_BRIDGE_IO_MIN 0x1000
23#define PCI_BRIDGE_MEM_MIN 0x100000
Isaku Yamahataaf0963d2010-06-22 17:57:53 +090024
Gerd Hoffmann82b39b22011-07-11 09:20:28 +020025enum pci_region_type {
26 PCI_REGION_TYPE_IO,
27 PCI_REGION_TYPE_MEM,
28 PCI_REGION_TYPE_PREFMEM,
29 PCI_REGION_TYPE_COUNT,
30};
31
32static const char *region_type_name[] = {
33 [ PCI_REGION_TYPE_IO ] = "io",
34 [ PCI_REGION_TYPE_MEM ] = "mem",
35 [ PCI_REGION_TYPE_PREFMEM ] = "prefmem",
36};
37
Gerd Hoffmanne55c4e82012-06-07 10:34:32 +020038u64 pcimem_start = BUILD_PCIMEM_START;
39u64 pcimem_end = BUILD_PCIMEM_END;
40u64 pcimem64_start = BUILD_PCIMEM64_START;
41u64 pcimem64_end = BUILD_PCIMEM64_END;
42
Alexey Korolevfa51bcd2012-04-18 17:21:19 +120043struct pci_region_entry {
44 struct pci_device *dev;
45 int bar;
Alexey Korolev030288f2012-04-19 17:44:55 +120046 u64 size;
47 u64 align;
Alexey Korolevfa51bcd2012-04-18 17:21:19 +120048 int is64;
49 enum pci_region_type type;
50 struct pci_region_entry *next;
51};
52
Alexey Korolev35a770f2012-04-19 17:47:19 +120053struct pci_region {
Alexey Korolev35a770f2012-04-19 17:47:19 +120054 /* pci region assignments */
55 u64 base;
56 struct pci_region_entry *list;
57};
58
Kevin O'Connorb725dcb2011-10-15 11:53:38 -040059struct pci_bus {
Alexey Korolev35a770f2012-04-19 17:47:19 +120060 struct pci_region r[PCI_REGION_TYPE_COUNT];
Kevin O'Connor2c4c2112011-10-15 11:42:48 -040061 struct pci_device *bus_dev;
Kevin O'Connorb725dcb2011-10-15 11:53:38 -040062};
Gerd Hoffmann82b39b22011-07-11 09:20:28 +020063
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -040064static u32 pci_bar(struct pci_device *pci, int region_num)
Isaku Yamahataa65821d2010-06-22 17:57:50 +090065{
66 if (region_num != PCI_ROM_SLOT) {
67 return PCI_BASE_ADDRESS_0 + region_num * 4;
68 }
Isaku Yamahata5d0de152010-06-22 17:57:51 +090069
70#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -040071 u8 type = pci->header_type & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
Isaku Yamahata5d0de152010-06-22 17:57:51 +090072 return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
Isaku Yamahataa65821d2010-06-22 17:57:50 +090073}
74
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -040075static void
Alexey Korolev030288f2012-04-19 17:44:55 +120076pci_set_io_region_addr(struct pci_device *pci, int bar, u64 addr, int is64)
Kevin O'Connor0525d292008-07-04 06:18:30 -040077{
Alexey Korolev030288f2012-04-19 17:44:55 +120078 u32 ofs = pci_bar(pci, bar);
79 pci_config_writel(pci->bdf, ofs, addr);
80 if (is64)
81 pci_config_writel(pci->bdf, ofs + 4, addr >> 32);
Isaku Yamahatab9e47212010-06-22 17:57:47 +090082}
83
Kevin O'Connor5bab7e62011-10-01 11:33:31 -040084
85/****************************************************************
86 * Misc. device init
87 ****************************************************************/
88
89/* host irqs corresponding to PCI irqs A-D */
90const u8 pci_irqs[4] = {
91 10, 10, 11, 11
92};
93
Kevin O'Connor0ce21382011-10-01 14:52:35 -040094// Return the global irq number corresponding to a host bus device irq pin.
Gerd Hoffmann0c8f58d2012-05-04 17:33:36 +020095static int pci_slot_get_irq(struct pci_device *pci, int pin)
Kevin O'Connor0525d292008-07-04 06:18:30 -040096{
Gerd Hoffmann0c8f58d2012-05-04 17:33:36 +020097 int slot_addend = 0;
98
99 while (pci->parent != NULL) {
100 slot_addend += pci_bdf_to_dev(pci->bdf);
101 pci = pci->parent;
102 }
103 slot_addend += pci_bdf_to_dev(pci->bdf) - 1;
Kevin O'Connor0ce21382011-10-01 14:52:35 -0400104 return pci_irqs[(pin - 1 + slot_addend) & 3];
Kevin O'Connor0525d292008-07-04 06:18:30 -0400105}
106
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400107/* PIIX3/PIIX4 PCI to ISA bridge */
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400108static void piix_isa_bridge_init(struct pci_device *pci, void *arg)
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400109{
110 int i, irq;
111 u8 elcr[2];
112
113 elcr[0] = 0x00;
114 elcr[1] = 0x00;
115 for (i = 0; i < 4; i++) {
116 irq = pci_irqs[i];
117 /* set to trigger level */
118 elcr[irq >> 3] |= (1 << (irq & 7));
119 /* activate irq remapping in PIIX */
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400120 pci_config_writeb(pci->bdf, 0x60 + i, irq);
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400121 }
122 outb(elcr[0], 0x4d0);
123 outb(elcr[1], 0x4d1);
124 dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n", elcr[0], elcr[1]);
125}
126
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100127/* ICH9 LPC PCI to ISA bridge */
128/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */
129void mch_isa_bridge_init(struct pci_device *dev, void *arg)
130{
131 u16 bdf = dev->bdf;
132 int i, irq;
133 u8 elcr[2];
134
135 elcr[0] = 0x00;
136 elcr[1] = 0x00;
137
138 for (i = 0; i < 4; i++) {
139 irq = pci_irqs[i];
140 /* set to trigger level */
141 elcr[irq >> 3] |= (1 << (irq & 7));
142
143 /* activate irq remapping in LPC */
144
145 /* PIRQ[A-D] routing */
146 pci_config_writeb(bdf, ICH9_LPC_PIRQA_ROUT + i,
147 irq | ICH9_LPC_PIRQ_ROUT_IRQEN);
148 /* PIRQ[E-H] routing */
149 pci_config_writeb(bdf, ICH9_LPC_PIRQE_ROUT + i,
150 irq | ICH9_LPC_PIRQ_ROUT_IRQEN);
151 }
152 outb(elcr[0], ICH9_LPC_PORT_ELCR1);
153 outb(elcr[1], ICH9_LPC_PORT_ELCR2);
154 dprintf(1, "Q35 LPC init: elcr=%02x %02x\n", elcr[0], elcr[1]);
155
156 /* pm io base */
157 pci_config_writel(bdf, ICH9_LPC_PMBASE,
158 PORT_ACPI_PM_BASE | ICH9_LPC_PMBASE_RTE);
159
160 /* acpi enable, SCI: IRQ9 000b = irq9*/
161 pci_config_writeb(bdf, ICH9_LPC_ACPI_CTRL, ICH9_LPC_ACPI_CTRL_ACPI_EN);
162
163 pmtimer_init(PORT_ACPI_PM_BASE + 0x08, PM_TIMER_FREQUENCY / 1000);
164}
165
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400166static void storage_ide_init(struct pci_device *pci, void *arg)
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400167{
168 /* IDE: we map it as in ISA mode */
Alexey Korolev030288f2012-04-19 17:44:55 +1200169 pci_set_io_region_addr(pci, 0, PORT_ATA1_CMD_BASE, 0);
170 pci_set_io_region_addr(pci, 1, PORT_ATA1_CTRL_BASE, 0);
171 pci_set_io_region_addr(pci, 2, PORT_ATA2_CMD_BASE, 0);
172 pci_set_io_region_addr(pci, 3, PORT_ATA2_CTRL_BASE, 0);
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400173}
174
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400175/* PIIX3/PIIX4 IDE */
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400176static void piix_ide_init(struct pci_device *pci, void *arg)
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400177{
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400178 u16 bdf = pci->bdf;
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400179 pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
180 pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400181}
182
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400183static void pic_ibm_init(struct pci_device *pci, void *arg)
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400184{
185 /* PIC, IBM, MPIC & MPIC2 */
Alexey Korolev030288f2012-04-19 17:44:55 +1200186 pci_set_io_region_addr(pci, 0, 0x80800000 + 0x00040000, 0);
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400187}
188
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400189static void apple_macio_init(struct pci_device *pci, void *arg)
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400190{
191 /* macio bridge */
Alexey Korolev030288f2012-04-19 17:44:55 +1200192 pci_set_io_region_addr(pci, 0, 0x80800000, 0);
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400193}
194
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400195/* PIIX4 Power Management device (for ACPI) */
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400196static void piix4_pm_init(struct pci_device *pci, void *arg)
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400197{
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400198 u16 bdf = pci->bdf;
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400199 // acpi sci is hardwired to 9
200 pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
201
202 pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
203 pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
204 pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
205 pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
Gerd Hoffmann455a7c82012-09-06 08:01:00 +0200206
207 pmtimer_init(PORT_ACPI_PM_BASE + 0x08, PM_TIMER_FREQUENCY / 1000);
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400208}
209
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100210/* ICH9 SMBUS */
211/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_SMBUS */
212void ich9_smbus_init(struct pci_device *dev, void *arg)
213{
214 u16 bdf = dev->bdf;
215 /* map smbus into io space */
216 pci_config_writel(bdf, ICH9_SMB_SMB_BASE,
217 PORT_SMB_BASE | PCI_BASE_ADDRESS_SPACE_IO);
218
219 /* enable SMBus */
220 pci_config_writeb(bdf, ICH9_SMB_HOSTC, ICH9_SMB_HOSTC_HST_EN);
221}
222
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400223static const struct pci_device_id pci_device_tbl[] = {
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500224 /* PIIX3/PIIX4 PCI to ISA bridge */
225 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0,
226 piix_isa_bridge_init),
227 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
228 piix_isa_bridge_init),
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100229 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC,
230 mch_isa_bridge_init),
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500231
232 /* STORAGE IDE */
233 PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1,
234 PCI_CLASS_STORAGE_IDE, piix_ide_init),
235 PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
236 PCI_CLASS_STORAGE_IDE, piix_ide_init),
237 PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
238 storage_ide_init),
239
240 /* PIC, IBM, MIPC & MPIC2 */
241 PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0x0046, PCI_CLASS_SYSTEM_PIC,
242 pic_ibm_init),
243 PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0xFFFF, PCI_CLASS_SYSTEM_PIC,
244 pic_ibm_init),
245
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400246 /* PIIX4 Power Management device (for ACPI) */
247 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
248 piix4_pm_init),
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100249 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_SMBUS,
250 ich9_smbus_init),
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400251
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500252 /* 0xff00 */
253 PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_init),
254 PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_init),
255
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400256 PCI_DEVICE_END,
257};
258
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400259static void pci_bios_init_device(struct pci_device *pci)
Kevin O'Connor0525d292008-07-04 06:18:30 -0400260{
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400261 u16 bdf = pci->bdf;
Kevin O'Connor99e37c42011-10-01 10:47:21 -0400262 dprintf(1, "PCI: init bdf=%02x:%02x.%x id=%04x:%04x\n"
263 , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400264 , pci->vendor, pci->device);
Kevin O'Connor0ce21382011-10-01 14:52:35 -0400265
Kevin O'Connor0525d292008-07-04 06:18:30 -0400266 /* map the interrupt */
Kevin O'Connor0ce21382011-10-01 14:52:35 -0400267 int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
268 if (pin != 0)
Gerd Hoffmann0c8f58d2012-05-04 17:33:36 +0200269 pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin));
Kevin O'Connor0525d292008-07-04 06:18:30 -0400270
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400271 pci_init_device(pci_device_tbl, pci, NULL);
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500272
273 /* enable memory mappings */
Isaku Yamahatad146ab82012-11-28 10:17:32 +0100274 pci_config_maskw(bdf, PCI_COMMAND, 0,
275 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR);
Kevin O'Connor0525d292008-07-04 06:18:30 -0400276}
277
Kevin O'Connor3f2288f2011-10-15 12:02:14 -0400278static void pci_bios_init_devices(void)
Isaku Yamahataaf0963d2010-06-22 17:57:53 +0900279{
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400280 struct pci_device *pci;
281 foreachpci(pci) {
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400282 pci_bios_init_device(pci);
Isaku Yamahataaf0963d2010-06-22 17:57:53 +0900283 }
284}
285
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400286
287/****************************************************************
Kevin O'Connorb1c35f22012-11-26 11:05:32 -0500288 * Platform device initialization
289 ****************************************************************/
290
291void i440fx_mem_addr_init(struct pci_device *dev, void *arg)
292{
293 if (RamSize <= 0x80000000)
294 pcimem_start = 0x80000000;
295 else if (RamSize <= 0xc0000000)
296 pcimem_start = 0xc0000000;
297}
298
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100299void mch_mem_addr_init(struct pci_device *dev, void *arg)
300{
301 u64 addr = Q35_HOST_BRIDGE_PCIEXBAR_ADDR;
302 u32 size = Q35_HOST_BRIDGE_PCIEXBAR_SIZE;
303
304 /* setup mmconfig */
305 u16 bdf = dev->bdf;
306 u32 upper = addr >> 32;
307 u32 lower = (addr & 0xffffffff) | Q35_HOST_BRIDGE_PCIEXBAREN;
308 pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0);
309 pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);
310 pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower);
311 add_e820(addr, size, E820_RESERVED);
312
313 /* setup pci i/o window (above mmconfig) */
314 pcimem_start = addr + size;
315}
316
Kevin O'Connorb1c35f22012-11-26 11:05:32 -0500317static const struct pci_device_id pci_platform_tbl[] = {
318 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441,
319 i440fx_mem_addr_init),
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100320 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH,
321 mch_mem_addr_init),
Kevin O'Connorb1c35f22012-11-26 11:05:32 -0500322 PCI_DEVICE_END
323};
324
325static void pci_bios_init_platform(void)
326{
327 struct pci_device *pci;
328 foreachpci(pci) {
329 pci_init_device(pci_platform_tbl, pci, NULL);
330 }
331}
332
333
334/****************************************************************
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400335 * Bus initialization
336 ****************************************************************/
337
Isaku Yamahataf4416662010-06-22 17:57:52 +0900338static void
339pci_bios_init_bus_rec(int bus, u8 *pci_bus)
340{
Kevin O'Connor2b333e42011-07-02 14:49:41 -0400341 int bdf;
Isaku Yamahataf4416662010-06-22 17:57:52 +0900342 u16 class;
343
344 dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus);
345
346 /* prevent accidental access to unintended devices */
Kevin O'Connor2b333e42011-07-02 14:49:41 -0400347 foreachbdf(bdf, bus) {
Isaku Yamahataf4416662010-06-22 17:57:52 +0900348 class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
349 if (class == PCI_CLASS_BRIDGE_PCI) {
350 pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255);
351 pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0);
352 }
353 }
354
Kevin O'Connor2b333e42011-07-02 14:49:41 -0400355 foreachbdf(bdf, bus) {
Isaku Yamahataf4416662010-06-22 17:57:52 +0900356 class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
357 if (class != PCI_CLASS_BRIDGE_PCI) {
358 continue;
359 }
360 dprintf(1, "PCI: %s bdf = 0x%x\n", __func__, bdf);
361
362 u8 pribus = pci_config_readb(bdf, PCI_PRIMARY_BUS);
363 if (pribus != bus) {
364 dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus);
365 pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus);
366 } else {
367 dprintf(1, "PCI: primary bus = 0x%x\n", pribus);
368 }
369
370 u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
371 (*pci_bus)++;
372 if (*pci_bus != secbus) {
373 dprintf(1, "PCI: secondary bus = 0x%x -> 0x%x\n",
374 secbus, *pci_bus);
375 secbus = *pci_bus;
376 pci_config_writeb(bdf, PCI_SECONDARY_BUS, secbus);
377 } else {
378 dprintf(1, "PCI: secondary bus = 0x%x\n", secbus);
379 }
380
381 /* set to max for access to all subordinate buses.
382 later set it to accurate value */
383 u8 subbus = pci_config_readb(bdf, PCI_SUBORDINATE_BUS);
384 pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 255);
385
386 pci_bios_init_bus_rec(secbus, pci_bus);
387
388 if (subbus != *pci_bus) {
389 dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
390 subbus, *pci_bus);
391 subbus = *pci_bus;
392 } else {
393 dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
394 }
395 pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus);
396 }
397}
398
399static void
400pci_bios_init_bus(void)
401{
402 u8 pci_bus = 0;
403 pci_bios_init_bus_rec(0 /* host bus */, &pci_bus);
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200404}
405
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400406
407/****************************************************************
408 * Bus sizing
409 ****************************************************************/
410
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -0400411static void
Alexey Korolev030288f2012-04-19 17:44:55 +1200412pci_bios_get_bar(struct pci_device *pci, int bar,
413 int *ptype, u64 *psize, int *pis64)
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200414{
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -0400415 u32 ofs = pci_bar(pci, bar);
416 u16 bdf = pci->bdf;
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200417 u32 old = pci_config_readl(bdf, ofs);
Alexey Korolev030288f2012-04-19 17:44:55 +1200418 int is64 = 0, type = PCI_REGION_TYPE_MEM;
419 u64 mask;
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200420
421 if (bar == PCI_ROM_SLOT) {
422 mask = PCI_ROM_ADDRESS_MASK;
423 pci_config_writel(bdf, ofs, mask);
424 } else {
Alexey Korolev030288f2012-04-19 17:44:55 +1200425 if (old & PCI_BASE_ADDRESS_SPACE_IO) {
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200426 mask = PCI_BASE_ADDRESS_IO_MASK;
Alexey Korolev030288f2012-04-19 17:44:55 +1200427 type = PCI_REGION_TYPE_IO;
428 } else {
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200429 mask = PCI_BASE_ADDRESS_MEM_MASK;
Alexey Korolev030288f2012-04-19 17:44:55 +1200430 if (old & PCI_BASE_ADDRESS_MEM_PREFETCH)
431 type = PCI_REGION_TYPE_PREFMEM;
432 is64 = ((old & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
433 == PCI_BASE_ADDRESS_MEM_TYPE_64);
434 }
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200435 pci_config_writel(bdf, ofs, ~0);
436 }
Alexey Korolev030288f2012-04-19 17:44:55 +1200437 u64 val = pci_config_readl(bdf, ofs);
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200438 pci_config_writel(bdf, ofs, old);
Alexey Korolev030288f2012-04-19 17:44:55 +1200439 if (is64) {
440 u32 hold = pci_config_readl(bdf, ofs + 4);
441 pci_config_writel(bdf, ofs + 4, ~0);
442 u32 high = pci_config_readl(bdf, ofs + 4);
443 pci_config_writel(bdf, ofs + 4, hold);
444 val |= ((u64)high << 32);
445 mask |= ((u64)0xffffffff << 32);
446 *psize = (~(val & mask)) + 1;
447 } else {
448 *psize = ((~(val & mask)) + 1) & 0xffffffff;
449 }
450 *ptype = type;
451 *pis64 = is64;
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200452}
453
Alexey Korolevac0cd582012-04-19 17:48:54 +1200454static int pci_bios_bridge_region_is64(struct pci_region *r,
455 struct pci_device *pci, int type)
456{
457 if (type != PCI_REGION_TYPE_PREFMEM)
458 return 0;
459 u32 pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE);
460 if (!pmem) {
461 pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0xfff0fff0);
462 pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE);
463 pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0x0);
464 }
465 if ((pmem & PCI_PREF_RANGE_TYPE_MASK) != PCI_PREF_RANGE_TYPE_64)
466 return 0;
467 struct pci_region_entry *entry = r->list;
468 while (entry) {
469 if (!entry->is64)
470 return 0;
471 entry = entry->next;
472 }
473 return 1;
474}
475
Alexey Korolev37c111f2012-04-26 16:51:05 +1200476static u64 pci_region_align(struct pci_region *r)
477{
478 if (!r->list)
479 return 1;
480 // The first entry in the sorted list has the largest alignment
481 return r->list->align;
482}
483
484static u64 pci_region_sum(struct pci_region *r)
485{
486 struct pci_region_entry *entry = r->list;
487 u64 sum = 0;
488 while (entry) {
489 sum += entry->size;
490 entry = entry->next;
Kevin O'Connore5d71ca2012-04-26 22:04:34 -0400491 }
492 return sum;
Alexey Korolev37c111f2012-04-26 16:51:05 +1200493}
494
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200495static void pci_region_migrate_64bit_entries(struct pci_region *from,
496 struct pci_region *to)
497{
Kevin O'Connord630d142012-04-26 22:20:56 -0400498 struct pci_region_entry **pprev = &from->list, **last = &to->list;
Kevin O'Connore5d71ca2012-04-26 22:04:34 -0400499 while (*pprev) {
Kevin O'Connord630d142012-04-26 22:20:56 -0400500 struct pci_region_entry *entry = *pprev;
501 if (!entry->is64) {
502 pprev = &entry->next;
503 continue;
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200504 }
Kevin O'Connord630d142012-04-26 22:20:56 -0400505 // Move from source list to destination list.
506 *pprev = entry->next;
507 entry->next = NULL;
508 *last = entry;
509 last = &entry->next;
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200510 }
511}
512
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200513static struct pci_region_entry *
514pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
Alexey Korolev030288f2012-04-19 17:44:55 +1200515 int bar, u64 size, u64 align, int type, int is64)
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200516{
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200517 struct pci_region_entry *entry = malloc_tmp(sizeof(*entry));
518 if (!entry) {
519 warn_noalloc();
520 return NULL;
521 }
522 memset(entry, 0, sizeof(*entry));
523 entry->dev = dev;
524 entry->bar = bar;
525 entry->size = size;
Kevin O'Connor3d1bc9d2012-04-01 12:30:32 -0400526 entry->align = align;
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200527 entry->is64 = is64;
528 entry->type = type;
529 // Insert into list in sorted order.
530 struct pci_region_entry **pprev;
531 for (pprev = &bus->r[type].list; *pprev; pprev = &(*pprev)->next) {
532 struct pci_region_entry *pos = *pprev;
Kevin O'Connor3d1bc9d2012-04-01 12:30:32 -0400533 if (pos->align < align || (pos->align == align && pos->size < size))
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200534 break;
535 }
536 entry->next = *pprev;
537 *pprev = entry;
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200538 return entry;
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200539}
540
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200541static int pci_bios_check_devices(struct pci_bus *busses)
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200542{
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400543 dprintf(1, "PCI: check devices\n");
544
545 // Calculate resources needed for regular (non-bus) devices.
546 struct pci_device *pci;
547 foreachpci(pci) {
Alexey Korolev1a9f47f2012-04-19 17:40:13 +1200548 if (pci->class == PCI_CLASS_BRIDGE_PCI)
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400549 busses[pci->secondary_bus].bus_dev = pci;
Alexey Korolev1a9f47f2012-04-19 17:40:13 +1200550
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400551 struct pci_bus *bus = &busses[pci_bdf_to_bus(pci->bdf)];
552 int i;
553 for (i = 0; i < PCI_NUM_REGIONS; i++) {
Alexey Korolev1a9f47f2012-04-19 17:40:13 +1200554 if ((pci->class == PCI_CLASS_BRIDGE_PCI) &&
555 (i >= PCI_BRIDGE_NUM_REGIONS && i < PCI_ROM_SLOT))
556 continue;
Alexey Korolev030288f2012-04-19 17:44:55 +1200557 int type, is64;
558 u64 size;
559 pci_bios_get_bar(pci, i, &type, &size, &is64);
560 if (size == 0)
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400561 continue;
562
Alexey Korolev5fa24b52012-04-18 17:31:58 +1200563 if (type != PCI_REGION_TYPE_IO && size < PCI_DEVICE_MEM_MIN)
564 size = PCI_DEVICE_MEM_MIN;
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200565 struct pci_region_entry *entry = pci_region_create_entry(
Kevin O'Connor3d1bc9d2012-04-01 12:30:32 -0400566 bus, pci, i, size, size, type, is64);
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200567 if (!entry)
568 return -1;
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400569
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200570 if (is64)
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400571 i++;
572 }
573 }
574
575 // Propagate required bus resources to parent busses.
576 int secondary_bus;
577 for (secondary_bus=MaxPCIBus; secondary_bus>0; secondary_bus--) {
578 struct pci_bus *s = &busses[secondary_bus];
579 if (!s->bus_dev)
580 continue;
581 struct pci_bus *parent = &busses[pci_bdf_to_bus(s->bus_dev->bdf)];
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -0400582 int type;
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200583 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
Alexey Korolev030288f2012-04-19 17:44:55 +1200584 u64 align = (type == PCI_REGION_TYPE_IO) ?
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200585 PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
Alexey Korolev37c111f2012-04-26 16:51:05 +1200586 if (pci_region_align(&s->r[type]) > align)
587 align = pci_region_align(&s->r[type]);
588 u64 sum = pci_region_sum(&s->r[type]);
589 u64 size = ALIGN(sum, align);
Alexey Korolevac0cd582012-04-19 17:48:54 +1200590 int is64 = pci_bios_bridge_region_is64(&s->r[type],
591 s->bus_dev, type);
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200592 // entry->bar is -1 if the entry represents a bridge region
593 struct pci_region_entry *entry = pci_region_create_entry(
Alexey Korolevac0cd582012-04-19 17:48:54 +1200594 parent, s->bus_dev, -1, size, align, type, is64);
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200595 if (!entry)
596 return -1;
Alexey Korolev030288f2012-04-19 17:44:55 +1200597 dprintf(1, "PCI: secondary bus %d size %08llx type %s\n",
Alexey Korolevf3c2b062012-04-18 17:26:43 +1200598 entry->dev->secondary_bus, size,
599 region_type_name[entry->type]);
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200600 }
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400601 }
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200602 return 0;
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400603}
604
Kevin O'Connore5d71ca2012-04-26 22:04:34 -0400605
606/****************************************************************
607 * BAR assignment
608 ****************************************************************/
609
Kevin O'Connora8dcc5b2011-10-01 12:08:57 -0400610// Setup region bases (given the regions' size and alignment)
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200611static int pci_bios_init_root_regions(struct pci_bus *bus)
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400612{
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400613 bus->r[PCI_REGION_TYPE_IO].base = 0xc000;
614
Alexey Korolev37c111f2012-04-26 16:51:05 +1200615 struct pci_region *r_end = &bus->r[PCI_REGION_TYPE_PREFMEM];
616 struct pci_region *r_start = &bus->r[PCI_REGION_TYPE_MEM];
617
618 if (pci_region_align(r_start) < pci_region_align(r_end)) {
Kevin O'Connor3d1bc9d2012-04-01 12:30:32 -0400619 // Swap regions to improve alignment.
Alexey Korolev37c111f2012-04-26 16:51:05 +1200620 r_end = r_start;
621 r_start = &bus->r[PCI_REGION_TYPE_PREFMEM];
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400622 }
Alexey Korolev37c111f2012-04-26 16:51:05 +1200623 u64 sum = pci_region_sum(r_end);
624 u64 align = pci_region_align(r_end);
Gerd Hoffmanne55c4e82012-06-07 10:34:32 +0200625 r_end->base = ALIGN_DOWN((pcimem_end - sum), align);
Alexey Korolev37c111f2012-04-26 16:51:05 +1200626 sum = pci_region_sum(r_start);
627 align = pci_region_align(r_start);
628 r_start->base = ALIGN_DOWN((r_end->base - sum), align);
629
Gerd Hoffmanne55c4e82012-06-07 10:34:32 +0200630 if ((r_start->base < pcimem_start) ||
631 (r_start->base > pcimem_end))
Kevin O'Connora8dcc5b2011-10-01 12:08:57 -0400632 // Memory range requested is larger than available.
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200633 return -1;
634 return 0;
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400635}
636
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400637#define PCI_IO_SHIFT 8
638#define PCI_MEMORY_SHIFT 16
639#define PCI_PREF_MEMORY_SHIFT 16
640
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200641static void
Alexey Korolev35a770f2012-04-19 17:47:19 +1200642pci_region_map_one_entry(struct pci_region_entry *entry, u64 addr)
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200643{
644 u16 bdf = entry->dev->bdf;
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200645 if (entry->bar >= 0) {
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200646 dprintf(1, "PCI: map device bdf=%02x:%02x.%x"
Alexey Korolev030288f2012-04-19 17:44:55 +1200647 " bar %d, addr %08llx, size %08llx [%s]\n",
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200648 pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf),
649 entry->bar, addr, entry->size, region_type_name[entry->type]);
650
Alexey Korolev030288f2012-04-19 17:44:55 +1200651 pci_set_io_region_addr(entry->dev, entry->bar, addr, entry->is64);
Alexey Korolev3a297162012-04-18 17:22:29 +1200652 return;
653 }
654
Alexey Korolev030288f2012-04-19 17:44:55 +1200655 u64 limit = addr + entry->size - 1;
Alexey Korolev3a297162012-04-18 17:22:29 +1200656 if (entry->type == PCI_REGION_TYPE_IO) {
657 pci_config_writeb(bdf, PCI_IO_BASE, addr >> PCI_IO_SHIFT);
658 pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
659 pci_config_writeb(bdf, PCI_IO_LIMIT, limit >> PCI_IO_SHIFT);
660 pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
661 }
662 if (entry->type == PCI_REGION_TYPE_MEM) {
663 pci_config_writew(bdf, PCI_MEMORY_BASE, addr >> PCI_MEMORY_SHIFT);
664 pci_config_writew(bdf, PCI_MEMORY_LIMIT, limit >> PCI_MEMORY_SHIFT);
665 }
666 if (entry->type == PCI_REGION_TYPE_PREFMEM) {
667 pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, addr >> PCI_PREF_MEMORY_SHIFT);
668 pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, limit >> PCI_PREF_MEMORY_SHIFT);
Alexey Korolev030288f2012-04-19 17:44:55 +1200669 pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, addr >> 32);
670 pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, limit >> 32);
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200671 }
672}
673
Alexey Korolev35a770f2012-04-19 17:47:19 +1200674static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r)
675{
676 struct pci_region_entry *entry = r->list;
Kevin O'Connore5d71ca2012-04-26 22:04:34 -0400677 while (entry) {
Alexey Korolev35a770f2012-04-19 17:47:19 +1200678 u64 addr = r->base;
679 r->base += entry->size;
680 if (entry->bar == -1)
681 // Update bus base address if entry is a bridge region
682 busses[entry->dev->secondary_bus].r[entry->type].base = addr;
683 pci_region_map_one_entry(entry, addr);
684 struct pci_region_entry *next = entry->next;
685 free(entry);
686 entry = next;
687 }
688}
689
Kevin O'Connorb725dcb2011-10-15 11:53:38 -0400690static void pci_bios_map_devices(struct pci_bus *busses)
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200691{
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200692 if (pci_bios_init_root_regions(busses)) {
693 struct pci_region r64_mem, r64_pref;
694 r64_mem.list = NULL;
695 r64_pref.list = NULL;
696 pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_MEM],
697 &r64_mem);
698 pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM],
699 &r64_pref);
700
701 if (pci_bios_init_root_regions(busses))
702 panic("PCI: out of 32bit address space\n");
703
Gerd Hoffmann5283b2e2012-06-12 09:27:15 +0200704 u64 sum_mem = pci_region_sum(&r64_mem);
705 u64 sum_pref = pci_region_sum(&r64_pref);
706 u64 align_mem = pci_region_align(&r64_mem);
707 u64 align_pref = pci_region_align(&r64_pref);
708
709 r64_mem.base = ALIGN(0x100000000LL + RamSizeOver4G, align_mem);
710 r64_pref.base = ALIGN(r64_mem.base + sum_mem, align_pref);
711 pcimem64_start = r64_mem.base;
712 pcimem64_end = r64_pref.base + sum_pref;
713
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200714 pci_region_map_entries(busses, &r64_mem);
715 pci_region_map_entries(busses, &r64_pref);
Gerd Hoffmann5283b2e2012-06-12 09:27:15 +0200716 } else {
717 // no bars mapped high -> drop 64bit window (see dsdt)
718 pcimem64_start = 0;
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200719 }
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400720 // Map regions on each device.
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200721 int bus;
722 for (bus = 0; bus<=MaxPCIBus; bus++) {
723 int type;
Alexey Korolev35a770f2012-04-19 17:47:19 +1200724 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++)
725 pci_region_map_entries(busses, &busses[bus].r[type]);
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200726 }
727}
728
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200729
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400730/****************************************************************
731 * Main setup code
732 ****************************************************************/
Isaku Yamahataf4416662010-06-22 17:57:52 +0900733
Kevin O'Connor0525d292008-07-04 06:18:30 -0400734void
Kevin O'Connor40f5b5a2009-09-13 10:46:57 -0400735pci_setup(void)
Kevin O'Connor0525d292008-07-04 06:18:30 -0400736{
Kevin O'Connor37956dd2011-06-21 22:22:58 -0400737 if (CONFIG_COREBOOT || usingXen()) {
738 // PCI setup already done by coreboot or Xen - just do probe.
Jan Kiszka58e6b3f2011-09-21 08:16:21 +0200739 pci_probe_devices();
Kevin O'Connor0525d292008-07-04 06:18:30 -0400740 return;
Kevin O'Connor37956dd2011-06-21 22:22:58 -0400741 }
Kevin O'Connor0525d292008-07-04 06:18:30 -0400742
Kevin O'Connor40f5b5a2009-09-13 10:46:57 -0400743 dprintf(3, "pci setup\n");
744
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200745 dprintf(1, "=== PCI bus & bridge init ===\n");
Jan Kiszka58e6b3f2011-09-21 08:16:21 +0200746 if (pci_probe_host() != 0) {
747 return;
748 }
Isaku Yamahataf4416662010-06-22 17:57:52 +0900749 pci_bios_init_bus();
750
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200751 dprintf(1, "=== PCI device probing ===\n");
Jan Kiszka58e6b3f2011-09-21 08:16:21 +0200752 pci_probe_devices();
Kevin O'Connor37956dd2011-06-21 22:22:58 -0400753
Kevin O'Connorb1c35f22012-11-26 11:05:32 -0500754 pcimem_start = RamSize;
755 pci_bios_init_platform();
756
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200757 dprintf(1, "=== PCI new allocation pass #1 ===\n");
Kevin O'Connorb725dcb2011-10-15 11:53:38 -0400758 struct pci_bus *busses = malloc_tmp(sizeof(*busses) * (MaxPCIBus + 1));
Kevin O'Connor28a20e12011-10-15 11:07:30 -0400759 if (!busses) {
760 warn_noalloc();
761 return;
762 }
763 memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1));
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200764 if (pci_bios_check_devices(busses))
765 return;
766
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200767 dprintf(1, "=== PCI new allocation pass #2 ===\n");
Kevin O'Connorb725dcb2011-10-15 11:53:38 -0400768 pci_bios_map_devices(busses);
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200769
Kevin O'Connor3f2288f2011-10-15 12:02:14 -0400770 pci_bios_init_devices();
Gerd Hoffmann8e301472011-08-09 17:22:42 +0200771
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200772 free(busses);
Kevin O'Connor0525d292008-07-04 06:18:30 -0400773}