Page MenuHomeFreeBSD

D22835.id65840.diff
No OneTemporary

D22835.id65840.diff

Index: sys/dev/kbd/kbd.c
===================================================================
--- sys/dev/kbd/kbd.c
+++ sys/dev/kbd/kbd.c
@@ -70,7 +70,7 @@
static SLIST_HEAD(, keyboard_driver) keyboard_drivers =
SLIST_HEAD_INITIALIZER(keyboard_drivers);
-SET_DECLARE(kbddriver_set, const keyboard_driver_t);
+SET_DECLARE(kbddriver_set, keyboard_driver_t);
/* local arrays */
@@ -159,23 +159,70 @@
kbd->kb_fkeytab_size = fkeymap_size;
}
-/* declare a new keyboard driver */
-int
-kbd_add_driver(keyboard_driver_t *driver)
+/*
+ * kbd_add_driver_internal: declare a new keyboard driver. This may be called
+ * up to twice for a given keyboard driver: once if it's built into the kernel,
+ * and again if it's also been declared as a module and it's built into the
+ * kernel. The first call will always add the driver to the driver list, and
+ * the second call (post-linker set registration) will just mark the driver as
+ * officially registered so we reject any later calls.
+ */
+static int
+kbd_add_driver_internal(keyboard_driver_t *driver, bool linker_set)
{
- if (SLIST_NEXT(driver, link))
+
+ KASSERT(!linker_set || (driver->flags & KBDF_SET_REGISTERED) == 0,
+ ("%s: double registration from linker set for '%s'",
+ __func__, driver->name));
+ if ((driver->flags & KBDF_REGISTERED) != 0)
return (EINVAL);
+
+ /*
+ * No further action required if the driver has already been registered
+ * as a linker set driver. Just mark it as fully registered and return,
+ * it has already been added to the driver list in the first pass.
+ */
+ if (!linker_set && (driver->flags & KBDF_SET_REGISTERED) != 0) {
+ driver->flags |= KBDF_REGISTERED;
+ return (0);
+ }
+
+ KASSERT(SLIST_NEXT(driver, link) == NULL,
+ ("%s: keyboard driver list garbage detected", __func__));
if (driver->kbdsw->get_fkeystr == NULL)
driver->kbdsw->get_fkeystr = genkbd_get_fkeystr;
if (driver->kbdsw->diag == NULL)
driver->kbdsw->diag = genkbd_diag;
+
+ driver->flags |= (linker_set ? KBDF_SET_REGISTERED : KBDF_REGISTERED);
SLIST_INSERT_HEAD(&keyboard_drivers, driver, link);
return (0);
}
+int
+kbd_add_driver(keyboard_driver_t *driver)
+{
+
+ return (kbd_add_driver_internal(driver, false));
+}
+
int
kbd_delete_driver(keyboard_driver_t *driver)
{
+
+ /*
+ * Imbalanced kbd_add_driver/kbd_delete_driver. Technically one can
+ * call kbd_delete_driver without having callded kbd_add_driver if
+ * there's been some sort of error and the driver will not be
+ * functional. Most likely these will already have a matching
+ * kbd_add_driver because they're processing module events and doing
+ * setup along those lines. We don't discriminate against in-kernel
+ * only drivers that wish to unregister, though.
+ */
+ if ((driver->flags & KBDF_REGISTRATION_MASK) == 0)
+ return (EINVAL);
+
+ driver->flags &= ~KBDF_REGISTRATION_MASK;
SLIST_REMOVE(&keyboard_drivers, driver, keyboard_driver, link);
SLIST_NEXT(driver, link) = NULL;
return (0);
@@ -185,7 +232,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 +272,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 +311,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 +458,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);
}
@@ -1510,16 +1527,19 @@
static void
kbd_drv_init(void)
{
- const keyboard_driver_t **list;
- const keyboard_driver_t *p;
+ keyboard_driver_t *drv, **list;
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 = *list;
+
+ if (kbd_add_driver_internal(drv, true) != 0)
+ printf("kbd: failed to register driver '%s'\n",
+ drv->name);
+ 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
@@ -107,8 +107,14 @@
keyboard_switch_t * const kbdsw;
/* backdoor for the console driver */
int (* const configure)(int);
+ int flags;
} keyboard_driver_t;
+#define KBDF_SET_REGISTERED 0x0001
+#define KBDF_REGISTERED 0x0002
+
+#define KBDF_REGISTRATION_MASK (KBDF_SET_REGISTERED | KBDF_REGISTERED)
+
/* keyboard */
struct keyboard {
/* the following fields are managed by kbdio */

File Metadata

Mime Type
text/plain
Expires
Fri, May 1, 8:09 AM (8 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32564665
Default Alt Text
D22835.id65840.diff (5 KB)

Event Timeline