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