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