summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2005-12-30 19:28:26 +0000
committerimp <imp@FreeBSD.org>2005-12-30 19:28:26 +0000
commit8b103956352bbf908cdf84ca9e7310de2bd06bbe (patch)
tree139e605050b33331064d95ea7d0126216817ed0c
parent5a187111138f2534b84bbe17deb1b321c5426b2b (diff)
downloadFreeBSD-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).
-rw-r--r--sys/dev/pci/pci.c90
-rw-r--r--sys/dev/pci/pci_private.h2
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, &reg, start, end, count, 0);
+ res = resource_list_alloc(rl, bus, dev, type, &reg, 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);
OpenPOWER on IntegriCloud