xref: /original-bsd/sys/vax/uba/va.c (revision d25e1985)
1 /*	va.c	3.6	06/22/80	*/
2 
3 #include "../h/param.h"
4 #include "../h/dir.h"
5 #include "../h/user.h"
6 #include "../h/buf.h"
7 #include "../h/systm.h"
8 #include "../h/map.h"
9 #include "../h/pte.h"
10 #include "../h/uba.h"
11 #include "../h/vcmd.h"
12 
13 /*
14  * Benson-Varian matrix printer/plotter
15  * dma interface driver
16  */
17 int	vabdp = 1;
18 
19 unsigned minvaph();
20 
21 #define	VAPRI	(PZERO-1)
22 
23 #define	ushort	unsigned short
24 struct	varegs {
25 	ushort	vaba;
26 	short	vawc;
27 	union {
28 		short	Vacsw;
29 		struct {
30 			char Vacsl;
31 			char Vacsh;
32 		} vacsr;
33 	} vacs;
34 	short	vadata;
35 };
36 
37 #define	vacsw	vacs.Vacsw
38 #define	vacsh	vacs.vacsr.Vacsh
39 #define	vacsl	vacs.vacsr.Vacsl
40 
41 #define	VAADDR	((struct varegs *)(UBA0_DEV + 0164000))
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 	ubafree(va_ubinfo), va_ubinfo = 0;
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->vawc = va11.va_wc;
170 		return;
171 	}
172 }
173 
174 /*ARGSUSED*/
175 vaioctl(dev, cmd, addr, flag)
176 	register caddr_t addr;
177 {
178 	register int vcmd;
179 
180 	switch (cmd) {
181 
182 	case VGETSTATE:
183 		(void) suword(addr, va11.va_state);
184 		return;
185 
186 	case VSETSTATE:
187 		vcmd = fuword(addr);
188 		if (vcmd == -1) {
189 			u.u_error = EFAULT;
190 			return;
191 		}
192 		vacmd(vcmd);
193 		return;
194 
195 	default:
196 		u.u_error = ENOTTY;	/* Not a legal ioctl cmd. */
197 		return;
198 	}
199 }
200 
201 /*
202  * Send a command code to the va, and wait for it to complete.
203  * If an error occurs, u.u_error is set to EIO.
204  * In any case, update va11.va_state.
205  */
206 vacmd(vcmd)
207 {
208 	(void) spl4();
209 	(void) vaerror(DONE);		/* Wait for va to be ready */
210 	switch (vcmd) {
211 
212 	case VPLOT:
213 		/* Must turn on plot AND autostep modes. */
214 		VAADDR->vacsh = VAPLOT;
215 		if (vaerror(DONE))
216 			u.u_error = EIO;
217 		VAADDR->vacsh = VAAUTOSTEP;
218 		break;
219 
220 	case VPRINT:
221 		VAADDR->vacsh = VAPRINT;
222 		break;
223 
224 	case VPRINTPLOT:
225 		VAADDR->vacsh = VAPRINTPLOT;
226 		break;
227 	}
228 	va11.va_state =
229 		(va11.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd;
230 
231 	if (vaerror(DONE))	/* Wait for command to complete. */
232 		u.u_error = EIO;
233 	(void) spl0();
234 }
235 
236 vatimo()
237 {
238 	if (va11.va_open)
239 		timeout(vatimo, (caddr_t)0, HZ/10);
240 	vaintr(0);
241 }
242 
243 /*ARGSUSED*/
244 vaintr(dev)
245 {
246 	wakeup((caddr_t)&va11);
247 }
248 
249 vaclose()
250 {
251 
252 	va11.va_open = 0;
253 	va11.va_busy = 0;
254 	va11.va_state = 0;
255 	va11.va_wc = 0;
256 	va11.va_bufp = 0;
257 	VAADDR->vacsl = 0;
258 }
259 
260 #define	DELAY(N)	{ register int d; d = N; while (--d > 0); }
261 
262 vareset()
263 {
264 
265 	if (va11.va_open == 0)
266 		return;
267 	printf(" va");
268 	VAADDR->vacsl = IENABLE;
269 	if (va11.va_state & VPLOT) {
270 		VAADDR->vacsh = VAPLOT;
271 		DELAY(10000);
272 		VAADDR->vacsh = VAAUTOSTEP;
273 	} else if (va11.va_state & VPRINTPLOT)
274 		VAADDR->vacsh = VPRINTPLOT;
275 	else
276 		VAADDR->vacsh = VAPRINTPLOT;
277 	DELAY(10000);
278 	if (va11.va_busy == 0)
279 		return;
280 	if (va_ubinfo) {
281 		printf("<%d>", (va_ubinfo>>28)&0xf);
282 		ubafree(va_ubinfo), va_ubinfo = 0;
283 	}
284 	/* This code belongs in vastart() */
285 	va_ubinfo = ubasetup(va11.va_bp, vabdp);
286 	va11.va_bufp = va_ubinfo & 0x3ffff;
287 	va11.va_wc = (-va11.va_bp->b_bcount/2);
288 	/* End badly placed code */
289 	vastart();
290 }
291