1: /*
2: * SCCS id @(#)vp.c 2.1 (Berkeley) 8/5/83
3: */
4:
5: /*
6: * Versatec printer/plotter driver for model c-pdp11(dma) controller
7: *
8: * Thomas Ferrin, UCSF Computer Graphics Laboratory, April 1979
9: *
10: * Uses the same user interface as Bell Labs' driver but runs in raw
11: * mode, since even the small 11" versatec outputs ~53kbytes/inch!
12: */
13:
14: /* #define NOMESG /* no console messages if defined */
15: /* #define VP_TWOSCOMPL /* use two's-complement bytecount */
16:
17: #include "vp.h"
18: #if NVP > 0
19: #include "param.h"
20: #include <sys/dir.h>
21: #include <sys/user.h>
22: #include <sys/buf.h>
23: #include <sys/proc.h>
24: #include <sys/vcmd.h>
25:
26: #define PRINTADR ((struct devregs *)0177514) /* printer csr */
27: #define PLOTADR ((struct devregs *)0177510) /* plotter csr */
28: /*
29: * Note that there is really only 1 csr! Changes to 'PRINTADR'
30: * csr are reflected in 'PLOTADR' csr and vice versa. Referencing
31: * the particular csr sets the device into that mode of operation.
32: */
33: #define DMA ((struct dmaregs *)0177500) /* dma register base */
34:
35: #define ERROR 0100000
36: #define DTCENABLE 040000 /* interrupt on data xfer complete */
37: #define IENABLE 0100 /* interrupt on ready or error */
38: #define READY 0200 /* previous operation complete */
39: #define REOT 010 /* remote end-of-transmission */
40: #define RESET 02
41: #define CMDS 076
42: #define SPP 01 /* simultaneous print/plot mode */
43:
44: struct buf vpbuf;
45: #ifndef NOMESG
46: char *vperr = "\nVersatec needs attention\n";
47: #endif
48:
49: struct devregs {
50: short csr;
51: };
52:
53: struct dmaregs {
54: short plotbytes;
55: short addrext;
56: short printbytes;
57: unsigned short addr;
58: };
59:
60: struct {
61: int state;
62: unsigned bytecount;
63: int alive;
64: } vp11;
65:
66: /* states */
67: #define PPLOT 0400 /* low 6 bits reserved for hardware functions */
68: #define PLOT 0200
69: #define PRINT 0100
70: #define MODE 0700
71: #define ERRMSG 01000
72: #define NOSTART 02000
73: #define WBUSY 04000
74:
75: /*
76: * This driver should be converted to use a single VPADDR pointer.
77: * Until then, the attach only marks the unit as alive.
78: */
79: vpattach(addr, unit)
80: struct vpdevice *addr;
81: {
82: if (((unsigned) unit == 0) || (addr == DMA)) {
83: vp11.alive++;
84: return 1;
85: }
86: return 0;
87: }
88:
89: /* ARGSUSED */
90: vpopen(dev, flag)
91: dev_t dev;
92: {
93: register short *vpp;
94:
95: if (!vp11.alive || vp11.state&MODE) {
96: u.u_error = ENXIO;
97: return;
98: }
99: vpp = &PRINTADR->csr;
100: vp11.state = PRINT;
101: vpbuf.b_flags = B_DONE;
102: *vpp = IENABLE | RESET;
103: /*
104: * Contrary to the implication in the operator's manual, it is an
105: * error to have the bits for both an operation complete interrupt
106: * and a data transmission complete interrupt set at the same time.
107: * Doing so will cause erratic operation of 'READY' interrupts.
108: */
109: if (vperror())
110: *vpp = vp11.state = 0;
111: }
112:
113: /* ARGSUSED */
114: vpclose(dev, flag)
115: dev_t dev;
116: {
117: register short *vpp;
118:
119: vperror();
120: vpp = (vp11.state&PLOT)? &PLOTADR->csr : &PRINTADR->csr;
121: *vpp = IENABLE | REOT; /* page eject past toner bath */
122: vperror();
123: *vpp = vp11.state = 0;
124: }
125:
126: vpwrite(dev)
127: dev_t dev;
128: {
129: int vpstart();
130:
131: if ((vp11.bytecount=u.u_count) == 0) /* true byte count */
132: return;
133: if (u.u_count&01) /* avoid EFAULT error in physio() */
134: u.u_count++;
135: if (vperror())
136: return;
137: physio(vpstart, &vpbuf, dev, B_WRITE);
138: /* note that newer 1200A's print @ 1000 lines/min = 2.2kbytes/sec */
139: }
140:
141: #ifdef V6
142: vpctl(dev, v)
143: dev_t dev;
144: int *v;
145: {
146: register int ctrl;
147: register short *vpp;
148:
149: if (v) {
150: *v = vp11.state;
151: return;
152: }
153: if (vperror())
154: return;
155: ctrl = u.u_arg[0];
156: vp11.state = (vp11.state&~MODE) | (ctrl&MODE);
157: vpp = (ctrl&PLOT)? &PLOTADR->csr : &PRINTADR->csr;
158: if (ctrl&CMDS) {
159: *vpp = IENABLE | (ctrl&CMDS) | (vp11.state&SPP);
160: vperror();
161: }
162: if (ctrl&PPLOT) {
163: vp11.state |= SPP;
164: *vpp = DTCENABLE | SPP;
165: } else if (ctrl&PRINT) {
166: vp11.state &= ~SPP;
167: *vpp = IENABLE;
168: } else
169: *vpp = IENABLE | (vp11.state&SPP);
170: }
171: #else
172:
173: /* ARGSUSED */
174: vpioctl(dev, cmd, addr, flag)
175: dev_t dev;
176: caddr_t addr;
177: {
178: register int ctrl;
179: register short *vpp;
180: register struct buf *bp;
181:
182: switch (cmd) {
183:
184: case GETSTATE:
185: suword(addr, vp11.state);
186: return;
187:
188: case SETSTATE:
189: ctrl = fuword(addr);
190: if (ctrl == -1) {
191: u.u_error = EFAULT;
192: return;
193: }
194: if (vperror())
195: return;
196: vp11.state = (vp11.state&~MODE) | (ctrl&MODE);
197: vpp = (ctrl&PLOT)? &PLOTADR->csr : &PRINTADR->csr;
198: if (ctrl&CMDS) {
199: *vpp = IENABLE | (ctrl&CMDS) | (vp11.state&SPP);
200: vperror();
201: }
202: if (ctrl&PPLOT) {
203: vp11.state |= SPP;
204: *vpp = DTCENABLE | SPP;
205: } else if (ctrl&PRINT) {
206: vp11.state &= ~SPP;
207: *vpp = IENABLE;
208: } else
209: *vpp = IENABLE | (vp11.state&SPP);
210: return;
211:
212: case BUFWRITE:
213: u.u_base = fuword(addr);
214: u.u_count = fuword(addr+NBPW);
215: if ((int)u.u_base == -1 || (int)u.u_count == -1) {
216: u.u_error = EFAULT;
217: return;
218: }
219: bp = &vpbuf;
220: if (vp11.state&WBUSY) {
221: /* wait for previous write */
222: (void) _spl4();
223: while ((bp->b_flags&B_DONE) == 0)
224: sleep(bp, PRIBIO);
225: u.u_procp->p_flag &= ~SLOCK;
226: bp->b_flags &= ~B_BUSY;
227: vp11.state &= ~WBUSY;
228: (void) _spl0();
229: geterror(bp);
230: if (u.u_error)
231: return;
232: }
233: if (u.u_count == 0)
234: return;
235: /* simulate a write without starting i/o */
236: (void) _spl4();
237: vp11.state |= NOSTART;
238: vpwrite(dev);
239: vp11.state &= ~NOSTART;
240: if (u.u_error) {
241: (void) _spl0();
242: return;
243: }
244: /* fake write was ok, now do it for real */
245: bp->b_flags = B_BUSY | B_PHYS | B_WRITE;
246: u.u_procp->p_flag |= SLOCK;
247: vp11.state |= WBUSY;
248: vpstart(bp);
249: (void) _spl0();
250: return;
251:
252: default:
253: u.u_error = ENOTTY;
254: }
255: }
256: #endif
257:
258: vperror()
259: {
260: register int state, err;
261:
262: state = vp11.state & PLOT;
263: (void) _spl4();
264: while ((err=(state? PLOTADR->csr : PRINTADR->csr)&(READY|ERROR))==0)
265: sleep((caddr_t)&vp11, PRIBIO);
266: (void) _spl0();
267: if (err&ERROR) {
268: u.u_error = EIO;
269: #ifndef NOMESG
270: if (!(vp11.state&ERRMSG)) {
271: printf(vperr);
272: vp11.state |= ERRMSG;
273: }
274: #endif
275: } else
276: vp11.state &= ~ERRMSG;
277: return(err&ERROR);
278: }
279:
280: vpstart(bp)
281: register struct buf *bp;
282: {
283: register struct dmaregs *vpp = DMA;
284:
285: if (vp11.state&NOSTART) {
286: bp->b_flags |= B_DONE; /* fake it */
287: return;
288: }
289: #ifdef UNIBUS_MAP
290: mapalloc(bp);
291: #endif
292: vpp->addr = (short)(bp->b_un.b_addr);
293: vpp->addrext = (bp->b_xmem & 03) << 4;
294: #ifndef VP_TWOSCOMPL
295: if (vp11.state&PLOT)
296: vpp->plotbytes = vp11.bytecount;
297: else
298: vpp->printbytes = vp11.bytecount;
299: #else
300: if (vp11.state&PLOT)
301: vpp->plotbytes = -vp11.bytecount;
302: else
303: vpp->printbytes = -vp11.bytecount;
304: #endif
305: }
306:
307: vpintr()
308: {
309: register struct buf *bp = &vpbuf;
310:
311: /*
312: * Hardware botch. Interrupts occur a few usec before the 'READY'
313: * bit actually sets. On fast processors it is unreliable to test
314: * this bit in the interrupt service routine!
315: */
316: if (bp->b_flags&B_DONE) {
317: wakeup((caddr_t)&vp11);
318: return;
319: }
320: if (((vp11.state&PLOT)? PLOTADR->csr : PRINTADR->csr) < 0) {
321: #ifndef NOMESG
322: if (!(vp11.state&ERRMSG)) {
323: printf(vperr);
324: vp11.state |= ERRMSG;
325: }
326: #endif
327: bp->b_flags |= B_ERROR;
328: bp->b_error = EIO;
329: wakeup((caddr_t)&vp11);
330: }
331: iodone(bp);
332: }
333: #endif NVP
Defined functions
Defined variables
vpbuf
defined in line
44; used 4 times
vperr
defined in line
46; used 2 times
Defined struct's
Defined macros
CMDS
defined in line
41; used 4 times
DMA
defined in line
33; used 2 times
ERROR
defined in line
35; used 3 times
MODE
defined in line
70; used 5 times
PLOT
defined in line
68; used 7 times
PPLOT
defined in line
67; used 2 times
PRINT
defined in line
69; used 3 times
READY
defined in line
38; used 1 times
REOT
defined in line
39; used 1 times
RESET
defined in line
40; used 1 times
SPP
defined in line
42; used 10 times
WBUSY
defined in line
73; used 3 times