Home | History | Annotate | Line # | Download | only in ic
lpt.c revision 1.7.4.1
      1      1.1      cgd /*
      2      1.1      cgd  * Copyright (c) 1990 William F. Jolitz, TeleMuse
      3      1.1      cgd  * All rights reserved.
      4      1.1      cgd  *
      5      1.1      cgd  * Redistribution and use in source and binary forms, with or without
      6      1.1      cgd  * modification, are permitted provided that the following conditions
      7      1.1      cgd  * are met:
      8      1.1      cgd  * 1. Redistributions of source code must retain the above copyright
      9      1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     10      1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     11      1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     12      1.1      cgd  *    documentation and/or other materials provided with the distribution.
     13      1.1      cgd  * 3. All advertising materials mentioning features or use of this software
     14      1.1      cgd  *    must display the following acknowledgement:
     15      1.1      cgd  *	This software is a component of "386BSD" developed by
     16      1.1      cgd  *	William F. Jolitz, TeleMuse.
     17      1.1      cgd  * 4. Neither the name of the developer nor the name "386BSD"
     18      1.1      cgd  *    may be used to endorse or promote products derived from this software
     19      1.1      cgd  *    without specific prior written permission.
     20      1.1      cgd  *
     21      1.1      cgd  * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
     22      1.1      cgd  * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
     23      1.1      cgd  * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
     24      1.1      cgd  * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
     25      1.1      cgd  * NOT MAKE USE OF THIS WORK.
     26      1.1      cgd  *
     27      1.1      cgd  * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
     28      1.1      cgd  * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
     29      1.1      cgd  * REFERENCES SUCH AS THE  "PORTING UNIX TO THE 386" SERIES
     30      1.1      cgd  * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
     31      1.1      cgd  * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
     32      1.1      cgd  * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
     33      1.1      cgd  * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
     34      1.1      cgd  * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
     35      1.1      cgd  *
     36      1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
     37      1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     38      1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     39      1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
     40      1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     41      1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     42      1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     43      1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     44      1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     45      1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     46      1.1      cgd  * SUCH DAMAGE.
     47      1.1      cgd  *
     48  1.7.4.1  mycroft  *	$Id: lpt.c,v 1.7.4.1 1993/09/14 17:32:46 mycroft Exp $
     49      1.1      cgd  */
     50      1.1      cgd 
     51      1.1      cgd /*
     52      1.1      cgd  * Device Driver for AT parallel printer port
     53      1.1      cgd  * Written by William Jolitz 12/18/90
     54      1.3      cgd  *
     55      1.3      cgd  * Hacked heavily by Rod Grimes and Eric Haug...
     56      1.1      cgd  */
     57      1.1      cgd 
     58      1.1      cgd #include "lpt.h"
     59      1.1      cgd #if NLPT > 0
     60      1.1      cgd 
     61      1.1      cgd #include "param.h"
     62      1.2      cgd #include "systm.h"
     63      1.2      cgd #include "proc.h"
     64      1.1      cgd #include "user.h"
     65      1.1      cgd #include "buf.h"
     66      1.1      cgd #include "kernel.h"
     67      1.1      cgd #include "ioctl.h"
     68      1.1      cgd #include "tty.h"
     69      1.1      cgd #include "uio.h"
     70      1.1      cgd 
     71      1.2      cgd #include "i386/isa/isa.h"
     72      1.1      cgd #include "i386/isa/isa_device.h"
     73      1.1      cgd #include "i386/isa/lptreg.h"
     74      1.1      cgd 
     75      1.1      cgd #define	LPINITRDY	4	/* wait up to 4 seconds for a ready */
     76      1.1      cgd #define	LPTOUTTIME	4	/* wait up to 4 seconds for a ready */
     77      1.1      cgd #define	LPPRI		(PZERO+8)
     78      1.1      cgd #define	BUFSIZE		1024
     79      1.1      cgd 
     80      1.1      cgd #ifndef DEBUG
     81      1.1      cgd #define lprintf
     82      1.1      cgd #else
     83      1.5      cgd #define lprintf		if (lptflag) printf
     84      1.5      cgd int lptflag = 1;
     85      1.1      cgd #endif
     86      1.1      cgd 
     87      1.1      cgd #ifdef DEBUG
     88      1.5      cgd int lptflag = 1;
     89      1.1      cgd #endif
     90      1.1      cgd 
     91  1.7.4.1  mycroft void lptout __P((struct lpt_softc *sc));
     92  1.7.4.1  mycroft int 	lptprobe(), lptattach();
     93  1.7.4.1  mycroft void	lptintr();
     94      1.1      cgd 
     95      1.1      cgd struct	isa_driver lptdriver = {
     96      1.1      cgd 	lptprobe, lptattach, "lpt"
     97      1.1      cgd };
     98      1.1      cgd 
     99      1.1      cgd #define	LPTUNIT(s)	(((s)>>6)&0x3)
    100      1.1      cgd #define	LPTFLAGS(s)	((s)&0x3f)
    101      1.1      cgd 
    102      1.1      cgd struct lpt_softc {
    103      1.1      cgd 	short	sc_port;
    104      1.1      cgd 	short	sc_state;
    105      1.1      cgd 	/* default case: negative prime, negative ack, handshake strobe,
    106      1.1      cgd 	   prime once */
    107      1.1      cgd 	u_char	sc_control;
    108      1.1      cgd 	char	sc_flags;
    109      1.1      cgd #define LP_POS_INIT	0x01	/* if we are a postive init signal */
    110      1.1      cgd #define LP_POS_ACK	0x02	/* if we are a positive going ack */
    111      1.1      cgd #define LP_NO_PRIME	0x04	/* don't prime the printer at all */
    112      1.1      cgd #define LP_PRIMEOPEN	0x08	/* prime on every open */
    113      1.1      cgd #define LP_AUTOLF	0x10	/* tell printer to do an automatic lf */
    114      1.1      cgd #define LP_BYPASS	0x20	/* bypass  printer ready checks */
    115      1.1      cgd 	struct	buf *sc_inbuf;
    116      1.1      cgd 	short	sc_xfercnt ;
    117      1.1      cgd 	char	sc_primed;
    118      1.1      cgd 	char	*sc_cp ;
    119      1.1      cgd } lpt_sc[NLPT] ;
    120      1.1      cgd 
    121      1.1      cgd /* bits for state */
    122      1.1      cgd #define	OPEN		(1<<0)	/* device is open */
    123      1.1      cgd #define	ASLP		(1<<1)	/* awaiting draining of printer */
    124      1.1      cgd #define	ERROR		(1<<2)	/* error was received from printer */
    125      1.1      cgd #define	OBUSY		(1<<3)	/* printer is busy doing output */
    126      1.1      cgd #define LPTOUT		(1<<4)	/* timeout while not selected	*/
    127      1.1      cgd #define TOUT		(1<<5)	/* timeout while not selected	*/
    128      1.1      cgd #define INIT		(1<<6)	/* waiting to initialize for open */
    129      1.1      cgd 
    130      1.2      cgd /*
    131      1.2      cgd  * Internal routine to lptprobe to do port tests of one byte value
    132      1.2      cgd  */
    133      1.2      cgd int
    134  1.7.4.1  mycroft lpt_port_test(port, data, mask)
    135  1.7.4.1  mycroft 	u_short port;
    136  1.7.4.1  mycroft 	u_char data, mask;
    137  1.7.4.1  mycroft {
    138      1.5      cgd 	int	temp, timeout;
    139      1.2      cgd 
    140      1.2      cgd 	data = data & mask;
    141      1.2      cgd 	outb(port, data);
    142      1.5      cgd 	timeout = 100;
    143      1.5      cgd 	do
    144      1.5      cgd 		temp = inb(port) & mask;
    145      1.5      cgd 	while (temp != data && --timeout);
    146      1.2      cgd 	lprintf("Port 0x%x\tout=%x\tin=%x\n", port, data, temp);
    147      1.2      cgd 	return (temp == data);
    148  1.7.4.1  mycroft }
    149      1.2      cgd 
    150      1.2      cgd /*
    151      1.2      cgd  * New lptprobe routine written by Rodney W. Grimes, 3/25/1993
    152      1.2      cgd  *
    153      1.2      cgd  * Logic:
    154      1.2      cgd  *	1) You should be able to write to and read back the same value
    155      1.2      cgd  *	   to the data port.  Do an alternating zeros, alternating ones,
    156      1.2      cgd  *	   walking zero, and walking one test to check for stuck bits.
    157      1.2      cgd  *
    158      1.2      cgd  *	2) You should be able to write to and read back the same value
    159      1.2      cgd  *	   to the control port lower 5 bits, the upper 3 bits are reserved
    160      1.2      cgd  *	   per the IBM PC technical reference manauls and different boards
    161      1.2      cgd  *	   do different things with them.  Do an alternating zeros, alternating
    162      1.2      cgd  *	   ones, walking zero, and walking one test to check for stuck bits.
    163      1.2      cgd  *
    164      1.2      cgd  *	   Some printers drag the strobe line down when the are powered off
    165      1.2      cgd  * 	   so this bit has been masked out of the control port test.
    166      1.2      cgd  *
    167      1.2      cgd  *	   XXX Some printers may not like a fast pulse on init or strobe, I
    168      1.2      cgd  *	   don't know at this point, if that becomes a problem these bits
    169      1.2      cgd  *	   should be turned off in the mask byte for the control port test.
    170      1.2      cgd  *
    171      1.2      cgd  *	3) Set the data and control ports to a value of 0
    172      1.2      cgd  */
    173      1.2      cgd 
    174      1.2      cgd int
    175  1.7.4.1  mycroft lptprobe(dvp)
    176  1.7.4.1  mycroft 	struct isa_device *dvp;
    177  1.7.4.1  mycroft {
    178      1.2      cgd 	int	status;
    179      1.2      cgd 	short	port;
    180      1.2      cgd 	u_char	data;
    181      1.2      cgd 	u_char	mask;
    182      1.2      cgd 	int	i;
    183      1.2      cgd 
    184      1.2      cgd 	status = IO_LPTSIZE;
    185      1.2      cgd 
    186      1.2      cgd 	port = dvp->id_iobase + lpt_data;
    187      1.2      cgd 	mask = 0xff;
    188      1.2      cgd 	while (mask != 0)
    189      1.2      cgd 	{
    190      1.2      cgd 		data = 0x55;				/* Alternating zeros */
    191      1.2      cgd 		if (!lpt_port_test(port, data, mask)) status = 0;
    192      1.2      cgd 
    193      1.2      cgd 		data = 0xaa;				/* Alternating ones */
    194      1.2      cgd 		if (!lpt_port_test(port, data, mask)) status = 0;
    195      1.2      cgd 
    196      1.2      cgd 		for (i = 0; i < 8; i++)			/* Walking zero */
    197      1.2      cgd 			{
    198      1.2      cgd 			data = ~(1 << i);
    199      1.2      cgd 			if (!lpt_port_test(port, data, mask)) status = 0;
    200      1.2      cgd 			}
    201      1.2      cgd 
    202      1.2      cgd 		for (i = 0; i < 8; i++)			/* Walking one */
    203      1.2      cgd 			{
    204      1.2      cgd 			data = (1 << i);
    205      1.2      cgd 			if (!lpt_port_test(port, data, mask)) status = 0;
    206      1.2      cgd 			}
    207      1.2      cgd 
    208      1.2      cgd 		if (port == dvp->id_iobase + lpt_data)
    209      1.2      cgd 			{
    210      1.2      cgd 			port = dvp->id_iobase + lpt_control;
    211      1.2      cgd 			mask = 0x1e;
    212      1.2      cgd 			}
    213      1.2      cgd 		else
    214      1.2      cgd 			mask = 0;
    215  1.7.4.1  mycroft 	}
    216      1.2      cgd 	outb(dvp->id_iobase+lpt_data, 0);
    217      1.2      cgd 	outb(dvp->id_iobase+lpt_control, 0);
    218      1.2      cgd 	return (status);
    219  1.7.4.1  mycroft }
    220      1.1      cgd 
    221  1.7.4.1  mycroft int
    222      1.1      cgd lptattach(isdp)
    223      1.1      cgd 	struct isa_device *isdp;
    224      1.1      cgd {
    225      1.1      cgd 	struct	lpt_softc	*sc;
    226      1.1      cgd 
    227      1.1      cgd 	sc = lpt_sc + isdp->id_unit;
    228      1.1      cgd 	sc->sc_port = isdp->id_iobase;
    229      1.6  mycroft 	sc->sc_state = 0;
    230      1.1      cgd 	outb(sc->sc_port+lpt_control, LPC_NINIT);
    231      1.1      cgd 	return (1);
    232      1.1      cgd }
    233      1.1      cgd 
    234      1.1      cgd /*
    235      1.1      cgd  * lptopen -- reset the printer, then wait until it's selected and not busy.
    236      1.1      cgd  */
    237      1.1      cgd 
    238  1.7.4.1  mycroft int
    239      1.1      cgd lptopen(dev, flag)
    240      1.1      cgd 	dev_t dev;
    241      1.1      cgd 	int flag;
    242      1.1      cgd {
    243  1.7.4.1  mycroft 	struct lpt_softc *sc;
    244      1.1      cgd 	int s;
    245      1.1      cgd 	int trys, port;
    246  1.7.4.1  mycroft 	int unit = LPTUNIT(minor(dev));
    247  1.7.4.1  mycroft 
    248  1.7.4.1  mycroft 	if (unit >= NLPT)
    249  1.7.4.1  mycroft 		return ENXIO;
    250  1.7.4.1  mycroft 	sc = &lpt_sc[unit];
    251      1.1      cgd 
    252      1.1      cgd 	if (sc->sc_state) {
    253      1.1      cgd lprintf("lp: still open\n") ;
    254      1.1      cgd printf("still open %x\n", sc->sc_state);
    255      1.1      cgd 		return(EBUSY);
    256      1.1      cgd 	} else	sc->sc_state |= INIT;
    257      1.1      cgd 
    258      1.1      cgd 	s = spltty();
    259      1.1      cgd 	sc->sc_flags = LPTFLAGS(minor(dev));
    260      1.1      cgd lprintf("lp flags 0x%x\n", sc->sc_flags);
    261      1.1      cgd 	port = sc->sc_port;
    262      1.1      cgd 
    263      1.1      cgd 	/* init printer */
    264      1.1      cgd 	if((sc->sc_flags & LP_NO_PRIME) == 0) {
    265      1.1      cgd 		if((sc->sc_flags & LP_PRIMEOPEN) || sc->sc_primed == 0) {
    266      1.1      cgd 			outb(port+lpt_control, 0);
    267      1.1      cgd 			sc->sc_primed++;
    268      1.1      cgd 			DELAY(500);
    269      1.1      cgd 		}
    270      1.1      cgd 	}
    271      1.1      cgd 	outb(port+lpt_control, LPC_SEL|LPC_NINIT);
    272      1.1      cgd 
    273      1.1      cgd 	/* wait till ready (printer running diagnostics) */
    274      1.1      cgd 	trys = 0;
    275      1.1      cgd 	do {
    276      1.1      cgd 		/* ran out of waiting for the printer */
    277      1.1      cgd 		if (trys++ >= LPINITRDY*4) {
    278      1.1      cgd 			splx(s);
    279      1.1      cgd 			sc->sc_state = 0;
    280      1.1      cgd printf ("status %x\n", inb(port+lpt_status) );
    281      1.1      cgd 			return (EBUSY);
    282      1.1      cgd 		}
    283      1.1      cgd 
    284      1.1      cgd 		/* wait 1/4 second, give up if we get a signal */
    285      1.7  mycroft 		if (tsleep((caddr_t)sc,
    286      1.7  mycroft 			   LPPRI|PCATCH, "lptinit", hz/4) != EWOULDBLOCK) {
    287      1.1      cgd 			sc->sc_state = 0;
    288      1.1      cgd 			splx(s);
    289      1.1      cgd 			return (EBUSY);
    290      1.1      cgd 		}
    291      1.1      cgd 
    292      1.1      cgd 		/* is printer online and ready for output */
    293      1.1      cgd 	} while ((inb(port+lpt_status) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
    294      1.1      cgd 			(LPS_SEL|LPS_NBSY|LPS_NERR));
    295      1.1      cgd 
    296      1.1      cgd 	if(sc->sc_flags&LP_AUTOLF) {
    297      1.1      cgd 		outb(port+lpt_control, LPC_SEL|LPC_NINIT|LPC_ENA|LPC_AUTOL);
    298      1.1      cgd 		sc->sc_control = LPC_SEL|LPC_NINIT|LPC_ENA|LPC_AUTOL;
    299      1.1      cgd 	} else {
    300      1.1      cgd 		outb(port+lpt_control, LPC_SEL|LPC_NINIT|LPC_ENA);
    301      1.1      cgd 		sc->sc_control = LPC_SEL|LPC_NINIT|LPC_ENA;
    302      1.1      cgd 	}
    303      1.1      cgd 
    304      1.1      cgd 	sc->sc_state = OPEN | TOUT;
    305      1.1      cgd 	sc->sc_inbuf = geteblk(BUFSIZE);
    306      1.1      cgd 	sc->sc_xfercnt = 0;
    307      1.1      cgd 	splx(s);
    308      1.7  mycroft 	timeout((timeout_t)lptout, (caddr_t)sc, hz/2);
    309      1.1      cgd lprintf("opened.\n");
    310      1.1      cgd 	return(0);
    311      1.1      cgd }
    312      1.1      cgd 
    313  1.7.4.1  mycroft void
    314  1.7.4.1  mycroft lptout(sc)
    315      1.1      cgd 	struct lpt_softc *sc;
    316      1.1      cgd {	int pl;
    317      1.1      cgd 
    318      1.1      cgd lprintf ("T %x ", inb(sc->sc_port+lpt_status));
    319      1.1      cgd 	if (sc->sc_state&OPEN)
    320      1.7  mycroft 		timeout((timeout_t)lptout, (caddr_t)sc, hz/2);
    321      1.1      cgd 	else	sc->sc_state &= ~TOUT;
    322      1.1      cgd 
    323      1.1      cgd 	if (sc->sc_state & ERROR)
    324      1.1      cgd 		sc->sc_state &= ~ERROR;
    325      1.1      cgd 
    326      1.1      cgd 	/*
    327      1.1      cgd 	 * Avoid possible hangs do to missed interrupts
    328      1.1      cgd 	 */
    329      1.1      cgd 	if (sc->sc_xfercnt) {
    330      1.1      cgd 		pl = spltty();
    331      1.1      cgd 		lptintr(sc - lpt_sc);
    332      1.1      cgd 		splx(pl);
    333      1.1      cgd 	} else {
    334      1.1      cgd 		sc->sc_state &= ~OBUSY;
    335      1.1      cgd 		wakeup((caddr_t)sc);
    336      1.1      cgd 	}
    337      1.1      cgd }
    338      1.1      cgd 
    339      1.1      cgd /*
    340      1.1      cgd  * lptclose -- close the device, free the local line buffer.
    341      1.1      cgd  */
    342      1.1      cgd 
    343  1.7.4.1  mycroft int
    344      1.1      cgd lptclose(dev, flag)
    345  1.7.4.1  mycroft 	dev_t dev;
    346      1.1      cgd 	int flag;
    347      1.1      cgd {
    348      1.1      cgd 	struct lpt_softc *sc = lpt_sc + LPTUNIT(minor(dev));
    349      1.1      cgd 	int port = sc->sc_port;
    350      1.1      cgd 
    351      1.1      cgd 	sc->sc_state &= ~OPEN;
    352      1.1      cgd 	while ((inb(port+lpt_status) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
    353      1.1      cgd 			(LPS_SEL|LPS_NBSY|LPS_NERR) || sc->sc_xfercnt)
    354      1.1      cgd 		/* wait 1/4 second, give up if we get a signal */
    355      1.7  mycroft 		if (tsleep((caddr_t)sc,
    356      1.7  mycroft 			   LPPRI|PCATCH, "lpclose", hz) != EWOULDBLOCK)
    357      1.1      cgd 			break;
    358      1.1      cgd 
    359      1.1      cgd 	sc->sc_state = 0;
    360      1.1      cgd 	sc->sc_xfercnt = 0;
    361      1.1      cgd 	outb(sc->sc_port+lpt_control, LPC_NINIT);
    362      1.1      cgd 	brelse(sc->sc_inbuf);
    363      1.1      cgd lprintf("closed.\n");
    364      1.1      cgd 	return(0);
    365      1.1      cgd }
    366      1.1      cgd 
    367      1.1      cgd /*
    368      1.1      cgd  * lptwrite --copy a line from user space to a local buffer, then call
    369      1.1      cgd  * putc to get the chars moved to the output queue.
    370      1.1      cgd  */
    371      1.1      cgd 
    372  1.7.4.1  mycroft int
    373      1.1      cgd lptwrite(dev, uio)
    374      1.1      cgd 	dev_t dev;
    375      1.1      cgd 	struct uio *uio;
    376      1.1      cgd {
    377      1.1      cgd 	register unsigned n;
    378      1.1      cgd 	int pl, err;
    379      1.1      cgd 	struct lpt_softc *sc = lpt_sc + LPTUNIT(minor(dev));
    380      1.1      cgd 
    381      1.1      cgd 	while (n = MIN(BUFSIZE, uio->uio_resid)) {
    382      1.1      cgd 		sc->sc_cp = sc->sc_inbuf->b_un.b_addr ;
    383      1.1      cgd 		uiomove(sc->sc_cp, n, uio);
    384      1.1      cgd 		sc->sc_xfercnt = n ;
    385      1.1      cgd 		while (sc->sc_xfercnt > 0) {
    386      1.1      cgd 			/* if the printer is ready for a char, give it one */
    387      1.1      cgd 			if ((sc->sc_state & OBUSY) == 0){
    388      1.1      cgd lprintf("\nC %d. ", sc->sc_xfercnt);
    389      1.1      cgd 				pl = spltty();
    390      1.1      cgd 				lptintr(sc - lpt_sc);
    391      1.1      cgd 				(void) splx(pl);
    392      1.1      cgd 			}
    393      1.1      cgd lprintf("W ");
    394      1.7  mycroft 			if (err = tsleep((caddr_t)sc,
    395      1.7  mycroft 					 LPPRI|PCATCH, "lpwrite", 0))
    396      1.1      cgd 				return(err);
    397      1.1      cgd 		}
    398      1.1      cgd 	}
    399      1.1      cgd 	return(0);
    400      1.1      cgd }
    401      1.1      cgd 
    402      1.1      cgd /*
    403      1.1      cgd  * lptintr -- handle printer interrupts which occur when the printer is
    404      1.1      cgd  * ready to accept another char.
    405      1.1      cgd  */
    406      1.1      cgd 
    407  1.7.4.1  mycroft void
    408      1.1      cgd lptintr(unit)
    409  1.7.4.1  mycroft 	int unit;
    410      1.1      cgd {
    411      1.1      cgd 	struct lpt_softc *sc = lpt_sc + unit;
    412      1.1      cgd 	int port = sc->sc_port,sts;
    413      1.1      cgd 
    414      1.6  mycroft 	sts = inb(port+lpt_status);
    415      1.6  mycroft 
    416      1.6  mycroft 	if (!sc->sc_state) {
    417      1.6  mycroft 		printf ("lpt%d: stray interrupt sts=0x%02x\n", unit, sts);
    418      1.6  mycroft 		return;
    419      1.6  mycroft 	}
    420      1.6  mycroft 
    421      1.1      cgd 	/* is printer online and ready for output */
    422      1.6  mycroft 	if ((sts & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR/*|LPS_NACK*/)) ==
    423      1.1      cgd 			(LPS_SEL|LPS_NBSY|LPS_NERR)) {
    424      1.1      cgd 			/* is this a false interrupt ? */
    425      1.1      cgd 			if ((sc->sc_state & OBUSY)
    426      1.1      cgd 				&& (sts & LPS_NACK) == 0) return;
    427      1.1      cgd 		sc->sc_state |= OBUSY; sc->sc_state &= ~ERROR;
    428      1.1      cgd 
    429      1.1      cgd 		if (sc->sc_xfercnt) {
    430      1.1      cgd 			/* send char */
    431      1.1      cgd /*lprintf("%x ", *sc->sc_cp); */
    432      1.1      cgd 			outb(port+lpt_data, *sc->sc_cp++) ; sc->sc_xfercnt-- ;
    433      1.1      cgd 			outb(port+lpt_control, sc->sc_control|LPC_STB);
    434      1.1      cgd 			/* DELAY(X) */
    435      1.1      cgd 			outb(port+lpt_control, sc->sc_control);
    436      1.1      cgd 		}
    437      1.1      cgd 
    438      1.1      cgd 		/* any more bytes for the printer? */
    439      1.1      cgd 		if (sc->sc_xfercnt > 0) return;
    440      1.1      cgd 
    441      1.1      cgd 		/* none, wake up the top half to get more */
    442      1.1      cgd 		sc->sc_state &= ~OBUSY;
    443      1.1      cgd 		wakeup((caddr_t)sc);
    444      1.1      cgd lprintf("w ");
    445      1.1      cgd return;
    446      1.1      cgd 	} else	sc->sc_state |= ERROR;
    447      1.1      cgd lprintf("sts %x ", sts);
    448      1.1      cgd }
    449      1.1      cgd 
    450      1.2      cgd int
    451  1.7.4.1  mycroft lptioctl(dev, cmd, data, flag)
    452  1.7.4.1  mycroft 	dev_t dev;
    453  1.7.4.1  mycroft 	int cmd;
    454  1.7.4.1  mycroft 	caddr_t data;
    455  1.7.4.1  mycroft 	int flag;
    456      1.2      cgd {
    457      1.2      cgd 	int	error;
    458      1.2      cgd 
    459      1.2      cgd 	error = 0;
    460      1.2      cgd 	switch (cmd) {
    461      1.2      cgd #ifdef THISISASAMPLE
    462      1.2      cgd 	case XXX:
    463      1.2      cgd 		dothis; andthis; andthat;
    464      1.2      cgd 		error=x;
    465      1.2      cgd 		break;
    466      1.2      cgd #endif /* THISISASAMPLE */
    467      1.2      cgd 	default:
    468      1.2      cgd 		error = ENODEV;
    469      1.2      cgd 	}
    470      1.2      cgd 
    471      1.2      cgd 	return(error);
    472      1.2      cgd }
    473      1.2      cgd 
    474      1.2      cgd #endif	/* NLPT */
    475