xref: /original-bsd/sys/vax/uba/va.c (revision 62734ea8)
1 /*	va.c	4.13	82/05/19	*/
2 
3 #include "va.h"
4 #if NVA > 0
5 /*
6  * Varian printer plotter
7  */
8 #include "../h/param.h"
9 #include "../h/dir.h"
10 #include "../h/user.h"
11 #include "../h/buf.h"
12 #include "../h/systm.h"
13 #include "../h/map.h"
14 #include "../h/pte.h"
15 #include "../h/ubareg.h"
16 #include "../h/ubavar.h"
17 #include "../h/vcmd.h"
18 
19 unsigned minvaph();
20 
21 #define	VAPRI	(PZERO-1)
22 
23 struct	vadevice {
24 	u_short	vaba;			/* buffer address */
25 	short	vawc;			/* word count (2's complement) */
26 	union {
27 		short	Vacsw;		/* control status as word */
28 		struct {		/* control status as bytes */
29 			char Vacsl;
30 			char Vacsh;
31 		} vacsr;
32 	} vacs;
33 	short	vadata;			/* programmed i/o data buffer */
34 };
35 
36 #define	vacsw	vacs.Vacsw
37 #define	vacsh	vacs.vacsr.Vacsh
38 #define	vacsl	vacs.vacsr.Vacsl
39 
40 /* vacsw bits */
41 #define	VA_ERROR	0100000		/* some error has occurred */
42 #define	VA_NPRTIMO	0001000		/* DMA timeout error */
43 #define	VA_NOTREADY	0000400		/* something besides NPRTIMO */
44 #define	VA_DONE		0000200
45 #define	VA_IENABLE	0000100		/* interrupt enable */
46 #define	VA_SUPPLIESLOW	0000004
47 #define	VA_BOTOFFORM	0000002
48 #define	VA_BYTEREVERSE	0000001		/* reverse byte order in words */
49 
50 /* vacsh command bytes */
51 #define	VAPLOT		0000340
52 #define	VAPRINT		0000100
53 #define	VAPRINTPLOT	0000160
54 #define	VAAUTOSTEP	0000244
55 #define	VANOAUTOSTEP	0000045
56 #define	VAFORMFEED	0000263
57 #define	VASLEW		0000265
58 #define	VASTEP		0000064
59 
60 struct va_softc {
61 	char	sc_openf;
62 	char	sc_busy;
63 	int	sc_state;
64 	int	sc_wc;
65 	struct	buf *sc_bp;
66 	int	sc_ubinfo;
67 } va_softc[NVA];
68 
69 #define	VAUNIT(dev)	(minor(dev))
70 
71 struct	buf rvabuf[NVA];
72 
73 int	vaprobe(), vaattach();
74 struct	uba_device *vadinfo[NVA];
75 u_short	vastd[] = { 0764000, 0 };
76 struct	uba_driver vadriver =
77     { vaprobe, 0, vaattach, 0, vastd, "va", vadinfo };
78 
79 vaprobe(reg)
80 	caddr_t reg;
81 {
82 	register int br, cvec;		/* value-result */
83 	register struct vadevice *vaaddr = (struct vadevice *)reg;
84 
85 #ifdef lint
86 	br = 0; cvec = br; br = cvec;
87 	vaintr(0);
88 #endif
89 	vaaddr->vacsl = VA_IENABLE;
90 	vaaddr->vaba = 0;
91 	vaaddr->vacsh = VAPLOT;
92 	vaaddr->vacsl = 0;
93 	vaaddr->vawc = -1;
94 	DELAY(100000);
95 	vaaddr->vacsl = 0;
96 }
97 
98 /*ARGSUSED*/
99 vaattach(ui)
100 	struct uba_device *ui;
101 {
102 
103 }
104 
105 vaopen(dev)
106 	dev_t dev;
107 {
108 	register struct va_softc *sc;
109 	register struct vadevice *vaaddr;
110 	register struct uba_device *ui;
111 
112 	if (VAUNIT(dev) >= NVA || (sc = &va_softc[minor(dev)])->sc_openf ||
113 	    (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0) {
114 		u.u_error = ENXIO;
115 		return;
116 	}
117 	vaaddr = (struct vadevice *)ui->ui_addr;
118 	sc->sc_openf = 1;
119 	vaaddr->vawc = 0;
120 	sc->sc_wc = 0;
121 	sc->sc_state = 0;
122 	vaaddr->vacsl = VA_IENABLE;
123 	vatimo(dev);
124 	vacmd(dev, VPRINT);
125 	if (u.u_error)
126 		vaclose(dev);
127 }
128 
129 vastrategy(bp)
130 	register struct buf *bp;
131 {
132 	register int e;
133 	register struct va_softc *sc = &va_softc[VAUNIT(bp->b_dev)];
134 	register struct uba_device *ui = vadinfo[VAUNIT(bp->b_dev)];
135 	register struct vadevice *vaaddr = (struct vadevice *)ui->ui_addr;
136 
137 	(void) spl4();
138 	while (sc->sc_busy)
139 		sleep((caddr_t)sc, VAPRI);
140 	sc->sc_busy = 1;
141 	sc->sc_bp = bp;
142 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
143 	if (e = vawait(bp->b_dev))
144 		goto brkout;
145 	sc->sc_wc = -(bp->b_bcount/2);
146 	vastart(bp->b_dev);
147 	e = vawait(bp->b_dev);
148 	sc->sc_wc = 0;
149 	if (sc->sc_state & VPRINTPLOT) {
150 		sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
151 		vaaddr->vacsh = VAAUTOSTEP;
152 		e |= vawait(bp->b_dev);
153 	}
154 	(void) spl0();
155 brkout:
156 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
157 	sc->sc_bp = 0;
158 	sc->sc_busy = 0;
159 	iodone(bp);
160 	if (e)
161 		u.u_error = EIO;
162 	wakeup((caddr_t)sc);
163 }
164 
165 int	vablock = 16384;
166 
167 unsigned
168 minvaph(bp)
169 	struct buf *bp;
170 {
171 
172 	if (bp->b_bcount > vablock)
173 		bp->b_bcount = vablock;
174 }
175 
176 /*ARGSUSED*/
177 vawrite(dev)
178 	dev_t dev;
179 {
180 
181 	physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, minvaph);
182 }
183 
184 vawait(dev)
185 	dev_t dev;
186 {
187 	register struct vadevice *vaaddr =
188 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
189 	register int e;
190 
191 	while (((e = vaaddr->vacsw) & (VA_DONE|VA_ERROR)) == 0)
192 		sleep((caddr_t)&va_softc[VAUNIT(dev)], VAPRI);
193 	if (e & VA_NPRTIMO)
194 		printf("va%d: npr timeout\n", VAUNIT(dev));
195 	return (e & VA_ERROR);
196 }
197 
198 vastart(dev)
199 	dev_t;
200 {
201 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
202 	register struct vadevice *vaaddr =
203 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
204 
205 	if (sc->sc_wc == 0)
206 		return;
207 	vaaddr->vaba = sc->sc_ubinfo;
208 	vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30;
209 	vaaddr->vawc = sc->sc_wc;
210 }
211 
212 /*ARGSUSED*/
213 vaioctl(dev, cmd, addr, flag)
214 	register caddr_t addr;
215 {
216 	register int vcmd;
217 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
218 
219 	switch (cmd) {
220 
221 	case VGETSTATE:
222 		(void) suword(addr, sc->sc_state);
223 		return;
224 
225 	case VSETSTATE:
226 		vcmd = fuword(addr);
227 		if (vcmd == -1) {
228 			u.u_error = EFAULT;
229 			return;
230 		}
231 		vacmd(dev, vcmd);
232 		return;
233 
234 	default:
235 		u.u_error = ENOTTY;
236 		return;
237 	}
238 }
239 
240 vacmd(dev, vcmd)
241 	dev_t dev;
242 	int vcmd;
243 {
244 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
245 	register struct vadevice *vaaddr =
246 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
247 
248 	(void) spl4();
249 	(void) vawait(dev);
250 	switch (vcmd) {
251 
252 	case VPLOT:
253 		/* Must turn on plot AND autostep modes. */
254 		vaaddr->vacsh = VAPLOT;
255 		if (vawait(dev))
256 			u.u_error = EIO;
257 		vaaddr->vacsh = VAAUTOSTEP;
258 		break;
259 
260 	case VPRINT:
261 		vaaddr->vacsh = VAPRINT;
262 		break;
263 
264 	case VPRINTPLOT:
265 		vaaddr->vacsh = VAPRINTPLOT;
266 		break;
267 	}
268 	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
269 	if (vawait(dev))
270 		u.u_error = EIO;
271 	(void) spl0();
272 }
273 
274 vatimo(dev)
275 	dev_t dev;
276 {
277 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
278 
279 	if (sc->sc_openf)
280 		timeout(vatimo, (caddr_t)dev, hz/10);
281 	vaintr(dev);
282 }
283 
284 /*ARGSUSED*/
285 vaintr(dev)
286 	dev_t dev;
287 {
288 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
289 
290 	wakeup((caddr_t)sc);
291 }
292 
293 vaclose(dev)
294 	dev_t dev;
295 {
296 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
297 	register struct vadevice *vaaddr =
298 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
299 
300 	sc->sc_openf = 0;
301 	sc->sc_busy = 0;
302 	sc->sc_state = 0;
303 	sc->sc_ubinfo = 0;
304 	vaaddr->vacsl = 0;
305 }
306 
307 vareset(uban)
308 	int uban;
309 {
310 	register int va11;
311 	register struct uba_device *ui;
312 	register struct va_softc *sc = va_softc;
313 	register struct vadevice *vaaddr;
314 
315 	for (va11 = 0; va11 < NVA; va11++, sc++) {
316 		if ((ui = vadinfo[va11]) == 0 || ui->ui_alive == 0 ||
317 		    ui->ui_ubanum != uban || sc->sc_openf == 0)
318 			continue;
319 		printf(" va%d", va11);
320 		vaaddr = (struct vadevice *)ui->ui_addr;
321 		vaaddr->vacsl = VA_IENABLE;
322 		if (sc->sc_state & VPLOT) {
323 			vaaddr->vacsh = VAPLOT;
324 			DELAY(10000);
325 			vaaddr->vacsh = VAAUTOSTEP;
326 		} else if (sc->sc_state & VPRINTPLOT)
327 			vaaddr->vacsh = VPRINTPLOT;
328 		else
329 			vaaddr->vacsh = VAPRINTPLOT;
330 		DELAY(10000);
331 		if (sc->sc_busy == 0)
332 			continue;
333 		if (sc->sc_ubinfo) {
334 			printf("<%d>", (sc->sc_ubinfo>>28)&0xf);
335 			ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
336 		}
337 		sc->sc_ubinfo = ubasetup(ui->ui_ubanum, sc->sc_bp, UBA_NEEDBDP);
338 		sc->sc_wc = -(sc->sc_bp->b_bcount/2);
339 		vastart(sc->sc_bp->b_dev);
340 	}
341 }
342 
343 vaselect()
344 {
345 	return (1);
346 }
347 #endif
348