svn commit: r193512 - in head/sys/dev: kbd kbdmux

Ed Schouten ed at FreeBSD.org
Fri Jun 5 15:19:06 UTC 2009


Author: ed
Date: Fri Jun  5 15:19:05 2009
New Revision: 193512
URL: http://svn.freebsd.org/changeset/base/193512

Log:
  Move buffer management into kbd and kbdmux drivers.
  
  These two drivers seem to be the last consumers of clists. clists are
  quite overengineered for simple circular buffers, so I'm adding similar
  buffer management routines to the kbd and kbdmux drivers. The input
  buffer is now part of the softc structures, instead of having
  dynamically allocated cblocks.

Modified:
  head/sys/dev/kbd/kbd.c
  head/sys/dev/kbdmux/kbdmux.c

Modified: head/sys/dev/kbd/kbd.c
==============================================================================
--- head/sys/dev/kbd/kbd.c	Fri Jun  5 14:55:22 2009	(r193511)
+++ head/sys/dev/kbd/kbd.c	Fri Jun  5 15:19:05 2009	(r193512)
@@ -34,7 +34,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
-#include <sys/clist.h>
 #include <sys/conf.h>
 #include <sys/fcntl.h>
 #include <sys/poll.h>
@@ -50,11 +49,16 @@ __FBSDID("$FreeBSD$");
 
 #define KBD_INDEX(dev)	dev2unit(dev)
 
+#define KB_QSIZE	512
+#define KB_BUFSIZE	64
+
 typedef struct genkbd_softc {
 	int		gkb_flags;	/* flag/status bits */
 #define KB_ASLEEP	(1 << 0)
-	struct clist	gkb_q;		/* input queue */
 	struct selinfo	gkb_rsel;
+	char		gkb_q[KB_QSIZE];		/* input queue */
+	unsigned int	gkb_q_start;
+	unsigned int	gkb_q_length;
 } genkbd_softc_t;
 
 static	SLIST_HEAD(, keyboard_driver) keyboard_drivers =
@@ -521,8 +525,38 @@ kbd_detach(keyboard_t *kbd)
  * driver functions.
  */
 
-#define KB_QSIZE	512
-#define KB_BUFSIZE	64
+static void
+genkbd_putc(genkbd_softc_t *sc, char c)
+{
+	unsigned int p;
+
+	if (sc->gkb_q_length == KB_QSIZE)
+		return;
+
+	p = (sc->gkb_q_start + sc->gkb_q_length) % KB_QSIZE;
+	sc->gkb_q[p] = c;
+	sc->gkb_q_length++;
+}
+
+static size_t
+genkbd_getc(genkbd_softc_t *sc, char *buf, size_t len)
+{
+
+	/* Determine copy size. */
+	if (sc->gkb_q_length == 0)
+		return (0);
+	if (len >= sc->gkb_q_length)
+		len = sc->gkb_q_length;
+	if (len >= KB_QSIZE - sc->gkb_q_start)
+		len = KB_QSIZE - sc->gkb_q_start;
+
+	/* Copy out data and progress offset. */
+	memcpy(buf, sc->gkb_q + sc->gkb_q_start, len);
+	sc->gkb_q_start = (sc->gkb_q_start + len) % KB_QSIZE;
+	sc->gkb_q_length -= len;
+
+	return (len);
+}
 
 static kbd_callback_func_t genkbd_event;
 
