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:
Marius Strobl 2011-10-02 23:22:38 +00:00
parent 6ec3cd078c
commit bda8e754a1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=225931
22 changed files with 685 additions and 551 deletions

View File

@ -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);

View File

@ -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),

View File

@ -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)
{

View File

@ -19,3 +19,5 @@ options GEOM_PART_VTOC8
# Let sunkbd emulate an AT keyboard by default.
options SUNKBD_EMULATE_ATKBD
#options NEW_PCIB

View File

@ -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

View File

@ -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)
{

View File

@ -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) \

View File

@ -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;

View File

@ -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));
}

View File

@ -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)
{

View File

@ -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;

View File

@ -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>

View File

@ -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);
}

View File

@ -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;

View File

@ -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));
}
/*

View File

@ -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)
{

View File

@ -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;

View File

@ -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),

View File

@ -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)
{

View File

@ -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.
*/

View File

@ -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;

View File

@ -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)
{