Annotation of linux/kernel/tty_io.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
        !             3:  * or rs-channels. It also implements echoing, cooked mode etc (well,
        !             4:  * not currently, but ...)
        !             5:  */
        !             6: #include <ctype.h>
        !             7: #include <errno.h>
        !             8: #include <signal.h>
        !             9: 
        !            10: #define ALRMMASK (1<<(SIGALRM-1))
        !            11: 
        !            12: #include <linux/sched.h>
        !            13: #include <linux/tty.h>
        !            14: #include <asm/segment.h>
        !            15: #include <asm/system.h>
        !            16: 
        !            17: #define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f)
        !            18: #define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)
        !            19: #define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f)
        !            20: 
        !            21: #define L_CANON(tty)   _L_FLAG((tty),ICANON)
        !            22: #define L_ISIG(tty)    _L_FLAG((tty),ISIG)
        !            23: #define L_ECHO(tty)    _L_FLAG((tty),ECHO)
        !            24: #define L_ECHOE(tty)   _L_FLAG((tty),ECHOE)
        !            25: #define L_ECHOK(tty)   _L_FLAG((tty),ECHOK)
        !            26: #define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
        !            27: #define L_ECHOKE(tty)  _L_FLAG((tty),ECHOKE)
        !            28: 
        !            29: #define I_UCLC(tty)    _I_FLAG((tty),IUCLC)
        !            30: #define I_NLCR(tty)    _I_FLAG((tty),INLCR)
        !            31: #define I_CRNL(tty)    _I_FLAG((tty),ICRNL)
        !            32: #define I_NOCR(tty)    _I_FLAG((tty),IGNCR)
        !            33: 
        !            34: #define O_POST(tty)    _O_FLAG((tty),OPOST)
        !            35: #define O_NLCR(tty)    _O_FLAG((tty),ONLCR)
        !            36: #define O_CRNL(tty)    _O_FLAG((tty),OCRNL)
        !            37: #define O_NLRET(tty)   _O_FLAG((tty),ONLRET)
        !            38: #define O_LCUC(tty)    _O_FLAG((tty),OLCUC)
        !            39: 
        !            40: struct tty_struct tty_table[] = {
        !            41:        {
        !            42:                {0,
        !            43:                OPOST|ONLCR,    /* change outgoing NL to CRNL */
        !            44:                0,
        !            45:                ICANON | ECHO | ECHOCTL | ECHOKE,
        !            46:                0,              /* console termio */
        !            47:                INIT_C_CC},
        !            48:                0,                      /* initial pgrp */
        !            49:                0,                      /* initial stopped */
        !            50:                con_write,
        !            51:                {0,0,0,0,""},           /* console read-queue */
        !            52:                {0,0,0,0,""},           /* console write-queue */
        !            53:                {0,0,0,0,""}            /* console secondary queue */
        !            54:        },{
        !            55:                {0, /*IGNCR*/
        !            56:                OPOST | ONLRET,         /* change outgoing NL to CR */
        !            57:                B2400 | CS8,
        !            58:                0,
        !            59:                0,
        !            60:                INIT_C_CC},
        !            61:                0,
        !            62:                0,
        !            63:                rs_write,
        !            64:                {0x3f8,0,0,0,""},               /* rs 1 */
        !            65:                {0x3f8,0,0,0,""},
        !            66:                {0,0,0,0,""}
        !            67:        },{
        !            68:                {0, /*IGNCR*/
        !            69:                OPOST | ONLRET,         /* change outgoing NL to CR */
        !            70:                B2400 | CS8,
        !            71:                0,
        !            72:                0,
        !            73:                INIT_C_CC},
        !            74:                0,
        !            75:                0,
        !            76:                rs_write,
        !            77:                {0x2f8,0,0,0,""},               /* rs 2 */
        !            78:                {0x2f8,0,0,0,""},
        !            79:                {0,0,0,0,""}
        !            80:        }
        !            81: };
        !            82: 
        !            83: /*
        !            84:  * these are the tables used by the machine code handlers.
        !            85:  * you can implement pseudo-tty's or something by changing
        !            86:  * them. Currently not done.
        !            87:  */
        !            88: struct tty_queue * table_list[]={
        !            89:        &tty_table[0].read_q, &tty_table[0].write_q,
        !            90:        &tty_table[1].read_q, &tty_table[1].write_q,
        !            91:        &tty_table[2].read_q, &tty_table[2].write_q
        !            92:        };
        !            93: 
        !            94: void tty_init(void)
        !            95: {
        !            96:        rs_init();
        !            97:        con_init();
        !            98: }
        !            99: 
        !           100: void tty_intr(struct tty_struct * tty, int signal)
        !           101: {
        !           102:        int i;
        !           103: 
        !           104:        if (tty->pgrp <= 0)
        !           105:                return;
        !           106:        for (i=0;i<NR_TASKS;i++)
        !           107:                if (task[i] && task[i]->pgrp==tty->pgrp)
        !           108:                        task[i]->signal |= 1<<(signal-1);
        !           109: }
        !           110: 
        !           111: static void sleep_if_empty(struct tty_queue * queue)
        !           112: {
        !           113:        cli();
        !           114:        while (!current->signal && EMPTY(*queue))
        !           115:                interruptible_sleep_on(&queue->proc_list);
        !           116:        sti();
        !           117: }
        !           118: 
        !           119: static void sleep_if_full(struct tty_queue * queue)
        !           120: {
        !           121:        if (!FULL(*queue))
        !           122:                return;
        !           123:        cli();
        !           124:        while (!current->signal && LEFT(*queue)<128)
        !           125:                interruptible_sleep_on(&queue->proc_list);
        !           126:        sti();
        !           127: }
        !           128: 
        !           129: void copy_to_cooked(struct tty_struct * tty)
        !           130: {
        !           131:        signed char c;
        !           132: 
        !           133:        while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
        !           134:                GETCH(tty->read_q,c);
        !           135:                if (c==13)
        !           136:                        if (I_CRNL(tty))
        !           137:                                c=10;
        !           138:                        else if (I_NOCR(tty))
        !           139:                                continue;
        !           140:                        else ;
        !           141:                else if (c==10 && I_NLCR(tty))
        !           142:                        c=13;
        !           143:                if (I_UCLC(tty))
        !           144:                        c=tolower(c);
        !           145:                if (L_CANON(tty)) {
        !           146:                        if (c==ERASE_CHAR(tty)) {
        !           147:                                if (EMPTY(tty->secondary) ||
        !           148:                                   (c=LAST(tty->secondary))==10 ||
        !           149:                                   c==EOF_CHAR(tty))
        !           150:                                        continue;
        !           151:                                if (L_ECHO(tty)) {
        !           152:                                        if (c<32)
        !           153:                                                PUTCH(127,tty->write_q);
        !           154:                                        PUTCH(127,tty->write_q);
        !           155:                                        tty->write(tty);
        !           156:                                }
        !           157:                                DEC(tty->secondary.head);
        !           158:                                continue;
        !           159:                        }
        !           160:                        if (c==STOP_CHAR(tty)) {
        !           161:                                tty->stopped=1;
        !           162:                                continue;
        !           163:                        }
        !           164:                        if (c==START_CHAR(tty)) {
        !           165:                                tty->stopped=0;
        !           166:                                continue;
        !           167:                        }
        !           168:                }
        !           169:                if (!L_ISIG(tty)) {
        !           170:                        if (c==INTR_CHAR(tty)) {
        !           171:                                tty_intr(tty,SIGINT);
        !           172:                                continue;
        !           173:                        }
        !           174:                }
        !           175:                if (c==10 || c==EOF_CHAR(tty))
        !           176:                        tty->secondary.data++;
        !           177:                if (L_ECHO(tty)) {
        !           178:                        if (c==10) {
        !           179:                                PUTCH(10,tty->write_q);
        !           180:                                PUTCH(13,tty->write_q);
        !           181:                        } else if (c<32) {
        !           182:                                if (L_ECHOCTL(tty)) {
        !           183:                                        PUTCH('^',tty->write_q);
        !           184:                                        PUTCH(c+64,tty->write_q);
        !           185:                                }
        !           186:                        } else
        !           187:                                PUTCH(c,tty->write_q);
        !           188:                        tty->write(tty);
        !           189:                }
        !           190:                PUTCH(c,tty->secondary);
        !           191:        }
        !           192:        wake_up(&tty->secondary.proc_list);
        !           193: }
        !           194: 
        !           195: int tty_read(unsigned channel, char * buf, int nr)
        !           196: {
        !           197:        struct tty_struct * tty;
        !           198:        char c, * b=buf;
        !           199:        int minimum,time,flag=0;
        !           200:        long oldalarm;
        !           201: 
        !           202:        if (channel>2 || nr<0) return -1;
        !           203:        tty = &tty_table[channel];
        !           204:        oldalarm = current->alarm;
        !           205:        time = (unsigned) 10*tty->termios.c_cc[VTIME];
        !           206:        minimum = (unsigned) tty->termios.c_cc[VMIN];
        !           207:        if (time && !minimum) {
        !           208:                minimum=1;
        !           209:                if (flag=(!oldalarm || time+jiffies<oldalarm))
        !           210:                        current->alarm = time+jiffies;
        !           211:        }
        !           212:        if (minimum>nr)
        !           213:                minimum=nr;
        !           214:        while (nr>0) {
        !           215:                if (flag && (current->signal & ALRMMASK)) {
        !           216:                        current->signal &= ~ALRMMASK;
        !           217:                        break;
        !           218:                }
        !           219:                if (current->signal)
        !           220:                        break;
        !           221:                if (EMPTY(tty->secondary) || (L_CANON(tty) &&
        !           222:                !tty->secondary.data && LEFT(tty->secondary)>20)) {
        !           223:                        sleep_if_empty(&tty->secondary);
        !           224:                        continue;
        !           225:                }
        !           226:                do {
        !           227:                        GETCH(tty->secondary,c);
        !           228:                        if (c==EOF_CHAR(tty) || c==10)
        !           229:                                tty->secondary.data--;
        !           230:                        if (c==EOF_CHAR(tty) && L_CANON(tty))
        !           231:                                return (b-buf);
        !           232:                        else {
        !           233:                                put_fs_byte(c,b++);
        !           234:                                if (!--nr)
        !           235:                                        break;
        !           236:                        }
        !           237:                } while (nr>0 && !EMPTY(tty->secondary));
        !           238:                if (time && !L_CANON(tty))
        !           239:                        if (flag=(!oldalarm || time+jiffies<oldalarm))
        !           240:                                current->alarm = time+jiffies;
        !           241:                        else
        !           242:                                current->alarm = oldalarm;
        !           243:                if (L_CANON(tty)) {
        !           244:                        if (b-buf)
        !           245:                                break;
        !           246:                } else if (b-buf >= minimum)
        !           247:                        break;
        !           248:        }
        !           249:        current->alarm = oldalarm;
        !           250:        if (current->signal && !(b-buf))
        !           251:                return -EINTR;
        !           252:        return (b-buf);
        !           253: }
        !           254: 
        !           255: int tty_write(unsigned channel, char * buf, int nr)
        !           256: {
        !           257:        static cr_flag=0;
        !           258:        struct tty_struct * tty;
        !           259:        char c, *b=buf;
        !           260: 
        !           261:        if (channel>2 || nr<0) return -1;
        !           262:        tty = channel + tty_table;
        !           263:        while (nr>0) {
        !           264:                sleep_if_full(&tty->write_q);
        !           265:                if (current->signal)
        !           266:                        break;
        !           267:                while (nr>0 && !FULL(tty->write_q)) {
        !           268:                        c=get_fs_byte(b);
        !           269:                        if (O_POST(tty)) {
        !           270:                                if (c=='\r' && O_CRNL(tty))
        !           271:                                        c='\n';
        !           272:                                else if (c=='\n' && O_NLRET(tty))
        !           273:                                        c='\r';
        !           274:                                if (c=='\n' && !cr_flag && O_NLCR(tty)) {
        !           275:                                        cr_flag = 1;
        !           276:                                        PUTCH(13,tty->write_q);
        !           277:                                        continue;
        !           278:                                }
        !           279:                                if (O_LCUC(tty))
        !           280:                                        c=toupper(c);
        !           281:                        }
        !           282:                        b++; nr--;
        !           283:                        cr_flag = 0;
        !           284:                        PUTCH(c,tty->write_q);
        !           285:                }
        !           286:                tty->write(tty);
        !           287:                if (nr>0)
        !           288:                        schedule();
        !           289:        }
        !           290:        return (b-buf);
        !           291: }
        !           292: 
        !           293: /*
        !           294:  * Jeh, sometimes I really like the 386.
        !           295:  * This routine is called from an interrupt,
        !           296:  * and there should be absolutely no problem
        !           297:  * with sleeping even in an interrupt (I hope).
        !           298:  * Of course, if somebody proves me wrong, I'll
        !           299:  * hate intel for all time :-). We'll have to
        !           300:  * be careful and see to reinstating the interrupt
        !           301:  * chips before calling this, though.
        !           302:  */
        !           303: void do_tty_interrupt(int tty)
        !           304: {
        !           305:        copy_to_cooked(tty_table+tty);
        !           306: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.