diff options
author | ed <ed@FreeBSD.org> | 2009-06-05 15:19:05 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2009-06-05 15:19:05 +0000 |
commit | 16054e9f49d102b1082dbca77148d1b65698aed7 (patch) | |
tree | d0e24bc66e27d40282feaaab0a6bb38fa91f2541 | |
parent | f4934662e5d837053e785525653e390ce6933d2b (diff) | |
download | FreeBSD-src-16054e9f49d102b1082dbca77148d1b65698aed7.zip FreeBSD-src-16054e9f49d102b1082dbca77148d1b65698aed7.tar.gz |
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.
-rw-r--r-- | sys/dev/kbd/kbd.c | 74 | ||||
-rw-r--r-- | sys/dev/kbdmux/kbdmux.c | 64 |
2 files changed, 93 insertions, 45 deletions
diff --git a/sys/dev/kbd/kbd.c b/sys/dev/kbd/kbd.c index 753269a..851f677 100644 --- a/sys/dev/kbd/kbd.c +++ b/sys/dev/kbd/kbd.c @@ -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, int flag, struct thread *td) * 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, int flag, struct thread *td) /* 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 *uio, int flag) 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 *uio, int flag) 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, struct thread *td) 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, void *arg) /* 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, void *arg) /* 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, void *arg) /* 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); diff --git a/sys/dev/kbdmux/kbdmux.c b/sys/dev/kbdmux/kbdmux.c index ac6095c..0f1fe42 100644 --- a/sys/dev/kbdmux/kbdmux.c +++ b/sys/dev/kbdmux/kbdmux.c @@ -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 event, void *arg) 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, void *arg, int flags) } 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, void *arg, int flags) 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) 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 |