4421e0e215792f45d2abd924ddad148ba99a1b54
* Copyright (c) 1982 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)vp.c 6.7 (Berkeley) %G%
* Versatec matrix printer/plotter
* Set up both print and plot interrupts to go through the same vector
* (or kludge probe to reset second vector to first;
* default 174/200 is already handled).
* Give the address of the plcsr register in the config specification
#include "../machine/pte.h"
#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);
br
= 0; cvec
= br
; br
= cvec
;
vpaddr
->prcsr
= VP_IENABLE
|VP_DTCINTR
;
/* GET INTERRUPT AT SECOND VECTOR BUT WANT FIRST */
printf("vp reset vec from 200 to 174\n");
return (sizeof (struct vpdevice
));
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
)
return (physio(vpstrategy
, &rvpbuf
[VPUNIT(dev
)], dev
, B_WRITE
,
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
, data
, flag
)
register struct vp_softc
*sc
= &vp_softc
[VPUNIT(dev
)];
register struct vpdevice
*vpaddr
=
(struct vpdevice
*)vpdinfo
[VPUNIT(dev
)]->ui_addr
;
*(int *)data
= sc
->sc_state
;
(sc
->sc_state
& ~VPSC_MODE
) |
((*(int *)data
) & (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)
sc
->sc_count
= sc
->sc_bp
->b_bcount
;
vpstart(sc
->sc_bp
->b_dev
);