xref: /original-bsd/sys/vax/uba/va.c (revision 6c57d260)
1 /*	va.c	4.9	81/03/10	*/
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 struct	uba_device *vadinfo[NVA];
70 
71 #define	VAUNIT(dev)	(minor(dev))
72 
73 struct	buf rvabuf[NVA];
74 
75 int	vaprobe(), vaattach();
76 struct	uba_device *vadinfo[NVA];
77 u_short	vastd[] = { 0764000, 0 };
78 struct	uba_driver vadriver =
79     { vaprobe, 0, vaattach, 0, vastd, "va", vadinfo };
80 
81 vaprobe(reg)
82 	caddr_t reg;
83 {
84 	register int br, cvec;		/* value-result */
85 	register struct vadevice *vaaddr = (struct vadevice *)reg;
86 
87 	vaaddr->vacsl = VA_IENABLE;
88 	vaaddr->vaba = 0;
89 	vaaddr->vacsh = VAPLOT;
90 	vaaddr->vacsl = 0;
91 	vaaddr->vawc = -1;
92 	DELAY(10000);
93 	vaaddr->vacsl = 0;
94 }
95 
96 /*ARGSUSED*/
97 vaattach(ui)
98 	struct uba_device *ui;
99 {
100 
101 }
102 
103 vaopen(dev)
104 	dev_t dev;
105 {
106 	register struct va_softc *sc;
107 	register struct vadevice *vaaddr;
108 	register struct uba_device *ui;
109 
110 	if (VAUNIT(dev) >= NVA || (sc = &va_softc[minor(dev)])->sc_openf ||
111 	    (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0) {
112 		u.u_error = ENXIO;
113 		return;
114 	}
115 	vaaddr = (struct vadevice *)ui->ui_addr;
116 	sc->sc_openf = 1;
117 	vaaddr->vawc = 0;
118 	sc->sc_wc = 0;
119 	sc->sc_state = 0;
120 	vaaddr->vacsl = VA_IENABLE;
121 	vatimo(dev);
122 	vacmd(dev, VPRINT);
123 	if (u.u_error)
124 		vaclose(dev);
125 }
126 
127 vastrategy(bp)
128 	register struct buf *bp;
129 {
130 	register int e;
131 	register struct va_softc *sc = &va_softc[VAUNIT(bp->b_dev)];
132 	register struct uba_device *ui = vadinfo[VAUNIT(bp->b_dev)];
133 	register struct vadevice *vaaddr = (struct vadevice *)ui->ui_addr;
134 
135 	(void) spl4();
136 	while (sc->sc_busy)
137 		sleep((caddr_t)sc, VAPRI);
138 	sc->sc_busy = 1;
139 	sc->sc_bp = bp;
140 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
141 	if (e = vawait(bp->b_dev))
142 		goto brkout;
143 	sc->sc_wc = -(bp->b_bcount/2);
144 	vastart(bp->b_dev);
145 	e = vawait(bp->b_dev);
146 	sc->sc_wc = 0;
147 	if (sc->sc_state & VPRINTPLOT) {
148 		sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
149 		vaaddr->vacsh = VAAUTOSTEP;
150 		e |= vawait(bp->b_dev);
151 	}
152 	(void) spl0();
153 brkout:
154 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
155 	sc->sc_bp = 0;
156 	sc->sc_busy = 0;
157 	iodone(bp);
158 	if (e)
159 		u.u_error = EIO;
160 	wakeup((caddr_t)sc);
161 }
162 
163 int	vablock = 16384;
164 
165 unsigned
166 minvaph(bp)
167 	struct buf *bp;
168 {
169 
170 	if (bp->b_bcount > vablock)
171 		bp->b_bcount = vablock;
172 }
173 
174 /*ARGSUSED*/
175 vawrite(dev)
176 	dev_t dev;
177 {
178 
179 	physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, minvaph);
180 }
181 
182 vawait(dev)
183 	dev_t dev;
184 {
185 	register struct vadevice *vaaddr =
186 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
187 	register int e;
188 
189 	while (((e = vaaddr->vacsw) & (VA_DONE|VA_ERROR)) == 0)
190 		sleep((caddr_t)&va_softc[VAUNIT(dev)], VAPRI);
191 	if (e & VA_NPRTIMO)
192 		printf("va%d: npr timeout\n", VAUNIT(dev));
193 	return (e & VA_ERROR);
194 }
195 
196 vastart(dev)
197 	dev_t;
198 {
199 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
200 	register struct vadevice *vaaddr =
201 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
202 
203 	if (sc->sc_wc == 0)
204 		return;
205 	vaaddr->vaba = sc->sc_ubinfo;
206 	vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30;
207 	vaaddr->vawc = sc->sc_wc;
208 }
209 
210 /*ARGSUSED*/
211 vaioctl(dev, cmd, addr, flag)
212 	register caddr_t addr;
213 {
214 	register int vcmd;
215 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
216 
217 	switch (cmd) {
218 
219 	case VGETSTATE:
220 		(void) suword(addr, sc->sc_state);
221 		return;
222 
223 	case VSETSTATE:
224 		vcmd = fuword(addr);
225 		if (vcmd == -1) {
226 			u.u_error = EFAULT;
227 			return;
228 		}
229 		vacmd(dev, vcmd);
230 		return;
231 
232 	default:
233 		u.u_error = ENOTTY;
234 		return;
235 	}
236 }
237 
238 vacmd(dev, vcmd)
239 	dev_t dev;
240 	int vcmd;
241 {
242 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
243 	register struct vadevice *vaaddr =
244 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
245 
246 	(void) spl4();
247 	(void) vawait(dev);
248 	switch (vcmd) {
249 
250 	case VPLOT:
251 		/* Must turn on plot AND autostep modes. */
252 		vaaddr->vacsh = VAPLOT;
253 		if (vawait(dev))
254 			u.u_error = EIO;
255 		vaaddr->vacsh = VAAUTOSTEP;
256 		break;
257 
258 	case VPRINT:
259 		vaaddr->vacsh = VAPRINT;
260 		break;
261 
262 	case VPRINTPLOT:
263 		vaaddr->vacsh = VAPRINTPLOT;
264 		break;
265 	}
266 	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
267 	if (vawait(dev))
268 		u.u_error = EIO;
269 	(void) spl0();
270 }
271 
272 vatimo(dev)
273 	dev_t dev;
274 {
275 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
276 
277 	if (sc->sc_openf)
278 		timeout(vatimo, (caddr_t)dev, hz/10);
279 	vaintr(dev);
280 }
281 
282 /*ARGSUSED*/
283 vaintr(dev)
284 	dev_t dev;
285 {
286 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
287 
288 	wakeup((caddr_t)sc);
289 }
290 
291 vaclose(dev)
292 	dev_t dev;
293 {
294 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
295 	register struct vadevice *vaaddr =
296 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
297 
298 	sc->sc_openf = 0;
299 	sc->sc_busy = 0;
300 	sc->sc_state = 0;
301 	sc->sc_ubinfo = 0;
302 	vaaddr->vacsl = 0;
303 }
304 
305 vareset(uban)
306 	int uban;
307 {
308 	register int va11;
309 	register struct uba_device *ui;
310 	register struct va_softc *sc = va_softc;
311 	register struct vadevice *vaaddr;
312 
313 	for (va11 = 0; va11 < NVA; va11++, sc++) {
314 		if ((ui = vadinfo[va11]) == 0 || ui->ui_alive == 0 ||
315 		    ui->ui_ubanum != uban || sc->sc_openf == 0)
316 			continue;
317 		printf(" va%d", va11);
318 		vaaddr = (struct vadevice *)ui->ui_addr;
319 		vaaddr->vacsl = VA_IENABLE;
320 		if (sc->sc_state & VPLOT) {
321 			vaaddr->vacsh = VAPLOT;
322 			DELAY(10000);
323 			vaaddr->vacsh = VAAUTOSTEP;
324 		} else if (sc->sc_state & VPRINTPLOT)
325 			vaaddr->vacsh = VPRINTPLOT;
326 		else
327 			vaaddr->vacsh = VAPRINTPLOT;
328 		DELAY(10000);
329 		if (sc->sc_busy == 0)
330 			continue;
331 		if (sc->sc_ubinfo) {
332 			printf("<%d>", (sc->sc_ubinfo>>28)&0xf);
333 			ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
334 		}
335 		sc->sc_ubinfo = ubasetup(ui->ui_ubanum, sc->sc_bp, UBA_NEEDBDP);
336 		sc->sc_wc = -(sc->sc_bp->b_bcount/2);
337 		vastart(sc->sc_bp->b_dev);
338 	}
339 }
340 #endif
341