xref: /csrg-svn/sys/vax/uba/va.c (revision 1938)
1*1938Swnj /*	va.c	4.3	12/19/80	*/
241Sbill 
3*1938Swnj #include "va.h"
41564Sbill #if NVA > 0
51564Sbill /*
61564Sbill  * Benson-Varian matrix printer/plotter
71564Sbill  * dma interface driver
81564Sbill  */
941Sbill #include "../h/param.h"
1041Sbill #include "../h/dir.h"
1141Sbill #include "../h/user.h"
1241Sbill #include "../h/buf.h"
1341Sbill #include "../h/systm.h"
1441Sbill #include "../h/map.h"
1541Sbill #include "../h/pte.h"
1641Sbill #include "../h/uba.h"
1741Sbill #include "../h/vcmd.h"
1841Sbill 
19287Sbill int	vabdp = 1;
2041Sbill 
21287Sbill unsigned minvaph();
2241Sbill 
2341Sbill #define	VAPRI	(PZERO-1)
2441Sbill 
25287Sbill #define	ushort	unsigned short
26287Sbill struct	varegs {
27287Sbill 	ushort	vaba;
28287Sbill 	short	vawc;
2941Sbill 	union {
30287Sbill 		short	Vacsw;
3141Sbill 		struct {
32287Sbill 			char Vacsl;
33287Sbill 			char Vacsh;
34287Sbill 		} vacsr;
35287Sbill 	} vacs;
3641Sbill 	short	vadata;
3741Sbill };
3841Sbill 
39287Sbill #define	vacsw	vacs.Vacsw
40287Sbill #define	vacsh	vacs.vacsr.Vacsh
41287Sbill #define	vacsl	vacs.vacsr.Vacsl
42287Sbill 
43287Sbill /* vacsw bits */
44287Sbill #define	ERROR		0100000		/* Some error has occurred */
451564Sbill #define	NPRTIMO		01000		/* DMA timeout error */
461564Sbill #define	NOTREADY	0400		/* Something besides NPRTIMO */
471564Sbill #define	DONE		0200
48287Sbill #define	IENABLE		0100		/* Interrupt enable */
49287Sbill #define	SUPPLIESLOW	04
501564Sbill #define	BOTOFFORM	02
511564Sbill #define	BYTEREVERSE	01		/* Reverse byte order in words */
5241Sbill 
53287Sbill /* vacsh command bytes */
541564Sbill #define	VAPLOT		0340
551564Sbill #define	VAPRINT		0100
561564Sbill #define	VAPRINTPLOT	0160
571564Sbill #define	VAAUTOSTEP	0244
581564Sbill #define	VANOAUTOSTEP	0045		/* unused */
59287Sbill #define	VAFORMFEED	0263		/* unused */
60287Sbill #define	VASLEW		0265		/* unused */
61287Sbill #define	VASTEP		0064		/* unused */
6241Sbill 
6341Sbill struct {
64287Sbill 	char	va_open;
6541Sbill 	char	va_busy;
6641Sbill 	int	va_state;	/* State: bits are commands in vcmd.h. */
67287Sbill 	int	va_wc;
6841Sbill 	int	va_bufp;
69287Sbill 	struct	buf *va_bp;
70287Sbill } va11;
7141Sbill int	va_ubinfo;
7241Sbill 
7341Sbill struct	buf rvabuf;		/* Used by physio for a buffer. */
7441Sbill 
7541Sbill vaopen()
7641Sbill {
7741Sbill 
78287Sbill 	if (va11.va_open) {
7941Sbill 		u.u_error = ENXIO;
8041Sbill 		return;
8141Sbill 	}
82287Sbill 	va11.va_open = 1;
83287Sbill 	VAADDR->vawc = 0;
84287Sbill 	va11.va_wc = 0;
85287Sbill 	va11.va_state = 0;
86287Sbill 	VAADDR->vacsl = IENABLE;
8741Sbill 	vatimo();
88287Sbill 	vacmd(VPRINT);
8941Sbill 	if (u.u_error)
9041Sbill 		vaclose();
9141Sbill }
9241Sbill 
9341Sbill vastrategy(bp)
9441Sbill 	register struct buf *bp;
9541Sbill {
9641Sbill 	register int e;
9741Sbill 
98133Sbill 	(void) spl4();
99287Sbill 	while (va11.va_busy)
100287Sbill 		sleep((caddr_t)&va11, VAPRI);
101287Sbill 	va11.va_busy = 1;
102287Sbill 	va11.va_bp = bp;
103287Sbill 	va_ubinfo = ubasetup(bp, vabdp);
104287Sbill 	va11.va_bufp = va_ubinfo & 0x3ffff;
10541Sbill 	if (e = vaerror(DONE))
10641Sbill 		goto brkout;
107287Sbill 	va11.va_wc = -(bp->b_bcount/2);
10841Sbill 	vastart();
109287Sbill 	e = vaerror(DONE);	/* Wait for DMA to complete */
110287Sbill 	va11.va_wc = 0;
111287Sbill 	va11.va_bufp = 0;
11241Sbill 
113287Sbill 	/*
114287Sbill 	 * After printing a line of characters, VPRINTPLOT mode essentially
115287Sbill 	 * reverts to VPLOT mode, plotting things until a new mode is set.
116287Sbill 	 * This change is indicated by sending a VAAUTOSTEP command to
117287Sbill 	 * the va.  We also change va_state to reflect this effective
118287Sbill 	 * mode change.
11941Sbill 	 */
120287Sbill 	if (va11.va_state & VPRINTPLOT) {
121287Sbill 		va11.va_state = (va11.va_state & ~VPRINTPLOT) | VPLOT;
122287Sbill 		VAADDR->vacsh = VAAUTOSTEP;
12341Sbill 		e |= vaerror(DONE);
12441Sbill 	}
125133Sbill 	(void) spl0();
12641Sbill brkout:
12741Sbill 	ubafree(va_ubinfo), va_ubinfo = 0;
128287Sbill 	va11.va_bp = 0;
129287Sbill 	va11.va_busy = 0;
13041Sbill 	iodone(bp);
13141Sbill 	if (e)
13241Sbill 		u.u_error = EIO;
133287Sbill 	wakeup((caddr_t)&va11);
13441Sbill }
13541Sbill 
13641Sbill int	vablock = 16384;
13741Sbill 
13841Sbill unsigned
13941Sbill minvaph(bp)
14041Sbill struct buf *bp;
14141Sbill {
14241Sbill 	if (bp->b_bcount > vablock)
14341Sbill 		bp->b_bcount = vablock;
14441Sbill }
14541Sbill 
14641Sbill /*ARGSUSED*/
14741Sbill vawrite(dev)
14841Sbill {
14941Sbill 	physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph);
15041Sbill }
15141Sbill 
15241Sbill /*
15341Sbill  * Vaerror waits until bit or ERROR gets set, then returns non-zero if
15441Sbill  * if it was ERROR that was set.
15541Sbill  */
15641Sbill vaerror(bit)
15741Sbill {
15841Sbill 	register int e;
15941Sbill 
160287Sbill 	while ((e = VAADDR->vacsw & (bit|ERROR)) == 0)
161287Sbill 		sleep((caddr_t)&va11, VAPRI);
16241Sbill 	return (e & ERROR);
16341Sbill }
16441Sbill 
16541Sbill vastart()
16641Sbill {
167287Sbill 	if (va11.va_wc) {
168287Sbill 		VAADDR->vaba = va11.va_bufp;
1691903Swnj 		VAADDR->vacsl = (va11.va_bufp >> 12) & 0x30;
170287Sbill 		VAADDR->vawc = va11.va_wc;
17141Sbill 		return;
17241Sbill 	}
17341Sbill }
17441Sbill 
17541Sbill /*ARGSUSED*/
17641Sbill vaioctl(dev, cmd, addr, flag)
17741Sbill 	register caddr_t addr;
17841Sbill {
17941Sbill 	register int vcmd;
18041Sbill 
18141Sbill 	switch (cmd) {
18241Sbill 
18341Sbill 	case VGETSTATE:
184287Sbill 		(void) suword(addr, va11.va_state);
18541Sbill 		return;
18641Sbill 
18741Sbill 	case VSETSTATE:
18841Sbill 		vcmd = fuword(addr);
18941Sbill 		if (vcmd == -1) {
19041Sbill 			u.u_error = EFAULT;
19141Sbill 			return;
19241Sbill 		}
19341Sbill 		vacmd(vcmd);
19441Sbill 		return;
19541Sbill 
19641Sbill 	default:
19741Sbill 		u.u_error = ENOTTY;	/* Not a legal ioctl cmd. */
19841Sbill 		return;
19941Sbill 	}
20041Sbill }
20141Sbill 
202287Sbill /*
203287Sbill  * Send a command code to the va, and wait for it to complete.
204287Sbill  * If an error occurs, u.u_error is set to EIO.
205287Sbill  * In any case, update va11.va_state.
20641Sbill  */
20741Sbill vacmd(vcmd)
20841Sbill {
209133Sbill 	(void) spl4();
210287Sbill 	(void) vaerror(DONE);		/* Wait for va to be ready */
21141Sbill 	switch (vcmd) {
21241Sbill 
21341Sbill 	case VPLOT:
21441Sbill 		/* Must turn on plot AND autostep modes. */
215287Sbill 		VAADDR->vacsh = VAPLOT;
21641Sbill 		if (vaerror(DONE))
21741Sbill 			u.u_error = EIO;
218287Sbill 		VAADDR->vacsh = VAAUTOSTEP;
21941Sbill 		break;
22041Sbill 
22141Sbill 	case VPRINT:
222287Sbill 		VAADDR->vacsh = VAPRINT;
22341Sbill 		break;
22441Sbill 
22541Sbill 	case VPRINTPLOT:
226287Sbill 		VAADDR->vacsh = VAPRINTPLOT;
22741Sbill 		break;
22841Sbill 	}
229287Sbill 	va11.va_state =
230287Sbill 		(va11.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd;
23141Sbill 
23241Sbill 	if (vaerror(DONE))	/* Wait for command to complete. */
23341Sbill 		u.u_error = EIO;
234133Sbill 	(void) spl0();
23541Sbill }
23641Sbill 
23741Sbill vatimo()
23841Sbill {
239287Sbill 	if (va11.va_open)
24041Sbill 		timeout(vatimo, (caddr_t)0, HZ/10);
24141Sbill 	vaintr(0);
24241Sbill }
24341Sbill 
24441Sbill /*ARGSUSED*/
24541Sbill vaintr(dev)
24641Sbill {
247287Sbill 	wakeup((caddr_t)&va11);
24841Sbill }
24941Sbill 
25041Sbill vaclose()
25141Sbill {
25241Sbill 
253287Sbill 	va11.va_open = 0;
254287Sbill 	va11.va_busy = 0;
255287Sbill 	va11.va_state = 0;
256287Sbill 	va11.va_wc = 0;
257287Sbill 	va11.va_bufp = 0;
258287Sbill 	VAADDR->vacsl = 0;
25941Sbill }
260287Sbill 
261287Sbill #define	DELAY(N)	{ register int d; d = N; while (--d > 0); }
262287Sbill 
263287Sbill vareset()
264287Sbill {
265287Sbill 
266287Sbill 	if (va11.va_open == 0)
267287Sbill 		return;
268287Sbill 	printf(" va");
269287Sbill 	VAADDR->vacsl = IENABLE;
270287Sbill 	if (va11.va_state & VPLOT) {
271287Sbill 		VAADDR->vacsh = VAPLOT;
272287Sbill 		DELAY(10000);
273287Sbill 		VAADDR->vacsh = VAAUTOSTEP;
274287Sbill 	} else if (va11.va_state & VPRINTPLOT)
275287Sbill 		VAADDR->vacsh = VPRINTPLOT;
276287Sbill 	else
277287Sbill 		VAADDR->vacsh = VAPRINTPLOT;
278287Sbill 	DELAY(10000);
279287Sbill 	if (va11.va_busy == 0)
280287Sbill 		return;
281287Sbill 	if (va_ubinfo) {
282287Sbill 		printf("<%d>", (va_ubinfo>>28)&0xf);
283287Sbill 		ubafree(va_ubinfo), va_ubinfo = 0;
284287Sbill 	}
285287Sbill 	/* This code belongs in vastart() */
286287Sbill 	va_ubinfo = ubasetup(va11.va_bp, vabdp);
287287Sbill 	va11.va_bufp = va_ubinfo & 0x3ffff;
288287Sbill 	va11.va_wc = (-va11.va_bp->b_bcount/2);
289287Sbill 	/* End badly placed code */
290287Sbill 	vastart();
291287Sbill }
2921564Sbill #endif
293