4a462b8783e8c2b38a71497ab4c8c752e8191848
* Benson-Varian matrix printer/plotter. Device "va", for "varian".
int vabdp
= 1; /* Used with ubasetup. */
unsigned minvaph(); /* Maximum amount transferred by physio. */
struct varegs
{ /* Unibus registers provided by va. */
unsigned short vabufaddr
; /* DMA buffer address. */
short vawcount
; /* Negative of number of 16-bit
words to transfer by DMA. */
short vacsrword
; /* csr addressed as a word (for R). */
char Vacsrhi
; /* High byte (command bytes go here). */
} vacsrbytes
; /* csr addressed as bytes (for W). */
} vacsr
; /* Control/Status Register (csr). */
#define vacsrhi vacsr.vacsrbytes.Vacsrhi
#define vacsrlo vacsr.vacsrbytes.Vacsrlo
#define VAADDR ((struct varegs *)(UBA0_DEV + 0164000))
/* vacsr.vacsrword bits: */
#define ERROR 0100000 /* R Some error has occurred */
#define NPRTIMO 01000 /* R DMA timeout error */
#define NOTREADY 0400 /* R Something besides NPRTIMO */
#define DONE 0200 /* R */
#define IENABLE 0100 /* R/W Interrupt enable */
#define SUPPLIESLOW 04 /* R */
#define BOTOFFORM 02 /* R */
#define BYTEREVERSE 01 /* R/W Reverse byte order in words */
/* Command bytes sent to vacsrhi */
/* The following commands are not used in this driver: */
#define VANOAUTOSTEP 0045
int va_state
; /* State: bits are commands in vcmd.h. */
struct buf rvabuf
; /* Used by physio for a buffer. */
if (vainfo
.va_is_open
) { /* Can't open if it's already open. */
vainfo
.va_is_open
= 1; /* NOW it's open! */
VAADDR
->vawcount
= 0; /* Clear residual errors */
vainfo
.va_wcount
= 0; /* No DMA to do now. */
VAADDR
->vacsrlo
= IENABLE
;
vacmd(VPRINT
); /* Start in print mode. */
while (vainfo
.va_busy
) /* Wait till not busy. */
sleep((caddr_t
)&vainfo
, VAPRI
);
vainfo
.va_busy
= 1; /* Grab it. */
va_ubinfo
= ubasetup(bp
, vabdp
); /* Set up uba mapper. */
vainfo
.va_bufp
= va_ubinfo
& 0x3ffff;
vainfo
.va_wcount
= -(bp
->b_bcount
/2);
so user had better supply an even number of bytes. */
e
= vaerror(DONE
); /* Wait for DMA to complete. */
vainfo
.va_wcount
= 0; /* Reset state info. */
/* After printing a line of characters, VPRINTPLOT mode essentially
reverts to VPLOT mode, plotting things until a new mode is set.
This change is indicated by sending a VAAUTOSTEP command to
the va. We also change va_state to reflect this effective
if (vainfo
.va_state
& VPRINTPLOT
) {
vainfo
.va_state
= (vainfo
.va_state
& ~VPRINTPLOT
) | VPLOT
;
VAADDR
->vacsrhi
= VAAUTOSTEP
;
ubafree(va_ubinfo
), va_ubinfo
= 0;
wakeup((caddr_t
)&vainfo
);
if (bp
->b_bcount
> vablock
)
physio(vastrategy
, &rvabuf
, dev
, B_WRITE
, minvaph
);
* Vaerror waits until bit or ERROR gets set, then returns non-zero if
* if it was ERROR that was set.
while ((e
= VAADDR
->vacsr
.vacsrword
& (bit
|ERROR
)) == 0)
sleep((caddr_t
)&vainfo
, VAPRI
);
/* vastart starts up the DMA by setting the buffer pointer and the word count. */
VAADDR
->vabufaddr
= vainfo
.va_bufp
;
VAADDR
->vawcount
= vainfo
.va_wcount
;
vaioctl(dev
, cmd
, addr
, flag
)
(void) suword(addr
, vainfo
.va_state
);
u
.u_error
= ENOTTY
; /* Not a legal ioctl cmd. */
/* vacmd sends a command code to the va, and waits for it to complete.
If an error occurs, u.u_error is set to EIO.
vacmd also updates vainfo.va_state.
(void) vaerror(DONE
); /* Wait for va to be ready. */
/* Must turn on plot AND autostep modes. */
VAADDR
->vacsrhi
= VAPLOT
;
VAADDR
->vacsrhi
= VAAUTOSTEP
;
VAADDR
->vacsrhi
= VAPRINT
;
VAADDR
->vacsrhi
= VAPRINTPLOT
;
(vainfo
.va_state
& ~(VPLOT
| VPRINT
| VPRINTPLOT
)) | vcmd
;
if (vaerror(DONE
)) /* Wait for command to complete. */
timeout(vatimo
, (caddr_t
)0, HZ
/10);
wakeup((caddr_t
)&vainfo
);