xref: /csrg-svn/sys/vax/uba/va.c (revision 41)
1*41Sbill /*	va.c	3.1	10/14/12	*/
2*41Sbill 
3*41Sbill #ifdef ERNIE
4*41Sbill #include "../h/param.h"
5*41Sbill #include "../h/dir.h"
6*41Sbill #include "../h/user.h"
7*41Sbill #include "../h/buf.h"
8*41Sbill #include "../h/systm.h"
9*41Sbill #include "../h/map.h"
10*41Sbill #include "../h/pte.h"
11*41Sbill #include "../h/uba.h"
12*41Sbill #include "../h/vcmd.h"
13*41Sbill 
14*41Sbill /*
15*41Sbill  * Benson-Varian matrix printer/plotter.  Device "va", for "varian".
16*41Sbill  * dma interface driver
17*41Sbill  */
18*41Sbill int	vabdp = 1;	/* Used with ubasetup. */
19*41Sbill 
20*41Sbill unsigned minvaph();	/* Maximum amount transferred by physio. */
21*41Sbill 
22*41Sbill #define	VAPRI	(PZERO-1)
23*41Sbill 
24*41Sbill struct	varegs {	/* Unibus registers provided by va. */
25*41Sbill 	unsigned short vabufaddr;	/* DMA buffer address. */
26*41Sbill 	short vawcount;			/* Negative of number of 16-bit
27*41Sbill 					   words to transfer by DMA. */
28*41Sbill 	union {
29*41Sbill 		short vacsrword;	/* csr addressed as a word (for R). */
30*41Sbill 		struct {
31*41Sbill 			char Vacsrlo;
32*41Sbill 			char Vacsrhi;	/* High byte (command bytes go here). */
33*41Sbill 		} vacsrbytes;		/* csr addressed as bytes (for W). */
34*41Sbill 	} vacsr;			/* Control/Status Register (csr). */
35*41Sbill 	short	vadata;
36*41Sbill };
37*41Sbill 
38*41Sbill #define	vacsrhi	vacsr.vacsrbytes.Vacsrhi
39*41Sbill #define	vacsrlo	vacsr.vacsrbytes.Vacsrlo
40*41Sbill #define	VAADDR	((struct varegs *)(UBA0_DEV + 0164000))
41*41Sbill 
42*41Sbill /* vacsr.vacsrword bits: */
43*41Sbill #define	ERROR		0100000		/* R	Some error has occurred */
44*41Sbill #define NPRTIMO		01000		/* R    DMA timeout error */
45*41Sbill #define NOTREADY	0400		/* R	Something besides NPRTIMO */
46*41Sbill #define DONE		0200		/* R	*/
47*41Sbill #define	IENABLE		0100		/* R/W	Interrupt enable */
48*41Sbill #define	SUPPLIESLOW	04		/* R	*/
49*41Sbill #define BOTOFFORM	02		/* R	*/
50*41Sbill #define BYTEREVERSE	01		/* R/W	Reverse byte order in words */
51*41Sbill 
52*41Sbill /* Command bytes sent to vacsrhi */
53*41Sbill #define VAPLOT		0340
54*41Sbill #define VAPRINT		0100
55*41Sbill #define VAPRINTPLOT	0160
56*41Sbill #define VAAUTOSTEP	0244
57*41Sbill /* The following commands are not used in this driver: */
58*41Sbill #define VANOAUTOSTEP	0045
59*41Sbill #define	VAFORMFEED	0263
60*41Sbill #define	VASLEW		0265
61*41Sbill #define	VASTEP		0064
62*41Sbill 
63*41Sbill struct {
64*41Sbill 	char	va_is_open;
65*41Sbill 	char	va_busy;
66*41Sbill 	int	va_state;	/* State: bits are commands in vcmd.h. */
67*41Sbill 	int	va_wcount;
68*41Sbill 	int	va_bufp;
69*41Sbill } vainfo;
70*41Sbill int	va_ubinfo;
71*41Sbill 
72*41Sbill struct	buf rvabuf;		/* Used by physio for a buffer. */
73*41Sbill 
74*41Sbill vaopen()
75*41Sbill {
76*41Sbill 
77*41Sbill 	if (vainfo.va_is_open) {	/* Can't open if it's already open. */
78*41Sbill 		u.u_error = ENXIO;
79*41Sbill 		return;
80*41Sbill 	}
81*41Sbill 	vainfo.va_is_open = 1;		/* NOW it's open! */
82*41Sbill 	VAADDR->vawcount = 0;		/* Clear residual errors */
83*41Sbill 	vainfo.va_wcount = 0;		/* No DMA to do now. */
84*41Sbill 	vainfo.va_state = 0;
85*41Sbill 	VAADDR->vacsrlo = IENABLE;
86*41Sbill 					/* Enable interrupts. */
87*41Sbill 	vatimo();
88*41Sbill 
89*41Sbill 	vacmd(VPRINT);			/* Start in print mode. */
90*41Sbill 	if (u.u_error)
91*41Sbill 		vaclose();
92*41Sbill }
93*41Sbill 
94*41Sbill vastrategy(bp)
95*41Sbill 	register struct buf *bp;
96*41Sbill {
97*41Sbill 	register int e;
98*41Sbill 
99*41Sbill 	VOID spl4();
100*41Sbill 	while (vainfo.va_busy)		/* Wait till not busy. */
101*41Sbill 		sleep((caddr_t)&vainfo, VAPRI);
102*41Sbill 	vainfo.va_busy = 1;		/* Grab it. */
103*41Sbill 	VOID spl0();
104*41Sbill 
105*41Sbill 	va_ubinfo = ubasetup(bp, vabdp);	/* Set up uba mapper. */
106*41Sbill 	vainfo.va_bufp = va_ubinfo & 0x3ffff;
107*41Sbill 
108*41Sbill 	VOID spl4();
109*41Sbill 	if (e = vaerror(DONE))
110*41Sbill 		goto brkout;
111*41Sbill 	vainfo.va_wcount = -(bp->b_bcount/2);
112*41Sbill 		/* va uses a word count,
113*41Sbill 		   so user had better supply an even number of bytes. */
114*41Sbill 	vastart();
115*41Sbill 	e = vaerror(DONE);	/* Wait for DMA to complete. */
116*41Sbill 	vainfo.va_wcount = 0;	/* Reset state info. */
117*41Sbill 	vainfo.va_bufp = 0;
118*41Sbill 
119*41Sbill 	/* After printing a line of characters, VPRINTPLOT mode essentially
120*41Sbill 	   reverts to VPLOT mode, plotting things until a new mode is set.
121*41Sbill 	   This change is indicated by sending a VAAUTOSTEP command to
122*41Sbill 	   the va.  We also change va_state to reflect this effective
123*41Sbill 	   mode change.
124*41Sbill 	 */
125*41Sbill 	if (vainfo.va_state & VPRINTPLOT) {
126*41Sbill 		vainfo.va_state = (vainfo.va_state & ~VPRINTPLOT) | VPLOT;
127*41Sbill 		VAADDR->vacsrhi = VAAUTOSTEP;
128*41Sbill 		e |= vaerror(DONE);
129*41Sbill 	}
130*41Sbill 	VOID spl0();
131*41Sbill brkout:
132*41Sbill 	ubafree(va_ubinfo), va_ubinfo = 0;
133*41Sbill 	vainfo.va_busy = 0;
134*41Sbill 	iodone(bp);
135*41Sbill 	if (e)
136*41Sbill 		u.u_error = EIO;
137*41Sbill 	wakeup((caddr_t)&vainfo);
138*41Sbill }
139*41Sbill 
140*41Sbill int	vablock = 16384;
141*41Sbill 
142*41Sbill unsigned
143*41Sbill minvaph(bp)
144*41Sbill struct buf *bp;
145*41Sbill {
146*41Sbill 	if (bp->b_bcount > vablock)
147*41Sbill 		bp->b_bcount = vablock;
148*41Sbill }
149*41Sbill 
150*41Sbill /*ARGSUSED*/
151*41Sbill vawrite(dev)
152*41Sbill {
153*41Sbill 	physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph);
154*41Sbill }
155*41Sbill 
156*41Sbill /*
157*41Sbill  * Vaerror waits until bit or ERROR gets set, then returns non-zero if
158*41Sbill  * if it was ERROR that was set.
159*41Sbill  */
160*41Sbill vaerror(bit)
161*41Sbill {
162*41Sbill 	register int e;
163*41Sbill 
164*41Sbill 	while ((e = VAADDR->vacsr.vacsrword & (bit|ERROR)) == 0)
165*41Sbill 		sleep((caddr_t)&vainfo, VAPRI);
166*41Sbill 	return (e & ERROR);
167*41Sbill }
168*41Sbill 
169*41Sbill /* vastart starts up the DMA by setting the buffer pointer and the word count. */
170*41Sbill vastart()
171*41Sbill {
172*41Sbill 	if (vainfo.va_wcount) {
173*41Sbill 		VAADDR->vabufaddr = vainfo.va_bufp;
174*41Sbill 		VAADDR->vawcount = vainfo.va_wcount;
175*41Sbill 		return;
176*41Sbill 	}
177*41Sbill }
178*41Sbill 
179*41Sbill /*ARGSUSED*/
180*41Sbill vaioctl(dev, cmd, addr, flag)
181*41Sbill 	register caddr_t addr;
182*41Sbill {
183*41Sbill 	register int vcmd;
184*41Sbill 
185*41Sbill 	switch (cmd) {
186*41Sbill 
187*41Sbill 	case VGETSTATE:
188*41Sbill 		VOID suword(addr, vainfo.va_state);
189*41Sbill 		return;
190*41Sbill 
191*41Sbill 	case VSETSTATE:
192*41Sbill 		vcmd = fuword(addr);
193*41Sbill 		if (vcmd == -1) {
194*41Sbill 			u.u_error = EFAULT;
195*41Sbill 			return;
196*41Sbill 		}
197*41Sbill 		vacmd(vcmd);
198*41Sbill 		return;
199*41Sbill 
200*41Sbill 	default:
201*41Sbill 		u.u_error = ENOTTY;	/* Not a legal ioctl cmd. */
202*41Sbill 		return;
203*41Sbill 	}
204*41Sbill }
205*41Sbill 
206*41Sbill /* vacmd sends a command code to the va, and waits for it to complete.
207*41Sbill    If an error occurs, u.u_error is set to EIO.
208*41Sbill    vacmd also updates vainfo.va_state.
209*41Sbill  */
210*41Sbill 
211*41Sbill vacmd(vcmd)
212*41Sbill {
213*41Sbill 	VOID spl4();
214*41Sbill 	VOID vaerror(DONE);	/* Wait for va to be ready. */
215*41Sbill 	switch (vcmd) {
216*41Sbill 
217*41Sbill 	case VPLOT:
218*41Sbill 		/* Must turn on plot AND autostep modes. */
219*41Sbill 		VAADDR->vacsrhi = VAPLOT;
220*41Sbill 		if (vaerror(DONE))
221*41Sbill 			u.u_error = EIO;
222*41Sbill 		VAADDR->vacsrhi = VAAUTOSTEP;
223*41Sbill 		break;
224*41Sbill 
225*41Sbill 	case VPRINT:
226*41Sbill 		VAADDR->vacsrhi = VAPRINT;
227*41Sbill 		break;
228*41Sbill 
229*41Sbill 	case VPRINTPLOT:
230*41Sbill 		VAADDR->vacsrhi = VAPRINTPLOT;
231*41Sbill 		break;
232*41Sbill 	}
233*41Sbill 	vainfo.va_state =
234*41Sbill 		(vainfo.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd;
235*41Sbill 
236*41Sbill 	if (vaerror(DONE))	/* Wait for command to complete. */
237*41Sbill 		u.u_error = EIO;
238*41Sbill 	VOID spl0();
239*41Sbill }
240*41Sbill 
241*41Sbill vatimo()
242*41Sbill {
243*41Sbill 	if (vainfo.va_is_open)
244*41Sbill 		timeout(vatimo, (caddr_t)0, HZ/10);
245*41Sbill 	vaintr(0);
246*41Sbill }
247*41Sbill 
248*41Sbill /*ARGSUSED*/
249*41Sbill vaintr(dev)
250*41Sbill {
251*41Sbill 	wakeup((caddr_t)&vainfo);
252*41Sbill }
253*41Sbill 
254*41Sbill vaclose()
255*41Sbill {
256*41Sbill 
257*41Sbill 	vainfo.va_is_open = 0;
258*41Sbill 	vainfo.va_busy = 0;
259*41Sbill 	vainfo.va_state = 0;
260*41Sbill 	vainfo.va_wcount = 0;
261*41Sbill 	vainfo.va_bufp = 0;
262*41Sbill 	VAADDR->vacsrlo = 0;
263*41Sbill }
264*41Sbill #endif
265