svn commit: r356087 - in head/sys: dev/kbd kern

Kyle Evans kevans at FreeBSD.org
Thu Dec 26 15:21:35 UTC 2019


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.


More information about the svn-src-head mailing list