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