diff options
author | imp <imp@FreeBSD.org> | 2005-12-30 19:28:26 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2005-12-30 19:28:26 +0000 |
commit | 8b103956352bbf908cdf84ca9e7310de2bd06bbe (patch) | |
tree | 139e605050b33331064d95ea7d0126216817ed0c /sys/dev/pci | |
parent | 5a187111138f2534b84bbe17deb1b321c5426b2b (diff) | |
download | FreeBSD-src-8b103956352bbf908cdf84ca9e7310de2bd06bbe.zip FreeBSD-src-8b103956352bbf908cdf84ca9e7310de2bd06bbe.tar.gz |
Expose pci_add_resources to the outside world, add a 'force' flag to
force allocation of unallocated BARs (cardbus uses this to preallocate
everything). Add a prefetchmask to allow for busses that get prefetch
hints to set them. Addjust pci_add_map and pci_ata_maps to take a new
force flag which pci_add_resources will pass in. Implement 'force' in
pci_add_map. Write new value of allocated resource into the bar, if
the allocation succeeded (we should have done this before, but with
the new force the bug was very obvious).
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/pci.c | 90 | ||||
-rw-r--r-- | sys/dev/pci/pci_private.h | 2 |
2 files changed, 63 insertions, 29 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 9db25d0..eff9290 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -80,9 +80,7 @@ static void pci_assign_interrupt(device_t bus, device_t dev, int force_route); static int pci_add_map(device_t pcib, device_t bus, device_t dev, int b, int s, int f, int reg, - struct resource_list *rl); -static void pci_add_resources(device_t pcib, device_t bus, - device_t dev); + struct resource_list *rl, int force, int prefetch); static int pci_probe(device_t dev); static int pci_attach(device_t dev); static void pci_load_vendor_data(void); @@ -830,7 +828,8 @@ pci_memen(device_t pcib, int b, int s, int f) */ static int pci_add_map(device_t pcib, device_t bus, device_t dev, - int b, int s, int f, int reg, struct resource_list *rl) + int b, int s, int f, int reg, struct resource_list *rl, int force, + int prefetch) { uint32_t map; uint64_t base; @@ -841,6 +840,7 @@ pci_add_map(device_t pcib, device_t bus, device_t dev, uint16_t cmd; int type; int barlen; + struct resource *res; map = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4); PCIB_WRITE_CONFIG(pcib, b, s, f, reg, 0xffffffff, 4); @@ -889,14 +889,20 @@ pci_add_map(device_t pcib, device_t bus, device_t dev, /* * If base is 0, then we have problems. It is best to ignore * such entries for the moment. These will be allocated later if - * the driver specifically requests them. + * the driver specifically requests them. However, some + * removable busses look better when all resources are allocated, + * so allow '0' to be overriden. * * Similarly treat maps whose values is the same as the test value * read back. These maps have had all f's written to them by the * BIOS in an attempt to disable the resources. */ - if (base == 0 || map == testval) + if (!force && (base == 0 || map == testval)) { + if (bootverbose) + printf("ignored rid %#x: base %#llx map %#x testval %#x\n", + reg, base, map, testval); return (barlen); + } /* * This code theoretically does the right thing, but has @@ -924,16 +930,28 @@ pci_add_map(device_t pcib, device_t bus, device_t dev, return (barlen); } - start = base; - end = base + (1 << ln2size) - 1; count = 1 << ln2size; + if (base == 0 || base == pci_mapbase(testval)) { + start = 0; /* Let the parent deside */ + end = ~0ULL; + } else { + start = base; + end = base + (1 << ln2size) - 1; + } resource_list_add(rl, type, reg, start, end, count); /* * Not quite sure what to do on failure of allocating the resource * since I can postulate several right answers. */ - resource_list_alloc(rl, bus, dev, type, ®, start, end, count, 0); + res = resource_list_alloc(rl, bus, dev, type, ®, start, end, count, + prefetch ? RF_PREFETCHABLE : 0); + if (res == NULL) + printf("alloc failed\n"); + else + printf("Allocated for %#x: start %#lx end %#lx\n", reg, rman_get_start(res), rman_get_end(res)); + if (res != NULL) + pci_write_config(dev, reg, rman_get_start(res), 4); return (barlen); } @@ -946,7 +964,7 @@ pci_add_map(device_t pcib, device_t bus, device_t dev, */ static void pci_ata_maps(device_t pcib, device_t bus, device_t dev, int b, - int s, int f, struct resource_list *rl) + int s, int f, struct resource_list *rl, int force, uint32_t prefetchmask) { int rid, type, progif; #if 0 @@ -963,29 +981,39 @@ pci_ata_maps(device_t pcib, device_t bus, device_t dev, int b, progif = pci_read_config(dev, PCIR_PROGIF, 1); type = SYS_RES_IOPORT; if (progif & PCIP_STORAGE_IDE_MODEPRIM) { - pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(0), rl); - pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(1), rl); + pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(0), rl, force, + prefetchmask & (1 << 0)); + pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(1), rl, force, + prefetchmask & (1 << 1)); } else { rid = PCIR_BAR(0); resource_list_add(rl, type, rid, 0x1f0, 0x1f7, 8); - resource_list_alloc(rl, bus, dev, type, &rid, 0x1f0, 0x1f7,8,0); + resource_list_alloc(rl, bus, dev, type, &rid, 0x1f0, 0x1f7, 8, + 0); rid = PCIR_BAR(1); resource_list_add(rl, type, rid, 0x3f6, 0x3f6, 1); - resource_list_alloc(rl, bus, dev, type, &rid, 0x3f6, 0x3f6,1,0); + resource_list_alloc(rl, bus, dev, type, &rid, 0x3f6, 0x3f6, 1, + 0); } if (progif & PCIP_STORAGE_IDE_MODESEC) { - pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(2), rl); - pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(3), rl); + pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(2), rl, force, + prefetchmask & (1 << 2)); + pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(3), rl, force, + prefetchmask & (1 << 3)); } else { rid = PCIR_BAR(2); resource_list_add(rl, type, rid, 0x170, 0x177, 8); - resource_list_alloc(rl, bus, dev, type, &rid, 0x170, 0x177,8,0); + resource_list_alloc(rl, bus, dev, type, &rid, 0x170, 0x177, 8, + 0); rid = PCIR_BAR(3); resource_list_add(rl, type, rid, 0x376, 0x376, 1); - resource_list_alloc(rl, bus, dev, type, &rid, 0x376, 0x376,1,0); + resource_list_alloc(rl, bus, dev, type, &rid, 0x376, 0x376, 1, + 0); } - pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(4), rl); - pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(5), rl); + pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(4), rl, force, + prefetchmask & (1 << 4)); + pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(5), rl, force, + prefetchmask & (1 << 5)); } static void @@ -1035,15 +1063,18 @@ pci_assign_interrupt(device_t bus, device_t dev, int force_route) resource_list_add(&dinfo->resources, SYS_RES_IRQ, 0, irq, irq, 1); } -static void -pci_add_resources(device_t pcib, device_t bus, device_t dev) +void +pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask) { + device_t pcib; struct pci_devinfo *dinfo = device_get_ivars(dev); pcicfgregs *cfg = &dinfo->cfg; struct resource_list *rl = &dinfo->resources; struct pci_quirk *q; int b, i, f, s; + pcib = device_get_parent(bus); + b = cfg->bus; s = cfg->slot; f = cfg->func; @@ -1052,16 +1083,20 @@ pci_add_resources(device_t pcib, device_t bus, device_t dev) if ((pci_get_class(dev) == PCIC_STORAGE) && (pci_get_subclass(dev) == PCIS_STORAGE_IDE) && (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV)) - pci_ata_maps(pcib, bus, dev, b, s, f, rl); + pci_ata_maps(pcib, bus, dev, b, s, f, rl, force, prefetchmask); else for (i = 0; i < cfg->nummaps;) i += pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(i), - rl); + rl, force, prefetchmask & (1 << i)); + /* + * Add additional, quirked resources. + */ for (q = &pci_quirks[0]; q->devid; q++) { if (q->devid == ((cfg->device << 16) | cfg->vendor) && q->type == PCI_QUIRK_MAP_REG) - pci_add_map(pcib, bus, dev, b, s, f, q->arg1, rl); + pci_add_map(pcib, bus, dev, b, s, f, q->arg1, rl, + force, 0); } if (cfg->intpin > 0 && PCI_INTERRUPT_VALID(cfg->intline)) { @@ -1115,16 +1150,13 @@ pci_add_children(device_t dev, int busno, size_t dinfo_size) void pci_add_child(device_t bus, struct pci_devinfo *dinfo) { - device_t pcib; - - pcib = device_get_parent(bus); dinfo->cfg.dev = device_add_child(bus, NULL, -1); device_set_ivars(dinfo->cfg.dev, dinfo); resource_list_init(&dinfo->resources); pci_cfg_save(dinfo->cfg.dev, dinfo, 0); pci_cfg_restore(dinfo->cfg.dev, dinfo); pci_print_verbose(dinfo); - pci_add_resources(pcib, bus, dinfo->cfg.dev); + pci_add_resources(bus, dinfo->cfg.dev, 0, 0); } static int diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h index 65884cc..06beee9 100644 --- a/sys/dev/pci/pci_private.h +++ b/sys/dev/pci/pci_private.h @@ -41,6 +41,8 @@ extern devclass_t pci_devclass; void pci_add_children(device_t dev, int busno, size_t dinfo_size); void pci_add_child(device_t bus, struct pci_devinfo *dinfo); +void pci_add_resources(device_t bus, device_t dev, int force, + uint32_t prefetchmask); void pci_driver_added(device_t dev, driver_t *driver); int pci_print_child(device_t dev, device_t child); void pci_probe_nomatch(device_t dev, device_t child); |