* LP-11 Line printer driver
* This driver has been modified to work on printers where
* leaving IENABLE set would cause continuous interrupts.
* Test driver on multiple printers
#define LPUNIT(dev) (minor(dev) >> 3)
struct uba_device
*lpinfo
[NLP
];
int lpprobe(), lpattach(), lptout();
u_short lpstd
[] = { 0177514 };
struct uba_driver lpdriver
=
{ lpprobe
, 0, lpattach
, 0, lpstd
, "lp", lpinfo
};
#define OPEN 1 /* device is open */
#define TOUT 2 /* timeout is active */
#define MOD 4 /* device state has been modified */
#define ASLP 8 /* awaiting draining of printer */
register struct lpdevice
*lpaddr
;
register struct lp_softc
*sc
;
register struct uba_device
*ui
;
if ((unit
= LPUNIT(dev
)) >= NLP
)
lpaddr
= (struct lpdevice
*) ui
->ui_addr
;
if (sc
->sc_state
&OPEN
|| lpaddr
->lpsr
&ERROR
) {
sc
->sc_inbuf
= geteblk();
sc
->sc_flags
= minor(dev
) & 07;
if ((sc
->sc_state
&TOUT
) == 0) {
timeout(lptout
, dev
, 10*hz
);
register struct lp_softc
*sc
;
sc
= &lp_softc
[LPUNIT(dev
)];
register struct lp_softc
*sc
;
sc
= &lp_softc
[LPUNIT(dev
)];
while (n
= min(BSIZE
, u
.u_count
)) {
cp
= sc
->sc_inbuf
->b_un
.b_addr
;
register int logcol
, physcol
;
register struct lp_softc
*sc
;
sc
= &lp_softc
[LPUNIT(dev
)];
physcol
= sc
->sc_physcol
;
logcol
= (logcol
-8) & ~7;
if (sc
->sc_physline
== 0 && physcol
== 0)
while (logcol
> physcol
) {
if (logcol
> 1000) /* ignore long lines */
sc
->sc_physcol
= physcol
;
register struct lp_softc
*sc
;
sc
= &lp_softc
[LPUNIT(dev
)];
if (sc
->sc_outq
.c_cc
>= LPHWAT
) {
lpintr(dev
); /* unchoke */
while (sc
->sc_outq
.c_cc
>= LPHWAT
) {
sc
->sc_state
|= ASLP
; /* must be ERROR */
sleep((caddr_t
)sc
, LPPRI
);
while (putc(c
, &sc
->sc_outq
))
sleep((caddr_t
)&lbolt
, LPPRI
);
register struct lp_softc
*sc
;
register struct lpdevice
*lpaddr
;
register struct uba_device
*ui
;
sc
= &lp_softc
[LPUNIT(dev
)];
ui
= lpinfo
[LPUNIT(dev
)];
lpaddr
= (struct lpdevice
*) ui
->ui_addr
;
lpaddr
->lpsr
&= ~IENABLE
;
sc
->sc_lpchar
= getc(&sc
->sc_outq
);
while ((lpaddr
->lpsr
&DONE
) && sc
->sc_lpchar
>= 0) {
lpaddr
->lpbuf
= sc
->sc_lpchar
;
sc
->sc_lpchar
= getc(&sc
->sc_outq
);
if (sc
->sc_outq
.c_cc
> 0 && (lpaddr
->lpsr
&ERROR
)==0)
lpaddr
->lpsr
|= IENABLE
; /* ok and more to do later */
if (n
>LPLWAT
&& sc
->sc_outq
.c_cc
<=LPLWAT
&& sc
->sc_state
&ASLP
) {
wakeup((caddr_t
)sc
); /* top half should go on */
register struct lp_softc
*sc
;
register struct uba_device
*ui
;
register struct lpdevice
*lpaddr
;
sc
= &lp_softc
[LPUNIT(dev
)];
ui
= lpinfo
[LPUNIT(dev
)];
lpaddr
= (struct lpdevice
*) ui
->ui_addr
;
if ((sc
->sc_state
&MOD
) != 0) {
sc
->sc_state
&= ~MOD
; /* something happened */
timeout(lptout
, dev
, 2*hz
); /* so don't sweat */
if ((sc
->sc_state
&OPEN
) == 0) {
sc
->sc_state
&= ~TOUT
; /* no longer open */
if (sc
->sc_outq
.c_cc
&& (lpaddr
->lpsr
&DONE
) && (lpaddr
->lpsr
&ERROR
)==0)
lpintr(dev
); /* ready to go */
timeout(lptout
, dev
, 10*hz
);
register struct uba_device
*ui
;
register struct lpdevice
*lpaddr
;
for (unit
= 0; unit
< NLP
; unit
++)
if (ui
== 0 || ui
->ui_ubanum
!= uban
|| ui
->ui_alive
== 0)
lpaddr
= (struct lpdevice
*) ui
->ui_addr
;
register struct lp_softc
*sc
;
sc
= &lp_softc
[ui
->ui_unit
];
register struct lpdevice
*lpaddr
;
register int delay
= 10000;
lpaddr
= (struct lpdevice
*) reg
;
lpaddr
->lpsr
&= ~IENABLE
;