- Add a device interface method for bus_get_resource_list() and use
bus_generic_rl_release_resource() for the bus_release_resource() method instead of a local copy. - Correctly handle pass-through allocations in fhc_alloc_resource(). - In case the board model can't be determined just print "unknown model" so the physical slot number is reported in any case. - Add support for blinking the 'Cycling' LED of boards on a fhc(4) hanging of off the nexus (i.e. all boards except the clock board) via led(4). All boards have at least 3 controllable status LEDs, 'Power', 'Failure' and 'Cycling'. While the 'Cycling' LED is suitable for signaling from the OS the others are better off being controlled by the firmware. The device name for the 'Cycling' LED of each board is /dev/led/boardX where X is the physical slot number of the board. [1] Obtained from: OpenBSD [1] Tested by: joerg [1]
This commit is contained in:
parent
4d9d925bbc
commit
771997501f
@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/pcpu.h>
|
||||
|
||||
#include <dev/led/led.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
@ -65,6 +66,7 @@ struct fhc_devinfo {
|
||||
};
|
||||
|
||||
static void fhc_intr_stub(void *);
|
||||
static void fhc_led_func(void *, int);
|
||||
|
||||
int
|
||||
fhc_probe(device_t dev)
|
||||
@ -76,6 +78,7 @@ fhc_probe(device_t dev)
|
||||
int
|
||||
fhc_attach(device_t dev)
|
||||
{
|
||||
char ledname[sizeof("boardXX")];
|
||||
struct fhc_devinfo *fdi;
|
||||
struct sbus_regs *reg;
|
||||
struct fhc_softc *sc;
|
||||
@ -95,10 +98,12 @@ fhc_attach(device_t dev)
|
||||
sc = device_get_softc(dev);
|
||||
node = sc->sc_node;
|
||||
|
||||
device_printf(dev, "board %d, ", sc->sc_board);
|
||||
if (OF_getprop_alloc(node, "board-model", 1, (void **)&name) != -1) {
|
||||
device_printf(dev, "board %d, %s\n", sc->sc_board, name);
|
||||
printf("model %s\n", name);
|
||||
free(name, M_OFWPROP);
|
||||
}
|
||||
} else
|
||||
printf("model unknown\n");
|
||||
|
||||
for (i = FHC_FANFAIL; i <= FHC_TOD; i++) {
|
||||
bus_space_write_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR, 0x0);
|
||||
@ -118,8 +123,8 @@ fhc_attach(device_t dev)
|
||||
ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE);
|
||||
bus_space_write_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
|
||||
FHC_CTRL, ctrl);
|
||||
ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
|
||||
sc->sc_bh[FHC_INTERNAL], FHC_CTRL);
|
||||
bus_space_read_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
|
||||
FHC_CTRL);
|
||||
|
||||
sc->sc_nrange = OF_getprop_alloc(node, "ranges",
|
||||
sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges);
|
||||
@ -128,6 +133,11 @@ fhc_attach(device_t dev)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if ((sc->sc_flags & FHC_CENTRAL) == 0) {
|
||||
snprintf(ledname, sizeof(ledname), "board%d", sc->sc_board);
|
||||
sc->sc_led_dev = led_create(fhc_led_func, sc, ledname);
|
||||
}
|
||||
|
||||
for (child = OF_child(node); child != 0; child = OF_peer(child)) {
|
||||
if ((OF_getprop_alloc(child, "name", 1, (void **)&name)) == -1)
|
||||
continue;
|
||||
@ -291,36 +301,41 @@ struct resource *
|
||||
fhc_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
struct resource_list *rl;
|
||||
struct resource_list_entry *rle;
|
||||
struct fhc_devinfo *fdi;
|
||||
struct fhc_softc *sc;
|
||||
struct resource *res;
|
||||
bus_addr_t coffset;
|
||||
bus_addr_t cend;
|
||||
bus_addr_t phys;
|
||||
int isdefault;
|
||||
int passthrough;
|
||||
int i;
|
||||
|
||||
isdefault = (start == 0UL && end == ~0UL);
|
||||
passthrough = (device_get_parent(child) != bus);
|
||||
res = NULL;
|
||||
rle = NULL;
|
||||
rl = BUS_GET_RESOURCE_LIST(bus, child);
|
||||
sc = device_get_softc(bus);
|
||||
fdi = device_get_ivars(child);
|
||||
rle = resource_list_find(&fdi->fdi_rl, type, *rid);
|
||||
if (rle == NULL)
|
||||
return (NULL);
|
||||
if (rle->res != NULL)
|
||||
panic("%s: resource entry is busy", __func__);
|
||||
if (isdefault) {
|
||||
start = rle->start;
|
||||
count = ulmax(count, rle->count);
|
||||
end = ulmax(rle->end, start + count - 1);
|
||||
}
|
||||
rle = resource_list_find(rl, type, *rid);
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
res = bus_generic_alloc_resource(bus, child, type, rid,
|
||||
start, end, count, flags);
|
||||
return (resource_list_alloc(rl, bus, child, type, rid, start,
|
||||
end, count, flags));
|
||||
break;
|
||||
case SYS_RES_MEMORY:
|
||||
if (!passthrough) {
|
||||
if (rle == NULL)
|
||||
return (NULL);
|
||||
if (rle->res != NULL)
|
||||
panic("%s: resource entry is busy", __func__);
|
||||
if (isdefault) {
|
||||
start = rle->start;
|
||||
count = ulmax(count, rle->count);
|
||||
end = ulmax(rle->end, start + count - 1);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < sc->sc_nrange; i++) {
|
||||
coffset = sc->sc_ranges[i].coffset;
|
||||
cend = coffset + sc->sc_ranges[i].size - 1;
|
||||
@ -332,7 +347,8 @@ fhc_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
res = bus_generic_alloc_resource(bus, child,
|
||||
type, rid, phys + start, phys + end,
|
||||
count, flags);
|
||||
rle->res = res;
|
||||
if (!passthrough)
|
||||
rle->res = res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -343,25 +359,34 @@ fhc_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
fhc_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
struct resource_list *
|
||||
fhc_get_resource_list(device_t bus, device_t child)
|
||||
{
|
||||
struct resource_list_entry *rle;
|
||||
struct fhc_devinfo *fdi;
|
||||
int error;
|
||||
|
||||
error = bus_generic_release_resource(bus, child, type, rid, r);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
fdi = device_get_ivars(child);
|
||||
rle = resource_list_find(&fdi->fdi_rl, type, rid);
|
||||
if (rle == NULL)
|
||||
panic("%s: can't find resource", __func__);
|
||||
if (rle->res == NULL)
|
||||
panic("%s: resource entry is not busy", __func__);
|
||||
rle->res = NULL;
|
||||
return (error);
|
||||
return (&fdi->fdi_rl);
|
||||
}
|
||||
|
||||
static void
|
||||
fhc_led_func(void *arg, int onoff)
|
||||
{
|
||||
struct fhc_softc *sc;
|
||||
uint32_t ctrl;
|
||||
|
||||
sc = (struct fhc_softc *)arg;
|
||||
|
||||
ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
|
||||
sc->sc_bh[FHC_INTERNAL], FHC_CTRL);
|
||||
if (onoff)
|
||||
ctrl |= FHC_CTRL_RLED;
|
||||
else
|
||||
ctrl &= ~FHC_CTRL_RLED;
|
||||
ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE);
|
||||
bus_space_write_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
|
||||
FHC_CTRL, ctrl);
|
||||
bus_space_read_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
|
||||
FHC_CTRL);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
@ -58,9 +58,10 @@ static device_method_t fhc_central_methods[] = {
|
||||
DEVMETHOD(bus_setup_intr, fhc_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, fhc_teardown_intr),
|
||||
DEVMETHOD(bus_alloc_resource, fhc_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, fhc_release_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),
|
||||
DEVMETHOD(bus_get_resource_list, fhc_get_resource_list),
|
||||
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_compat, fhc_get_compat),
|
||||
|
@ -61,9 +61,10 @@ static device_method_t fhc_nexus_methods[] = {
|
||||
DEVMETHOD(bus_setup_intr, fhc_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, fhc_teardown_intr),
|
||||
DEVMETHOD(bus_alloc_resource, fhc_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, fhc_release_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),
|
||||
DEVMETHOD(bus_get_resource_list, fhc_get_resource_list),
|
||||
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_compat, fhc_get_compat),
|
||||
|
@ -41,6 +41,7 @@ struct fhc_softc {
|
||||
int sc_board;
|
||||
int sc_ign;
|
||||
int sc_flags;
|
||||
struct cdev *sc_led_dev;
|
||||
};
|
||||
|
||||
device_probe_t fhc_probe;
|
||||
@ -51,7 +52,7 @@ bus_probe_nomatch_t fhc_probe_nomatch;
|
||||
bus_setup_intr_t fhc_setup_intr;
|
||||
bus_teardown_intr_t fhc_teardown_intr;
|
||||
bus_alloc_resource_t fhc_alloc_resource;
|
||||
bus_release_resource_t fhc_release_resource;
|
||||
bus_get_resource_list_t fhc_get_resource_list;
|
||||
|
||||
ofw_bus_get_compat_t fhc_get_compat;
|
||||
ofw_bus_get_model_t fhc_get_model;
|
||||
@ -59,4 +60,4 @@ ofw_bus_get_name_t fhc_get_name;
|
||||
ofw_bus_get_node_t fhc_get_node;
|
||||
ofw_bus_get_type_t fhc_get_type;
|
||||
|
||||
#endif
|
||||
#endif /* !_SPARC64_FHC_FHCVAR_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user