|
|
1.1 root 1: /*
2: * DZ-11 Driver
3: */
4:
5: /* Modified 4/84 by J. Wolitzky to allow dialout operation with smart modems */
6:
7: #define TRC(c)
8:
9: #include "sys/param.h"
10: #include "sys/stream.h"
11: #include "sys/ttyio.h"
12: #include "sys/ttyld.h"
13: #include "sys/ubaddr.h"
14: #include "sys/dz.h"
15: #include "sys/conf.h"
16:
17: #define LPB 8 /* lines per board */
18: #define BOARD(d) ((d)>>3)
19: #define LINE(d) ((d)&07)
20:
21: #define BITS7 020
22: #define BITS8 030
23: #define TWOSB 040
24: #define PENABLE 0100
25: #define OPAR 0200
26: #define CLR 020 /* Clear */
27: #define MSE 040 /* Master Scan Enable */
28: #define RIE 0100 /* Receiver Interrupt Enable */
29: #define SAE 010000 /* Silo Alarm Enable */
30: #define TIE 040000 /* Transmit Interrupt Enable */
31: #define TRDY 0100000 /* Transmitter ready */
32: #define DZ_IEN (MSE+RIE+TIE)
33: #define PERROR 010000
34: #define FRERROR 020000
35: #define OVERRUN 040000
36: #define SSPEED B1200 /* std speed = 1200 baud */
37:
38: #define ISOPEN 02
39: #define WOPEN 04
40: #define TIMEOUT 010
41: #define CARR_ON 020
42: #define DZSTOP 040
43: #define HPCL 0100
44: #define BRKING 0200
45: #define DIALOUT 0400 /* set when used as dialout with smart modems */
46:
47: #define DZPRI 30
48:
49: struct device {
50: short dzcsr;
51: short dzrbuf;
52: #define dzlpr dzrbuf
53: char dztcr;
54: char dzdtr;
55: char dztbuf;
56: #define dzrind dztbuf
57: char dzbrk;
58: #define dzmsr dzbrk
59: };
60:
61: extern struct dz dz[]; /* one per line */
62: extern struct ubaddr dzaddr[]; /* one per board */
63: extern int dzcnt; /* number of lines */
64: int dzoverrun;
65:
66: char dz_speeds[] = {
67: 0, 020, 021, 022, 023, 024, 0, 025,
68: 026, 027, 030, 032, 034, 036, 037, 0
69: };
70:
71: long dzopen();
72: int dzclose(), dzoput();
73:
74: static struct qinit dzrinit = { noput, NULL, dzopen, dzclose, 0, 0 };
75: struct qinit dzwinit = { dzoput, NULL, dzopen, dzclose, 200, 100 };
76: struct streamtab dzinfo = { &dzrinit, &dzwinit };
77: struct cdevsw dzcdev = cstrinit(&dzinfo);
78:
79: int dzmiss;
80:
81: long
82: dzopen(q, d)
83: register struct queue *q;
84: dev_t d;
85: {
86: register dev;
87: register struct dz *dzp;
88: register int s;
89: static int onceinit = 0;
90:
91: dev = minor(d);
92: if (dev >= dzcnt)
93: return(0);
94: dzp = &dz[dev];
95: if ((dzp->addr = (struct device *)ubaddr(&dzaddr[BOARD(dev)])) == NULL
96: || ubbadaddr(dzaddr[BOARD(dev)].ubno, dzp->addr, sizeof(short))) {
97: printf("dz%d absent\n", BOARD(dev));
98: return (0);
99: }
100: dz[BOARD(dev)*LPB].addr = dzp->addr; /* see intr code */
101: if (onceinit == 0) {
102: onceinit++;
103: dzscan((caddr_t)0);
104: }
105: dzp->board = BOARD(dev);
106: dzp->line = LINE(dev);
107: q->ptr = (caddr_t)dzp;
108: WR(q)->ptr = (caddr_t)dzp;
109: dzscan((caddr_t)1); /* update CARR_ON */
110: if ((dzp->state&ISOPEN)==0 || (dzp->state&CARR_ON)==0) {
111: s = spl5();
112: for (;;) {
113: dzp->flags = F8BIT|ODDP|EVENP;
114: dzp->speed = SSPEED;
115: dzparam(dzp);
116: if (dzp->state & CARR_ON)
117: break;
118: #if NOTDEF
119: dzflag = dzboard[BOARD(dev)]->ui_flags;
120: /* ignore carrier? */
121: if (dzflag & (1 << (LINE(dev)))) {
122: dzp->state |= (DIALOUT | CARR_ON);
123: break;
124: }
125: #endif
126: if (tsleep((caddr_t)dzp, DZPRI, 0) != TS_OK) {
127: wakeup((caddr_t)dzp);
128: dzp->speed = 0;
129: dzparam(dzp);
130: splx(s);
131: return(0);
132: }
133: }
134: dzp->rdq = q;
135: dzp->state |= ISOPEN;
136: splx(s);
137: }
138: TRC('o');
139: return(1);
140: }
141:
142: dzclose(q)
143: register struct queue *q;
144: {
145: register struct dz *dzp;
146: register s;
147:
148: dzp = (struct dz *)q->ptr;
149: s = spl5();
150: if (dzp->oblock) {
151: register struct block *bp = dzp->oblock;
152: dzp->oblock = NULL;
153: freeb(bp);
154: }
155: flushq(WR(q), 1);
156: dzp->rdq = NULL;
157: if (dzp->state&HPCL || (dzp->state&CARR_ON)==0) {
158: dzp->speed = 0;
159: dzparam(dzp);
160: }
161: dzp->state = 0;
162: splx(s);
163: TRC('c');
164: }
165:
166: /*
167: * DZ write put routine
168: */
169: dzoput(q, bp)
170: register struct queue *q;
171: register struct block *bp;
172: {
173: register struct dz *dzp = (struct dz *)q->ptr;
174: register s;
175: register struct ttydevb *tb;
176: register delaytime;
177:
178: TRC('p');
179: switch(bp->type) {
180:
181: case M_IOCTL:
182: TRC('i');
183: switch (stiocom(bp)) {
184:
185: case TIOCSDEV:
186: tb = (struct ttydevb *)stiodata(bp);
187: delaytime = 0;
188: if (dzp->speed != tb->ispeed)
189: delaytime = 20;
190: dzp->speed = tb->ispeed;
191: dzp->flags = tb->flags;
192: bp->type = M_IOCACK;
193: bp->wptr = bp->rptr;
194: qreply(q, bp);
195: qpctl1(q, M_DELAY, delaytime); /* wait a bit */
196: qpctl(q, M_CTL); /* means do dzparam */
197: dzstart(dzp);
198: return;
199:
200: case TIOCGDEV:
201: tb = (struct ttydevb *)stiodata(bp);
202: tb->ispeed = tb->ospeed = dzp->speed;
203: tb->flags = dzp->flags;
204: bp->wptr = bp->rptr + sizeof(struct ttydevb) + STIOCHDR;
205: bp->type = M_IOCACK;
206: qreply(q, bp);
207: return;
208:
209: case TIOCHPCL:
210: dzp->state |= HPCL;
211: bp->type = M_IOCACK;
212: bp->wptr = bp->rptr;
213: qreply(q, bp);
214: return;
215:
216: default:
217: bp->wptr = bp->rptr;
218: bp->type = M_IOCNAK;
219: qreply(q, bp);
220: return;
221: }
222:
223: case M_STOP:
224: s = spl5();
225: dzp->state |= DZSTOP;
226: freeb(bp);
227: if (bp = dzp->oblock) {
228: dzp->oblock = NULL;
229: putbq(q, bp);
230: }
231: splx(s);
232: return;
233:
234: case M_START:
235: dzp->state &= ~DZSTOP;
236: dzstart(dzp);
237: break;
238:
239: case M_FLUSH:
240: flushq(q, 1);
241: freeb(bp);
242: s = spl5();
243: if (bp = dzp->oblock) {
244: dzp->oblock = NULL;
245: freeb(bp);
246: }
247: splx(s);
248: return;
249:
250: case M_BREAK:
251: qpctl1(q, M_DELAY, 10);
252: putq(q, bp);
253: qpctl1(q, M_DELAY, 10);
254: dzstart(dzp);
255: return;
256:
257: case M_HANGUP:
258: dzp->state &= ~DZSTOP;
259: case M_DELAY:
260: case M_DATA:
261: putq(q, bp);
262: TRC('d');
263: dzstart(dzp);
264: return;
265:
266: default: /* not handled; just toss */
267: break;
268: }
269: freeb(bp);
270: }
271:
272: /*
273: * Receive interrupt. Argument is DZ board number
274: */
275: dz0int(dev)
276: {
277: register struct dz *dzp;
278: register struct block *bp;
279: register struct device *dzaddr;
280: register int c;
281:
282: if (dev >= BOARD(dzcnt)) {
283: printf("dz%d bad rcv int\n", dev);
284: return;
285: }
286: dzaddr = dz[dev*LPB].addr;
287: while ((c = dzaddr->dzrbuf) < 0) { /* char present */
288: dzp = &dz[dev*LPB + ((c>>8)&07)];
289: if (c&(OVERRUN/*|PERROR*/)) {
290: if (c&OVERRUN)
291: dzoverrun++;
292: continue;
293: }
294: if (dzp->rdq == NULL)
295: continue;
296: if (dzp->rdq->next->flag&QFULL) {
297: dzmiss++;
298: continue;
299: }
300: if ((bp = allocb(16)) == NULL)
301: continue; /* no space */
302: if (c&FRERROR) /* frame err (break) */
303: bp->type = M_BREAK;
304: else
305: *bp->wptr++ = c;
306: (*dzp->rdq->next->qinfo->putp)(dzp->rdq->next, bp);
307: }
308: }
309:
310: /*
311: * set device parameters
312: */
313: dzparam(dzp)
314: register struct dz *dzp;
315: {
316: register short lpr;
317: register struct device *dzaddr;
318:
319: dzaddr = dzp->addr;
320: dzaddr->dzcsr = DZ_IEN;
321: if (dzp->speed == 0) {
322: dzaddr->dzdtr &= ~(1 << dzp->line); /* hang up */
323: return;
324: }
325: dzaddr->dzdtr |= 1 << dzp->line;
326: lpr = (dz_speeds[dzp->speed]<<8) | dzp->line;
327: if (dzp->flags & F8BIT)
328: lpr |= BITS8;
329: else
330: lpr |= (BITS7|PENABLE);
331: if ((dzp->flags & EVENP) == 0)
332: lpr |= OPAR;
333: if (dzp->speed == 3)
334: lpr |= TWOSB; /* 110 baud: 2 stop bits */
335: dzaddr->dzlpr = lpr;
336: }
337:
338: /*
339: * Transmitter interrupt. dev is board number.
340: */
341: dz1int(dev)
342: {
343: register struct device *dzaddr;
344: register struct dz *dzp;
345: register struct block *bp;
346: register sts;
347:
348: if (dev >= BOARD(dzcnt)) {
349: printf("dz%d bad xmt int\n", dev);
350: return;
351: }
352: dzaddr = dz[dev*LPB].addr;
353: while ((sts = dzaddr->dzcsr) & TRDY) {
354: dzp = &dz[dev*LPB + ((sts>>8)&07)];
355: if (bp = dzp->oblock) {
356: if (bp->rptr < bp->wptr) {
357: dzaddr->dztbuf = *bp->rptr++;
358: continue;
359: }
360: freeb(bp);
361: dzp->oblock = NULL;
362: }
363: dzaddr->dztcr &= ~(1 << (dzp->line));
364: dzstart(dzp);
365: }
366: }
367:
368: dztimo(dzp)
369: register struct dz *dzp;
370: {
371: if (dzp->state&BRKING) {
372: dzp->brking &= ~(1 << dzp->line);
373: dzp->addr->dzbrk = dzp->brking;
374: }
375: dzp->state &= ~(TIMEOUT|BRKING);
376: dzstart(dzp);
377: }
378:
379: dzstart(dzp)
380: register struct dz *dzp;
381: {
382: register s = spl5();
383: register struct block *bp;
384: register struct device *dzaddr;
385:
386: TRC('s');
387: again:
388: if (dzp->state & (TIMEOUT|DZSTOP|BRKING) || dzp->oblock) {
389: TRC('t');
390: goto out;
391: }
392: if (dzp->rdq == NULL)
393: goto out;
394: if ((bp = getq(WR(dzp->rdq))) == NULL) {
395: TRC('n');
396: goto out;
397: }
398: switch (bp->type) {
399:
400: case M_DATA:
401: dzp->oblock = bp;
402: dzaddr = dzp->addr;
403: dzaddr->dztcr |= 1 << (dzp->line);
404: break;
405:
406: case M_BREAK:
407: dzaddr = dzp->addr;
408: dzp->brking |= 1 << dzp->line;
409: dzaddr->dzbrk = dzp->brking;
410: dzp->state |= BRKING|TIMEOUT;
411: timeout(dztimo, (caddr_t)dzp, HZ/4); /* about 250 ms */
412: freeb(bp);
413: break;
414:
415: case M_DELAY:
416: dzp->state |= TIMEOUT;
417: timeout(dztimo, (caddr_t)dzp, (int)*bp->rptr + 6);
418: freeb(bp);
419: break;
420:
421: case M_HANGUP:
422: dzp->speed = 0;
423: case M_CTL:
424: freeb(bp);
425: dzparam(dzp);
426: goto again;
427:
428: }
429: out:
430: splx(s);
431: }
432:
433: dzscan(timo)
434: caddr_t timo;
435: {
436: register struct device *dzaddr;
437: register struct dz *dzp;
438: register i;
439:
440: for (i=0, dzp=dz; i<dzcnt; dzp++, i++) {
441: if (dzp->addr == 0)
442: continue;
443: dzaddr = dzp->addr;
444: if (dzaddr->dzmsr & (1<<dzp->line)) {
445: /* carrier present */
446: if ((dzp->state & CARR_ON)==0)
447: wakeup((caddr_t)dzp);
448: dzp->state |= CARR_ON;
449: } else if ((dzp->state & CARR_ON) && !(dzp->state & DIALOUT)) {
450: /* carrier lost */
451: if (dzp->state&ISOPEN) {
452: dzaddr->dzdtr &= ~(1<<dzp->line);
453: if (dzp->rdq)
454: putctl(dzp->rdq->next,M_HANGUP);
455: }
456: dzp->state &= ~CARR_ON;
457: }
458: }
459: if (timo == 0)
460: timeout(dzscan, (caddr_t)0, 2*HZ);
461: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.