Annotation of coherent/d/286_KERNEL/USRSRC/io/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: static int iocbaud[MAX_HSNUM];
                    114: static char ioclcr[MAX_HSNUM];
                    115: 
                    116: /*
                    117:  * Time constant table.
                    118:  * Indexed by ioctl baud rate.
                    119:  */
                    120: static
                    121: int timeconst[] = {
                    122:        0,                              /* 0 */
                    123:        2304,                           /* 50 */
                    124:        1536,                           /* 75 */
                    125:        1047,                           /* 110 */
                    126:        857,                            /* 134.5 */
                    127:        768,                            /* 150 */
                    128:        576,                            /* 200 */
                    129:        384,                            /* 300 */
                    130:        192,                            /* 600 */
                    131:        96,                             /* 1200 */
                    132:        64,                             /* 1800 */
                    133:        58,                             /* 2000 */
                    134:        48,                             /* 2400 */
                    135:        32,                             /* 3600 */
                    136:        24,                             /* 4800 */
                    137:        16,                             /* 7200 */
                    138:        12,                             /* 9600 */
                    139:        6,                              /* 19200 */
                    140:        6,                              /* EXTA */
                    141:        6                               /* EXTB */
                    142: };
                    143: 
                    144: /*
                    145:  * poll_hz[] is tied to timeconst[] - it gives the minimum polling
                    146:  *     rate for the corresponding port speed; it must be a multiple
                    147:  *     of 100 (system clock Hz) and >= baud/6
                    148:  */
                    149: int poll_hz[] ={
                    150:        0,                              /* 0 */
                    151:        1*HZ,                           /* 50 */
                    152:        1*HZ,                           /* 75 */
                    153:        1*HZ,                           /* 110 */
                    154:        1*HZ,                           /* 134.5 */
                    155:        1*HZ,                           /* 150 */
                    156:        1*HZ,                           /* 200 */
                    157:        1*HZ,                           /* 300 */
                    158:        1*HZ,                           /* 600 */
                    159:        2*HZ,                           /* 1200 */
                    160:        3*HZ,                           /* 1800 */
                    161:        4*HZ,                           /* 2000 */
                    162:        4*HZ,                           /* 2400 */
                    163:        6*HZ,                           /* 3600 */
                    164:        8*HZ,                           /* 4800 */
                    165:        12*HZ,                          /* 7200 */
                    166:        16*HZ,                          /* 9600 */
                    167:        0,                              /* 19200 */
                    168:        0,                              /* EXTA */
                    169:        0                               /* EXTB */
                    170: };
                    171: 
                    172: /*
                    173:  * Load Routine.
                    174:  */
                    175: static hsload()
                    176: {
                    177:        register TTY * tp;
                    178:        register int port;
                    179:        int i, b;
                    180: 
                    181:        if ((hstty = (TTY *)kalloc(HSNUM*sizeof(TTY))) == 0) {
                    182:                printf("hsload: can't allocate tty's\n");
                    183:                return;
                    184:        }
                    185:        kclear(hstty, HSNUM*sizeof(TTY));
                    186: 
                    187:        for (i = 0; i < HSNUM; i++) {
                    188:                port = HS_PORTS[i].addr;
                    189:                tp = hstty + i;
                    190: 
                    191:                outb(port+MCR, 0);
                    192:                outb(port+IER, 0);
                    193: 
                    194:                if (inb(port+IER))
                    195:                        break;
                    196: 
                    197:                tp->t_cs_sel  = cs_sel();
                    198:                tp->t_start   = hsstart;
                    199:                tp->t_param   = hsparam;
                    200:                tp->t_sgttyb.sg_ospeed = tp->t_sgttyb.sg_ispeed = 
                    201:                tp->t_dispeed = tp->t_dospeed = HS_PORTS[i].speed;
                    202:                tp->t_ddp     = port;
                    203: 
                    204:                b = timeconst[ tp->t_sgttyb.sg_ospeed ];
                    205:                outb(port+LCR, LC_DLAB);
                    206:                outb(port+DLL, b);
                    207:                outb(port+DLH, b >> 8);
                    208:                outb(port+LCR, LC_CS8);
                    209: 
                    210:                hslimtty = tp;
                    211:        }
                    212: }
                    213: 
                    214: static hsunload()
                    215: {
                    216:        if (hstty != (TTY *)0)
                    217:                kfree(hstty);
                    218: }
                    219: 
                    220: /*
                    221:  * Open Routine.
                    222:  */
                    223: hsopen(dev, mode)
                    224: dev_t dev;
                    225: {
                    226:        register TTY * tp = &hstty[ dev & 15 ];
                    227:        register int b;
                    228:        int s;
                    229: 
                    230:        /*
                    231:         * Verify hardware exists.
                    232:         */
                    233:        if ((PORT == 0) || (inb(PORT+IER) & ~IE_TxI)) {
                    234:                u.u_error = ENXIO;
                    235:                return;
                    236:        }
                    237: 
                    238:        /*
                    239:         * Can't open if another driver is using polling
                    240:         */
                    241:        if (poll_owner & ~ POLL_HS) {
                    242:                u.u_error = EDBUSY;
                    243:                return;
                    244:        }
                    245: 
                    246:        /*
                    247:         * Initialize if not already open.
                    248:         */
                    249:        if (++tp->t_open == 1) {
                    250:                ttopen(tp);
                    251: 
                    252:                if (dev & 0x80) {
                    253:                        s = sphi();
                    254:                        b = inb(PORT+MSR);
                    255:                        tp->t_flags |= T_MODC + T_STOP;
                    256:                        if (b & MS_CTS)
                    257:                                tp->t_flags &= ~T_STOP;
                    258:                        if (b & MS_DSR)
                    259:                                tp->t_flags |=  T_CARR;
                    260:                        spl(s);
                    261:                } else  {
                    262:                        tp->t_flags &= ~T_MODC;
                    263:                        tp->t_flags |=  T_CARR;
                    264:                }
                    265:                hscycle(tp);
                    266:        }
                    267:        ttsetgrp(tp, dev);
                    268:        set_poll_rate();
                    269: }
                    270: 
                    271: /*
                    272:  * Close Routine.
                    273:  */
                    274: hsclose(dev)
                    275: dev_t dev;
                    276: {
                    277:        register TTY * tp = &hstty[ dev & 15 ];
                    278: 
                    279:        /*
                    280:         * Reset if last close.
                    281:         */
                    282:        if (tp->t_open == 1) {
                    283:                int state;
                    284: 
                    285:                ttclose(tp);
                    286:                /*
                    287:                 * ttclose() only emptied the output queue tp->t_oq;
                    288:                 * now wait 0.1 sec for the silo tp->rawout to empty
                    289:                 * and allow a delay for the UART on-chip xmit buffer to empty
                    290:                 *
                    291:                 * state 2: waiting for silo to empty
                    292:                 * state 1: stalling so UART can empty xmit buffer
                    293:                 * state 0: done!
                    294:                 */
                    295:                state = 2;
                    296:                while (state) {
                    297:                        timeout(&hstim, 10, wakeup, (int)&hstim);
                    298:                        sleep((char *)&hstim, CVTTOUT, IVTTOUT, SVTTOUT);
                    299:                        if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
                    300:                                state--;
                    301:                }
                    302:        }
                    303: 
                    304:        --tp->t_open;
                    305:        set_poll_rate();
                    306: }
                    307: 
                    308: /*
                    309:  * Read Routine.
                    310:  */
                    311: hsread(dev, iop)
                    312: dev_t dev;
                    313: register IO * iop;
                    314: {
                    315:        ttread(&hstty[ dev & 15 ], iop);
                    316: }
                    317: 
                    318: /*
                    319:  * Write Routine.
                    320:  */
                    321: hswrite(dev, iop)
                    322: dev_t dev;
                    323: register IO * iop;
                    324: {
                    325:        ttwrite(&hstty[ dev & 15 ], iop);
                    326: }
                    327: 
                    328: /*
                    329:  * Ioctl Routine.
                    330:  */
                    331: hsioctl(dev, com, vec)
                    332: dev_t dev;
                    333: int com;
                    334: struct sgttyb * vec;
                    335: {
                    336:        ttioctl(&hstty[ dev & 15 ], com, vec);
                    337: }
                    338: 
                    339: /*
                    340:  * Polling Routine.
                    341:  */
                    342: hspoll(dev, ev, msec)
                    343: dev_t dev;
                    344: int ev;
                    345: int msec;
                    346: {
                    347:        return ttpoll(&hstty[ dev & 15 ], ev, msec);
                    348: }
                    349: 
                    350: /*
                    351:  * Cyclic routine - invoked every clock tick to perform raw input/output.
                    352:  *
                    353:  *     Notes:  Invoked 10 times per second.
                    354:  */
                    355: hscycle(tp)
                    356: register TTY * tp;
                    357: {
                    358:        register int resid;
                    359:        register int c;
                    360: 
                    361:        /*
                    362:         * Process rawin buf.
                    363:         */
                    364:        while (tp->t_rawin.si_ix != tp->t_rawin.si_ox) {
                    365: 
                    366:                ttin(tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ]);
                    367: 
                    368:                if (tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1)
                    369:                        tp->t_rawin.si_ox = 0;
                    370:                else
                    371:                        tp->t_rawin.si_ox++;
                    372:        }
                    373: 
                    374:        /*
                    375:         * Calculate free output slot count.
                    376:         */
                    377:        resid  = sizeof(tp->t_rawout.si_buf) - 1;
                    378:        resid += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
                    379:        resid %= sizeof(tp->t_rawout.si_buf);
                    380: 
                    381:        /*
                    382:         * Fill raw output buffer.
                    383:         */
                    384:        while ((--resid >= 0) && ((c = ttout(tp)) >= 0)) {
                    385: 
                    386:                tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = c;
                    387: 
                    388:                if (tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1)
                    389:                        tp->t_rawout.si_ix = 0;
                    390:                else
                    391:                        tp->t_rawout.si_ix++;
                    392:        }
                    393: 
                    394:        /*
                    395:         * (Re)start output, waking processes waiting to output, etc.
                    396:         */
                    397:        ttstart(tp);
                    398: 
                    399:        /*
                    400:         * Schedule next cycle.
                    401:         */
                    402:        if (tp->t_open != 0)
                    403:                timeout(&tp->t_rawtim, HZ/10, hscycle, tp);
                    404: }
                    405: 
                    406: /*
                    407:  * Clock Interrupt driven Polling routine.
                    408:  */
                    409: hsintr()
                    410: {
                    411:        register TTY * tp = &hstty[0];
                    412:        register int b;
                    413: 
                    414:        do {
                    415:                if (tp->t_open == 0)
                    416:                        continue;
                    417: 
                    418:                /*
                    419:                 * Check modem status if modem control is enabled.
                    420:                 */
                    421:                if (tp->t_flags & T_MODC) {
                    422: 
                    423:                        b = inb(PORT+MSR);
                    424: 
                    425:                        if (b & (MS_DCTS|MS_DDSR)) {
                    426: 
                    427:                                if (b & MS_DCTS) {
                    428:                                        if (b & MS_CTS)
                    429:                                                tp->t_flags &= ~T_STOP;
                    430:                                        else
                    431:                                                tp->t_flags |=  T_STOP;
                    432:                                }
                    433:                                if (b & MS_DDSR) {
                    434:                                        if (b & MS_DSR)
                    435:                                                tp->t_flags |=  T_CARR;
                    436:                                        else {
                    437:                                                tp->t_flags &= ~T_CARR;
                    438:                                                tthup(tp);
                    439:                                        }
                    440:                                }
                    441:                        }
                    442:                }
                    443: 
                    444:                b = inb(PORT+LSR);
                    445: 
                    446:                if ((b & LS_BREAK) && (tp->t_flags & T_CARR))
                    447:                        ttsignal(tp, SIGINT);
                    448: 
                    449:                /*
                    450:                 * Receive ready.
                    451:                 */
                    452:                if (b & LS_RxRDY) {
                    453: 
                    454:                        tp->t_rawin.si_buf[tp->t_rawin.si_ix] = inb(PORT+DREG);
                    455: 
                    456:                        if (tp->t_flags & T_CARR) {
                    457: 
                    458:                                if (++(tp->t_rawin.si_ix) >=
                    459:                                                sizeof(tp->t_rawin.si_buf))
                    460:                                        tp->t_rawin.si_ix = 0;
                    461:                        }
                    462:                }
                    463: 
                    464:                /*
                    465:                 * Transmit ready and raw output data exists.
                    466:                 */
                    467:                if ((b & LS_TxRDY) && ((tp->t_flags & T_STOP) == 0)
                    468:                  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox)) {
                    469: 
                    470:                        outb(   PORT+DREG,
                    471:                                tp->t_rawout.si_buf[ tp->t_rawout.si_ox ]);
                    472: 
                    473:                        if (++(tp->t_rawout.si_ox) >=
                    474:                                        sizeof(tp->t_rawout.si_buf))
                    475:                                tp->t_rawout.si_ox = 0;
                    476:                }
                    477: 
                    478:        } while (++tp <= hslimtty);
                    479: }
                    480: 
                    481: /*
                    482:  * Set hardware parameters.
                    483:  */
                    484: hsparam(tp)
                    485: register TTY * tp;
                    486: {
                    487:        register int b;
                    488:        int s;
                    489:        int hnum;
                    490:        int newbaud;
                    491:        char newlcr;
                    492:        int write_baud = 1, write_lcr = 1;
                    493: 
                    494:        newbaud = timeconst[tp->t_sgttyb.sg_ospeed];
                    495: 
                    496:        switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
                    497:        case ODDP:
                    498:                newlcr = LC_CS7|LC_PARENB;
                    499:                break;
                    500:        case EVENP:
                    501:                newlcr = LC_CS7|LC_PARENB|LC_PAREVEN;
                    502:                break;
                    503:        default:
                    504:                newlcr = LC_CS8;
                    505:                break;
                    506:        }
                    507:        
                    508:        hnum = tp - hstty;
                    509:        if (hnum >= 0 && hnum < HSNUM) {
                    510:                if (newbaud == iocbaud[hnum]) {
                    511:                        write_baud = 0;
                    512:                        if (newlcr == ioclcr[hnum]) {
                    513:                                write_lcr = 0;
                    514:                        }
                    515:                }
                    516:                iocbaud[hnum] = newbaud;
                    517:                ioclcr[hnum] = newlcr;
                    518:        }
                    519: 
                    520:        s = sphi();
                    521:        /*
                    522:         * Assert required modem control lines (DTR, RTS).
                    523:         */
                    524:        if (tp->t_sgttyb.sg_ospeed == B0) {
                    525:                outb(PORT+MCR, 0);
                    526:        } else {
                    527:                outb(PORT+MCR, MC_DTR | MC_RTS);
                    528:        }
                    529: 
                    530:        /*
                    531:         * Program baud rate.
                    532:         */
                    533:        if (write_baud) {
                    534:                outb(PORT+LCR, LC_DLAB);
                    535:                outb(PORT+DLL, newbaud);
                    536:                outb(PORT+DLH, newbaud >> 8);
                    537:        }
                    538: 
                    539:        /*
                    540:         * Program character size, parity.
                    541:         */
                    542:        if (write_lcr)
                    543:                outb(PORT+LCR, newlcr);
                    544: 
                    545:        /*
                    546:         * Enable Transmit Buffer Empty Interrupts.
                    547:         */
                    548:        outb(PORT+IER, IE_TxI);
                    549: 
                    550:        spl(s);
                    551:        set_poll_rate();
                    552: }
                    553: 
                    554: /*
                    555:  * Start Routine.
                    556:  */
                    557: hsstart(tp)
                    558: register TTY * tp;
                    559: {
                    560:        register int s;
                    561: 
                    562:        /*
                    563:         * Transmit buffer is empty, and raw output buffer is not.
                    564:         */
                    565:        s = sphi();
                    566:        if ((inb(PORT+LSR) & LS_TxRDY)
                    567:          && (tp->t_rawout.si_ix != tp->t_rawout.si_ox)) {
                    568: 
                    569:                /*
                    570:                 * Send next char from raw output buffer.
                    571:                 */
                    572:                outb(PORT+DREG, tp->t_rawout.si_buf[ tp->t_rawout.si_ox ]);
                    573: 
                    574:                if (++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf))
                    575:                        tp->t_rawout.si_ox = 0;
                    576:        }
                    577:        spl(s);
                    578: }
                    579: 
                    580: /*
                    581:  * hsclk will be called every time T0 interrupts - if it returns 0,
                    582:  * the usual system timer interrupt stuff is done
                    583:  */
                    584: static int hsclk()
                    585: {
                    586:   static int count;
                    587: 
                    588:   hsintr();
                    589:   count++;
                    590:   if (count >= poll_divisor)
                    591:     count = 0;
                    592:   return count;
                    593: }
                    594: 
                    595: /*
                    596:  * set_poll_rate is called when a port is opened or closed or changes speed
                    597:  * it sets the polling rate only as fast as needed, and shuts off polling
                    598:  * whenever possible
                    599:  */
                    600: static set_poll_rate()
                    601: {
                    602:        int port_num, max_rate, port_rate;
                    603: 
                    604:        /*
                    605:         * If another driver has the polling clock, do nothing.
                    606:         */
                    607:        if (poll_owner & ~ POLL_HS)
                    608:                return;
                    609: 
                    610:        /*
                    611:         * find highest valid polling rate in units of HZ/10
                    612:         */
                    613:        max_rate = 0;
                    614:        for (port_num = 0; port_num < HSNUM; port_num++) {
                    615:                if (hstty[port_num].t_open) {
                    616:                  port_rate = poll_hz[hstty[port_num].t_sgttyb.sg_ispeed];
                    617:                  if (max_rate < port_rate)
                    618:                        max_rate = port_rate;
                    619:                }
                    620:        }
                    621:        /*
                    622:         * if max_rate is not current rate, adjust the system clock
                    623:         */
                    624:        if (max_rate != poll_rate) {
                    625:                poll_rate = max_rate;
                    626:                poll_divisor = poll_rate/HZ;  /* used in hsclk() */
                    627:                altclk_out();           /* stop previous polling */
                    628:                poll_owner &= ~POLL_HS;
                    629:                if (max_rate) { /* resume polling at new rate if needed */
                    630:                        altclk_in(poll_rate, hsclk);
                    631:                        poll_owner |= POLL_HS;
                    632:                }
                    633:        }
                    634: }

unix.superglobalmegacorp.com

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