|
|
1.1 root 1: /*
2: * DZ-11 driver
3: * ------------
4: *
5: * Written to handle single dz - `carrier'|`ring' support non-existent
6: *
7: * Piers Lauder
8: * SYDNEY UNIVERSITY
9: * July 1977
10: *
11: * Re-written to handle multiple dz's and `carrier'|`ring'.
12: *
13: * Ian Johnstone
14: * UNSW
15: * December 1977
16: * January 1978
17: *
18: * General tidy up, new comments etc. Removal of ifdefs
19: * for CARRIER and RING. If you don't want them, tough.
20: *
21: * Chris Maltby
22: * Basser October 1979
23: */
24:
25:
26: /* ( no messages )
27: #define MESSAGES
28: /*
29: * Define this if you want parity and framing errors
30: * to be logged (via printf). It can be very wordy.
31: */
32:
33: #define INTR_ON_BREAK
34: /*
35: * Define this to translate framing errors (breaks)
36: * to CINTR for terminals which lack a DEL key.
37: * Can be nasty if you get lots of line errors.
38: */
39:
40: /* (not DEBUG)
41: #define DEBUG
42: /*
43: * Define to debug info for dialup lines.
44: * costs approximately 128 bytes
45: */
46:
47: #include "../defines.h"
48: #include "../param.h"
49: #ifdef DEBUG
50: #ifdef AUSAML
51: #include "../lnode.h"
52: #endif AUSAML
53: #include "../systm.h"
54: #endif DEBUG
55: #include "../conf.h"
56: #include "../user.h"
57: #include "../tty.h"
58: #include "../proc.h"
59:
60:
61: #define NDZ 2 /* number of DZ-11s */
62: #define NLINES 8*NDZ /* total number of lines */
63: #define TSCANRATE 2 /* dzscan called every 2 tics */
64: /* Must be >= 2 always */
65:
66: #define RESPONDTIME (25*HZ) /* Carrier must be raised inside this */
67: #define CARRIERTIME (1*HZ) /* Carrier must drop for this before hangup */
68:
69: #define FLUSHTIME 5 /* time required to allow hardware buffered
70: * characters to flush before setting speed */
71:
72: #define SSPEED 12 /* standard speed 4800 bd */
73:
74: struct dz /* one for each dz-11 */
75: {
76: int *dzaddr; /* dz device address */
77: char sopen; /* bit set for single open lines */
78: char carrier; /* bits set for carrier controlled lines */
79: char ring; /* bits set for lines with dial in modems */
80: char active; /* bits set for active dialup lines */
81: char openl; /* bits set for open lines */
82: unsigned pyerrors; /* count of of parity errors on input */
83: unsigned overrors; /* count of of overrun errors on input */
84: }
85: dz[NDZ]
86: {
87: /* dzaddr sopen carr ring */
88: { 0160040, 0002, 0077, 0074 },
89: { 0160050, 0000, 0000, 0000 }
90: };
91: int dzscanning; /* set when scanning for input and modem change */
92:
93: /*
94: * DZ11 register layout
95: */
96:
97: struct dzr_read
98: {
99: int dzcsr; /* r/w */
100: int dzrbuf; /* no bit, byte, or tst ops */
101: char dztcr; /* r/w */
102: char dzdtr; /* r/w */
103: char dzring;
104: char dzcarr;
105: };
106:
107: struct dzr_write
108: {
109: int dzcsr; /* r/w */
110: int dzlpr; /* no bit or byte ops */
111: char dztcr; /* r/w */
112: char dzdtr; /* r/w */
113: char dztbuf; /* no bit ops */
114: char dzbrk; /* no bit ops */
115: };
116:
117: /*
118: * register control bits
119: */
120: #define TRDY 0100000 /* dzcsr */
121: #define TIE 040000
122: #define SA 020000
123: #define SAE 010000
124: #define TLINE 03400
125: #define RDONE 0200
126: #define RIE 0100
127: #define MSE 040
128: #define CLR 020
129:
130: #define RCVR_ON 010000 /* dzlpr */
131: #define S9600 07000
132: #define S300 02400
133: #define S134_5 01400
134: #define S110 01000
135: #define ODD_PAR 0300
136: #define EVN_PAR 0100
137: #define TWOSBIT 040
138: #define C8BIT 030
139: #define C7BIT 020
140: #define C6BIT 010
141: /*
142: #define IBM2741 RCVR_ON|S134_5|ODD_PAR|C6BIT /* if you must */
143:
144: #define RERROR 070000 /* dzrbuf */
145: #define OVR_RUN 040000
146: #define FRAME 020000
147: #define PARITY 010000
148: #define LINE_NO 03400
149:
150: /*
151: * table to map UNIX standard speeds to DZ11 speeds
152: * illegal speeds are ignored.
153: */
154: char dzspeedmap[16]
155: {
156: 0 /* 0 - zero */
157: , 020 /* 1 - 50 */
158: , 021 /* 2 - 75 */
159: , 022 /* 3 - 110 */
160: , 023 /* 4 - 134.5 */
161: , 024 /* 5 - 150 */
162: ,0200 /* 6 - 200 -- ## ILLEGAL ## */
163: , 025 /* 7 - 300 */
164: , 026 /* 8 - 600 */
165: , 027 /* 9 - 1200 */
166: , 030 /* 10 - 1800 */
167: , 032 /* 11 - 2400 */
168: , 034 /* 12 - 4800 */
169: , 036 /* 13 - 9600 */
170: , 031 /* 14 - ext A - maps to 2000 */
171: , 037 /* 15 - ext B - maps to 19200 */
172: };
173:
174:
175:
176: struct tty dz11[NLINES];
177:
178: char dzdelays[NLINES]; /* Count of clock ticks for per-line
179: * delays. Count of <= 0 means no delay.
180: * Reduces requirement of timeouts.
181: */
182:
183: int dzringt[NLINES]; /* Delay counts for modem control */
184:
185: /*
186: * open a DZ11 line
187: */
188: dzopen(dev, flag)
189: {
190: register struct tty *tp;
191: register struct dz *dzp;
192: register int t_bit;
193: extern dzstart(), dzscan();
194:
195:
196: if(dev.d_minor >= NLINES)
197: {
198: u.u_error = ENXIO;
199: return;
200: }
201: dzp = &dz[dev.d_minor>>3];
202: t_bit = (1<<(dev.d_minor&07));
203: if((dzp->sopen&t_bit) && (dzp->openl&t_bit))
204: {
205: u.u_error = EOPENFAIL;
206: return;
207: }
208: tp = &dz11[dev.d_minor];
209: if(u.u_procp->p_ttyp == 0)
210: u.u_procp->p_ttyp = tp;
211: if((tp->t_state&ISOPEN) == 0)
212: {
213: tp->t_dev = dev;
214: tp->t_addr = &dzstart;
215: tp->t_speeds = SSPEED|(SSPEED<<8);
216: tp->t_flags = ODDP|EVENP|XTABS|RAW;
217: tp->t_erase = CERASE;
218: tp->t_kill = CKILL;
219: if(dzp->openl == 0)
220: dzp->dzaddr->dzcsr =| (TIE|RIE|SAE|MSE); /* reciever interrupt every 16 chars */
221: dzp->openl =| t_bit;
222: spl5();
223: if(dzscanning == 0)
224: dzscan(); /* start scanning */
225: if(!(dzp->ring&t_bit) && !(dzp->carrier&t_bit))
226: dzp->dzaddr->dzdtr =| t_bit; /* turn on DTR for non-dialup lines */
227: else
228: {
229: # ifdef DEBUG
230: printf("%d wo%d\n", time.loint, dev.d_minor);
231: # endif DEBUG
232: while(!(dzp->dzaddr->dzcarr&t_bit))
233: {
234: tp->t_state =| WOPEN;
235: sleep(&tp->t_rawq, TTIPRI);
236: }
237: # ifdef DEBUG
238: printf("%d op%d\n", time.loint, dev.d_minor);
239: # endif DEBUG
240: }
241: spl0();
242: tp->t_state = (ISOPEN|CARR_ON|SSTART);
243: dzparam(tp, 1);
244: }
245: }
246:
247:
248: /*
249: * scan open lines for:
250: * 1. modem status changes
251: * 2. process timeouts as dictated by dzdelays
252: * 3. input by calling dzrint
253: */
254: dzscan() /* at spl5 */
255: {
256: register struct dz *dzp;
257: struct tty *tp;
258: int *p;
259: extern dzstart(), dzrint(), dzscan();
260: # define openring (dzp->openl & dzp->ring)
261: # define opencarrier (dzp->openl & dzp->carrier)
262:
263: /*
264: * scan open dialup/carrier lines.
265: */
266: tp = &dz11[0];
267: p = &dzringt[0];
268: for(dzp = dz; dzp < &dz[NDZ]; dzp++)
269: {
270: register int *dzaddr;
271: char scanl, scanc;
272:
273: dzaddr = dzp->dzaddr;
274: if((scanl = openring) | (scanc = opencarrier))
275: {
276: register int t_bit;
277:
278: for(t_bit = 1; t_bit&0377; t_bit =<< 1, tp++, p++)
279: {
280: if(scanl&t_bit)
281: {
282: /* this is an open `dialup' line */
283: if(dzp->active&t_bit)
284: {
285: if(!(dzaddr->dzcarr&t_bit))
286: {
287: if(*p == 0)
288: *p = CARRIERTIME;
289: else if((*p =- TSCANRATE) <= 0)
290: {
291: *p = 0; /* disable */
292: # ifdef DEBUG
293: printf("%d hu%d\n", time.loint, tp->t_dev.d_minor);
294: # endif DEBUG
295: dzaddr->dzdtr =& ~t_bit; /* hang up the phone */
296: signal(tp, SIGHUP);
297: flushtty(tp);
298: dzaddr->dztcr =& ~t_bit; /* disable transmit */
299: dzp->active =& ~t_bit;
300: }
301: }
302: else
303: {
304: if(tp->t_state&WOPEN)
305: wakeup(&tp->t_rawq);
306: *p = 0;
307: if(!(tp->t_state&TIMEOUT) && (tp->t_outq.c_cc))
308: dzaddr->dztcr =| t_bit;
309: }
310: }
311: else
312: {
313: if(!(dzaddr->dzdtr&t_bit) && (dzaddr->dzring&t_bit))
314: {
315: dzaddr->dzdtr =| t_bit; /* answer the phone */
316: *p = RESPONDTIME;
317: dzp->active =| t_bit;
318: # ifdef DEBUG
319: printf("%d ap%d\n", time.loint, tp->t_dev.d_minor);
320: # endif DEBUG
321: }
322: }
323: }
324: else if((scanc&t_bit) && (dzaddr->dzcarr&t_bit))
325: { /* carrier only line */
326: if(tp->t_state&WOPEN)
327: {
328: dzaddr->dzdtr =| t_bit;
329: wakeup(&tp->t_rawq);
330: }
331: else if((!(tp->t_state&TIMEOUT)) && (tp->t_outq.c_cc))
332: dzaddr->dztcr =| t_bit;
333: }
334: }
335: }
336: else
337: {
338: tp =+ 8; p =+ 8; /* in the case where no dialup/carrier lines on current dz */
339: }
340: }
341:
342: /*
343: * process timeouts for each line
344: */
345:
346: {
347: register i;
348:
349: for(i = 0; i < NLINES; i++)
350: if((dzdelays[i] > 0) && (--dzdelays[i] <= 0))
351: {
352: dz11[i].t_state =& ~TIMEOUT;
353: dzstart(&dz11[i]);
354: }
355: }
356:
357: /*
358: * scan each dz for input
359: */
360:
361: dzrint(0);
362:
363: /*
364: * restart scanning if necessary
365: */
366:
367: dzp = dz;
368: do
369: {
370: if(dzp->openl)
371: {
372: dzscanning = timeout(&dzscan, 0, TSCANRATE);
373: return;
374: }
375: dzp++;
376: } while(dzp < &dz[NDZ]);
377: dzscanning = 0;
378: }
379:
380: /*
381: * close a DZ11 line
382: */
383: dzclose(dev)
384: {
385: register struct tty *tp;
386: register t_bit;
387: register struct dz *dzp;
388:
389: tp = &dz11[dev.d_minor];
390: wflushtty(tp);
391: tp->t_state = SSTART;
392: dzp = &dz[dev.d_minor>>3];
393: t_bit = 1<<(dev.d_minor&07);
394: if(dzp->ring&t_bit)
395: {
396: if(tp->t_flags&HUPCL)
397: dzp->dzaddr->dzdtr =& ~t_bit; /* hang up the phone */
398: }
399: else
400: {
401: dzp->dzaddr->dzdtr =& ~t_bit; /* turn off dtr for non-dialup lines */
402: }
403: if((dzp->openl =& ~t_bit) == 0)
404: dzp->dzaddr->dzcsr = 0; /* disable receive on final close */
405: }
406:
407:
408:
409: /*
410: * read from a DZ11 line
411: */
412: dzread(dev)
413: {
414: ttread(&dz11[dev.d_minor]);
415: }
416:
417:
418:
419: /*
420: * write on a DZ11 line
421: */
422: dzwrite(dev)
423: {
424: ttwrite(&dz11[dev.d_minor]);
425: }
426:
427:
428:
429: /*
430: * stty/gtty for DZ11
431: */
432: dzsgtty(dev, av)
433: int *av;
434: {
435: register struct tty *tp;
436:
437: if((av == 0) && (dzspeedmap[u.u_arg[0]&017] < 0))
438: {
439: u.u_error = ENXIO; /* illegal speed */
440: return;
441: }
442: tp = &dz11[dev.d_minor];
443: if(ttystty(tp, av))
444: return;
445: dzparam(tp, 1);
446: }
447:
448:
449:
450: /*
451: * set parameters from open or stty into DZ hardware registers
452: */
453: dzparam(tp, dflag)
454: register struct tty *tp;
455: {
456: register lpr, x;
457: extern wakeup();
458:
459:
460: lpr = dzspeedmap[tp->t_speeds&017]<<8;
461:
462: #ifdef IBM2741
463: if(lpr == (RCVR_ON|S134_5))
464: lpr = IBM2741;
465: else
466: {
467: #endif IBM2741
468: if(lpr == (RCVR_ON|S110))
469: lpr =| TWOSBIT;
470:
471: if((x = tp->t_flags)&EVENP)
472: if((x&ODDP) == 0)
473: lpr =| (EVN_PAR|C7BIT);
474: else
475: lpr =| C8BIT;
476: else if(x&ODDP)
477: lpr =| (ODD_PAR|C7BIT);
478: else
479: lpr =| C8BIT;
480: #ifdef IBM2741
481: }
482: #endif IBM2741
483:
484: if(dflag)
485: {
486: /* delay only if it is permissible */
487: #ifndef DELAY
488: timeout(&wakeup, tp, FLUSHTIME); /* wakeup in 5 tics */
489: sleep(tp, TTOPRI); /* delay while controller flushes */
490: #else
491: delay(FLUSHTIME); /* hang 5 */
492: #endif DELAY
493: }
494:
495: dz[tp->t_dev.d_minor>>3].dzaddr->dzlpr = lpr|(tp->t_dev.d_minor&07);
496: }
497:
498:
499:
500: /*
501: * start (restart) transmission on a DZ11 line
502: */
503: dzstart(tp)
504: register struct tty *tp;
505: {
506: register t_bit;
507: register struct dz *dzp;
508:
509:
510: t_bit = 1<<(tp->t_dev.d_minor&07);
511: dzp = &dz[tp->t_dev.d_minor>>3];
512: if((!(dzp->carrier&t_bit)) || (dzp->dzaddr->dzcarr&t_bit))
513: dzp->dzaddr->dztcr =| t_bit;
514: }
515:
516:
517: /*
518: * DZ11 transmitter interrupt.
519: *
520: * Scan every line on each dz.
521: * Commencing with the device that caused
522: * dzxint to be called.
523: */
524: dzxint(dev)
525: {
526: register struct tty *tp;
527: register c;
528: register struct dzr_read *dzaddr;
529: struct dz *dzp;
530: struct tty *dzbase;
531: int t_bit, lino, i, n;
532:
533: n = dev.d_minor;
534: for(i = 0; i < NDZ; i++)
535: {
536: dzaddr = (dzp = &dz[n])->dzaddr;
537: dzbase = &dz11[n*8];
538: while((c = dzaddr->dzcsr) < 0) /* xmit line ready */
539: {
540: t_bit = 1<<(lino = (c>>8)&07);
541:
542: tp = &dzbase[lino];
543:
544: if((!(dzp->carrier&t_bit) || (dzaddr->dzcarr&t_bit)) && (c = getc(&tp->t_outq)) >= 0)
545: if(c <= 0177 || tp->t_flags == RAW)
546: dzaddr->dztbuf = c;
547: else
548: {
549: dzaddr->dztcr =& ~t_bit;
550: tp->t_state =| TIMEOUT;
551: dzdelays[tp-dz11] = ((c&0177)+(TSCANRATE-1))/TSCANRATE+1; /* set up timeout */
552: continue;
553: }
554: else
555: dzaddr->dztcr =& ~t_bit;
556:
557: #ifdef TTY_HISPEED
558: if(tp->t_outq.c_cc <= ((tp->t_speeds&017) > B1200?TTHSLOWAT:TTLOWAT) && (tp->t_state&ASLEEP))
559: #else
560: if(tp->t_outq.c_cc <= TTLOWAT && (tp->t_state&ASLEEP))
561: #endif TTY_HISPEED
562: {
563: tp->t_state =& ~ASLEEP;
564: wakeup(&tp->t_outq);
565: }
566: }
567: if(++n >= NDZ)
568: n = 0;
569: }
570: }
571:
572:
573:
574: /*
575: * DZ11 receiver interrupt
576: *
577: * Scan each dz commencing with the
578: * particular device that caused this call.
579: * Storing each charater as it comes.
580: */
581: dzrint(dev)
582: {
583: register struct tty *tp;
584: register c;
585: register struct dzr_read *dzaddr;
586: struct dz *dzp;
587: struct tty *dzbase;
588: int i, n, lino, t_bit;
589:
590: n = dev.d_minor;
591: for(i = 0; i < NDZ; i++)
592: {
593: dzp = &dz[n];
594: if(dzp->openl)
595: {
596: dzbase = &dz11[n*8];
597: while((c = dzp->dzaddr->dzrbuf) < 0) /* char present in silo */
598: {
599: tp = &dzbase[lino = ((c>>8)&07)];
600: t_bit = 1<<lino;
601: if(c&RERROR)
602: {
603: if(c&OVR_RUN)
604: {
605: dzp->overrors++;
606: # ifdef MESSAGES
607: printf("over run on dz %d/%d\n", n, lino);
608: # endif MESSAGES
609: }
610: if(c&FRAME) /* break */
611: if(tp->t_flags&RAW)
612: c = 0; /* null ( for getty ) */
613: else
614: # ifdef INTR_ON_BREAK
615: c = CINTR; /* del for NCRs. */
616: # else
617: continue; /* ignore framing errors if not raw */
618: # endif INTR_ON_BREAK
619: else if(c&PARITY)
620: {
621: dzp->pyerrors++;
622: # ifdef MESSAGES
623: printf("parity on dz %d/%d\n", n, lino);
624: # endif MESSAGES
625: continue; /* throw away bad chars */
626: }
627: }
628: if((!(dzp->carrier&t_bit)) || (dzp->dzaddr->dzcarr&t_bit))
629: ttyinput(c, tp);
630: }
631: }
632: if(++n >= NDZ)
633: n = 0;
634: }
635: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.