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