diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2013-06-12 19:07:41 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2013-06-12 19:07:41 +0000 |
commit | b1d0d4c0c5835e90d0c4678c4f257cba36875924 (patch) | |
tree | d30eaf2998c5a516a6d05cb8211d28213c07c601 /sys/dev | |
parent | c710be29d5b3ed61094e3146cba2282504276380 (diff) |
Add suspend/resume support to lpt. Basically, ensure that DACT_SUSPEND
stops the timeouts, and that DVACT_RESUME unwedges the soft state and
bring the hardware state back to normal operation.
Tested by rpe, thanks a lot!
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/lpt.c | 87 | ||||
-rw-r--r-- | sys/dev/ic/lptvar.h | 4 | ||||
-rw-r--r-- | sys/dev/isa/lpt_isa.c | 5 |
3 files changed, 82 insertions, 14 deletions
diff --git a/sys/dev/ic/lpt.c b/sys/dev/ic/lpt.c index 4053411ebc3..8d623901128 100644 --- a/sys/dev/ic/lpt.c +++ b/sys/dev/ic/lpt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lpt.c,v 1.9 2012/01/11 16:22:33 dhill Exp $ */ +/* $OpenBSD: lpt.c,v 1.10 2013/06/12 19:07:40 deraadt Exp $ */ /* $NetBSD: lpt.c,v 1.42 1996/10/21 22:41:14 thorpej Exp $ */ /* @@ -98,9 +98,9 @@ struct cfdriver lpt_cd = { #define LPS_INVERT (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK) #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK|LPS_NOPAPER) #define NOT_READY() \ - ((bus_space_read_1(iot, ioh, lpt_status) ^ LPS_INVERT) & LPS_MASK) + ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, lpt_status) ^ LPS_INVERT) & LPS_MASK) #define NOT_READY_ERR() \ - lpt_not_ready(bus_space_read_1(iot, ioh, lpt_status), sc) + lpt_not_ready(bus_space_read_1(sc->sc_iot, sc->sc_ioh, lpt_status), sc) int lpt_not_ready(u_int8_t, struct lpt_softc *); void lptwakeup(void *arg); @@ -138,6 +138,16 @@ lpt_attach_common(struct lpt_softc *sc) timeout_set(&sc->sc_wakeup_tmo, lptwakeup, sc); } +void +lpt_detach_common(struct lpt_softc *sc) +{ + timeout_del(&sc->sc_wakeup_tmo); + if (sc->sc_state != 0) { + sc->sc_state = 0; + wakeup(sc); + } +} + /* * Reset the printer, then wait until it's selected and not busy. */ @@ -147,8 +157,6 @@ lptopen(dev_t dev, int flag, int mode, struct proc *p) int unit = LPTUNIT(dev); u_int8_t flags = LPTFLAGS(dev); struct lpt_softc *sc; - bus_space_tag_t iot; - bus_space_handle_t ioh; u_int8_t control; int error; int spin; @@ -174,17 +182,15 @@ lptopen(dev_t dev, int flag, int mode, struct proc *p) sc->sc_state = LPT_INIT; LPRINTF(("%s: open: flags=0x%x\n", sc->sc_dev.dv_xname, flags)); - iot = sc->sc_iot; - ioh = sc->sc_ioh; if ((flags & LPT_NOPRIME) == 0) { /* assert INIT for 100 usec to start up printer */ - bus_space_write_1(iot, ioh, lpt_control, LPC_SELECT); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, LPC_SELECT); delay(100); } control = LPC_SELECT | LPC_NINIT; - bus_space_write_1(iot, ioh, lpt_control, control); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, control); /* wait till ready (printer running diagnostics) */ for (spin = 0; NOT_READY_ERR(); spin += STEP) { @@ -195,6 +201,8 @@ lptopen(dev_t dev, int flag, int mode, struct proc *p) /* wait 1/4 second, give up if we get a signal */ error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptopen", STEP); + if (sc->sc_state == 0) + return (EIO); if (error != EWOULDBLOCK) { sc->sc_state = 0; return error; @@ -206,7 +214,7 @@ lptopen(dev_t dev, int flag, int mode, struct proc *p) if (flags & LPT_AUTOLF) control |= LPC_AUTOLF; sc->sc_control = control; - bus_space_write_1(iot, ioh, lpt_control, control); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, control); sc->sc_inbuf = geteblk(LPT_BSIZE); sc->sc_count = 0; @@ -248,7 +256,8 @@ lptwakeup(void *arg) lptintr(sc); splx(s); - timeout_add(&sc->sc_wakeup_tmo, STEP); + if (sc->sc_state != 0) + timeout_add(&sc->sc_wakeup_tmo, STEP); } /* @@ -290,6 +299,8 @@ lptpushbytes(struct lpt_softc *sc) while (sc->sc_count > 0) { spin = 0; + if (sc->sc_state == 0) + return (EIO); while (NOT_READY()) { if (++spin < sc->sc_spinmax) continue; @@ -303,6 +314,8 @@ lptpushbytes(struct lpt_softc *sc) tic = TIMEOUT; error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptpsh", tic); + if (sc->sc_state == 0) + error = EIO; if (error != EWOULDBLOCK) return error; } @@ -331,8 +344,12 @@ lptpushbytes(struct lpt_softc *sc) (void) lptintr(sc); splx(s); } + if (sc->sc_state == 0) + return (EIO); error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptwrite2", 0); + if (sc->sc_state == 0) + error = EIO; if (error) return error; } @@ -408,3 +425,51 @@ lptintr(void *arg) return 1; } + +int +lpt_activate(struct device *self, int act) +{ + struct lpt_softc *sc = (struct lpt_softc *)self; + + switch (act) { + case DVACT_SUSPEND: + if (timeout_pending(&sc->sc_wakeup_tmo)) + timeout_del(&sc->sc_wakeup_tmo); + break; + case DVACT_RESUME: + bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, LPC_NINIT); + + if (sc->sc_state) { + int spin; + + if ((sc->sc_flags & LPT_NOPRIME) == 0) { + /* assert INIT for 100 usec to start up printer */ + bus_space_write_1(sc->sc_iot, sc->sc_ioh, + lpt_control, LPC_SELECT); + delay(100); + } + + bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, + LPC_SELECT | LPC_NINIT); + + /* wait till ready (printer running diagnostics) */ + for (spin = 0; NOT_READY_ERR(); spin += STEP) { + if (spin >= TIMEOUT) { + sc->sc_state = 0; + goto fail; + } + + /* wait 1/4 second, give up if we get a signal */ + delay(STEP * 1000); + } + + bus_space_write_1(sc->sc_iot, sc->sc_ioh, + lpt_control, sc->sc_control); + wakeup(sc); + } +fail: + break; + } + + return (0); +} diff --git a/sys/dev/ic/lptvar.h b/sys/dev/ic/lptvar.h index a33bfcdd562..98a52d2eaa9 100644 --- a/sys/dev/ic/lptvar.h +++ b/sys/dev/ic/lptvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: lptvar.h,v 1.3 2002/03/14 01:26:54 millert Exp $ */ +/* $OpenBSD: lptvar.h,v 1.4 2013/06/12 19:07:40 deraadt Exp $ */ /* $NetBSD: lpt.c,v 1.42 1996/10/21 22:41:14 thorpej Exp $ */ /* @@ -80,3 +80,5 @@ int lptintr(void *); int lpt_port_test(bus_space_tag_t, bus_space_handle_t, bus_addr_t, bus_size_t, u_int8_t, u_int8_t); void lpt_attach_common(struct lpt_softc *); +void lpt_detach_common(struct lpt_softc *); +int lpt_activate(struct device *, int); diff --git a/sys/dev/isa/lpt_isa.c b/sys/dev/isa/lpt_isa.c index 5248c70d243..f3d62dd57fa 100644 --- a/sys/dev/isa/lpt_isa.c +++ b/sys/dev/isa/lpt_isa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lpt_isa.c,v 1.13 2011/09/16 17:20:07 miod Exp $ */ +/* $OpenBSD: lpt_isa.c,v 1.14 2013/06/12 19:07:39 deraadt Exp $ */ /* * Copyright (c) 1993, 1994 Charles Hannum. @@ -68,7 +68,8 @@ int lpt_isa_probe(struct device *, void *, void *); void lpt_isa_attach(struct device *, struct device *, void *); struct cfattach lpt_isa_ca = { - sizeof(struct lpt_softc), lpt_isa_probe, lpt_isa_attach + sizeof(struct lpt_softc), lpt_isa_probe, lpt_isa_attach, NULL, + lpt_activate }; /* |