Annotation of coherent/d/286_KERNEL/USRSRC/io/gc.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Interrupt Driver Multi-Port Device Driver.
        !             3:  * - supports version 7 compatible ioctl
        !             4:  */
        !             5: 
        !             6: #include "coherent.h"
        !             7: #include "ins8250.h"
        !             8: #include <sys/stat.h>
        !             9: #include <sys/uproc.h>
        !            10: #include <sys/proc.h>
        !            11: #include <sys/tty.h>           /* indirectly includes sgtty.h */
        !            12: #include <sys/con.h>
        !            13: #include <errno.h>
        !            14: #include <sys/timeout.h>       /* TIM */
        !            15: #include <sched.h>             /* CVTTOUT, IVTTOUT, SVTTOUT */
        !            16: #include <poll_clk.h>
        !            17: 
        !            18: /*
        !            19:  * Definitions.
        !            20:  *
        !            21:  * MAX_GCNUM is the maximum number of devices that can be polled
        !            22:  *   using this driver and can be revised up or down
        !            23:  * PORT is a convenience macro for the base address of a port
        !            24:  * port_config is the structure of the initial configuration for each
        !            25:  *   polled port;  note that "speed" is NOT the actual baud rate, but
        !            26:  *   the value of the symbol for that baud rate as defined in
        !            27:  *   /usr/include/sgtty.h
        !            28:  * GCINT is the IRQ number for the interrupt belonging to the board.
        !            29:  *   On the AT, IRQ2 is mapped to the same vector as IRQ9.
        !            30:  */
        !            31: #define MAX_GCNUM      8
        !            32: #define        PORT    ((int)(tp->t_ddp))
        !            33: struct port_config {
        !            34:        int     addr;   /* base address of the 8250-family UART */
        !            35:        int     speed;  /* B0..B19200 */
        !            36: };
        !            37: #define GCINT          2
        !            38: 
        !            39: /*
        !            40:  * Export Variables - these can be patched without recompiling and linking
        !            41:  *
        !            42:  * GCNUM is the actual number of polled serial ports, and should be
        !            43:  *   less than or equal to MAX_GCNUM
        !            44:  * GCIRPT is the I/O address of the multiport interrupt register;
        !            45:  *   a value of 0 in bit 0..3 means a pending interrupt for port 0..3
        !            46:  * GC_PORTS is an array of address/speed pairs, one for each port
        !            47:  */
        !            48: int    GCNUM = 4;
        !            49: int    GCIRPT = 0x2BF;
        !            50: /*
        !            51:  * Defaults are for PC COM4, Enhanced Mode, High Address.
        !            52:  */
        !            53: struct port_config GC_PORTS[MAX_GCNUM] = {
        !            54:        { 0x2A0, B9600 },
        !            55:        { 0x2A8, B9600 },
        !            56:        { 0x2B0, B9600 },
        !            57:        { 0x2B8, B9600 }
        !            58: };
        !            59: 
        !            60: /*
        !            61:  * Export Functions.
        !            62:  */
        !            63: int    gcload();
        !            64: int    gcopen();
        !            65: int    gcclose();
        !            66: int    gcread();
        !            67: int    gcwrite();
        !            68: int    gcioctl();
        !            69: int    gcunload();
        !            70: int    gcpoll();
        !            71: 
        !            72: int    gccycle();
        !            73: int    gcintr();
        !            74: int    gcparam();
        !            75: int    gcstart();
        !            76: 
        !            77: /*
        !            78:  * Import Functions
        !            79:  */
        !            80: int    nulldev();
        !            81: int    nonedev();
        !            82: 
        !            83: /*
        !            84:  * Configuration table.
        !            85:  */
        !            86: CON gccon ={
        !            87:        DFCHR|DFPOL,                    /* Flags */
        !            88:        GCINT,                          /* Major index */
        !            89:        gcopen,                         /* Open */
        !            90:        gcclose,                        /* Close */
        !            91:        nulldev,                        /* Block */
        !            92:        gcread,                         /* Read */
        !            93:        gcwrite,                        /* Write */
        !            94:        gcioctl,                        /* Ioctl */
        !            95:        nulldev,                        /* Powerfail */
        !            96:        nulldev,                        /* Timeout */
        !            97:        gcload,                         /* Load */
        !            98:        gcunload,                       /* Unload */
        !            99:        gcpoll                          /* Poll */
        !           100: };
        !           101: 
        !           102: /*
        !           103:  * Local variables.
        !           104:  */
        !           105: static TTY *hstty;
        !           106: static TTY *hslimtty;
        !           107: static TIM hstim;
        !           108: 
        !           109: /*
        !           110:  * Time constant table.
        !           111:  * Indexed by ioctl baud rate.
        !           112:  */
        !           113: static
        !           114: int timeconst[] = {
        !           115:        0,                              /* 0 */
        !           116:        2304,                           /* 50 */
        !           117:        1536,                           /* 75 */
        !           118:        1047,                           /* 110 */
        !           119:        857,                            /* 134.5 */
        !           120:        768,                            /* 150 */
        !           121:        576,                            /* 200 */
        !           122:        384,                            /* 300 */
        !           123:        192,                            /* 600 */
        !           124:        96,                             /* 1200 */
        !           125:        64,                             /* 1800 */
        !           126:        58,                             /* 2000 */
        !           127:        48,                             /* 2400 */
        !           128:        32,                             /* 3600 */
        !           129:        24,                             /* 4800 */
        !           130:        16,                             /* 7200 */
        !           131:        12,                             /* 9600 */
        !           132:        6,                              /* 19200 */
        !           133:        6,                              /* EXTA */
        !           134:        6                               /* EXTB */
        !           135: };
        !           136: 
        !           137: /*
        !           138:  * Load Routine.
        !           139:  */
        !           140: static gcload()
        !           141: {
        !           142:        register TTY * tp;
        !           143:        register int port;
        !           144:        int i, b, s;
        !           145: 
        !           146:        if ((hstty = (TTY *)kalloc(GCNUM*sizeof(TTY))) == 0) {
        !           147:                printf("gcload: can't allocate tty's\n");
        !           148:                return;
        !           149:        }
        !           150:        kclear(hstty, GCNUM*sizeof(TTY));
        !           151: 
        !           152:        s = sphi();
        !           153:        for (i = 0; i < GCNUM; i++) {
        !           154:                port = GC_PORTS[i].addr;
        !           155:                tp = hstty + i;
        !           156: 
        !           157:                outb( port+MCR, 0 );
        !           158:                outb( port+IER, 0 );
        !           159: 
        !           160:                if ( inb( port+IER ) )
        !           161:                        break;
        !           162: 
        !           163:                tp->t_cs_sel  = cs_sel();
        !           164:                tp->t_start   = gcstart;
        !           165:                tp->t_param   = gcparam;
        !           166:                tp->t_sgttyb.sg_ospeed = tp->t_sgttyb.sg_ispeed = 
        !           167:                tp->t_dispeed = tp->t_dospeed = GC_PORTS[i].speed;
        !           168:                tp->t_ddp     = port;
        !           169: 
        !           170:                b = timeconst[ tp->t_sgttyb.sg_ospeed ];
        !           171:                outb( port+LCR, LC_DLAB );
        !           172:                outb( port+DLL, b );
        !           173:                outb( port+DLH, b >> 8);
        !           174:                outb( port+LCR, LC_CS8);
        !           175: 
        !           176:                hslimtty = tp;
        !           177:        }
        !           178:        setivec(GCINT, gcintr);
        !           179:        spl(s);
        !           180: }
        !           181: 
        !           182: static gcunload()
        !           183: {
        !           184:        clrivec(GCINT);
        !           185:        kfree(hstty);
        !           186: }
        !           187: 
        !           188: /*
        !           189:  * Open Routine.
        !           190:  */
        !           191: gcopen( dev, mode )
        !           192: dev_t dev;
        !           193: {
        !           194:        register TTY * tp = &hstty[ dev & 15 ];
        !           195:        register int b;
        !           196:        int s;
        !           197: 
        !           198:        /*
        !           199:         * Verify hardware exists.
        !           200:         */
        !           201:        if ( (PORT == 0) || (inb(PORT+IER) & ~IE_TxI) ) {
        !           202:                u.u_error = ENXIO;
        !           203:                return;
        !           204:        }
        !           205: 
        !           206:        /*
        !           207:         * Initialize if not already open.
        !           208:         */
        !           209:        if ( ++tp->t_open == 1 ) {
        !           210:                ttopen( tp );
        !           211: 
        !           212:                if ( dev & 0x80 ) {
        !           213:                        s = sphi();
        !           214:                        b = inb(PORT+MSR);
        !           215:                        tp->t_flags |= T_MODC + T_STOP;
        !           216:                        if ( b & MS_CTS )
        !           217:                                tp->t_flags &= ~T_STOP;
        !           218:                        if ( b & MS_DSR )
        !           219:                                tp->t_flags |=  T_CARR;
        !           220:                        spl( s );
        !           221:                } else  {
        !           222:                        tp->t_flags &= ~T_MODC;
        !           223:                        tp->t_flags |=  T_CARR;
        !           224:                }
        !           225:                gccycle( tp );
        !           226:        }
        !           227:        ttsetgrp( tp, dev );
        !           228: }
        !           229: 
        !           230: /*
        !           231:  * Close Routine.
        !           232:  */
        !           233: gcclose( dev )
        !           234: dev_t dev;
        !           235: {
        !           236:        register TTY * tp = &hstty[ dev & 15 ];
        !           237: 
        !           238:        /*
        !           239:         * Reset if last close.
        !           240:         */
        !           241:        if ( tp->t_open == 1 ) {
        !           242:                int state;
        !           243: 
        !           244:                ttclose( tp );
        !           245:                /*
        !           246:                 * ttclose() only emptied the output queue tp->t_oq;
        !           247:                 * now wait 0.1 sec for the silo tp->rawout to empty
        !           248:                 * and allow a delay for the UART on-chip xmit buffer to empty
        !           249:                 *
        !           250:                 * state 2: waiting for silo to empty
        !           251:                 * state 1: stalling so UART can empty xmit buffer
        !           252:                 * state 0: done!
        !           253:                 */
        !           254:                state = 2;
        !           255:                while (state) {
        !           256:                        timeout(&hstim, 10, wakeup, (int)&hstim);
        !           257:                        sleep((char *)&hstim, CVTTOUT, IVTTOUT, SVTTOUT);
        !           258:                        if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
        !           259:                                state--;
        !           260:                }
        !           261:        }
        !           262: 
        !           263:        --tp->t_open;
        !           264: }
        !           265: 
        !           266: /*
        !           267:  * Read Routine.
        !           268:  */
        !           269: gcread( dev, iop )
        !           270: dev_t dev;
        !           271: register IO * iop;
        !           272: {
        !           273:        ttread( &hstty[ dev & 15 ], iop, 0 );
        !           274: }
        !           275: 
        !           276: /*
        !           277:  * Write Routine.
        !           278:  */
        !           279: gcwrite( dev, iop )
        !           280: dev_t dev;
        !           281: register IO * iop;
        !           282: {
        !           283:        ttwrite( &hstty[ dev & 15 ], iop, 0 );
        !           284: }
        !           285: 
        !           286: /*
        !           287:  * Ioctl Routine.
        !           288:  */
        !           289: gcioctl( dev, com, vec )
        !           290: dev_t dev;
        !           291: int com;
        !           292: struct sgttyb * vec;
        !           293: {
        !           294:        ttioctl( &hstty[ dev & 15 ], com, vec );
        !           295: }
        !           296: 
        !           297: /*
        !           298:  * Polling Routine.
        !           299:  */
        !           300: gcpoll( dev, ev, msec )
        !           301: dev_t dev;
        !           302: int ev;
        !           303: int msec;
        !           304: {
        !           305:        return ttpoll( &hstty[ dev & 15 ], ev, msec );
        !           306: }
        !           307: 
        !           308: /*
        !           309:  * Cyclic routine - invoked every clock tick to perform raw input/output.
        !           310:  *
        !           311:  *     Notes:  Invoked 10 times per second.
        !           312:  */
        !           313: gccycle( tp )
        !           314: register TTY * tp;
        !           315: {
        !           316:        register int resid;
        !           317:        register int c;
        !           318: 
        !           319:        /*
        !           320:         * Process rawin buf.
        !           321:         */
        !           322:        while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {
        !           323: 
        !           324:                ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );
        !           325: 
        !           326:                if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
        !           327:                        tp->t_rawin.si_ox = 0;
        !           328:                else
        !           329:                        tp->t_rawin.si_ox++;
        !           330:        }
        !           331: 
        !           332:        /*
        !           333:         * Calculate free output slot count.
        !           334:         */
        !           335:        resid  = sizeof(tp->t_rawout.si_buf) - 1;
        !           336:        resid += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
        !           337:        resid %= sizeof(tp->t_rawout.si_buf);
        !           338: 
        !           339:        /*
        !           340:         * Fill raw output buffer.
        !           341:         */
        !           342:        while ( (--resid >= 0) && ((c = ttout(tp)) >= 0) ) {
        !           343: 
        !           344:                tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = c;
        !           345: 
        !           346:                if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
        !           347:                        tp->t_rawout.si_ix = 0;
        !           348:                else
        !           349:                        tp->t_rawout.si_ix++;
        !           350:        }
        !           351: 
        !           352:        /*
        !           353:         * (Re)start output, waking processes waiting to output, etc.
        !           354:         */
        !           355:        ttstart( tp );
        !           356: 
        !           357:        /*
        !           358:         * Schedule next cycle.
        !           359:         */
        !           360:        if ( tp->t_open != 0 )
        !           361:                timeout( &tp->t_rawtim, HZ/10, gccycle, tp );
        !           362: }
        !           363: 
        !           364: /*
        !           365:  * Interrupt driven Polling routine.
        !           366:  */
        !           367: gcintr()
        !           368: {
        !           369:        register TTY * tp = &hstty[0];
        !           370:        register int b;
        !           371: 
        !           372:        do {
        !           373:                if ( tp->t_open == 0 )
        !           374:                        continue;
        !           375: 
        !           376:                /*
        !           377:                 * Check modem status if modem control is enabled.
        !           378:                 */
        !           379:                if ( tp->t_flags & T_MODC ) {
        !           380: 
        !           381:                        b = inb( PORT+MSR );
        !           382: 
        !           383:                        if ( b & (MS_DCTS|MS_DDSR) ) {
        !           384: 
        !           385:                                if ( b & MS_DCTS ) {
        !           386:                                        if ( b & MS_CTS )
        !           387:                                                tp->t_flags &= ~T_STOP;
        !           388:                                        else
        !           389:                                                tp->t_flags |=  T_STOP;
        !           390:                                }
        !           391:                                if ( b & MS_DDSR ) {
        !           392:                                        if ( b & MS_DSR )
        !           393:                                                tp->t_flags |=  T_CARR;
        !           394:                                        else {
        !           395:                                                tp->t_flags &= ~T_CARR;
        !           396:                                                tthup( tp );
        !           397:                                        }
        !           398:                                }
        !           399:                        }
        !           400:                }
        !           401: 
        !           402:                b = inb( PORT+LSR );
        !           403: 
        !           404:                if ( (b & LS_BREAK) && (tp->t_flags & T_CARR) )
        !           405:                        ttsignal( tp, SIGINT );
        !           406: 
        !           407:                /*
        !           408:                 * Receive ready.
        !           409:                 */
        !           410:                if ( b & LS_RxRDY ) {
        !           411: 
        !           412:                        tp->t_rawin.si_buf[tp->t_rawin.si_ix] = inb(PORT+DREG);
        !           413: 
        !           414:                        if ( tp->t_flags & T_CARR ) {
        !           415: 
        !           416:                                if ( ++(tp->t_rawin.si_ix) >=
        !           417:                                                sizeof(tp->t_rawin.si_buf) )
        !           418:                                        tp->t_rawin.si_ix = 0;
        !           419:                        }
        !           420:                }
        !           421: 
        !           422:                /*
        !           423:                 * Transmit ready and raw output data exists.
        !           424:                 */
        !           425:                if ( (b & LS_TxRDY) && ((tp->t_flags & T_STOP) == 0)
        !           426:                  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {
        !           427: 
        !           428:                        outb(   PORT+DREG,
        !           429:                                tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );
        !           430: 
        !           431:                        if ( ++(tp->t_rawout.si_ox) >=
        !           432:                                        sizeof(tp->t_rawout.si_buf) )
        !           433:                                tp->t_rawout.si_ox = 0;
        !           434:                }
        !           435: 
        !           436:        } while ( ++tp <= hslimtty );
        !           437: }
        !           438: 
        !           439: /*
        !           440:  * Set hardware parameters.
        !           441:  */
        !           442: gcparam( tp )
        !           443: register TTY * tp;
        !           444: {
        !           445:        register int b;
        !           446:        int s;
        !           447: 
        !           448:        s = sphi();
        !           449:        /*
        !           450:         * Assert required modem control lines (DTR, RTS).
        !           451:         */
        !           452:        b = 0;
        !           453:        if ( tp->t_sgttyb.sg_ospeed != B0 )
        !           454:                b |=  MC_DTR | MC_RTS;
        !           455:        outb( PORT+MCR, b );
        !           456: 
        !           457:        /*
        !           458:         * Program baud rate.
        !           459:         */
        !           460:        if (b = timeconst[ tp->t_sgttyb.sg_ospeed ]) {
        !           461:                outb( PORT+LCR, LC_DLAB );
        !           462:                outb( PORT+DLL, b );
        !           463:                outb( PORT+DLH, b >> 8 );
        !           464:        }
        !           465: 
        !           466:        /*
        !           467:         * Program character size, parity.
        !           468:         */
        !           469:        switch ( tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW) ) {
        !           470:        case ODDP:              b = LC_CS7|LC_PARENB;            break;
        !           471:        case EVENP:             b = LC_CS7|LC_PARENB|LC_PAREVEN; break;
        !           472:        default:                b = LC_CS8;                      break;
        !           473:        }
        !           474:        outb( PORT+LCR, b );
        !           475: 
        !           476:        /*
        !           477:         * Enable Transmit Buffer Empty Interrupts.
        !           478:         */
        !           479:        outb( PORT+IER, IE_TxI );
        !           480: 
        !           481:        spl(s);
        !           482: }
        !           483: 
        !           484: /*
        !           485:  * Start Routine.
        !           486:  */
        !           487: gcstart( tp )
        !           488: register TTY * tp;
        !           489: {
        !           490:        register int s;
        !           491: 
        !           492:        /*
        !           493:         * Transmit buffer is empty, and raw output buffer is not.
        !           494:         */
        !           495:        s = sphi();
        !           496:        if ( (inb( PORT+LSR ) & LS_TxRDY)
        !           497:          && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {
        !           498: 
        !           499:                /*
        !           500:                 * Send next char from raw output buffer.
        !           501:                 */
        !           502:                outb( PORT+DREG, tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );
        !           503: 
        !           504:                if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
        !           505:                        tp->t_rawout.si_ox = 0;
        !           506:        }
        !           507:        spl( s );
        !           508: }

unix.superglobalmegacorp.com

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