Annotation of coherent/d/kernel/USRSRC/i8086/drv/hs.c, revision 1.1.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.