Annotation of coherent/d/kernel/USRSRC/i8086/drv/hs.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:  * Polled Serial Port Device Driver.
        !             8:  * - supports version 7 compatible ioctl
        !             9:  */
        !            10: 
        !            11: #include <sys/coherent.h>
        !            12: #include <sys/ins8250.h>
        !            13: #include <sys/stat.h>
        !            14: #include <sys/uproc.h>
        !            15: #include <sys/proc.h>
        !            16: #include <sys/tty.h>           /* indirectly includes sgtty.h */
        !            17: #include <sys/con.h>
        !            18: #include <sys/devices.h>
        !            19: #include <errno.h>
        !            20: #include <sys/sched.h>         /* CVTTOUT, IVTTOUT, SVTTOUT */
        !            21: #include <sys/poll_clk.h>
        !            22: 
        !            23: /*
        !            24:  * Definitions.
        !            25:  *
        !            26:  * HSBAUD is the highest baud rate supported by this driver
        !            27:  * HS_HZ is the polling rate, i.e. the number of times per second
        !            28:  *   at which all open ports are checked for input, output, and
        !            29:  *   line status changes
        !            30:  * MAX_HSNUM is the maximum number of devices that can be polled
        !            31:  *   using this driver and can be revised up or down
        !            32:  * PORT is a convenience macro for the base address of a port
        !            33:  * port_config is the structure of the initial configuration for each
        !            34:  *   polled port;  note that "speed" is NOT the actual baud rate, but
        !            35:  *   the value of the symbol for that baud rate as defined in
        !            36:  *   /usr/include/sgtty.h
        !            37:  */
        !            38: #define        HSBAUD  9600
        !            39: #define        HS_HZ   (HSBAUD/6)
        !            40: #define MAX_HSNUM      8
        !            41: #define        PORT    ((int)(tp->t_ddp))
        !            42: struct port_config {
        !            43:        int     addr;   /* base address of the 8250-family UART */
        !            44:        int     speed;  /* B0..B19200 */
        !            45: };
        !            46: 
        !            47: /*
        !            48:  * Export Variables - these can be patched without recompiling and linking
        !            49:  *
        !            50:  * HSNUM is the actual number of polled serial ports, and should be
        !            51:  *   less than or equal to MAX_HSNUM
        !            52:  * HS_PORTS is an array of address/speed pairs, one for each port
        !            53:  */
        !            54: int    HSNUM = 4;
        !            55: struct port_config HS_PORTS[MAX_HSNUM] = {
        !            56:        { 0x3F8, B9600 },
        !            57:        { 0x2F8, B9600 },
        !            58:        { 0x3E8, B9600 },
        !            59:        { 0x2E8, B9600 }
        !            60: };
        !            61: 
        !            62: /*
        !            63:  * Export Functions.
        !            64:  */
        !            65: int    hsload();
        !            66: int    hsopen();
        !            67: int    hsclose();
        !            68: int    hsread();
        !            69: int    hswrite();
        !            70: int    hsioctl();
        !            71: int    hsunload();
        !            72: int    hspoll();
        !            73: 
        !            74: int    hscycle();
        !            75: int    hsintr();
        !            76: int    hsparam();
        !            77: int    hsstart();
        !            78: int    hsclk();
        !            79: int    set_poll_rate();
        !            80: 
        !            81: /*
        !            82:  * Import Functions
        !            83:  */
        !            84: int    nulldev();
        !            85: int    nonedev();
        !            86: 
        !            87: /*
        !            88:  * Configuration table.
        !            89:  */
        !            90: CON hscon ={
        !            91:        DFCHR|DFPOL,                    /* Flags */
        !            92:        HS_MAJOR,                       /* Major index */
        !            93:        hsopen,                         /* Open */
        !            94:        hsclose,                        /* Close */
        !            95:        nulldev,                        /* Block */
        !            96:        hsread,                         /* Read */
        !            97:        hswrite,                        /* Write */
        !            98:        hsioctl,                        /* Ioctl */
        !            99:        nulldev,                        /* Powerfail */
        !           100:        nulldev,                        /* Timeout */
        !           101:        hsload,                         /* Load */
        !           102:        hsunload,                       /* Unload */
        !           103:        hspoll                          /* Poll */
        !           104: };
        !           105: 
        !           106: /*
        !           107:  * Local variables.
        !           108:  */
        !           109: static TTY *hstty;
        !           110: static TTY *hslimtty;
        !           111: static TIM hstim;
        !           112: static int poll_divisor;       /* used in hsclk() and set_poll_rate() */
        !           113: 
        !           114: /*
        !           115:  * Time constant table.
        !           116:  * Indexed by ioctl baud rate.
        !           117:  */
        !           118: static
        !           119: int timeconst[] = {
        !           120:        0,                              /* 0 */
        !           121:        2304,                           /* 50 */
        !           122:        1536,                           /* 75 */
        !           123:        1047,                           /* 110 */
        !           124:        857,                            /* 134.5 */
        !           125:        768,                            /* 150 */
        !           126:        576,                            /* 200 */
        !           127:        384,                            /* 300 */
        !           128:        192,                            /* 600 */
        !           129:        96,                             /* 1200 */
        !           130:        64,                             /* 1800 */
        !           131:        58,                             /* 2000 */
        !           132:        48,                             /* 2400 */
        !           133:        32,                             /* 3600 */
        !           134:        24,                             /* 4800 */
        !           135:        16,                             /* 7200 */
        !           136:        12,                             /* 9600 */
        !           137:        6,                              /* 19200 */
        !           138:        6,                              /* EXTA */
        !           139:        6                               /* EXTB */
        !           140: };
        !           141: 
        !           142: /*
        !           143:  * poll_hz[] is tied to timeconst[] - it gives the minimum polling
        !           144:  *     rate for the corresponding port speed; it must be a multiple
        !           145:  *     of 100 (system clock Hz) and >= baud/6
        !           146:  */
        !           147: int poll_hz[] ={
        !           148:        0,                              /* 0 */
        !           149:        1*HZ,                           /* 50 */
        !           150:        1*HZ,                           /* 75 */
        !           151:        1*HZ,                           /* 110 */
        !           152:        1*HZ,                           /* 134.5 */
        !           153:        1*HZ,                           /* 150 */
        !           154:        1*HZ,                           /* 200 */
        !           155:        1*HZ,                           /* 300 */
        !           156:        1*HZ,                           /* 600 */
        !           157:        2*HZ,                           /* 1200 */
        !           158:        3*HZ,                           /* 1800 */
        !           159:        4*HZ,                           /* 2000 */
        !           160:        4*HZ,                           /* 2400 */
        !           161:        6*HZ,                           /* 3600 */
        !           162:        8*HZ,                           /* 4800 */
        !           163:        12*HZ,                          /* 7200 */
        !           164:        16*HZ,                          /* 9600 */
        !           165:        0,                              /* 19200 */
        !           166:        0,                              /* EXTA */
        !           167:        0                               /* EXTB */
        !           168: };
        !           169: 
        !           170: /*
        !           171:  * Load Routine.
        !           172:  */
        !           173: static hsload()
        !           174: {
        !           175:        register TTY * tp;
        !           176:        register int port;
        !           177:        int i, b;
        !           178: 
        !           179:        if ((hstty = (TTY *)kalloc(HSNUM*sizeof(TTY))) == 0) {
        !           180:                printf("hsload: can't allocate tty's\n");
        !           181:                return;
        !           182:        }
        !           183:        kclear(hstty, HSNUM*sizeof(TTY));
        !           184: 
        !           185:        for (i = 0; i < HSNUM; i++) {
        !           186:                port = HS_PORTS[i].addr;
        !           187:                tp = hstty + i;
        !           188: 
        !           189:                outb( port+MCR, 0 );
        !           190:                outb( port+IER, 0 );
        !           191: 
        !           192:                if ( inb( port+IER ) )
        !           193:                        break;
        !           194: 
        !           195:                tp->t_cs_sel  = cs_sel();
        !           196:                tp->t_start   = hsstart;
        !           197:                tp->t_param   = hsparam;
        !           198:                tp->t_sgttyb.sg_ospeed = tp->t_sgttyb.sg_ispeed = 
        !           199:                tp->t_dispeed = tp->t_dospeed = HS_PORTS[i].speed;
        !           200:                tp->t_ddp     = port;
        !           201: 
        !           202:                b = timeconst[ tp->t_sgttyb.sg_ospeed ];
        !           203:                outb( port+LCR, LC_DLAB );
        !           204:                outb( port+DLL, b );
        !           205:                outb( port+DLH, b >> 8);
        !           206:                outb( port+LCR, LC_CS8);
        !           207: 
        !           208:                hslimtty = tp;
        !           209:        }
        !           210: }
        !           211: 
        !           212: static hsunload()
        !           213: {
        !           214:        if (hstty != (TTY *)0)
        !           215:                kfree(hstty);
        !           216: }
        !           217: 
        !           218: /*
        !           219:  * Open Routine.
        !           220:  */
        !           221: hsopen( dev, mode )
        !           222: dev_t dev;
        !           223: {
        !           224:        register TTY * tp = &hstty[ dev & 15 ];
        !           225:        register int b;
        !           226:        int s;
        !           227: 
        !           228:        /*
        !           229:         * Verify hardware exists.
        !           230:         */
        !           231:        if ( (PORT == 0) || (inb(PORT+IER) & ~IE_TxI) ) {
        !           232:                u.u_error = ENXIO;
        !           233:                return;
        !           234:        }
        !           235: 
        !           236:        /*
        !           237:         * Can't open if another driver is using polling
        !           238:         */
        !           239:        if (poll_owner & ~ POLL_HS) {
        !           240:                u.u_error = EDBUSY;
        !           241:                return;
        !           242:        }
        !           243: 
        !           244:        /*
        !           245:         * Initialize if not already open.
        !           246:         */
        !           247:        if ( ++tp->t_open == 1 ) {
        !           248:                ttopen( tp );
        !           249: 
        !           250:                if ( dev & 0x80 ) {
        !           251:                        s = sphi();
        !           252:                        b = inb(PORT+MSR);
        !           253:                        tp->t_flags |= T_MODC + T_STOP;
        !           254:                        if ( b & MS_CTS )
        !           255:                                tp->t_flags &= ~T_STOP;
        !           256:                        if ( b & MS_DSR )
        !           257:                                tp->t_flags |=  T_CARR;
        !           258:                        spl( s );
        !           259:                } else  {
        !           260:                        tp->t_flags &= ~T_MODC;
        !           261:                        tp->t_flags |=  T_CARR;
        !           262:                }
        !           263:                hscycle( tp );
        !           264:        }
        !           265:        ttsetgrp( tp, dev );
        !           266:        set_poll_rate();
        !           267: }
        !           268: 
        !           269: /*
        !           270:  * Close Routine.
        !           271:  */
        !           272: hsclose( dev )
        !           273: dev_t dev;
        !           274: {
        !           275:        register TTY * tp = &hstty[ dev & 15 ];
        !           276: 
        !           277:        /*
        !           278:         * Reset if last close.
        !           279:         */
        !           280:        if ( tp->t_open == 1 ) {
        !           281:                int state;
        !           282: 
        !           283:                ttclose( tp );
        !           284:                /*
        !           285:                 * ttclose() only emptied the output queue tp->t_oq;
        !           286:                 * now wait 0.1 sec for the silo tp->rawout to empty
        !           287:                 * and allow a delay for the UART on-chip xmit buffer to empty
        !           288:                 *
        !           289:                 * state 2: waiting for silo to empty
        !           290:                 * state 1: stalling so UART can empty xmit buffer
        !           291:                 * state 0: done!
        !           292:                 */
        !           293:                state = 2;
        !           294:                while (state) {
        !           295:                        timeout(&hstim, 10, wakeup, (int)&hstim);
        !           296:                        sleep((char *)&hstim, CVTTOUT, IVTTOUT, SVTTOUT);
        !           297:                        if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
        !           298:                                state--;
        !           299:                }
        !           300:        }
        !           301: 
        !           302:        --tp->t_open;
        !           303:        set_poll_rate();
        !           304: }
        !           305: 
        !           306: /*
        !           307:  * Read Routine.
        !           308:  */
        !           309: hsread( dev, iop )
        !           310: dev_t dev;
        !           311: register IO * iop;
        !           312: {
        !           313:        ttread( &hstty[ dev & 15 ], iop, 0 );
        !           314: }
        !           315: 
        !           316: /*
        !           317:  * Write Routine.
        !           318:  */
        !           319: hswrite( dev, iop )
        !           320: dev_t dev;
        !           321: register IO * iop;
        !           322: {
        !           323:        ttwrite( &hstty[ dev & 15 ], iop, 0 );
        !           324: }
        !           325: 
        !           326: /*
        !           327:  * Ioctl Routine.
        !           328:  */
        !           329: hsioctl( dev, com, vec )
        !           330: dev_t dev;
        !           331: int com;
        !           332: struct sgttyb * vec;
        !           333: {
        !           334:        ttioctl( &hstty[ dev & 15 ], com, vec );
        !           335: }
        !           336: 
        !           337: /*
        !           338:  * Polling Routine.
        !           339:  */
        !           340: hspoll( dev, ev, msec )
        !           341: dev_t dev;
        !           342: int ev;
        !           343: int msec;
        !           344: {
        !           345:        return ttpoll( &hstty[ dev & 15 ], ev, msec );
        !           346: }
        !           347: 
        !           348: /*
        !           349:  * Cyclic routine - invoked every clock tick to perform raw input/output.
        !           350:  *
        !           351:  *     Notes:  Invoked 10 times per second.
        !           352:  */
        !           353: hscycle( tp )
        !           354: register TTY * tp;
        !           355: {
        !           356:        register int resid;
        !           357:        register int c;
        !           358: 
        !           359:        /*
        !           360:         * Process rawin buf.
        !           361:         */
        !           362:        while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {
        !           363: 
        !           364:                ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );
        !           365: 
        !           366:                if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
        !           367:                        tp->t_rawin.si_ox = 0;
        !           368:                else
        !           369:                        tp->t_rawin.si_ox++;
        !           370:        }
        !           371: 
        !           372:        /*
        !           373:         * Calculate free output slot count.
        !           374:         */
        !           375:        resid  = sizeof(tp->t_rawout.si_buf) - 1;
        !           376:        resid += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
        !           377:        resid %= sizeof(tp->t_rawout.si_buf);
        !           378: 
        !           379:        /*
        !           380:         * Fill raw output buffer.
        !           381:         */
        !           382:        while ( (--resid >= 0) && ((c = ttout(tp)) >= 0) ) {
        !           383: 
        !           384:                tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = c;
        !           385: 
        !           386:                if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
        !           387:                        tp->t_rawout.si_ix = 0;
        !           388:                else
        !           389:                        tp->t_rawout.si_ix++;
        !           390:        }
        !           391: 
        !           392:        /*
        !           393:         * (Re)start output, waking processes waiting to output, etc.
        !           394:         */
        !           395:        ttstart( tp );
        !           396: 
        !           397:        /*
        !           398:         * Schedule next cycle.
        !           399:         */
        !           400:        if ( tp->t_open != 0 )
        !           401:                timeout( &tp->t_rawtim, HZ/10, hscycle, tp );
        !           402: }
        !           403: 
        !           404: /*
        !           405:  * Clock Interrupt driven Polling routine.
        !           406:  */
        !           407: hsintr()
        !           408: {
        !           409:        register TTY * tp = &hstty[0];
        !           410:        register int b;
        !           411: 
        !           412:        do {
        !           413:                if ( tp->t_open == 0 )
        !           414:                        continue;
        !           415: 
        !           416:                /*
        !           417:                 * Check modem status if modem control is enabled.
        !           418:                 */
        !           419:                if ( tp->t_flags & T_MODC ) {
        !           420: 
        !           421:                        b = inb( PORT+MSR );
        !           422: 
        !           423:                        if ( b & (MS_DCTS|MS_DDSR) ) {
        !           424: 
        !           425:                                if ( b & MS_DCTS ) {
        !           426:                                        if ( b & MS_CTS )
        !           427:                                                tp->t_flags &= ~T_STOP;
        !           428:                                        else
        !           429:                                                tp->t_flags |=  T_STOP;
        !           430:                                }
        !           431:                                if ( b & MS_DDSR ) {
        !           432:                                        if ( b & MS_DSR )
        !           433:                                                tp->t_flags |=  T_CARR;
        !           434:                                        else {
        !           435:                                                tp->t_flags &= ~T_CARR;
        !           436:                                                tthup( tp );
        !           437:                                        }
        !           438:                                }
        !           439:                        }
        !           440:                }
        !           441: 
        !           442:                b = inb( PORT+LSR );
        !           443: 
        !           444:                if ( (b & LS_BREAK) && (tp->t_flags & T_CARR) )
        !           445:                        ttsignal( tp, SIGINT );
        !           446: 
        !           447:                /*
        !           448:                 * Receive ready.
        !           449:                 */
        !           450:                if ( b & LS_RxRDY ) {
        !           451: 
        !           452:                        tp->t_rawin.si_buf[tp->t_rawin.si_ix] = inb(PORT+DREG);
        !           453: 
        !           454:                        if ( tp->t_flags & T_CARR ) {
        !           455: 
        !           456:                                if ( ++(tp->t_rawin.si_ix) >=
        !           457:                                                sizeof(tp->t_rawin.si_buf) )
        !           458:                                        tp->t_rawin.si_ix = 0;
        !           459:                        }
        !           460:                }
        !           461: 
        !           462:                /*
        !           463:                 * Transmit ready and raw output data exists.
        !           464:                 */
        !           465:                if ( (b & LS_TxRDY) && ((tp->t_flags & T_STOP) == 0)
        !           466:                  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {
        !           467: 
        !           468:                        outb(   PORT+DREG,
        !           469:                                tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );
        !           470: 
        !           471:                        if ( ++(tp->t_rawout.si_ox) >=
        !           472:                                        sizeof(tp->t_rawout.si_buf) )
        !           473:                                tp->t_rawout.si_ox = 0;
        !           474:                }
        !           475: 
        !           476:        } while ( ++tp <= hslimtty );
        !           477: }
        !           478: 
        !           479: /*
        !           480:  * Set hardware parameters.
        !           481:  */
        !           482: hsparam( tp )
        !           483: register TTY * tp;
        !           484: {
        !           485:        register int b;
        !           486:        int s;
        !           487: 
        !           488:        s = sphi();
        !           489:        /*
        !           490:         * Assert required modem control lines (DTR, RTS).
        !           491:         */
        !           492:        b = 0;
        !           493:        if ( tp->t_sgttyb.sg_ospeed != B0 )
        !           494:                b |=  MC_DTR | MC_RTS;
        !           495:        outb( PORT+MCR, b );
        !           496: 
        !           497:        /*
        !           498:         * Program baud rate.
        !           499:         */
        !           500:        if (b = timeconst[ tp->t_sgttyb.sg_ospeed ]) {
        !           501:                outb( PORT+LCR, LC_DLAB );
        !           502:                outb( PORT+DLL, b );
        !           503:                outb( PORT+DLH, b >> 8 );
        !           504:        }
        !           505: 
        !           506:        /*
        !           507:         * Program character size, parity.
        !           508:         */
        !           509:        switch ( tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW) ) {
        !           510:        case ODDP:              b = LC_CS7|LC_PARENB;            break;
        !           511:        case EVENP:             b = LC_CS7|LC_PARENB|LC_PAREVEN; break;
        !           512:        default:                b = LC_CS8;                      break;
        !           513:        }
        !           514:        outb( PORT+LCR, b );
        !           515: 
        !           516:        /*
        !           517:         * Enable Transmit Buffer Empty Interrupts.
        !           518:         */
        !           519:        outb( PORT+IER, IE_TxI );
        !           520: 
        !           521:        spl(s);
        !           522:        set_poll_rate();
        !           523: }
        !           524: 
        !           525: /*
        !           526:  * Start Routine.
        !           527:  */
        !           528: hsstart( tp )
        !           529: register TTY * tp;
        !           530: {
        !           531:        register int s;
        !           532: 
        !           533:        /*
        !           534:         * Transmit buffer is empty, and raw output buffer is not.
        !           535:         */
        !           536:        s = sphi();
        !           537:        if ( (inb( PORT+LSR ) & LS_TxRDY)
        !           538:          && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {
        !           539: 
        !           540:                /*
        !           541:                 * Send next char from raw output buffer.
        !           542:                 */
        !           543:                outb( PORT+DREG, tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );
        !           544: 
        !           545:                if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
        !           546:                        tp->t_rawout.si_ox = 0;
        !           547:        }
        !           548:        spl( s );
        !           549: }
        !           550: 
        !           551: /*
        !           552:  * hsclk will be called every time T0 interrupts - if it returns 0,
        !           553:  * the usual system timer interrupt stuff is done
        !           554:  */
        !           555: static int hsclk()
        !           556: {
        !           557:   static int count;
        !           558: 
        !           559:   hsintr();
        !           560:   count++;
        !           561:   if (count >= poll_divisor)
        !           562:     count = 0;
        !           563:   return count;
        !           564: }
        !           565: 
        !           566: /*
        !           567:  * set_poll_rate is called when a port is opened or closed or changes speed
        !           568:  * it sets the polling rate only as fast as needed, and shuts off polling
        !           569:  * whenever possible
        !           570:  */
        !           571: static set_poll_rate()
        !           572: {
        !           573:        int port_num, max_rate, port_rate;
        !           574: 
        !           575:        /*
        !           576:         * If another driver has the polling clock, do nothing.
        !           577:         */
        !           578:        if (poll_owner & ~ POLL_HS)
        !           579:                return;
        !           580: 
        !           581:        /*
        !           582:         * find highest valid polling rate in units of HZ/10
        !           583:         */
        !           584:        max_rate = 0;
        !           585:        for (port_num = 0; port_num < HSNUM; port_num++) {
        !           586:                if (hstty[port_num].t_open) {
        !           587:                  port_rate = poll_hz[hstty[port_num].t_sgttyb.sg_ispeed];
        !           588:                  if (max_rate < port_rate)
        !           589:                        max_rate = port_rate;
        !           590:                }
        !           591:        }
        !           592:        /*
        !           593:         * if max_rate is not current rate, adjust the system clock
        !           594:         */
        !           595:        if (max_rate != poll_rate) {
        !           596:                poll_rate = max_rate;
        !           597:                poll_divisor = poll_rate/HZ;  /* used in hsclk() */
        !           598:                altclk_out();           /* stop previous polling */
        !           599:                poll_owner &= ~POLL_HS;
        !           600:                if (max_rate) { /* resume polling at new rate if needed */
        !           601:                        altclk_in(poll_rate, hsclk);
        !           602:                        poll_owner |= POLL_HS;
        !           603:                }
        !           604:        }
        !           605: }

unix.superglobalmegacorp.com

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