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