Make sparc64 compatible with NEW_PCIB and enable it:
- Implement bus_adjust_resource() methods as far as necessary and in non-PCI bridge drivers as far as feasible without rototilling them. - As NEW_PCIB does a layering violation by activating resources at layers above pci(4) without previously bubbling up their allocation there, move the assignment of bus tags and handles from the bus_alloc_resource() to the bus_activate_resource() methods like at least the other NEW_PCIB enabled architectures do. This is somewhat unfortunate as previously sparc64 (ab)used resource activation to indicate whether SYS_RES_MEMORY resources should be mapped into KVA, which is only necessary if their going to be accessed via the pointer returned from rman_get_virtual() but not for bus_space(9) as the later always uses physical access on sparc64. Besides wasting KVA if we always map in SYS_RES_MEMORY resources, a driver also may deliberately not map them in if the firmware already has done so, possibly in a special way. So in order to still allow a driver to decide whether a SYS_RES_MEMORY resource should be mapped into KVA we let it indicate that by calling bus_space_map(9) with BUS_SPACE_MAP_LINEAR as actually documented in the bus_space(9) page. This is implemented by allocating a separate bus tag per SYS_RES_MEMORY resource and passing the resource via the previously unused bus tag cookie so we later on can call rman_set_virtual() in sparc64_bus_mem_map(). As a side effect this now also allows to actually indicate that a SYS_RES_MEMORY resource should be mapped in as cacheable and/or read-only via BUS_SPACE_MAP_CACHEABLE and BUS_SPACE_MAP_READONLY respectively. - Do some minor cleanup like taking advantage of rman_init_from_resource(), factor out the common part of bus tag allocation into a newly added sparc64_alloc_bus_tag(), hook up some missing newbus methods and replace some homegrown versions with the generic counterparts etc. - While at it, let apb_attach() (which can't use the generic NEW_PCIB code as APB bridges just don't have the base and limit registers implemented) regarding the config space registers cached in pcib_softc and the SYSCTL reporting nodes set up.
This commit is contained in:
parent
6ec3cd078c
commit
bda8e754a1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=225931
@ -87,7 +87,9 @@ struct machfb_softc {
|
||||
struct resource *sc_vmemres;
|
||||
bus_space_tag_t sc_memt;
|
||||
bus_space_tag_t sc_regt;
|
||||
bus_space_tag_t sc_vmemt;
|
||||
bus_space_handle_t sc_memh;
|
||||
bus_space_handle_t sc_vmemh;
|
||||
bus_space_handle_t sc_regh;
|
||||
u_long sc_mem;
|
||||
u_long sc_vmem;
|
||||
@ -1175,68 +1177,52 @@ machfb_pci_attach(device_t dev)
|
||||
adp = &sc->sc_va;
|
||||
vi = &adp->va_info;
|
||||
|
||||
/*
|
||||
* Allocate resources regardless of whether we are the console
|
||||
* and already obtained the bus tag and handle for the framebuffer
|
||||
* in machfb_configure() or not so the resources are marked as
|
||||
* taken in the respective RMAN.
|
||||
*/
|
||||
|
||||
/* Enable memory and IO access. */
|
||||
pci_write_config(dev, PCIR_COMMAND,
|
||||
pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_PORTEN |
|
||||
PCIM_CMD_MEMEN, 2);
|
||||
|
||||
/*
|
||||
* NB: we need to take care that the framebuffer isn't mapped
|
||||
* in twice as besides wasting resources this isn't possible with
|
||||
* all MMUs.
|
||||
*/
|
||||
rid = PCIR_BAR(0);
|
||||
if ((sc->sc_memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&rid, 0)) == NULL) {
|
||||
if ((sc->sc_memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
RF_ACTIVE)) == NULL) {
|
||||
device_printf(dev, "cannot allocate memory resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
sc->sc_memt = rman_get_bustag(sc->sc_memres);
|
||||
sc->sc_memh = rman_get_bushandle(sc->sc_memres);
|
||||
sc->sc_mem = rman_get_start(sc->sc_memres);
|
||||
vi->vi_buffer = sc->sc_memh;
|
||||
vi->vi_buffer_size = rman_get_size(sc->sc_memres);
|
||||
if (OF_getprop(sc->sc_node, "address", &u32, sizeof(u32)) > 0 &&
|
||||
vtophys(u32) == rman_get_bushandle(sc->sc_memres))
|
||||
vtophys(u32) == sc->sc_memh)
|
||||
adp->va_mem_base = u32;
|
||||
else {
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
rman_get_rid(sc->sc_memres), sc->sc_memres);
|
||||
rid = PCIR_BAR(0);
|
||||
if ((sc->sc_memres = bus_alloc_resource_any(dev,
|
||||
SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) {
|
||||
device_printf(dev,
|
||||
"cannot allocate memory resources\n");
|
||||
return (ENXIO);
|
||||
if (bus_space_map(sc->sc_memt, vi->vi_buffer,
|
||||
vi->vi_buffer_size, BUS_SPACE_MAP_LINEAR,
|
||||
&sc->sc_memh) != 0) {
|
||||
device_printf(dev, "cannot map memory resources\n");
|
||||
error = ENXIO;
|
||||
goto fail_memres;
|
||||
}
|
||||
adp->va_mem_base =
|
||||
(vm_offset_t)rman_get_virtual(sc->sc_memres);
|
||||
}
|
||||
sc->sc_memt = rman_get_bustag(sc->sc_memres);
|
||||
sc->sc_memh = rman_get_bushandle(sc->sc_memres);
|
||||
sc->sc_regt = sc->sc_memt;
|
||||
bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF,
|
||||
MACH64_REG_SIZE, &sc->sc_regh);
|
||||
adp->va_mem_size = rman_get_size(sc->sc_memres);
|
||||
adp->va_mem_size = vi->vi_buffer_size;
|
||||
adp->va_buffer = adp->va_mem_base;
|
||||
adp->va_buffer_size = adp->va_mem_size;
|
||||
sc->sc_mem = rman_get_start(sc->sc_memres);
|
||||
vi->vi_buffer = sc->sc_memh;
|
||||
vi->vi_buffer_size = adp->va_buffer_size;
|
||||
sc->sc_regt = sc->sc_memt;
|
||||
if (bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF,
|
||||
MACH64_REG_SIZE, &sc->sc_regh) != 0) {
|
||||
device_printf(dev, "cannot allocate register resources\n");
|
||||
error = ENXIO;
|
||||
goto fail_memmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Depending on the firmware version the VGA I/O and/or memory
|
||||
* resources of the Mach64 chips come up disabled. We generally
|
||||
* enable them above (pci(4) actually already did this unless
|
||||
* pci_enable_io_modes is not set) but this doesn't necessarily
|
||||
* mean that we get valid ones. Invalid resources seem to have
|
||||
* in common that they start at address 0. We don't allocate
|
||||
* them in this case in order to avoid warnings in apb(4) and
|
||||
* crashes when using these invalid resources. X.Org is aware
|
||||
* of this and doesn't use the VGA resources in this case (but
|
||||
* demands them if they are valid).
|
||||
* resources of the Mach64 chips come up disabled. These will be
|
||||
* enabled by pci(4) when activating the resource in question but
|
||||
* this doesn't necessarily mean that the resource is valid.
|
||||
* Invalid resources seem to have in common that they start at
|
||||
* address 0. We don't allocate the VGA memory in this case in
|
||||
* order to avoid warnings in apb(4) and crashes when using this
|
||||
* invalid resources. X.Org is aware of this and doesn't use the
|
||||
* VGA memory resource in this case (but demands it if it's valid).
|
||||
*/
|
||||
rid = PCIR_BAR(2);
|
||||
if (bus_get_resource_start(dev, SYS_RES_MEMORY, rid) != 0) {
|
||||
@ -1245,21 +1231,31 @@ machfb_pci_attach(device_t dev)
|
||||
device_printf(dev,
|
||||
"cannot allocate VGA memory resources\n");
|
||||
error = ENXIO;
|
||||
goto fail_memres;
|
||||
goto fail_memmap;
|
||||
}
|
||||
sc->sc_vmemt = rman_get_bustag(sc->sc_vmemres);
|
||||
sc->sc_vmemh = rman_get_bushandle(sc->sc_vmemres);
|
||||
sc->sc_vmem = rman_get_start(sc->sc_vmemres);
|
||||
vi->vi_registers = sc->sc_vmemh;
|
||||
vi->vi_registers_size = rman_get_size(sc->sc_vmemres);
|
||||
if (bus_space_map(sc->sc_vmemt, vi->vi_registers,
|
||||
vi->vi_registers_size, BUS_SPACE_MAP_LINEAR,
|
||||
&sc->sc_vmemh) != 0) {
|
||||
device_printf(dev,
|
||||
"cannot map VGA memory resources\n");
|
||||
error = ENXIO;
|
||||
goto fail_vmemres;
|
||||
}
|
||||
adp->va_registers =
|
||||
(vm_offset_t)rman_get_virtual(sc->sc_vmemres);
|
||||
adp->va_registers_size = rman_get_size(sc->sc_vmemres);
|
||||
sc->sc_vmem = rman_get_start(sc->sc_vmemres);
|
||||
vi->vi_registers = rman_get_bushandle(sc->sc_vmemres);
|
||||
vi->vi_registers_size = adp->va_registers_size;
|
||||
adp->va_registers_size = vi->vi_registers_size;
|
||||
}
|
||||
|
||||
if (!(sc->sc_flags & MACHFB_CONSOLE)) {
|
||||
if ((sw = vid_get_switch(MACHFB_DRIVER_NAME)) == NULL) {
|
||||
device_printf(dev, "cannot get video switch\n");
|
||||
error = ENODEV;
|
||||
goto fail_vmemres;
|
||||
goto fail_vmemmap;
|
||||
}
|
||||
/*
|
||||
* During device configuration we don't necessarily probe
|
||||
@ -1275,7 +1271,7 @@ machfb_pci_attach(device_t dev)
|
||||
break;
|
||||
if ((error = sw->init(i, adp, 0)) != 0) {
|
||||
device_printf(dev, "cannot initialize adapter\n");
|
||||
goto fail_vmemres;
|
||||
goto fail_vmemmap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1283,8 +1279,8 @@ machfb_pci_attach(device_t dev)
|
||||
* Test whether the aperture is byte swapped or not, set
|
||||
* va_window and va_window_size as appropriate. Note that
|
||||
* the aperture could be mapped either big or little endian
|
||||
* on independently of the endianess of the host so this
|
||||
* has to be a runtime test.
|
||||
* independently of the endianess of the host so this has
|
||||
* to be a runtime test.
|
||||
*/
|
||||
p32 = (uint32_t *)adp->va_buffer;
|
||||
u32 = *p32;
|
||||
@ -1346,10 +1342,16 @@ machfb_pci_attach(device_t dev)
|
||||
|
||||
return (0);
|
||||
|
||||
fail_vmemmap:
|
||||
if (adp->va_registers != 0)
|
||||
bus_space_unmap(sc->sc_vmemt, sc->sc_vmemh,
|
||||
vi->vi_registers_size);
|
||||
fail_vmemres:
|
||||
if (sc->sc_vmemres != NULL)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
rman_get_rid(sc->sc_vmemres), sc->sc_vmemres);
|
||||
fail_memmap:
|
||||
bus_space_unmap(sc->sc_memt, sc->sc_memh, vi->vi_buffer_size);
|
||||
fail_memres:
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
rman_get_rid(sc->sc_memres), sc->sc_memres);
|
||||
|
@ -81,6 +81,7 @@ static device_method_t lebuffer_methods[] = {
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
|
||||
DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
|
@ -60,6 +60,7 @@ static device_attach_t central_attach;
|
||||
static bus_print_child_t central_print_child;
|
||||
static bus_probe_nomatch_t central_probe_nomatch;
|
||||
static bus_alloc_resource_t central_alloc_resource;
|
||||
static bus_adjust_resource_t central_adjust_resource;
|
||||
static bus_get_resource_list_t central_get_resource_list;
|
||||
static ofw_bus_get_devinfo_t central_get_devinfo;
|
||||
|
||||
@ -79,6 +80,7 @@ static device_method_t central_methods[] = {
|
||||
DEVMETHOD(bus_alloc_resource, central_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, central_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
@ -179,6 +181,15 @@ central_attach(device_t dev)
|
||||
return (bus_generic_attach(dev));
|
||||
}
|
||||
|
||||
static int
|
||||
central_adjust_resource(device_t bus __unused, device_t child __unused,
|
||||
int type __unused, struct resource *r __unused, u_long start __unused,
|
||||
u_long end __unused)
|
||||
{
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
central_print_child(device_t dev, device_t child)
|
||||
{
|
||||
|
@ -19,3 +19,5 @@ options GEOM_PART_VTOC8
|
||||
|
||||
# Let sunkbd emulate an AT keyboard by default.
|
||||
options SUNKBD_EMULATE_ATKBD
|
||||
|
||||
#options NEW_PCIB
|
||||
|
@ -136,6 +136,8 @@ static device_attach_t ebus_pci_attach;
|
||||
static bus_print_child_t ebus_print_child;
|
||||
static bus_probe_nomatch_t ebus_probe_nomatch;
|
||||
static bus_alloc_resource_t ebus_alloc_resource;
|
||||
static bus_activate_resource_t ebus_activate_resource;
|
||||
static bus_adjust_resource_t ebus_adjust_resource;
|
||||
static bus_release_resource_t ebus_release_resource;
|
||||
static bus_setup_intr_t ebus_setup_intr;
|
||||
static bus_get_resource_list_t ebus_get_resource_list;
|
||||
@ -161,8 +163,9 @@ static device_method_t ebus_nexus_methods[] = {
|
||||
DEVMETHOD(bus_print_child, ebus_print_child),
|
||||
DEVMETHOD(bus_probe_nomatch, ebus_probe_nomatch),
|
||||
DEVMETHOD(bus_alloc_resource, ebus_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_activate_resource, ebus_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, ebus_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, ebus_release_resource),
|
||||
DEVMETHOD(bus_setup_intr, ebus_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
@ -342,16 +345,10 @@ ebus_pci_attach(device_t dev)
|
||||
eri->eri_res = res;
|
||||
eri->eri_rman.rm_type = RMAN_ARRAY;
|
||||
eri->eri_rman.rm_descr = "EBus range";
|
||||
if (rman_init(&eri->eri_rman) != 0) {
|
||||
if (rman_init_from_resource(&eri->eri_rman, res) != 0) {
|
||||
printf("%s: failed to initialize rman!", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if (rman_manage_region(&eri->eri_rman, rman_get_start(res),
|
||||
rman_get_end(res)) != 0) {
|
||||
printf("%s: failed to register region!", __func__);
|
||||
rman_fini(&eri->eri_rman);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return (ebus_attach(dev, sc, node));
|
||||
|
||||
@ -423,12 +420,10 @@ ebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
struct resource_list *rl;
|
||||
struct resource_list_entry *rle = NULL;
|
||||
struct resource *res;
|
||||
struct ebus_rinfo *ri;
|
||||
struct ebus_rinfo *eri;
|
||||
struct ebus_nexus_ranges *enr;
|
||||
bus_space_tag_t bt;
|
||||
bus_space_handle_t bh;
|
||||
uint64_t cend, cstart, offset;
|
||||
int i, isdefault, passthrough, ridx, rv;
|
||||
int i, isdefault, passthrough, ridx;
|
||||
|
||||
isdefault = (start == 0UL && end == ~0UL);
|
||||
passthrough = (device_get_parent(child) != bus);
|
||||
@ -459,23 +454,17 @@ ebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
*/
|
||||
(void)ofw_isa_range_map(sc->sc_range, sc->sc_nrange,
|
||||
&start, &end, &ridx);
|
||||
ri = &sc->sc_rinfo[ridx];
|
||||
res = rman_reserve_resource(&ri->eri_rman, start, end,
|
||||
count, flags, child);
|
||||
eri = &sc->sc_rinfo[ridx];
|
||||
res = rman_reserve_resource(&eri->eri_rman, start,
|
||||
end, count, flags & ~RF_ACTIVE, child);
|
||||
if (res == NULL)
|
||||
return (NULL);
|
||||
rman_set_rid(res, *rid);
|
||||
bt = rman_get_bustag(ri->eri_res);
|
||||
rman_set_bustag(res, bt);
|
||||
rv = bus_space_subregion(bt,
|
||||
rman_get_bushandle(ri->eri_res),
|
||||
rman_get_start(res) - rman_get_start(ri->eri_res),
|
||||
count, &bh);
|
||||
if (rv != 0) {
|
||||
if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(
|
||||
child, type, *rid, res) != 0) {
|
||||
rman_release_resource(res);
|
||||
return (NULL);
|
||||
}
|
||||
rman_set_bushandle(res, bh);
|
||||
} else {
|
||||
/* Map EBus ranges to nexus ranges. */
|
||||
for (i = 0; i < sc->sc_nrange; i++) {
|
||||
@ -496,7 +485,6 @@ ebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!passthrough)
|
||||
rle->res = res;
|
||||
@ -508,6 +496,48 @@ ebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
ebus_activate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *res)
|
||||
{
|
||||
struct ebus_softc *sc;
|
||||
struct ebus_rinfo *eri;
|
||||
bus_space_tag_t bt;
|
||||
bus_space_handle_t bh;
|
||||
int i, rv;
|
||||
|
||||
sc = device_get_softc(bus);
|
||||
if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) {
|
||||
for (i = 0; i < sc->sc_nrange; i++) {
|
||||
eri = &sc->sc_rinfo[i];
|
||||
if (rman_is_region_manager(res, &eri->eri_rman) != 0) {
|
||||
bt = rman_get_bustag(eri->eri_res);
|
||||
rv = bus_space_subregion(bt,
|
||||
rman_get_bushandle(eri->eri_res),
|
||||
rman_get_start(res) -
|
||||
rman_get_start(eri->eri_res),
|
||||
rman_get_size(res), &bh);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
rman_set_bustag(res, bt);
|
||||
rman_set_bushandle(res, bh);
|
||||
return (rman_activate_resource(res));
|
||||
}
|
||||
}
|
||||
return (EINVAL);
|
||||
}
|
||||
return (bus_generic_activate_resource(bus, child, type, rid, res));
|
||||
}
|
||||
|
||||
static int
|
||||
ebus_adjust_resource(device_t bus __unused, device_t child __unused,
|
||||
int type __unused, struct resource *res __unused, u_long start __unused,
|
||||
u_long end __unused)
|
||||
{
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
ebus_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *res)
|
||||
@ -519,13 +549,15 @@ ebus_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
|
||||
passthrough = (device_get_parent(child) != bus);
|
||||
rl = BUS_GET_RESOURCE_LIST(bus, child);
|
||||
switch (type) {
|
||||
case SYS_RES_MEMORY:
|
||||
sc = device_get_softc(bus);
|
||||
if ((sc->sc_flags & EBUS_PCI) == 0)
|
||||
return (resource_list_release(rl, bus, child, type,
|
||||
rid, res));
|
||||
if ((rv = rman_release_resource(res)) != 0)
|
||||
sc = device_get_softc(bus);
|
||||
if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) {
|
||||
if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){
|
||||
rv = bus_deactivate_resource(child, type, rid, res);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
}
|
||||
rv = rman_release_resource(res);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
if (!passthrough) {
|
||||
rle = resource_list_find(rl, type, rid);
|
||||
@ -535,13 +567,9 @@ ebus_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
("%s: resource entry is not busy", __func__));
|
||||
rle->res = NULL;
|
||||
}
|
||||
break;
|
||||
case SYS_RES_IRQ:
|
||||
return (resource_list_release(rl, bus, child, type, rid, res));
|
||||
default:
|
||||
panic("%s: unsupported resource type %d", __func__, type);
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
return (resource_list_release(rl, bus, child, type, rid, res));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -69,6 +69,7 @@ static bus_print_child_t fhc_print_child;
|
||||
static bus_probe_nomatch_t fhc_probe_nomatch;
|
||||
static bus_setup_intr_t fhc_setup_intr;
|
||||
static bus_alloc_resource_t fhc_alloc_resource;
|
||||
static bus_adjust_resource_t fhc_adjust_resource;
|
||||
static bus_get_resource_list_t fhc_get_resource_list;
|
||||
static ofw_bus_get_devinfo_t fhc_get_devinfo;
|
||||
|
||||
@ -93,6 +94,7 @@ static device_method_t fhc_methods[] = {
|
||||
DEVMETHOD(bus_alloc_resource, fhc_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, fhc_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
|
||||
DEVMETHOD(bus_setup_intr, fhc_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
@ -475,6 +477,15 @@ fhc_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
return (res);
|
||||
}
|
||||
|
||||
static int
|
||||
fhc_adjust_resource(device_t bus __unused, device_t child __unused,
|
||||
int type __unused, struct resource *r __unused, u_long start __unused,
|
||||
u_long end __unused)
|
||||
{
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static struct resource_list *
|
||||
fhc_get_resource_list(device_t bus, device_t child)
|
||||
{
|
||||
|
@ -122,32 +122,15 @@ static int bus_space_subregion(bus_space_tag_t, bus_space_handle_t,
|
||||
/*
|
||||
* Map a region of device bus space into CPU virtual address space.
|
||||
*/
|
||||
|
||||
static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
|
||||
bus_size_t size, int flags, bus_space_handle_t *bshp);
|
||||
|
||||
static __inline int
|
||||
bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr,
|
||||
bus_size_t size __unused, int flags __unused, bus_space_handle_t *bshp)
|
||||
{
|
||||
|
||||
*bshp = addr;
|
||||
return (0);
|
||||
}
|
||||
int bus_space_map(bus_space_tag_t tag, bus_addr_t address, bus_size_t size,
|
||||
int flags, bus_space_handle_t *handlep);
|
||||
|
||||
/*
|
||||
* Unmap a region of device bus space.
|
||||
*/
|
||||
static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
|
||||
void bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t handle,
|
||||
bus_size_t size);
|
||||
|
||||
static __inline void
|
||||
bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
|
||||
bus_size_t size __unused)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* This macro finds the first "upstream" implementation of method `f' */
|
||||
#define _BS_CALL(t,f) \
|
||||
while (t->f == NULL) \
|
||||
|
@ -36,10 +36,14 @@
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
int sparc64_bus_mem_map(bus_space_tag_t, bus_space_handle_t, bus_size_t,
|
||||
int, vm_offset_t, void **);
|
||||
int sparc64_bus_mem_unmap(void *, bus_size_t);
|
||||
bus_space_handle_t sparc64_fake_bustag(int, bus_addr_t, struct bus_space_tag *);
|
||||
int sparc64_bus_mem_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size,
|
||||
int flags, vm_offset_t vaddr, bus_space_handle_t *hp);
|
||||
int sparc64_bus_mem_unmap(bus_space_tag_t tag, bus_space_handle_t handle,
|
||||
bus_size_t size);
|
||||
bus_space_tag_t sparc64_alloc_bus_tag(void *cookie,
|
||||
struct bus_space_tag *ptag, int type, void *barrier);
|
||||
bus_space_handle_t sparc64_fake_bustag(int space, bus_addr_t addr,
|
||||
struct bus_space_tag *ptag);
|
||||
|
||||
struct bus_dmamap_res {
|
||||
struct resource *dr_res;
|
||||
|
@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
@ -77,6 +78,7 @@ struct apb_softc {
|
||||
static device_probe_t apb_probe;
|
||||
static device_attach_t apb_attach;
|
||||
static bus_alloc_resource_t apb_alloc_resource;
|
||||
static bus_adjust_resource_t apb_adjust_resource;
|
||||
|
||||
static device_method_t apb_methods[] = {
|
||||
/* Device interface */
|
||||
@ -85,6 +87,8 @@ static device_method_t apb_methods[] = {
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_alloc_resource, apb_alloc_resource),
|
||||
DEVMETHOD(bus_adjust_resource, apb_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
|
||||
|
||||
/* pcib interface */
|
||||
DEVMETHOD(pcib_route_interrupt, ofw_pcib_gen_route_interrupt),
|
||||
@ -158,6 +162,8 @@ static int
|
||||
apb_attach(device_t dev)
|
||||
{
|
||||
struct apb_softc *sc;
|
||||
struct sysctl_ctx_list *sctx;
|
||||
struct sysctl_oid *soid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
@ -165,12 +171,41 @@ apb_attach(device_t dev)
|
||||
* Get current bridge configuration.
|
||||
*/
|
||||
sc->sc_bsc.ops_pcib_sc.domain = pci_get_domain(dev);
|
||||
sc->sc_bsc.ops_pcib_sc.secstat =
|
||||
pci_read_config(dev, PCIR_SECSTAT_1, 2);
|
||||
sc->sc_bsc.ops_pcib_sc.command =
|
||||
pci_read_config(dev, PCIR_COMMAND, 2);
|
||||
sc->sc_bsc.ops_pcib_sc.pribus =
|
||||
pci_read_config(dev, PCIR_PRIBUS_1, 1);
|
||||
sc->sc_bsc.ops_pcib_sc.secbus =
|
||||
pci_read_config(dev, PCIR_SECBUS_1, 1);
|
||||
sc->sc_bsc.ops_pcib_sc.subbus =
|
||||
pci_read_config(dev, PCIR_SUBBUS_1, 1);
|
||||
sc->sc_bsc.ops_pcib_sc.bridgectl =
|
||||
pci_read_config(dev, PCIR_BRIDGECTL_1, 2);
|
||||
sc->sc_bsc.ops_pcib_sc.seclat =
|
||||
pci_read_config(dev, PCIR_SECLAT_1, 1);
|
||||
sc->sc_iomap = pci_read_config(dev, APBR_IOMAP, 1);
|
||||
sc->sc_memmap = pci_read_config(dev, APBR_MEMMAP, 1);
|
||||
|
||||
/*
|
||||
* Setup SYSCTL reporting nodes.
|
||||
*/
|
||||
sctx = device_get_sysctl_ctx(dev);
|
||||
soid = device_get_sysctl_tree(dev);
|
||||
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "domain",
|
||||
CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.domain, 0,
|
||||
"Domain number");
|
||||
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "pribus",
|
||||
CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.pribus, 0,
|
||||
"Primary bus number");
|
||||
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus",
|
||||
CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.secbus, 0,
|
||||
"Secondary bus number");
|
||||
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus",
|
||||
CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.subbus, 0,
|
||||
"Subordinate bus number");
|
||||
|
||||
ofw_pcib_gen_setup(dev);
|
||||
|
||||
if (bootverbose) {
|
||||
@ -233,9 +268,9 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
"%s requested decoded I/O range 0x%lx-0x%lx\n",
|
||||
device_get_nameunit(child), start, end);
|
||||
break;
|
||||
|
||||
case SYS_RES_MEMORY:
|
||||
if (!apb_checkrange(sc->sc_memmap, APB_MEM_SCALE, start, end)) {
|
||||
if (!apb_checkrange(sc->sc_memmap, APB_MEM_SCALE, start,
|
||||
end)) {
|
||||
device_printf(dev, "device %s requested unsupported "
|
||||
"memory range 0x%lx-0x%lx\n",
|
||||
device_get_nameunit(child), start, end);
|
||||
@ -246,9 +281,6 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
"%s requested decoded memory range 0x%lx-0x%lx\n",
|
||||
device_get_nameunit(child), start, end);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
passup:
|
||||
@ -258,3 +290,23 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
|
||||
count, flags));
|
||||
}
|
||||
|
||||
static int
|
||||
apb_adjust_resource(device_t dev, device_t child, int type,
|
||||
struct resource *r, u_long start, u_long end)
|
||||
{
|
||||
struct apb_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
switch (type) {
|
||||
case SYS_RES_IOPORT:
|
||||
if (!apb_checkrange(sc->sc_iomap, APB_IO_SCALE, start, end))
|
||||
return (ENXIO);
|
||||
break;
|
||||
case SYS_RES_MEMORY:
|
||||
if (!apb_checkrange(sc->sc_memmap, APB_MEM_SCALE, start, end))
|
||||
return (ENXIO);
|
||||
break;
|
||||
}
|
||||
return (bus_generic_adjust_resource(dev, child, type, r, start, end));
|
||||
}
|
||||
|
@ -85,7 +85,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
struct fire_msiqarg;
|
||||
|
||||
static bus_space_tag_t fire_alloc_bus_tag(struct fire_softc *sc, int type);
|
||||
static const struct fire_desc *fire_get_desc(device_t dev);
|
||||
static void fire_dmamap_sync(bus_dma_tag_t dt __unused, bus_dmamap_t map,
|
||||
bus_dmasync_op_t op);
|
||||
@ -113,11 +112,11 @@ static driver_filter_t fire_xcb;
|
||||
* Methods
|
||||
*/
|
||||
static bus_activate_resource_t fire_activate_resource;
|
||||
static bus_adjust_resource_t fire_adjust_resource;
|
||||
static pcib_alloc_msi_t fire_alloc_msi;
|
||||
static pcib_alloc_msix_t fire_alloc_msix;
|
||||
static bus_alloc_resource_t fire_alloc_resource;
|
||||
static device_attach_t fire_attach;
|
||||
static bus_deactivate_resource_t fire_deactivate_resource;
|
||||
static bus_get_dma_tag_t fire_get_dma_tag;
|
||||
static ofw_bus_get_node_t fire_get_node;
|
||||
static pcib_map_msi_t fire_map_msi;
|
||||
@ -127,7 +126,6 @@ static pcib_read_config_t fire_read_config;
|
||||
static bus_read_ivar_t fire_read_ivar;
|
||||
static pcib_release_msi_t fire_release_msi;
|
||||
static pcib_release_msix_t fire_release_msix;
|
||||
static bus_release_resource_t fire_release_resource;
|
||||
static pcib_route_interrupt_t fire_route_interrupt;
|
||||
static bus_setup_intr_t fire_setup_intr;
|
||||
static bus_teardown_intr_t fire_teardown_intr;
|
||||
@ -147,9 +145,10 @@ static device_method_t fire_methods[] = {
|
||||
DEVMETHOD(bus_setup_intr, fire_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, fire_teardown_intr),
|
||||
DEVMETHOD(bus_alloc_resource, fire_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, fire_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, fire_deactivate_resource),
|
||||
DEVMETHOD(bus_release_resource, fire_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, fire_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, fire_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
|
||||
DEVMETHOD(bus_get_dma_tag, fire_get_dma_tag),
|
||||
|
||||
/* pcib interface */
|
||||
@ -757,13 +756,19 @@ fire_attach(device_t dev)
|
||||
free(range, M_OFWPROP);
|
||||
|
||||
/* Allocate our tags. */
|
||||
sc->sc_pci_memt = fire_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE);
|
||||
sc->sc_pci_iot = fire_alloc_bus_tag(sc, PCI_IO_BUS_SPACE);
|
||||
sc->sc_pci_cfgt = fire_alloc_bus_tag(sc, PCI_CONFIG_BUS_SPACE);
|
||||
sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
|
||||
sc->sc_mem_res[FIRE_PCI]), PCI_IO_BUS_SPACE, NULL);
|
||||
if (sc->sc_pci_iot == NULL)
|
||||
panic("%s: could not allocate PCI I/O tag", __func__);
|
||||
sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
|
||||
sc->sc_mem_res[FIRE_PCI]), PCI_CONFIG_BUS_SPACE, NULL);
|
||||
if (sc->sc_pci_cfgt == NULL)
|
||||
panic("%s: could not allocate PCI configuration space tag",
|
||||
__func__);
|
||||
if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0,
|
||||
sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr,
|
||||
0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0)
|
||||
panic("%s: bus_dma_tag_create failed", __func__);
|
||||
panic("%s: could not create PCI DMA tag", __func__);
|
||||
/* Customize the tag. */
|
||||
sc->sc_pci_dmat->dt_cookie = &sc->sc_is;
|
||||
sc->sc_pci_dmat->dt_mt = &sc->sc_dma_methods;
|
||||
@ -2015,14 +2020,10 @@ fire_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
struct fire_softc *sc;
|
||||
struct resource *rv;
|
||||
struct rman *rm;
|
||||
bus_space_tag_t bt;
|
||||
bus_space_handle_t bh;
|
||||
int needactivate = flags & RF_ACTIVE;
|
||||
|
||||
flags &= ~RF_ACTIVE;
|
||||
|
||||
sc = device_get_softc(bus);
|
||||
if (type == SYS_RES_IRQ) {
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
/*
|
||||
* XXX: Don't accept blank ranges for now, only single
|
||||
* interrupts. The other case should not happen with
|
||||
@ -2034,38 +2035,28 @@ fire_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
panic("%s: XXX: interrupt range", __func__);
|
||||
if (*rid == 0)
|
||||
start = end = INTMAP_VEC(sc->sc_ign, end);
|
||||
return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, start, end, count, flags));
|
||||
}
|
||||
switch (type) {
|
||||
return (bus_generic_alloc_resource(bus, child, type, rid,
|
||||
start, end, count, flags));
|
||||
case SYS_RES_MEMORY:
|
||||
rm = &sc->sc_pci_mem_rman;
|
||||
bt = sc->sc_pci_memt;
|
||||
bh = sc->sc_pci_bh[OFW_PCI_CS_MEM32];
|
||||
break;
|
||||
case SYS_RES_IOPORT:
|
||||
rm = &sc->sc_pci_io_rman;
|
||||
bt = sc->sc_pci_iot;
|
||||
bh = sc->sc_pci_bh[OFW_PCI_CS_IO];
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
rv = rman_reserve_resource(rm, start, end, count, flags, child);
|
||||
rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
|
||||
child);
|
||||
if (rv == NULL)
|
||||
return (NULL);
|
||||
rman_set_rid(rv, *rid);
|
||||
bh += rman_get_start(rv);
|
||||
rman_set_bustag(rv, bt);
|
||||
rman_set_bushandle(rv, bh);
|
||||
|
||||
if (needactivate) {
|
||||
if (bus_activate_resource(child, type, *rid, rv)) {
|
||||
rman_release_resource(rv);
|
||||
return (NULL);
|
||||
}
|
||||
if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
|
||||
*rid, rv) != 0) {
|
||||
rman_release_resource(rv);
|
||||
return (NULL);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
@ -2074,56 +2065,56 @@ static int
|
||||
fire_activate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
{
|
||||
void *p;
|
||||
int error;
|
||||
struct fire_softc *sc;
|
||||
struct bus_space_tag *tag;
|
||||
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, r));
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
/*
|
||||
* Need to memory-map the device space, as some drivers
|
||||
* depend on the virtual address being set and usable.
|
||||
*/
|
||||
error = sparc64_bus_mem_map(rman_get_bustag(r),
|
||||
rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
rman_set_virtual(r, p);
|
||||
sc = device_get_softc(bus);
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
return (bus_generic_activate_resource(bus, child, type, rid,
|
||||
r));
|
||||
case SYS_RES_MEMORY:
|
||||
tag = sparc64_alloc_bus_tag(r, rman_get_bustag(
|
||||
sc->sc_mem_res[FIRE_PCI]), PCI_MEMORY_BUS_SPACE, NULL);
|
||||
if (tag == NULL)
|
||||
return (ENOMEM);
|
||||
rman_set_bustag(r, tag);
|
||||
rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] +
|
||||
rman_get_start(r));
|
||||
break;
|
||||
case SYS_RES_IOPORT:
|
||||
rman_set_bustag(r, sc->sc_pci_iot);
|
||||
rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] +
|
||||
rman_get_start(r));
|
||||
break;
|
||||
}
|
||||
return (rman_activate_resource(r));
|
||||
}
|
||||
|
||||
static int
|
||||
fire_deactivate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
fire_adjust_resource(device_t bus, device_t child, int type,
|
||||
struct resource *r, u_long start, u_long end)
|
||||
{
|
||||
struct fire_softc *sc;
|
||||
struct rman *rm;
|
||||
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, r));
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r));
|
||||
rman_set_virtual(r, NULL);
|
||||
sc = device_get_softc(bus);
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
return (bus_generic_adjust_resource(bus, child, type, r,
|
||||
start, end));
|
||||
case SYS_RES_MEMORY:
|
||||
rm = &sc->sc_pci_mem_rman;
|
||||
break;
|
||||
case SYS_RES_IOPORT:
|
||||
rm = &sc->sc_pci_io_rman;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
return (rman_deactivate_resource(r));
|
||||
}
|
||||
|
||||
static int
|
||||
fire_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, r));
|
||||
if (rman_get_flags(r) & RF_ACTIVE) {
|
||||
error = bus_deactivate_resource(child, type, rid, r);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
return (rman_release_resource(r));
|
||||
if (rman_is_region_manager(r, rm) == 0)
|
||||
return (EINVAL);
|
||||
return (rman_adjust_resource(r, start, end));
|
||||
}
|
||||
|
||||
static bus_dma_tag_t
|
||||
@ -2145,22 +2136,6 @@ fire_get_node(device_t bus, device_t child __unused)
|
||||
return (sc->sc_node);
|
||||
}
|
||||
|
||||
static bus_space_tag_t
|
||||
fire_alloc_bus_tag(struct fire_softc *sc, int type)
|
||||
{
|
||||
bus_space_tag_t bt;
|
||||
|
||||
bt = malloc(sizeof(struct bus_space_tag), M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (bt == NULL)
|
||||
panic("%s: out of memory", __func__);
|
||||
|
||||
bt->bst_cookie = sc;
|
||||
bt->bst_parent = rman_get_bustag(sc->sc_mem_res[FIRE_PCI]);
|
||||
bt->bst_type = type;
|
||||
return (bt);
|
||||
}
|
||||
|
||||
static u_int
|
||||
fire_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
|
@ -47,7 +47,6 @@ struct fire_softc {
|
||||
bus_space_handle_t sc_pci_bh[FIRE_NRANGE];
|
||||
bus_space_tag_t sc_pci_cfgt;
|
||||
bus_space_tag_t sc_pci_iot;
|
||||
bus_space_tag_t sc_pci_memt;
|
||||
bus_dma_tag_t sc_pci_dmat;
|
||||
|
||||
device_t sc_dev;
|
||||
|
@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_pci.h>
|
||||
|
@ -89,7 +89,6 @@ static void psycho_intr_enable(void *);
|
||||
static void psycho_intr_disable(void *);
|
||||
static void psycho_intr_assign(void *);
|
||||
static void psycho_intr_clear(void *);
|
||||
static bus_space_tag_t psycho_alloc_bus_tag(struct psycho_softc *, int);
|
||||
|
||||
/* Interrupt handlers */
|
||||
static driver_filter_t psycho_ue;
|
||||
@ -113,8 +112,7 @@ static bus_read_ivar_t psycho_read_ivar;
|
||||
static bus_setup_intr_t psycho_setup_intr;
|
||||
static bus_alloc_resource_t psycho_alloc_resource;
|
||||
static bus_activate_resource_t psycho_activate_resource;
|
||||
static bus_deactivate_resource_t psycho_deactivate_resource;
|
||||
static bus_release_resource_t psycho_release_resource;
|
||||
static bus_adjust_resource_t psycho_adjust_resource;
|
||||
static bus_get_dma_tag_t psycho_get_dma_tag;
|
||||
static pcib_maxslots_t psycho_maxslots;
|
||||
static pcib_read_config_t psycho_read_config;
|
||||
@ -137,9 +135,10 @@ static device_method_t psycho_methods[] = {
|
||||
DEVMETHOD(bus_setup_intr, psycho_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
DEVMETHOD(bus_alloc_resource, psycho_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, psycho_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, psycho_deactivate_resource),
|
||||
DEVMETHOD(bus_release_resource, psycho_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, psycho_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, psycho_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
|
||||
DEVMETHOD(bus_describe_intr, bus_generic_describe_intr),
|
||||
DEVMETHOD(bus_get_dma_tag, psycho_get_dma_tag),
|
||||
|
||||
@ -567,13 +566,19 @@ psycho_attach(device_t dev)
|
||||
}
|
||||
|
||||
/* Allocate our tags. */
|
||||
sc->sc_pci_memt = psycho_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE);
|
||||
sc->sc_pci_iot = psycho_alloc_bus_tag(sc, PCI_IO_BUS_SPACE);
|
||||
sc->sc_pci_cfgt = psycho_alloc_bus_tag(sc, PCI_CONFIG_BUS_SPACE);
|
||||
sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
|
||||
sc->sc_mem_res), PCI_IO_BUS_SPACE, NULL);
|
||||
if (sc->sc_pci_iot == NULL)
|
||||
panic("%s: could not allocate PCI I/O tag", __func__);
|
||||
sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
|
||||
sc->sc_mem_res), PCI_CONFIG_BUS_SPACE, NULL);
|
||||
if (sc->sc_pci_cfgt == NULL)
|
||||
panic("%s: could not allocate PCI configuration space tag",
|
||||
__func__);
|
||||
if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0,
|
||||
sc->sc_is->is_pmaxaddr, ~0, NULL, NULL, sc->sc_is->is_pmaxaddr,
|
||||
0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0)
|
||||
panic("%s: bus_dma_tag_create failed", __func__);
|
||||
panic("%s: could not create PCI DMA tag", __func__);
|
||||
/* Customize the tag. */
|
||||
sc->sc_pci_dmat->dt_cookie = sc->sc_is;
|
||||
sc->sc_pci_dmat->dt_mt = sc->sc_dma_methods;
|
||||
@ -1165,14 +1170,10 @@ psycho_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
struct psycho_softc *sc;
|
||||
struct resource *rv;
|
||||
struct rman *rm;
|
||||
bus_space_tag_t bt;
|
||||
bus_space_handle_t bh;
|
||||
int needactivate = flags & RF_ACTIVE;
|
||||
|
||||
flags &= ~RF_ACTIVE;
|
||||
|
||||
sc = device_get_softc(bus);
|
||||
if (type == SYS_RES_IRQ) {
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
/*
|
||||
* XXX: Don't accept blank ranges for now, only single
|
||||
* interrupts. The other case should not happen with
|
||||
@ -1183,38 +1184,28 @@ psycho_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
if (start != end)
|
||||
panic("%s: XXX: interrupt range", __func__);
|
||||
start = end = INTMAP_VEC(sc->sc_ign, end);
|
||||
return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, start, end, count, flags));
|
||||
}
|
||||
switch (type) {
|
||||
return (bus_generic_alloc_resource(bus, child, type, rid,
|
||||
start, end, count, flags));
|
||||
case SYS_RES_MEMORY:
|
||||
rm = &sc->sc_pci_mem_rman;
|
||||
bt = sc->sc_pci_memt;
|
||||
bh = sc->sc_pci_bh[OFW_PCI_CS_MEM32];
|
||||
break;
|
||||
case SYS_RES_IOPORT:
|
||||
rm = &sc->sc_pci_io_rman;
|
||||
bt = sc->sc_pci_iot;
|
||||
bh = sc->sc_pci_bh[OFW_PCI_CS_IO];
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
rv = rman_reserve_resource(rm, start, end, count, flags, child);
|
||||
rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
|
||||
child);
|
||||
if (rv == NULL)
|
||||
return (NULL);
|
||||
rman_set_rid(rv, *rid);
|
||||
bh += rman_get_start(rv);
|
||||
rman_set_bustag(rv, bt);
|
||||
rman_set_bushandle(rv, bh);
|
||||
|
||||
if (needactivate) {
|
||||
if (bus_activate_resource(child, type, *rid, rv)) {
|
||||
rman_release_resource(rv);
|
||||
return (NULL);
|
||||
}
|
||||
if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
|
||||
*rid, rv) != 0) {
|
||||
rman_release_resource(rv);
|
||||
return (NULL);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
@ -1223,56 +1214,56 @@ static int
|
||||
psycho_activate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
{
|
||||
void *p;
|
||||
int error;
|
||||
struct psycho_softc *sc;
|
||||
struct bus_space_tag *tag;
|
||||
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, r));
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
/*
|
||||
* Need to memory-map the device space, as some drivers
|
||||
* depend on the virtual address being set and usable.
|
||||
*/
|
||||
error = sparc64_bus_mem_map(rman_get_bustag(r),
|
||||
rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
rman_set_virtual(r, p);
|
||||
sc = device_get_softc(bus);
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
return (bus_generic_activate_resource(bus, child, type, rid,
|
||||
r));
|
||||
case SYS_RES_MEMORY:
|
||||
tag = sparc64_alloc_bus_tag(r, rman_get_bustag(
|
||||
sc->sc_mem_res), PCI_MEMORY_BUS_SPACE, NULL);
|
||||
if (tag == NULL)
|
||||
return (ENOMEM);
|
||||
rman_set_bustag(r, tag);
|
||||
rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] +
|
||||
rman_get_start(r));
|
||||
break;
|
||||
case SYS_RES_IOPORT:
|
||||
rman_set_bustag(r, sc->sc_pci_iot);
|
||||
rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] +
|
||||
rman_get_start(r));
|
||||
break;
|
||||
}
|
||||
return (rman_activate_resource(r));
|
||||
}
|
||||
|
||||
static int
|
||||
psycho_deactivate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
psycho_adjust_resource(device_t bus, device_t child, int type,
|
||||
struct resource *r, u_long start, u_long end)
|
||||
{
|
||||
struct psycho_softc *sc;
|
||||
struct rman *rm;
|
||||
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, r));
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r));
|
||||
rman_set_virtual(r, NULL);
|
||||
sc = device_get_softc(bus);
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
return (bus_generic_adjust_resource(bus, child, type, r,
|
||||
start, end));
|
||||
case SYS_RES_MEMORY:
|
||||
rm = &sc->sc_pci_mem_rman;
|
||||
break;
|
||||
case SYS_RES_IOPORT:
|
||||
rm = &sc->sc_pci_io_rman;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
return (rman_deactivate_resource(r));
|
||||
}
|
||||
|
||||
static int
|
||||
psycho_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, r));
|
||||
if (rman_get_flags(r) & RF_ACTIVE) {
|
||||
error = bus_deactivate_resource(child, type, rid, r);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
return (rman_release_resource(r));
|
||||
if (rman_is_region_manager(r, rm) == 0)
|
||||
return (EINVAL);
|
||||
return (rman_adjust_resource(r, start, end));
|
||||
}
|
||||
|
||||
static bus_dma_tag_t
|
||||
@ -1312,19 +1303,3 @@ psycho_setup_device(device_t bus, device_t child)
|
||||
PCICTL_WRITE8(sc, PCR_CS, PCICTL_READ8(sc, PCR_CS) &
|
||||
~PCICTL_ARB_PARK);
|
||||
}
|
||||
|
||||
static bus_space_tag_t
|
||||
psycho_alloc_bus_tag(struct psycho_softc *sc, int type)
|
||||
{
|
||||
bus_space_tag_t bt;
|
||||
|
||||
bt = malloc(sizeof(struct bus_space_tag), M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (bt == NULL)
|
||||
panic("%s: out of memory", __func__);
|
||||
|
||||
bt->bst_cookie = sc;
|
||||
bt->bst_parent = rman_get_bustag(sc->sc_mem_res);
|
||||
bt->bst_type = type;
|
||||
return (bt);
|
||||
}
|
||||
|
@ -65,7 +65,6 @@ struct psycho_softc {
|
||||
|
||||
/* Tags for PCI access */
|
||||
bus_space_tag_t sc_pci_cfgt;
|
||||
bus_space_tag_t sc_pci_memt;
|
||||
bus_space_tag_t sc_pci_iot;
|
||||
bus_dma_tag_t sc_pci_dmat;
|
||||
|
||||
|
@ -259,6 +259,9 @@ static const char *sbbc_serengeti_set_console_input(char *new);
|
||||
/*
|
||||
* SBBC PCI interface
|
||||
*/
|
||||
static bus_activate_resource_t sbbc_bus_activate_resource;
|
||||
static bus_adjust_resource_t sbbc_bus_adjust_resource;
|
||||
static bus_deactivate_resource_t sbbc_bus_deactivate_resource;
|
||||
static bus_alloc_resource_t sbbc_bus_alloc_resource;
|
||||
static bus_release_resource_t sbbc_bus_release_resource;
|
||||
static bus_get_resource_list_t sbbc_bus_get_resource_list;
|
||||
@ -278,9 +281,13 @@ static device_method_t sbbc_pci_methods[] = {
|
||||
|
||||
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
||||
DEVMETHOD(bus_alloc_resource, sbbc_bus_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource,sbbc_bus_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource,sbbc_bus_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, sbbc_bus_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, sbbc_bus_release_resource),
|
||||
DEVMETHOD(bus_setup_intr, sbbc_bus_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, sbbc_bus_teardown_intr),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
DEVMETHOD(bus_get_resource_list, sbbc_bus_get_resource_list),
|
||||
|
||||
/* clock interface */
|
||||
@ -333,11 +340,8 @@ sbbc_pci_attach(device_t dev)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
rid = SBBC_PCI_BAR;
|
||||
/*
|
||||
* Note that we don't activate the resource so it's not mapped twice
|
||||
* but only once by the firmware.
|
||||
*/
|
||||
sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
|
||||
sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->sc_res == NULL) {
|
||||
device_printf(dev, "failed to allocate resources\n");
|
||||
return (ENXIO);
|
||||
@ -402,24 +406,52 @@ sbbc_bus_alloc_resource(device_t dev, device_t child __unused, int type,
|
||||
sc = device_get_softc(dev);
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, type,
|
||||
rid, start, end, count, flags));
|
||||
return (bus_generic_alloc_resource(dev, dev, type, rid, start,
|
||||
end, count, flags));
|
||||
case SYS_RES_MEMORY:
|
||||
return (sc->sc_res);
|
||||
default:
|
||||
return (NULL);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sbbc_bus_activate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *res)
|
||||
{
|
||||
|
||||
if (type == SYS_RES_MEMORY)
|
||||
return (0);
|
||||
return (bus_generic_activate_resource(bus, child, type, rid, res));
|
||||
}
|
||||
|
||||
static int
|
||||
sbbc_bus_deactivate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *res)
|
||||
{
|
||||
|
||||
if (type == SYS_RES_MEMORY)
|
||||
return (0);
|
||||
return (bus_generic_deactivate_resource(bus, child, type, rid, res));
|
||||
}
|
||||
|
||||
static int
|
||||
sbbc_bus_adjust_resource(device_t bus __unused, device_t child __unused,
|
||||
int type __unused, struct resource *res __unused, u_long start __unused,
|
||||
u_long end __unused)
|
||||
{
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
sbbc_bus_release_resource(device_t dev, device_t child __unused, int type,
|
||||
int rid, struct resource *res)
|
||||
{
|
||||
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
|
||||
type, rid, res));
|
||||
return (bus_generic_release_resource(dev, dev, type, rid,
|
||||
res));
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -427,7 +459,7 @@ static struct resource_list *
|
||||
sbbc_bus_get_resource_list(device_t dev, device_t child __unused)
|
||||
{
|
||||
|
||||
return (BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev));
|
||||
return (bus_generic_get_resource_list(dev, dev));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -436,8 +468,8 @@ sbbc_bus_setup_intr(device_t dev, device_t child __unused,
|
||||
driver_intr_t *intr, void *arg, void **cookiep)
|
||||
{
|
||||
|
||||
return (BUS_SETUP_INTR(device_get_parent(dev), dev, res, flags, filt,
|
||||
intr, arg, cookiep));
|
||||
return (bus_generic_setup_intr(dev, dev, res, flags, filt, intr, arg,
|
||||
cookiep));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -445,7 +477,7 @@ sbbc_bus_teardown_intr(device_t dev, device_t child __unused,
|
||||
struct resource *res, void *cookie)
|
||||
{
|
||||
|
||||
return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, res, cookie));
|
||||
return (bus_generic_teardown_intr(dev, dev, res, cookie));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -91,7 +91,6 @@ static void schizo_intr_clear(void *);
|
||||
static int schizo_intr_register(struct schizo_softc *sc, u_int ino);
|
||||
static int schizo_get_intrmap(struct schizo_softc *, u_int,
|
||||
bus_addr_t *, bus_addr_t *);
|
||||
static bus_space_tag_t schizo_alloc_bus_tag(struct schizo_softc *, int);
|
||||
static timecounter_get_t schizo_get_timecount;
|
||||
|
||||
/* Interrupt handlers */
|
||||
@ -113,8 +112,7 @@ static bus_read_ivar_t schizo_read_ivar;
|
||||
static bus_setup_intr_t schizo_setup_intr;
|
||||
static bus_alloc_resource_t schizo_alloc_resource;
|
||||
static bus_activate_resource_t schizo_activate_resource;
|
||||
static bus_deactivate_resource_t schizo_deactivate_resource;
|
||||
static bus_release_resource_t schizo_release_resource;
|
||||
static bus_adjust_resource_t schizo_adjust_resource;
|
||||
static bus_get_dma_tag_t schizo_get_dma_tag;
|
||||
static pcib_maxslots_t schizo_maxslots;
|
||||
static pcib_read_config_t schizo_read_config;
|
||||
@ -137,9 +135,10 @@ static device_method_t schizo_methods[] = {
|
||||
DEVMETHOD(bus_setup_intr, schizo_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
DEVMETHOD(bus_alloc_resource, schizo_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, schizo_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, schizo_deactivate_resource),
|
||||
DEVMETHOD(bus_release_resource, schizo_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, schizo_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, schizo_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
|
||||
DEVMETHOD(bus_get_dma_tag, schizo_get_dma_tag),
|
||||
|
||||
/* pcib interface */
|
||||
@ -151,7 +150,7 @@ static device_method_t schizo_methods[] = {
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_node, schizo_get_node),
|
||||
|
||||
/* ofw_pci interface */
|
||||
/* ofw_pci interface */
|
||||
DEVMETHOD(ofw_pci_setup_device, schizo_setup_device),
|
||||
|
||||
KOBJMETHOD_END
|
||||
@ -580,14 +579,20 @@ schizo_attach(device_t dev)
|
||||
SLIST_INSERT_HEAD(&schizo_softcs, sc, sc_link);
|
||||
|
||||
/* Allocate our tags. */
|
||||
sc->sc_pci_memt = schizo_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE);
|
||||
sc->sc_pci_iot = schizo_alloc_bus_tag(sc, PCI_IO_BUS_SPACE);
|
||||
sc->sc_pci_cfgt = schizo_alloc_bus_tag(sc, PCI_CONFIG_BUS_SPACE);
|
||||
sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
|
||||
sc->sc_mem_res[STX_PCI]), PCI_IO_BUS_SPACE, NULL);
|
||||
if (sc->sc_pci_iot == NULL)
|
||||
panic("%s: could not allocate PCI I/O tag", __func__);
|
||||
sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
|
||||
sc->sc_mem_res[STX_PCI]), PCI_CONFIG_BUS_SPACE, NULL);
|
||||
if (sc->sc_pci_cfgt == NULL)
|
||||
panic("%s: could not allocate PCI configuration space tag",
|
||||
__func__);
|
||||
if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0,
|
||||
sc->sc_is.sis_is.is_pmaxaddr, ~0, NULL, NULL,
|
||||
sc->sc_is.sis_is.is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL,
|
||||
&sc->sc_pci_dmat) != 0)
|
||||
panic("%s: bus_dma_tag_create failed", __func__);
|
||||
panic("%s: could not create PCI DMA tag", __func__);
|
||||
/* Customize the tag. */
|
||||
sc->sc_pci_dmat->dt_cookie = &sc->sc_is;
|
||||
sc->sc_pci_dmat->dt_mt = &sc->sc_dma_methods;
|
||||
@ -1161,7 +1166,7 @@ schizo_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op)
|
||||
|
||||
if ((op & BUS_DMASYNC_POSTREAD) != 0) {
|
||||
/*
|
||||
* Note that in order to allow this function to be called from
|
||||
* Note that in order to allow this function to be called from
|
||||
* filters we would need to use a spin mutex for serialization
|
||||
* but given that these disable interrupts we have to emulate
|
||||
* one.
|
||||
@ -1333,14 +1338,10 @@ schizo_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
struct schizo_softc *sc;
|
||||
struct resource *rv;
|
||||
struct rman *rm;
|
||||
bus_space_tag_t bt;
|
||||
bus_space_handle_t bh;
|
||||
int needactivate = flags & RF_ACTIVE;
|
||||
|
||||
flags &= ~RF_ACTIVE;
|
||||
|
||||
sc = device_get_softc(bus);
|
||||
if (type == SYS_RES_IRQ) {
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
/*
|
||||
* XXX: Don't accept blank ranges for now, only single
|
||||
* interrupts. The other case should not happen with
|
||||
@ -1351,38 +1352,28 @@ schizo_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
if (start != end)
|
||||
panic("%s: XXX: interrupt range", __func__);
|
||||
start = end = INTMAP_VEC(sc->sc_ign, end);
|
||||
return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, start, end, count, flags));
|
||||
}
|
||||
switch (type) {
|
||||
return (bus_generic_alloc_resource(bus, child, type, rid,
|
||||
start, end, count, flags));
|
||||
case SYS_RES_MEMORY:
|
||||
rm = &sc->sc_pci_mem_rman;
|
||||
bt = sc->sc_pci_memt;
|
||||
bh = sc->sc_pci_bh[OFW_PCI_CS_MEM32];
|
||||
break;
|
||||
case SYS_RES_IOPORT:
|
||||
rm = &sc->sc_pci_io_rman;
|
||||
bt = sc->sc_pci_iot;
|
||||
bh = sc->sc_pci_bh[OFW_PCI_CS_IO];
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
rv = rman_reserve_resource(rm, start, end, count, flags, child);
|
||||
rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
|
||||
child);
|
||||
if (rv == NULL)
|
||||
return (NULL);
|
||||
rman_set_rid(rv, *rid);
|
||||
bh += rman_get_start(rv);
|
||||
rman_set_bustag(rv, bt);
|
||||
rman_set_bushandle(rv, bh);
|
||||
|
||||
if (needactivate) {
|
||||
if (bus_activate_resource(child, type, *rid, rv)) {
|
||||
rman_release_resource(rv);
|
||||
return (NULL);
|
||||
}
|
||||
if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
|
||||
*rid, rv) != 0) {
|
||||
rman_release_resource(rv);
|
||||
return (NULL);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
@ -1391,56 +1382,56 @@ static int
|
||||
schizo_activate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
{
|
||||
void *p;
|
||||
int error;
|
||||
struct schizo_softc *sc;
|
||||
struct bus_space_tag *tag;
|
||||
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, r));
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
/*
|
||||
* Need to memory-map the device space, as some drivers
|
||||
* depend on the virtual address being set and usable.
|
||||
*/
|
||||
error = sparc64_bus_mem_map(rman_get_bustag(r),
|
||||
rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
rman_set_virtual(r, p);
|
||||
sc = device_get_softc(bus);
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
return (bus_generic_activate_resource(bus, child, type, rid,
|
||||
r));
|
||||
case SYS_RES_MEMORY:
|
||||
tag = sparc64_alloc_bus_tag(r, rman_get_bustag(
|
||||
sc->sc_mem_res[STX_PCI]), PCI_MEMORY_BUS_SPACE, NULL);
|
||||
if (tag == NULL)
|
||||
return (ENOMEM);
|
||||
rman_set_bustag(r, tag);
|
||||
rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] +
|
||||
rman_get_start(r));
|
||||
break;
|
||||
case SYS_RES_IOPORT:
|
||||
rman_set_bustag(r, sc->sc_pci_iot);
|
||||
rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] +
|
||||
rman_get_start(r));
|
||||
break;
|
||||
}
|
||||
return (rman_activate_resource(r));
|
||||
}
|
||||
|
||||
static int
|
||||
schizo_deactivate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
schizo_adjust_resource(device_t bus, device_t child, int type,
|
||||
struct resource *r, u_long start, u_long end)
|
||||
{
|
||||
struct schizo_softc *sc;
|
||||
struct rman *rm;
|
||||
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, r));
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r));
|
||||
rman_set_virtual(r, NULL);
|
||||
sc = device_get_softc(bus);
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
return (bus_generic_adjust_resource(bus, child, type, r,
|
||||
start, end));
|
||||
case SYS_RES_MEMORY:
|
||||
rm = &sc->sc_pci_mem_rman;
|
||||
break;
|
||||
case SYS_RES_IOPORT:
|
||||
rm = &sc->sc_pci_io_rman;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
return (rman_deactivate_resource(r));
|
||||
}
|
||||
|
||||
static int
|
||||
schizo_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
|
||||
type, rid, r));
|
||||
if (rman_get_flags(r) & RF_ACTIVE) {
|
||||
error = bus_deactivate_resource(child, type, rid, r);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
return (rman_release_resource(r));
|
||||
if (rman_is_region_manager(r, rm) == 0)
|
||||
return (EINVAL);
|
||||
return (rman_adjust_resource(r, start, end));
|
||||
}
|
||||
|
||||
static bus_dma_tag_t
|
||||
@ -1473,7 +1464,7 @@ schizo_setup_device(device_t bus, device_t child)
|
||||
/*
|
||||
* Disable bus parking in order to work around a bus hang caused by
|
||||
* Casinni/Skyhawk combinations.
|
||||
*/
|
||||
*/
|
||||
if (OF_getproplen(ofw_bus_get_node(child), "pci-req-removal") >= 0)
|
||||
SCHIZO_PCI_SET(sc, STX_PCI_CTRL, SCHIZO_PCI_READ_8(sc,
|
||||
STX_PCI_CTRL) & ~STX_PCI_CTRL_ARB_PARK);
|
||||
@ -1498,22 +1489,6 @@ schizo_setup_device(device_t bus, device_t child)
|
||||
}
|
||||
}
|
||||
|
||||
static bus_space_tag_t
|
||||
schizo_alloc_bus_tag(struct schizo_softc *sc, int type)
|
||||
{
|
||||
bus_space_tag_t bt;
|
||||
|
||||
bt = malloc(sizeof(struct bus_space_tag), M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (bt == NULL)
|
||||
panic("%s: out of memory", __func__);
|
||||
|
||||
bt->bst_cookie = sc;
|
||||
bt->bst_parent = rman_get_bustag(sc->sc_mem_res[STX_PCI]);
|
||||
bt->bst_type = type;
|
||||
return (bt);
|
||||
}
|
||||
|
||||
static u_int
|
||||
schizo_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
|
@ -81,7 +81,6 @@ struct schizo_softc {
|
||||
bus_space_handle_t sc_pci_bh[STX_NRANGE];
|
||||
bus_space_tag_t sc_pci_cfgt;
|
||||
bus_space_tag_t sc_pci_iot;
|
||||
bus_space_tag_t sc_pci_memt;
|
||||
bus_dma_tag_t sc_pci_dmat;
|
||||
|
||||
uint32_t sc_stats_dma_ce;
|
||||
|
@ -118,6 +118,7 @@ static device_method_t dma_methods[] = {
|
||||
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
|
@ -108,7 +108,6 @@ struct sbus_rd {
|
||||
struct sbus_softc {
|
||||
device_t sc_dev;
|
||||
bus_dma_tag_t sc_cdmatag;
|
||||
bus_space_tag_t sc_cbustag;
|
||||
int sc_clockfreq; /* clock frequency (in Hz) */
|
||||
int sc_nrange;
|
||||
struct sbus_rd *sc_rd;
|
||||
@ -137,9 +136,9 @@ static bus_read_ivar_t sbus_read_ivar;
|
||||
static bus_get_resource_list_t sbus_get_resource_list;
|
||||
static bus_setup_intr_t sbus_setup_intr;
|
||||
static bus_alloc_resource_t sbus_alloc_resource;
|
||||
static bus_release_resource_t sbus_release_resource;
|
||||
static bus_activate_resource_t sbus_activate_resource;
|
||||
static bus_deactivate_resource_t sbus_deactivate_resource;
|
||||
static bus_adjust_resource_t sbus_adjust_resource;
|
||||
static bus_release_resource_t sbus_release_resource;
|
||||
static bus_get_dma_tag_t sbus_get_dma_tag;
|
||||
static ofw_bus_get_devinfo_t sbus_get_devinfo;
|
||||
|
||||
@ -153,7 +152,6 @@ static void sbus_intr_assign(void *);
|
||||
static void sbus_intr_clear(void *);
|
||||
static int sbus_find_intrmap(struct sbus_softc *, u_int, bus_addr_t *,
|
||||
bus_addr_t *);
|
||||
static bus_space_tag_t sbus_alloc_bustag(struct sbus_softc *);
|
||||
static driver_intr_t sbus_overtemp;
|
||||
static driver_intr_t sbus_pwrfail;
|
||||
static int sbus_print_res(struct sbus_devinfo *);
|
||||
@ -171,10 +169,11 @@ static device_method_t sbus_methods[] = {
|
||||
DEVMETHOD(bus_probe_nomatch, sbus_probe_nomatch),
|
||||
DEVMETHOD(bus_read_ivar, sbus_read_ivar),
|
||||
DEVMETHOD(bus_alloc_resource, sbus_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, sbus_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, sbus_deactivate_resource),
|
||||
DEVMETHOD(bus_activate_resource, sbus_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, sbus_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, sbus_release_resource),
|
||||
DEVMETHOD(bus_setup_intr, sbus_setup_intr),
|
||||
DEVMETHOD(bus_setup_intr, sbus_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
DEVMETHOD(bus_get_resource_list, sbus_get_resource_list),
|
||||
@ -284,7 +283,6 @@ sbus_attach(device_t dev)
|
||||
if (OF_getprop(node, "interrupts", &prop, sizeof(prop)) == -1)
|
||||
panic("%s: cannot get IGN", __func__);
|
||||
sc->sc_ign = INTIGN(prop);
|
||||
sc->sc_cbustag = sbus_alloc_bustag(sc);
|
||||
|
||||
/*
|
||||
* Record clock frequency for synchronous SCSI.
|
||||
@ -343,7 +341,6 @@ sbus_attach(device_t dev)
|
||||
sc->sc_burst =
|
||||
(SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF;
|
||||
|
||||
|
||||
/* initalise the IOMMU */
|
||||
|
||||
/* punch in our copies */
|
||||
@ -375,7 +372,7 @@ sbus_attach(device_t dev)
|
||||
sc->sc_cdmatag->dt_cookie = &sc->sc_is;
|
||||
sc->sc_cdmatag->dt_mt = &iommu_dma_methods;
|
||||
|
||||
/*
|
||||
/*
|
||||
* Hunt through all the interrupt mapping regs and register our
|
||||
* interrupt controller for the corresponding interrupt vectors.
|
||||
* We do this early in order to be able to catch stray interrupts.
|
||||
@ -701,12 +698,12 @@ sbus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags,
|
||||
/*
|
||||
* Make sure the vector is fully specified and we registered
|
||||
* our interrupt controller for it.
|
||||
*/
|
||||
*/
|
||||
vec = rman_get_start(ires);
|
||||
if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &sbus_ic) {
|
||||
device_printf(dev, "invalid interrupt vector 0x%lx\n", vec);
|
||||
return (EINVAL);
|
||||
}
|
||||
return (EINVAL);
|
||||
}
|
||||
return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr,
|
||||
arg, cookiep));
|
||||
}
|
||||
@ -721,14 +718,12 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
struct resource_list *rl;
|
||||
struct resource_list_entry *rle;
|
||||
device_t schild;
|
||||
bus_space_handle_t bh;
|
||||
bus_addr_t toffs;
|
||||
bus_size_t tend;
|
||||
int i, slot;
|
||||
int isdefault, needactivate, passthrough;
|
||||
int isdefault, passthrough;
|
||||
|
||||
isdefault = (start == 0UL && end == ~0UL);
|
||||
needactivate = flags & RF_ACTIVE;
|
||||
passthrough = (device_get_parent(child) != bus);
|
||||
rle = NULL;
|
||||
sc = device_get_softc(bus);
|
||||
@ -751,7 +746,6 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
}
|
||||
}
|
||||
rm = NULL;
|
||||
bh = toffs = tend = 0;
|
||||
schild = child;
|
||||
while (device_get_parent(schild) != bus)
|
||||
schild = device_get_parent(schild);
|
||||
@ -768,24 +762,21 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
toffs = start - sc->sc_rd[i].rd_coffset;
|
||||
tend = end - sc->sc_rd[i].rd_coffset;
|
||||
rm = &sc->sc_rd[i].rd_rman;
|
||||
bh = sc->sc_rd[i].rd_bushandle;
|
||||
break;
|
||||
}
|
||||
if (rm == NULL)
|
||||
return (NULL);
|
||||
flags &= ~RF_ACTIVE;
|
||||
rv = rman_reserve_resource(rm, toffs, tend, count, flags,
|
||||
child);
|
||||
|
||||
rv = rman_reserve_resource(rm, toffs, tend, count, flags &
|
||||
~RF_ACTIVE, child);
|
||||
if (rv == NULL)
|
||||
return (NULL);
|
||||
rman_set_rid(rv, *rid);
|
||||
rman_set_bustag(rv, sc->sc_cbustag);
|
||||
rman_set_bushandle(rv, bh + rman_get_start(rv));
|
||||
if (needactivate) {
|
||||
if (bus_activate_resource(child, type, *rid, rv)) {
|
||||
rman_release_resource(rv);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child,
|
||||
type, *rid, rv)) {
|
||||
rman_release_resource(rv);
|
||||
return (NULL);
|
||||
}
|
||||
if (!passthrough)
|
||||
rle->res = rv;
|
||||
@ -799,41 +790,53 @@ static int
|
||||
sbus_activate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
{
|
||||
void *p;
|
||||
int error;
|
||||
struct sbus_softc *sc;
|
||||
struct bus_space_tag *tag;
|
||||
int i;
|
||||
|
||||
if (type == SYS_RES_IRQ) {
|
||||
return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus),
|
||||
child, type, rid, r));
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
return (bus_generic_activate_resource(bus, child, type, rid,
|
||||
r));
|
||||
case SYS_RES_MEMORY:
|
||||
sc = device_get_softc(bus);
|
||||
for (i = 0; i < sc->sc_nrange; i++) {
|
||||
if (rman_is_region_manager(r,
|
||||
&sc->sc_rd[i].rd_rman) != 0) {
|
||||
tag = sparc64_alloc_bus_tag(r,
|
||||
rman_get_bustag(sc->sc_sysio_res),
|
||||
SBUS_BUS_SPACE, NULL);
|
||||
if (tag == NULL)
|
||||
return (ENOMEM);
|
||||
rman_set_bustag(r, tag);
|
||||
rman_set_bushandle(r,
|
||||
sc->sc_rd[i].rd_bushandle +
|
||||
rman_get_start(r));
|
||||
return (rman_activate_resource(r));
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
/*
|
||||
* Need to memory-map the device space, as some drivers
|
||||
* depend on the virtual address being set and usable.
|
||||
*/
|
||||
error = sparc64_bus_mem_map(rman_get_bustag(r),
|
||||
rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
rman_set_virtual(r, p);
|
||||
}
|
||||
return (rman_activate_resource(r));
|
||||
}
|
||||
|
||||
static int
|
||||
sbus_deactivate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
sbus_adjust_resource(device_t bus, device_t child, int type,
|
||||
struct resource *r, u_long start, u_long end)
|
||||
{
|
||||
struct sbus_softc *sc;
|
||||
int i;
|
||||
|
||||
if (type == SYS_RES_IRQ) {
|
||||
return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus),
|
||||
child, type, rid, r));
|
||||
}
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r));
|
||||
rman_set_virtual(r, NULL);
|
||||
sc = device_get_softc(bus);
|
||||
for (i = 0; i < sc->sc_nrange; i++)
|
||||
if (rman_is_region_manager(r,
|
||||
&sc->sc_rd[i].rd_rman) != 0)
|
||||
return (rman_adjust_resource(r, start, end));
|
||||
return (EINVAL);
|
||||
}
|
||||
return (rman_deactivate_resource(r));
|
||||
return (bus_generic_adjust_resource(bus, child, type, r, start, end));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -846,23 +849,26 @@ sbus_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
|
||||
passthrough = (device_get_parent(child) != bus);
|
||||
rl = BUS_GET_RESOURCE_LIST(bus, child);
|
||||
if (type == SYS_RES_IRQ)
|
||||
return (resource_list_release(rl, bus, child, type, rid, r));
|
||||
if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
|
||||
error = bus_deactivate_resource(child, type, rid, r);
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
|
||||
error = bus_deactivate_resource(child, type, rid, r);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
error = rman_release_resource(r);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (!passthrough) {
|
||||
rle = resource_list_find(rl, type, rid);
|
||||
KASSERT(rle != NULL,
|
||||
("%s: resource entry not found!", __func__));
|
||||
KASSERT(rle->res != NULL,
|
||||
("%s: resource entry is not busy", __func__));
|
||||
rle->res = NULL;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
error = rman_release_resource(r);
|
||||
if (error != 0 || passthrough)
|
||||
return (error);
|
||||
rle = resource_list_find(rl, type, rid);
|
||||
if (rle == NULL)
|
||||
panic("%s: cannot find resource", __func__);
|
||||
if (rle->res == NULL)
|
||||
panic("%s: resource entry is not busy", __func__);
|
||||
rle->res = NULL;
|
||||
return (0);
|
||||
return (resource_list_release(rl, bus, child, type, rid, r));
|
||||
}
|
||||
|
||||
static bus_dma_tag_t
|
||||
@ -918,22 +924,6 @@ sbus_pwrfail(void *arg)
|
||||
shutdown_nice(0);
|
||||
}
|
||||
|
||||
static bus_space_tag_t
|
||||
sbus_alloc_bustag(struct sbus_softc *sc)
|
||||
{
|
||||
bus_space_tag_t sbt;
|
||||
|
||||
sbt = (bus_space_tag_t)malloc(sizeof(struct bus_space_tag), M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (sbt == NULL)
|
||||
panic("%s: out of memory", __func__);
|
||||
|
||||
sbt->bst_cookie = sc;
|
||||
sbt->bst_parent = rman_get_bustag(sc->sc_sysio_res);
|
||||
sbt->bst_type = SBUS_BUS_SPACE;
|
||||
return (sbt);
|
||||
}
|
||||
|
||||
static int
|
||||
sbus_print_res(struct sbus_devinfo *sdi)
|
||||
{
|
||||
|
@ -101,6 +101,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/smp.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/uio.h>
|
||||
@ -665,7 +666,7 @@ nexus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
|
||||
contigfree(vaddr, dmat->dt_maxsize, M_DEVBUF);
|
||||
}
|
||||
|
||||
struct bus_dma_methods nexus_dma_methods = {
|
||||
static struct bus_dma_methods nexus_dma_methods = {
|
||||
nexus_dmamap_create,
|
||||
nexus_dmamap_destroy,
|
||||
nexus_dmamap_load,
|
||||
@ -703,22 +704,43 @@ struct bus_dma_tag nexus_dmatag = {
|
||||
* Helpers to map/unmap bus memory
|
||||
*/
|
||||
int
|
||||
sparc64_bus_mem_map(bus_space_tag_t tag, bus_space_handle_t handle,
|
||||
bus_size_t size, int flags, vm_offset_t vaddr, void **hp)
|
||||
bus_space_map(bus_space_tag_t tag, bus_addr_t address, bus_size_t size,
|
||||
int flags, bus_space_handle_t *handlep)
|
||||
{
|
||||
|
||||
return (sparc64_bus_mem_map(tag, address, size, flags, 0, handlep));
|
||||
}
|
||||
|
||||
int
|
||||
sparc64_bus_mem_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size,
|
||||
int flags, vm_offset_t vaddr, bus_space_handle_t *hp)
|
||||
{
|
||||
vm_offset_t addr;
|
||||
vm_offset_t sva;
|
||||
vm_offset_t va;
|
||||
vm_paddr_t pa;
|
||||
vm_size_t vsz;
|
||||
u_long pm_flags;
|
||||
|
||||
addr = (vm_offset_t)handle;
|
||||
/*
|
||||
* Given that we use physical access for bus_space(9) there's no need
|
||||
* need to map anything in unless BUS_SPACE_MAP_LINEAR is requested.
|
||||
*/
|
||||
if ((flags & BUS_SPACE_MAP_LINEAR) == 0) {
|
||||
*hp = addr;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (tag->bst_cookie == NULL) {
|
||||
printf("%s: resource cookie not set\n", __func__);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
size = round_page(size);
|
||||
if (size == 0) {
|
||||
printf("%s: zero size\n", __func__);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
switch (tag->bst_type) {
|
||||
case PCI_CONFIG_BUS_SPACE:
|
||||
case PCI_IO_BUS_SPACE:
|
||||
@ -730,7 +752,7 @@ sparc64_bus_mem_map(bus_space_tag_t tag, bus_space_handle_t handle,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(flags & BUS_SPACE_MAP_CACHEABLE))
|
||||
if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0)
|
||||
pm_flags |= TD_E;
|
||||
|
||||
if (vaddr != 0L)
|
||||
@ -740,9 +762,6 @@ sparc64_bus_mem_map(bus_space_tag_t tag, bus_space_handle_t handle,
|
||||
panic("%s: cannot allocate virtual memory", __func__);
|
||||
}
|
||||
|
||||
/* Preserve page offset. */
|
||||
*hp = (void *)(sva | ((u_long)addr & PAGE_MASK));
|
||||
|
||||
pa = trunc_page(addr);
|
||||
if ((flags & BUS_SPACE_MAP_READONLY) == 0)
|
||||
pm_flags |= TD_W;
|
||||
@ -755,17 +774,32 @@ sparc64_bus_mem_map(bus_space_tag_t tag, bus_space_handle_t handle,
|
||||
pa += PAGE_SIZE;
|
||||
} while ((vsz -= PAGE_SIZE) > 0);
|
||||
tlb_range_demap(kernel_pmap, sva, sva + size - 1);
|
||||
|
||||
/* Note: we preserve the page offset. */
|
||||
rman_set_virtual(tag->bst_cookie, (void *)(sva | (addr & PAGE_MASK)));
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t handle,
|
||||
bus_size_t size)
|
||||
{
|
||||
|
||||
sparc64_bus_mem_unmap(tag, handle, size);
|
||||
}
|
||||
|
||||
int
|
||||
sparc64_bus_mem_unmap(void *bh, bus_size_t size)
|
||||
sparc64_bus_mem_unmap(bus_space_tag_t tag, bus_space_handle_t handle,
|
||||
bus_size_t size)
|
||||
{
|
||||
vm_offset_t sva;
|
||||
vm_offset_t va;
|
||||
vm_offset_t endva;
|
||||
|
||||
sva = trunc_page((vm_offset_t)bh);
|
||||
if (tag->bst_cookie == NULL ||
|
||||
(sva = (vm_offset_t)rman_get_virtual(tag->bst_cookie)) == 0)
|
||||
return (0);
|
||||
sva = trunc_page(sva);
|
||||
endva = sva + round_page(size);
|
||||
for (va = sva; va < endva; va += PAGE_SIZE)
|
||||
pmap_kremove_flags(va);
|
||||
@ -790,6 +824,25 @@ sparc64_fake_bustag(int space, bus_addr_t addr, struct bus_space_tag *ptag)
|
||||
return (addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a bus tag.
|
||||
*/
|
||||
bus_space_tag_t
|
||||
sparc64_alloc_bus_tag(void *cookie, struct bus_space_tag *ptag, int type,
|
||||
void *barrier)
|
||||
{
|
||||
bus_space_tag_t bt;
|
||||
|
||||
bt = malloc(sizeof(struct bus_space_tag), M_DEVBUF, M_NOWAIT);
|
||||
if (bt == NULL)
|
||||
return (NULL);
|
||||
bt->bst_cookie = cookie;
|
||||
bt->bst_parent = ptag;
|
||||
bt->bst_type = type;
|
||||
bt->bst_bus_barrier = barrier;
|
||||
return (bt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Base bus space handlers.
|
||||
*/
|
||||
|
@ -90,6 +90,7 @@ static bus_teardown_intr_t nexus_teardown_intr;
|
||||
static bus_alloc_resource_t nexus_alloc_resource;
|
||||
static bus_activate_resource_t nexus_activate_resource;
|
||||
static bus_deactivate_resource_t nexus_deactivate_resource;
|
||||
static bus_adjust_resource_t nexus_adjust_resource;
|
||||
static bus_release_resource_t nexus_release_resource;
|
||||
static bus_get_resource_list_t nexus_get_resource_list;
|
||||
#ifdef SMP
|
||||
@ -122,6 +123,7 @@ static device_method_t nexus_methods[] = {
|
||||
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, nexus_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, nexus_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, nexus_release_resource),
|
||||
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
|
||||
@ -277,22 +279,22 @@ nexus_add_child(device_t dev, u_int order, const char *name, int unit)
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_print_child(device_t dev, device_t child)
|
||||
nexus_print_child(device_t bus, device_t child)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = bus_print_child_header(dev, child);
|
||||
rv = bus_print_child_header(bus, child);
|
||||
rv += nexus_print_res(device_get_ivars(child));
|
||||
rv += bus_print_child_footer(dev, child);
|
||||
rv += bus_print_child_footer(bus, child);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static void
|
||||
nexus_probe_nomatch(device_t dev, device_t child)
|
||||
nexus_probe_nomatch(device_t bus, device_t child)
|
||||
{
|
||||
const char *type;
|
||||
|
||||
device_printf(dev, "<%s>", ofw_bus_get_name(child));
|
||||
device_printf(bus, "<%s>", ofw_bus_get_name(child));
|
||||
nexus_print_res(device_get_ivars(child));
|
||||
type = ofw_bus_get_type(child);
|
||||
printf(" type %s (no driver attached)\n",
|
||||
@ -300,23 +302,24 @@ nexus_probe_nomatch(device_t dev, device_t child)
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
|
||||
driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
|
||||
nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r,
|
||||
int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
|
||||
void **cookiep)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (res == NULL)
|
||||
if (r == NULL)
|
||||
panic("%s: NULL interrupt resource!", __func__);
|
||||
|
||||
if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
|
||||
if ((rman_get_flags(r) & RF_SHAREABLE) == 0)
|
||||
flags |= INTR_EXCL;
|
||||
|
||||
/* We depend here on rman_activate_resource() being idempotent. */
|
||||
error = rman_activate_resource(res);
|
||||
error = rman_activate_resource(r);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = inthand_add(device_get_nameunit(child), rman_get_start(res),
|
||||
error = inthand_add(device_get_nameunit(child), rman_get_start(r),
|
||||
filt, intr, arg, flags, cookiep);
|
||||
|
||||
/*
|
||||
@ -328,7 +331,8 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
|
||||
nexus_teardown_intr(device_t bus __unused, device_t child __unused,
|
||||
struct resource *r, void *ih)
|
||||
{
|
||||
|
||||
inthand_remove(rman_get_start(r), ih);
|
||||
@ -337,7 +341,8 @@ nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
|
||||
|
||||
#ifdef SMP
|
||||
static int
|
||||
nexus_bind_intr(device_t dev, device_t child, struct resource *r, int cpu)
|
||||
nexus_bind_intr(device_t bus __unused, device_t child __unused,
|
||||
struct resource *r, int cpu)
|
||||
{
|
||||
|
||||
return (intr_bind(rman_get_start(r), cpu));
|
||||
@ -345,8 +350,8 @@ nexus_bind_intr(device_t dev, device_t child, struct resource *r, int cpu)
|
||||
#endif
|
||||
|
||||
static int
|
||||
nexus_describe_intr(device_t dev, device_t child, struct resource *r,
|
||||
void *cookie, const char *descr)
|
||||
nexus_describe_intr(device_t bus __unused, device_t child __unused,
|
||||
struct resource *r, void *cookie, const char *descr)
|
||||
{
|
||||
|
||||
return (intr_describe(rman_get_start(r), cookie, descr));
|
||||
@ -361,10 +366,9 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
struct resource *rv;
|
||||
struct resource_list_entry *rle;
|
||||
device_t nexus;
|
||||
int isdefault, needactivate, passthrough;
|
||||
int isdefault, passthrough;
|
||||
|
||||
isdefault = (start == 0UL && end == ~0UL);
|
||||
needactivate = flags & RF_ACTIVE;
|
||||
passthrough = (device_get_parent(child) != bus);
|
||||
nexus = bus;
|
||||
while (strcmp(device_get_name(device_get_parent(nexus)), "root") != 0)
|
||||
@ -397,21 +401,16 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
flags &= ~RF_ACTIVE;
|
||||
rv = rman_reserve_resource(rm, start, end, count, flags, child);
|
||||
rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
|
||||
child);
|
||||
if (rv == NULL)
|
||||
return (NULL);
|
||||
rman_set_rid(rv, *rid);
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
rman_set_bustag(rv, &nexus_bustag);
|
||||
rman_set_bushandle(rv, rman_get_start(rv));
|
||||
}
|
||||
|
||||
if (needactivate) {
|
||||
if (bus_activate_resource(child, type, *rid, rv) != 0) {
|
||||
rman_release_resource(rv);
|
||||
return (NULL);
|
||||
}
|
||||
if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
|
||||
*rid, rv) != 0) {
|
||||
rman_release_resource(rv);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (!passthrough) {
|
||||
@ -425,30 +424,61 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
nexus_activate_resource(device_t bus __unused, device_t child __unused,
|
||||
int type, int rid __unused, struct resource *r)
|
||||
{
|
||||
|
||||
/* Not much to be done yet... */
|
||||
if (type == SYS_RES_MEMORY) {
|
||||
rman_set_bustag(r, &nexus_bustag);
|
||||
rman_set_bushandle(r, rman_get_start(r));
|
||||
}
|
||||
return (rman_activate_resource(r));
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
nexus_deactivate_resource(device_t bus __unused, device_t child __unused,
|
||||
int type __unused, int rid __unused, struct resource *r)
|
||||
{
|
||||
|
||||
/* Not much to be done yet... */
|
||||
return (rman_deactivate_resource(r));
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
nexus_adjust_resource(device_t bus, device_t child __unused, int type,
|
||||
struct resource *r, u_long start, u_long end)
|
||||
{
|
||||
struct nexus_softc *sc;
|
||||
struct rman *rm;
|
||||
device_t nexus;
|
||||
|
||||
nexus = bus;
|
||||
while (strcmp(device_get_name(device_get_parent(nexus)), "root") != 0)
|
||||
nexus = device_get_parent(nexus);
|
||||
sc = device_get_softc(nexus);
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
rm = &sc->sc_intr_rman;
|
||||
break;
|
||||
case SYS_RES_MEMORY:
|
||||
rm = &sc->sc_mem_rman;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
if (rm == NULL)
|
||||
return (ENXIO);
|
||||
if (rman_is_region_manager(r, rm) == 0)
|
||||
return (EINVAL);
|
||||
return (rman_adjust_resource(r, start, end));
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_release_resource(device_t bus __unused, device_t child, int type,
|
||||
int rid, struct resource *r)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (rman_get_flags(r) & RF_ACTIVE) {
|
||||
if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
|
||||
error = bus_deactivate_resource(child, type, rid, r);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -457,7 +487,7 @@ nexus_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
}
|
||||
|
||||
static struct resource_list *
|
||||
nexus_get_resource_list(device_t dev, device_t child)
|
||||
nexus_get_resource_list(device_t bus __unused, device_t child)
|
||||
{
|
||||
struct nexus_devinfo *ndi;
|
||||
|
||||
@ -466,14 +496,14 @@ nexus_get_resource_list(device_t dev, device_t child)
|
||||
}
|
||||
|
||||
static bus_dma_tag_t
|
||||
nexus_get_dma_tag(device_t bus, device_t child)
|
||||
nexus_get_dma_tag(device_t bus __unused, device_t child __unused)
|
||||
{
|
||||
|
||||
return (&nexus_dmatag);
|
||||
}
|
||||
|
||||
static const struct ofw_bus_devinfo *
|
||||
nexus_get_devinfo(device_t dev, device_t child)
|
||||
nexus_get_devinfo(device_t bus __unused, device_t child)
|
||||
{
|
||||
struct nexus_devinfo *ndi;
|
||||
|
||||
|
@ -99,10 +99,11 @@ struct upa_softc {
|
||||
|
||||
static device_probe_t upa_probe;
|
||||
static device_attach_t upa_attach;
|
||||
static bus_alloc_resource_t upa_alloc_resource;
|
||||
static bus_setup_intr_t upa_setup_intr;
|
||||
static bus_print_child_t upa_print_child;
|
||||
static bus_probe_nomatch_t upa_probe_nomatch;
|
||||
static bus_alloc_resource_t upa_alloc_resource;
|
||||
static bus_adjust_resource_t upa_adjust_resource;
|
||||
static bus_setup_intr_t upa_setup_intr;
|
||||
static bus_get_resource_list_t upa_get_resource_list;
|
||||
static ofw_bus_get_devinfo_t upa_get_devinfo;
|
||||
|
||||
@ -130,6 +131,7 @@ static device_method_t upa_methods[] = {
|
||||
DEVMETHOD(bus_alloc_resource, upa_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_adjust_resource, upa_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
|
||||
DEVMETHOD(bus_setup_intr, upa_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
@ -506,6 +508,15 @@ upa_setup_intr(device_t dev, device_t child, struct resource *ires, int flags,
|
||||
arg, cookiep));
|
||||
}
|
||||
|
||||
static int
|
||||
upa_adjust_resource(device_t bus __unused, device_t child __unused,
|
||||
int type __unused, struct resource *r __unused, u_long start __unused,
|
||||
u_long end __unused)
|
||||
{
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static struct resource_list *
|
||||
upa_get_resource_list(device_t dev, device_t child)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user