xref: /original-bsd/sys/vax/uba/vp.c (revision b3b53e97)
1 /*	vp.c	4.11	82/04/01	*/
2 
3 #include "vp.h"
4 #if NVP > 0
5 /*
6  * Versatec matrix printer/plotter
7  * dma interface driver
8  *
9  * SETUP NOTES:
10  *	Set up both print and plot interrupts to go through the same vector
11  *	Give the address of the plcsr register in the config specification
12  */
13 #include "../h/param.h"
14 #include "../h/dir.h"
15 #include "../h/user.h"
16 #include "../h/buf.h"
17 #include "../h/systm.h"
18 #include "../h/map.h"
19 #include "../h/pte.h"
20 #include "../h/ubavar.h"
21 #include "../h/ubareg.h"
22 #include "../h/vcmd.h"
23 
24 unsigned minvpph();
25 
26 #define	VPPRI	(PZERO-1)
27 
28 struct	vpdevice {
29 	short	plbcr;
30 	short	pbxaddr;
31 	short	prbcr;
32 	u_short pbaddr;
33 	short	plcsr;
34 	short	plbuf;
35 	short	prcsr;
36 	u_short prbuf;
37 };
38 
39 #define	VP_ERROR	0100000
40 #define	VP_DTCINTR	0040000
41 #define	VP_DMAACT	0020000
42 #define	VP_READY	0000200
43 #define	VP_IENABLE	0000100
44 #define	VP_TERMCOM	0000040
45 #define	VP_FFCOM	0000020
46 #define	VP_EOTCOM	0000010
47 #define	VP_CLRCOM	0000004
48 #define	VP_RESET	0000002
49 #define	VP_SPP		0000001
50 
51 struct vp_softc {
52 	int	sc_state;
53 	int	sc_count;
54 	int	sc_bufp;
55 	struct	buf *sc_bp;
56 	int	sc_ubinfo;
57 } vp_softc[NVP];
58 
59 /* sc_state bits */
60 #define	VPSC_BUSY	0001000
61 #define	VPSC_MODE	0000700
62 #define	VPSC_SPP	0000400
63 #define	VPSC_PLOT	0000200
64 #define	VPSC_PRINT	0000100
65 #define	VPSC_CMNDS	0000076
66 #define	VPSC_OPEN	0000001
67 
68 struct	uba_device *vpdinfo[NVP];
69 
70 #define	VPUNIT(dev)	(minor(dev))
71 
72 struct	buf rvpbuf[NVP];
73 
74 int	vpprobe(), vpattach();
75 struct	uba_device *vpdinfo[NVP];
76 u_short	vpstd[] = { 0777500, 0 };
77 struct	uba_driver vpdriver =
78     { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo };
79 
80 vpprobe(reg)
81 	caddr_t reg;
82 {
83 	register int br, cvec;		/* value-result */
84 	register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010);
85 
86 #ifdef lint
87 	br = 0; cvec = br; br = cvec;
88 	vpintr(0);
89 #endif
90 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
91 	vpaddr->pbaddr = 0;
92 	vpaddr->pbxaddr = 0;
93 	vpaddr->prbcr = 1;
94 	DELAY(10000);
95 	vpaddr->prcsr = 0;
96 #ifdef ERNIE
97 	/* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */
98 	if (cvec == 0200) {
99 		printf("vp reset vec from 200 to 174\n");
100 		cvec = 0174;
101 	}
102 #endif
103 }
104 
105 /*ARGSUSED*/
106 vpattach(ui)
107 	struct uba_device *ui;
108 {
109 
110 	ui->ui_addr -= 010;
111 	ui->ui_physaddr -= 010;
112 }
113 
114 vpopen(dev)
115 	dev_t dev;
116 {
117 	register struct vp_softc *sc;
118 	register struct vpdevice *vpaddr;
119 	register struct uba_device *ui;
120 
121 	if (VPUNIT(dev) >= NVP ||
122 	    ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) ||
123 	    (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) {
124 		u.u_error = ENXIO;
125 		return;
126 	}
127 	vpaddr = (struct vpdevice *)ui->ui_addr;
128 	sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
129 	sc->sc_count = 0;
130 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
131 	vptimo(dev);
132 	while (sc->sc_state & VPSC_CMNDS) {
133 		(void) spl4();
134 		if (vpwait(dev)) {
135 			vpclose(dev);
136 			u.u_error = EIO;
137 			return;
138 		}
139 		vpstart(dev);
140 		(void) spl0();
141 	}
142 }
143 
144 vpstrategy(bp)
145 	register struct buf *bp;
146 {
147 	register int e;
148 	register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
149 	register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
150 	register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
151 
152 	(void) spl4();
153 	while (sc->sc_state & VPSC_BUSY)
154 		sleep((caddr_t)sc, VPPRI);
155 	sc->sc_state |= VPSC_BUSY;
156 	sc->sc_bp = bp;
157 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
158 	if (e = vpwait(bp->b_dev))
159 		goto brkout;
160 	sc->sc_count = bp->b_bcount;
161 	vpstart(bp->b_dev);
162 	while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
163 		sleep((caddr_t)sc, VPPRI);
164 	sc->sc_count = 0;
165 	if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
166 		sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
167 	(void) spl0();
168 brkout:
169 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
170 	sc->sc_state &= ~VPSC_BUSY;
171 	sc->sc_bp = 0;
172 	iodone(bp);
173 	if (e)
174 		u.u_error = EIO;
175 	wakeup((caddr_t)sc);
176 }
177 
178 int	vpblock = 16384;
179 
180 unsigned
181 minvpph(bp)
182 	struct buf *bp;
183 {
184 
185 	if (bp->b_bcount > vpblock)
186 		bp->b_bcount = vpblock;
187 }
188 
189 /*ARGSUSED*/
190 vpwrite(dev)
191 	dev_t dev;
192 {
193 
194 	physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph);
195 }
196 
197 vpwait(dev)
198 	dev_t dev;
199 {
200 	register struct vpdevice *vpaddr =
201 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
202 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
203 	register int e;
204 
205 	for (;;) {
206 		e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
207 		if (e & (VP_READY|VP_ERROR))
208 			break;
209 		sleep((caddr_t)sc, VPPRI);
210 	}
211 	/* I wish i could tell whether an error indicated an npr timeout */
212 	return (e & VP_ERROR);
213 }
214 
215 vpstart(dev)
216 	dev_t;
217 {
218 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
219 	register struct vpdevice *vpaddr =
220 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
221 	short bit;
222 
223 	if (sc->sc_count) {
224 		vpaddr->pbaddr = sc->sc_ubinfo;
225 		vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
226 		if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
227 			vpaddr->prbcr = sc->sc_count;
228 		else
229 			vpaddr->plbcr = sc->sc_count;
230 		return;
231 	}
232 	for (bit = 1; bit != 0; bit <<= 1)
233 		if (sc->sc_state&bit&VPSC_CMNDS) {
234 			vpaddr->plcsr |= bit;
235 			sc->sc_state &= ~bit;
236 			return;
237 		}
238 }
239 
240 /*ARGSUSED*/
241 vpioctl(dev, cmd, addr, flag)
242 	dev_t dev;
243 	int cmd;
244 	register caddr_t addr;
245 	int flag;
246 {
247 	register int m;
248 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
249 	register struct vpdevice *vpaddr =
250 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
251 
252 	switch (cmd) {
253 
254 	case VGETSTATE:
255 		(void) suword(addr, sc->sc_state);
256 		return;
257 
258 	case VSETSTATE:
259 		m = fuword(addr);
260 		if (m == -1) {
261 			u.u_error = EFAULT;
262 			return;
263 		}
264 		sc->sc_state =
265 		    (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS));
266 		break;
267 
268 	default:
269 		u.u_error = ENOTTY;
270 		return;
271 	}
272 	(void) spl4();
273 	(void) vpwait(dev);
274 	if (sc->sc_state&VPSC_SPP)
275 		vpaddr->plcsr |= VP_SPP;
276 	else
277 		vpaddr->plcsr &= ~VP_SPP;
278 	sc->sc_count = 0;
279 	while (sc->sc_state & VPSC_CMNDS) {
280 		(void) vpwait(dev);
281 		vpstart(dev);
282 	}
283 	(void) spl0();
284 }
285 
286 vptimo(dev)
287 	dev_t dev;
288 {
289 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
290 
291 	if (sc->sc_state&VPSC_OPEN)
292 		timeout(vptimo, (caddr_t)dev, hz/10);
293 	vpintr(dev);
294 }
295 
296 /*ARGSUSED*/
297 vpintr(dev)
298 	dev_t dev;
299 {
300 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
301 
302 	wakeup((caddr_t)sc);
303 }
304 
305 vpclose(dev)
306 	dev_t dev;
307 {
308 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
309 	register struct vpdevice *vpaddr =
310 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
311 
312 	sc->sc_state = 0;
313 	sc->sc_count = 0;
314 	vpaddr->plcsr = 0;
315 }
316 
317 vpreset(uban)
318 	int uban;
319 {
320 	register int vp11;
321 	register struct uba_device *ui;
322 	register struct vp_softc *sc = vp_softc;
323 	register struct vpdevice *vpaddr;
324 
325 	for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
326 		if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
327 		    ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
328 			continue;
329 		printf(" vp%d", vp11);
330 		vpaddr = (struct vpdevice *)ui->ui_addr;
331 		vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
332 		if ((sc->sc_state & VPSC_BUSY) == 0)
333 			continue;
334 		if (sc->sc_ubinfo) {
335 			printf("<%d>", (sc->sc_ubinfo>>28)&0xf);
336 			ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
337 		}
338 		sc->sc_count = sc->sc_bp->b_bcount;
339 		vpstart(sc->sc_bp->b_dev);
340 	}
341 }
342 
343 vpselect()
344 {
345 	return (1);
346 }
347 #endif
348