@@ -555,10 +589,7 @@ genkbdopen(struct cdev *dev, int mode, i
 	 * the device may still be missing (!KBD_HAS_DEVICE(kbd)).
 	 */
 
-#if 0
-	bzero(&sc->gkb_q, sizeof(sc->gkb_q));
-#endif
-	clist_alloc_cblocks(&sc->gkb_q, KB_QSIZE, KB_QSIZE/2); /* XXX */
+	sc->gkb_q_length = 0;
 	splx(s);
 
 	return (0);
@@ -582,9 +613,6 @@ genkbdclose(struct cdev *dev, int mode, 
 		/* XXX: we shall be forgiving and don't report error... */
 	} else {
 		kbd_release(kbd, (void *)sc);
-#if 0
-		clist_free_cblocks(&sc->gkb_q);
-#endif
 	}
 	splx(s);
 	return (0);
@@ -608,7 +636,7 @@ genkbdread(struct cdev *dev, struct uio 
 		splx(s);
 		return (ENXIO);
 	}
-	while (sc->gkb_q.c_cc == 0) {
+	while (sc->gkb_q_length == 0) {
 		if (flag & O_NONBLOCK) {
 			splx(s);
 			return (EWOULDBLOCK);
@@ -632,7 +660,7 @@ genkbdread(struct cdev *dev, struct uio 
 	error = 0;
 	while (uio->uio_resid > 0) {
 		len = imin(uio->uio_resid, sizeof(buffer));
-		len = q_to_b(&sc->gkb_q, buffer, len);
+		len = genkbd_getc(sc, buffer, len);
 		if (len <= 0)
 			break;
 		error = uiomove(buffer, len, uio);
@@ -684,7 +712,7 @@ genkbdpoll(struct cdev *dev, int events,
 	if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
 		revents =  POLLHUP;	/* the keyboard has gone */
 	} else if (events & (POLLIN | POLLRDNORM)) {
-		if (sc->gkb_q.c_cc > 0)
+		if (sc->gkb_q_length > 0)
 			revents = events & (POLLIN | POLLRDNORM);
 		else
 			selrecord(td, &sc->gkb_rsel);
@@ -738,7 +766,7 @@ genkbd_event(keyboard_t *kbd, int event,
 
 		/* store the byte as is for K_RAW and K_CODE modes */
 		if (mode != K_XLATE) {
-			putc(KEYCHAR(c), &sc->gkb_q);
+			genkbd_putc(sc, KEYCHAR(c));
 			continue;
 		}
 
@@ -753,9 +781,9 @@ genkbd_event(keyboard_t *kbd, int event,
 				/* ignore them... */
 				continue;
 			case BTAB:	/* a backtab: ESC [ Z */
-				putc(0x1b, &sc->gkb_q);
-				putc('[', &sc->gkb_q);
-				putc('Z', &sc->gkb_q);
+				genkbd_putc(sc, 0x1b);
+				genkbd_putc(sc, '[');
+				genkbd_putc(sc, 'Z');
 				continue;
 			}
 		}
@@ -763,24 +791,24 @@ genkbd_event(keyboard_t *kbd, int event,
 		/* normal chars, normal chars with the META, function keys */
 		switch (KEYFLAGS(c)) {
 		case 0:			/* a normal char */
-			putc(KEYCHAR(c), &sc->gkb_q);
+			genkbd_putc(sc, KEYCHAR(c));
 			break;
 		case MKEY:		/* the META flag: prepend ESC */
-			putc(0x1b, &sc->gkb_q);
-			putc(KEYCHAR(c), &sc->gkb_q);
+			genkbd_putc(sc, 0x1b);
+			genkbd_putc(sc, KEYCHAR(c));
 			break;
 		case FKEY | SPCLKEY:	/* a function key, return string */
 			cp = kbdd_get_fkeystr(kbd, KEYCHAR(c), &len);
 			if (cp != NULL) {
 				while (len-- >  0)
-					putc(*cp++, &sc->gkb_q);
+					genkbd_putc(sc, *cp++);
 			}
 			break;
 		}
 	}
 
 	/* wake up sleeping/polling processes */
-	if (sc->gkb_q.c_cc > 0) {
+	if (sc->gkb_q_length > 0) {
 		if (sc->gkb_flags & KB_ASLEEP) {
 			sc->gkb_flags &= ~KB_ASLEEP;
 			wakeup(sc);

Modified: head/sys/dev/kbdmux/kbdmux.c
==============================================================================
--- head/sys/dev/kbdmux/kbdmux.c	Fri Jun  5 14:55:22 2009	(r193511)
+++ head/sys/dev/kbdmux/kbdmux.c	Fri Jun  5 15:19:05 2009	(r193512)
@@ -36,7 +36,6 @@
 
 #include <sys/param.h>
 #include <sys/bus.h>
-#include <sys/clist.h>
 #include <sys/conf.h>
 #include <sys/consio.h>
 #include <sys/fcntl.h>
@@ -134,7 +133,9 @@ typedef struct kbdmux_kbd	kbdmux_kbd_t;
  */
 struct kbdmux_state
 {
-	struct clist		 ks_inq;	/* input chars queue */
+	char			 ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
+	unsigned int		 ks_inq_start;
+	unsigned int		 ks_inq_length;
 	struct task		 ks_task;	/* interrupt task */
 	struct callout		 ks_timo;	/* timeout handler */
 #define TICKS			(hz)		/* rate */
@@ -167,6 +168,34 @@ static task_fn_t		kbdmux_kbd_intr;
 static timeout_t		kbdmux_kbd_intr_timo;
 static kbd_callback_func_t	kbdmux_kbd_event;
 
+static void
+kbdmux_kbd_putc(kbdmux_state_t *state, char c)
+{
+	unsigned int p;
+
+	if (state->ks_inq_length == KBDMUX_Q_SIZE)
+		return;
+
+	p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
+	state->ks_inq[p] = c;
+	state->ks_inq_length++;
+}
+
+static char
+kbdmux_kbd_getc(kbdmux_state_t *state)
+{
+	char c;
+
+	if (state->ks_inq_length == 0)
+		return (-1);
+
+	c = state->ks_inq[state->ks_inq_start];
+	state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
+	state->ks_inq_length--;
+
+	return (c);
+}
+
 /*
  * Interrupt handler task
  */
@@ -205,7 +234,7 @@ kbdmux_kbd_intr_timo(void *xstate)
 	callout_deactivate(&state->ks_timo);
 
 	/* queue interrupt task if needed */
-	if (state->ks_inq.c_cc > 0 && !(state->ks_flags & TASK) &&
+	if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
 	    KBDMUX_QUEUE_INTR(state) == 0)
 		state->ks_flags |= TASK;
 
@@ -246,11 +275,11 @@ kbdmux_kbd_event(keyboard_t *kbd, int ev
 			if (!KBD_IS_BUSY(kbd))
 				continue; /* not open - discard the input */
 
-			putc(c, &state->ks_inq);
+			kbdmux_kbd_putc(state, c);
 		}
 
 		/* queue interrupt task if needed */
-		if (state->ks_inq.c_cc > 0 && !(state->ks_flags & TASK) &&
+		if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
 		    KBDMUX_QUEUE_INTR(state) == 0)
 			state->ks_flags |= TASK;
 
@@ -384,8 +413,6 @@ kbdmux_init(int unit, keyboard_t **kbdp,
 		}
 
 		KBDMUX_LOCK_INIT(state);
-		clist_alloc_cblocks(&state->ks_inq,
-				KBDMUX_Q_SIZE, KBDMUX_Q_SIZE / 2);
 		TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
 		KBDMUX_CALLOUT_INIT(state);
 		SLIST_INIT(&state->ks_kbds);
@@ -448,10 +475,8 @@ kbdmux_init(int unit, keyboard_t **kbdp,
 	return (0);
 bad:
 	if (needfree) {
-		if (state != NULL) {
-			clist_free_cblocks(&state->ks_inq);
+		if (state != NULL)
 			free(state, M_KBDMUX);
-		}
 		if (keymap != NULL)
 			free(keymap, M_KBDMUX);
 		if (accmap != NULL)
@@ -495,10 +520,6 @@ kbdmux_term(keyboard_t *kbd)
 		free(k, M_KBDMUX);
 	}
 
-	/* flush input queue */
-	ndflush(&state->ks_inq, state->ks_inq.c_cc);
-	clist_free_cblocks(&state->ks_inq);
-
 	KBDMUX_UNLOCK(state);
 
 	kbd_unregister(kbd);
@@ -577,7 +598,7 @@ kbdmux_read(keyboard_t *kbd, int wait)
 	int		 c;
 
 	KBDMUX_LOCK(state);
-	c = getc(&state->ks_inq);
+	c = kbdmux_kbd_getc(state);
 	KBDMUX_UNLOCK(state);
 
 	if (c != -1)
@@ -599,7 +620,7 @@ kbdmux_check(keyboard_t *kbd)
 		return (FALSE);
 
 	KBDMUX_LOCK(state);
-	ready = (state->ks_inq.c_cc > 0)? TRUE : FALSE;
+	ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
 	KBDMUX_UNLOCK(state);
 
 	return (ready);
@@ -635,7 +656,7 @@ next_code:
 	}
 
 	/* see if there is something in the keyboard queue */
-	scancode = getc(&state->ks_inq);
+	scancode = kbdmux_kbd_getc(state);
 	if (scancode == -1) {
 		if (state->ks_flags & POLLING) {
 			kbdmux_kbd_t	*k;
@@ -650,11 +671,11 @@ next_code:
 					if (!KBD_IS_BUSY(k->kbd))
 						continue; 
 
-					putc(scancode, &state->ks_inq);
+					kbdmux_kbd_putc(state, scancode);
 				}
 			}
 
-			if (state->ks_inq.c_cc > 0)
+			if (state->ks_inq_length > 0)
 				goto next_code;
 		}
 
@@ -895,7 +916,7 @@ kbdmux_check_char(keyboard_t *kbd)
 	if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
 		ready = TRUE;
 	else
-		ready = (state->ks_inq.c_cc > 0)? TRUE : FALSE;
+		ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
 
 	KBDMUX_UNLOCK(state);
 
@@ -1219,8 +1240,7 @@ kbdmux_clear_state_locked(kbdmux_state_t
 	state->ks_accents = 0;
 	state->ks_composed_char = 0;
 /*	state->ks_prefix = 0;		XXX */
-
-	ndflush(&state->ks_inq, state->ks_inq.c_cc);
+	state->ks_inq_length = 0;
 }
 
 static void


More information about the svn-src-head mailing list