|
|
1.1 root 1: /*
2: * VAX 11/780 console driver
3: * multiple ID stuff is mostly to aid floppy
4: */
5: #include "sys/param.h"
6: #include "sys/stream.h"
7: #include "sys/ttyio.h"
8: #include "sys/cons.h"
9: #include "sys/mtpr.h"
10: #include "sys/conf.h"
11:
12: #define NCONS 16 /* possible console IDs */
13:
14: #define DATA 0xff
15: #define IDMASK 0xff
16: #define IDSHIFT 8
17:
18: #define CONPRI (PZERO+5) /* something interruptible */
19:
20: /*
21: * state bits
22: */
23: #define TTSTOP 01
24: #define TIMEOUT 04
25:
26: /*
27: * cnbusy bits
28: */
29: #define TXBUSY 01
30: #define IOBUSY 02 /* cninc/cnoutc busy */
31:
32: static char cnbusy;
33: static char cnonext;
34: static char cnstate[NCONS];
35: static struct queue *cnrq[NCONS];
36: static struct queue *cnwq[NCONS];
37:
38: /*
39: * for internal io without device open
40: */
41: struct cnbuf {
42: int count;
43: char *buf;
44: };
45: static struct cnbuf cnibuf[NCONS];
46: static struct cnbuf cnobuf[NCONS];
47: static short cnlastin; /* debugging */
48:
49: long cnopen();
50: int cnclose(), cnoput();
51:
52: static struct qinit cnrinit = { nulldev, NULL, cnopen, cnclose, 0, 0 };
53: static struct qinit cnwinit = { cnoput, NULL, cnopen, cnclose, 200, 100 };
54: struct streamtab cnstream = { &cnrinit, &cnwinit };
55: struct cdevsw cncdev = cstrinit(&cnstream);
56:
57: long
58: cnopen(qp, dev)
59: struct queue *qp;
60: dev_t dev;
61: {
62: register int i;
63:
64: i = minor(dev);
65: if (i >= NCONS)
66: return (1);
67: cnrq[i] = qp;
68: cnwq[i] = WR(qp);
69: qp->ptr = (caddr_t)i;
70: mtpr(RXCS, mfpr(RXCS)|RXCS_IE);
71: return(1);
72: }
73:
74: cnclose(qp)
75: struct queue *qp;
76: {
77: register int i;
78:
79: i = (int)qp->ptr;
80: cnrq[i] = NULL;
81: cnwq[i] = NULL;
82: }
83:
84: /*
85: * Console write put routine
86: */
87: cnoput(q, bp)
88: register struct queue *q;
89: register struct block *bp;
90: {
91: register struct ttydevb *sp;
92: register int dev;
93:
94: dev = (int)OTHERQ(q)->ptr;
95: switch(bp->type) {
96: case M_IOCTL: /* just acknowledge */
97: sp = (struct ttydevb *)stiodata(bp);
98: switch (stiocom(bp)) {
99: case TIOCGDEV:
100: sp->ispeed = sp->ospeed = B9600;
101: bp->wptr = bp->rptr + sizeof(struct ttydevb) + STIOCHDR;
102: bp->type = M_IOCACK;
103: qreply(q, bp);
104: return;
105:
106: case TIOCSDEV:
107: bp->wptr = bp->rptr;
108: bp->type = M_IOCACK;
109: qreply(q, bp);
110: return;
111:
112: default:
113: bp->type = M_IOCNAK;
114: bp->wptr = bp->rptr;
115: qreply(q, bp);
116: return;
117: }
118:
119: case M_STOP:
120: cnstate[dev] |= TTSTOP;
121: break;
122:
123: case M_START:
124: cnstate[dev] &= ~TTSTOP;
125: cnstart();
126: break;
127:
128: case M_FLUSH:
129: flushq(q, 0);
130: break;
131:
132: case M_DELAY:
133: case M_DATA:
134: if (bp->rptr >= bp->wptr)
135: break;
136: putq(q, bp);
137: cnstart();
138: return;
139:
140: default: /* not handled; just toss */
141: break;
142: }
143: freeb(bp);
144: }
145:
146: /*
147: * Console receive interrupt
148: */
149:
150: cnrint()
151: {
152: register int c, dev;
153: register struct queue *qp;
154: register struct cnbuf *cp;
155:
156: c = mfpr(RXDB);
157: dev = (c >> IDSHIFT) & IDMASK;
158: cp = &cnibuf[dev];
159: if (cp->count) {
160: *cp->buf++ = c;
161: if (--cp->count == 0)
162: wakeup((caddr_t)&cp->count);
163: return;
164: }
165: if ((qp = cnrq[dev])!=NULL) {
166: if ((qp->next->flag & QFULL) == 0)
167: putd(qp->next->qinfo->putp, qp->next, c);
168: return;
169: }
170: cnlastin = c; /* for debugging */
171: }
172:
173: /*
174: * Transmitter interrupt
175: */
176: cnxint()
177: {
178: cnbusy &=~ TXBUSY;
179: mtpr(TXCS, mfpr(TXCS)&~TXCS_IE);
180: cnstart();
181: }
182:
183: cntime(dev)
184: caddr_t dev;
185: {
186: cnstate[(int)dev] &= ~TIMEOUT;
187: cnstart();
188: }
189:
190: #define NEXT(i) (((i)+1)%NCONS)
191:
192: cnstart()
193: {
194: register struct block *bp;
195: register int i;
196: register struct queue *q;
197: register struct cnbuf *cp;
198: register s, j;
199:
200: s = spl6();
201: if (cnbusy & TXBUSY) {
202: splx(s);
203: return;
204: }
205: i = cnonext;
206: for (j = 0; j < NCONS && (cnbusy & TXBUSY) == 0; i = NEXT(i), j++) {
207: cp = &cnobuf[i];
208: if (cp->count) {
209: mtpr(TXDB, (*cp->buf++&0377) | (i<<IDSHIFT));
210: mtpr(TXCS, mfpr(TXCS)|TXCS_IE);
211: cnbusy |= TXBUSY;
212: if (--cp->count == 0)
213: wakeup((caddr_t)&cp->count);
214: continue;
215: }
216: if ((q = cnwq[i]) == NULL)
217: continue;
218: if ((cnstate[i] & (TIMEOUT|TTSTOP)) || q->count == 0)
219: continue;
220: bp = getq(q);
221: switch (bp->type) {
222: case M_DATA:
223: mtpr(TXDB, (i<<IDSHIFT)|*bp->rptr++);
224: mtpr(TXCS, mfpr(TXCS)|TXCS_IE);
225: cnbusy |= TXBUSY;
226: if (bp->rptr >= bp->wptr)
227: freeb(bp);
228: else
229: putbq(q, bp);
230: break;
231:
232: case M_DELAY:
233: timeout(cntime, (caddr_t)i, (int)*bp->rptr);
234: cnstate[i] |= TIMEOUT;
235: default: /* flow through */
236: freeb(bp);
237: break;
238: }
239: }
240: cnonext = i;
241: splx(s);
242: }
243:
244: /*
245: * Print a character on console; for printf.
246: * try to preserve things; wait a bit for console to come ready.
247: * all fairly hopeless.
248: */
249: cnputc(c)
250: register c;
251: {
252: register s, timo;
253:
254: timo = 3000000;
255: while((mfpr(TXCS)&TXCS_RDY) == 0)
256: if(--timo == 0)
257: return;
258: if(c == 0)
259: return;
260: s = mfpr(TXCS);
261: mtpr(TXCS, 0);
262: mtpr(TXDB, c&DATA);
263: if(c == '\n')
264: cnputc('\r');
265: cnputc(0);
266: mtpr(TXCS, s);
267: }
268:
269: /*
270: * primitives for internal console I/O
271: * p = cniwrite(id, buf, count)
272: * p = cniread(id, buf, count)
273: * p is a pointer to an integer.
274: * when the count is satisfied, *p will be zero and p will be awakened
275: * *p = 0 aborts the I/O
276: * cniwait(p, s) waits for at most s seconds, then aborts
277: *
278: * only one I/O may be outstanding per id;
279: * a new one aborts the previous one, quietly
280: *
281: * buf had best be static; stacks move, and the process waiting for io
282: * will almost certainly go out of context.
283: * hence the KSTART checks.
284: */
285:
286: int *
287: cniread(id, buf, count)
288: int id, count;
289: char *buf;
290: {
291: register struct cnbuf *cp;
292:
293: if (id < 0 || id >= NCONS || (int)buf < KSTART)
294: panic("cniread");
295: cp = &cnibuf[id];
296: cp->buf = buf;
297: cp->count = count;
298: mtpr(RXCS, mfpr(RXCS)|RXCS_IE);
299: return (&cp->count);
300: }
301:
302: int *
303: cniwrite(id, buf, count)
304: int id, count;
305: char *buf;
306: {
307: register struct cnbuf *cp;
308:
309: if (id < 0 || id >= NCONS || (int)buf < KSTART)
310: panic("cniwrite");
311: cp = &cnobuf[id];
312: cp->buf = buf;
313: cp->count = count;
314: cnstart();
315: return (&cp->count);
316: }
317:
318: cniwait(p, t)
319: register int *p;
320: int t;
321: {
322: register int s;
323: register int sh;
324:
325: s = spl6();
326: while (*p)
327: if (tsleep((caddr_t)p, CONPRI, t) != TS_OK) {
328: sh = *p;
329: *p = 0;
330: splx(s);
331: return (sh);
332: }
333: splx(s);
334: return (0);
335: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.