|
|
1.1 ! root 1: /* dh.c 2.2 2/18/80 */ ! 2: ! 3: /* ! 4: * DH-11 driver ! 5: * This driver calls on the DHDM driver. ! 6: * If the DH has no DM11-BB, then the latter will ! 7: * be fake. To insure loading of the correct DM code, ! 8: * lib2 should have dhdm.o, dh.o and dhfdm.o in that order. ! 9: */ ! 10: ! 11: #include "../h/param.h" ! 12: #include "../h/conf.h" ! 13: #include "../h/dir.h" ! 14: #include "../h/user.h" ! 15: #include "../h/tty.h" ! 16: #include "../h/map.h" ! 17: #include "../h/pte.h" ! 18: #include "../h/uba.h" ! 19: ! 20: #define q3 tp->t_outq ! 21: #define DHADDR ((struct device *)(UBA0_DEV + 0160020)) ! 22: #define NDH11 16 /* number of lines */ ! 23: #define UBACVT(x) (cbase + (short)((x)-(char *)cfree)) ! 24: ! 25: struct cblock { ! 26: struct cblock *c_next; ! 27: char c_info[CBSIZE]; ! 28: }; ! 29: ! 30: struct tty dh11[NDH11]; ! 31: short dhcc[NDH11]; ! 32: int dhchars[(NDH11+15)/16]; ! 33: int ndh11 = NDH11; ! 34: int dhstart(); ! 35: int ttrstrt(); ! 36: int cbase; ! 37: extern struct cblock cfree[]; ! 38: ! 39: /* ! 40: * Hardware control bits ! 41: */ ! 42: #define BITS6 01 ! 43: #define BITS7 02 ! 44: #define BITS8 03 ! 45: #define TWOSB 04 ! 46: #define PENABLE 020 ! 47: /* DEC manuals incorrectly say this bit causes generation of even parity. */ ! 48: #define OPAR 040 ! 49: #define HDUPLX 040000 ! 50: ! 51: #define IENAB 030100 ! 52: #define PERROR 010000 ! 53: #define FRERROR 020000 ! 54: #define OVERRUN 040000 ! 55: #define XINT 0100000 ! 56: #define SSPEED 7 /* standard speed: 300 baud */ ! 57: #define NSILO 16 ! 58: #define DHTIME 6 ! 59: extern int dhtimer(); ! 60: ! 61: /* ! 62: * DM control bits ! 63: */ ! 64: #define TURNON 03 /* CD lead + line enable */ ! 65: #define TURNOFF 01 /* line enable */ ! 66: #define RQS 04 /* request to send */ ! 67: ! 68: /* ! 69: * Software copy of last dhbar ! 70: */ ! 71: short dhsar[(NDH11+15)/16]; ! 72: ! 73: struct device ! 74: { ! 75: union { ! 76: short dhcsr; ! 77: char dhcsrl; ! 78: } un; ! 79: short dhnxch; ! 80: short dhlpr; ! 81: unsigned short dhcar; ! 82: short dhbcr; ! 83: unsigned short dhbar; ! 84: short dhbreak; ! 85: short dhsilo; ! 86: }; ! 87: ! 88: /* ! 89: * Open a DH11 line. ! 90: */ ! 91: dhopen(dev, flag) ! 92: { ! 93: register struct tty *tp; ! 94: register d; ! 95: register struct device *addr; ! 96: static timer_on; ! 97: int s; ! 98: ! 99: d = minor(dev) & 0177; ! 100: if (d >= NDH11) { ! 101: u.u_error = ENXIO; ! 102: return; ! 103: } ! 104: tp = &dh11[d]; ! 105: addr = DHADDR; ! 106: addr += d>>4; ! 107: tp->t_addr = (caddr_t)addr; ! 108: tp->t_oproc = dhstart; ! 109: tp->t_iproc = NULL; ! 110: tp->t_state |= WOPEN; ! 111: s = spl6(); ! 112: if (!timer_on) { ! 113: timer_on++; ! 114: timeout(dhtimer, (caddr_t)0, DHTIME); ! 115: cbase = (short)uballoc(cfree, NCLIST*sizeof(struct cblock), 0); ! 116: } ! 117: splx(s); ! 118: addr->un.dhcsr |= IENAB; ! 119: if ((tp->t_state&ISOPEN) == 0) { ! 120: ttychars(tp); ! 121: tp->t_ispeed = SSPEED; ! 122: tp->t_ospeed = SSPEED; ! 123: tp->t_flags = ODDP|EVENP|ECHO; ! 124: dhparam(d); ! 125: } ! 126: if (tp->t_state&XCLUDE && u.u_uid!=0) { ! 127: u.u_error = EBUSY; ! 128: return; ! 129: } ! 130: dmopen(dev); ! 131: (*linesw[tp->t_line].l_open)(dev,tp); ! 132: } ! 133: ! 134: /* ! 135: * Close a DH11 line. ! 136: */ ! 137: dhclose(dev, flag) ! 138: dev_t dev; ! 139: int flag; ! 140: { ! 141: register struct tty *tp; ! 142: register d; ! 143: ! 144: d = minor(dev) & 0177; ! 145: tp = &dh11[d]; ! 146: (*linesw[tp->t_line].l_close)(tp); ! 147: if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0) ! 148: dmctl(d, TURNOFF); ! 149: ttyclose(tp); ! 150: } ! 151: ! 152: /* ! 153: * Read from a DH11 line. ! 154: */ ! 155: dhread(dev) ! 156: { ! 157: register struct tty *tp; ! 158: ! 159: tp = &dh11[minor(dev) & 0177]; ! 160: (*linesw[tp->t_line].l_read)(tp); ! 161: } ! 162: ! 163: /* ! 164: * write on a DH11 line ! 165: */ ! 166: dhwrite(dev) ! 167: { ! 168: register struct tty *tp; ! 169: ! 170: tp = &dh11[minor(dev) & 0177]; ! 171: (*linesw[tp->t_line].l_write)(tp); ! 172: } ! 173: ! 174: /* ! 175: * DH11 receiver interrupt. ! 176: */ ! 177: dhrint(dev) ! 178: { ! 179: register struct tty *tp; ! 180: register short c; ! 181: register struct device *addr; ! 182: ! 183: addr = DHADDR; ! 184: addr += minor(dev) & 0177; ! 185: while ((c = addr->dhnxch) < 0) { /* char. present */ ! 186: tp = &dh11[((minor(dev)&0177)<<4) + ((c>>8)&017)]; ! 187: dhchars[minor(dev)&0177]++; ! 188: if (tp >= &dh11[NDH11]) ! 189: continue; ! 190: if((tp->t_state&ISOPEN)==0) { ! 191: wakeup((caddr_t)tp); ! 192: continue; ! 193: } ! 194: if (c&PERROR) ! 195: if ((tp->t_flags&(EVENP|ODDP))==EVENP ! 196: || (tp->t_flags&(EVENP|ODDP))==ODDP ) ! 197: continue; ! 198: if (c&OVERRUN) ! 199: printf("O"); ! 200: if (c&FRERROR) /* break */ ! 201: if (tp->t_flags&RAW) ! 202: c = 0; /* null (for getty) */ ! 203: else ! 204: c = 0177; /* DEL (intr) */ ! 205: (*linesw[tp->t_line].l_rint)(c,tp); ! 206: } ! 207: } ! 208: ! 209: /* ! 210: * stty/gtty for DH11 ! 211: */ ! 212: dhioctl(dev, cmd, addr, flag) ! 213: caddr_t addr; ! 214: { ! 215: register struct tty *tp; ! 216: ! 217: tp = &dh11[minor(dev) & 0177]; ! 218: if (ttioccomm(cmd, tp, addr, dev)) { ! 219: if (cmd==TIOCSETP||cmd==TIOCSETN) ! 220: dhparam(dev); ! 221: } else if (cmd==TIOCSBRK) { ! 222: /* send a break */ ! 223: register int linebit = 1 << (dev&017); ! 224: extern dhunbrk(); ! 225: ! 226: wflushtty(tp); ! 227: spl5(); ! 228: ((struct device *)tp->t_addr)->dhbreak |= linebit; ! 229: tp->t_state |= TIMEOUT; ! 230: timeout(dhunbrk, (caddr_t)tp, 25); /* 300-500 ms */ ! 231: while (((struct device *)tp->t_addr)->dhbreak & linebit) ! 232: sleep((caddr_t)&tp->t_rawq, TTIPRI); ! 233: tp->t_state &= ~TIMEOUT; ! 234: spl0(); ! 235: flushtty(tp); ! 236: return; ! 237: } else ! 238: u.u_error = ENOTTY; ! 239: } ! 240: ! 241: dhunbrk(tp) ! 242: register struct tty *tp; ! 243: { ! 244: ! 245: ((struct device *)tp->t_addr)->dhbreak &= ~ (1 << (minor(tp->t_dev)&017)); ! 246: wakeup((caddr_t)&tp->t_rawq); ! 247: } ! 248: ! 249: /* ! 250: * Set parameters from open or stty into the DH hardware ! 251: * registers. ! 252: */ ! 253: dhparam(dev) ! 254: { ! 255: register struct tty *tp; ! 256: register struct device *addr; ! 257: register d; ! 258: ! 259: d = minor(dev) & 0177; ! 260: tp = &dh11[d]; ! 261: addr = (struct device *)tp->t_addr; ! 262: spl5(); ! 263: addr->un.dhcsrl = (d&017) | IENAB; ! 264: /* ! 265: * Hang up line? ! 266: */ ! 267: if ((tp->t_ispeed)==0) { ! 268: tp->t_state |= HUPCLS; ! 269: dmctl(d, TURNOFF); ! 270: return; ! 271: } ! 272: d = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6); ! 273: if ((tp->t_ispeed) == 4) /* 134.5 baud */ ! 274: d |= BITS6|PENABLE|HDUPLX; ! 275: else if (tp->t_flags&RAW) ! 276: d |= BITS8; ! 277: else ! 278: d |= BITS7|PENABLE; ! 279: if ((tp->t_flags&EVENP) == 0) ! 280: d |= OPAR; ! 281: if ((tp->t_ospeed) == 3) /* 110 baud */ ! 282: d |= TWOSB; ! 283: addr->dhlpr = d; ! 284: spl0(); ! 285: } ! 286: ! 287: /* ! 288: * DH11 transmitter interrupt. ! 289: * Restart each line which used to be active but has ! 290: * terminated transmission since the last interrupt. ! 291: */ ! 292: dhxint(dev) ! 293: { ! 294: register struct tty *tp; ! 295: register struct device *addr; ! 296: register d; ! 297: short ttybit, bar, *sbar; ! 298: ! 299: d = minor(dev) & 0177; ! 300: addr = DHADDR + d; ! 301: addr->un.dhcsr &= (short)~XINT; ! 302: sbar = &dhsar[d]; ! 303: bar = *sbar & ~addr->dhbar; ! 304: d <<= 4; ttybit = 1; ! 305: ! 306: for(; bar; d++, ttybit <<= 1) { ! 307: if(bar&ttybit) { ! 308: *sbar &= ~ttybit; ! 309: bar &= ~ttybit; ! 310: tp = &dh11[d]; ! 311: if (tp->t_line) { ! 312: (*linesw[tp->t_line].l_start)(tp); ! 313: } else { ! 314: addr->un.dhcsrl = (d&017)|IENAB; ! 315: if (tp->t_state&FLUSH) ! 316: tp->t_state &= ~FLUSH; ! 317: else { ! 318: ndflush(&q3, dhcc[d]); ! 319: } ! 320: tp->t_state &= ~BUSY; ! 321: dhstart(tp); ! 322: } ! 323: } ! 324: } ! 325: } ! 326: ! 327: /* ! 328: * Start (restart) transmission on the given DH11 line. ! 329: */ ! 330: dhstart(tp) ! 331: register struct tty *tp; ! 332: { ! 333: register struct device *addr; ! 334: register short nch; ! 335: int s, d; ! 336: ! 337: /* ! 338: * If it's currently active, or delaying, ! 339: * no need to do anything. ! 340: */ ! 341: s = spl5(); ! 342: d = tp-dh11; ! 343: addr = (struct device *)tp->t_addr; ! 344: if (tp->t_state&(TIMEOUT|BUSY|TTSTOP)) ! 345: goto out; ! 346: ! 347: ! 348: /* ! 349: * If the writer was sleeping on output overflow, ! 350: * wake him when low tide is reached. ! 351: */ ! 352: if (tp->t_state&ASLEEP && tp->t_outq.c_cc<=TTLOWAT) { ! 353: tp->t_state &= ~ASLEEP; ! 354: if (tp->t_chan) ! 355: mcstart(tp->t_chan, (caddr_t)&tp->t_outq); else ! 356: wakeup((caddr_t)&tp->t_outq); ! 357: } ! 358: ! 359: if (tp->t_outq.c_cc == 0) ! 360: goto out; ! 361: ! 362: ! 363: ! 364: /* ! 365: * Find number of characters to transfer. ! 366: */ ! 367: if (tp->t_flags & RAW) { ! 368: nch = ndqb(&tp->t_outq, 0); ! 369: } else { ! 370: nch = ndqb(&tp->t_outq, 0200); ! 371: if (nch == 0) { ! 372: nch = getc(&tp->t_outq); ! 373: timeout(ttrstrt, (caddr_t)tp, (nch&0177)+6); ! 374: tp->t_state |= TIMEOUT; ! 375: goto out; ! 376: } ! 377: } ! 378: /* ! 379: * If any characters were set up, start transmission; ! 380: */ ! 381: if (nch) { ! 382: addr->un.dhcsrl = (d&017)|IENAB; ! 383: addr->dhcar = UBACVT(tp->t_outq.c_cf); ! 384: addr->dhbcr = -nch; ! 385: dhcc[d] = nch; ! 386: nch = 1<<(d&017); ! 387: addr->dhbar |= nch; ! 388: dhsar[d>>4] |= nch; ! 389: tp->t_state |= BUSY; ! 390: } ! 391: out: ! 392: splx(s); ! 393: } ! 394: ! 395: ! 396: /* ! 397: * Stop output on a line. ! 398: * Assume call is made at spl6. ! 399: */ ! 400: dhstop(tp, flag) ! 401: register struct tty *tp; ! 402: { ! 403: register struct device *addr; ! 404: register d, s; ! 405: ! 406: addr = (struct device *)tp->t_addr; ! 407: s = spl6(); ! 408: if (tp->t_state & BUSY) { ! 409: /* ! 410: d = minor(tp->t_dev); ! 411: addr->un.dhcsrl = (d&017) | IENAB; ! 412: */ ! 413: if ((tp->t_state&TTSTOP)==0) { ! 414: tp->t_state |= FLUSH; ! 415: } ! 416: /* ! 417: addr->dhbcr = -1; ! 418: */ ! 419: } ! 420: splx(s); ! 421: } ! 422: ! 423: dhtimer(dev) ! 424: { ! 425: register d,cc; ! 426: register struct device *addr; ! 427: ! 428: addr = DHADDR; d = 0; ! 429: do { ! 430: cc = dhchars[d]; ! 431: dhchars[d] = 0; ! 432: if (cc > 50) ! 433: cc = 32; else ! 434: if (cc > 16) ! 435: cc = 16; else ! 436: cc = 0; ! 437: addr->dhsilo = cc; ! 438: addr += 1; ! 439: dhrint(d++); ! 440: } while (d < (NDH11+15)/16); ! 441: timeout(dhtimer, (caddr_t)0, DHTIME); ! 442: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.