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