diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/hil/hil.c | 81 | ||||
-rw-r--r-- | sys/dev/hil/hilkbd.c | 25 | ||||
-rw-r--r-- | sys/dev/hil/hilvar.h | 4 |
3 files changed, 94 insertions, 16 deletions
diff --git a/sys/dev/hil/hil.c b/sys/dev/hil/hil.c index 869ac0d56d8..43626d14bf4 100644 --- a/sys/dev/hil/hil.c +++ b/sys/dev/hil/hil.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hil.c,v 1.4 2003/02/15 23:45:52 miod Exp $ */ +/* $OpenBSD: hil.c,v 1.5 2003/02/18 02:40:51 miod Exp $ */ /* * Copyright (c) 2003, Miodrag Vallat. * All rights reserved. @@ -97,6 +97,7 @@ struct cfdriver hil_cd = { void hilconfig(struct hil_softc *); int hilsubmatch(struct device *, void *, void *); void hil_process_int(struct hil_softc *, u_int8_t, u_int8_t); +int hil_process_poll(struct hil_softc *, u_int8_t, u_int8_t); void polloff(struct hil_softc *); void pollon(struct hil_softc *); @@ -361,6 +362,63 @@ hil_process_int(struct hil_softc *sc, u_int8_t stat, u_int8_t c) } /* + * Same as above, but in polled mode: return data as it gets seen, instead + * of buffering it. + */ +int +hil_process_poll(struct hil_softc *sc, u_int8_t stat, u_int8_t c) +{ + switch ((stat >> HIL_SSHIFT) & HIL_SMASK) { + case HIL_STATUS: + if (c & HIL_ERROR) { + sc->sc_cmddone = 1; + if (c == HIL_RECONFIG) { + /* + * XXX We should remember if a configuration + * event occured and invoke hilconfig() upon + * leaving polled mode... + */ + } + break; + } + if (c & HIL_COMMAND) { + if (!(c & HIL_POLLDATA)) { + /* End of command */ + sc->sc_cmdending = 1; + } + sc->sc_actdev = 0; + } else { + if (c & HIL_POLLDATA) { + /* Start of polled data */ + sc->sc_actdev = (c & HIL_DEVMASK); + sc->sc_pollbp = sc->sc_pollbuf; + } else { + /* Start of command - should not happen */ + if (sc->sc_cmddev == (c & HIL_DEVMASK)) { + sc->sc_cmdbp = sc->sc_cmdbuf; + sc->sc_actdev = 0; + } + } + } + break; + case HIL_DATA: + if (sc->sc_actdev != 0) /* Collecting poll data */ + return 1; + else { + if (sc->sc_cmddev != 0) { /* Discarding cmd data */ + if (sc->sc_cmdending) { + sc->sc_cmddone = 1; + sc->sc_cmdending = 0; + } + } + } + break; + } + + return 0; +} + +/* * Called after the loop has reconfigured. Here we need to: * - determine how many devices are on the loop * (some may have been added or removed) @@ -534,6 +592,9 @@ polloff(struct hil_softc *sc) hildatawait(sc); db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); } while (db & BSY_LOOPBUSY); + + sc->sc_cmddone = 0; + sc->sc_cmddev = 0; } void @@ -573,16 +634,24 @@ hil_set_poll(struct hil_softc *sc, int on) } int -hil_poll_data(struct hil_softc *sc, u_int8_t *stat, u_int8_t *data) +hil_poll_data(struct hil_softc *sc, u_int code, u_int8_t *stat, u_int8_t *data) { - u_int8_t s; + u_int8_t s, c; s = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT); if ((s & HIL_DATA_RDY) == 0) return -1; - *stat = s; - *data = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); + c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); - return 0; + if (hil_process_poll(sc, s, c)) { + /* Discard any data not for us */ + if (sc->sc_actdev == code) { + *stat = s; + *data = c; + return 0; + } + } + + return -1; } diff --git a/sys/dev/hil/hilkbd.c b/sys/dev/hil/hilkbd.c index 49f76dd0c29..166d8824b59 100644 --- a/sys/dev/hil/hilkbd.c +++ b/sys/dev/hil/hilkbd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hilkbd.c,v 1.5 2003/02/18 00:38:56 miod Exp $ */ +/* $OpenBSD: hilkbd.c,v 1.6 2003/02/18 02:40:51 miod Exp $ */ /* * Copyright (c) 2003, Miodrag Vallat. * All rights reserved. @@ -252,31 +252,40 @@ hilkbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) void hilkbd_cngetc(void *v, u_int *type, int *data) { - struct hil_softc *sc = v; + struct hilkbd_softc *sc = v; u_int8_t c, stat; - /* XXX This should really filter on keyboard events only */ for (;;) { - if (hil_poll_data(sc, &stat, &c) != -1) + while (hil_poll_data((struct hil_softc *)sc->sc_dev.dv_parent, + sc->sc_code, &stat, &c) != 0) + ; + + /* + * Disregard keyboard data packet header. + * Note that no key generates it, so we're safe. + */ + if (c != HIL_KBDDATA) break; } + hilkbd_decode(stat, c, type, data); } void hilkbd_cnpollc(void *v, int on) { - struct hil_softc *sc = v; + struct hilkbd_softc *sc = v; - hil_set_poll(sc, on); + hil_set_poll((struct hil_softc *)sc->sc_dev.dv_parent, on); } void hilkbd_cnbell(void *v, u_int pitch, u_int period, u_int volume) { - struct hil_softc *sc = v; + struct hilkbd_softc *sc = v; - hilkbd_bell(sc, pitch, period, volume); + hilkbd_bell((struct hil_softc *)sc->sc_dev.dv_parent, + pitch, period, volume); } void diff --git a/sys/dev/hil/hilvar.h b/sys/dev/hil/hilvar.h index 58e91aabe7a..c663d305d98 100644 --- a/sys/dev/hil/hilvar.h +++ b/sys/dev/hil/hilvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hilvar.h,v 1.3 2003/02/15 23:42:48 miod Exp $ */ +/* $OpenBSD: hilvar.h,v 1.4 2003/02/18 02:40:51 miod Exp $ */ /* * Copyright (c) 2003, Miodrag Vallat. * All rights reserved. @@ -99,7 +99,7 @@ struct hil_softc { void send_hil_cmd(struct hil_softc *, u_int, u_int8_t *, u_int, u_int8_t *); void send_hildev_cmd(struct hil_softc *, u_int, u_int, u_int8_t *, u_int *); void hil_set_poll(struct hil_softc *, int); -int hil_poll_data(struct hil_softc *, u_int8_t *, u_int8_t *); +int hil_poll_data(struct hil_softc *, u_int, u_int8_t *, u_int8_t *); void hil_attach(struct hil_softc *, int); void hil_attach_deferred(void *); |