* LP-11 Line printer driver
* This driver has been modified to work on printers where
* leaving IENABLE set would cause continuous interrupts.
#include "../machine/pte.h"
#include "../vaxuba/ubavar.h"
#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 lp_softc
*sc
;
sc
= &lp_softc
[ui
->ui_unit
];
register int br
, cvec
; /* value-result */
register struct lpdevice
*lpaddr
= (struct lpdevice
*)reg
;
br
= 0; cvec
= br
; br
= cvec
;
return (sizeof (struct lpdevice
));
register struct lpdevice
*lpaddr
;
register struct lp_softc
*sc
;
register struct uba_device
*ui
;
if ((unit
= LPUNIT(dev
)) >= NLP
||
(sc
= &lp_softc
[unit
])->sc_state
&OPEN
||
(ui
= lpinfo
[unit
]) == 0 || ui
->ui_alive
== 0)
lpaddr
= (struct lpdevice
*)ui
->ui_addr
;
sc
->sc_inbuf
= geteblk(512);
sc
->sc_flags
= minor(dev
) & 07;
if ((sc
->sc_state
&TOUT
) == 0) {
timeout(lptout
, (caddr_t
)dev
, 10*hz
);
register struct lp_softc
*sc
= &lp_softc
[LPUNIT(dev
)];
register struct lp_softc
*sc
= &lp_softc
[LPUNIT(dev
)];
while (n
= min(512, uio
->uio_resid
)) {
cp
= sc
->sc_inbuf
->b_un
.b_addr
;
error
= uiomove(cp
, n
, UIO_WRITE
, uio
);
register int logcol
, physcol
;
register struct lp_softc
*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
= &lp_softc
[LPUNIT(dev
)];
if (sc
->sc_outq
.c_cc
>= LPHWAT
) {
lpintr(LPUNIT(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
= &lp_softc
[lp11
];
register struct uba_device
*ui
= lpinfo
[lp11
];
register struct lpdevice
*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
, (caddr_t
)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(LPUNIT(dev
)); /* ready to go */
timeout(lptout
, (caddr_t
)dev
, 10*hz
);
register struct uba_device
*ui
;
register struct lpdevice
*lpaddr
;
for (unit
= 0; unit
< NLP
; unit
++) {
if ((ui
= lpinfo
[unit
]) == 0 || ui
->ui_ubanum
!= uban
||
lpaddr
= (struct lpdevice
*)ui
->ui_addr
;