Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_bus.c
| Show First 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | struct devclass { | ||||
| int maxunit; /* size of devices array */ | int maxunit; /* size of devices array */ | ||||
| int flags; | int flags; | ||||
| #define DC_HAS_CHILDREN 1 | #define DC_HAS_CHILDREN 1 | ||||
| struct sysctl_ctx_list sysctl_ctx; | struct sysctl_ctx_list sysctl_ctx; | ||||
| struct sysctl_oid *sysctl_tree; | struct sysctl_oid *sysctl_tree; | ||||
| }; | }; | ||||
| struct device_prop_elm { | |||||
| const char *name; | |||||
| void *val; | |||||
| void *dtr_ctx; | |||||
| device_prop_dtr_t dtr; | |||||
| LIST_ENTRY(device_prop_elm) link; | |||||
| }; | |||||
| static void device_destroy_props(device_t dev); | |||||
| /** | /** | ||||
| * @brief Implementation of _device. | * @brief Implementation of _device. | ||||
| * | * | ||||
| * The structure is named "_device" instead of "device" to avoid type confusion | * The structure is named "_device" instead of "device" to avoid type confusion | ||||
| * caused by other subsystems defining a (struct device). | * caused by other subsystems defining a (struct device). | ||||
| */ | */ | ||||
| struct _device { | struct _device { | ||||
| /* | /* | ||||
| Show All 20 Lines | struct _device { | ||||
| char* desc; /**< driver specific description */ | char* desc; /**< driver specific description */ | ||||
| u_int busy; /**< count of calls to device_busy() */ | u_int busy; /**< count of calls to device_busy() */ | ||||
| device_state_t state; /**< current device state */ | device_state_t state; /**< current device state */ | ||||
| uint32_t devflags; /**< api level flags for device_get_flags() */ | uint32_t devflags; /**< api level flags for device_get_flags() */ | ||||
| u_int flags; /**< internal device flags */ | u_int flags; /**< internal device flags */ | ||||
| u_int order; /**< order from device_add_child_ordered() */ | u_int order; /**< order from device_add_child_ordered() */ | ||||
| void *ivars; /**< instance variables */ | void *ivars; /**< instance variables */ | ||||
| void *softc; /**< current driver's variables */ | void *softc; /**< current driver's variables */ | ||||
| LIST_HEAD(, device_prop_elm) props; | |||||
| struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables */ | struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables */ | ||||
| struct sysctl_oid *sysctl_tree; /**< state for sysctl variables */ | struct sysctl_oid *sysctl_tree; /**< state for sysctl variables */ | ||||
| }; | }; | ||||
| 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"); | ||||
| ▲ Show 20 Lines • Show All 1,192 Lines • ▼ Show 20 Lines | if (devclass_add_device(dc, dev)) { | ||||
| kobj_delete((kobj_t) dev, M_BUS); | kobj_delete((kobj_t) dev, M_BUS); | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| } | } | ||||
| if (parent != NULL && device_has_quiet_children(parent)) | if (parent != NULL && device_has_quiet_children(parent)) | ||||
| dev->flags |= DF_QUIET | DF_QUIET_CHILDREN; | dev->flags |= DF_QUIET | DF_QUIET_CHILDREN; | ||||
| dev->ivars = NULL; | dev->ivars = NULL; | ||||
| dev->softc = NULL; | dev->softc = NULL; | ||||
| LIST_INIT(&dev->props); | |||||
| dev->state = DS_NOTPRESENT; | dev->state = DS_NOTPRESENT; | ||||
| TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink); | TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink); | ||||
| bus_data_generation_update(); | bus_data_generation_update(); | ||||
| return (dev); | return (dev); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | device_delete_child(device_t dev, device_t child) | ||||
| /* Delete any grandchildren left after detach. */ | /* Delete any grandchildren left after detach. */ | ||||
| while ((grandchild = TAILQ_FIRST(&child->children)) != NULL) { | while ((grandchild = TAILQ_FIRST(&child->children)) != NULL) { | ||||
| error = device_delete_child(child, grandchild); | error = device_delete_child(child, grandchild); | ||||
| if (error) | if (error) | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| device_destroy_props(dev); | |||||
| if (child->devclass) | if (child->devclass) | ||||
| devclass_delete_device(child->devclass, child); | devclass_delete_device(child->devclass, child); | ||||
| if (child->parent) | if (child->parent) | ||||
| BUS_CHILD_DELETED(dev, child); | BUS_CHILD_DELETED(dev, child); | ||||
| TAILQ_REMOVE(&dev->children, child, link); | TAILQ_REMOVE(&dev->children, child, link); | ||||
| TAILQ_REMOVE(&bus_data_devices, child, devlink); | TAILQ_REMOVE(&bus_data_devices, child, devlink); | ||||
| kobj_delete((kobj_t) child, M_BUS); | kobj_delete((kobj_t) child, M_BUS); | ||||
| ▲ Show 20 Lines • Show All 4,506 Lines • ▼ Show 20 Lines | if (sb != NULL) { | ||||
| } | } | ||||
| sbuf_delete(sb); | sbuf_delete(sb); | ||||
| } | } | ||||
| } | } | ||||
| if (error != 0 || res == NULL || res->dln_path == NULL) | if (error != 0 || res == NULL || res->dln_path == NULL) | ||||
| return (false); | return (false); | ||||
| return (strcmp(res->dln_path, cp) == 0); | return (strcmp(res->dln_path, cp) == 0); | ||||
| } | |||||
| static struct device_prop_elm * | |||||
| device_prop_find(device_t dev, const char *name) | |||||
| { | |||||
| struct device_prop_elm *e; | |||||
| bus_topo_assert(); | |||||
| LIST_FOREACH(e, &dev->props, link) { | |||||
| if (strcmp(name, e->name) == 0) | |||||
| return (e); | |||||
| } | |||||
| return (NULL); | |||||
| } | |||||
| int | |||||
| device_set_prop(device_t dev, const char *name, void *val, | |||||
| device_prop_dtr_t dtr, void *dtr_ctx) | |||||
| { | |||||
| struct device_prop_elm *e, *e1; | |||||
| bus_topo_assert(); | |||||
| e = device_prop_find(dev, name); | |||||
| if (e != NULL) | |||||
| goto found; | |||||
| e1 = malloc(sizeof(*e), M_BUS, M_WAITOK); | |||||
| e = device_prop_find(dev, name); | |||||
| if (e != NULL) { | |||||
| free(e1, M_BUS); | |||||
| goto found; | |||||
| } | |||||
| e1->name = name; | |||||
| e1->val = val; | |||||
| e1->dtr = dtr; | |||||
| e1->dtr_ctx = dtr_ctx; | |||||
| LIST_INSERT_HEAD(&dev->props, e1, link); | |||||
| return (0); | |||||
| found: | |||||
| LIST_REMOVE(e, link); | |||||
| if (e->dtr != NULL) | |||||
| e->dtr(dev, name, e->val, e->dtr_ctx); | |||||
| e->val = val; | |||||
| e->dtr = dtr; | |||||
| e->dtr_ctx = dtr_ctx; | |||||
| LIST_INSERT_HEAD(&dev->props, e, link); | |||||
| return (EEXIST); | |||||
| } | |||||
| int | |||||
| device_get_prop(device_t dev, const char *name, void **valp) | |||||
| { | |||||
| struct device_prop_elm *e; | |||||
| bus_topo_assert(); | |||||
| e = device_prop_find(dev, name); | |||||
| if (e == NULL) | |||||
| return (ENOENT); | |||||
| *valp = e->val; | |||||
| return (0); | |||||
| } | |||||
| int | |||||
| device_clear_prop(device_t dev, const char *name) | |||||
| { | |||||
| struct device_prop_elm *e; | |||||
| bus_topo_assert(); | |||||
| e = device_prop_find(dev, name); | |||||
| if (e == NULL) | |||||
| return (ENOENT); | |||||
| LIST_REMOVE(e, link); | |||||
| if (e->dtr != NULL) | |||||
| e->dtr(dev, e->name, e->val, e->dtr_ctx); | |||||
| free(e, M_BUS); | |||||
| return (0); | |||||
| } | |||||
| static void | |||||
| device_destroy_props(device_t dev) | |||||
| { | |||||
| struct device_prop_elm *e; | |||||
| bus_topo_assert(); | |||||
| while ((e = LIST_FIRST(&dev->props)) != NULL) { | |||||
| LIST_REMOVE_HEAD(&dev->props, link); | |||||
| if (e->dtr != NULL) | |||||
| e->dtr(dev, e->name, e->val, e->dtr_ctx); | |||||
| free(e, M_BUS); | |||||
| } | |||||
| } | |||||
| void | |||||
| device_clear_prop_alldev(const char *name) | |||||
| { | |||||
| device_t dev; | |||||
| TAILQ_FOREACH(dev, &bus_data_devices, devlink) { | |||||
| device_clear_prop(dev, name); | |||||
| } | |||||
| } | } | ||||
| /* | /* | ||||
| * APIs to manage deprecation and obsolescence. | * APIs to manage deprecation and obsolescence. | ||||
| */ | */ | ||||
| static int obsolete_panic = 0; | static int obsolete_panic = 0; | ||||
| SYSCTL_INT(_debug, OID_AUTO, obsolete_panic, CTLFLAG_RWTUN, &obsolete_panic, 0, | SYSCTL_INT(_debug, OID_AUTO, obsolete_panic, CTLFLAG_RWTUN, &obsolete_panic, 0, | ||||
| "Panic when obsolete features are used (0 = never, 1 = if obsolete, " | "Panic when obsolete features are used (0 = never, 1 = if obsolete, " | ||||
| ▲ Show 20 Lines • Show All 70 Lines • Show Last 20 Lines | |||||