Author: kevans Date: Thu Dec 26 15:21:34 2019 New Revision: 356087 URL: https://svnweb.freebsd.org/changeset/base/356087
Log: kbd: merge linker set drivers into standard kbd driver list This leads to the revert of r355806; this reduces duplication in keyboard registration and driver switch lookup and leaves us with one authoritative source for currently registered drivers. The reduced duplication later is nice as we have more procedure involved in keyboard setup. keyboard_driver->flags is used to more quickly detect bogus adds/removes. From KPI consumers' perspective, nothing changes- kbd_add_driver of an already-registered driver will succeed, and a single kbd_delete_driver will later remove it as expected. In contrast to historical behavior, kbd_delete_driver on a driver registered via linker set will now actually de-register the driver so that it may not be used -- e.g. if kbdmux's MOD_LOAD handler fails somewhere. Detection for already-registered drivers in kbd_add_driver has improved, as the previous SLIST_NEXT(driver) != NULL check would not have caught a driver that's at the tail end. kbdinit is now called from cninit() rather than via SYSINIT so that keyboard drivers are available as early as console drivers. This is particularly important as cnprobe will, in both syscons and vt, attempt to do any early configuration of keyboard drivers built-in (see: kbd_configure). Reviewed by: imp (earlier version, pre-cninit change) Differential Revision: https://reviews.freebsd.org/D22835 Modified: head/sys/dev/kbd/kbd.c head/sys/dev/kbd/kbdreg.h head/sys/kern/kern_cons.c Modified: head/sys/dev/kbd/kbd.c ============================================================================== --- head/sys/dev/kbd/kbd.c Thu Dec 26 02:22:38 2019 (r356086) +++ head/sys/dev/kbd/kbd.c Thu Dec 26 15:21:34 2019 (r356087) @@ -70,7 +70,7 @@ static void genkbd_diag(keyboard_t *kbd, int level); 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 */ @@ -163,12 +163,18 @@ kbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accent int kbd_add_driver(keyboard_driver_t *driver) { - if (SLIST_NEXT(driver, link)) - return (EINVAL); + + if ((driver->flags & KBDF_REGISTERED) != 0) + 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 |= KBDF_REGISTERED; SLIST_INSERT_HEAD(&keyboard_drivers, driver, link); return (0); } @@ -176,6 +182,11 @@ kbd_add_driver(keyboard_driver_t *driver) int kbd_delete_driver(keyboard_driver_t *driver) { + + if ((driver->flags & KBDF_REGISTERED) == 0) + return (EINVAL); + + driver->flags &= ~KBDF_REGISTERED; SLIST_REMOVE(&keyboard_drivers, driver, keyboard_driver, link); SLIST_NEXT(driver, link) = NULL; return (0); @@ -185,7 +196,6 @@ kbd_delete_driver(keyboard_driver_t *driver) int kbd_register(keyboard_t *kbd) { - const keyboard_driver_t **list; const keyboard_driver_t *p; keyboard_t *mux; keyboard_info_t ki; @@ -226,24 +236,7 @@ kbd_register(keyboard_t *kbd) 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 +275,12 @@ kbd_unregister(keyboard_t *kbd) 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 +422,12 @@ kbd_get_keyboard(int index) 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); } @@ -1507,19 +1488,27 @@ kbd_ev_event(keyboard_t *kbd, uint16_t type, uint16_t } } -static void -kbd_drv_init(void) +void +kbdinit(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; + + /* + * The following printfs will almost universally get dropped, + * with exception to kernel configs with EARLY_PRINTF and + * special setups where msgbufinit() is called early with a + * static buffer to capture output occurring before the dynamic + * message buffer is mapped. + */ + if (kbd_add_driver(drv) != 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); +} Modified: head/sys/dev/kbd/kbdreg.h ============================================================================== --- head/sys/dev/kbd/kbdreg.h Thu Dec 26 02:22:38 2019 (r356086) +++ head/sys/dev/kbd/kbdreg.h Thu Dec 26 15:21:34 2019 (r356087) @@ -107,8 +107,11 @@ typedef struct keyboard_driver { keyboard_switch_t * const kbdsw; /* backdoor for the console driver */ int (* const configure)(int); + int flags; } keyboard_driver_t; +#define KBDF_REGISTERED 0x0001 + /* keyboard */ struct keyboard { /* the following fields are managed by kbdio */ @@ -396,6 +399,9 @@ int kbd_detach(keyboard_t *kbd); #define LED_SCR (1 << 2) #define LED_MASK (LED_CAP | LED_NUM | LED_SCR) */ + +/* Initialization for the kbd layer, performed by cninit. */ +void kbdinit(void); int genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg); int genkbd_keyaction(keyboard_t *kbd, int keycode, int up, Modified: head/sys/kern/kern_cons.c ============================================================================== --- head/sys/kern/kern_cons.c Thu Dec 26 02:22:38 2019 (r356086) +++ head/sys/kern/kern_cons.c Thu Dec 26 15:21:34 2019 (r356087) @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <sys/conf.h> #include <sys/cons.h> #include <sys/fcntl.h> +#include <sys/kbio.h> #include <sys/kdb.h> #include <sys/kernel.h> #include <sys/malloc.h> @@ -69,6 +70,8 @@ __FBSDID("$FreeBSD$"); #include <ddb/ddb.h> +#include <dev/kbd/kbdreg.h> + #include <machine/cpu.h> #include <machine/clock.h> @@ -122,6 +125,14 @@ cninit(void) |RB_SINGLE |RB_VERBOSE |RB_ASKNAME)) == RB_MUTE); + + /* + * Bring up the kbd layer just in time for cnprobe. Console drivers + * have a dependency on kbd being ready, so this fits nicely between the + * machdep callers of cninit() and MI probing/initialization of consoles + * here. + */ + kbdinit(); /* * Find the first console with the highest priority. _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"