Annotation of coherent/d/286_KERNEL/USRSRC/io/gc.c, revision 1.1.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.