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