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