--- Net2/arch/i386/isa/lpt.c 2018/04/24 18:06:59 1.1 +++ Net2/arch/i386/isa/lpt.c 2018/04/24 18:19:52 1.1.1.2 @@ -45,26 +45,30 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - */ + * lpt.c,v 1.7 1993/07/17 16:20:32 mycroft Exp */ /* * Device Driver for AT parallel printer port * Written by William Jolitz 12/18/90 + * + * Hacked heavily by Rod Grimes and Eric Haug... */ #include "lpt.h" #if NLPT > 0 #include "param.h" +#include "systm.h" +#include "proc.h" #include "user.h" #include "buf.h" -#include "systm.h" #include "kernel.h" #include "ioctl.h" #include "tty.h" #include "uio.h" +#include "i386/isa/isa.h" #include "i386/isa/isa_device.h" #include "i386/isa/lptreg.h" @@ -76,12 +80,13 @@ #ifndef DEBUG #define lprintf #else -#define lprintf if (lpflag) printf +#define lprintf if (lptflag) printf +int lptflag = 1; #endif int lptout(); #ifdef DEBUG -int lpflag = 1; +int lptflag = 1; #endif int lptprobe(), lptattach(), lptintr(); @@ -121,26 +126,93 @@ struct lpt_softc { #define TOUT (1<<5) /* timeout while not selected */ #define INIT (1<<6) /* waiting to initialize for open */ -lptprobe(idp) - struct isa_device *idp; -{ unsigned v; - - outb(idp->id_iobase+lpt_status,0xf0); - v = inb(idp->id_iobase+lpt_status); - outb(idp->id_iobase+lpt_status,0); - if (inb(idp->id_iobase+lpt_status) == v) { - outb(idp->id_iobase+lpt_control,0xff); - DELAY(100); - if (inb(idp->id_iobase+lpt_control) != 0xff) - return(0); - outb(idp->id_iobase+lpt_control,0); - DELAY(100); - if (inb(idp->id_iobase+lpt_control) != 0xe0) - return(0); - return(1); +/* + * Internal routine to lptprobe to do port tests of one byte value + */ +int +lpt_port_test(short port, u_char data, u_char mask) + { + int temp, timeout; + + data = data & mask; + outb(port, data); + timeout = 100; + do + temp = inb(port) & mask; + while (temp != data && --timeout); + lprintf("Port 0x%x\tout=%x\tin=%x\n", port, data, temp); + return (temp == data); + } + +/* + * New lptprobe routine written by Rodney W. Grimes, 3/25/1993 + * + * Logic: + * 1) You should be able to write to and read back the same value + * to the data port. Do an alternating zeros, alternating ones, + * walking zero, and walking one test to check for stuck bits. + * + * 2) You should be able to write to and read back the same value + * to the control port lower 5 bits, the upper 3 bits are reserved + * per the IBM PC technical reference manauls and different boards + * do different things with them. Do an alternating zeros, alternating + * ones, walking zero, and walking one test to check for stuck bits. + * + * Some printers drag the strobe line down when the are powered off + * so this bit has been masked out of the control port test. + * + * XXX Some printers may not like a fast pulse on init or strobe, I + * don't know at this point, if that becomes a problem these bits + * should be turned off in the mask byte for the control port test. + * + * 3) Set the data and control ports to a value of 0 + */ + +int +lptprobe(struct isa_device *dvp) + { + int status; + short port; + u_char data; + u_char mask; + int i; + + status = IO_LPTSIZE; + + port = dvp->id_iobase + lpt_data; + mask = 0xff; + while (mask != 0) + { + data = 0x55; /* Alternating zeros */ + if (!lpt_port_test(port, data, mask)) status = 0; + + data = 0xaa; /* Alternating ones */ + if (!lpt_port_test(port, data, mask)) status = 0; + + for (i = 0; i < 8; i++) /* Walking zero */ + { + data = ~(1 << i); + if (!lpt_port_test(port, data, mask)) status = 0; + } + + for (i = 0; i < 8; i++) /* Walking one */ + { + data = (1 << i); + if (!lpt_port_test(port, data, mask)) status = 0; + } + + if (port == dvp->id_iobase + lpt_data) + { + port = dvp->id_iobase + lpt_control; + mask = 0x1e; + } + else + mask = 0; + } + outb(dvp->id_iobase+lpt_data, 0); + outb(dvp->id_iobase+lpt_control, 0); + return (status); } - return(0); -} lptattach(isdp) struct isa_device *isdp; @@ -149,6 +221,7 @@ lptattach(isdp) sc = lpt_sc + isdp->id_unit; sc->sc_port = isdp->id_iobase; + sc->sc_state = 0; outb(sc->sc_port+lpt_control, LPC_NINIT); return (1); } @@ -198,7 +271,8 @@ printf ("status %x\n", inb(port+lpt_stat } /* wait 1/4 second, give up if we get a signal */ - if (tsleep (sc, LPPRI|PCATCH, "lptinit", hz/4) != EWOULDBLOCK) { + if (tsleep((caddr_t)sc, + LPPRI|PCATCH, "lptinit", hz/4) != EWOULDBLOCK) { sc->sc_state = 0; splx(s); return (EBUSY); @@ -220,7 +294,7 @@ printf ("status %x\n", inb(port+lpt_stat sc->sc_inbuf = geteblk(BUFSIZE); sc->sc_xfercnt = 0; splx(s); - timeout (lptout, sc, hz/2); + timeout((timeout_t)lptout, (caddr_t)sc, hz/2); lprintf("opened.\n"); return(0); } @@ -231,7 +305,7 @@ lptout (sc) lprintf ("T %x ", inb(sc->sc_port+lpt_status)); if (sc->sc_state&OPEN) - timeout (lptout, sc, hz/2); + timeout((timeout_t)lptout, (caddr_t)sc, hz/2); else sc->sc_state &= ~TOUT; if (sc->sc_state & ERROR) @@ -264,7 +338,8 @@ lptclose(dev, flag) while ((inb(port+lpt_status) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) != (LPS_SEL|LPS_NBSY|LPS_NERR) || sc->sc_xfercnt) /* wait 1/4 second, give up if we get a signal */ - if (tsleep (sc, LPPRI|PCATCH, "lpclose", hz) != EWOULDBLOCK) + if (tsleep((caddr_t)sc, + LPPRI|PCATCH, "lpclose", hz) != EWOULDBLOCK) break; sc->sc_state = 0; @@ -301,7 +376,8 @@ lprintf("\nC %d. ", sc->sc_xfercnt); (void) splx(pl); } lprintf("W "); - if (err = tsleep (sc, LPPRI|PCATCH, "lpwrite", 0)) + if (err = tsleep((caddr_t)sc, + LPPRI|PCATCH, "lpwrite", 0)) return(err); } } @@ -318,8 +394,15 @@ lptintr(unit) struct lpt_softc *sc = lpt_sc + unit; int port = sc->sc_port,sts; + sts = inb(port+lpt_status); + + if (!sc->sc_state) { + printf ("lpt%d: stray interrupt sts=0x%02x\n", unit, sts); + return; + } + /* is printer online and ready for output */ - if (((sts=inb(port+lpt_status)) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR/*|LPS_NACK*/)) == + if ((sts & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR/*|LPS_NACK*/)) == (LPS_SEL|LPS_NBSY|LPS_NERR)) { /* is this a false interrupt ? */ if ((sc->sc_state & OBUSY) @@ -347,4 +430,24 @@ return; lprintf("sts %x ", sts); } -#endif NLP +int +lptioctl(dev_t dev, int cmd, caddr_t data, int flag) +{ + int error; + + error = 0; + switch (cmd) { +#ifdef THISISASAMPLE + case XXX: + dothis; andthis; andthat; + error=x; + break; +#endif /* THISISASAMPLE */ + default: + error = ENODEV; + } + + return(error); +} + +#endif /* NLPT */