restrict zero write widths
[unix-history] / usr / src / sys / vax / uba / va.c
CommitLineData
cd1b1cd4 1/* va.c 4.8 81/03/09 */
20cc8b5b 2
66b4fb09 3#include "va.h"
a5cc519e
BJ
4#if NVA > 0
5/*
6 * Benson-Varian matrix printer/plotter
7 * dma interface driver
8 */
20cc8b5b
BJ
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
71357272 19int vabdp = 1;
20cc8b5b 20
71357272 21unsigned minvaph();
20cc8b5b
BJ
22
23#define VAPRI (PZERO-1)
24
71357272
BJ
25#define ushort unsigned short
26struct varegs {
27 ushort vaba;
28 short vawc;
20cc8b5b 29 union {
71357272 30 short Vacsw;
20cc8b5b 31 struct {
71357272
BJ
32 char Vacsl;
33 char Vacsh;
34 } vacsr;
35 } vacs;
20cc8b5b
BJ
36 short vadata;
37};
38
71357272
BJ
39#define vacsw vacs.Vacsw
40#define vacsh vacs.vacsr.Vacsh
41#define vacsl vacs.vacsr.Vacsl
42
71357272
BJ
43/* vacsw bits */
44#define ERROR 0100000 /* Some error has occurred */
a5cc519e
BJ
45#define NPRTIMO 01000 /* DMA timeout error */
46#define NOTREADY 0400 /* Something besides NPRTIMO */
47#define DONE 0200
71357272
BJ
48#define IENABLE 0100 /* Interrupt enable */
49#define SUPPLIESLOW 04
a5cc519e
BJ
50#define BOTOFFORM 02
51#define BYTEREVERSE 01 /* Reverse byte order in words */
71357272
BJ
52
53/* vacsh command bytes */
a5cc519e
BJ
54#define VAPLOT 0340
55#define VAPRINT 0100
56#define VAPRINTPLOT 0160
57#define VAAUTOSTEP 0244
58#define VANOAUTOSTEP 0045 /* unused */
71357272
BJ
59#define VAFORMFEED 0263 /* unused */
60#define VASLEW 0265 /* unused */
61#define VASTEP 0064 /* unused */
20cc8b5b
BJ
62
63struct {
71357272 64 char va_open;
20cc8b5b
BJ
65 char va_busy;
66 int va_state; /* State: bits are commands in vcmd.h. */
71357272 67 int va_wc;
20cc8b5b 68 int va_bufp;
71357272
BJ
69 struct buf *va_bp;
70} va11;
20cc8b5b
BJ
71int va_ubinfo;
72
73struct buf rvabuf; /* Used by physio for a buffer. */
74
75vaopen()
76{
77
71357272 78 if (va11.va_open) {
20cc8b5b
BJ
79 u.u_error = ENXIO;
80 return;
81 }
71357272
BJ
82 va11.va_open = 1;
83 VAADDR->vawc = 0;
84 va11.va_wc = 0;
85 va11.va_state = 0;
86 VAADDR->vacsl = IENABLE;
20cc8b5b 87 vatimo();
71357272 88 vacmd(VPRINT);
20cc8b5b
BJ
89 if (u.u_error)
90 vaclose();
91}
92
93vastrategy(bp)
94 register struct buf *bp;
95{
96 register int e;
97
81263dba 98 (void) spl4();
71357272
BJ
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;
20cc8b5b
BJ
105 if (e = vaerror(DONE))
106 goto brkout;
71357272 107 va11.va_wc = -(bp->b_bcount/2);
20cc8b5b 108 vastart();
71357272
BJ
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.
20cc8b5b 119 */
71357272
BJ
120 if (va11.va_state & VPRINTPLOT) {
121 va11.va_state = (va11.va_state & ~VPRINTPLOT) | VPLOT;
122 VAADDR->vacsh = VAAUTOSTEP;
20cc8b5b
BJ
123 e |= vaerror(DONE);
124 }
81263dba 125 (void) spl0();
20cc8b5b 126brkout:
b28deaf8 127 ubarelse(&va_ubinfo);
71357272
BJ
128 va11.va_bp = 0;
129 va11.va_busy = 0;
20cc8b5b
BJ
130 iodone(bp);
131 if (e)
132 u.u_error = EIO;
71357272 133 wakeup((caddr_t)&va11);
20cc8b5b
BJ
134}
135
136int vablock = 16384;
137
138unsigned
139minvaph(bp)
140struct buf *bp;
141{
142 if (bp->b_bcount > vablock)
143 bp->b_bcount = vablock;
144}
145
146/*ARGSUSED*/
147vawrite(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 */
156vaerror(bit)
157{
158 register int e;
159
71357272
BJ
160 while ((e = VAADDR->vacsw & (bit|ERROR)) == 0)
161 sleep((caddr_t)&va11, VAPRI);
20cc8b5b
BJ
162 return (e & ERROR);
163}
164
20cc8b5b
BJ
165vastart()
166{
71357272
BJ
167 if (va11.va_wc) {
168 VAADDR->vaba = va11.va_bufp;
3bfdaa99 169 VAADDR->vacsl = (va11.va_bufp >> 12) & 0x30;
71357272 170 VAADDR->vawc = va11.va_wc;
20cc8b5b
BJ
171 return;
172 }
173}
174
175/*ARGSUSED*/
176vaioctl(dev, cmd, addr, flag)
177 register caddr_t addr;
178{
179 register int vcmd;
180
181 switch (cmd) {
182
183 case VGETSTATE:
71357272 184 (void) suword(addr, va11.va_state);
20cc8b5b
BJ
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
71357272
BJ
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.
20cc8b5b 206 */
20cc8b5b
BJ
207vacmd(vcmd)
208{
81263dba 209 (void) spl4();
71357272 210 (void) vaerror(DONE); /* Wait for va to be ready */
20cc8b5b
BJ
211 switch (vcmd) {
212
213 case VPLOT:
214 /* Must turn on plot AND autostep modes. */
71357272 215 VAADDR->vacsh = VAPLOT;
20cc8b5b
BJ
216 if (vaerror(DONE))
217 u.u_error = EIO;
71357272 218 VAADDR->vacsh = VAAUTOSTEP;
20cc8b5b
BJ
219 break;
220
221 case VPRINT:
71357272 222 VAADDR->vacsh = VAPRINT;
20cc8b5b
BJ
223 break;
224
225 case VPRINTPLOT:
71357272 226 VAADDR->vacsh = VAPRINTPLOT;
20cc8b5b
BJ
227 break;
228 }
71357272
BJ
229 va11.va_state =
230 (va11.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd;
20cc8b5b
BJ
231
232 if (vaerror(DONE)) /* Wait for command to complete. */
233 u.u_error = EIO;
81263dba 234 (void) spl0();
20cc8b5b
BJ
235}
236
237vatimo()
238{
71357272 239 if (va11.va_open)
7780575a 240 timeout(vatimo, (caddr_t)0, hz/10);
20cc8b5b
BJ
241 vaintr(0);
242}
243
244/*ARGSUSED*/
245vaintr(dev)
246{
71357272 247 wakeup((caddr_t)&va11);
20cc8b5b
BJ
248}
249
250vaclose()
251{
252
71357272
BJ
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
71357272
BJ
261vareset()
262{
263
264 if (va11.va_open == 0)
265 return;
266 printf(" va");
267 VAADDR->vacsl = IENABLE;
268 if (va11.va_state & VPLOT) {
269 VAADDR->vacsh = VAPLOT;
270 DELAY(10000);
271 VAADDR->vacsh = VAAUTOSTEP;
272 } else if (va11.va_state & VPRINTPLOT)
273 VAADDR->vacsh = VPRINTPLOT;
274 else
275 VAADDR->vacsh = VAPRINTPLOT;
276 DELAY(10000);
277 if (va11.va_busy == 0)
278 return;
279 if (va_ubinfo) {
280 printf("<%d>", (va_ubinfo>>28)&0xf);
b28deaf8 281 ubarelse(&va_ubinfo);
71357272
BJ
282 }
283 /* This code belongs in vastart() */
284 va_ubinfo = ubasetup(va11.va_bp, vabdp);
285 va11.va_bufp = va_ubinfo & 0x3ffff;
286 va11.va_wc = (-va11.va_bp->b_bcount/2);
287 /* End badly placed code */
288 vastart();
20cc8b5b 289}
a5cc519e 290#endif