static int cmx_filter_read(struct knote *kn, long hint) { struct cmx_softc *sc = (struct cmx_softc *)kn->kn_hook; int ready = 0; uint8_t bsr = 0; if (sc == NULL || sc->dying) { kn->kn_flags |= EV_EOF; return (1); } bsr = cmx_read_BSR(sc); if (cmx_test(bsr, BSR_BULK_IN_FULL, 1)) { ready = 1; } else { CMX_LOCK(sc); if (!sc->polling) { sc->polling = 1; callout_reset(&sc->ch, POLL_TICKS, cmx_tick, sc); } CMX_UNLOCK(sc); } return (ready); }
/* * Interrupt handler. Currently has no function except to * print register status (if debugging is also enabled). */ static void cmx_intr(void *arg) { struct cmx_softc *sc = (struct cmx_softc *)arg; if (sc == NULL || sc->dying) return; DEBUG_printf(sc->dev, "received interrupt (SCR=%b BSR=%b)\n", cmx_read_SCR(sc), SCRBITS, cmx_read_BSR(sc), BSRBITS); return; }
/* * Periodical callout routine, polling the reader for data * availability. If the reader signals data ready for reading, * wakes up the processes which are waiting in select()/poll(). * Otherwise, reschedules itself with a delay of POLL_TICKS. */ static void cmx_tick(void *xsc) { struct cmx_softc *sc = xsc; uint8_t bsr; CMX_LOCK(sc); if (sc->polling && !sc->dying) { bsr = cmx_read_BSR(sc); DEBUG_printf(sc->dev, "BSR=%b\n", bsr, BSRBITS); if (cmx_test(bsr, BSR_BULK_IN_FULL, 1)) { sc->polling = 0; selwakeuppri(&sc->sel, PZERO); } else { callout_reset(&sc->ch, POLL_TICKS, cmx_tick, sc); } } CMX_UNLOCK(sc); }
/* * Poll handler. Writing is always possible, reading is only possible * if BSR_BULK_IN_FULL is set. Will start the cmx_tick callout and * set sc->polling. */ static int cmx_poll(struct cdev *cdev, int events, struct thread *td) { struct cmx_softc *sc = cdev->si_drv1; int revents = 0; uint8_t bsr = 0; if (sc == NULL || sc->dying) return ENXIO; bsr = cmx_read_BSR(sc); DEBUG_printf(sc->dev, "called (events=%b BSR=%b)\n", events, POLLBITS, bsr, BSRBITS); revents = events & (POLLOUT | POLLWRNORM); if (events & (POLLIN | POLLRDNORM)) { if (cmx_test(bsr, BSR_BULK_IN_FULL, 1)) { revents |= events & (POLLIN | POLLRDNORM); } else { selrecord(td, &sc->sel); CMX_LOCK(sc); if (!sc->polling) { DEBUG_printf(sc->dev, "enabling polling\n"); sc->polling = 1; callout_reset(&sc->ch, POLL_TICKS, cmx_tick, sc); } else { DEBUG_printf(sc->dev, "already polling\n"); } CMX_UNLOCK(sc); } } DEBUG_printf(sc->dev, "success (revents=%b)\n", revents, POLLBITS); return revents; }