Page MenuHomeFreeBSD

D22835.id65708.diff
No OneTemporary

D22835.id65708.diff

Index: sys/dev/kbd/kbd.c
===================================================================
--- sys/dev/kbd/kbd.c
+++ sys/dev/kbd/kbd.c
@@ -163,12 +163,39 @@
int
kbd_add_driver(keyboard_driver_t *driver)
{
- if (SLIST_NEXT(driver, link))
+ keyboard_driver_t *p;
+
+ if (driver->registered != 0)
return (EINVAL);
+
+ SLIST_FOREACH(p, &keyboard_drivers, link) {
+ if (strcmp(p->name, driver->name) == 0) {
+ /*
+ * registered here indicates that we've invoked
+ * kbd_add_driver() on the driver previously. For
+ * drivers registered from the linker set, we don't
+ * consider it fully registered unless kbd_add_driver()
+ * is invoked on it because some of them are available
+ * with kld module events that will get triggered and
+ * cause us to register it.
+ */
+ if (!p->registered) {
+ driver->registered = p->registered = 1;
+ return (0);
+ }
+
+ return (EINVAL);
+ }
+ }
+
+ KASSERT(SLIST_NEXT(driver, link) == NULL,
+ ("%s: keyboard driver list garbage detected", __func__));
+ driver->registered = 1;
if (driver->kbdsw->get_fkeystr == NULL)
driver->kbdsw->get_fkeystr = genkbd_get_fkeystr;
if (driver->kbdsw->diag == NULL)
driver->kbdsw->diag = genkbd_diag;
+
SLIST_INSERT_HEAD(&keyboard_drivers, driver, link);
return (0);
}
@@ -176,8 +203,33 @@
int
kbd_delete_driver(keyboard_driver_t *driver)
{
- SLIST_REMOVE(&keyboard_drivers, driver, keyboard_driver, link);
- SLIST_NEXT(driver, link) = NULL;
+ keyboard_driver_t *p;
+
+ /* Imbalanced kbd_add_driver/kbd_delete_driver. */
+ if (!driver->registered)
+ return (EINVAL);
+
+ SLIST_FOREACH(p, &keyboard_drivers, link) {
+ if (strcmp(p->name, driver->name) == 0)
+ break;
+ }
+
+ /*
+ * We mostly use 'p' here, but we're really removing 'driver'. If the
+ * driver initially came in from the linker set, we need to remove that
+ * instance. If that's the case, we can also go ahead and free it -- if
+ * it's been removed, it's because the driver had an error. The
+ * driver's always able to re-register with its copy of the
+ * keyboard_driver and we'll continue to DTRT.
+ */
+ KASSERT(p != NULL,
+ ("%s: keyboard driver '%s' missing", __func__, driver->name));
+ driver->registered = 0;
+ SLIST_REMOVE(&keyboard_drivers, p, keyboard_driver, link);
+ if (p != driver)
+ free(p, M_DEVBUF);
+ else
+ SLIST_NEXT(p, link) = NULL;
return (0);
}
@@ -185,7 +237,6 @@
int
kbd_register(keyboard_t *kbd)
{
- const keyboard_driver_t **list;
const keyboard_driver_t *p;
keyboard_t *mux;
keyboard_info_t ki;
@@ -226,23 +277,6 @@
return (index);
}
}
- SET_FOREACH(list, kbddriver_set) {
- p = *list;
- if (strcmp(p->name, kbd->kb_name) == 0) {
- kbd->kb_drv = p;
- keyboard[index] = kbd;
-
- if (mux != NULL) {
- bzero(&ki, sizeof(ki));
- strcpy(ki.kb_name, kbd->kb_name);
- ki.kb_unit = kbd->kb_unit;
-
- (void)kbdd_ioctl(mux, KBADDKBD, (caddr_t) &ki);
- }
-
- return (index);
- }
- }
return (-1);
}
@@ -282,18 +316,12 @@
keyboard_switch_t *
kbd_get_switch(char *driver)
{
- const keyboard_driver_t **list;
const keyboard_driver_t *p;
SLIST_FOREACH(p, &keyboard_drivers, link) {
if (strcmp(p->name, driver) == 0)
return (p->kbdsw);
}
- SET_FOREACH(list, kbddriver_set) {
- p = *list;
- if (strcmp(p->name, driver) == 0)
- return (p->kbdsw);
- }
return (NULL);
}
@@ -435,18 +463,12 @@
int
kbd_configure(int flags)
{
- const keyboard_driver_t **list;
const keyboard_driver_t *p;
SLIST_FOREACH(p, &keyboard_drivers, link) {
if (p->configure != NULL)
(*p->configure)(flags);
}
- SET_FOREACH(list, kbddriver_set) {
- p = *list;
- if (p->configure != NULL)
- (*p->configure)(flags);
- }
return (0);
}
@@ -1511,15 +1533,22 @@
kbd_drv_init(void)
{
const keyboard_driver_t **list;
- const keyboard_driver_t *p;
+ keyboard_driver_t *drv;
SET_FOREACH(list, kbddriver_set) {
- p = *list;
- if (p->kbdsw->get_fkeystr == NULL)
- p->kbdsw->get_fkeystr = genkbd_get_fkeystr;
- if (p->kbdsw->diag == NULL)
- p->kbdsw->diag = genkbd_diag;
+ drv = malloc(sizeof(*drv), M_DEVBUF, M_WAITOK | M_ZERO);
+ bcopy(*list, drv, sizeof(*drv));
+
+ if (kbd_add_driver(drv) != 0) {
+ printf("kbd: failed to register driver '%s'\n",
+ drv->name);
+ free(drv, M_DEVBUF);
+ } else if (bootverbose) {
+ printf("kbd: registered driver '%s'\n",
+ drv->name);
+ }
}
+
}
SYSINIT(kbd_drv_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, kbd_drv_init, NULL);
Index: sys/dev/kbd/kbdreg.h
===================================================================
--- sys/dev/kbd/kbdreg.h
+++ sys/dev/kbd/kbdreg.h
@@ -102,6 +102,7 @@
char *name;
keyboard_switch_t *kbdsw;
int (*configure)(int); /* backdoor for the console driver */
+ int registered;
} keyboard_driver_t;
/* keyboard */

File Metadata

Mime Type
text/plain
Expires
Thu, Feb 19, 11:54 AM (7 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28852168
Default Alt Text
D22835.id65708.diff (4 KB)

Event Timeline