8100: # / * general TTY subroutines */
8101:
8102: #include "../param.h"
8103: #include "../systm.h"
8104: #include "../user.h"
8105: #include "../tty.h"
8106: #include "../proc.h"
8107: #include "../inode.h"
8108: #include "../file.h"
8109: #include "../reg.h"
8110: #include "../conf.h"
8111:
8112: /* Input mapping table-- if an entry is non-zero, when the
8113: * corresponding character is typed preceded by "\" the escape
8114: * sequence is replaced by the table value. Mostly used for
8115: * upper-case only terminals.
8116: */
8117: char maptab[]
8118: {
8119: 000,000,000,000,004,000,000,000,
8120: 000,000,000,000,000,000,000,000,
8121: 000,000,000,000,000,000,000,000,
8122: 000,000,000,000,000,000,000,000,
8123: 000,'|',000,'#',000,000,000,'`',
8124: '{','}',000,000,000,000,000,000,
8125: 000,000,000,000,000,000,000,000,
8126: 000,000,000,000,000,000,000,000,
8127: '@',000,000,000,000,000,000,000,
8128: 000,000,000,000,000,000,000,000,
8129: 000,000,000,000,000,000,000,000,
8130: 000,000,000,000,000,000,'~',000,
8131: 000,'A','B','C','D','E','F','G',
8132: 'H','I','J','K','L','M','N','O',
8133: 'P','Q','R','S','T','U','V','W',
8134: 'X','Y','Z',000,000,000,000,000,
8135: };
8136: /* --------------------------- */
8137: /* The actual structure of a clist block manipulated by
8138: * getc and putc (mch.s)
8139: */
8140: struct cblock {
8141: struct cblock *c_next;
8142: char info[6];
8143: };
8144: /* --------------------------- */
8145: /* The character lists-- space for 6*NCLIST characters */
8146: struct cblock cfree[NCLIST];
8147: /* List head for unused character blocks. */
8148: struct cblock *cfreelist;
8149:
8150: /* structure of device registers for KL, DL, and DC
8151: * interfaces-- more particularly, those for which the
8152: * SSTART bit is off and can be treated by general routines
8153: * (that is, not DH).
8154: */
8155: struct {
8156: int ttrcsr;
8157: int ttrbuf;
8158: int tttcsr;
8159: int tttbuf;
8160: };
8161: /* --------------------------- */
8162: /* The routine implementing the gtty system call.
8163: * Just call lower level routine and pass back values.
8164: */
8165: gtty()
8166: {
8167: int v[3];
8168: register *up, *vp;
8169:
8170: vp = v;
8171: sgtty(vp);
8172: if (u.u_error)
8173: return;
8174: up = u.u_arg[0];
8175: suword(up, *vp++);
8176: suword(++up, *vp++);
8177: suword(++up, *vp++);
8178: }
8179: /* --------------------------- */
8180: /* The routine implementing the stty system call.
8181: * Read in values and call lower level.
8182: */
8183: stty()
8184: {
8185: register int *up;
8186:
8187: up = u.u_arg[0];
8188: u.u_arg[0] = fuword(up);
8189: u.u_arg[1] = fuword(++up);
8190: u.u_arg[2] = fuword(++up);
8191: sgtty(0);
8192: }
8193: /* --------------------------- */
8194: /* Stuff common to stty and gtty.
8195: * Check legality and switch out to individual
8196: * device routine.
8197: * v is 0 for stty; the parameters are taken from u.u_arg[].
8198: * c is non-zero for gtty and is the place in which the device
8199: * routines place their information.
8200: */
8201: sgtty(v)
8202: int *v;
8203: {
8204: register struct file *fp;
8205: register struct inode *ip;
8206: if ((fp = getf(u.u_ar0[R0])) == NULL)
8207: return;
8208: ip = fp->f_inode;
8209: if ((ip->i_mode&IFMT) != IFCHR) {
8210: u.u_error = ENOTTY;
8211: return;
8212: }
8213: (*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v);
8214: }
8215: /* --------------------------- */
8216: /* Wait for output to drain, then flush input waiting. */
8217: wflushtty(atp)
8218: struct tty *atp;
8219: {
8220: register struct tty *tp;
8221: tp = atp;
8222: spl5();
8223: while (tp->t_outq.c_cc) {
8224: tp->t_state =| ASLEEP;
8225: sleep(&tp->t_outq, TTOPRI);
8226: }
8227: flushtty(tp);
8228: spl0();
8229: }
8230: /* --------------------------- */
8231: /* Initialize clist by freeing all character blocks, then count
8232: * number of character devices. (Once-only routine)
8233: */
8234: cinit()
8235: {
8236: register int ccp;
8237: register struct cblock *cp;
8238: register struct cdevsw *cdp;
8239: ccp = cfree;
8240: for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) {
8241: cp->c_next = cfreelist;
8242: cfreelist = cp;
8243: }
8244: ccp = 0;
8245: for(cdp = cdevsw; cdp->d_open; cdp++)
8246: ccp++;
8247: nchrdev = ccp;
8248: }
8249: /* --------------------------- */
8250: /* flush all TTY queues
8251: */
8252: flushtty(atp)
8253: struct tty *atp;
8254: {
8255: register struct tty *tp;
8256: register int sps;
8257: tp = atp;
8258: while (getc(&tp->t_canq) >= 0);
8259: while (getc(&tp->t_outq) >= 0);
8260: wakeup(&tp->t_rawq);
8261: wakeup(&tp->t_outq);
8262: sps = PS->integ;
8263: spl5();
8264: while (getc(&tp->t_rawq) >= 0);
8265: tp->t_delct = 0;
8266: PS->integ = sps;
8267: }
8268: /* --------------------------- */
8269: /* transfer raw input list to canonical list,
8270: * doing erase-kill processing and handling escapes.
8271: * It waits until a full line has been typed in cooked mode,
8272: * or until any character has been typed in raw mode.
8273: */
8274: canon(atp)
8275: struct tty *atp;
8276: {
8277: register char *bp;
8278: char *bp1;
8279: register struct tty *tp;
8280: register int c;
8281:
8282: tp = atp;
8283: spl5();
8284: while (tp->t_delct==0) {
8285: if ((tp->t_state&CARR_ON)==0)
8286: return(0);
8287: sleep(&tp->t_rawq, TTIPRI);
8288: }
8289: spl0();
8290: loop:
8291: bp = &canonb[2];
8292: while ((c=getc(&tp->t_rawq)) >= 0) {
8293: if (c==0377) {
8294: tp->t_delct--;
8295: break;
8296: }
8297: if ((tp->t_flags&RAW)==0) {
8298: if (bp[-1]!='\\') {
8299: if (c==tp->t_erase) {
8300: if (bp > &canonb[2])
8301: bp--;
8302: continue;
8303: }
8304: if (c==tp->t_kill)
8305: goto loop;
8306: if (c==CEOT)
8307: continue;
8308: } else
8309: if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE))) {
8310: if (bp[-2] != '\\')
8311: c = maptab[c];
8312: bp--;
8313: }
8314: }
8315: *bp++ = c;
8316: if (bp>=canonb+CANBSIZ)
8317: break;
8318: }
8319: bp1 = bp;
8320: bp = &canonb[2];
8321: c = &tp->t_canq;
8322: while (bp<bp1)
8323: putc(*bp++, c);
8324: return(1);
8325: }
8326: /* --------------------------- */
8327: /* Place a character on raw TTY input queue, putting in delimiters
8328: * and waking up top half as needed.
8329: * Also echo if required.
8330: * The arguments are the character and the appropriate
8331: * tty structure.
8332: */
8333: ttyinput(ac, atp)
8334: struct tty *atp;
8335: {
8336: register int t_flags, c;
8337: register struct tty *tp;
8338:
8339: tp = atp;
8340: c = ac;
8341: t_flags = tp->t_flags;
8342: if ((c =& 0177) == '\r' && t_flags&CRMOD)
8343: c = '\n';
8344: if ((t_flags&RAW)==0 && (c==CQUIT || c==CINTR)) {
8345: signal(tp, c==CINTR? SIGINT:SIGQIT);
8346: flushtty(tp);
8347: return;
8348: }
8349: if (tp->t_rawq.c_cc>=TTYHOG) {
8350: flushtty(tp);
8351: return;
8352: }
8353: if (t_flags&LCASE && c>='A' && c<='Z')
8354: c =+ 'a'-'A';
8355: putc(c, &tp->t_rawq);
8356: if (t_flags&RAW || c=='\n' || c==004) {
8357: wakeup(&tp->t_rawq);
8358: if (putc(0377, &tp->t_rawq)==0)
8359: tp->t_delct++;
8360: }
8361: if (t_flags&ECHO) {
8362: ttyoutput(c, tp);
8363: ttstart(tp);
8364: }
8365: }
8366: /* --------------------------- */
8367: /* put character on TTY output queue, adding delays,
8368: * expanding tabs, and handling the CR/NL bit.
8369: * It is called both from the top half for output, and from
8370: * interrupt level for echoing.
8371: * The arguments are the character and the tty structure.
8372: */
8373: ttyoutput(ac, tp)
8374: struct tty *tp;
8375: {
8376: register int c;
8377: register struct tty *rtp;
8378: register char *colp;
8379: int ctype;
8380:
8381: rtp = tp;
8382: c = ac&0177;
8383: /* Ignore EOT in normal mode to avoid hanging up
8384: * certain terminals.
8385: */
8386: if (c==004 && (rtp->t_flags&RAW)==0)
8387: return;
8388: /* Turn tabs to spaces as required
8389: */
8390: if (c=='\t' && rtp->t_flags&XTABS) {
8391: do
8392: ttyoutput(' ', rtp);
8393: while (rtp->t_col&07);
8394: return;
8395: }
8396: /* for upper-case-only terminals,
8397: * generate escapes.
8398: */
8399: if (rtp->t_flags&LCASE) {
8400: colp = "({)}!|^~'`";
8401: while(*colp++)
8402: if(c == *colp++) {
8403: ttyoutput('\\', rtp);
8404: c = colp[-2];
8405: break;
8406: }
8407: if ('a'<=c && c<='z')
8408: c =+ 'A' - 'a';
8409: }
8410: /* turn <nl> to <cr><lf> if desired.
8411: */
8412: if (c=='\n' && rtp->t_flags&CRMOD)
8413: ttyoutput('\r', rtp);
8414: if (putc(c, &rtp->t_outq))
8415: return;
8416: /* Calculate delays.
8417: * The numbers here represent clock ticks
8418: * and are not necessarily optimal for all terminals.
8419: * The delays are indicated by characters above 0200,
8420: * thus (unfortunately) restricting the transmission
8421: * path to 7 bits.
8422: */
8423: colp = &rtp->t_col;
8424: ctype = partab[c];
8425: c = 0;
8426: switch (ctype&077) {
8427: /* ordinary */
8428: case 0:
8429: (*colp)++;
8430: /* non-printing */
8431: case 1:
8432: break;
8433: /* backspace */
8434: case 2:
8435: if (*colp)
8436: (*colp)--;
8437: break;
8438: /* newline */
8439: case 3:
8440: ctype = (rtp->t_flags >> 8) & 03;
8441: if(ctype == 1) { /* tty 37 */
8442: if (*colp)
8443: c = max((*colp>>4) + 3, 6);
8444: } else
8445: if(ctype == 2) { /* vt05 */
8446: c = 6;
8447: }
8448: *colp = 0;
8449: break;
8450: /* tab */
8451: case 4:
8452: ctype = (rtp->t_flags >> 10) & 03;
8453: if(ctype == 1) { /* tty 37 */
8454: c = 1 - (*colp | ~07);
8455: if(c < 5)
8456: c = 0;
8457: }
8458: *colp =| 07;
8459: (*colp)++;
8460: break;
8461: /* vertical motion */
8462: case 5:
8463: if(rtp->t_flags & VTDELAY) /* tty 37 */
8464: c = 0177;
8465: break;
8466: /* carriage return */
8467: case 6:
8468: ctype = (rtp->t_flags >> 12) & 03;
8469: if(ctype == 1) { /* tn 300 */
8470: c = 5;
8471: } else
8472: if(ctype == 2) { /* ti 700 */
8473: c = 10;
8474: }
8475: *colp = 0;
8476: }
8477: if(c)
8478: putc(c|0200, &rtp->t_outq);
8479: }
8480: /* --------------------------- */
8481: /* Restart typewriter output following a delay
8482: * timeout.
8483: * The name of the routine is passed to the timeout
8484: * subroutine and it is called during a clock interrupt.
8485: */
8486: ttrstrt(atp)
8487: {
8488: register struct tty *tp;
8489:
8490: tp = atp;
8491: tp->t_state =& ~TIMEOUT;
8492: ttstart(tp);
8493: }
8494: /* --------------------------- */
8495: /*
8496: * Start output on the typewriter. It is used from the top half
8497: * after some characters have been put on the output queue,
8498: * from the interrupt routine to transmit the next
8499: * character, and after a timeout has finished.
8500: * If the SSTART bit is off for the tty the work is done here,
8501: * using the protocol of the single-line interfaces (KL, DL, DC);
8502: * otherwise the address word of the tty structure is
8503: * taken to be the name of the device-dependent startup routine.
8504: */
8505: ttstart(atp)
8506: struct tty *atp;
8507: {
8508: register int *addr, c;
8509: register struct tty *tp;
8510: struct { int (*func)(); };
8511:
8512: tp = atp;
8513: addr = tp->t_addr;
8514: if (tp->t_state&SSTART) {
8515: (*addr.func)(tp);
8516: return;
8517: }
8518: if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT)
8519: return;
8520: if ((c=getc(&tp->t_outq)) >= 0) {
8521: if (c<=0177)
8522: addr->tttbuf = c | (partab[c]&0200);
8523: else {
8524: timeout(ttrstrt, tp, c&0177);
8525: tp->t_state =| TIMEOUT;
8526: }
8527: }
8528: }
8529: /* --------------------------- */
8530: /* Called from device's read routine after it has
8531: * calculated the tty-structure given as argument.
8532: * The pc is backed up for the duration of this call.
8533: * In case of a caught interrupt, an RTI will re-execute.
8534: */
8535: ttread(atp)
8536: struct tty *atp;
8537: {
8538: register struct tty *tp;
8539:
8540: tp = atp;
8541: if ((tp->t_state&CARR_ON)==0)
8542: return;
8543: if (tp->t_canq.c_cc || canon(tp))
8544: while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0);
8545: }
8546: /* --------------------------- */
8547: /* Called from the device's write routine after it has
8548: * calculated the tty-structure given as argument.
8549: */
8550: ttwrite(atp)
8551: struct tty *atp;
8552: {
8553: register struct tty *tp;
8554: register int c;
8555: tp = atp;
8556: if ((tp->t_state&CARR_ON)==0)
8557: return;
8558: while ((c=cpass())>=0) {
8559: spl5();
8560: while (tp->t_outq.c_cc > TTHIWAT) {
8561: ttstart(tp);
8562: tp->t_state =| ASLEEP;
8563: sleep(&tp->t_outq, TTOPRI);
8564: }
8565: spl0();
8566: ttyoutput(c, tp);
8567: }
8568: ttstart(tp);
8569: }
8570: /* --------------------------- */
8571: /* Common code for gtty and stty functions on typewriters.
8572: * If v is non-zero then gtty is being done and information is
8573: * passed back therein;
8574: * if it is zero stty is being done and the input information is in the
8575: * u_arg array.
8576: */
8577: ttystty(atp, av)
8578: int *atp, *av;
8579: {
8580: register *tp, *v;
8581: tp = atp;
8582: if(v = av) {
8583: *v++ = tp->t_speeds;
8584: v->lobyte = tp->t_erase;
8585: v->hibyte = tp->t_kill;
8586: v[1] = tp->t_flags;
8587: return(1);
8588: }
8589: wflushtty(tp);
8590: v = u.u_arg;
8591: tp->t_speeds = *v++;
8592: tp->t_erase = v->lobyte;
8593: tp->t_kill = v->hibyte;
8594: tp->t_flags = v[1];
8595: return(0);
8596: }
8597: /* --------------------------- */