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

unix.superglobalmegacorp.com

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