xref: /original-bsd/sys/vax/uba/vp.c (revision 6c57d260)
1 /*	vp.c	4.9	81/04/02	*/
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 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
87 	vpaddr->pbaddr = 0;
88 	vpaddr->pbxaddr = 0;
89 	vpaddr->prbcr = 1;
90 	DELAY(10000);
91 	vpaddr->prcsr = 0;
92 #ifdef ERNIE
93 	/* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */
94 	if (cvec == 0200) {
95 		printf("vp reset vec from 200 to 174\n");
96 		cvec = 0174;
97 	}
98 #endif
99 }
100 
101 /*ARGSUSED*/
102 vpattach(ui)
103 	struct uba_device *ui;
104 {
105 
106 	ui->ui_addr -= 010;
107 	ui->ui_physaddr -= 010;
108 }
109 
110 vpopen(dev)
111 	dev_t dev;
112 {
113 	register struct vp_softc *sc;
114 	register struct vpdevice *vpaddr;
115 	register struct uba_device *ui;
116 
117 	if (VPUNIT(dev) >= NVP ||
118 	    ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) ||
119 	    (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) {
120 		u.u_error = ENXIO;
121 		return;
122 	}
123 	vpaddr = (struct vpdevice *)ui->ui_addr;
124 	sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
125 	sc->sc_count = 0;
126 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
127 	vptimo(dev);
128 	while (sc->sc_state & VPSC_CMNDS) {
129 		(void) spl4();
130 		if (vpwait(dev)) {
131 			vpclose(dev);
132 			u.u_error = EIO;
133 			return;
134 		}
135 		vpstart(dev);
136 		(void) spl0();
137 	}
138 }
139 
140 vpstrategy(bp)
141 	register struct buf *bp;
142 {
143 	register int e;
144 	register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
145 	register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
146 	register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
147 
148 	(void) spl4();
149 	while (sc->sc_state & VPSC_BUSY)
150 		sleep((caddr_t)sc, VPPRI);
151 	sc->sc_state |= VPSC_BUSY;
152 	sc->sc_bp = bp;
153 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
154 	if (e = vpwait(bp->b_dev))
155 		goto brkout;
156 	sc->sc_count = bp->b_bcount;
157 	vpstart(bp->b_dev);
158 	while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
159 		sleep((caddr_t)sc, VPPRI);
160 	sc->sc_count = 0;
161 	if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
162 		sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
163 	(void) spl0();
164 brkout:
165 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
166 	sc->sc_state &= ~VPSC_BUSY;
167 	sc->sc_bp = 0;
168 	iodone(bp);
169 	if (e)
170 		u.u_error = EIO;
171 	wakeup((caddr_t)sc);
172 }
173 
174 int	vpblock = 16384;
175 
176 unsigned
177 minvpph(bp)
178 	struct buf *bp;
179 {
180 
181 	if (bp->b_bcount > vpblock)
182 		bp->b_bcount = vpblock;
183 }
184 
185 /*ARGSUSED*/
186 vpwrite(dev)
187 	dev_t dev;
188 {
189 
190 	physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph);
191 }
192 
193 vpwait(dev)
194 	dev_t dev;
195 {
196 	register struct vpdevice *vpaddr =
197 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
198 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
199 	register int e;
200 
201 	for (;;) {
202 		e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
203 		if (e & (VP_READY|VP_ERROR))
204 			break;
205 		sleep((caddr_t)sc, VPPRI);
206 	}
207 	/* I wish i could tell whether an error indicated an npr timeout */
208 	return (e & VP_ERROR);
209 }
210 
211 vpstart(dev)
212 	dev_t;
213 {
214 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
215 	register struct vpdevice *vpaddr =
216 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
217 	short bit;
218 
219 	if (sc->sc_count) {
220 		vpaddr->pbaddr = sc->sc_ubinfo;
221 		vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
222 		if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
223 			vpaddr->prbcr = sc->sc_count;
224 		else
225 			vpaddr->plbcr = sc->sc_count;
226 		return;
227 	}
228 	for (bit = 1; bit != 0; bit <<= 1)
229 		if (sc->sc_state&bit&VPSC_CMNDS) {
230 			vpaddr->plcsr |= bit;
231 			sc->sc_state &= ~bit;
232 			return;
233 		}
234 }
235 
236 /*ARGSUSED*/
237 vpioctl(dev, cmd, addr, flag)
238 	dev_t dev;
239 	int cmd;
240 	register caddr_t addr;
241 	int flag;
242 {
243 	register int m;
244 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
245 	register struct vpdevice *vpaddr =
246 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
247 
248 	switch (cmd) {
249 
250 	case VGETSTATE:
251 		(void) suword(addr, sc->sc_state);
252 		return;
253 
254 	case VSETSTATE:
255 		m = fuword(addr);
256 		if (m == -1) {
257 			u.u_error = EFAULT;
258 			return;
259 		}
260 		sc->sc_state =
261 		    (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS));
262 		break;
263 
264 	default:
265 		u.u_error = ENOTTY;
266 		return;
267 	}
268 	(void) spl4();
269 	(void) vpwait(dev);
270 	if (sc->sc_state&VPSC_SPP)
271 		vpaddr->plcsr |= VP_SPP;
272 	else
273 		vpaddr->plcsr &= ~VP_SPP;
274 	sc->sc_count = 0;
275 	while (sc->sc_state & VPSC_CMNDS) {
276 		(void) vpwait(dev);
277 		vpstart(dev);
278 	}
279 	(void) spl0();
280 }
281 
282 vptimo(dev)
283 	dev_t dev;
284 {
285 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
286 
287 	if (sc->sc_state&VPSC_OPEN)
288 		timeout(vptimo, (caddr_t)dev, hz/10);
289 	vpintr(dev);
290 }
291 
292 /*ARGSUSED*/
293 vpintr(dev)
294 	dev_t dev;
295 {
296 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
297 
298 	wakeup((caddr_t)sc);
299 }
300 
301 vpclose(dev)
302 	dev_t dev;
303 {
304 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
305 	register struct vpdevice *vpaddr =
306 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
307 
308 	sc->sc_state = 0;
309 	sc->sc_count = 0;
310 	vpaddr->plcsr = 0;
311 }
312 
313 vpreset(uban)
314 	int uban;
315 {
316 	register int vp11;
317 	register struct uba_device *ui;
318 	register struct vp_softc *sc = vp_softc;
319 	register struct vpdevice *vpaddr;
320 
321 	for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
322 		if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
323 		    ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
324 			continue;
325 		printf(" vp%d", vp11);
326 		vpaddr = (struct vpdevice *)ui->ui_addr;
327 		vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
328 		if ((sc->sc_state & VPSC_BUSY) == 0)
329 			continue;
330 		if (sc->sc_ubinfo) {
331 			printf("<%d>", (sc->sc_ubinfo>>28)&0xf);
332 			ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
333 		}
334 		sc->sc_count = sc->sc_bp->b_bcount;
335 		vpstart(sc->sc_bp->b_dev);
336 	}
337 }
338 #endif
339