Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/pci/pci_pci.c
Show First 20 Lines • Show All 206 Lines • ▼ Show 20 Lines | pcib_write_windows(struct pcib_softc *sc, int mask) | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* This is used to reject I/O port allocations that conflict with an | * This is used to reject I/O port allocations that conflict with an | ||||
* ISA alias range. | * ISA alias range. | ||||
*/ | */ | ||||
static int | static int | ||||
pcib_is_isa_range(struct pcib_softc *sc, u_long start, u_long end, u_long count) | pcib_is_isa_range(struct pcib_softc *sc, rman_res_t start, rman_res_t end, | ||||
rman_res_t count) | |||||
{ | { | ||||
u_long next_alias; | rman_res_t next_alias; | ||||
if (!(sc->bridgectl & PCIB_BCR_ISA_ENABLE)) | if (!(sc->bridgectl & PCIB_BCR_ISA_ENABLE)) | ||||
return (0); | return (0); | ||||
/* Only check fixed ranges for overlap. */ | /* Only check fixed ranges for overlap. */ | ||||
if (start + count - 1 != end) | if (start + count - 1 != end) | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | pcib_add_window_resources(struct pcib_window *w, struct resource **res, | ||||
for (i = 0; i < count; i++) { | for (i = 0; i < count; i++) { | ||||
error = rman_manage_region(&w->rman, rman_get_start(res[i]), | error = rman_manage_region(&w->rman, rman_get_start(res[i]), | ||||
rman_get_end(res[i])); | rman_get_end(res[i])); | ||||
if (error) | if (error) | ||||
panic("Failed to add resource to rman"); | panic("Failed to add resource to rman"); | ||||
} | } | ||||
} | } | ||||
typedef void (nonisa_callback)(u_long start, u_long end, void *arg); | typedef void (nonisa_callback)(rman_res_t start, rman_res_t end, void *arg); | ||||
static void | static void | ||||
pcib_walk_nonisa_ranges(u_long start, u_long end, nonisa_callback *cb, | pcib_walk_nonisa_ranges(rman_res_t start, rman_res_t end, nonisa_callback *cb, | ||||
void *arg) | void *arg) | ||||
{ | { | ||||
u_long next_end; | rman_res_t next_end; | ||||
/* | /* | ||||
* If start is within an ISA alias range, move up to the start | * If start is within an ISA alias range, move up to the start | ||||
* of the next non-alias range. As a special case, addresses | * of the next non-alias range. As a special case, addresses | ||||
* in the range 0x000 - 0x0ff should also be skipped since | * in the range 0x000 - 0x0ff should also be skipped since | ||||
* those are used for various system I/O devices in ISA | * those are used for various system I/O devices in ISA | ||||
* systems. | * systems. | ||||
*/ | */ | ||||
Show All 11 Lines | while (start <= MIN(end, 65535)) { | ||||
start += 0x400; | start += 0x400; | ||||
} | } | ||||
if (start <= end) | if (start <= end) | ||||
cb(start, end, arg); | cb(start, end, arg); | ||||
} | } | ||||
static void | static void | ||||
count_ranges(u_long start, u_long end, void *arg) | count_ranges(rman_res_t start, rman_res_t end, void *arg) | ||||
{ | { | ||||
int *countp; | int *countp; | ||||
countp = arg; | countp = arg; | ||||
(*countp)++; | (*countp)++; | ||||
} | } | ||||
struct alloc_state { | struct alloc_state { | ||||
struct resource **res; | struct resource **res; | ||||
struct pcib_softc *sc; | struct pcib_softc *sc; | ||||
int count, error; | int count, error; | ||||
}; | }; | ||||
static void | static void | ||||
alloc_ranges(u_long start, u_long end, void *arg) | alloc_ranges(rman_res_t start, rman_res_t end, void *arg) | ||||
{ | { | ||||
struct alloc_state *as; | struct alloc_state *as; | ||||
struct pcib_window *w; | struct pcib_window *w; | ||||
int rid; | int rid; | ||||
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 %#lx-%#lx\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++; | ||||
} | } | ||||
static int | static int | ||||
pcib_alloc_nonisa_ranges(struct pcib_softc *sc, u_long start, u_long end) | pcib_alloc_nonisa_ranges(struct pcib_softc *sc, rman_res_t start, rman_res_t end) | ||||
{ | { | ||||
struct alloc_state as; | struct alloc_state as; | ||||
int i, new_count; | int i, new_count; | ||||
/* First, see how many ranges we need. */ | /* First, see how many ranges we need. */ | ||||
new_count = 0; | new_count = 0; | ||||
pcib_walk_nonisa_ranges(start, end, count_ranges, &new_count); | pcib_walk_nonisa_ranges(start, end, count_ranges, &new_count); | ||||
▲ Show 20 Lines • Show All 244 Lines • ▼ Show 20 Lines | if (error) | ||||
panic("Failed to add resource to rman"); | panic("Failed to add resource to rman"); | ||||
bus->sec = rman_get_start(bus->res); | bus->sec = rman_get_start(bus->res); | ||||
bus->sub = rman_get_end(bus->res); | bus->sub = rman_get_end(bus->res); | ||||
} | } | ||||
} | } | ||||
static struct resource * | static struct resource * | ||||
pcib_suballoc_bus(struct pcib_secbus *bus, device_t child, int *rid, | pcib_suballoc_bus(struct pcib_secbus *bus, device_t child, int *rid, | ||||
u_long start, u_long end, u_long count, u_int flags) | rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) | ||||
{ | { | ||||
struct resource *res; | struct resource *res; | ||||
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 (%lu-%lu) 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, u_long new_end) | pcib_grow_subbus(struct pcib_secbus *bus, rman_res_t new_end) | ||||
{ | { | ||||
u_long 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 %lu-%lu\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); | ||||
} | } | ||||
struct resource * | struct resource * | ||||
pcib_alloc_subbus(struct pcib_secbus *bus, device_t child, int *rid, | pcib_alloc_subbus(struct pcib_secbus *bus, device_t child, int *rid, | ||||
u_long start, u_long end, u_long count, u_int flags) | rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) | ||||
{ | { | ||||
struct resource *res; | struct resource *res; | ||||
u_long start_free, end_free, new_end; | rman_res_t start_free, end_free, new_end; | ||||
/* | /* | ||||
* First, see if the request can be satisified by the existing | * First, see if the request can be satisified by the existing | ||||
* bus range. | * bus range. | ||||
*/ | */ | ||||
res = pcib_suballoc_bus(bus, child, rid, start, end, count, flags); | res = pcib_suballoc_bus(bus, child, rid, start, end, count, flags); | ||||
if (res != NULL) | if (res != NULL) | ||||
return (res); | return (res); | ||||
▲ Show 20 Lines • Show All 480 Lines • ▼ Show 20 Lines | |||||
#ifdef NEW_PCIB | #ifdef NEW_PCIB | ||||
/* | /* | ||||
* Attempt to allocate a resource from the existing resources assigned | * Attempt to allocate a resource from the existing resources assigned | ||||
* to a window. | * to a window. | ||||
*/ | */ | ||||
static struct resource * | static struct resource * | ||||
pcib_suballoc_resource(struct pcib_softc *sc, struct pcib_window *w, | pcib_suballoc_resource(struct pcib_softc *sc, struct pcib_window *w, | ||||
device_t child, int type, int *rid, u_long start, u_long end, u_long count, | device_t child, int type, int *rid, rman_res_t start, rman_res_t end, | ||||
u_int flags) | rman_res_t count, u_int flags) | ||||
{ | { | ||||
struct resource *res; | struct resource *res; | ||||
if (!pcib_is_window_open(w)) | if (!pcib_is_window_open(w)) | ||||
return (NULL); | return (NULL); | ||||
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); | ||||
Show All 20 Lines | pcib_suballoc_resource(struct pcib_softc *sc, struct pcib_window *w, | ||||
} | } | ||||
return (res); | return (res); | ||||
} | } | ||||
/* Allocate a fresh resource range for an unconfigured window. */ | /* Allocate a fresh resource range for an unconfigured window. */ | ||||
static int | static int | ||||
pcib_alloc_new_window(struct pcib_softc *sc, struct pcib_window *w, int type, | pcib_alloc_new_window(struct pcib_softc *sc, struct pcib_window *w, int type, | ||||
u_long start, u_long end, u_long count, u_int flags) | rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) | ||||
{ | { | ||||
struct resource *res; | struct resource *res; | ||||
u_long base, limit, wmask; | rman_res_t base, limit, wmask; | ||||
int rid; | int rid; | ||||
/* | /* | ||||
* If this is an I/O window on a bridge with ISA enable set | * If this is an I/O window on a bridge with ISA enable set | ||||
* and the start address is below 64k, then try to allocate an | * and the start address is below 64k, then try to allocate an | ||||
* initial window of 0x1000 bytes long starting at address | * initial window of 0x1000 bytes long starting at address | ||||
* 0xf000 and walking down. Note that if the original request | * 0xf000 and walking down. Note that if the original request | ||||
* was larger than the non-aliased range size of 0x100 our | * was larger than the non-aliased range size of 0x100 our | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | pcib_alloc_new_window(struct pcib_softc *sc, struct pcib_window *w, int type, | ||||
w->base = rman_get_start(res); | w->base = rman_get_start(res); | ||||
w->limit = rman_get_end(res); | w->limit = rman_get_end(res); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* Try to expand an existing window to the requested base and limit. */ | /* Try to expand an existing window to the requested base and limit. */ | ||||
static int | static int | ||||
pcib_expand_window(struct pcib_softc *sc, struct pcib_window *w, int type, | pcib_expand_window(struct pcib_softc *sc, struct pcib_window *w, int type, | ||||
u_long base, u_long limit) | rman_res_t base, rman_res_t limit) | ||||
{ | { | ||||
struct resource *res; | struct resource *res; | ||||
int error, i, force_64k_base; | int error, i, force_64k_base; | ||||
KASSERT(base <= w->base && limit >= w->limit, | KASSERT(base <= w->base && limit >= w->limit, | ||||
("attempting to shrink window")); | ("attempting to shrink window")); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | pcib_expand_window(struct pcib_softc *sc, struct pcib_window *w, int type, | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Attempt to grow a window to make room for a given resource request. | * Attempt to grow a window to make room for a given resource request. | ||||
*/ | */ | ||||
static int | static int | ||||
pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type, | pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type, | ||||
u_long start, u_long end, u_long count, u_int flags) | rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) | ||||
{ | { | ||||
u_long align, start_free, end_free, front, back, wmask; | rman_res_t align, start_free, end_free, front, back, wmask; | ||||
int error; | int error; | ||||
/* | /* | ||||
* Clamp the desired resource range to the maximum address | * Clamp the desired resource range to the maximum address | ||||
* this window supports. Reject impossible requests. | * this window supports. Reject impossible requests. | ||||
* | * | ||||
* For I/O port requests behind a bridge with the ISA enable | * For I/O port requests behind a bridge with the ISA enable | ||||
* bit set, force large allocations to start above 64k. | * bit set, force large allocations to start above 64k. | ||||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* We have to trap resource allocation requests and ensure that the bridge | * We have to trap resource allocation requests and ensure that the bridge | ||||
* is set up to, or capable of handling them. | * is set up to, or capable of handling them. | ||||
*/ | */ | ||||
struct resource * | struct resource * | ||||
pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, | pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, | ||||
u_long start, u_long end, u_long count, u_int flags) | rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) | ||||
{ | { | ||||
struct pcib_softc *sc; | struct pcib_softc *sc; | ||||
struct resource *r; | struct resource *r; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
/* | /* | ||||
* VGA resources are decoded iff the VGA enable bit is set in | * VGA resources are decoded iff the VGA enable bit is set in | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | #endif | ||||
if (sc->flags & PCIB_SUBTRACTIVE && r == NULL) | if (sc->flags & PCIB_SUBTRACTIVE && r == NULL) | ||||
return (bus_generic_alloc_resource(dev, child, type, rid, | return (bus_generic_alloc_resource(dev, child, type, rid, | ||||
start, end, count, flags)); | start, end, count, flags)); | ||||
return (r); | return (r); | ||||
} | } | ||||
int | int | ||||
pcib_adjust_resource(device_t bus, device_t child, int type, struct resource *r, | pcib_adjust_resource(device_t bus, device_t child, int type, struct resource *r, | ||||
u_long start, u_long end) | rman_res_t start, rman_res_t end) | ||||
{ | { | ||||
struct pcib_softc *sc; | struct pcib_softc *sc; | ||||
sc = device_get_softc(bus); | sc = device_get_softc(bus); | ||||
if (pcib_is_resource_managed(sc, type, r)) | if (pcib_is_resource_managed(sc, type, r)) | ||||
return (rman_adjust_resource(r, start, end)); | return (rman_adjust_resource(r, start, end)); | ||||
return (bus_generic_adjust_resource(bus, child, type, r, start, end)); | return (bus_generic_adjust_resource(bus, child, type, r, start, end)); | ||||
} | } | ||||
Show All 18 Lines | |||||
} | } | ||||
#else | #else | ||||
/* | /* | ||||
* We have to trap resource allocation requests and ensure that the bridge | * We have to trap resource allocation requests and ensure that the bridge | ||||
* is set up to, or capable of handling them. | * is set up to, or capable of handling them. | ||||
*/ | */ | ||||
struct resource * | struct resource * | ||||
pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, | pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, | ||||
u_long start, u_long end, u_long count, u_int flags) | rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) | ||||
{ | { | ||||
struct pcib_softc *sc = device_get_softc(dev); | struct pcib_softc *sc = device_get_softc(dev); | ||||
const char *name, *suffix; | const char *name, *suffix; | ||||
int ok; | int ok; | ||||
/* | /* | ||||
* Fail the allocation for this range if it's not supported. | * Fail the allocation for this range if it's not supported. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 449 Lines • Show Last 20 Lines |