header files for vax are in their place
[unix-history] / usr / src / sys / vax / uba / vp.c
CommitLineData
896962b1 1/* vp.c 4.19 82/10/10 */
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) ||
126 (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) {
2a75a0e9
BJ
127 u.u_error = ENXIO;
128 return;
129 }
fc4d0a69
BJ
130 vpaddr = (struct vpdevice *)ui->ui_addr;
131 sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
132 sc->sc_count = 0;
133 vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
134 vptimo(dev);
135 while (sc->sc_state & VPSC_CMNDS) {
81263dba 136 (void) spl4();
fc4d0a69
BJ
137 if (vpwait(dev)) {
138 vpclose(dev);
2a75a0e9
BJ
139 u.u_error = EIO;
140 return;
141 }
fc4d0a69 142 vpstart(dev);
81263dba 143 (void) spl0();
2a75a0e9
BJ
144 }
145}
146
147vpstrategy(bp)
148 register struct buf *bp;
149{
150 register int e;
fc4d0a69
BJ
151 register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
152 register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
153 register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
2a75a0e9 154
81263dba 155 (void) spl4();
fc4d0a69
BJ
156 while (sc->sc_state & VPSC_BUSY)
157 sleep((caddr_t)sc, VPPRI);
158 sc->sc_state |= VPSC_BUSY;
159 sc->sc_bp = bp;
160 sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
161 if (e = vpwait(bp->b_dev))
2a75a0e9 162 goto brkout;
fc4d0a69
BJ
163 sc->sc_count = bp->b_bcount;
164 vpstart(bp->b_dev);
165 while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
166 sleep((caddr_t)sc, VPPRI);
167 sc->sc_count = 0;
168 if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
169 sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
81263dba 170 (void) spl0();
2a75a0e9 171brkout:
fc4d0a69
BJ
172 ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
173 sc->sc_state &= ~VPSC_BUSY;
174 sc->sc_bp = 0;
2a75a0e9
BJ
175 iodone(bp);
176 if (e)
177 u.u_error = EIO;
fc4d0a69 178 wakeup((caddr_t)sc);
2a75a0e9
BJ
179}
180
181int vpblock = 16384;
182
183unsigned
184minvpph(bp)
fc4d0a69 185 struct buf *bp;
2a75a0e9
BJ
186{
187
188 if (bp->b_bcount > vpblock)
189 bp->b_bcount = vpblock;
190}
191
192/*ARGSUSED*/
0cd5eac7 193vpwrite(dev, uio)
fc4d0a69 194 dev_t dev;
0cd5eac7 195 struct uio *uio;
2a75a0e9
BJ
196{
197
002227dd 198 if (VPUNIT(dev) >= NVP)
0cd5eac7
BJ
199 return (ENXIO);
200 return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE,
201 minvpph, uio));
2a75a0e9
BJ
202}
203
fc4d0a69
BJ
204vpwait(dev)
205 dev_t dev;
2a75a0e9 206{
fc4d0a69
BJ
207 register struct vpdevice *vpaddr =
208 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
209 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
210 register int e;
2a75a0e9 211
fc4d0a69
BJ
212 for (;;) {
213 e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
214 if (e & (VP_READY|VP_ERROR))
215 break;
216 sleep((caddr_t)sc, VPPRI);
217 }
218 /* I wish i could tell whether an error indicated an npr timeout */
219 return (e & VP_ERROR);
2a75a0e9
BJ
220}
221
fc4d0a69
BJ
222vpstart(dev)
223 dev_t;
2a75a0e9 224{
fc4d0a69
BJ
225 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
226 register struct vpdevice *vpaddr =
227 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
228 short bit;
229
230 if (sc->sc_count) {
231 vpaddr->pbaddr = sc->sc_ubinfo;
232 vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
233 if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
234 vpaddr->prbcr = sc->sc_count;
2a75a0e9 235 else
fc4d0a69 236 vpaddr->plbcr = sc->sc_count;
2a75a0e9
BJ
237 return;
238 }
239 for (bit = 1; bit != 0; bit <<= 1)
fc4d0a69
BJ
240 if (sc->sc_state&bit&VPSC_CMNDS) {
241 vpaddr->plcsr |= bit;
242 sc->sc_state &= ~bit;
2a75a0e9
BJ
243 return;
244 }
245}
246
247/*ARGSUSED*/
248vpioctl(dev, cmd, addr, flag)
fc4d0a69
BJ
249 dev_t dev;
250 int cmd;
2a75a0e9 251 register caddr_t addr;
fc4d0a69 252 int flag;
2a75a0e9
BJ
253{
254 register int m;
fc4d0a69
BJ
255 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
256 register struct vpdevice *vpaddr =
257 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
2a75a0e9
BJ
258
259 switch (cmd) {
260
fc4d0a69
BJ
261 case VGETSTATE:
262 (void) suword(addr, sc->sc_state);
2a75a0e9
BJ
263 return;
264
fc4d0a69 265 case VSETSTATE:
2a75a0e9
BJ
266 m = fuword(addr);
267 if (m == -1) {
268 u.u_error = EFAULT;
269 return;
270 }
fc4d0a69
BJ
271 sc->sc_state =
272 (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS));
2a75a0e9
BJ
273 break;
274
275 default:
276 u.u_error = ENOTTY;
277 return;
278 }
81263dba 279 (void) spl4();
fc4d0a69
BJ
280 (void) vpwait(dev);
281 if (sc->sc_state&VPSC_SPP)
282 vpaddr->plcsr |= VP_SPP;
2a75a0e9 283 else
fc4d0a69
BJ
284 vpaddr->plcsr &= ~VP_SPP;
285 sc->sc_count = 0;
286 while (sc->sc_state & VPSC_CMNDS) {
287 (void) vpwait(dev);
288 vpstart(dev);
2a75a0e9 289 }
81263dba 290 (void) spl0();
2a75a0e9
BJ
291}
292
fc4d0a69
BJ
293vptimo(dev)
294 dev_t dev;
2a75a0e9 295{
fc4d0a69 296 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
2a75a0e9 297
fc4d0a69
BJ
298 if (sc->sc_state&VPSC_OPEN)
299 timeout(vptimo, (caddr_t)dev, hz/10);
300 vpintr(dev);
2a75a0e9
BJ
301}
302
303/*ARGSUSED*/
304vpintr(dev)
fc4d0a69 305 dev_t dev;
2a75a0e9 306{
fc4d0a69 307 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
2a75a0e9 308
fc4d0a69 309 wakeup((caddr_t)sc);
2a75a0e9
BJ
310}
311
fc4d0a69
BJ
312vpclose(dev)
313 dev_t dev;
2a75a0e9 314{
fc4d0a69
BJ
315 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
316 register struct vpdevice *vpaddr =
317 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
2a75a0e9 318
fc4d0a69
BJ
319 sc->sc_state = 0;
320 sc->sc_count = 0;
321 vpaddr->plcsr = 0;
2a75a0e9 322}
d62630e9 323
fc4d0a69
BJ
324vpreset(uban)
325 int uban;
d62630e9 326{
fc4d0a69
BJ
327 register int vp11;
328 register struct uba_device *ui;
329 register struct vp_softc *sc = vp_softc;
330 register struct vpdevice *vpaddr;
331
332 for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
333 if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
334 ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
335 continue;
336 printf(" vp%d", vp11);
337 vpaddr = (struct vpdevice *)ui->ui_addr;
338 vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
339 if ((sc->sc_state & VPSC_BUSY) == 0)
340 continue;
341 if (sc->sc_ubinfo) {
342 printf("<%d>", (sc->sc_ubinfo>>28)&0xf);
343 ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
344 }
345 sc->sc_count = sc->sc_bp->b_bcount;
346 vpstart(sc->sc_bp->b_dev);
d62630e9 347 }
d62630e9 348}
941b74fe
SL
349
350vpselect()
351{
352 return (1);
353}
a5cc519e 354#endif