xref: /csrg-svn/sys/vax/uba/va.c (revision 2054)
1 /*	va.c	4.5	12/30/80	*/
2 
3 #include "va.h"
4 #if NVA > 0
5 /*
6  * Benson-Varian matrix printer/plotter
7  * dma interface driver
8  */
9 #include "../h/param.h"
10 #include "../h/dir.h"
11 #include "../h/user.h"
12 #include "../h/buf.h"
13 #include "../h/systm.h"
14 #include "../h/map.h"
15 #include "../h/pte.h"
16 #include "../h/uba.h"
17 #include "../h/vcmd.h"
18 
19 int	vabdp = 1;
20 
21 unsigned minvaph();
22 
23 #define	VAPRI	(PZERO-1)
24 
25 #define	ushort	unsigned short
26 struct	varegs {
27 	ushort	vaba;
28 	short	vawc;
29 	union {
30 		short	Vacsw;
31 		struct {
32 			char Vacsl;
33 			char Vacsh;
34 		} vacsr;
35 	} vacs;
36 	short	vadata;
37 };
38 
39 #define	vacsw	vacs.Vacsw
40 #define	vacsh	vacs.vacsr.Vacsh
41 #define	vacsl	vacs.vacsr.Vacsl
42 
43 /* vacsw bits */
44 #define	ERROR		0100000		/* Some error has occurred */
45 #define	NPRTIMO		01000		/* DMA timeout error */
46 #define	NOTREADY	0400		/* Something besides NPRTIMO */
47 #define	DONE		0200
48 #define	IENABLE		0100		/* Interrupt enable */
49 #define	SUPPLIESLOW	04
50 #define	BOTOFFORM	02
51 #define	BYTEREVERSE	01		/* Reverse byte order in words */
52 
53 /* vacsh command bytes */
54 #define	VAPLOT		0340
55 #define	VAPRINT		0100
56 #define	VAPRINTPLOT	0160
57 #define	VAAUTOSTEP	0244
58 #define	VANOAUTOSTEP	0045		/* unused */
59 #define	VAFORMFEED	0263		/* unused */
60 #define	VASLEW		0265		/* unused */
61 #define	VASTEP		0064		/* unused */
62 
63 struct {
64 	char	va_open;
65 	char	va_busy;
66 	int	va_state;	/* State: bits are commands in vcmd.h. */
67 	int	va_wc;
68 	int	va_bufp;
69 	struct	buf *va_bp;
70 } va11;
71 int	va_ubinfo;
72 
73 struct	buf rvabuf;		/* Used by physio for a buffer. */
74 
75 vaopen()
76 {
77 
78 	if (va11.va_open) {
79 		u.u_error = ENXIO;
80 		return;
81 	}
82 	va11.va_open = 1;
83 	VAADDR->vawc = 0;
84 	va11.va_wc = 0;
85 	va11.va_state = 0;
86 	VAADDR->vacsl = IENABLE;
87 	vatimo();
88 	vacmd(VPRINT);
89 	if (u.u_error)
90 		vaclose();
91 }
92 
93 vastrategy(bp)
94 	register struct buf *bp;
95 {
96 	register int e;
97 
98 	(void) spl4();
99 	while (va11.va_busy)
100 		sleep((caddr_t)&va11, VAPRI);
101 	va11.va_busy = 1;
102 	va11.va_bp = bp;
103 	va_ubinfo = ubasetup(bp, vabdp);
104 	va11.va_bufp = va_ubinfo & 0x3ffff;
105 	if (e = vaerror(DONE))
106 		goto brkout;
107 	va11.va_wc = -(bp->b_bcount/2);
108 	vastart();
109 	e = vaerror(DONE);	/* Wait for DMA to complete */
110 	va11.va_wc = 0;
111 	va11.va_bufp = 0;
112 
113 	/*
114 	 * After printing a line of characters, VPRINTPLOT mode essentially
115 	 * reverts to VPLOT mode, plotting things until a new mode is set.
116 	 * This change is indicated by sending a VAAUTOSTEP command to
117 	 * the va.  We also change va_state to reflect this effective
118 	 * mode change.
119 	 */
120 	if (va11.va_state & VPRINTPLOT) {
121 		va11.va_state = (va11.va_state & ~VPRINTPLOT) | VPLOT;
122 		VAADDR->vacsh = VAAUTOSTEP;
123 		e |= vaerror(DONE);
124 	}
125 	(void) spl0();
126 brkout:
127 	ubarelse(&va_ubinfo);
128 	va11.va_bp = 0;
129 	va11.va_busy = 0;
130 	iodone(bp);
131 	if (e)
132 		u.u_error = EIO;
133 	wakeup((caddr_t)&va11);
134 }
135 
136 int	vablock = 16384;
137 
138 unsigned
139 minvaph(bp)
140 struct buf *bp;
141 {
142 	if (bp->b_bcount > vablock)
143 		bp->b_bcount = vablock;
144 }
145 
146 /*ARGSUSED*/
147 vawrite(dev)
148 {
149 	physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph);
150 }
151 
152 /*
153  * Vaerror waits until bit or ERROR gets set, then returns non-zero if
154  * if it was ERROR that was set.
155  */
156 vaerror(bit)
157 {
158 	register int e;
159 
160 	while ((e = VAADDR->vacsw & (bit|ERROR)) == 0)
161 		sleep((caddr_t)&va11, VAPRI);
162 	return (e & ERROR);
163 }
164 
165 vastart()
166 {
167 	if (va11.va_wc) {
168 		VAADDR->vaba = va11.va_bufp;
169 		VAADDR->vacsl = (va11.va_bufp >> 12) & 0x30;
170 		VAADDR->vawc = va11.va_wc;
171 		return;
172 	}
173 }
174 
175 /*ARGSUSED*/
176 vaioctl(dev, cmd, addr, flag)
177 	register caddr_t addr;
178 {
179 	register int vcmd;
180 
181 	switch (cmd) {
182 
183 	case VGETSTATE:
184 		(void) suword(addr, va11.va_state);
185 		return;
186 
187 	case VSETSTATE:
188 		vcmd = fuword(addr);
189 		if (vcmd == -1) {
190 			u.u_error = EFAULT;
191 			return;
192 		}
193 		vacmd(vcmd);
194 		return;
195 
196 	default:
197 		u.u_error = ENOTTY;	/* Not a legal ioctl cmd. */
198 		return;
199 	}
200 }
201 
202 /*
203  * Send a command code to the va, and wait for it to complete.
204  * If an error occurs, u.u_error is set to EIO.
205  * In any case, update va11.va_state.
206  */
207 vacmd(vcmd)
208 {
209 	(void) spl4();
210 	(void) vaerror(DONE);		/* Wait for va to be ready */
211 	switch (vcmd) {
212 
213 	case VPLOT:
214 		/* Must turn on plot AND autostep modes. */
215 		VAADDR->vacsh = VAPLOT;
216 		if (vaerror(DONE))
217 			u.u_error = EIO;
218 		VAADDR->vacsh = VAAUTOSTEP;
219 		break;
220 
221 	case VPRINT:
222 		VAADDR->vacsh = VAPRINT;
223 		break;
224 
225 	case VPRINTPLOT:
226 		VAADDR->vacsh = VAPRINTPLOT;
227 		break;
228 	}
229 	va11.va_state =
230 		(va11.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd;
231 
232 	if (vaerror(DONE))	/* Wait for command to complete. */
233 		u.u_error = EIO;
234 	(void) spl0();
235 }
236 
237 vatimo()
238 {
239 	if (va11.va_open)
240 		timeout(vatimo, (caddr_t)0, HZ/10);
241 	vaintr(0);
242 }
243 
244 /*ARGSUSED*/
245 vaintr(dev)
246 {
247 	wakeup((caddr_t)&va11);
248 }
249 
250 vaclose()
251 {
252 
253 	va11.va_open = 0;
254 	va11.va_busy = 0;
255 	va11.va_state = 0;
256 	va11.va_wc = 0;
257 	va11.va_bufp = 0;
258 	VAADDR->vacsl = 0;
259 }
260 
261 #define	DELAY(N)	{ register int d; d = N; while (--d > 0); }
262 
263 vareset()
264 {
265 
266 	if (va11.va_open == 0)
267 		return;
268 	printf(" va");
269 	VAADDR->vacsl = IENABLE;
270 	if (va11.va_state & VPLOT) {
271 		VAADDR->vacsh = VAPLOT;
272 		DELAY(10000);
273 		VAADDR->vacsh = VAAUTOSTEP;
274 	} else if (va11.va_state & VPRINTPLOT)
275 		VAADDR->vacsh = VPRINTPLOT;
276 	else
277 		VAADDR->vacsh = VAPRINTPLOT;
278 	DELAY(10000);
279 	if (va11.va_busy == 0)
280 		return;
281 	if (va_ubinfo) {
282 		printf("<%d>", (va_ubinfo>>28)&0xf);
283 		ubarelse(&va_ubinfo);
284 	}
285 	/* This code belongs in vastart() */
286 	va_ubinfo = ubasetup(va11.va_bp, vabdp);
287 	va11.va_bufp = va_ubinfo & 0x3ffff;
288 	va11.va_wc = (-va11.va_bp->b_bcount/2);
289 	/* End badly placed code */
290 	vastart();
291 }
292 #endif
293