|
|
1.1 ! root 1: /* cons.c 7.5 90/01/17 */ ! 2: ! 3: /* ! 4: * Tahoe console processor driver ! 5: * ! 6: * Minor device 0 is the CP itself. ! 7: * No real read/writes can be done to him. ! 8: * Minor 1 is the console terminal. ! 9: * Minor 2 is the remote line trminal. ! 10: */ ! 11: #include "param.h" ! 12: #include "conf.h" ! 13: #include "ioctl.h" ! 14: #include "user.h" ! 15: #include "proc.h" ! 16: #include "tty.h" ! 17: #include "callout.h" ! 18: #include "systm.h" ! 19: #include "kernel.h" ! 20: #include "syslog.h" ! 21: ! 22: #include "../tahoe/cp.h" ! 23: #include "../tahoe/cpu.h" ! 24: #include "../tahoe/mtpr.h" ! 25: ! 26: int cnrestart(); ! 27: int timeout(); ! 28: ! 29: struct tty CPtty; ! 30: struct tty cons; ! 31: struct tty RLtty; ! 32: struct tty *cntty[3] = { &CPtty, &cons, &RLtty }; ! 33: ! 34: struct tty *constty = 0; /* virtual console */ ! 35: ! 36: struct consoftc { ! 37: char cs_flags; ! 38: #define CSF_ACTIVE 0x1 /* timeout active */ ! 39: #define CSF_POLLING 0x2 /* polling for input */ ! 40: char cs_lastc; /* last char sent */ ! 41: int cs_timo; /* timeouts since interrupt */ ! 42: u_long cs_wedgecnt; /* times restarted */ ! 43: } consoftc[3]; ! 44: ! 45: struct speedtab cnspeedtab[] = { ! 46: 9600, 13, ! 47: 4800, 12, ! 48: 2400, 11, ! 49: 1800, 10, ! 50: 1200, 9, ! 51: 600, 8, ! 52: 300, 7, ! 53: 200, 6, ! 54: 150, 5, ! 55: 134, 4, ! 56: 110, 3, ! 57: 75, 2, ! 58: 50, 1, ! 59: 0, 13, ! 60: -1, -1, ! 61: }; ! 62: ! 63: /* ! 64: * We check the console periodically to make sure ! 65: * that it hasn't wedged. Unfortunately, if an XOFF ! 66: * is typed on the console, that can't be distinguished ! 67: * from more catastrophic failure. ! 68: */ ! 69: #define CN_TIMERVAL (hz) /* frequency at which to check cons */ ! 70: #define CN_TIMO (2*60) /* intervals to allow for output char */ ! 71: ! 72: struct cpdcb_o consout[3] = { ! 73: { CPTAKE|CPDONE }, { CPTAKE|CPDONE }, { CPTAKE|CPDONE } ! 74: }; ! 75: struct cpdcb_i consin[3] = { ! 76: { CPTAKE|CPDONE }, { CPTAKE|CPDONE }, { CPTAKE|CPDONE } ! 77: }; ! 78: struct cphdr *cnlast; ! 79: ! 80: int cnstart(); ! 81: int ttrstrt(); ! 82: char partab[]; ! 83: ! 84: /* ! 85: * Wait for CP to accept last CP command sent ! 86: * before setting up next command. ! 87: */ ! 88: #define waitforlast(timo) { \ ! 89: if (cnlast) { \ ! 90: (timo) = 10000; \ ! 91: do \ ! 92: uncache((char *)&cnlast->cp_unit); \ ! 93: while ((cnlast->cp_unit&CPTAKE) == 0 && --(timo)); \ ! 94: } \ ! 95: } ! 96: ! 97: /*ARGSUSED*/ ! 98: cnopen(dev, flag) ! 99: dev_t dev; ! 100: { ! 101: register struct tty *tp; ! 102: int unit = minor(dev); ! 103: int cnparams(); ! 104: ! 105: if (unit > CPREMOT) ! 106: return (ENXIO); ! 107: tp = cntty[unit]; ! 108: if (tp->t_state&TS_XCLUDE && u.u_uid != 0) ! 109: return (EBUSY); ! 110: cnpostread(unit); /* post request for input */ ! 111: tp->t_oproc = cnstart; ! 112: tp->t_param = cnparams; ! 113: tp->t_dev = dev; ! 114: if ((tp->t_state&TS_ISOPEN) == 0) { ! 115: ttychars(tp); ! 116: tp->t_iflag = TTYDEF_IFLAG|ICRNL; ! 117: tp->t_oflag = TTYDEF_OFLAG|OPOST|ONLCR; ! 118: tp->t_lflag = TTYDEF_LFLAG; ! 119: tp->t_cflag = CS8|CREAD; ! 120: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; ! 121: tp->t_state = TS_ISOPEN|TS_CARR_ON; ! 122: cnparams(tp, &tp->t_termios); ! 123: ttsetwater(tp); ! 124: } ! 125: return ((*linesw[tp->t_line].l_open)(dev, tp)); ! 126: } ! 127: ! 128: cnpostread(unit) ! 129: int unit; ! 130: { ! 131: register struct cpdcb_i *cin; ! 132: register int timo; ! 133: ! 134: waitforlast(timo); ! 135: cin = &consin[unit]; ! 136: cin->cp_hdr.cp_unit = unit; ! 137: cin->cp_hdr.cp_comm = CPREAD; ! 138: cin->cp_hdr.cp_count = 1; /* Get ready for input */ ! 139: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)cin)); ! 140: cnlast = &cin->cp_hdr; ! 141: } ! 142: ! 143: cnclose(dev) ! 144: dev_t dev; ! 145: { ! 146: register struct tty *tp = cntty[minor(dev)]; ! 147: ! 148: (*linesw[tp->t_line].l_close)(tp); ! 149: ttyclose(tp); ! 150: } ! 151: ! 152: /*ARGSUSED*/ ! 153: cnread(dev, uio, flag) ! 154: dev_t dev; ! 155: struct uio *uio; ! 156: { ! 157: struct tty *tp = cntty[minor(dev)]; ! 158: ! 159: return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); ! 160: } ! 161: ! 162: /*ARGSUSED*/ ! 163: cnwrite(dev, uio, flag) ! 164: dev_t dev; ! 165: struct uio *uio; ! 166: { ! 167: register struct tty *tp = cntty[minor(dev)]; ! 168: ! 169: if (tp == &cons && constty && ! 170: (constty->t_state & (TS_CARR_ON | TS_ISOPEN)) == ! 171: (TS_CARR_ON | TS_ISOPEN)) ! 172: tp = constty; ! 173: return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); ! 174: } ! 175: ! 176: /* ! 177: * Got a console receive interrupt - ! 178: * the console processor wants to give us a character. ! 179: * Catch the character, and see who it goes to. ! 180: */ ! 181: cnrint(dev) ! 182: dev_t dev; ! 183: { ! 184: register int unit, timo; ! 185: register struct tty *tp; ! 186: int c; ! 187: ! 188: unit = minor(dev); ! 189: if (!intenable || consoftc[unit].cs_flags&CSF_POLLING) ! 190: return; ! 191: /* make sure we dont take it from cache */ ! 192: uncache(&consin[unit].cpi_buf[0]); ! 193: c = consin[unit].cpi_buf[0]; ! 194: waitforlast(timo); ! 195: /* This resets status bits */ ! 196: consin[unit].cp_hdr.cp_unit = unit; ! 197: /* Ready for new character */ ! 198: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)&consin[unit])); ! 199: cnlast = &consin[unit].cp_hdr; ! 200: ! 201: tp = cntty[unit]; ! 202: if ((tp->t_cflag&CSIZE) != CS8) ! 203: c &= 0177; ! 204: #ifdef KADB ! 205: if (unit == CPCONS && kdbrintr(c, tp)) ! 206: return; ! 207: #endif ! 208: (*linesw[tp->t_line].l_rint)(c & 0377, tp); ! 209: } ! 210: ! 211: cnioctl(dev, cmd, addr, flag) ! 212: dev_t dev; ! 213: caddr_t addr; ! 214: { ! 215: register struct tty *tp = cntty[minor(dev)]; ! 216: register error; ! 217: ! 218: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); ! 219: if (error >= 0) ! 220: return error; ! 221: if ((error = ttioctl(tp, cmd, addr, flag)) < 0) ! 222: error = ENOTTY; ! 223: return (error); ! 224: } ! 225: ! 226: int consintr = 1; ! 227: /* ! 228: * Got a console transmission interrupt - ! 229: * the console processor wants another character. ! 230: */ ! 231: cnxint(dev) ! 232: dev_t dev; ! 233: { ! 234: register struct tty *tp; ! 235: register int unit; ! 236: ! 237: if (!intenable || !consintr) ! 238: return; ! 239: unit = minor(dev); ! 240: #ifdef CPPERF ! 241: scope_in(unit == CPCONS ? 1 : 2); ! 242: #endif ! 243: tp = cntty[unit]; ! 244: tp->t_state &= ~TS_BUSY; ! 245: consoftc[unit].cs_timo = 0; ! 246: if (tp->t_line) ! 247: (*linesw[tp->t_line].l_start)(tp); ! 248: else ! 249: cnstart(tp); ! 250: } ! 251: ! 252: cnstart(tp) ! 253: register struct tty *tp; ! 254: { ! 255: register c, s; ! 256: ! 257: #ifdef CPPERF ! 258: scope_in(minor(tp->t_dev) == CPCONS ? 3 : 4); ! 259: #endif ! 260: s = spl8(); ! 261: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) ! 262: goto out; ! 263: if (tp->t_outq.c_cc <= tp->t_lowat) { ! 264: if (tp->t_state&TS_ASLEEP) { ! 265: tp->t_state &= ~TS_ASLEEP; ! 266: wakeup((caddr_t)&tp->t_outq); ! 267: } ! 268: if (tp->t_wsel) { ! 269: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); ! 270: tp->t_wsel = 0; ! 271: tp->t_state &= ~TS_WCOLL; ! 272: } ! 273: } ! 274: if (tp->t_outq.c_cc == 0) ! 275: goto out; ! 276: c = getc(&tp->t_outq) & 0xff; ! 277: if (tp->t_cflag&PARENB && ((tp->t_cflag&CSIZE)==CS7)) { ! 278: c &= 0177; ! 279: c |= (tp->t_cflag&PARODD ? ~partab[c] : partab[c]) & 0200; ! 280: } ! 281: cnputchar(c, tp); ! 282: tp->t_state |= TS_BUSY; ! 283: out: ! 284: splx(s); ! 285: } ! 286: ! 287: cnputc(c) ! 288: char c; ! 289: { ! 290: ! 291: if (c == '\n') ! 292: cnputchar('\r', (struct tty *)0); ! 293: cnputchar(c, (struct tty *)0); ! 294: } ! 295: ! 296: /* ! 297: * Print a character on console. ! 298: */ ! 299: cnputchar(c, tp) ! 300: char c; ! 301: register struct tty *tp; ! 302: { ! 303: register timo; ! 304: register struct cpdcb_o *current; ! 305: register struct consoftc *cs; ! 306: int unit; ! 307: ! 308: /* tp == 0 only in system error messages */ ! 309: if (tp == 0) { ! 310: tp = &cons; ! 311: tp->t_dev = CPCONS; /* may not be open */ ! 312: c |= partab[c&0177]&0200; ! 313: } ! 314: unit = minor(tp->t_dev); ! 315: current = &consout[unit]; ! 316: timo = 30000; ! 317: /* ! 318: * Try waiting for the console tty to finish previous command ! 319: * on this unit, otherwise give up after a reasonable time. ! 320: */ ! 321: do ! 322: uncache(¤t->cp_hdr.cp_unit); ! 323: while ((current->cp_hdr.cp_unit&CPDONE) == 0 && --timo); ! 324: ! 325: current->cp_hdr.cp_comm = CPWRITE; ! 326: current->cp_hdr.cp_count = 1; ! 327: current->cp_buf[0] = c; ! 328: /* ! 329: * Try waiting for the console tty ! 330: * to accept previous command. ! 331: */ ! 332: waitforlast(timo); ! 333: ! 334: /* Reset done bit */ ! 335: current->cp_hdr.cp_unit = (char)unit; ! 336: #ifdef CPPERF ! 337: if (intenable != 0) ! 338: scope_in(5); ! 339: #endif ! 340: cs = &consoftc[unit]; ! 341: cs->cs_lastc = c; ! 342: cs->cs_timo = CN_TIMO; ! 343: if ((cs->cs_flags&CSF_ACTIVE) == 0 && clk_enable) { ! 344: cs->cs_flags |= CSF_ACTIVE; ! 345: timeout(cnrestart, (caddr_t)tp, CN_TIMERVAL); ! 346: } ! 347: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current)); ! 348: cnlast = ¤t->cp_hdr; ! 349: } ! 350: ! 351: #if defined(KADB) || defined(GENERIC) ! 352: cngetc() ! 353: { ! 354: register int c, s; ! 355: ! 356: s = spl8(); /* block cnrint while we poll */ ! 357: c = cngetchar(&cons); ! 358: if (c == '\r') ! 359: c = '\n'; ! 360: splx(s); ! 361: return (c); ! 362: } ! 363: ! 364: cngetchar(tp) ! 365: register struct tty *tp; ! 366: { ! 367: register timo, unit; ! 368: register struct cpdcb_i *current; ! 369: char c; ! 370: ! 371: unit = minor(tp->t_dev); ! 372: current = &consin[unit]; ! 373: waitforlast(timo); ! 374: current->cp_hdr.cp_unit = unit; /* Resets done bit */ ! 375: current->cp_hdr.cp_comm = CPREAD; ! 376: current->cp_hdr.cp_count = 1; ! 377: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current)); ! 378: while ((current->cp_hdr.cp_unit&CPDONE) == 0) ! 379: uncache(¤t->cp_hdr.cp_unit); ! 380: uncache(¤t->cpi_buf[0]); ! 381: c = current->cpi_buf[0] & 0x7f; ! 382: cnlast = ¤t->cp_hdr; ! 383: return (c); ! 384: } ! 385: #endif ! 386: ! 387: /* ! 388: * Restart (if necessary) transfer to CP line. ! 389: * This way, lost transmit interrupts don't wedge output. ! 390: */ ! 391: cnrestart(tp) ! 392: struct tty *tp; ! 393: { ! 394: register struct consoftc *cs; ! 395: ! 396: cs = &consoftc[minor(tp->t_dev)]; ! 397: cs->cs_flags &= ~CSF_ACTIVE; ! 398: if (cs->cs_timo) { ! 399: if (--cs->cs_timo == 0) { ! 400: cs->cs_wedgecnt++; ! 401: cnreset(tp); ! 402: cnputchar(cs->cs_lastc, tp); ! 403: } else { ! 404: cs->cs_flags |= CSF_ACTIVE; ! 405: timeout(cnrestart, (caddr_t)tp, CN_TIMERVAL); ! 406: } ! 407: } ! 408: } ! 409: ! 410: /* ! 411: * Reset console. ! 412: */ ! 413: cnreset(tp) ! 414: register struct tty *tp; ! 415: { ! 416: register timo; ! 417: register struct cpdcb_o *current; ! 418: register unit; ! 419: static int failed; ! 420: ! 421: unit = minor(tp->t_dev); ! 422: current = &consout[unit]; ! 423: current->cp_hdr.cp_comm = CPRESET; ! 424: current->cp_hdr.cp_count = 0; ! 425: current->cp_hdr.cp_unit = unit; ! 426: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current)); ! 427: cnlast = ¤t->cp_hdr; ! 428: timo = 10000; ! 429: do ! 430: uncache(¤t->cp_hdr.cp_unit); ! 431: while ((current->cp_hdr.cp_unit&CPTAKE) == 0 && --timo); ! 432: if (current->cp_hdr.cp_unit & CPTAKE) { ! 433: cnparams(tp, &tp->t_termios); ! 434: failed = 0; ! 435: } else if (failed++ == 0) ! 436: log(LOG_ERR, "Console wedged, reset failed.\n"); ! 437: } ! 438: ! 439: /* ! 440: * Set line parameters ! 441: */ ! 442: cnparams(tp, t) ! 443: register struct tty *tp; ! 444: register struct termios *t; ! 445: { ! 446: register timo = 30000; ! 447: int unit = minor(tp->t_dev); ! 448: register struct cpdcb_o *current = &consout[unit]; ! 449: register cflag = t->c_cflag; ! 450: int speedcode, csize; ! 451: ! 452: if (((speedcode == ttspeedtab(t->c_ospeed, cnspeedtab)) < 0) || ! 453: (t->c_ispeed && t->c_ispeed != t->c_ospeed) || ! 454: ((csize = (cflag&CSIZE)) != CS7 && csize != CS8)) ! 455: return (EINVAL); ! 456: /*XXX*/return (0); ! 457: /* ! 458: * Try waiting for the console tty to finish any output, ! 459: * otherwise give up after a reasonable time. ! 460: */ ! 461: do ! 462: uncache(¤t->cp_hdr.cp_unit); ! 463: while ((current->cp_hdr.cp_unit&CPDONE) == 0 && --timo); ! 464: current->cp_hdr.cp_comm = CPSTTY; ! 465: current->cp_hdr.cp_count = 4; ! 466: current->cp_buf[0] = speedcode; ! 467: #ifdef notyet ! 468: /* parity */ ! 469: current->cp_buf[1] = (cflag&PARENB) ? ((cflag&PARODD) ? 2 : 1) : 0; ! 470: /* stop bits */ ! 471: current->cp_buf[2] = (cflag&CSTOPB) ? 2 : 0; ! 472: /* data bits */ ! 473: current->cp_buf[3] = (csize==CS8) ? 8 : 7; ! 474: #else ! 475: current->cp_buf[1] = 0; /* no parity */ ! 476: current->cp_buf[2] = 0; /* stop bits */ ! 477: current->cp_buf[3] = 8; /* data bits */ ! 478: #endif ! 479: ! 480: /* Reset done bit */ ! 481: current->cp_hdr.cp_unit = unit; ! 482: ! 483: waitforlast(timo); ! 484: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current)); ! 485: cnlast = ¤t->cp_hdr; ! 486: cnpostread(unit); ! 487: return (0); ! 488: } ! 489: ! 490: #ifdef KADB ! 491: /* ! 492: * Turn input polling on/off (used by debugger). ! 493: */ ! 494: cnpoll(onoff) ! 495: int onoff; ! 496: { ! 497: ! 498: if (!onoff) { ! 499: consoftc[CPCONS].cs_flags &= ~CSF_POLLING; ! 500: cnpostread(CPCONS); /* restart input */ ! 501: } else ! 502: consoftc[CPCONS].cs_flags |= CSF_POLLING; ! 503: } ! 504: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.