static void lptout (void *arg) { struct lpt_softc *sc = arg; int pl; lprintf(("T %x ", inb(sc->sc_port+lpt_status))); if (sc->sc_state & OPEN) { sc->sc_backoff++; if (sc->sc_backoff > hz/LPTOUTMAX) sc->sc_backoff = sc->sc_backoff > hz/LPTOUTMAX; timeout (lptout, (caddr_t)sc, sc->sc_backoff); } else sc->sc_state &= ~TOUT; if (sc->sc_state & ERROR) sc->sc_state &= ~ERROR; /* * Avoid possible hangs do to missed interrupts */ if (sc->sc_xfercnt) { pl = spltty(); lpt_intr(sc); splx(pl); } else { sc->sc_state &= ~OBUSY; wakeup(sc); } }
int pushbytes(struct lpt_softc *sc) { int s, error, spin, tic; if (sc->sc_flags & LPT_NOINTR) { while (sc->sc_count > 0) { spin = 0; while ((sc->sc_funcs->lf_notrdy) (sc, 0)) { if (++spin < sc->sc_spinmax) continue; tic = 0; /* adapt busy-wait algorithm */ sc->sc_spinmax++; while ((sc->sc_funcs->lf_notrdy) (sc, 1)) { /* exponential backoff */ tic = tic + tic + 1; if (tic > TIMEOUT) tic = TIMEOUT; error = tsleep((void *) sc, LPTPRI | PCATCH, "lptpsh", tic); if (error != EWOULDBLOCK) return (error); } break; } (sc->sc_funcs->lf_wrdata) (sc, *sc->sc_cp++); sc->sc_count--; /* adapt busy-wait algorithm */ if (spin * 2 + 16 < sc->sc_spinmax) sc->sc_spinmax--; } } else { while (sc->sc_count > 0) { /* if the printer is ready for a char, give it one */ if ((sc->sc_state & LPT_OBUSY) == 0) { LPRINTF((sc->sc_dev, "write %d\n", sc->sc_count)); s = spltty(); (void) lpt_intr(sc); splx(s); } error = tsleep((void *) sc, LPTPRI | PCATCH, "lptwrite2", 0); if (error) return (error); } } return (0); }
void lpt_wakeup(void *arg) { struct lpt_softc *sc; int s; sc = arg; s = spltty(); lpt_intr(sc); splx(s); callout_reset(&sc->sc_wakeup_ch, STEP, lpt_wakeup, sc); }
static int lptwrite(dev_t dev, struct uio * uio, int ioflag) { register unsigned n; int pl, err; struct lpt_softc *sc; sc = devclass_get_softc(olpt_devclass, LPTUNIT(minor(dev))); if(sc->sc_flags & LP_BYPASS) { /* we can't do writes in bypass mode */ return(EPERM); } sc->sc_state &= ~INTERRUPTED; while ((n = min(BUFSIZE, uio->uio_resid)) != 0) { sc->sc_cp = sc->sc_inbuf->b_data ; uiomove(sc->sc_cp, n, uio); sc->sc_xfercnt = n ; while ((sc->sc_xfercnt > 0)&&(sc->sc_irq & LP_USE_IRQ)) { lprintf(("i")); /* if the printer is ready for a char, */ /* give it one */ if ((sc->sc_state & OBUSY) == 0){ lprintf(("\nC %d. ", sc->sc_xfercnt)); pl = spltty(); lpt_intr(sc); (void) splx(pl); } lprintf(("W ")); if (sc->sc_state & OBUSY) if ((err = tsleep ((caddr_t)sc, LPPRI|PCATCH, "lpwrite", 0))) { sc->sc_state |= INTERRUPTED; return(err); } } /* check to see if we must do a polled write */ if(!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) { lprintf(("p")); if((err = pushbytes(sc))) return(err); } } return(0); }