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

unix.superglobalmegacorp.com

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