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