Annotation of coherent/d/286_KERNEL/USRSRC/io/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/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.