Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/pci/pci_pci.c
Show First 20 Lines • Show All 241 Lines • ▼ Show 20 Lines | pcib_is_isa_range(struct pcib_softc *sc, rman_res_t start, rman_res_t end, | ||||
next_alias = (start & ~0x3fful) | 0x100; | next_alias = (start & ~0x3fful) | 0x100; | ||||
if (next_alias <= end) | if (next_alias <= end) | ||||
goto alias; | goto alias; | ||||
return (0); | return (0); | ||||
alias: | alias: | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"I/O range %#lx-%#lx overlaps with an ISA alias\n", start, | "I/O range %#jx-%#jx overlaps with an ISA alias\n", start, | ||||
end); | end); | ||||
return (1); | return (1); | ||||
} | } | ||||
static void | static void | ||||
pcib_add_window_resources(struct pcib_window *w, struct resource **res, | pcib_add_window_resources(struct pcib_window *w, struct resource **res, | ||||
int count) | int count) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | alloc_ranges(rman_res_t start, rman_res_t end, void *arg) | ||||
as = arg; | as = arg; | ||||
if (as->error != 0) | if (as->error != 0) | ||||
return; | return; | ||||
w = &as->sc->io; | w = &as->sc->io; | ||||
rid = w->reg; | rid = w->reg; | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(as->sc->dev, | device_printf(as->sc->dev, | ||||
"allocating non-ISA range %#lx-%#lx\n", start, end); | "allocating non-ISA range %#jx-%#jx\n", start, end); | ||||
as->res[as->count] = bus_alloc_resource(as->sc->dev, SYS_RES_IOPORT, | as->res[as->count] = bus_alloc_resource(as->sc->dev, SYS_RES_IOPORT, | ||||
&rid, start, end, end - start + 1, 0); | &rid, start, end, end - start + 1, 0); | ||||
if (as->res[as->count] == NULL) | if (as->res[as->count] == NULL) | ||||
as->error = ENXIO; | as->error = ENXIO; | ||||
else | else | ||||
as->count++; | as->count++; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 265 Lines • ▼ Show 20 Lines | pcib_suballoc_bus(struct pcib_secbus *bus, device_t child, int *rid, | ||||
res = rman_reserve_resource(&bus->rman, start, end, count, flags, | res = rman_reserve_resource(&bus->rman, start, end, count, flags, | ||||
child); | child); | ||||
if (res == NULL) | if (res == NULL) | ||||
return (NULL); | return (NULL); | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(bus->dev, | device_printf(bus->dev, | ||||
"allocated bus range (%lu-%lu) for rid %d of %s\n", | "allocated bus range (%ju-%ju) for rid %d of %s\n", | ||||
rman_get_start(res), rman_get_end(res), *rid, | rman_get_start(res), rman_get_end(res), *rid, | ||||
pcib_child_name(child)); | pcib_child_name(child)); | ||||
rman_set_rid(res, *rid); | rman_set_rid(res, *rid); | ||||
return (res); | return (res); | ||||
} | } | ||||
/* | /* | ||||
* Attempt to grow the secondary bus range. This is much simpler than | * Attempt to grow the secondary bus range. This is much simpler than | ||||
* for I/O windows as the range can only be grown by increasing | * for I/O windows as the range can only be grown by increasing | ||||
* subbus. | * subbus. | ||||
*/ | */ | ||||
static int | static int | ||||
pcib_grow_subbus(struct pcib_secbus *bus, rman_res_t new_end) | pcib_grow_subbus(struct pcib_secbus *bus, rman_res_t new_end) | ||||
{ | { | ||||
rman_res_t old_end; | rman_res_t old_end; | ||||
int error; | int error; | ||||
old_end = rman_get_end(bus->res); | old_end = rman_get_end(bus->res); | ||||
KASSERT(new_end > old_end, ("attempt to shrink subbus")); | KASSERT(new_end > old_end, ("attempt to shrink subbus")); | ||||
error = bus_adjust_resource(bus->dev, PCI_RES_BUS, bus->res, | error = bus_adjust_resource(bus->dev, PCI_RES_BUS, bus->res, | ||||
rman_get_start(bus->res), new_end); | rman_get_start(bus->res), new_end); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(bus->dev, "grew bus range to %lu-%lu\n", | device_printf(bus->dev, "grew bus range to %ju-%ju\n", | ||||
rman_get_start(bus->res), rman_get_end(bus->res)); | rman_get_start(bus->res), rman_get_end(bus->res)); | ||||
error = rman_manage_region(&bus->rman, old_end + 1, | error = rman_manage_region(&bus->rman, old_end + 1, | ||||
rman_get_end(bus->res)); | rman_get_end(bus->res)); | ||||
if (error) | if (error) | ||||
panic("Failed to add resource to rman"); | panic("Failed to add resource to rman"); | ||||
bus->sub = rman_get_end(bus->res); | bus->sub = rman_get_end(bus->res); | ||||
pci_write_config(bus->dev, bus->sub_reg, bus->sub, 1); | pci_write_config(bus->dev, bus->sub_reg, bus->sub, 1); | ||||
return (0); | return (0); | ||||
Show All 31 Lines | pcib_alloc_subbus(struct pcib_secbus *bus, device_t child, int *rid, | ||||
* succeeds. | * succeeds. | ||||
*/ | */ | ||||
if (new_end > end) | if (new_end > end) | ||||
return (NULL); | return (NULL); | ||||
/* Finally, attempt to grow the existing resource. */ | /* Finally, attempt to grow the existing resource. */ | ||||
if (bootverbose) { | if (bootverbose) { | ||||
device_printf(bus->dev, | device_printf(bus->dev, | ||||
"attempting to grow bus range for %lu buses\n", count); | "attempting to grow bus range for %ju buses\n", count); | ||||
printf("\tback candidate range: %lu-%lu\n", start_free, | printf("\tback candidate range: %ju-%ju\n", start_free, | ||||
new_end); | new_end); | ||||
} | } | ||||
if (pcib_grow_subbus(bus, new_end) == 0) | if (pcib_grow_subbus(bus, new_end) == 0) | ||||
return (pcib_suballoc_bus(bus, child, rid, start, end, count, | return (pcib_suballoc_bus(bus, child, rid, start, end, count, | ||||
flags)); | flags)); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 462 Lines • ▼ Show 20 Lines | pcib_suballoc_resource(struct pcib_softc *sc, struct pcib_window *w, | ||||
res = rman_reserve_resource(&w->rman, start, end, count, | res = rman_reserve_resource(&w->rman, start, end, count, | ||||
flags & ~RF_ACTIVE, child); | flags & ~RF_ACTIVE, child); | ||||
if (res == NULL) | if (res == NULL) | ||||
return (NULL); | return (NULL); | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"allocated %s range (%#lx-%#lx) for rid %x of %s\n", | "allocated %s range (%#jx-%#jx) for rid %x of %s\n", | ||||
w->name, rman_get_start(res), rman_get_end(res), *rid, | w->name, rman_get_start(res), rman_get_end(res), *rid, | ||||
pcib_child_name(child)); | pcib_child_name(child)); | ||||
rman_set_rid(res, *rid); | rman_set_rid(res, *rid); | ||||
/* | /* | ||||
* If the resource should be active, pass that request up the | * If the resource should be active, pass that request up the | ||||
* tree. This assumes the parent drivers can handle | * tree. This assumes the parent drivers can handle | ||||
* activating sub-allocated resources. | * activating sub-allocated resources. | ||||
▲ Show 20 Lines • Show All 210 Lines • ▼ Show 20 Lines | pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type, | ||||
* aligned space for this resource. | * aligned space for this resource. | ||||
*/ | */ | ||||
if (w->res == NULL) { | if (w->res == NULL) { | ||||
error = pcib_alloc_new_window(sc, w, type, start, end, count, | error = pcib_alloc_new_window(sc, w, type, start, end, count, | ||||
flags); | flags); | ||||
if (error) { | if (error) { | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"failed to allocate initial %s window (%#lx-%#lx,%#lx)\n", | "failed to allocate initial %s window (%#jx-%#jx,%#jx)\n", | ||||
w->name, start, end, count); | w->name, start, end, count); | ||||
return (error); | return (error); | ||||
} | } | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"allocated initial %s window of %#jx-%#jx\n", | "allocated initial %s window of %#jx-%#jx\n", | ||||
w->name, (uintmax_t)w->base, (uintmax_t)w->limit); | w->name, (uintmax_t)w->base, (uintmax_t)w->limit); | ||||
goto updatewin; | goto updatewin; | ||||
Show All 15 Lines | pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type, | ||||
* non-alias ranges when it is grown in either direction. | * non-alias ranges when it is grown in either direction. | ||||
* | * | ||||
* XXX: Special case: if w->res is completely empty and the | * XXX: Special case: if w->res is completely empty and the | ||||
* request size is larger than w->res, we should find the | * request size is larger than w->res, we should find the | ||||
* optimal aligned buffer containing w->res and allocate that. | * optimal aligned buffer containing w->res and allocate that. | ||||
*/ | */ | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"attempting to grow %s window for (%#lx-%#lx,%#lx)\n", | "attempting to grow %s window for (%#jx-%#jx,%#jx)\n", | ||||
w->name, start, end, count); | w->name, start, end, count); | ||||
align = (rman_res_t)1 << RF_ALIGNMENT(flags); | align = (rman_res_t)1 << RF_ALIGNMENT(flags); | ||||
if (start < w->base) { | if (start < w->base) { | ||||
if (rman_first_free_region(&w->rman, &start_free, &end_free) != | if (rman_first_free_region(&w->rman, &start_free, &end_free) != | ||||
0 || start_free != w->base) | 0 || start_free != w->base) | ||||
end_free = w->base; | end_free = w->base; | ||||
if (end_free > end) | if (end_free > end) | ||||
end_free = end + 1; | end_free = end + 1; | ||||
/* Move end_free down until it is properly aligned. */ | /* Move end_free down until it is properly aligned. */ | ||||
end_free &= ~(align - 1); | end_free &= ~(align - 1); | ||||
end_free--; | end_free--; | ||||
front = end_free - (count - 1); | front = end_free - (count - 1); | ||||
/* | /* | ||||
* The resource would now be allocated at (front, | * The resource would now be allocated at (front, | ||||
* end_free). Ensure that fits in the (start, end) | * end_free). Ensure that fits in the (start, end) | ||||
* bounds. end_free is checked above. If 'front' is | * bounds. end_free is checked above. If 'front' is | ||||
* ok, ensure it is properly aligned for this window. | * ok, ensure it is properly aligned for this window. | ||||
* Also check for underflow. | * Also check for underflow. | ||||
*/ | */ | ||||
if (front >= start && front <= end_free) { | if (front >= start && front <= end_free) { | ||||
if (bootverbose) | if (bootverbose) | ||||
printf("\tfront candidate range: %#lx-%#lx\n", | printf("\tfront candidate range: %#jx-%#jx\n", | ||||
front, end_free); | front, end_free); | ||||
front &= ~wmask; | front &= ~wmask; | ||||
front = w->base - front; | front = w->base - front; | ||||
} else | } else | ||||
front = 0; | front = 0; | ||||
} else | } else | ||||
front = 0; | front = 0; | ||||
if (end > w->limit) { | if (end > w->limit) { | ||||
Show All 11 Lines | if (end > w->limit) { | ||||
* The resource would now be allocated at (start_free, | * The resource would now be allocated at (start_free, | ||||
* back). Ensure that fits in the (start, end) | * back). Ensure that fits in the (start, end) | ||||
* bounds. start_free is checked above. If 'back' is | * bounds. start_free is checked above. If 'back' is | ||||
* ok, ensure it is properly aligned for this window. | * ok, ensure it is properly aligned for this window. | ||||
* Also check for overflow. | * Also check for overflow. | ||||
*/ | */ | ||||
if (back <= end && start_free <= back) { | if (back <= end && start_free <= back) { | ||||
if (bootverbose) | if (bootverbose) | ||||
printf("\tback candidate range: %#lx-%#lx\n", | printf("\tback candidate range: %#jx-%#jx\n", | ||||
start_free, back); | start_free, back); | ||||
back |= wmask; | back |= wmask; | ||||
back -= w->limit; | back -= w->limit; | ||||
} else | } else | ||||
back = 0; | back = 0; | ||||
} else | } else | ||||
back = 0; | back = 0; | ||||
▲ Show 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | #if 0 | ||||
* If we overlap with the subtractive range, then | * If we overlap with the subtractive range, then | ||||
* pick the upper range to use. | * pick the upper range to use. | ||||
*/ | */ | ||||
if (start < sc->iolimit && end > sc->iobase) | if (start < sc->iolimit && end > sc->iobase) | ||||
start = sc->iolimit + 1; | start = sc->iolimit + 1; | ||||
#endif | #endif | ||||
} | } | ||||
if (end < start) { | if (end < start) { | ||||
device_printf(dev, "ioport: end (%lx) < start (%lx)\n", | device_printf(dev, "ioport: end (%jx) < start (%jx)\n", | ||||
end, start); | end, start); | ||||
start = 0; | start = 0; | ||||
end = 0; | end = 0; | ||||
ok = 0; | ok = 0; | ||||
} | } | ||||
if (!ok) { | if (!ok) { | ||||
device_printf(dev, "%s%srequested unsupported I/O " | device_printf(dev, "%s%srequested unsupported I/O " | ||||
"range 0x%lx-0x%lx (decoding 0x%x-0x%x)\n", | "range 0x%jx-0x%jx (decoding 0x%x-0x%x)\n", | ||||
name, suffix, start, end, sc->iobase, sc->iolimit); | name, suffix, start, end, sc->iobase, sc->iolimit); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(dev, | device_printf(dev, | ||||
"%s%srequested I/O range 0x%lx-0x%lx: in range\n", | "%s%srequested I/O range 0x%jx-0x%jx: in range\n", | ||||
name, suffix, start, end); | name, suffix, start, end); | ||||
break; | break; | ||||
case SYS_RES_MEMORY: | case SYS_RES_MEMORY: | ||||
ok = 0; | ok = 0; | ||||
if (pcib_is_nonprefetch_open(sc)) | if (pcib_is_nonprefetch_open(sc)) | ||||
ok = ok || (start >= sc->membase && end <= sc->memlimit); | ok = ok || (start >= sc->membase && end <= sc->memlimit); | ||||
if (pcib_is_prefetch_open(sc)) | if (pcib_is_prefetch_open(sc)) | ||||
Show All 38 Lines | #if 0 | ||||
} | } | ||||
if (pcib_is_prefetch_open(sc)) { | if (pcib_is_prefetch_open(sc)) { | ||||
if (start < sc->pmemlimit && end > sc->pmembase) | if (start < sc->pmemlimit && end > sc->pmembase) | ||||
start = sc->pmemlimit + 1; | start = sc->pmemlimit + 1; | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
if (end < start) { | if (end < start) { | ||||
device_printf(dev, "memory: end (%lx) < start (%lx)\n", | device_printf(dev, "memory: end (%jx) < start (%jx)\n", | ||||
end, start); | end, start); | ||||
start = 0; | start = 0; | ||||
end = 0; | end = 0; | ||||
ok = 0; | ok = 0; | ||||
} | } | ||||
if (!ok && bootverbose) | if (!ok && bootverbose) | ||||
device_printf(dev, | device_printf(dev, | ||||
"%s%srequested unsupported memory range %#lx-%#lx " | "%s%srequested unsupported memory range %#jx-%#jx " | ||||
"(decoding %#jx-%#jx, %#jx-%#jx)\n", | "(decoding %#jx-%#jx, %#jx-%#jx)\n", | ||||
name, suffix, start, end, | name, suffix, start, end, | ||||
(uintmax_t)sc->membase, (uintmax_t)sc->memlimit, | (uintmax_t)sc->membase, (uintmax_t)sc->memlimit, | ||||
(uintmax_t)sc->pmembase, (uintmax_t)sc->pmemlimit); | (uintmax_t)sc->pmembase, (uintmax_t)sc->pmemlimit); | ||||
if (!ok) | if (!ok) | ||||
return (NULL); | return (NULL); | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(dev,"%s%srequested memory range " | device_printf(dev,"%s%srequested memory range " | ||||
"0x%lx-0x%lx: good\n", | "0x%jx-0x%jx: good\n", | ||||
name, suffix, start, end); | name, suffix, start, end); | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
/* | /* | ||||
* Bridge is OK decoding this resource, so pass it up. | * Bridge is OK decoding this resource, so pass it up. | ||||
▲ Show 20 Lines • Show All 313 Lines • Show Last 20 Lines |