|
|
1.1 root 1: // Initialize PCI devices (on emulators)
2: //
3: // Copyright (C) 2008 Kevin O'Connor <[email protected]>
4: // Copyright (C) 2006 Fabrice Bellard
5: //
6: // This file may be distributed under the terms of the GNU LGPLv3 license.
7:
8: #include "util.h" // dprintf
9: #include "pci.h" // pci_config_readl
10: #include "biosvar.h" // GET_EBDA
11: #include "pci_ids.h" // PCI_VENDOR_ID_INTEL
12: #include "pci_regs.h" // PCI_COMMAND
1.1.1.7 ! root 13: #include "xen.h" // usingXen
1.1 root 14:
1.1.1.7 ! root 15: #define PCI_IO_INDEX_SHIFT 2
! 16: #define PCI_MEM_INDEX_SHIFT 12
! 17:
! 18: #define PCI_BRIDGE_IO_MIN 0x1000
! 19: #define PCI_BRIDGE_MEM_MIN 0x100000
! 20:
! 21: enum pci_region_type {
! 22: PCI_REGION_TYPE_IO,
! 23: PCI_REGION_TYPE_MEM,
! 24: PCI_REGION_TYPE_PREFMEM,
! 25: PCI_REGION_TYPE_COUNT,
! 26: };
! 27:
! 28: static const char *region_type_name[] = {
! 29: [ PCI_REGION_TYPE_IO ] = "io",
! 30: [ PCI_REGION_TYPE_MEM ] = "mem",
! 31: [ PCI_REGION_TYPE_PREFMEM ] = "prefmem",
! 32: };
! 33:
! 34: static struct pci_bus {
! 35: struct {
! 36: /* pci region stats */
! 37: u32 count[32 - PCI_MEM_INDEX_SHIFT];
! 38: u32 sum, max;
! 39: /* seconday bus region sizes */
! 40: u32 size;
! 41: /* pci region assignments */
! 42: u32 bases[32 - PCI_MEM_INDEX_SHIFT];
! 43: u32 base;
! 44: } r[PCI_REGION_TYPE_COUNT];
! 45: } *busses;
! 46: static int busses_count;
1.1 root 47:
1.1.1.4 root 48: static void pci_bios_init_device_in_bus(int bus);
1.1.1.7 ! root 49: static void pci_bios_check_device_in_bus(int bus);
! 50: static void pci_bios_init_bus_bases(struct pci_bus *bus);
! 51: static void pci_bios_map_device_in_bus(int bus);
1.1.1.4 root 52:
1.1.1.7 ! root 53: static int pci_size_to_index(u32 size, enum pci_region_type type)
! 54: {
! 55: int index = __fls(size);
! 56: int shift = (type == PCI_REGION_TYPE_IO) ?
! 57: PCI_IO_INDEX_SHIFT : PCI_MEM_INDEX_SHIFT;
! 58:
! 59: if (index < shift)
! 60: index = shift;
! 61: index -= shift;
! 62: return index;
! 63: }
! 64:
! 65: static u32 pci_index_to_size(int index, enum pci_region_type type)
! 66: {
! 67: int shift = (type == PCI_REGION_TYPE_IO) ?
! 68: PCI_IO_INDEX_SHIFT : PCI_MEM_INDEX_SHIFT;
! 69:
! 70: return 0x1 << (index + shift);
! 71: }
! 72:
! 73: static enum pci_region_type pci_addr_to_type(u32 addr)
! 74: {
! 75: if (addr & PCI_BASE_ADDRESS_SPACE_IO)
! 76: return PCI_REGION_TYPE_IO;
! 77: if (addr & PCI_BASE_ADDRESS_MEM_PREFETCH)
! 78: return PCI_REGION_TYPE_PREFMEM;
! 79: return PCI_REGION_TYPE_MEM;
! 80: }
! 81:
! 82: static u32 pci_size_roundup(u32 size)
! 83: {
! 84: int index = __fls(size-1)+1;
! 85: return 0x1 << index;
! 86: }
1.1.1.6 root 87:
1.1 root 88: /* host irqs corresponding to PCI irqs A-D */
1.1.1.4 root 89: const u8 pci_irqs[4] = {
1.1 root 90: 10, 10, 11, 11
91: };
92:
1.1.1.4 root 93: static u32 pci_bar(u16 bdf, int region_num)
94: {
95: if (region_num != PCI_ROM_SLOT) {
96: return PCI_BASE_ADDRESS_0 + region_num * 4;
97: }
98:
99: #define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
100: u8 type = pci_config_readb(bdf, PCI_HEADER_TYPE);
101: type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
102: return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
103: }
104:
1.1 root 105: static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
106: {
1.1.1.5 root 107: u32 ofs;
1.1 root 108:
1.1.1.4 root 109: ofs = pci_bar(bdf, region_num);
1.1 root 110:
111: pci_config_writel(bdf, ofs, addr);
1.1.1.4 root 112: }
113:
1.1 root 114: /* return the global irq number corresponding to a given device irq
115: pin. We could also use the bus number to have a more precise
116: mapping. */
117: static int pci_slot_get_pirq(u16 bdf, int irq_num)
118: {
119: int slot_addend = pci_bdf_to_dev(bdf) - 1;
120: return (irq_num + slot_addend) & 3;
121: }
122:
1.1.1.7 ! root 123: /* PIIX3/PIIX4 PCI to ISA bridge */
! 124: static void piix_isa_bridge_init(struct pci_device *pci, void *arg)
! 125: {
! 126: int i, irq;
! 127: u8 elcr[2];
! 128:
! 129: elcr[0] = 0x00;
! 130: elcr[1] = 0x00;
! 131: for (i = 0; i < 4; i++) {
! 132: irq = pci_irqs[i];
! 133: /* set to trigger level */
! 134: elcr[irq >> 3] |= (1 << (irq & 7));
! 135: /* activate irq remapping in PIIX */
! 136: pci_config_writeb(pci->bdf, 0x60 + i, irq);
! 137: }
! 138: outb(elcr[0], 0x4d0);
! 139: outb(elcr[1], 0x4d1);
! 140: dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n", elcr[0], elcr[1]);
! 141: }
! 142:
1.1.1.4 root 143: static const struct pci_device_id pci_isa_bridge_tbl[] = {
144: /* PIIX3/PIIX4 PCI to ISA bridge */
145: PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0,
146: piix_isa_bridge_init),
147: PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
148: piix_isa_bridge_init),
149:
150: PCI_DEVICE_END
151: };
152:
153: #define PCI_IO_ALIGN 4096
154: #define PCI_IO_SHIFT 8
155: #define PCI_MEMORY_ALIGN (1UL << 20)
156: #define PCI_MEMORY_SHIFT 16
157: #define PCI_PREF_MEMORY_ALIGN (1UL << 20)
158: #define PCI_PREF_MEMORY_SHIFT 16
159:
1.1.1.7 ! root 160: static void storage_ide_init(struct pci_device *pci, void *arg)
1.1.1.4 root 161: {
1.1.1.7 ! root 162: u16 bdf = pci->bdf;
1.1.1.4 root 163: /* IDE: we map it as in ISA mode */
164: pci_set_io_region_addr(bdf, 0, PORT_ATA1_CMD_BASE);
165: pci_set_io_region_addr(bdf, 1, PORT_ATA1_CTRL_BASE);
166: pci_set_io_region_addr(bdf, 2, PORT_ATA2_CMD_BASE);
167: pci_set_io_region_addr(bdf, 3, PORT_ATA2_CTRL_BASE);
168: }
169:
1.1.1.7 ! root 170: /* PIIX3/PIIX4 IDE */
! 171: static void piix_ide_init(struct pci_device *pci, void *arg)
! 172: {
! 173: u16 bdf = pci->bdf;
! 174: pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
! 175: pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
! 176: }
! 177:
! 178: static void pic_ibm_init(struct pci_device *pci, void *arg)
1.1.1.4 root 179: {
180: /* PIC, IBM, MPIC & MPIC2 */
1.1.1.7 ! root 181: pci_set_io_region_addr(pci->bdf, 0, 0x80800000 + 0x00040000);
1.1 root 182: }
183:
1.1.1.7 ! root 184: static void apple_macio_init(struct pci_device *pci, void *arg)
1.1.1.4 root 185: {
186: /* macio bridge */
1.1.1.7 ! root 187: pci_set_io_region_addr(pci->bdf, 0, 0x80800000);
1.1.1.4 root 188: }
189:
190: static const struct pci_device_id pci_class_tbl[] = {
191: /* STORAGE IDE */
192: PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1,
193: PCI_CLASS_STORAGE_IDE, piix_ide_init),
194: PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
195: PCI_CLASS_STORAGE_IDE, piix_ide_init),
196: PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
197: storage_ide_init),
198:
199: /* PIC, IBM, MIPC & MPIC2 */
200: PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0x0046, PCI_CLASS_SYSTEM_PIC,
201: pic_ibm_init),
202: PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0xFFFF, PCI_CLASS_SYSTEM_PIC,
203: pic_ibm_init),
204:
205: /* 0xff00 */
206: PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_init),
207: PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_init),
208:
209: PCI_DEVICE_END,
210: };
211:
1.1.1.7 ! root 212: /* PIIX4 Power Management device (for ACPI) */
! 213: static void piix4_pm_init(struct pci_device *pci, void *arg)
! 214: {
! 215: u16 bdf = pci->bdf;
! 216: // acpi sci is hardwired to 9
! 217: pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
! 218:
! 219: pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
! 220: pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
! 221: pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
! 222: pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
! 223: }
! 224:
1.1.1.4 root 225: static const struct pci_device_id pci_device_tbl[] = {
226: /* PIIX4 Power Management device (for ACPI) */
227: PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
228: piix4_pm_init),
229:
230: PCI_DEVICE_END,
231: };
232:
1.1.1.7 ! root 233: static void pci_bios_init_device(struct pci_device *pci)
1.1 root 234: {
1.1.1.7 ! root 235: u16 bdf = pci->bdf;
! 236: int pin, pic_irq;
1.1 root 237:
238: dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n"
1.1.1.7 ! root 239: , pci_bdf_to_bus(bdf), pci_bdf_to_devfn(bdf)
! 240: , pci->vendor, pci->device);
! 241: pci_init_device(pci_class_tbl, pci, NULL);
1.1 root 242:
243: /* enable memory mappings */
244: pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
245:
246: /* map the interrupt */
247: pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
248: if (pin != 0) {
249: pin = pci_slot_get_pirq(bdf, pin - 1);
250: pic_irq = pci_irqs[pin];
251: pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pic_irq);
252: }
253:
1.1.1.7 ! root 254: pci_init_device(pci_device_tbl, pci, NULL);
1.1.1.4 root 255: }
256:
257: static void pci_bios_init_device_in_bus(int bus)
258: {
1.1.1.7 ! root 259: struct pci_device *pci;
! 260: foreachpci(pci) {
! 261: u8 pci_bus = pci_bdf_to_bus(pci->bdf);
! 262: if (pci_bus < bus)
! 263: continue;
! 264: if (pci_bus > bus)
! 265: break;
! 266: pci_bios_init_device(pci);
1.1 root 267: }
268: }
269:
1.1.1.4 root 270: static void
271: pci_bios_init_bus_rec(int bus, u8 *pci_bus)
272: {
1.1.1.7 ! root 273: int bdf;
1.1.1.4 root 274: u16 class;
275:
276: dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus);
277:
278: /* prevent accidental access to unintended devices */
1.1.1.7 ! root 279: foreachbdf(bdf, bus) {
1.1.1.4 root 280: class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
281: if (class == PCI_CLASS_BRIDGE_PCI) {
282: pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255);
283: pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0);
284: }
285: }
286:
1.1.1.7 ! root 287: foreachbdf(bdf, bus) {
1.1.1.4 root 288: class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
289: if (class != PCI_CLASS_BRIDGE_PCI) {
290: continue;
291: }
292: dprintf(1, "PCI: %s bdf = 0x%x\n", __func__, bdf);
293:
294: u8 pribus = pci_config_readb(bdf, PCI_PRIMARY_BUS);
295: if (pribus != bus) {
296: dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus);
297: pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus);
298: } else {
299: dprintf(1, "PCI: primary bus = 0x%x\n", pribus);
300: }
301:
302: u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
303: (*pci_bus)++;
304: if (*pci_bus != secbus) {
305: dprintf(1, "PCI: secondary bus = 0x%x -> 0x%x\n",
306: secbus, *pci_bus);
307: secbus = *pci_bus;
308: pci_config_writeb(bdf, PCI_SECONDARY_BUS, secbus);
309: } else {
310: dprintf(1, "PCI: secondary bus = 0x%x\n", secbus);
311: }
312:
313: /* set to max for access to all subordinate buses.
314: later set it to accurate value */
315: u8 subbus = pci_config_readb(bdf, PCI_SUBORDINATE_BUS);
316: pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 255);
317:
318: pci_bios_init_bus_rec(secbus, pci_bus);
319:
320: if (subbus != *pci_bus) {
321: dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
322: subbus, *pci_bus);
323: subbus = *pci_bus;
324: } else {
325: dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
326: }
327: pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus);
328: }
329: }
330:
331: static void
332: pci_bios_init_bus(void)
333: {
334: u8 pci_bus = 0;
335: pci_bios_init_bus_rec(0 /* host bus */, &pci_bus);
1.1.1.7 ! root 336: busses_count = pci_bus + 1;
! 337: }
! 338:
! 339: static void pci_bios_bus_get_bar(struct pci_bus *bus, int bdf, int bar,
! 340: u32 *val, u32 *size)
! 341: {
! 342: u32 ofs = pci_bar(bdf, bar);
! 343: u32 old = pci_config_readl(bdf, ofs);
! 344: u32 mask;
! 345:
! 346: if (bar == PCI_ROM_SLOT) {
! 347: mask = PCI_ROM_ADDRESS_MASK;
! 348: pci_config_writel(bdf, ofs, mask);
! 349: } else {
! 350: if (old & PCI_BASE_ADDRESS_SPACE_IO)
! 351: mask = PCI_BASE_ADDRESS_IO_MASK;
! 352: else
! 353: mask = PCI_BASE_ADDRESS_MEM_MASK;
! 354: pci_config_writel(bdf, ofs, ~0);
! 355: }
! 356: *val = pci_config_readl(bdf, ofs);
! 357: pci_config_writel(bdf, ofs, old);
! 358: *size = (~(*val & mask)) + 1;
! 359: }
! 360:
! 361: static void pci_bios_bus_reserve(struct pci_bus *bus, int type, u32 size)
! 362: {
! 363: u32 index;
! 364:
! 365: index = pci_size_to_index(size, type);
! 366: size = pci_index_to_size(index, type);
! 367: bus->r[type].count[index]++;
! 368: bus->r[type].sum += size;
! 369: if (bus->r[type].max < size)
! 370: bus->r[type].max = size;
! 371: }
! 372:
! 373: static u32 pci_bios_bus_get_addr(struct pci_bus *bus, int type, u32 size)
! 374: {
! 375: u32 index, addr;
! 376:
! 377: index = pci_size_to_index(size, type);
! 378: addr = bus->r[type].bases[index];
! 379: bus->r[type].bases[index] += pci_index_to_size(index, type);
! 380: return addr;
! 381: }
! 382:
! 383: static void pci_bios_check_device(struct pci_bus *bus, struct pci_device *dev)
! 384: {
! 385: u16 bdf = dev->bdf;
! 386: u32 limit;
! 387: int i,type;
! 388:
! 389: if (dev->class == PCI_CLASS_BRIDGE_PCI) {
! 390: if (dev->secondary_bus >= busses_count) {
! 391: /* should never trigger */
! 392: dprintf(1, "PCI: bus count too small (%d), skipping bus #%d\n",
! 393: busses_count, dev->secondary_bus);
! 394: return;
! 395: }
! 396: struct pci_bus *s = busses + dev->secondary_bus;
! 397: pci_bios_check_device_in_bus(dev->secondary_bus);
! 398: for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
! 399: limit = (type == PCI_REGION_TYPE_IO) ?
! 400: PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
! 401: s->r[type].size = s->r[type].sum;
! 402: if (s->r[type].size < limit)
! 403: s->r[type].size = limit;
! 404: s->r[type].size = pci_size_roundup(s->r[type].size);
! 405: pci_bios_bus_reserve(bus, type, s->r[type].size);
! 406: }
! 407: dprintf(1, "PCI: secondary bus %d sizes: io %x, mem %x, prefmem %x\n",
! 408: dev->secondary_bus,
! 409: s->r[PCI_REGION_TYPE_IO].size,
! 410: s->r[PCI_REGION_TYPE_MEM].size,
! 411: s->r[PCI_REGION_TYPE_PREFMEM].size);
! 412: return;
! 413: }
! 414:
! 415: for (i = 0; i < PCI_NUM_REGIONS; i++) {
! 416: u32 val, size;
! 417: pci_bios_bus_get_bar(bus, bdf, i, &val, &size);
! 418: if (val == 0) {
! 419: continue;
! 420: }
! 421: pci_bios_bus_reserve(bus, pci_addr_to_type(val), size);
! 422: dev->bars[i].addr = val;
! 423: dev->bars[i].size = size;
! 424: dev->bars[i].is64 = (!(val & PCI_BASE_ADDRESS_SPACE_IO) &&
! 425: (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64);
! 426:
! 427: if (dev->bars[i].is64) {
! 428: i++;
! 429: }
! 430: }
! 431: }
! 432:
! 433: static void pci_bios_map_device(struct pci_bus *bus, struct pci_device *dev)
! 434: {
! 435: u16 bdf = dev->bdf;
! 436: int type, i;
! 437:
! 438: if (dev->class == PCI_CLASS_BRIDGE_PCI) {
! 439: if (dev->secondary_bus >= busses_count) {
! 440: return;
! 441: }
! 442: struct pci_bus *s = busses + dev->secondary_bus;
! 443: u32 base, limit;
! 444:
! 445: for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
! 446: s->r[type].base = pci_bios_bus_get_addr(bus, type, s->r[type].size);
! 447: }
! 448: dprintf(1, "PCI: init bases bus %d (secondary)\n", dev->secondary_bus);
! 449: pci_bios_init_bus_bases(s);
! 450:
! 451: base = s->r[PCI_REGION_TYPE_IO].base;
! 452: limit = base + s->r[PCI_REGION_TYPE_IO].size - 1;
! 453: pci_config_writeb(bdf, PCI_IO_BASE, base >> PCI_IO_SHIFT);
! 454: pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
! 455: pci_config_writeb(bdf, PCI_IO_LIMIT, limit >> PCI_IO_SHIFT);
! 456: pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
! 457:
! 458: base = s->r[PCI_REGION_TYPE_MEM].base;
! 459: limit = base + s->r[PCI_REGION_TYPE_MEM].size - 1;
! 460: pci_config_writew(bdf, PCI_MEMORY_BASE, base >> PCI_MEMORY_SHIFT);
! 461: pci_config_writew(bdf, PCI_MEMORY_LIMIT, limit >> PCI_MEMORY_SHIFT);
! 462:
! 463: base = s->r[PCI_REGION_TYPE_PREFMEM].base;
! 464: limit = base + s->r[PCI_REGION_TYPE_PREFMEM].size - 1;
! 465: pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, base >> PCI_PREF_MEMORY_SHIFT);
! 466: pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, limit >> PCI_PREF_MEMORY_SHIFT);
! 467: pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, 0);
! 468: pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, 0);
! 469:
! 470: pci_bios_map_device_in_bus(dev->secondary_bus);
! 471: return;
! 472: }
! 473:
! 474: for (i = 0; i < PCI_NUM_REGIONS; i++) {
! 475: u32 addr;
! 476: if (dev->bars[i].addr == 0) {
! 477: continue;
! 478: }
! 479:
! 480: addr = pci_bios_bus_get_addr(bus, pci_addr_to_type(dev->bars[i].addr),
! 481: dev->bars[i].size);
! 482: dprintf(1, " bar %d, addr %x, size %x [%s]\n",
! 483: i, addr, dev->bars[i].size,
! 484: dev->bars[i].addr & PCI_BASE_ADDRESS_SPACE_IO ? "io" : "mem");
! 485: pci_set_io_region_addr(bdf, i, addr);
! 486:
! 487: if (dev->bars[i].is64) {
! 488: i++;
! 489: }
! 490: }
! 491: }
! 492:
! 493: static void pci_bios_check_device_in_bus(int bus)
! 494: {
! 495: struct pci_device *pci;
! 496:
! 497: dprintf(1, "PCI: check devices bus %d\n", bus);
! 498: foreachpci(pci) {
! 499: if (pci_bdf_to_bus(pci->bdf) != bus)
! 500: continue;
! 501: pci_bios_check_device(&busses[bus], pci);
! 502: }
! 503: }
! 504:
! 505: static void pci_bios_map_device_in_bus(int bus)
! 506: {
! 507: struct pci_device *pci;
! 508:
! 509: foreachpci(pci) {
! 510: if (pci_bdf_to_bus(pci->bdf) != bus)
! 511: continue;
! 512: dprintf(1, "PCI: map device bus %d, bfd 0x%x\n", bus, pci->bdf);
! 513: pci_bios_map_device(&busses[bus], pci);
! 514: }
! 515: }
! 516:
! 517: static void pci_bios_init_bus_bases(struct pci_bus *bus)
! 518: {
! 519: u32 base, newbase, size;
! 520: int type, i;
! 521:
! 522: for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
! 523: dprintf(1, " type %s max %x sum %x base %x\n", region_type_name[type],
! 524: bus->r[type].max, bus->r[type].sum, bus->r[type].base);
! 525: base = bus->r[type].base;
! 526: for (i = ARRAY_SIZE(bus->r[type].count)-1; i >= 0; i--) {
! 527: size = pci_index_to_size(i, type);
! 528: if (!bus->r[type].count[i])
! 529: continue;
! 530: newbase = base + size * bus->r[type].count[i];
! 531: dprintf(1, " size %8x: %d bar(s), %8x -> %8x\n",
! 532: size, bus->r[type].count[i], base, newbase - 1);
! 533: bus->r[type].bases[i] = base;
! 534: base = newbase;
! 535: }
! 536: }
! 537: }
! 538:
! 539: #define ROOT_BASE(top, sum, align) ALIGN_DOWN((top)-(sum),(align))
! 540:
! 541: static int pci_bios_init_root_regions(u32 start, u32 end)
! 542: {
! 543: struct pci_bus *bus = &busses[0];
! 544:
! 545: bus->r[PCI_REGION_TYPE_IO].base = 0xc000;
! 546:
! 547: if (bus->r[PCI_REGION_TYPE_MEM].sum < bus->r[PCI_REGION_TYPE_PREFMEM].sum) {
! 548: bus->r[PCI_REGION_TYPE_MEM].base =
! 549: ROOT_BASE(end,
! 550: bus->r[PCI_REGION_TYPE_MEM].sum,
! 551: bus->r[PCI_REGION_TYPE_MEM].max);
! 552: bus->r[PCI_REGION_TYPE_PREFMEM].base =
! 553: ROOT_BASE(bus->r[PCI_REGION_TYPE_MEM].base,
! 554: bus->r[PCI_REGION_TYPE_PREFMEM].sum,
! 555: bus->r[PCI_REGION_TYPE_PREFMEM].max);
! 556: if (bus->r[PCI_REGION_TYPE_PREFMEM].base >= start) {
! 557: return 0;
! 558: }
! 559: } else {
! 560: bus->r[PCI_REGION_TYPE_PREFMEM].base =
! 561: ROOT_BASE(end,
! 562: bus->r[PCI_REGION_TYPE_PREFMEM].sum,
! 563: bus->r[PCI_REGION_TYPE_PREFMEM].max);
! 564: bus->r[PCI_REGION_TYPE_MEM].base =
! 565: ROOT_BASE(bus->r[PCI_REGION_TYPE_PREFMEM].base,
! 566: bus->r[PCI_REGION_TYPE_MEM].sum,
! 567: bus->r[PCI_REGION_TYPE_MEM].max);
! 568: if (bus->r[PCI_REGION_TYPE_MEM].base >= start) {
! 569: return 0;
! 570: }
! 571: }
! 572: return -1;
1.1.1.4 root 573: }
574:
1.1 root 575: void
576: pci_setup(void)
577: {
1.1.1.7 ! root 578: if (CONFIG_COREBOOT || usingXen()) {
! 579: // PCI setup already done by coreboot or Xen - just do probe.
! 580: pci_probe();
1.1 root 581: return;
1.1.1.7 ! root 582: }
1.1 root 583:
584: dprintf(3, "pci setup\n");
585:
1.1.1.7 ! root 586: u32 start = BUILD_PCIMEM_START;
! 587: u32 end = BUILD_PCIMEM_END;
1.1.1.4 root 588:
1.1.1.7 ! root 589: dprintf(1, "=== PCI bus & bridge init ===\n");
1.1.1.4 root 590: pci_bios_init_bus();
1.1 root 591:
1.1.1.7 ! root 592: dprintf(1, "=== PCI device probing ===\n");
! 593: pci_probe();
! 594:
! 595: dprintf(1, "=== PCI new allocation pass #1 ===\n");
! 596: busses = malloc_tmp(sizeof(*busses) * busses_count);
! 597: memset(busses, 0, sizeof(*busses) * busses_count);
! 598: pci_bios_check_device_in_bus(0 /* host bus */);
! 599: if (pci_bios_init_root_regions(start, end) != 0) {
! 600: panic("PCI: out of address space\n");
1.1 root 601: }
1.1.1.7 ! root 602:
! 603: dprintf(1, "=== PCI new allocation pass #2 ===\n");
! 604: dprintf(1, "PCI: init bases bus 0 (primary)\n");
! 605: pci_bios_init_bus_bases(&busses[0]);
! 606: pci_bios_map_device_in_bus(0 /* host bus */);
! 607:
1.1.1.4 root 608: pci_bios_init_device_in_bus(0 /* host bus */);
1.1.1.7 ! root 609:
! 610: struct pci_device *pci;
! 611: foreachpci(pci) {
! 612: pci_init_device(pci_isa_bridge_tbl, pci, NULL);
! 613: }
! 614:
! 615: free(busses);
! 616: busses_count = 0;
1.1 root 617: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.