kbd: remove kbdsw, store pointer to driver in each keyboard_t

The previous implementation relied on a kbdsw array that mirrored the global
keyboards array. This is fine, but also requires extra locking consideration
when accessing to ensure that it's not being resized as new keyboards are
added.

The extra pointer costs little in a struct that there are relatively few of
on any given system, and simplifies locking requirements ever-so-slightly as
we only need to consider the locking requirements of whichever method is
being invoked.

__FreeBSD_version is bumped as any kbd modules will need rebuilt following
this change.
This commit is contained in:
Kyle Evans 2019-12-16 03:12:53 +00:00
parent f00bf028b6
commit 21d166316a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=355798
3 changed files with 78 additions and 93 deletions

View File

@ -83,8 +83,6 @@ SET_DECLARE(kbddriver_set, const keyboard_driver_t);
static int keyboards = 1;
static keyboard_t *kbd_ini;
static keyboard_t **keyboard = &kbd_ini;
static keyboard_switch_t *kbdsw_ini;
keyboard_switch_t **kbdsw = &kbdsw_ini;
static int keymap_restrict_change;
static SYSCTL_NODE(_hw, OID_AUTO, kbd, CTLFLAG_RD, 0, "kbd");
@ -97,7 +95,6 @@ static int
kbd_realloc_array(void)
{
keyboard_t **new_kbd;
keyboard_switch_t **new_kbdsw;
int newsize;
int s;
@ -108,21 +105,10 @@ kbd_realloc_array(void)
splx(s);
return (ENOMEM);
}
new_kbdsw = malloc(sizeof(*new_kbdsw)*newsize, M_DEVBUF,
M_NOWAIT|M_ZERO);
if (new_kbdsw == NULL) {
free(new_kbd, M_DEVBUF);
splx(s);
return (ENOMEM);
}
bcopy(keyboard, new_kbd, sizeof(*keyboard)*keyboards);
bcopy(kbdsw, new_kbdsw, sizeof(*kbdsw)*keyboards);
if (keyboards > 1) {
if (keyboards > 1)
free(keyboard, M_DEVBUF);
free(kbdsw, M_DEVBUF);
}
keyboard = new_kbd;
kbdsw = new_kbdsw;
keyboards = newsize;
splx(s);
@ -226,8 +212,8 @@ kbd_register(keyboard_t *kbd)
SLIST_FOREACH(p, &keyboard_drivers, link) {
if (strcmp(p->name, kbd->kb_name) == 0) {
kbd->kb_drv = p;
keyboard[index] = kbd;
kbdsw[index] = p->kbdsw;
if (mux != NULL) {
bzero(&ki, sizeof(ki));
@ -243,8 +229,8 @@ kbd_register(keyboard_t *kbd)
SET_FOREACH(list, kbddriver_set) {
p = *list;
if (strcmp(p->name, kbd->kb_name) == 0) {
kbd->kb_drv = p;
keyboard[index] = kbd;
kbdsw[index] = p->kbdsw;
if (mux != NULL) {
bzero(&ki, sizeof(ki));
@ -287,7 +273,6 @@ kbd_unregister(keyboard_t *kbd)
}
KBD_INVALID(kbd);
keyboard[kbd->kb_index] = NULL;
kbdsw[kbd->kb_index] = NULL;
splx(s);
return (0);

View File

@ -41,6 +41,30 @@ struct cdevsw;
/* call back funcion */
typedef int kbd_callback_func_t(keyboard_t *kbd, int event,
void *arg);
/* keyboard function table */
typedef int kbd_probe_t(int unit, void *arg, int flags);
typedef int kbd_init_t(int unit, keyboard_t **kbdp, void *arg,
int flags);
typedef int kbd_term_t(keyboard_t *kbd);
typedef int kbd_intr_t(keyboard_t *kbd, void *arg);
typedef int kbd_test_if_t(keyboard_t *kbd);
typedef int kbd_enable_t(keyboard_t *kbd);
typedef int kbd_disable_t(keyboard_t *kbd);
typedef int kbd_read_t(keyboard_t *kbd, int wait);
typedef int kbd_check_t(keyboard_t *kbd);
typedef u_int kbd_read_char_t(keyboard_t *kbd, int wait);
typedef int kbd_check_char_t(keyboard_t *kbd);
typedef int kbd_ioctl_t(keyboard_t *kbd, u_long cmd, caddr_t data);
typedef int kbd_lock_t(keyboard_t *kbd, int lock);
typedef void kbd_clear_state_t(keyboard_t *kbd);
typedef int kbd_get_state_t(keyboard_t *kbd, void *buf, size_t len);
typedef int kbd_set_state_t(keyboard_t *kbd, void *buf, size_t len);
typedef u_char *kbd_get_fkeystr_t(keyboard_t *kbd, int fkey,
size_t *len);
typedef int kbd_poll_mode_t(keyboard_t *kbd, int on);
typedef void kbd_diag_t(keyboard_t *kbd, int level);
/* event types */
#define KBDIO_KEYINPUT 0
#define KBDIO_UNLOADING 1
@ -50,6 +74,36 @@ typedef struct keyboard_callback {
void *kc_arg;
} keyboard_callback_t;
typedef struct keyboard_switch {
kbd_probe_t *probe;
kbd_init_t *init;
kbd_term_t *term;
kbd_intr_t *intr;
kbd_test_if_t *test_if;
kbd_enable_t *enable;
kbd_disable_t *disable;
kbd_read_t *read;
kbd_check_t *check;
kbd_read_char_t *read_char;
kbd_check_char_t *check_char;
kbd_ioctl_t *ioctl;
kbd_lock_t *lock;
kbd_clear_state_t *clear_state;
kbd_get_state_t *get_state;
kbd_set_state_t *set_state;
kbd_get_fkeystr_t *get_fkeystr;
kbd_poll_mode_t *poll;
kbd_diag_t *diag;
} keyboard_switch_t;
/* keyboard driver */
typedef struct keyboard_driver {
SLIST_ENTRY(keyboard_driver) link;
char *name;
keyboard_switch_t *kbdsw;
int (*configure)(int); /* backdoor for the console driver */
} keyboard_driver_t;
/* keyboard */
struct keyboard {
/* the following fields are managed by kbdio */
@ -94,6 +148,7 @@ struct keyboard {
unsigned long kb_count; /* # of processed key strokes */
u_char kb_lastact[NUM_KEYS/2];
struct cdev *kb_dev;
const keyboard_driver_t *kb_drv;
};
#define KBD_IS_VALID(k) ((k)->kb_flags & KB_VALID)
@ -118,61 +173,6 @@ struct keyboard {
#define KBD_DEACTIVATE(k) (--(k)->kb_active)
#define KBD_LED_VAL(k) ((k)->kb_led)
/* keyboard function table */
typedef int kbd_probe_t(int unit, void *arg, int flags);
typedef int kbd_init_t(int unit, keyboard_t **kbdp, void *arg,
int flags);
typedef int kbd_term_t(keyboard_t *kbd);
typedef int kbd_intr_t(keyboard_t *kbd, void *arg);
typedef int kbd_test_if_t(keyboard_t *kbd);
typedef int kbd_enable_t(keyboard_t *kbd);
typedef int kbd_disable_t(keyboard_t *kbd);
typedef int kbd_read_t(keyboard_t *kbd, int wait);
typedef int kbd_check_t(keyboard_t *kbd);
typedef u_int kbd_read_char_t(keyboard_t *kbd, int wait);
typedef int kbd_check_char_t(keyboard_t *kbd);
typedef int kbd_ioctl_t(keyboard_t *kbd, u_long cmd, caddr_t data);
typedef int kbd_lock_t(keyboard_t *kbd, int lock);
typedef void kbd_clear_state_t(keyboard_t *kbd);
typedef int kbd_get_state_t(keyboard_t *kbd, void *buf, size_t len);
typedef int kbd_set_state_t(keyboard_t *kbd, void *buf, size_t len);
typedef u_char *kbd_get_fkeystr_t(keyboard_t *kbd, int fkey,
size_t *len);
typedef int kbd_poll_mode_t(keyboard_t *kbd, int on);
typedef void kbd_diag_t(keyboard_t *kbd, int level);
typedef struct keyboard_switch {
kbd_probe_t *probe;
kbd_init_t *init;
kbd_term_t *term;
kbd_intr_t *intr;
kbd_test_if_t *test_if;
kbd_enable_t *enable;
kbd_disable_t *disable;
kbd_read_t *read;
kbd_check_t *check;
kbd_read_char_t *read_char;
kbd_check_char_t *check_char;
kbd_ioctl_t *ioctl;
kbd_lock_t *lock;
kbd_clear_state_t *clear_state;
kbd_get_state_t *get_state;
kbd_set_state_t *set_state;
kbd_get_fkeystr_t *get_fkeystr;
kbd_poll_mode_t *poll;
kbd_diag_t *diag;
} keyboard_switch_t;
/* keyboard driver */
typedef struct keyboard_driver {
SLIST_ENTRY(keyboard_driver) link;
char *name;
keyboard_switch_t *kbdsw;
int (*configure)(int); /* backdoor for the console driver */
} keyboard_driver_t;
extern keyboard_switch_t **kbdsw;
/*
* Keyboard disciplines: call actual handlers via kbdsw[].
*/
@ -180,77 +180,77 @@ static __inline int
kbdd_probe(keyboard_t *kbd, int unit, void *arg, int flags)
{
return ((*kbdsw[kbd->kb_index]->probe)(unit, arg, flags));
return ((*kbd->kb_drv->kbdsw->probe)(unit, arg, flags));
}
static __inline int
kbdd_init(keyboard_t *kbd, int unit, keyboard_t **kbdpp, void *arg, int flags)
{
return ((*kbdsw[kbd->kb_index]->init)(unit, kbdpp, arg, flags));
return ((*kbd->kb_drv->kbdsw->init)(unit, kbdpp, arg, flags));
}
static __inline int
kbdd_term(keyboard_t *kbd)
{
return ((*kbdsw[kbd->kb_index]->term)(kbd));
return ((*kbd->kb_drv->kbdsw->term)(kbd));
}
static __inline int
kbdd_intr(keyboard_t *kbd, void *arg)
{
return ((*kbdsw[kbd->kb_index]->intr)(kbd, arg));
return ((*kbd->kb_drv->kbdsw->intr)(kbd, arg));
}
static __inline int
kbdd_test_if(keyboard_t *kbd)
{
return ((*kbdsw[kbd->kb_index]->test_if)(kbd));
return ((*kbd->kb_drv->kbdsw->test_if)(kbd));
}
static __inline int
kbdd_enable(keyboard_t *kbd)
{
return ((*kbdsw[kbd->kb_index]->enable)(kbd));
return ((*kbd->kb_drv->kbdsw->enable)(kbd));
}
static __inline int
kbdd_disable(keyboard_t *kbd)
{
return ((*kbdsw[kbd->kb_index]->disable)(kbd));
return ((*kbd->kb_drv->kbdsw->disable)(kbd));
}
static __inline int
kbdd_read(keyboard_t *kbd, int wait)
{
return ((*kbdsw[kbd->kb_index]->read)(kbd, wait));
return ((*kbd->kb_drv->kbdsw->read)(kbd, wait));
}
static __inline int
kbdd_check(keyboard_t *kbd)
{
return ((*kbdsw[kbd->kb_index]->check)(kbd));
return ((*kbd->kb_drv->kbdsw->check)(kbd));
}
static __inline u_int
kbdd_read_char(keyboard_t *kbd, int wait)
{
return ((*kbdsw[kbd->kb_index]->read_char)(kbd, wait));
return ((*kbd->kb_drv->kbdsw->read_char)(kbd, wait));
}
static __inline int
kbdd_check_char(keyboard_t *kbd)
{
return ((*kbdsw[kbd->kb_index]->check_char)(kbd));
return ((*kbd->kb_drv->kbdsw->check_char)(kbd));
}
static __inline int
@ -259,56 +259,56 @@ kbdd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
if (kbd == NULL)
return (ENODEV);
return ((*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, data));
return ((*kbd->kb_drv->kbdsw->ioctl)(kbd, cmd, data));
}
static __inline int
kbdd_lock(keyboard_t *kbd, int lock)
{
return ((*kbdsw[kbd->kb_index]->lock)(kbd, lock));
return ((*kbd->kb_drv->kbdsw->lock)(kbd, lock));
}
static __inline void
kbdd_clear_state(keyboard_t *kbd)
{
(*kbdsw[kbd->kb_index]->clear_state)(kbd);
(*kbd->kb_drv->kbdsw->clear_state)(kbd);
}
static __inline int
kbdd_get_state(keyboard_t *kbd, void *buf, int len)
{
return ((*kbdsw[kbd->kb_index]->get_state)(kbd, buf, len));
return ((*kbd->kb_drv->kbdsw->get_state)(kbd, buf, len));
}
static __inline int
kbdd_set_state(keyboard_t *kbd, void *buf, int len)
{
return ((*kbdsw[kbd->kb_index]->set_state)(kbd, buf, len));
return ((*kbd->kb_drv->kbdsw->set_state)(kbd, buf, len));
}
static __inline u_char *
kbdd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len)
{
return ((*kbdsw[kbd->kb_index]->get_fkeystr)(kbd, fkey, len));
return ((*kbd->kb_drv->kbdsw->get_fkeystr)(kbd, fkey, len));
}
static __inline int
kbdd_poll(keyboard_t *kbd, int on)
{
return ((*kbdsw[kbd->kb_index]->poll)(kbd, on));
return ((*kbd->kb_drv->kbdsw->poll)(kbd, on));
}
static __inline void
kbdd_diag(keyboard_t *kbd, int level)
{
(*kbdsw[kbd->kb_index]->diag)(kbd, level);
(*kbd->kb_drv->kbdsw->diag)(kbd, level);
}
#define KEYBOARD_DRIVER(name, sw, config) \

View File

@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 1300067 /* Master, propagated to newvers */
#define __FreeBSD_version 1300068 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,