Annotation of coherent/d/PS2_KERNEL/io.286/rs.c, revision 1.1.1.1

1.1       root        1: /* (-lgl
                      2:  *     COHERENT Driver Kit Version 1.1.0
                      3:  *     Copyright (c) 1982, 1990 by Mark Williams Company.
                      4:  *     All rights reserved. May not be copied without permission.
                      5:  -lgl) */
                      6: /*
                      7:  * Raw Serial Device Driver.
                      8:  *
                      9:  *     Provides fast, efficiently buffered serial i/o to COM1 & COM2.
                     10:  *     Supports an extreme subset of System V (termio) parameters.
                     11:  *             c_iflag: ISTRIP, IXON, IXANY, IGNBRK, INPCK, PARMRK, IGNPAR.
                     12:  *             c_oflag: OPOST, ONLCR, ONLRET, TAB3.
                     13:  *             c_cflag: *.
                     14:  *
                     15:  */
                     16: 
                     17: #include <sys/coherent.h>
                     18: #include <sys/ins8250.h>
                     19: #include <sys/proc.h>
                     20: #include <sys/con.h>
                     21: #include <sys/devices.h>
                     22: #include <sys/sched.h>
                     23: #include <sys/stat.h>
                     24: #include <termio.h>
                     25: #include <errno.h>
                     26: 
                     27: #define        COM1VEC         4               /* interrupt vector for COM1    */
                     28: #define        COM2VEC         3               /* interrupt vector for COM2    */
                     29: 
                     30: #define        COM1PORT        0x3F8           /* i/o port address for COM1    */
                     31: #define        COM2PORT        0x2F8           /* i/o port address for COM2    */
                     32: 
                     33: #ifdef RS1
                     34: #      define  CFLAG   RS1CFLAG
                     35: #      define  MAJ     AL1_MAJOR       /* major device for /dev/rs1    */
                     36: #      define  rscon   rs1con          /* configuration table for "    */
                     37: #      define  rstty   rs1tty
                     38: #      define  IVEC    COM2VEC         /* interrupt vector for rs1     */
                     39: #      define  PORT    COM2PORT        /* i/o port address for rs1     */
                     40: #else
                     41: #      define  CFLAG   RS0CFLAG
                     42: #      define  MAJ     AL0_MAJOR       /* major device for /dev/rs0    */
                     43: #      define  rscon   rs0con          /* configuration table for "    */
                     44: #      define  rstty   rs0tty
                     45: #      define  IVEC    COM1VEC         /* interrupt vector for rs0     */
                     46: #      define  PORT    COM1PORT        /* i/o port address for rs0     */
                     47: #endif
                     48: 
                     49: #define        CTRLS   '\023'
                     50: #define        CTRLQ   '\021'
                     51: 
                     52: /*
                     53:  * Functions.
                     54:  */
                     55: 
                     56: int    rsload();
                     57: int    rsunload();
                     58: int    rsopen();
                     59: int    rsclose();
                     60: int    rsread();
                     61: int    rswrite();
                     62: int    rsioctl();
                     63: int    rspoll();
                     64: int    nulldev();
                     65: int    nonedev();
                     66: 
                     67: int    rsintr();
                     68: int    rsparam();
                     69: 
                     70: /*
                     71:  * Configuration table.
                     72:  */
                     73: 
                     74: CON rscon ={
                     75:        DFCHR|DFPOL,                    /* Flags */
                     76:        MAJ,                            /* Major index */
                     77:        rsopen,                         /* Open */
                     78:        rsclose,                        /* Close */
                     79:        nulldev,                        /* Block */
                     80:        rsread,                         /* Read */
                     81:        rswrite,                        /* Write */
                     82:        rsioctl,                        /* Ioctl */
                     83:        nulldev,                        /* Powerfail */
                     84:        nulldev,                        /* Timeout */
                     85:        rsload,                         /* Load */
                     86:        rsunload,                       /* Unload */
                     87:        rspoll                          /* Poll */
                     88: };
                     89: 
                     90: /*
                     91:  * Terminal structure.
                     92:  */
                     93: 
                     94: #define        RAWSZ   (2048-1)
                     95: #define        OUTSZ   (2048-1)
                     96: 
                     97: #define        NRAWC   ((rsrawq.rq_ix - rsrawq.rq_ox) & RAWSZ)
                     98: #define        NOUTC   ((rsoutq.rq_ix - rsoutq.rq_ox) & OUTSZ)
                     99: 
                    100: #define        TTSTOP  00001
                    101: #define        TTSBRK  00002
                    102: #define        CARRIER 00004
                    103: 
                    104: typedef
                    105: struct rawtty_s {
                    106:        unsigned        rt_state;       /* terminal state               */
                    107:        int             rt_group;       /* controlling process group    */
                    108:        unsigned        rt_ticks;       /* send break 1/10 sec counter  */
                    109:        unsigned        rt_iflag;       /* termio input   flags         */
                    110:        unsigned        rt_oflag;       /* termio output  flags         */
                    111:        unsigned        rt_cflag;       /* termio control flags         */
                    112:        unsigned char   rt_col;         /* current output column        */
                    113:        unsigned char   rt_refc;        /* # procs accessing the port   */
                    114:        unsigned char   rt_irefc;       /* # procs waiting for input    */
                    115:        unsigned char   rt_orefc;       /* # procs waitint for output   */
                    116:        unsigned char   rt_crefc;       /* # procs waiting for carrier  */
                    117:        unsigned char   rt_drefc;       /* # procs waiting for drain    */
                    118:        event_t         rt_ipolls;      /* Procs polling on input queue */
                    119:        event_t         rt_opolls;      /* Procs polling on output que  */
                    120: } RAWTTY;
                    121: 
                    122: typedef
                    123: struct iring_s {
                    124:        unsigned short  rq_mask;
                    125:        unsigned short  rq_ix;
                    126:        unsigned short  rq_ox;
                    127:        unsigned char   rq_cc[RAWSZ+1];
                    128: } IRING;
                    129: 
                    130: typedef
                    131: struct oring_s {
                    132:        unsigned short  rq_mask;
                    133:        unsigned short  rq_ix;
                    134:        unsigned short  rq_ox;
                    135:        unsigned char   rq_cc[OUTSZ+1];
                    136: } ORING;
                    137: 
                    138: /*
                    139:  * Local variables.
                    140:  */
                    141: unsigned CFLAG  = CLOCAL | CREAD | B1200 | CS8 | HUPCL;
                    142: RAWTTY rstty;
                    143: static ORING   rsoutq;
                    144: static IRING   rsrawq;
                    145: static TIM     rstim;
                    146: 
                    147: /*
                    148:  * Time constant table.
                    149:  * Indexed by ioctl baud rate.
                    150:  */
                    151: static
                    152: int timeconst[] = {
                    153:        0,                              /* 0 */
                    154:        2304,                           /* 50 */
                    155:        1536,                           /* 75 */
                    156:        1047,                           /* 110 */
                    157:        857,                            /* 134.5 */
                    158:        768,                            /* 150 */
                    159:        576,                            /* 200 */
                    160:        384,                            /* 300 */
                    161:        192,                            /* 600 */
                    162:        96,                             /* 1200 */
                    163:        64,                             /* 1800 */
                    164:        48,                             /* 2400 */
                    165:        24,                             /* 4800 */
                    166:        12,                             /* 9600 */
                    167:        6,                              /* 19200/EXTA */
                    168:        6                               /* 19200/EXTB */
                    169: };
                    170: 
                    171: /*
                    172:  * Rsload() -- Raw Serial Load Routine.
                    173:  *
                    174:  *     Action: Define terminal parameters.
                    175:  *             Initialize terminal hardware.
                    176:  *             If serial port exists, seize its interrupt vector.
                    177:  *
                    178:  *     Return: None.
                    179:  */
                    180: 
                    181: static
                    182: rsload()
                    183: {
                    184:        /*
                    185:         * Initialize terminal parameters.
                    186:         */
                    187:        rsoutq.rq_mask = OUTSZ;
                    188:        rsrawq.rq_mask = RAWSZ;
                    189: 
                    190:        /*
                    191:         * Initialize terminal hardware.
                    192:         */
                    193:        rsparam();
                    194: 
                    195:        /*
                    196:         * If serial port exists, initialize interrupt vector.
                    197:         */
                    198:        if ( inb(PORT+IER) == 0 ) {
                    199:                setivec( IVEC, rsintr);
                    200:                rscycle();
                    201:        }
                    202: }
                    203: 
                    204: /*
                    205:  * Rsunload() -- Raw Serial unload Routine.
                    206:  */
                    207: 
                    208: static
                    209: rsunload()
                    210: {
                    211:        timeout( &rstim, 0, NULL, 0 );  /* cancel timed function */
                    212:        clrivec( IVEC );                /* release interrupt vector */
                    213:        outb(PORT+IER, 0);              /* disable port interrupts */
                    214:        outb(PORT+MCR, MC_OUT2);        /* hangup port */
                    215: }
                    216: 
                    217: /*
                    218:  * Rsopen -- Open Routine.
                    219:  *
                    220:  *     Input:  dev = device to open.
                    221:  *             If high bit (0x80) set in minor, modem control is requested.
                    222:  *
                    223:  *     Action: Validate minor device.
                    224:  *             Increment reference count.
                    225:  *             If first reference and parameters are not initialized,
                    226:  *                     set default parameters and initialize hardware.
                    227:  *
                    228:  *     Return: None.
                    229:  */
                    230: 
                    231: static
                    232: rsopen( dev, mode )
                    233: 
                    234: dev_t dev;
                    235: 
                    236: {
                    237:        register PROC *pp = SELF;
                    238: 
                    239:        /*
                    240:         * Validate minor device.
                    241:         */
                    242:        if (minor(dev) & ~0x80) {
                    243:                u.u_error = ENODEV;
                    244:                return;
                    245:        }
                    246: 
                    247:        /*
                    248:         * Validate hardware.
                    249:         */
                    250:        if (inb(PORT+IER) & ~(IE_RxI|IE_TxI|IE_LSI)) {
                    251:                u.u_error = ENXIO;
                    252:                return;
                    253:        }
                    254: 
                    255:        /*
                    256:         * Ensure controlling terminal and group fields initialized.
                    257:         */
                    258:        if (pp->p_ttdev == NODEV)
                    259:                pp->p_ttdev = dev;
                    260:        if (pp->p_group == 0)
                    261:                pp->p_group = pp->p_pid;
                    262: 
                    263:        /*
                    264:         * Check for first open.
                    265:         */
                    266:        if (++rstty.rt_refc == 1) {
                    267: 
                    268:                if (pp->p_group == pp->p_pid)
                    269:                        rstty.rt_group = pp->p_group;
                    270: 
                    271:                if ((rstty.rt_cflag & CBAUD) == B0) {
                    272: 
                    273:                        /*
                    274:                         * Define terminal parameters.
                    275:                         */
                    276:                        rstty.rt_state = 0;
                    277:                        rstty.rt_col   = 0;
                    278:                        rstty.rt_iflag = ISTRIP | IXON;
                    279:                        rstty.rt_oflag = OPOST  | ONLCR | TAB3;
                    280:                        rstty.rt_cflag = CFLAG;
                    281:                        if ( minor(dev) & 0x80 )
                    282:                                rstty.rt_cflag &= ~CLOCAL;
                    283: 
                    284:                        /*
                    285:                         * Initialize terminal hardware.
                    286:                         */
                    287:                        rsparam();
                    288:                }
                    289: 
                    290:                /*
                    291:                 * Discard input data.
                    292:                 */
                    293:                rsrawq.rq_ox = rsrawq.rq_ix;
                    294:        }
                    295: 
                    296:        /*
                    297:         * If modem control is requested, check carrier.
                    298:         */
                    299:        if ( minor(dev) & 0x80 ) {
                    300: 
                    301:                /*
                    302:                 * Delay until carrier is present.
                    303:                 */
                    304:                while ( (rstty.rt_state & CARRIER) == 0 ) {
                    305: 
                    306:                        /*
                    307:                         * Sleep on carrier.
                    308:                         */
                    309:                        ++rstty.rt_crefc;
                    310:                        sleep( &rstty.rt_crefc,
                    311:                                CVTTOUT, IVTTOUT, SVTTOUT);
                    312:                        --rstty.rt_crefc;
                    313: 
                    314:                        /*
                    315:                         * Abort if non-ignored signal is received.
                    316:                         */
                    317:                        if (SELF->p_ssig && nondsig()) {
                    318: 
                    319:                                if (--rstty.rt_refc == 0) {
                    320:                                        rstty.rt_group = 0;
                    321:                                        rstty.rt_cflag = 0;
                    322:                                        rsparam();
                    323:                                }
                    324:                                u.u_error = EINTR;
                    325:                                return;
                    326:                        }
                    327:                }
                    328:        }
                    329: }
                    330: 
                    331: /*
                    332:  * Rsclose -- Close Routine.
                    333:  *
                    334:  *     Action: Decrement reference count.
                    335:  *             If serial port is no longer referenced,
                    336:  *             and the hangup on last close bit is set in rt_cflag,
                    337:  *             clear terminal parameters, and initialize hardware.
                    338:  *
                    339:  *     Return: None.
                    340:  *
                    341:  *     Note:   This routine does not wait for the output queue to empty.
                    342:  */
                    343: 
                    344: static
                    345: rsclose( dev )
                    346: 
                    347: dev_t dev;
                    348: 
                    349: {
                    350:        /*
                    351:         * Check for last close and hangup on close.
                    352:         */
                    353:        if ((rstty.rt_refc == 1) && (rstty.rt_cflag & HUPCL)) {
                    354: 
                    355:                /*
                    356:                 * Wait for output to drain.
                    357:                 */
                    358:                while ( rsoutq.rq_ox != rsoutq.rq_ix ) {
                    359: 
                    360:                        ++rstty.rt_drefc;
                    361:                        sleep( &rstty.rt_drefc, CVTTOUT, IVTTOUT, SVTTOUT );
                    362:                        --rstty.rt_drefc;
                    363: 
                    364:                        if (rstty.rt_refc != 1) {
                    365:                                rstty.rt_refc--;
                    366:                                return;
                    367:                        }
                    368: 
                    369:                        if (SELF->p_ssig && nondsig())
                    370:                                break;
                    371:                }
                    372: 
                    373:                /*
                    374:                 * Initialize terminal hardware.
                    375:                 */
                    376:                rstty.rt_group = 0;
                    377:                rstty.rt_cflag = 0;
                    378:                rsparam();
                    379: 
                    380:                /*
                    381:                 * Flush input and output queues.
                    382:                 */
                    383:                rsrawq.rq_ix =
                    384:                rsrawq.rq_ox =
                    385:                rsoutq.rq_ox =
                    386:                rsoutq.rq_ix = 0;
                    387:        }
                    388:        --rstty.rt_refc;
                    389: }
                    390: 
                    391: /*
                    392:  * Rsread -- Read Routine.
                    393:  *
                    394:  *     Input:  iop = pointer to structure containing i/o parameters.
                    395:  *
                    396:  *     Action: Attempt to read data from input buffer until at least
                    397:  *             one character has been read, or a signal is received
                    398:  *             by the current process.
                    399:  *             Update the parameters in the io structure.
                    400:  *             If a signal is received, set errno to EINTR.
                    401:  *
                    402:  *     Return: None.
                    403:  */
                    404: 
                    405: static
                    406: rsread( dev, iop )
                    407: 
                    408: dev_t dev;
                    409: register IO *iop;
                    410: 
                    411: {
                    412:        register int sioc;
                    413: 
                    414:        /*
                    415:         * Remember original char count.
                    416:         */
                    417:        sioc = iop->io_ioc;
                    418: 
                    419:        do {
                    420:                /*
                    421:                 * Transfer data until done or input buffer empty.
                    422:                 */
                    423:                rsin( &rsrawq, iop );
                    424: 
                    425:                /*
                    426:                 * Return if some data was transferred.
                    427:                 */
                    428:                if (sioc != iop->io_ioc)
                    429:                        return;
                    430: 
                    431:                /*
                    432:                 * Non-blocking reads.
                    433:                 */
                    434:                if ( iop->io_flag & IONDLY ) {
                    435:                        u.u_error = EAGAIN;
                    436:                        return;
                    437:                }
                    438: 
                    439:                /*
                    440:                 * Sleep waiting for a signal or input data.
                    441:                 */
                    442:                ++rstty.rt_irefc;
                    443:                sleep( &rstty.rt_irefc, CVTTOUT, IVTTOUT, SVTTOUT );
                    444:                --rstty.rt_irefc;
                    445: 
                    446:                /*
                    447:                 * Abort if a non-ignored signal was received.
                    448:                 */
                    449:                if (SELF->p_ssig && nondsig()) {
                    450:                        u.u_error = EINTR;
                    451:                        return;
                    452:                }
                    453: 
                    454:        } while (1);
                    455: }
                    456: 
                    457: /*
                    458:  * Rswrite -- Write Routine.
                    459:  */
                    460: 
                    461: static
                    462: rswrite( dev, iop )
                    463: 
                    464: dev_t dev;
                    465: register IO *iop;
                    466: 
                    467: {
                    468:        register int n;
                    469: 
                    470:        /*
                    471:         * Non-blocking write.
                    472:         */
                    473:        if ( iop->io_flag & IONDLY ) {
                    474: 
                    475:                /*
                    476:                 * Calculate free slots.
                    477:                 */
                    478:                n  = rsoutq.rq_mask - rsoutq.rq_ix + rsoutq.rq_ox;
                    479:                n &= rsoutq.rq_mask;
                    480: 
                    481:                /*
                    482:                 * Insufficient space.
                    483:                 */
                    484:                if ( n <= iop->io_ioc ) {
                    485:                        u.u_error = EAGAIN;
                    486:                        return;
                    487:                }
                    488:        }
                    489: 
                    490:        do {
                    491:                /*
                    492:                 * Transfer data until done or output queue full.
                    493:                 */
                    494:                rsout( &rsoutq, iop );
                    495: 
                    496:                /*
                    497:                 * Make sure the transmitter is operating.
                    498:                 */
                    499:                rsstart();
                    500: 
                    501:                /*
                    502:                 * Return if all data was transferred.
                    503:                 */
                    504:                if ( iop->io_ioc == 0 )
                    505:                        return;
                    506: 
                    507:                /*
                    508:                 * Sleep waiting for a signal or room in the output queue.
                    509:                 */
                    510:                ++rstty.rt_orefc;
                    511:                sleep( &rstty.rt_orefc, CVTTOUT, IVTTOUT, SVTTOUT );
                    512:                --rstty.rt_orefc;
                    513: 
                    514:                /*
                    515:                 * Abort if a non-ignored signal was received.
                    516:                 */
                    517:                if ( SELF->p_ssig && nondsig() ) {
                    518:                        u.u_error = EINTR;
                    519:                        return;
                    520:                }
                    521: 
                    522:        } while (1);
                    523: }
                    524: 
                    525: /*
                    526:  * Rspoll -- Polling Routine.
                    527:  */
                    528: static int
                    529: rspoll( dev, ev, msec )
                    530: dev_t dev;
                    531: register int ev;
                    532: int msec;
                    533: {
                    534:        /*
                    535:         * No priority reports.
                    536:         */
                    537:        ev &= ~POLLPRI;
                    538: 
                    539:        /*
                    540:         * Input poll with empty input ring.
                    541:         */
                    542:        if ( (ev & POLLIN) && (rsrawq.rq_ix == rsrawq.rq_ox) ) {
                    543: 
                    544:                /*
                    545:                 * Blocking input poll.
                    546:                 */
                    547:                if ( msec != 0 )
                    548:                        pollopen( &rstty.rt_ipolls );
                    549: 
                    550:                /*
                    551:                 * Second look and clear input report.
                    552:                 */
                    553:                if ( rsrawq.rq_ix == rsrawq.rq_ox )
                    554:                        ev &= ~POLLIN;
                    555:        }
                    556: 
                    557:        /*
                    558:         * Output poll with non-empty output ring.
                    559:         */
                    560:        if ( (ev & POLLOUT) && (rsoutq.rq_ix != rsrawq.rq_ox) ) {
                    561: 
                    562:                /*
                    563:                 * Blocking output poll.
                    564:                 */
                    565:                if ( msec != 0 )
                    566:                        pollopen( &rstty.rt_opolls );
                    567: 
                    568:                /*
                    569:                 * Second look and clear output report.
                    570:                 */
                    571:                if ( rsoutq.rq_ix != rsoutq.rq_ox )
                    572:                        ev &= ~POLLOUT;
                    573:        }
                    574: 
                    575:        return ev;
                    576: }
                    577: 
                    578: /*
                    579:  * Cyclic [1 sec] Routine.
                    580:  */
                    581: static
                    582: rscycle()
                    583: {
                    584:        register PROC *pp;
                    585:        register int b;
                    586: 
                    587:        /*
                    588:         * Check for carrier transitions.
                    589:         */
                    590:        if ( inb( PORT + MSR ) & MS_RLSD ) {
                    591: 
                    592:                /*
                    593:                 * Have carrier.  Wake processes waiting for carrier.
                    594:                 */
                    595:                rstty.rt_state |= CARRIER;
                    596: 
                    597:                if ( rstty.rt_crefc )
                    598:                        wakeup( &rstty.rt_crefc );
                    599:        }
                    600:        else if ((rstty.rt_state & CARRIER) && (rstty.rt_cflag&CLOCAL) == 0) {
                    601: 
                    602:                /*
                    603:                 * Lost carrier. Signal attached processes.
                    604:                 */
                    605:                rstty.rt_state &= ~CARRIER;
                    606: 
                    607:                if (rstty.rt_refc && (b = rstty.rt_group))
                    608:                        for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw)
                    609:                                if ( pp->p_group == b )
                    610:                                        sendsig( SIGHUP, pp );
                    611:        }
                    612: 
                    613:        /*
                    614:         * Wakeup processes waiting to read if input data present.
                    615:         */
                    616:        if ( rsrawq.rq_ix != rsrawq.rq_ox ) {
                    617:                if ( rstty.rt_irefc )
                    618:                        wakeup( &rstty.rt_irefc );
                    619:                if ( rstty.rt_ipolls.e_procp )
                    620:                        pollwake( &rstty.rt_ipolls );
                    621:        }
                    622: 
                    623:        /*
                    624:         * Check for break being sent.
                    625:         */
                    626:        if ( rstty.rt_ticks != 0 ) {
                    627: 
                    628:                if ( --rstty.rt_ticks == 0 ) {
                    629: 
                    630:                        b = inb( PORT + LCR );
                    631:                        outb( PORT + LCR, b & ~LC_SBRK );
                    632:                        rstty.rt_state &= ~TTSBRK;
                    633:                }
                    634:        }
                    635: 
                    636:        /*
                    637:         * Can check output if not sending break.
                    638:         */
                    639:        if ( rstty.rt_ticks == 0 ) {
                    640: 
                    641:                /*
                    642:                 * Restart output if necessary.
                    643:                 */
                    644:                if ( rsoutq.rq_ox != rsoutq.rq_ix )
                    645:                        rsstart();
                    646: 
                    647:                /*
                    648:                 * Wakeup processes waiting for drain if output queue empty.
                    649:                 */
                    650:                if ( rstty.rt_drefc ) {
                    651:                        if ( rsoutq.rq_ix == rsoutq.rq_ox )
                    652:                                wakeup( &rstty.rt_drefc );
                    653:                }
                    654: 
                    655:                /*
                    656:                 * Wakeup processes waiting to write if 512 slots are free.
                    657:                 */
                    658:                else if ( NOUTC < OUTSZ-512 ) {
                    659:                        if ( rstty.rt_orefc )
                    660:                                wakeup( &rstty.rt_orefc );
                    661:                        if ( rstty.rt_opolls.e_procp )
                    662:                                pollwake( &rstty.rt_opolls );
                    663:                }
                    664:        }
                    665: 
                    666:        timeout( &rstim, HZ/10, rscycle, 0 );
                    667: }
                    668: 
                    669: /*
                    670:  * Rsintr -- Serial Interrupt Handler.
                    671:  *
                    672:  *     Action: Process all pending interrupt service requests
                    673:  *             on the serial port.
                    674:  *
                    675:  *     Return: None.
                    676:  *
                    677:  *     Notes:  This routine must loop until all requests are serviced
                    678:  *             because of the edge sensitive nature of the programmable
                    679:  *             interrupt controller.
                    680:  */
                    681: 
                    682: static
                    683: rsintr()
                    684: {
                    685:        register int b;
                    686: 
                    687:        /*
                    688:         * Service serial port interrupt requests, highest to lowest priority.
                    689:         */
                    690: rescan:
                    691:        b = inb( PORT + IIR );
                    692: 
                    693:        switch ( b ) {
                    694: 
                    695:        case LS_INTR:
                    696:                /*
                    697:                 * Get line status (clear interrupt).
                    698:                 */
                    699:                b = inb( PORT + LSR );
                    700: 
                    701:                /*
                    702:                 * Check for received break.
                    703:                 */
                    704:                if (b & LS_BREAK) {
                    705: 
                    706:                        /*
                    707:                         * Read the break char ('\0').
                    708:                         */
                    709:                        rsrawq.rq_cc[ rsrawq.rq_ix ] = inb( PORT + DREG );
                    710: 
                    711:                        /*
                    712:                         * Clear output stops.
                    713:                         */
                    714:                        rstty.rt_state &= ~TTSTOP;
                    715: 
                    716:                        /*
                    717:                         * Update input index if not ignoring break.
                    718:                         */
                    719:                        if ((rstty.rt_iflag & IGNBRK) == 0) {
                    720:                                rsrawq.rq_ix ++;
                    721:                                rsrawq.rq_ix &= RAWSZ;
                    722:                        }
                    723:                }
                    724: 
                    725:                /*
                    726:                 * Special handling if frame/parity error and checking enabled.
                    727:                 */
                    728:                if ((b & (LS_FRAME|LS_PARITY)) && (rstty.rt_iflag & INPCK)) {
                    729: 
                    730:                        /*
                    731:                         * Ignore next input char if IGNPAR set.
                    732:                         */
                    733:                        if (rstty.rt_iflag & IGNPAR)
                    734:                                inb( PORT + DREG );
                    735:                        /*
                    736:                         * Change next input char into 0377,0,ch if PARMRK set.
                    737:                         */
                    738:                        else if (rstty.rt_iflag & PARMRK) {
                    739: 
                    740:                                b = rsrawq.rq_ix;
                    741:                                rsrawq.rq_cc[ b++ ] = 0377;
                    742:                                b &= RAWSZ;
                    743:                                rsrawq.rq_cc[ b++ ] = '\0';
                    744:                                b &= RAWSZ;
                    745:                                rsrawq.rq_cc[ b++ ] = inb( PORT + DREG );
                    746:                                b &= RAWSZ;
                    747:                                rsrawq.rq_ix = b;
                    748:                        }
                    749: 
                    750:                        /*
                    751:                         * Otherwise change next input char into null.
                    752:                         */
                    753:                        else {
                    754:                                inb( PORT + DREG );
                    755:                                rsrawq.rq_cc[ rsrawq.rq_ix++ ] = '\0';
                    756:                                rsrawq.rq_ix &= RAWSZ;
                    757:                        }
                    758:                }
                    759:                goto rescan;
                    760: 
                    761:        case Rx_INTR:
                    762:                /*
                    763:                 * Read character from receive buffer.
                    764:                 */
                    765:                b = inb( PORT + DREG );
                    766: 
                    767:                /*
                    768:                 * Discard high bit if ISTRIP set.
                    769:                 */
                    770:                if ( rstty.rt_iflag & ISTRIP )
                    771:                        b &= 0177;
                    772: 
                    773:                /*
                    774:                 * Check for output flow control if IXON set.
                    775:                 */
                    776:                if ( rstty.rt_iflag & IXON ) {
                    777: 
                    778:                        /*
                    779:                         * Stop output if Ctl-S.
                    780:                         */
                    781:                        if ( b == CTRLS ) {
                    782:                                rstty.rt_state |= TTSTOP;
                    783:                                goto rescan;
                    784:                        }
                    785: 
                    786:                        /*
                    787:                         * Resume output if Ctl-Q.
                    788:                         */
                    789:                        if ( b == CTRLQ ) {
                    790:                                rstty.rt_state &= ~TTSTOP;
                    791:                                goto rescan;
                    792:                        }
                    793: 
                    794:                        /*
                    795:                         * Enable output if IXANY set.
                    796:                         */
                    797:                        if ( rstty.rt_iflag & IXANY )
                    798:                                rstty.rt_state &= ~TTSTOP;
                    799:                }
                    800: 
                    801:                /*
                    802:                 * Save the character in the input queue.
                    803:                 */
                    804:                rsrawq.rq_cc[ rsrawq.rq_ix++ ] = b;
                    805:                rsrawq.rq_ix &= RAWSZ;
                    806: 
                    807:                /*
                    808:                 * Save again if 0377 and parity marking enabled.
                    809:                 */
                    810:                if ((b == 0377)
                    811:                &&  ((rstty.rt_iflag & (INPCK|PARMRK)) == (INPCK|PARMRK))) {
                    812: 
                    813:                        rsrawq.rq_cc[ rsrawq.rq_ix++ ] = b;
                    814:                        rsrawq.rq_ix &= RAWSZ;
                    815:                }
                    816: 
                    817:                goto rescan;
                    818: 
                    819:        case Tx_INTR:
                    820:                rsstart();
                    821:                goto rescan;
                    822:        }
                    823: }
                    824: 
                    825: /*
                    826:  * Rsstart()
                    827:  *
                    828:  *     Action: While output data is available, and the transmitter buffer
                    829:  *             is empty, transfer one character from the output queue to the
                    830:  *             transmit buffer.
                    831:  *
                    832:  *     Return: None.
                    833:  */
                    834: 
                    835: static
                    836: rsstart()
                    837: {
                    838:        register int b;
                    839:        register int s;
                    840: 
                    841:        /*
                    842:         * Can't transmit if output stopped or sending break.
                    843:         */
                    844:        if ( rstty.rt_state & (TTSTOP|TTSBRK) )
                    845:                return;
                    846: 
                    847:        /*
                    848:         * Can't transmit if modem control enabled without CTS present.
                    849:         */
                    850:        if ( (rstty.rt_cflag & CLOCAL) == 0 )
                    851:                if ( (inb(PORT+MSR) & MS_CTS) == 0 )
                    852:                        return;
                    853: 
                    854:        /*
                    855:         * Disable interrupts to avoid critical race.
                    856:         */
                    857:        s = sphi();
                    858: 
                    859:        /*
                    860:         * Can transmit if output data available and transmit buffer empty.
                    861:         */
                    862:        if ( (rsoutq.rq_ix != rsoutq.rq_ox)
                    863:        &&   (inb(PORT+LSR) & LS_TxRDY) ) {
                    864: 
                    865:                /*
                    866:                 * Get next char from output queue.
                    867:                 */
                    868:                b = rsoutq.rq_cc [ rsoutq.rq_ox ];
                    869: 
                    870:                if (rstty.rt_oflag & OPOST) {
                    871: 
                    872:                        /*
                    873:                         * Printable characters increment the column.
                    874:                         */
                    875:                        if (b >= ' ') {
                    876:                                rstty.rt_col++;
                    877:                        }
                    878:                        /*
                    879:                         * Carriage return resets the column.
                    880:                         */
                    881:                        else if (b == '\r') {
                    882:                                rstty.rt_col = 0;
                    883:                                if (rstty.rt_oflag & OCRNL)
                    884:                                        b = '\n';
                    885:                        }
                    886:                        /*
                    887:                         * New-line may also generate a carriage return.
                    888:                         */
                    889:                        else if (b == '\n') {
                    890:                                if (rstty.rt_oflag & ONLCR) {
                    891:                                        if (rstty.rt_col) {
                    892:                                                rstty.rt_col = 0;
                    893:                                                rsoutq.rq_ox--;
                    894:                                                b = '\r';
                    895:                                        }
                    896:                                }
                    897:                                else if (rstty.rt_oflag & ONLRET)
                    898:                                        rstty.rt_col = 0;
                    899:                        }
                    900:                        /*
                    901:                         * Backspace decrements the column.
                    902:                         */
                    903:                        else if (b == '\b') {
                    904:                                if (rstty.rt_col)
                    905:                                        --rstty.rt_col;
                    906:                        }
                    907:                        /*
                    908:                         * Tabs may generate spaces, always move to tab stop.
                    909:                         */
                    910:                        else if (b == '\t') {
                    911:                                if ((rstty.rt_oflag & TABDLY) == TAB3) {
                    912:                                        b = ' ';
                    913:                                        if (++rstty.rt_col & 7)
                    914:                                                rsoutq.rq_ox--;
                    915:                                }
                    916:                                else {
                    917:                                        rstty.rt_col |= 7;
                    918:                                        rstty.rt_col++;
                    919:                                }
                    920:                        }
                    921:                }
                    922:                rsoutq.rq_ox++;
                    923:                rsoutq.rq_ox &= OUTSZ;
                    924: 
                    925:                /*
                    926:                 * Transmit next char.
                    927:                 */
                    928:                outb( PORT+DREG, b );
                    929:        }
                    930: 
                    931:        spl(s);
                    932: }
                    933: 
                    934: /*
                    935:  * Ioctl Routine.
                    936:  */
                    937: 
                    938: static
                    939: rsioctl( dev, com, vec )
                    940: 
                    941: dev_t dev;
                    942: int com;
                    943: struct termio *vec;
                    944: 
                    945: {
                    946:        register int b;
                    947:        struct termio tb;
                    948: 
                    949:        switch (com) {
                    950: 
                    951:        case TCSETAW:   /* Set attributes after waiting for output to clear */
                    952:        case TCSETAF:   /* ditto, but also flush input queue */
                    953:        case TCSBRK:    /* wait for output to clear, send break */
                    954: 
                    955:                /*
                    956:                 * Delay until output queue is empty.
                    957:                 */
                    958:                while ( rsoutq.rq_ox != rsoutq.rq_ix ) {
                    959: 
                    960:                        /*
                    961:                         * Sleep waiting for empty output queue.
                    962:                         */
                    963:                        ++rstty.rt_drefc;
                    964:                        sleep( &rstty.rt_drefc, CVTTOUT, IVTTOUT, SVTTOUT);
                    965:                        --rstty.rt_drefc;
                    966: 
                    967:                        /*
                    968:                         * Abort if a non-ignored signal was received.
                    969:                         */
                    970:                        if ( SELF->p_ssig && nondsig() ) {
                    971:                                u.u_error = EINTR;
                    972:                                return;
                    973:                        }
                    974:                }
                    975: 
                    976:                if ( com == TCSBRK ) {
                    977: 
                    978:                        b = inb( PORT + LCR );
                    979: 
                    980:                        if ( vec == 0 ) {
                    981:                                rstty.rt_ticks  = 3;    /* 0.2 to 0.3 sec */
                    982:                                rstty.rt_state |= TTSBRK;
                    983:                                b |= LC_SBRK;
                    984:                        }
                    985:                        else {
                    986:                                rstty.rt_ticks  = 0;
                    987:                                rstty.rt_state &= ~TTSBRK;
                    988:                                b &= ~LC_SBRK;
                    989:                        }
                    990: 
                    991:                        outb( PORT + LCR, b );
                    992:                        return;
                    993:                }
                    994:                /* no break */
                    995: 
                    996:        case TCSETA:
                    997:                /*
                    998:                 * Get new terminal attributes.
                    999:                 */
                   1000:                ukcopy( vec, &tb, sizeof(tb) );
                   1001:                if ( u.u_error )
                   1002:                        return;
                   1003: 
                   1004:                /*
                   1005:                 * Set terminal attributes and hardware.
                   1006:                 */
                   1007:                rstty.rt_iflag = tb.c_iflag;
                   1008:                rstty.rt_oflag = tb.c_oflag;
                   1009:                if (rstty.rt_cflag != tb.c_cflag) {
                   1010:                        rstty.rt_cflag = tb.c_cflag;
                   1011:                        rsparam();
                   1012:                }
                   1013: 
                   1014:                if ((rstty.rt_iflag & IXON) == 0)
                   1015:                        rstty.rt_state &= ~TTSTOP;
                   1016: 
                   1017:                /*
                   1018:                 * Flush input queue if command was TCSETAF.
                   1019:                 */
                   1020:                if ( com == TCSETAF )
                   1021:                        rsrawq.rq_ox = rsrawq.rq_ix;
                   1022:                break;
                   1023: 
                   1024:        case TCGETA:    /* Get terminal attributes */
                   1025:                
                   1026:                memset( &tb, 0, sizeof(tb) );
                   1027:                tb.c_cflag = rstty.rt_cflag;
                   1028:                tb.c_iflag = rstty.rt_iflag;
                   1029:                tb.c_oflag = rstty.rt_oflag;
                   1030: 
                   1031:                /*
                   1032:                 * Transfer terminal attributes to user space.
                   1033:                 */
                   1034:                kucopy( &tb, vec, sizeof(tb) );
                   1035:                break;
                   1036: 
                   1037:        case TCFLSH:
                   1038:                switch ((int) vec) {
                   1039:                case 0:
                   1040:                        /* flush input queue */
                   1041:                        rsrawq.rq_ox = rsrawq.rq_ix;
                   1042:                        break;
                   1043:                case 1:
                   1044:                        /* flush output queue */
                   1045:                        rsoutq.rq_ox = rsoutq.rq_ix;
                   1046:                        break;
                   1047:                case 2:
                   1048:                        /* flush both input and output queues */
                   1049:                        rsrawq.rq_ox = rsrawq.rq_ix;
                   1050:                        rsoutq.rq_ox = rsoutq.rq_ix;
                   1051:                        break;
                   1052:                default:
                   1053:                        u.u_error = EINVAL;
                   1054:                }
                   1055:                break;
                   1056: 
                   1057:        case TCXONC:
                   1058:                switch ( (int) vec ) {
                   1059:                case 0:
                   1060:                        /* stop output */
                   1061:                        rstty.rt_state |= TTSTOP;
                   1062:                        break;
                   1063:                case 1:
                   1064:                        /* restart output */
                   1065:                        rstty.rt_state &= ~TTSTOP;
                   1066:                        rsstart();
                   1067:                        break;
                   1068:                default:
                   1069:                        u.u_error = EINVAL;
                   1070:                }
                   1071:                break;
                   1072: 
                   1073:        default:
                   1074:                u.u_error = EINVAL;
                   1075:        }
                   1076: }
                   1077: 
                   1078: /*
                   1079:  * Rsparam -- Setup hardware parameters.
                   1080:  */
                   1081: 
                   1082: static
                   1083: rsparam()
                   1084: {
                   1085:        register int b;
                   1086:        register int s;
                   1087: 
                   1088:        /*
                   1089:         * Disable interrupts.
                   1090:         */
                   1091:        s = sphi();
                   1092: 
                   1093:        /*
                   1094:         * Assert required modem control lines (DTR, RTS).
                   1095:         */
                   1096:        if ((rstty.rt_cflag & CBAUD) == B0)
                   1097:                outb( PORT+MCR, MC_OUT2 );
                   1098:        else if ((rstty.rt_refc == 0) && (rstty.rt_cflag & HUPCL))
                   1099:                outb( PORT+MCR, MC_OUT2 );
                   1100:        else
                   1101:                outb( PORT+MCR, MC_OUT2+MC_DTR+MC_RTS );
                   1102: 
                   1103:        /*
                   1104:         * Program baud rate.
                   1105:         */
                   1106:        if (b = timeconst[ rstty.rt_cflag & CBAUD ]) {
                   1107:                outb( PORT+LCR, LC_DLAB );
                   1108:                outb( PORT+DLL, b );
                   1109:                outb( PORT+DLH, b >> 8 );
                   1110:        }
                   1111: 
                   1112:        /*
                   1113:         * Program character size, parity, and stop bits.
                   1114:         */
                   1115:        switch (rstty.rt_cflag & CSIZE) {
                   1116:        case CS5:               b = LC_CS5;                     break;
                   1117:        case CS6:               b = LC_CS6;                     break;
                   1118:        case CS7:               b = LC_CS7;                     break;
                   1119:        case CS8:               b = LC_CS8;                     break;
                   1120:        }
                   1121: 
                   1122:        switch (rstty.rt_cflag & (PARENB|PARODD)) {
                   1123:        case PARENB:            b |= LC_PARENB|LC_PAREVEN;      break;
                   1124:        case PARENB|PARODD:     b |= LC_PARENB;                 break;
                   1125:        }
                   1126: 
                   1127:        if (rstty.rt_cflag & CSTOPB)
                   1128:                b |= LC_STOPB;
                   1129: 
                   1130:        if (rstty.rt_state & TTSBRK)
                   1131:                b |= LC_SBRK;
                   1132: 
                   1133:        outb( PORT+LCR, b );
                   1134: 
                   1135:        /*
                   1136:         * Enable desired interrupts.
                   1137:         */
                   1138:        b = 0;
                   1139:        if (rstty.rt_cflag & CBAUD) {
                   1140:                b = IE_TxI | IE_LSI;
                   1141:                if (rstty.rt_cflag & CREAD)
                   1142:                        b |= IE_RxI;
                   1143:        }
                   1144:        outb( PORT+IER, b );
                   1145: 
                   1146:        /*
                   1147:         * Enable interrupts.
                   1148:         */
                   1149:        spl( s );
                   1150: }

unix.superglobalmegacorp.com

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