Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145330005
D22835.id65708.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D22835.id65708.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D22835: kbd: merge linker set drivers into standard kbd driver list
Attached
Detach File
Event Timeline
Log In to Comment