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
This commit is contained in:
parent
6f3bd9a660
commit
3ed7166aca
@ -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, accentmap_t *accmap,
|
||||
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,23 +236,6 @@ 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 code, int32_t value)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
SYSINIT(kbd_drv_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, kbd_drv_init, NULL);
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 */
|
||||
@ -397,6 +400,9 @@ int kbd_detach(keyboard_t *kbd);
|
||||
#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,
|
||||
int *shiftstate, int *accents);
|
||||
|
@ -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>
|
||||
|
||||
@ -123,6 +126,14 @@ cninit(void)
|
||||
|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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user