Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_bus.c
Show First 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | |||||
static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures"); | static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures"); | ||||
static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc"); | static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc"); | ||||
EVENTHANDLER_LIST_DEFINE(device_attach); | EVENTHANDLER_LIST_DEFINE(device_attach); | ||||
EVENTHANDLER_LIST_DEFINE(device_detach); | EVENTHANDLER_LIST_DEFINE(device_detach); | ||||
EVENTHANDLER_LIST_DEFINE(dev_lookup); | EVENTHANDLER_LIST_DEFINE(dev_lookup); | ||||
static int bus_child_location_sb(device_t child, struct sbuf *sb); | |||||
static int bus_child_pnpinfo_sb(device_t child, struct sbuf *sb); | |||||
static void devctl2_init(void); | static void devctl2_init(void); | ||||
static bool device_frozen; | static bool device_frozen; | ||||
#define DRIVERNAME(d) ((d)? d->name : "no driver") | #define DRIVERNAME(d) ((d)? d->name : "no driver") | ||||
#define DEVCLANAME(d) ((d)? d->name : "no devclass") | #define DEVCLANAME(d) ((d)? d->name : "no devclass") | ||||
#ifdef BUS_DEBUG | #ifdef BUS_DEBUG | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | device_sysctl_handler(SYSCTL_HANDLER_ARGS) | ||||
switch (arg2) { | switch (arg2) { | ||||
case DEVICE_SYSCTL_DESC: | case DEVICE_SYSCTL_DESC: | ||||
sbuf_cat(&sb, dev->desc ? dev->desc : ""); | sbuf_cat(&sb, dev->desc ? dev->desc : ""); | ||||
break; | break; | ||||
case DEVICE_SYSCTL_DRIVER: | case DEVICE_SYSCTL_DRIVER: | ||||
sbuf_cat(&sb, dev->driver ? dev->driver->name : ""); | sbuf_cat(&sb, dev->driver ? dev->driver->name : ""); | ||||
break; | break; | ||||
case DEVICE_SYSCTL_LOCATION: | case DEVICE_SYSCTL_LOCATION: | ||||
bus_child_location_sb(dev, &sb); | bus_child_location(dev, &sb); | ||||
break; | break; | ||||
case DEVICE_SYSCTL_PNPINFO: | case DEVICE_SYSCTL_PNPINFO: | ||||
bus_child_pnpinfo_sb(dev, &sb); | bus_child_pnpinfo(dev, &sb); | ||||
break; | break; | ||||
case DEVICE_SYSCTL_PARENT: | case DEVICE_SYSCTL_PARENT: | ||||
sbuf_cat(&sb, dev->parent ? dev->parent->nameunit : ""); | sbuf_cat(&sb, dev->parent ? dev->parent->nameunit : ""); | ||||
break; | break; | ||||
default: | default: | ||||
sbuf_delete(&sb); | sbuf_delete(&sb); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 440 Lines • ▼ Show 20 Lines | devaddq(const char *type, const char *what, device_t dev) | ||||
dei = devctl_alloc_dei_sb(&sb); | dei = devctl_alloc_dei_sb(&sb); | ||||
if (dei == NULL) | if (dei == NULL) | ||||
return; | return; | ||||
sbuf_cpy(&sb, type); | sbuf_cpy(&sb, type); | ||||
sbuf_cat(&sb, what); | sbuf_cat(&sb, what); | ||||
sbuf_cat(&sb, " at "); | sbuf_cat(&sb, " at "); | ||||
/* Add in the location */ | /* Add in the location */ | ||||
bus_child_location_sb(dev, &sb); | bus_child_location(dev, &sb); | ||||
sbuf_putc(&sb, ' '); | sbuf_putc(&sb, ' '); | ||||
/* Add in pnpinfo */ | /* Add in pnpinfo */ | ||||
bus_child_pnpinfo_sb(dev, &sb); | bus_child_pnpinfo(dev, &sb); | ||||
/* Get the parent of this device, or / if high enough in the tree. */ | /* Get the parent of this device, or / if high enough in the tree. */ | ||||
if (device_get_parent(dev) == NULL) | if (device_get_parent(dev) == NULL) | ||||
parstr = "."; /* Or '/' ? */ | parstr = "."; /* Or '/' ? */ | ||||
else | else | ||||
parstr = device_get_nameunit(device_get_parent(dev)); | parstr = device_get_nameunit(device_get_parent(dev)); | ||||
sbuf_cat(&sb, " on "); | sbuf_cat(&sb, " on "); | ||||
sbuf_cat(&sb, parstr); | sbuf_cat(&sb, parstr); | ||||
▲ Show 20 Lines • Show All 4,190 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
int | int | ||||
bus_child_present(device_t child) | bus_child_present(device_t child) | ||||
{ | { | ||||
return (BUS_CHILD_PRESENT(device_get_parent(child), child)); | return (BUS_CHILD_PRESENT(device_get_parent(child), child)); | ||||
} | } | ||||
/** | /** | ||||
* @brief Wrapper function for BUS_CHILD_PNPINFO_STR(). | * @brief Wrapper function for BUS_CHILD_PNPINFO(). | ||||
* | * | ||||
* This function simply calls the BUS_CHILD_PNPINFO_STR() method of the | * This function simply calls the BUS_CHILD_PNPINFO() method of the parent of @p | ||||
* parent of @p dev. | * dev. | ||||
*/ | */ | ||||
int | int | ||||
bus_child_pnpinfo_str(device_t child, char *buf, size_t buflen) | bus_child_pnpinfo(device_t child, struct sbuf *sb) | ||||
{ | { | ||||
device_t parent; | device_t parent; | ||||
parent = device_get_parent(child); | parent = device_get_parent(child); | ||||
if (parent == NULL) { | if (parent == NULL) | ||||
*buf = '\0'; | |||||
return (0); | return (0); | ||||
return (BUS_CHILD_PNPINFO(parent, child, sb)); | |||||
} | } | ||||
return (BUS_CHILD_PNPINFO_STR(parent, child, buf, buflen)); | |||||
} | |||||
/** | /** | ||||
* @brief Wrapper function for BUS_CHILD_LOCATION_STR(). | * @brief Generic implementation that does nothing for bus_child_pnpinfo | ||||
* | * | ||||
* This function simply calls the BUS_CHILD_LOCATION_STR() method of the | * This function has the right signature and returns 0 since the sbuf is passed | ||||
* parent of @p dev. | * to us to append to. | ||||
*/ | */ | ||||
int | int | ||||
bus_child_location_str(device_t child, char *buf, size_t buflen) | bus_generic_child_pnpinfo(device_t dev, device_t child, struct sbuf *sb) | ||||
{ | { | ||||
device_t parent; | |||||
parent = device_get_parent(child); | |||||
if (parent == NULL) { | |||||
*buf = '\0'; | |||||
return (0); | return (0); | ||||
} | } | ||||
return (BUS_CHILD_LOCATION_STR(parent, child, buf, buflen)); | |||||
} | |||||
/** | /** | ||||
* @brief Wrapper function for bus_child_pnpinfo_str using sbuf | * @brief Wrapper function for BUS_CHILD_LOCATION(). | ||||
* | * | ||||
* A convenient wrapper frunction for bus_child_pnpinfo_str that allows | * This function simply calls the BUS_CHILD_LOCATION() method of the parent of | ||||
* us to splat that into an sbuf. It uses unholy knowledge of sbuf to | * @p dev. | ||||
* accomplish this, however. It is an interim function until we can convert | |||||
* this interface more fully. | |||||
*/ | */ | ||||
/* Note: we reach inside of sbuf because it's API isn't rich enough to do this */ | int | ||||
#define SPACE(s) ((s)->s_size - (s)->s_len) | bus_child_location(device_t child, struct sbuf *sb) | ||||
#define EOB(s) ((s)->s_buf + (s)->s_len) | |||||
static int | |||||
bus_child_pnpinfo_sb(device_t dev, struct sbuf *sb) | |||||
{ | { | ||||
char *p; | device_t parent; | ||||
ssize_t space; | |||||
MPASS((sb->s_flags & SBUF_INCLUDENUL) == 0); | parent = device_get_parent(child); | ||||
MPASS(sb->s_size >= sb->s_len); | if (parent == NULL) | ||||
if (sb->s_error != 0) | |||||
return (-1); | |||||
space = SPACE(sb); | |||||
if (space <= 1) { | |||||
sb->s_error = ENOMEM; | |||||
return (-1); | |||||
} | |||||
p = EOB(sb); | |||||
*p = '\0'; /* sbuf buffer isn't NUL terminated until sbuf_finish() */ | |||||
bus_child_pnpinfo_str(dev, p, space); | |||||
sb->s_len += strlen(p); | |||||
return (0); | return (0); | ||||
return (BUS_CHILD_LOCATION(parent, child, sb)); | |||||
} | } | ||||
/** | /** | ||||
* @brief Wrapper function for bus_child_pnpinfo_str using sbuf | * @brief Generic implementation that does nothing for bus_child_location | ||||
* | * | ||||
* A convenient wrapper frunction for bus_child_pnpinfo_str that allows | * This function has the right signature and returns 0 since the sbuf is passed | ||||
* us to splat that into an sbuf. It uses unholy knowledge of sbuf to | * to us to append to. | ||||
* accomplish this, however. It is an interim function until we can convert | |||||
* this interface more fully. | |||||
*/ | */ | ||||
static int | int | ||||
bus_child_location_sb(device_t dev, struct sbuf *sb) | bus_generic_child_location(device_t dev, device_t child, struct sbuf *sb) | ||||
{ | { | ||||
char *p; | |||||
ssize_t space; | |||||
MPASS((sb->s_flags & SBUF_INCLUDENUL) == 0); | |||||
MPASS(sb->s_size >= sb->s_len); | |||||
if (sb->s_error != 0) | |||||
return (-1); | |||||
space = SPACE(sb); | |||||
if (space <= 1) { | |||||
sb->s_error = ENOMEM; | |||||
return (-1); | |||||
} | |||||
p = EOB(sb); | |||||
*p = '\0'; /* sbuf buffer isn't NUL terminated until sbuf_finish() */ | |||||
bus_child_location_str(dev, p, space); | |||||
sb->s_len += strlen(p); | |||||
return (0); | return (0); | ||||
} | } | ||||
#undef SPACE | |||||
#undef EOB | |||||
/** | /** | ||||
* @brief Wrapper function for BUS_GET_CPUS(). | * @brief Wrapper function for BUS_GET_CPUS(). | ||||
* | * | ||||
* This function simply calls the BUS_GET_CPUS() method of the | * This function simply calls the BUS_GET_CPUS() method of the | ||||
* parent of @p dev. | * parent of @p dev. | ||||
*/ | */ | ||||
int | int | ||||
▲ Show 20 Lines • Show All 514 Lines • ▼ Show 20 Lines | if (dev->nameunit != NULL) | ||||
sbuf_cat(&sb, dev->nameunit); | sbuf_cat(&sb, dev->nameunit); | ||||
sbuf_putc(&sb, '\0'); | sbuf_putc(&sb, '\0'); | ||||
if (dev->desc != NULL) | if (dev->desc != NULL) | ||||
sbuf_cat(&sb, dev->desc); | sbuf_cat(&sb, dev->desc); | ||||
sbuf_putc(&sb, '\0'); | sbuf_putc(&sb, '\0'); | ||||
if (dev->driver != NULL) | if (dev->driver != NULL) | ||||
sbuf_cat(&sb, dev->driver->name); | sbuf_cat(&sb, dev->driver->name); | ||||
sbuf_putc(&sb, '\0'); | sbuf_putc(&sb, '\0'); | ||||
bus_child_pnpinfo_sb(dev, &sb); | bus_child_pnpinfo(dev, &sb); | ||||
sbuf_putc(&sb, '\0'); | sbuf_putc(&sb, '\0'); | ||||
bus_child_location_sb(dev, &sb); | bus_child_location(dev, &sb); | ||||
sbuf_putc(&sb, '\0'); | sbuf_putc(&sb, '\0'); | ||||
error = sbuf_finish(&sb); | error = sbuf_finish(&sb); | ||||
if (error == 0) | if (error == 0) | ||||
error = SYSCTL_OUT(req, udev, sizeof(*udev)); | error = SYSCTL_OUT(req, udev, sizeof(*udev)); | ||||
sbuf_delete(&sb); | sbuf_delete(&sb); | ||||
free(udev, M_BUS); | free(udev, M_BUS); | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 485 Lines • Show Last 20 Lines |