Annotation of coherent/d/PS2_KERNEL/io.286/rs.c, revision 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.