- 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:
Marius Strobl 2005-03-19 00:50:28 +00:00
parent 4d9d925bbc
commit 771997501f
4 changed files with 66 additions and 38 deletions

View File

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

View File

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

View File

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

View File

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