|
|
1.1 ! root 1: /* dh.c 4.3 11/13/80 */ ! 2: ! 3: #include "../conf/dh.h" ! 4: #if NDH11 > 0 ! 5: /* ! 6: * DH-11 driver ! 7: * ! 8: * Loaded with dhdm if there are DM-11's otherwise with dhfdm. ! 9: * ! 10: * NB: WE HAVEN'T TESTED dhdm CODE ON VAX. ! 11: */ ! 12: ! 13: #include "../h/param.h" ! 14: #include "../h/conf.h" ! 15: #include "../h/dir.h" ! 16: #include "../h/user.h" ! 17: #include "../h/tty.h" ! 18: #include "../h/map.h" ! 19: #include "../h/pte.h" ! 20: #include "../h/uba.h" ! 21: #include "../h/bk.h" ! 22: #include "../h/clist.h" ! 23: #include "../h/mx.h" ! 24: ! 25: /* ! 26: * When running dz's using only SAE (silo alarm) on input ! 27: * it is necessary to call dzrint() at clock interrupt time. ! 28: * This is unsafe unless spl5()s in tty code are changed to ! 29: * spl6()s to block clock interrupts. Note that the dh driver ! 30: * currently in use works the same way as the dz, even though ! 31: * we could try to more intelligently manage its silo. ! 32: * Thus don't take this out if you have no dz's unless you ! 33: * change clock.c and dhtimer(). ! 34: */ ! 35: #define spl5 spl6 ! 36: ! 37: #define UBACVT(x) (cbase + (short)((x)-(char *)cfree)) ! 38: ! 39: struct tty dh11[NDH11]; ! 40: int dhact; ! 41: int dhisilo; ! 42: int ndh11 = NDH11; ! 43: int dhstart(); ! 44: int ttrstrt(); ! 45: int dh_ubinfo; ! 46: int cbase; ! 47: int getcbase; ! 48: ! 49: /* ! 50: * Hardware control bits ! 51: */ ! 52: #define BITS6 01 ! 53: #define BITS7 02 ! 54: #define BITS8 03 ! 55: #define TWOSB 04 ! 56: #define PENABLE 020 ! 57: /* DEC manuals incorrectly say this bit causes generation of even parity. */ ! 58: #define OPAR 040 ! 59: #define HDUPLX 040000 ! 60: ! 61: #define IENAB 030100 ! 62: #define NXM 02000 ! 63: #define CLRNXM 0400 ! 64: #define PERROR 010000 ! 65: #define FRERROR 020000 ! 66: #define OVERRUN 040000 ! 67: #define XINT 0100000 ! 68: #define SSPEED 7 /* standard speed: 300 baud */ ! 69: ! 70: /* ! 71: * DM control bits ! 72: */ ! 73: #define TURNON 03 /* CD lead + line enable */ ! 74: #define TURNOFF 01 /* line enable */ ! 75: #define DTR 02 /* data terminal ready */ ! 76: #define RQS 04 /* request to send */ ! 77: ! 78: /* ! 79: * Software copy of last dhbar ! 80: */ ! 81: short dhsar[(NDH11+15)/16]; ! 82: ! 83: struct device ! 84: { ! 85: union { ! 86: short dhcsr; ! 87: char dhcsrl; ! 88: } un; ! 89: short dhnxch; ! 90: short dhlpr; ! 91: unsigned short dhcar; ! 92: short dhbcr; ! 93: unsigned short dhbar; ! 94: short dhbreak; ! 95: short dhsilo; ! 96: }; ! 97: ! 98: /* ! 99: * Open a DH11 line. ! 100: */ ! 101: /*ARGSUSED*/ ! 102: dhopen(dev, flag) ! 103: { ! 104: register struct tty *tp; ! 105: register d; ! 106: register struct device *addr; ! 107: int s; ! 108: ! 109: d = minor(dev) & 0177; ! 110: if (d >= NDH11) { ! 111: u.u_error = ENXIO; ! 112: return; ! 113: } ! 114: tp = &dh11[d]; ! 115: addr = DHADDR; ! 116: addr += d>>4; ! 117: tp->t_addr = (caddr_t)addr; ! 118: tp->t_oproc = dhstart; ! 119: tp->t_iproc = NULL; ! 120: tp->t_state |= WOPEN; ! 121: s = spl6(); ! 122: if (!getcbase) { ! 123: getcbase++; ! 124: /* 512+ is a kludge to try to get around a hardware problem */ ! 125: dh_ubinfo = uballoc((caddr_t)cfree, 512+NCLIST*sizeof(struct cblock), 0); ! 126: cbase = (short)dh_ubinfo; ! 127: } ! 128: splx(s); ! 129: addr->un.dhcsr |= IENAB; ! 130: dhact |= (1<<(d>>4)); ! 131: if ((tp->t_state&ISOPEN) == 0) { ! 132: ttychars(tp); ! 133: if (tp->t_ispeed == 0) { ! 134: tp->t_ispeed = SSPEED; ! 135: tp->t_ospeed = SSPEED; ! 136: tp->t_flags = ODDP|EVENP|ECHO; ! 137: } ! 138: dhparam(d); ! 139: } ! 140: if (tp->t_state&XCLUDE && u.u_uid!=0) { ! 141: u.u_error = EBUSY; ! 142: return; ! 143: } ! 144: dmopen(dev); ! 145: (*linesw[tp->t_line].l_open)(dev,tp); ! 146: } ! 147: ! 148: /* ! 149: * Close a DH11 line. ! 150: */ ! 151: /*ARGSUSED*/ ! 152: dhclose(dev, flag) ! 153: dev_t dev; ! 154: int flag; ! 155: { ! 156: register struct tty *tp; ! 157: register d; ! 158: ! 159: d = minor(dev) & 0177; ! 160: tp = &dh11[d]; ! 161: (*linesw[tp->t_line].l_close)(tp); ! 162: if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0) ! 163: dmctl(d, TURNOFF, DMSET); ! 164: ttyclose(tp); ! 165: } ! 166: ! 167: /* ! 168: * Read from a DH11 line. ! 169: */ ! 170: dhread(dev) ! 171: { ! 172: register struct tty *tp; ! 173: ! 174: tp = &dh11[minor(dev) & 0177]; ! 175: (*linesw[tp->t_line].l_read)(tp); ! 176: } ! 177: ! 178: /* ! 179: * write on a DH11 line ! 180: */ ! 181: dhwrite(dev) ! 182: { ! 183: register struct tty *tp; ! 184: ! 185: tp = &dh11[minor(dev) & 0177]; ! 186: (*linesw[tp->t_line].l_write)(tp); ! 187: } ! 188: ! 189: /* ! 190: * DH11 receiver interrupt. ! 191: */ ! 192: dhrint(dev) ! 193: { ! 194: register struct tty *tp; ! 195: register short c; ! 196: register struct device *addr; ! 197: register struct tty *tp0; ! 198: int s; ! 199: ! 200: s = spl6(); /* see comment in clock.c */ ! 201: addr = DHADDR; ! 202: addr += minor(dev) & 0177; ! 203: tp0 = &dh11[((minor(dev)&0177)<<4)]; ! 204: while ((c = addr->dhnxch) < 0) { /* char. present */ ! 205: tp = tp0 + ((c>>8)&017); ! 206: if (tp >= &dh11[NDH11]) ! 207: continue; ! 208: if((tp->t_state&ISOPEN)==0) { ! 209: wakeup((caddr_t)tp); ! 210: continue; ! 211: } ! 212: if (c&PERROR) ! 213: if ((tp->t_flags&(EVENP|ODDP))==EVENP ! 214: || (tp->t_flags&(EVENP|ODDP))==ODDP ) ! 215: continue; ! 216: if (c&OVERRUN) ! 217: printf("O"); ! 218: if (c&FRERROR) /* break */ ! 219: if (tp->t_flags&RAW) ! 220: c = 0; /* null (for getty) */ ! 221: else ! 222: #ifdef IIASA ! 223: continue; ! 224: #else ! 225: c = tun.t_intrc; ! 226: #endif ! 227: if (tp->t_line == NETLDISC) { ! 228: c &= 0177; ! 229: BKINPUT(c, tp); ! 230: } else ! 231: (*linesw[tp->t_line].l_rint)(c,tp); ! 232: } ! 233: splx(s); ! 234: } ! 235: ! 236: /* ! 237: * stty/gtty for DH11 ! 238: */ ! 239: /*ARGSUSED*/ ! 240: dhioctl(dev, cmd, addr, flag) ! 241: caddr_t addr; ! 242: { ! 243: register struct tty *tp; ! 244: ! 245: tp = &dh11[minor(dev) & 0177]; ! 246: cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); ! 247: if (cmd==0) ! 248: return; ! 249: if (ttioctl(cmd, tp, addr, dev, flag)) { ! 250: if (cmd==TIOCSETP||cmd==TIOCSETN) ! 251: dhparam(dev); ! 252: } else switch(cmd) { ! 253: case TIOCSBRK: ! 254: ((struct device *)(tp->t_addr))->dhbreak |= 1<<(minor(dev)&017); ! 255: break; ! 256: case TIOCCBRK: ! 257: ((struct device *)(tp->t_addr))->dhbreak &= ~(1<<(minor(dev)&017)); ! 258: break; ! 259: case TIOCSDTR: ! 260: dmctl(minor(dev), DTR|RQS, DMBIS); ! 261: break; ! 262: case TIOCCDTR: ! 263: dmctl(minor(dev), DTR|RQS, DMBIC); ! 264: break; ! 265: default: ! 266: u.u_error = ENOTTY; ! 267: } ! 268: } ! 269: ! 270: /* ! 271: * Set parameters from open or stty into the DH hardware ! 272: * registers. ! 273: */ ! 274: dhparam(dev) ! 275: { ! 276: register struct tty *tp; ! 277: register struct device *addr; ! 278: register d; ! 279: int s; ! 280: ! 281: d = minor(dev) & 0177; ! 282: tp = &dh11[d]; ! 283: addr = (struct device *)tp->t_addr; ! 284: s = spl5(); ! 285: addr->un.dhcsrl = (d&017) | IENAB; ! 286: /* ! 287: * Hang up line? ! 288: */ ! 289: if ((tp->t_ispeed)==0) { ! 290: tp->t_state |= HUPCLS; ! 291: dmctl(d, TURNOFF, DMSET); ! 292: return; ! 293: } ! 294: d = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6); ! 295: if ((tp->t_ispeed) == 4) /* 134.5 baud */ ! 296: d |= BITS6|PENABLE|HDUPLX; ! 297: else if (tp->t_flags&RAW) ! 298: d |= BITS8; ! 299: else ! 300: d |= BITS7|PENABLE; ! 301: if ((tp->t_flags&EVENP) == 0) ! 302: d |= OPAR; ! 303: if ((tp->t_ospeed) == 3) /* 110 baud */ ! 304: d |= TWOSB; ! 305: addr->dhlpr = d; ! 306: splx(s); ! 307: } ! 308: ! 309: /* ! 310: * DH11 transmitter interrupt. ! 311: * Restart each line which used to be active but has ! 312: * terminated transmission since the last interrupt. ! 313: */ ! 314: dhxint(dev) ! 315: { ! 316: register struct tty *tp; ! 317: register struct device *addr; ! 318: register d; ! 319: short ttybit, bar, *sbar; ! 320: int s; ! 321: ! 322: s = spl6(); /* block the clock */ ! 323: d = minor(dev) & 0177; ! 324: addr = DHADDR + d; ! 325: addr->un.dhcsr &= (short)~XINT; ! 326: if (addr->un.dhcsr & NXM) { ! 327: addr->un.dhcsr |= CLRNXM; ! 328: printf("dh clr NXM\n"); ! 329: } ! 330: sbar = &dhsar[d]; ! 331: bar = *sbar & ~addr->dhbar; ! 332: d <<= 4; ttybit = 1; ! 333: ! 334: for(; bar; d++, ttybit <<= 1) { ! 335: if(bar&ttybit) { ! 336: *sbar &= ~ttybit; ! 337: bar &= ~ttybit; ! 338: tp = &dh11[d]; ! 339: tp->t_state &= ~BUSY; ! 340: if (tp->t_state&FLUSH) ! 341: tp->t_state &= ~FLUSH; ! 342: else { ! 343: addr->un.dhcsrl = (d&017)|IENAB; ! 344: ndflush(&tp->t_outq, ! 345: (int)(short)addr->dhcar-UBACVT(tp->t_outq.c_cf)); ! 346: } ! 347: if (tp->t_line) ! 348: (*linesw[tp->t_line].l_start)(tp); ! 349: else ! 350: dhstart(tp); ! 351: } ! 352: } ! 353: splx(s); ! 354: } ! 355: ! 356: /* ! 357: * Start (restart) transmission on the given DH11 line. ! 358: */ ! 359: dhstart(tp) ! 360: register struct tty *tp; ! 361: { ! 362: register struct device *addr; ! 363: register short nch; ! 364: int s, d; ! 365: ! 366: /* ! 367: * If it's currently active, or delaying, ! 368: * no need to do anything. ! 369: */ ! 370: s = spl5(); ! 371: d = tp-dh11; ! 372: addr = (struct device *)tp->t_addr; ! 373: if (tp->t_state&(TIMEOUT|BUSY|TTSTOP)) ! 374: goto out; ! 375: ! 376: /* ! 377: * If the writer was sleeping on output overflow, ! 378: * wake him when low tide is reached. ! 379: */ ! 380: if (tp->t_state&ASLEEP && tp->t_outq.c_cc<=TTLOWAT(tp)) { ! 381: tp->t_state &= ~ASLEEP; ! 382: if (tp->t_chan) ! 383: mcstart(tp->t_chan, (caddr_t)&tp->t_outq); ! 384: else ! 385: wakeup((caddr_t)&tp->t_outq); ! 386: } ! 387: ! 388: if (tp->t_outq.c_cc == 0) ! 389: goto out; ! 390: ! 391: /* ! 392: * Find number of characters to transfer. ! 393: */ ! 394: if (tp->t_flags & RAW) { ! 395: nch = ndqb(&tp->t_outq, 0); ! 396: } else { ! 397: nch = ndqb(&tp->t_outq, 0200); ! 398: if (nch == 0) { ! 399: nch = getc(&tp->t_outq); ! 400: timeout(ttrstrt, (caddr_t)tp, (nch&0177)+6); ! 401: tp->t_state |= TIMEOUT; ! 402: goto out; ! 403: } ! 404: } ! 405: /* ! 406: * If any characters were set up, start transmission; ! 407: */ ! 408: if (nch) { ! 409: addr->un.dhcsrl = (d&017)|IENAB; ! 410: addr->dhcar = UBACVT(tp->t_outq.c_cf); ! 411: addr->dhbcr = -nch; ! 412: nch = 1<<(d&017); ! 413: addr->dhbar |= nch; ! 414: dhsar[d>>4] |= nch; ! 415: tp->t_state |= BUSY; ! 416: } ! 417: out: ! 418: splx(s); ! 419: } ! 420: ! 421: /* ! 422: * Stop output on a line. ! 423: * Assume call is made at spl6. ! 424: */ ! 425: /*ARGSUSED*/ ! 426: dhstop(tp, flag) ! 427: register struct tty *tp; ! 428: { ! 429: register struct device *addr; ! 430: register d, s; ! 431: ! 432: addr = (struct device *)tp->t_addr; ! 433: s = spl6(); ! 434: if (tp->t_state & BUSY) { ! 435: d = minor(tp->t_dev); ! 436: addr->un.dhcsrl = (d&017) | IENAB; ! 437: if ((tp->t_state&TTSTOP)==0) ! 438: tp->t_state |= FLUSH; ! 439: addr->dhbcr = -1; ! 440: } ! 441: splx(s); ! 442: } ! 443: ! 444: int dhsilo = 16; ! 445: /* ! 446: * Silo control is fixed strategy ! 447: * here, paralleling only option available ! 448: * on DZ-11. ! 449: */ ! 450: /*ARGSUSED*/ ! 451: dhtimer() ! 452: { ! 453: register d; ! 454: register struct device *addr; ! 455: ! 456: addr = DHADDR; d = 0; ! 457: do { ! 458: if (dhact & (1<<d)) { ! 459: if ((dhisilo & (1<<d)) == 0) { ! 460: addr->dhsilo = dhsilo; ! 461: dhisilo |= 1<<d; ! 462: } ! 463: dhrint(d); ! 464: } ! 465: d++; ! 466: addr++; ! 467: } while (d < (NDH11+15)/16); ! 468: } ! 469: ! 470: /* ! 471: * Reset state of driver if UBA reset was necessary. ! 472: * Reset the csrl and lpr registers on open lines, and ! 473: * restart transmitters. ! 474: */ ! 475: dhreset() ! 476: { ! 477: int d; ! 478: register struct tty *tp; ! 479: register struct device *addr; ! 480: ! 481: if (getcbase == 0) ! 482: return; ! 483: printf(" dh"); ! 484: dhisilo = 0; ! 485: ubafree(dh_ubinfo); ! 486: dh_ubinfo = uballoc((caddr_t)cfree, NCLIST*sizeof (struct cblock), 0); ! 487: cbase = (short)dh_ubinfo; ! 488: d = 0; ! 489: do { ! 490: addr = DHADDR + d; ! 491: if (dhact & (1<<d)) ! 492: addr->un.dhcsr |= IENAB; ! 493: d++; ! 494: } while (d < (NDH11+15)/16); ! 495: for (d = 0; d < NDH11; d++) { ! 496: tp = &dh11[d]; ! 497: if (tp->t_state & (ISOPEN|WOPEN)) { ! 498: dhparam(d); ! 499: dmctl(d, TURNON, DMSET); ! 500: tp->t_state &= ~BUSY; ! 501: dhstart(tp); ! 502: } ! 503: } ! 504: dhtimer(); ! 505: } ! 506: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.