Changeset View
Changeset View
Standalone View
Standalone View
stand/kshim/bsd_kernel.c
| Show First 20 Lines • Show All 548 Lines • ▼ Show 20 Lines | |||||
| /*------------------------------------------------------------------------* | /*------------------------------------------------------------------------* | ||||
| * Implementation of device API | * Implementation of device API | ||||
| *------------------------------------------------------------------------*/ | *------------------------------------------------------------------------*/ | ||||
| static const char unknown_string[] = { "unknown" }; | static const char unknown_string[] = { "unknown" }; | ||||
| static TAILQ_HEAD(, module_data) module_head = | static TAILQ_HEAD(, module_data) module_head = | ||||
| TAILQ_HEAD_INITIALIZER(module_head); | TAILQ_HEAD_INITIALIZER(module_head); | ||||
| static TAILQ_HEAD(, devclass) devclasses = | |||||
| TAILQ_HEAD_INITIALIZER(devclasses); | |||||
| static uint8_t | static uint8_t | ||||
| devclass_equal(const char *a, const char *b) | devclass_equal(const char *a, const char *b) | ||||
| { | { | ||||
| char ta, tb; | char ta, tb; | ||||
| if (a == b) | if (a == b) | ||||
| return (1); | return (1); | ||||
| ▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | |||||
| device_get_nameunit(device_t dev) | device_get_nameunit(device_t dev) | ||||
| { | { | ||||
| if (dev && dev->dev_nameunit[0]) | if (dev && dev->dev_nameunit[0]) | ||||
| return (dev->dev_nameunit); | return (dev->dev_nameunit); | ||||
| return (unknown_string); | return (unknown_string); | ||||
| } | } | ||||
| static uint8_t | static devclass_t | ||||
| devclass_create(devclass_t *dc_pp) | devclass_create(const char *classname) | ||||
| { | { | ||||
| if (dc_pp == NULL) { | devclass_t dc; | ||||
| return (1); | |||||
| } | |||||
| if (dc_pp[0] == NULL) { | |||||
| dc_pp[0] = malloc(sizeof(**(dc_pp)), | |||||
| M_DEVBUF, M_WAITOK | M_ZERO); | |||||
| if (dc_pp[0] == NULL) { | dc = malloc(sizeof(*dc), M_DEVBUF, M_WAITOK | M_ZERO); | ||||
| return (1); | if (dc == NULL) { | ||||
| return (NULL); | |||||
| } | } | ||||
| dc->name = classname; | |||||
| TAILQ_INSERT_TAIL(&devclasses, dc, link); | |||||
| return (dc); | |||||
| } | } | ||||
| return (0); | |||||
| } | |||||
| static const struct module_data * | static devclass_t | ||||
| devclass_find_create(const char *classname) | devclass_find_create(const char *classname) | ||||
| { | { | ||||
| const struct module_data *mod; | devclass_t dc; | ||||
| TAILQ_FOREACH(mod, &module_head, entry) { | dc = devclass_find(classname); | ||||
| if (devclass_equal(mod->mod_name, classname)) { | if (dc == NULL) | ||||
| if (devclass_create(mod->devclass_pp)) { | dc = devclass_create(classname); | ||||
| continue; | return (dc); | ||||
| } | } | ||||
| return (mod); | |||||
| } | |||||
| } | |||||
| return (NULL); | |||||
| } | |||||
| static uint8_t | static uint8_t | ||||
| devclass_add_device(const struct module_data *mod, device_t dev) | devclass_add_device(devclass_t dc, device_t dev) | ||||
| { | { | ||||
| device_t *pp_dev; | device_t *pp_dev; | ||||
| device_t *end; | device_t *end; | ||||
| uint8_t unit; | uint8_t unit; | ||||
| pp_dev = mod->devclass_pp[0]->dev_list; | pp_dev = dc->dev_list; | ||||
| end = pp_dev + DEVCLASS_MAXUNIT; | end = pp_dev + DEVCLASS_MAXUNIT; | ||||
| unit = 0; | unit = 0; | ||||
| while (pp_dev != end) { | while (pp_dev != end) { | ||||
| if (*pp_dev == NULL) { | if (*pp_dev == NULL) { | ||||
| *pp_dev = dev; | *pp_dev = dev; | ||||
| dev->dev_class = dc; | |||||
| dev->dev_unit = unit; | dev->dev_unit = unit; | ||||
| dev->dev_module = mod; | |||||
| snprintf(dev->dev_nameunit, | snprintf(dev->dev_nameunit, | ||||
| sizeof(dev->dev_nameunit), | sizeof(dev->dev_nameunit), | ||||
| "%s%d", device_get_name(dev), unit); | "%s%d", dc->name, unit); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| pp_dev++; | pp_dev++; | ||||
| unit++; | unit++; | ||||
| } | } | ||||
| DPRINTF("Could not add device to devclass.\n"); | DPRINTF("Could not add device to devclass.\n"); | ||||
| return (1); | return (1); | ||||
| } | } | ||||
| static void | static void | ||||
| devclass_delete_device(const struct module_data *mod, device_t dev) | devclass_delete_device(devclass_t dc, device_t dev) | ||||
| { | { | ||||
| if (mod == NULL) { | if (dc == NULL) { | ||||
| return; | return; | ||||
| } | } | ||||
| mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL; | dc->dev_list[dev->dev_unit] = NULL; | ||||
| dev->dev_module = NULL; | dev->dev_class = NULL; | ||||
| } | } | ||||
| static device_t | static device_t | ||||
| make_device(device_t parent, const char *name) | make_device(device_t parent, const char *name) | ||||
| { | { | ||||
| device_t dev = NULL; | device_t dev = NULL; | ||||
| const struct module_data *mod = NULL; | devclass_t dc = NULL; | ||||
| if (name) { | if (name) { | ||||
| mod = devclass_find_create(name); | dc = devclass_find_create(name); | ||||
| if (!mod) { | if (!dc) { | ||||
| DPRINTF("%s:%d:%s: can't find device " | DPRINTF("%s:%d:%s: can't find device " | ||||
| "class %s\n", __FILE__, __LINE__, | "class %s\n", __FILE__, __LINE__, | ||||
| __FUNCTION__, name); | __FUNCTION__, name); | ||||
| goto done; | goto done; | ||||
| } | } | ||||
| } | } | ||||
| dev = malloc(sizeof(*dev), | dev = malloc(sizeof(*dev), | ||||
| M_DEVBUF, M_WAITOK | M_ZERO); | M_DEVBUF, M_WAITOK | M_ZERO); | ||||
| if (dev == NULL) | if (dev == NULL) | ||||
| goto done; | goto done; | ||||
| dev->dev_parent = parent; | dev->dev_parent = parent; | ||||
| TAILQ_INIT(&dev->dev_children); | TAILQ_INIT(&dev->dev_children); | ||||
| if (name) { | if (name) { | ||||
| dev->dev_fixed_class = 1; | dev->dev_fixed_class = 1; | ||||
| if (devclass_add_device(mod, dev)) { | if (devclass_add_device(dc, dev)) { | ||||
| goto error; | goto error; | ||||
| } | } | ||||
| } | } | ||||
| done: | done: | ||||
| return (dev); | return (dev); | ||||
| error: | error: | ||||
| if (dev) { | if (dev) { | ||||
| Show All 39 Lines | device_delete_child(device_t dev, device_t child) | ||||
| while ((grandchild = TAILQ_FIRST(&child->dev_children))) { | while ((grandchild = TAILQ_FIRST(&child->dev_children))) { | ||||
| error = device_delete_child(child, grandchild); | error = device_delete_child(child, grandchild); | ||||
| if (error) { | if (error) { | ||||
| device_printf(dev, "Error deleting child!\n"); | device_printf(dev, "Error deleting child!\n"); | ||||
| goto done; | goto done; | ||||
| } | } | ||||
| } | } | ||||
| devclass_delete_device(child->dev_module, child); | if (child->dev_class != NULL) | ||||
| devclass_delete_device(child->dev_class, child); | |||||
| if (dev != NULL) { | if (dev != NULL) { | ||||
| /* remove child from parent */ | /* remove child from parent */ | ||||
| TAILQ_REMOVE(&dev->dev_children, child, dev_link); | TAILQ_REMOVE(&dev->dev_children, child, dev_link); | ||||
| } | } | ||||
| free(child, M_DEVBUF); | free(child, M_DEVBUF); | ||||
| done: | done: | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | while (mtod->func != NULL) { | ||||
| mtod++; | mtod++; | ||||
| } | } | ||||
| return ((void *)&default_method); | return ((void *)&default_method); | ||||
| } | } | ||||
| const char * | const char * | ||||
| device_get_name(device_t dev) | device_get_name(device_t dev) | ||||
| { | { | ||||
| if (dev == NULL) | if (dev == NULL || dev->dev_module == NULL) | ||||
| return (unknown_string); | return (unknown_string); | ||||
| return (dev->dev_module->driver->name); | return (dev->dev_module->driver->name); | ||||
| } | } | ||||
| static int | static int | ||||
| device_allocate_softc(device_t dev) | device_allocate_softc(device_t dev) | ||||
| { | { | ||||
| Show All 14 Lines | device_allocate_softc(device_t dev) | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| int | int | ||||
| device_probe_and_attach(device_t dev) | device_probe_and_attach(device_t dev) | ||||
| { | { | ||||
| const struct module_data *mod; | const struct module_data *mod; | ||||
| const char *bus_name_parent; | const char *bus_name_parent; | ||||
| devclass_t dc; | |||||
| bus_name_parent = device_get_name(device_get_parent(dev)); | |||||
| if (dev->dev_attached) | if (dev->dev_attached) | ||||
| return (0); /* fail-safe */ | return (0); /* fail-safe */ | ||||
| if (dev->dev_fixed_class) { | |||||
| mod = dev->dev_module; | |||||
| if (DEVICE_PROBE(dev) <= 0) { | |||||
| if (device_allocate_softc(dev) == 0) { | |||||
| if (DEVICE_ATTACH(dev) == 0) { | |||||
| /* success */ | |||||
| dev->dev_attached = 1; | |||||
| return (0); | |||||
| } | |||||
| } | |||||
| } | |||||
| device_detach(dev); | |||||
| goto error; | |||||
| } | |||||
| /* | /* | ||||
| * Else find a module for our device, if any | * Find a module for our device, if any | ||||
| */ | */ | ||||
| bus_name_parent = device_get_name(device_get_parent(dev)); | |||||
| TAILQ_FOREACH(mod, &module_head, entry) { | TAILQ_FOREACH(mod, &module_head, entry) { | ||||
| if (devclass_equal(mod->bus_name, bus_name_parent)) { | if (!devclass_equal(mod->bus_name, bus_name_parent)) | ||||
| if (devclass_create(mod->devclass_pp)) { | |||||
| continue; | continue; | ||||
| } | |||||
| if (devclass_add_device(mod, dev)) { | dc = devclass_find(mod->mod_name); | ||||
| /* Does this device need assigning to the new devclass? */ | |||||
| if (dev->dev_class != dc) { | |||||
| if (dev->dev_fixed_class) | |||||
| continue; | continue; | ||||
| if (dev->dev_class != NULL) | |||||
| devclass_delete_device(dev->dev_class, dev); | |||||
| if (devclass_add_device(dc, dev)) { | |||||
| continue; | |||||
| } | } | ||||
| } | |||||
| dev->dev_module = mod; | |||||
| if (DEVICE_PROBE(dev) <= 0) { | if (DEVICE_PROBE(dev) <= 0) { | ||||
| if (device_allocate_softc(dev) == 0) { | if (device_allocate_softc(dev) == 0) { | ||||
| if (DEVICE_ATTACH(dev) == 0) { | if (DEVICE_ATTACH(dev) == 0) { | ||||
| /* success */ | /* success */ | ||||
| dev->dev_attached = 1; | dev->dev_attached = 1; | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* else try next driver */ | /* else try next driver */ | ||||
| device_detach(dev); | device_detach(dev); | ||||
| } | } | ||||
| } | |||||
| error: | |||||
| return (ENODEV); | return (ENODEV); | ||||
| } | } | ||||
| int | int | ||||
| device_detach(device_t dev) | device_detach(device_t dev) | ||||
| { | { | ||||
| const struct module_data *mod = dev->dev_module; | const struct module_data *mod = dev->dev_module; | ||||
| int error; | int error; | ||||
| if (dev->dev_attached) { | if (dev->dev_attached) { | ||||
| error = DEVICE_DETACH(dev); | error = DEVICE_DETACH(dev); | ||||
| if (error) { | if (error) { | ||||
| return error; | return error; | ||||
| } | } | ||||
| dev->dev_attached = 0; | dev->dev_attached = 0; | ||||
| } | } | ||||
| device_set_softc(dev, NULL); | device_set_softc(dev, NULL); | ||||
| dev->dev_module = NULL; | |||||
| if (dev->dev_fixed_class == 0) | if (dev->dev_fixed_class == 0) | ||||
| devclass_delete_device(mod, dev); | devclass_delete_device(dev->dev_class, dev); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| void | void | ||||
| device_set_softc(device_t dev, void *softc) | device_set_softc(device_t dev, void *softc) | ||||
| { | { | ||||
| if (dev->dev_softc_alloc) { | if (dev->dev_softc_alloc) { | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ? | return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ? | ||||
| NULL : dc->dev_list[unit]); | NULL : dc->dev_list[unit]); | ||||
| } | } | ||||
| devclass_t | devclass_t | ||||
| devclass_find(const char *classname) | devclass_find(const char *classname) | ||||
| { | { | ||||
| const struct module_data *mod; | devclass_t dc; | ||||
| TAILQ_FOREACH(mod, &module_head, entry) { | TAILQ_FOREACH(dc, &devclasses, link) { | ||||
| if (devclass_equal(mod->driver->name, classname)) | if (devclass_equal(dc->name, classname)) | ||||
| return (mod->devclass_pp[0]); | return (dc); | ||||
| } | } | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| void | void | ||||
| module_register(void *data) | module_register(void *data) | ||||
| { | { | ||||
| struct module_data *mdata = data; | struct module_data *mdata = data; | ||||
| TAILQ_INSERT_TAIL(&module_head, mdata, entry); | TAILQ_INSERT_TAIL(&module_head, mdata, entry); | ||||
| (void)devclass_find_create(mdata->mod_name); | |||||
| } | } | ||||
| /*------------------------------------------------------------------------* | /*------------------------------------------------------------------------* | ||||
| * System startup | * System startup | ||||
| *------------------------------------------------------------------------*/ | *------------------------------------------------------------------------*/ | ||||
| static void | static void | ||||
| sysinit_run(const void **ppdata) | sysinit_run(const void **ppdata) | ||||
| ▲ Show 20 Lines • Show All 353 Lines • Show Last 20 Lines | |||||