Annotation of linux/kernel/tty_io.c, revision 1.1.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.