|
|
1.1 root 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.4 (Berkeley) 4/3/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 "machine/pte.h"
22:
23: #include "param.h"
24: #include "user.h"
25: #include "buf.h"
26: #include "systm.h"
27: #include "map.h"
28: #include "ioctl.h"
29: #include "vcmd.h"
30: #include "uio.h"
31: #include "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:
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:
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:
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
190: minvpph(bp)
191: struct buf *bp;
192: {
193:
194: if (bp->b_bcount > vpblock)
195: bp->b_bcount = vpblock;
196: }
197:
198: /*ARGSUSED*/
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:
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*/
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:
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*/
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:
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:
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:
349: vpselect()
350: {
351: return (1);
352: }
353: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.