* Versatec matrix printer/plotter
#define VP_DTCINTR 0040000
#define VP_DMAACT 0020000
#define VP_IENABLE 0000100
#define VP_TERMCOM 0000040
#define VP_EOTCOM 0000010
#define VP_CLRCOM 0000004
#define VPSC_BUSY 0001000
#define VPSC_MODE 0000700
#define VPSC_PLOT 0000200
#define VPSC_PRINT 0000100
#define VPSC_CMNDS 0000076
#define VPSC_OPEN 0000001
struct uba_device
*vpdinfo
[NVP
];
#define VPUNIT(dev) (minor(dev))
int vpprobe(), vpattach();
struct uba_device
*vpdinfo
[NVP
];
u_short vpstd
[] = { 0777500, 0 };
struct uba_driver vpdriver
=
{ vpprobe
, 0, vpattach
, 0, vpstd
, "vp", vpdinfo
};
register int br
, cvec
; /* value-result */
register struct vpdevice
*vpaddr
= (struct vpdevice
*)(reg
-010);
vpaddr
->prcsr
= VP_IENABLE
|VP_DTCINTR
;
register struct vp_softc
*sc
;
register struct vpdevice
*vpaddr
;
register struct uba_device
*ui
;
if (VPUNIT(dev
) >= NVP
||
((sc
= &vp_softc
[minor(dev
)])->sc_state
&VPSC_OPEN
) ||
(ui
= vpdinfo
[VPUNIT(dev
)]) == 0 || ui
->ui_alive
== 0) {
vpaddr
= (struct vpdevice
*)ui
->ui_addr
;
sc
->sc_state
= VPSC_OPEN
|VPSC_PRINT
| VP_CLRCOM
|VP_RESET
;
vpaddr
->prcsr
= VP_IENABLE
|VP_DTCINTR
;
while (sc
->sc_state
& VPSC_CMNDS
) {
register struct vp_softc
*sc
= &vp_softc
[VPUNIT(bp
->b_dev
)];
register struct uba_device
*ui
= vpdinfo
[VPUNIT(bp
->b_dev
)];
register struct vpdevice
*vpaddr
= (struct vpdevice
*)ui
->ui_addr
;
while (sc
->sc_state
& VPSC_BUSY
)
sleep((caddr_t
)sc
, VPPRI
);
sc
->sc_state
|= VPSC_BUSY
;
sc
->sc_ubinfo
= ubasetup(ui
->ui_ubanum
, bp
, UBA_NEEDBDP
);
if (e
= vpwait(bp
->b_dev
))
sc
->sc_count
= bp
->b_bcount
;
while (((sc
->sc_state
&VPSC_PLOT
) ? vpaddr
->plcsr
: vpaddr
->prcsr
) & VP_DMAACT
)
sleep((caddr_t
)sc
, VPPRI
);
if ((sc
->sc_state
&VPSC_MODE
) == VPSC_SPP
)
sc
->sc_state
= (sc
->sc_state
&~ VPSC_MODE
) | VPSC_PLOT
;
ubarelse(ui
->ui_ubanum
, &sc
->sc_ubinfo
);
sc
->sc_state
&= ~VPSC_BUSY
;
if (bp
->b_bcount
> vpblock
)
physio(vpstrategy
, &rvpbuf
[VPUNIT(dev
)], dev
, B_WRITE
, minvpph
);
register struct vpdevice
*vpaddr
=
(struct vpdevice
*)vpdinfo
[VPUNIT(dev
)]->ui_addr
;
register struct vp_softc
*sc
= &vp_softc
[VPUNIT(dev
)];
e
= (sc
->sc_state
& VPSC_PLOT
) ? vpaddr
->plcsr
: vpaddr
->prcsr
;
if (e
& (VP_READY
|VP_ERROR
))
sleep((caddr_t
)sc
, VPPRI
);
/* I wish i could tell whether an error indicated an npr timeout */
register struct vp_softc
*sc
= &vp_softc
[VPUNIT(dev
)];
register struct vpdevice
*vpaddr
=
(struct vpdevice
*)vpdinfo
[VPUNIT(dev
)]->ui_addr
;
vpaddr
->pbaddr
= sc
->sc_ubinfo
;
vpaddr
->pbxaddr
= (sc
->sc_ubinfo
>>12)&0x30;
if (sc
->sc_state
& (VPSC_PRINT
|VPSC_SPP
))
vpaddr
->prbcr
= sc
->sc_count
;
vpaddr
->plbcr
= sc
->sc_count
;
for (bit
= 1; bit
!= 0; bit
<<= 1)
if (sc
->sc_state
&bit
&VPSC_CMNDS
) {
vpioctl(dev
, cmd
, addr
, flag
)
register struct vp_softc
*sc
= &vp_softc
[VPUNIT(dev
)];
register struct vpdevice
*vpaddr
=
(struct vpdevice
*)vpdinfo
[VPUNIT(dev
)]->ui_addr
;
(void) suword(addr
, sc
->sc_state
);
(sc
->sc_state
& ~VPSC_MODE
) | (m
&(VPSC_MODE
|VPSC_CMNDS
));
if (sc
->sc_state
&VPSC_SPP
)
vpaddr
->plcsr
&= ~VP_SPP
;
while (sc
->sc_state
& VPSC_CMNDS
) {
register struct vp_softc
*sc
= &vp_softc
[VPUNIT(dev
)];
if (sc
->sc_state
&VPSC_OPEN
)
timeout(vptimo
, (caddr_t
)dev
, hz
/10);
register struct vp_softc
*sc
= &vp_softc
[VPUNIT(dev
)];
register struct vp_softc
*sc
= &vp_softc
[VPUNIT(dev
)];
register struct vpdevice
*vpaddr
=
(struct vpdevice
*)vpdinfo
[VPUNIT(dev
)]->ui_addr
;
register struct uba_device
*ui
;
register struct vp_softc
*sc
= vp_softc
;
register struct vpdevice
*vpaddr
;
for (vp11
= 0; vp11
< NVP
; vp11
++, sc
++) {
if ((ui
= vpdinfo
[vp11
]) == 0 || ui
->ui_alive
== 0 ||
ui
->ui_ubanum
!= uban
|| (sc
->sc_state
&VPSC_OPEN
) == 0)
vpaddr
= (struct vpdevice
*)ui
->ui_addr
;
vpaddr
->prcsr
= VP_IENABLE
|VP_DTCINTR
;
if ((sc
->sc_state
& VPSC_BUSY
) == 0)
printf("<%d>", (sc
->sc_ubinfo
>>28)&0xf);
ubarelse(ui
->ui_ubanum
, &sc
->sc_ubinfo
);
sc
->sc_count
= sc
->sc_bp
->b_bcount
;
vpstart(sc
->sc_bp
->b_dev
);