|
|
1.1 ! root 1: /* cons.c 4.10 81/05/09 */ ! 2: /* Tahoe version Dec 1982 */ ! 3: /* Minor device 0 is the CP itself. ! 4: /* No real read/writes can be done to him. ! 5: /* Minor 1 is the console terminal. ! 6: /* Minor 2 is the remote line trminal. ! 7: /**/ ! 8: ! 9: /* ! 10: * Tahoe console processor driver ! 11: * ! 12: */ ! 13: #include "../h/param.h" ! 14: #include "../h/conf.h" ! 15: #include "../h/dir.h" ! 16: #include "../h/ioctl.h" ! 17: #include "../h/user.h" ! 18: #include "../h/tty.h" ! 19: #include "../h/uio.h" ! 20: #include "../h/callout.h" ! 21: #include "../h/systm.h" ! 22: #include "../machine/cp.h" ! 23: #include "../machine/mtpr.h" ! 24: ! 25: #define FALSE 0 ! 26: #define TRUE 1 ! 27: ! 28: int cnrestart() ; ! 29: int timeout() ; ! 30: ! 31: struct tty cons[3]; /* One for each unit on CP */ ! 32: struct cons_info { ! 33: char last_one; /* Last char sent - possibly repeat ! 34: * If zero, timeout has nothing to do ! 35: */ ! 36: int active_timeout; /* There is an active timeout for this line ! 37: * Set by 'cnputc' when a timeout is initiated. ! 38: * Reset by the routine called at timeout. ! 39: */ ! 40: int try_later; /* If true, timeout has nothing to do. ! 41: * Set by 'cnputc' every time a char is sent. ! 42: * Reset by the timeout arrival. If next time ! 43: * the timeout comes it's zero, then it may ! 44: * have something to do. ! 45: */ ! 46: } cons_info[3]; ! 47: struct cpdcb_o consout[3] = { ! 48: /* unit, cmd,count, buf */ ! 49: {(char)(CPTAKE | CPDONE),0, 0 }, ! 50: {(char)(CPTAKE | CPDONE),0, 0 }, ! 51: {(char)(CPTAKE | CPDONE),0, 0 } ! 52: }; ! 53: struct cpdcb_i consin[3] = { ! 54: /* unit, cmd,count, buf */ ! 55: {(char)(CPTAKE | CPDONE),0, 0 }, ! 56: {(char)(CPTAKE | CPDONE),0, 0 }, ! 57: {(char)(CPTAKE | CPDONE),0, 0 } ! 58: }; ! 59: struct cphdr *lasthdr; ! 60: ! 61: int cnstart(); ! 62: int ttrstrt(); ! 63: char partab[]; ! 64: ! 65: cnopen(dev, flag) ! 66: dev_t dev; ! 67: { ! 68: register struct cpdcb_i *cin; ! 69: register struct tty *tp; ! 70: register int timo; ! 71: ! 72: if (minor(dev) > CPREMOT) ! 73: return EEXIST; ! 74: tp = &cons[minor(dev)]; ! 75: if (tp->t_state&TS_XCLUDE && u.u_uid != 0) ! 76: return EBUSY; ! 77: if (lasthdr != (struct cphdr *)0) { ! 78: timo = 10000; ! 79: uncache((char *)&lasthdr->cp_unit); ! 80: while ((lasthdr->cp_unit & CPTAKE)==0 && --timo ) ! 81: uncache((char *)&lasthdr->cp_unit); ! 82: } /* Here we give up waiting */ ! 83: cin = &consin[minor(dev)]; ! 84: cin->cp_hdr.cp_unit = (char)(minor(dev)); ! 85: cin->cp_hdr.cp_comm = (char)CPREAD; ! 86: cin->cp_hdr.cp_count = 1; /* Get ready for input */ ! 87: mtpr (cin, CPMDCB); ! 88: lasthdr = (struct cphdr *)cin; ! 89: tp->t_oproc = cnstart; ! 90: tp->t_dev = dev; ! 91: if ((tp->t_state&TS_ISOPEN) == 0) { ! 92: ttychars(tp); ! 93: tp->t_state = TS_ISOPEN|TS_CARR_ON; ! 94: tp->t_flags = EVENP|ECHO|XTABS|CRMOD; ! 95: } ! 96: (*linesw[tp->t_line].l_open)(dev, tp); ! 97: } ! 98: ! 99: cnclose(dev) ! 100: dev_t dev; ! 101: { ! 102: register struct tty *tp = &cons[minor(dev)]; ! 103: ! 104: (*linesw[tp->t_line].l_close)(tp); ! 105: ttyclose(tp); ! 106: } ! 107: ! 108: /*ARGSUSED*/ ! 109: cnread(dev, uio) ! 110: dev_t dev; ! 111: struct uio *uio; ! 112: { ! 113: register struct tty *tp = &cons[minor(dev)]; ! 114: ! 115: return ((*linesw[tp->t_line].l_read)(tp, uio)); ! 116: } ! 117: ! 118: /*ARGSUSED*/ ! 119: cnwrite(dev, uio) ! 120: dev_t dev; ! 121: struct uio *uio; ! 122: { ! 123: register struct tty *tp = &cons[minor(dev)]; ! 124: ! 125: return ((*linesw[tp->t_line].l_write)(tp, uio)); ! 126: } ! 127: ! 128: /* ! 129: * Got a console receive interrupt - ! 130: * the console processor wants to give us a character. ! 131: * Catch the character, and see who it goes to. ! 132: */ ! 133: cnrint(dev) ! 134: dev_t dev; ! 135: { ! 136: register int c, timo; ! 137: register struct tty *tp; ! 138: ! 139: if (intenable == 0) return; ! 140: /* make sure we dont take it from cache */ ! 141: uncache((char *)&consin[minor(dev)].cpi_buf[0]); ! 142: c = consin[minor(dev)].cpi_buf[0]; ! 143: /* ! 144: /* Wait about 5 milli for last CPMDCB to be read by CP, ! 145: /* otherwise give up ! 146: /**/ ! 147: timo = 10000; ! 148: uncache((char *)&lasthdr->cp_unit); ! 149: while ((lasthdr->cp_unit & CPTAKE)==0 && --timo ) ! 150: uncache((char *)&lasthdr->cp_unit); ! 151: uncache((char *)&lasthdr->cp_unit); ! 152: if (lasthdr->cp_unit & CPTAKE) ! 153: { ! 154: consin[minor(dev)].cp_hdr.cp_unit = (char)(minor(dev)); ! 155: /* This resets status bits */ ! 156: mtpr (&consin[minor(dev)], CPMDCB); /* Ready for new character */ ! 157: lasthdr = (struct cphdr *)&consin[minor(dev)]; ! 158: tp = &cons[minor(dev)]; ! 159: (*linesw[tp->t_line].l_rint)(c, tp); ! 160: } ! 161: } ! 162: ! 163: cnioctl(dev, cmd, addr, flag) ! 164: dev_t dev; ! 165: caddr_t addr; ! 166: { ! 167: register struct tty *tp = &cons[minor(dev)]; ! 168: register error; ! 169: ! 170: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); ! 171: if (error >= 0) ! 172: return error; ! 173: if ((error = ttioctl(tp, cmd, addr, flag)) < 0) ! 174: error = ENOTTY; ! 175: else if(cmd==TIOCSETP || cmd==TIOCSETN) ! 176: cnparams(tp); ! 177: return error; ! 178: } ! 179: ! 180: int consintr = 1; ! 181: /* ! 182: * Got a console transmission interrupt - ! 183: * the console processor wants another character. ! 184: */ ! 185: cnxint(dev) ! 186: dev_t dev; ! 187: { ! 188: register struct tty *tp; ! 189: register int line_no; ! 190: ! 191: if (intenable == 0 || consintr == 0) return; ! 192: #ifdef CPPERF ! 193: if (minor(dev)==CPCONS) scope_in(1); ! 194: else scope_in(2); ! 195: #endif ! 196: line_no = minor(dev); ! 197: tp = &cons[line_no]; ! 198: tp->t_state &= ~TS_BUSY; ! 199: cons_info[line_no].last_one = (char)0; ! 200: if (tp->t_line) ! 201: (*linesw[tp->t_line].l_start)(tp); ! 202: else ! 203: cnstart(tp); ! 204: } ! 205: ! 206: cnstart(tp) ! 207: register struct tty *tp; ! 208: { ! 209: register c; ! 210: register s; ! 211: ! 212: #ifdef CPPERF ! 213: if (minor(tp->t_dev)==CPCONS) scope_in(3); ! 214: else scope_in(4); ! 215: #endif ! 216: s = spl8(); ! 217: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) ! 218: goto out; ! 219: if (tp->t_outq.c_cc <= TTLOWAT(tp)) { ! 220: if (tp->t_state&TS_ASLEEP) { ! 221: tp->t_state &= ~TS_ASLEEP; ! 222: wakeup((caddr_t)&tp->t_outq); ! 223: } ! 224: if (tp->t_wsel) { ! 225: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); ! 226: tp->t_wsel = 0; ! 227: tp->t_state &= ~TS_WCOLL; ! 228: } ! 229: } ! 230: if (tp->t_outq.c_cc == 0) ! 231: goto out; ! 232: c = getc(&tp->t_outq) & 0xff; ! 233: if (tp->t_flags&(RAW|LITOUT)) ! 234: cnputc(c,tp); ! 235: else if (c<=0177) ! 236: cnputc ((c | (partab[c]&0200))&0xff,tp); ! 237: else { ! 238: timeout(ttrstrt, (caddr_t)tp, (c&0177)); ! 239: tp->t_state |= TS_TIMEOUT; ! 240: goto out; ! 241: } ! 242: tp->t_state |= TS_BUSY; ! 243: out: ! 244: splx(s); ! 245: } ! 246: ! 247: /* ! 248: * Print a character on console. ! 249: */ ! 250: cnputc(c,tp) ! 251: register char c; ! 252: register struct tty *tp; ! 253: { ! 254: register timo , line_no, s; ! 255: register struct cpdcb_o *current; ! 256: ! 257: /* tp == 0 only in system error messages */ ! 258: if (tp == 0) { ! 259: current = &consout[CPCONS]; ! 260: line_no = CPCONS; ! 261: if(lasthdr == 0) /* not done anythig yet */ ! 262: lasthdr = (struct cphdr *)current; ! 263: c |= partab[c&0177]&0200; ! 264: } ! 265: else { ! 266: current = &consout[minor(tp->t_dev)]; ! 267: line_no = minor(tp->t_dev); ! 268: } ! 269: timo = 30000; ! 270: /* ! 271: * Try waiting for the console tty to come ready, ! 272: * otherwise give up after a reasonable time. ! 273: * make sure we dont test this bit in cache! ! 274: */ ! 275: uncache((char *)¤t->cp_hdr.cp_unit); ! 276: while ((current->cp_hdr.cp_unit & CPDONE) == 0 && --timo ) ! 277: uncache((char *)¤t->cp_hdr.cp_unit); ! 278: current->cp_hdr.cp_comm = (char)CPWRITE; ! 279: current->cp_hdr.cp_count = 1; ! 280: current->cp_buf[0] = (char)(c & 0xff); ! 281: timo = 10000; ! 282: /* ! 283: * Try waiting for the console tty to come ready, ! 284: * otherwise give up after a reasonable time. ! 285: */ ! 286: uncache((char *)&lasthdr->cp_unit); ! 287: while ((lasthdr->cp_unit & CPTAKE)==0 && --timo ) ! 288: uncache((char *)&lasthdr->cp_unit); ! 289: /* Reset done bit */ ! 290: current->cp_hdr.cp_unit = (char)line_no; ! 291: lasthdr = (struct cphdr *)current; ! 292: #ifdef CPPERF ! 293: if (intenable != 0) scope_in(5); ! 294: #endif ! 295: cons_info[line_no].last_one = c; ! 296: if ( !cons_info[line_no].active_timeout && clk_enable) { ! 297: cons_info[line_no].active_timeout = TRUE; ! 298: timeout (cnrestart, (caddr_t)tp, 10); ! 299: } ! 300: cons_info[line_no].try_later = TRUE; /* For timeout-means wait some more */ ! 301: mtpr (current, CPMDCB); ! 302: } ! 303: ! 304: /* ! 305: * Restart (if necessary) transfer to CP line. ! 306: * This way, lost 'transmit' interrupts don't break the chain. ! 307: */ ! 308: cnrestart (tp) ! 309: struct tty *tp; ! 310: { ! 311: register line_no, s; ! 312: ! 313: if (tp == 0) { ! 314: line_no = CPCONS; ! 315: } else ! 316: line_no = minor(tp->t_dev); ! 317: if (cons_info[line_no].try_later) { ! 318: cons_info[line_no].try_later = FALSE; ! 319: timeout (cnrestart, (caddr_t)tp, 10); ! 320: } ! 321: else { ! 322: cons_info[line_no].active_timeout = FALSE; ! 323: if (cons_info[line_no].last_one != (char)0) ! 324: cnputc (cons_info[line_no].last_one, tp); ! 325: } ! 326: } ! 327: ! 328: /* ! 329: * Set line parameters ! 330: */ ! 331: cnparams(tp) ! 332: register struct tty *tp; ! 333: { ! 334: register timo ; ! 335: register struct cpdcb_o *current; ! 336: register struct cpdcb_i *cin; ! 337: ! 338: current = &consout[minor(tp->t_dev)]; ! 339: timo = 30000; ! 340: /* ! 341: * Try waiting for the console tty to come ready, ! 342: * otherwise give up after a reasonable time. ! 343: * make sure we dont test this bit in cache! ! 344: */ ! 345: uncache((char *)¤t->cp_hdr.cp_unit); ! 346: while ((current->cp_hdr.cp_unit & CPDONE) == 0 && --timo ) ! 347: uncache((char *)¤t->cp_hdr.cp_unit); ! 348: current->cp_hdr.cp_comm = (char)CPSTTY; ! 349: current->cp_hdr.cp_count = 4; ! 350: current->cp_buf[0] = tp->t_ispeed; ! 351: /* the rest are defaults */ ! 352: current->cp_buf[1] = 0; /* no parity */ ! 353: current->cp_buf[2] = 0; /* stop bits */ ! 354: current->cp_buf[3] = 8; /* data bits */ ! 355: timo = 10000; ! 356: /* ! 357: * Try waiting for the console tty to come ready, ! 358: * otherwise give up after a reasonable time. ! 359: */ ! 360: uncache((char *)&lasthdr->cp_unit); ! 361: while ((lasthdr->cp_unit & CPTAKE)==0 && --timo ) ! 362: uncache((char *)&lasthdr->cp_unit); ! 363: /* Reset done bit */ ! 364: current->cp_hdr.cp_unit = (char)minor(tp->t_dev); ! 365: lasthdr = (struct cphdr *)current; ! 366: mtpr (current, CPMDCB); ! 367: ! 368: timo = 10000; ! 369: uncache((char *)&lasthdr->cp_unit); ! 370: while ((lasthdr->cp_unit & CPTAKE)==0 && --timo ) ! 371: uncache((char *)&lasthdr->cp_unit); ! 372: cin = &consin[minor(tp->t_dev)]; ! 373: cin->cp_hdr.cp_unit = (char)(minor(tp->t_dev)); ! 374: cin->cp_hdr.cp_comm = (char)CPREAD; ! 375: cin->cp_hdr.cp_count = 1; /* Get ready for input */ ! 376: mtpr (cin, CPMDCB); ! 377: lasthdr = (struct cphdr *)cin; ! 378: ! 379: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.