Annotation of coherent/b/STREAMS/io.386/alx.c, revision 1.1.1.1

1.1       root        1: /* (-lgl
                      2:  *     COHERENT Driver Kit Version 2.1.0
                      3:  *     Copyright (c) 1982, 1993 by Mark Williams Company.
                      4:  *     All rights reserved. May not be copied without permission.
                      5:  *
                      6:  *
                      7:  -lgl) */
                      8: /*
                      9:  * Shared parts of IBM async port drivers.
                     10:  */
                     11: 
                     12: #include <kernel/timeout.h>
                     13: 
                     14: #include <sys/coherent.h>
                     15: #if    ! _I386
                     16: #include <sys/i8086.h>
                     17: #endif
                     18: #include <sys/al.h>
                     19: #include <sys/con.h>
                     20: #include <sys/errno.h>
                     21: #include <sys/stat.h>
                     22: #include <sys/tty.h>
                     23: #include <sys/clist.h>
                     24: #include <sys/ins8250.h>
                     25: #include <sys/sched.h>
                     26: #include <sys/silo.h>
                     27: 
                     28: #ifdef _I386
                     29: #define        EEBUSY  EBUSY
                     30: #else
                     31: #define        EEBUSY  EDBUSY
                     32: #endif
                     33: 
                     34: #define ALPORT (((COM_DDP *)(tp->t_ddp))->port)
                     35: #define AL_NUM (((COM_DDP *)(tp->t_ddp))->com_num)
                     36: 
                     37: #define DTRTMOUT  3    /* DTR timeout interval in seconds for close */
                     38: 
                     39: /*
                     40:  * For rawin silo (see poll_clk.h), use last element of si_buf to count
                     41:  * the number of characters in the silo.
                     42:  */
                     43: #define SILO_CHAR_COUNT        si_buf[SI_BUFSIZ-1]
                     44: #define SILO_HIGH_MARK (SI_BUFSIZ-SI_BUFSIZ/4)
                     45: #define SILO_LOW_MARK  (SI_BUFSIZ/4)
                     46: #define MAX_SILO_INDEX (SI_BUFSIZ-2)
                     47: #define MAX_SILO_CHARS (SI_BUFSIZ-1)
                     48: 
                     49: /*
                     50:  * The following silo FLUSH macros are always called at high priority!
                     51:  */
                     52: #ifdef NO_ISILO
                     53: #define RAWIN_FLUSH(in_silo)
                     54: #else
                     55: #define RAWIN_FLUSH(in_silo)   { in_silo->si_ox = in_silo->si_ix; \
                     56:          in_silo->SILO_CHAR_COUNT = 0; }
                     57: #endif
                     58: #define RAWOUT_FLUSH(out_silo) { out_silo->si_ox = out_silo->si_ix; }
                     59: 
                     60: int    al_sg_set = 0;
                     61: int    al_sg_clr = 0;
                     62: static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */
                     63: 
                     64: /*
                     65:  * functions herein
                     66:  */
                     67: int    alxopen();
                     68: int    alxclose();
                     69: int    alxtimer();
                     70: int    alxioctl();
                     71: int    alxparam();
                     72: int    alxcycle();
                     73: int    alxstart();
                     74: int    alxbreak();
                     75: int    alxintr();
                     76: static int alxclk();
                     77: static set_poll_rate();
                     78: static void alxpoll();
                     79: static void alx_send();
                     80: static int iocbaud[4];
                     81: static char ioclcr[4];
                     82: 
                     83: /*
                     84:  * Port addresses are now patchable.
                     85:  */
                     86: int AL_ADDR[] = {
                     87: #if BOB_H
                     88:        0x280, 0x288, 0x290, 0x298
                     89: #else
                     90:        0x3F8, 0x2F8, 0x3E8, 0x2E8
                     91: #endif
                     92: };
                     93: 
                     94: /*
                     95:  * Baud rate table and polling rate table.
                     96:  * Indexed by ioctl bit rates.
                     97:  */
                     98: extern int albaud[], alp_rate[];
                     99: 
                    100: /*
                    101:  *     the following is for debug only
                    102:  */
                    103: #if TRACER
                    104: int ASY_OR = 0;
                    105: #define LSR_READ(lval, port) \
                    106:   { lval = inb((port)+LSR); if (lval & LS_OVER) ASY_OR++; }
                    107: #define CDUMP(text, tp)        cdump(text, tp);
                    108: #define tprintf(str)   { T_HAL(4, printf(str)); }
                    109: #define REPORT_OE {if(ASY_OR&&(t_hal&0x20)){printf("oe=%d ",ASY_OR);ASY_OR=0;}}
                    110: cdump(message, tp)
                    111: char *message;
                    112: TTY *tp;
                    113: {
                    114:        int i, b;
                    115:        char cmd[11];
                    116: 
                    117:        if ((t_hal & 4) == 0)
                    118:                return;
                    119:        for (i = 0; i < NUM_AL_PORTS; i++) {
                    120:                if (tp_table[i]) {
                    121:                        b = ((COM_DDP *)(tp_table[i]->t_ddp))->port;
                    122:                        printf("%x:%x:%x:%x ", i+1, b, inb(b+MCR), inb(b+IER));
                    123:                }
                    124:        }
                    125:        for (i = 0; i < 10; i++) {
                    126:                cmd[i] = u.u_comm[i];
                    127:        }
                    128:        cmd[10] = '\0';
                    129:        printf("poll=%d cmd=%s pid=%d ", poll_rate, cmd, SELF->p_pid);
                    130:        printf("%s\n", message);
                    131:        if (tp) {
                    132:                printf("#%d f=%x op=%d ", AL_NUM, tp->t_flags, tp->t_open);
                    133:                printf("in_use=%d irq=%d has_irq=%d ",
                    134:                  com_usage[AL_NUM].in_use,
                    135:                  com_usage[AL_NUM].irq,
                    136:                  com_usage[AL_NUM].has_irq);
                    137:                printf("poll=%d hcls=%d ohlt=%d\n",
                    138:                  com_usage[AL_NUM].poll,
                    139:                  com_usage[AL_NUM].hcls,
                    140:                  com_usage[AL_NUM].ohlt);
                    141:        }
                    142: }
                    143: #else
                    144: #define CDUMP(text, tp)
                    145: #define REPORT_OE
                    146: #define LSR_READ(lval, port)   { lval = inb((port)+LSR); }
                    147: #endif
                    148: 
                    149: /*
                    150:  * alxopen()
                    151:  */
                    152: alxopen(dev, mode, tp, irqtty)
                    153: dev_t  dev;
                    154: int    mode;
                    155: register TTY   *tp, **irqtty;
                    156: {
                    157:        int     s;
                    158:        int     b;
                    159:        int     minor_h;  /* minor device number including high bit */
                    160:        unsigned char   msr;
                    161: 
                    162:        minor_h = minor(dev);     /* complete minor number */
                    163:        b = ALPORT;
                    164: 
                    165:        if (com_usage[AL_NUM].uart_type == US_NONE) { /* chip not found */
                    166:                u.u_error = ENXIO;
                    167:                goto bad_open;
                    168:        }
                    169: 
                    170:        if ((tp->t_flags & T_EXCL) && !super()) {
                    171:                u.u_error = ENODEV;
                    172:                goto bad_open;
                    173:        }
                    174: 
                    175:        if (drvl[major(dev)].d_time) {  /* Modem settling */
                    176:                u.u_error = EEBUSY;
                    177:                goto bad_open;
                    178:        }
                    179: 
                    180:        /*
                    181:         * Can't open a polled port if another driver is using polling.
                    182:         */
                    183:        if (dev & CPOLL && poll_owner & ~ POLL_AL) {
                    184:                u.u_error = EEBUSY;
                    185:                goto bad_open;
                    186:        }
                    187: 
                    188:        /*
                    189:         * Can't have both com[13] or both com[24] IRQ at once.
                    190:         */
                    191:        if ( !(dev & CPOLL)
                    192:        && com_usage[AL_NUM^2].irq
                    193:        && com_usage[AL_NUM^2].in_use) {
                    194:                u.u_error = EEBUSY;
                    195:                goto bad_open;
                    196:        }
                    197: 
                    198:        /*
                    199:         * If port already in use, are new and old open modes compatible?
                    200:         */
                    201:        if (com_usage[AL_NUM].in_use) {
                    202:                int oldmode = 0, newmode = 0; /* mctl:1 poll:2 flow:4 */
                    203: 
                    204:                if (tp->t_flags & T_MODC)
                    205:                        oldmode += 1;
                    206:                if (com_usage[AL_NUM].irq == 0)
                    207:                        oldmode += 2;
                    208:                if (tp->t_flags & T_CFLOW)
                    209:                        oldmode += 4;
                    210:                if ((minor_h & NMODC) == 0)
                    211:                        newmode += 1;
                    212:                if (dev & CPOLL)
                    213:                        newmode += 2;
                    214:                if (minor_h & CFLOW)
                    215:                        newmode += 4;
                    216:                if (oldmode != newmode) {
                    217:                        u.u_error = EEBUSY;
                    218:                        goto bad_open;
                    219:                }
                    220:        }
                    221: 
                    222:        /*
                    223:         * Sleep here if another process is opening or closing the port.
                    224:         * This can happen if:
                    225:         *   another process is trying a first open and awaiting CD;
                    226:         *   another process is closing the port after losing CD;
                    227:         *   a remote process opened the port, spawned a daemon,
                    228:         *     and disconnected, and the daemon ignored SIGHUP and is
                    229:         *     improperly keeping the port open.
                    230:         * Don't try to set tp->t_flags before this sleep!  During
                    231:         *   the sleep, ttclose() may be called and clear the flags.
                    232:         */
                    233:        while (com_usage[AL_NUM].in_use &&
                    234:          (com_usage[AL_NUM].hcls ||
                    235:          ((minor_h & NMODC) == 0 && (inb(b+MSR) & MS_RLSD) == 0))) {
                    236: #ifdef _I386
                    237:                if (x_sleep ((char *) & tp->t_open, pritty, slpriSigCatch,
                    238:                             "alxopn1") == PROCESS_SIGNALLED) {
                    239: #else
                    240:                v_sleep((char *)(&tp->t_open),
                    241:                  CVTTOUT, IVTTOUT, SVTTOUT, "alxopn1");
                    242:                if (nondsig ()) {  /* signal? */
                    243: #endif
                    244:                        u.u_error = EINTR;
                    245:                        goto bad_open;
                    246:                }
                    247:        }
                    248: 
                    249:        /*
                    250:         * If port already in use, are new and old open modes compatible?
                    251:         * If not in use, mark it as such.
                    252:         */
                    253:        if (com_usage[AL_NUM].in_use) {
                    254:                int oldmode = 0, newmode = 0; /* mctl:1 poll:2 flow:4 */
                    255: 
                    256:                if (tp->t_flags & T_MODC)
                    257:                        oldmode += 1;
                    258:                if (com_usage[AL_NUM].irq == 0)
                    259:                        oldmode += 2;
                    260:                if (tp->t_flags & T_CFLOW)
                    261:                        oldmode += 4;
                    262:                if ((minor_h & NMODC) == 0)
                    263:                        newmode += 1;
                    264:                if (dev & CPOLL)
                    265:                        newmode += 2;
                    266:                if (minor_h & CFLOW)
                    267:                        newmode += 4;
                    268:                if (oldmode != newmode) {
                    269:                        u.u_error = EEBUSY;
                    270:                        goto bad_open;
                    271:                }
                    272:        } else {
                    273:                /*
                    274:                 * Save modes for this open attempt to avoid future conflicts.
                    275:                 * Then start alxcycle() for this port.
                    276:                 */
                    277:                if (dev & CPOLL)
                    278:                        com_usage[AL_NUM].irq = 0;
                    279:                else
                    280:                        com_usage[AL_NUM].irq = 1;
                    281:                if (minor_h & CFLOW)
                    282:                        tp->t_flags |= T_CFLOW;
                    283:                else
                    284:                        tp->t_flags &= ~T_CFLOW;
                    285:                if (minor_h & NMODC)
                    286:                        tp->t_flags &= ~T_MODC;
                    287:                else
                    288:                        tp->t_flags |= T_MODC;
                    289:        }
                    290:        com_usage[AL_NUM].in_use++;
                    291:        /*
                    292:         * From here, error exit is bad_open_u.
                    293:         */
                    294: 
                    295:        if (tp->t_open == 0) {        /* not already open */
                    296:                if (!(dev & CPOLL)) {
                    297:                        *irqtty = tp_table[AL_NUM];
                    298:                        com_usage[AL_NUM].has_irq = 1;
                    299:                }
                    300: 
                    301:                /*
                    302:                 * Need to start cycling to scan for CD.
                    303:                 */
                    304:                alxcycle(tp);
                    305: 
                    306:                s = sphi();
                    307:                /*
                    308:                 * Raise basic modem control lines even if modem
                    309:                 * control hasn't been specified.
                    310:                 * MC_OUT2 turns on NON-open-collector IRQ line from the UART.
                    311:                 * since we can't have two UART's on same IRQ with MC_OUT2 on
                    312:                 */
                    313:                if (dev & CPOLL) {
                    314:                        outb(b+MCR, MC_RTS|MC_DTR);
                    315:                } else {
                    316:                        outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
                    317:                        outb(b+IER, IENABLE);
                    318:                }
                    319: 
                    320:                if ((minor_h & NMODC) == 0) {   /* want modem control? */
                    321:                        tp->t_flags |= T_HOPEN | T_STOP;
                    322:                        for (;;) {      /* wait for carrier */
                    323:                                msr = inb(b+MSR);
                    324:                                /*
                    325:                                 * If carrier detect present
                    326:                                 *   if port not already open
                    327:                                 *     break out of loop and finish first open
                    328:                                 *   else
                    329:                                 *     do second (or third, etc.) open
                    330:                                 */
                    331:                                if (msr & MS_RLSD)
                    332:                                        break;
                    333: 
                    334:                                /* wait for carrier */
                    335: #ifdef _I386
                    336:                                if (x_sleep ((char *) & tp->t_open, pritty,
                    337:                                             slpriSigCatch, "alxopn2")
                    338:                                    == PROCESS_SIGNALLED) {
                    339: #else
                    340:                                v_sleep((char *)(&tp->t_open),
                    341:                                  CVTTOUT, IVTTOUT, SVTTOUT, "alxopn2");
                    342:                                if (nondsig ()) {  /* signal? */
                    343: #endif
                    344:                                        outb(b+MCR, 0);
                    345:                                        outb(b+IER, 0);
                    346:                                        u.u_error = EINTR;
                    347:                                        tp->t_flags &= ~(T_HOPEN | T_STOP);
                    348:                                        spl(s);
                    349:                                        goto bad_open_u;
                    350:                                }
                    351:                        }
                    352: 
                    353:                        /*
                    354:                         * Mark that we are no longer hanging in open.
                    355:                         * Allow output over the port unless hardware flow
                    356:                         * control says not to.
                    357:                         */
                    358:                        tp->t_flags &= ~T_HOPEN;
                    359:                        tp->t_flags &= ~T_STOP;
                    360:                        if (!(tp->t_flags & T_CFLOW) || (msr & MS_CTS))
                    361:                                com_usage[AL_NUM].ohlt = 0;
                    362:                        else
                    363:                                com_usage[AL_NUM].ohlt = 1;
                    364: 
                    365:                        /*
                    366:                         * Awaken any other opens on same device.
                    367:                         */
                    368:                        wakeup((char *)(&tp->t_open));
                    369:                }
                    370:                tp->t_flags |= T_CARR;
                    371:                ttopen(tp);                             /* stty inits */
                    372: 
                    373:                /*
                    374:                 * Allow custom modification of defaults.
                    375:                 */
                    376:                tp->t_sgttyb.sg_flags |=  al_sg_set;
                    377:                tp->t_sgttyb.sg_flags &= ~al_sg_clr;
                    378: 
                    379:                alxparam(tp);
                    380:                spl(s);
                    381:        } /* end of first-open case */
                    382: 
                    383:        tp->t_open++;
                    384:        ttsetgrp(tp, dev, mode);
                    385: 
                    386:        /*
                    387:         * Turn on polling for the port.
                    388:         */
                    389:        if (dev & CPOLL) {
                    390:                com_usage[AL_NUM].poll = 1;
                    391:                set_poll_rate();
                    392:        }
                    393: 
                    394:        CDUMP((dev&CPOLL)?"open polled":"open irq", tp)
                    395:        return;
                    396: 
                    397: bad_open_u:
                    398:        --com_usage[AL_NUM].in_use;
                    399:        wakeup((char *)(&tp->t_open));
                    400: bad_open:
                    401:        return;
                    402: }
                    403: 
                    404: /*
                    405:  * alxclose()
                    406:  *
                    407:  *     Called whenever kernel closes a com port.
                    408:  */
                    409: alxclose(dev, mode, tp)
                    410: dev_t  dev;
                    411: int    mode;
                    412: TTY    *tp;
                    413: {
                    414:        register int b;
                    415:        int maj;
                    416:        int flags;
                    417:        int s;
                    418:        unsigned char lsr;
                    419:        silo_t * out_silo = &com_usage[AL_NUM].raw_out;
                    420:        silo_t * in_silo = &com_usage[AL_NUM].raw_in;
                    421: 
                    422:        if (--tp->t_open)
                    423:                goto closed;
                    424:        s = sphi();
                    425: 
                    426:        /*
                    427:         * Called at high priority by alclose after al_buff is drained
                    428:         */
                    429:        com_usage[AL_NUM].hcls = 1;     /* disallow reopen til done closing */
                    430:        flags = tp->t_flags;            /* save flags - ttclose zeroes them */
                    431:        ttclose(tp);
                    432:        b = ALPORT;
                    433: 
                    434:        /*
                    435:         * Wait for output silo and uart xmit buffer to empty.
                    436:         * Allow signal to break the sleep.
                    437:         */
                    438:        for (;;) {
                    439:                LSR_READ(lsr, b);
                    440:                if ((lsr & LS_TxIDLE)
                    441:                  && (out_silo->si_ix == out_silo->si_ox))
                    442:                        break;
                    443: CDUMP("slp cls", tp)
                    444: #ifdef _I386
                    445:                if (x_sleep ((char *) out_silo, pritty, slpriSigCatch,
                    446:                             "alxcls1") == PROCESS_SIGNALLED) {
                    447: #else
                    448:                v_sleep((char *)out_silo, CVTTOUT, IVTTOUT, SVTTOUT, "alxcls1");
                    449:                if (nondsig ()) {  /* signal? */
                    450: #endif
                    451:                        RAWOUT_FLUSH(out_silo);
                    452:                        break;
                    453:                }
                    454:        }
                    455: 
                    456:        /*
                    457:         * If not hanging in open
                    458:         */
                    459:        if ((flags & T_HOPEN) == 0) {
                    460:                /*
                    461:                 * Disable interrupts.
                    462:                 */
                    463:                outb(b+IER, 0);
                    464:                outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
                    465:        }
                    466: 
                    467:        /*
                    468:         * If hupcls
                    469:         */
                    470:        if (flags & T_HPCL) {
                    471:                /*
                    472:                 * Hangup port - drop DTR and RTS.
                    473:                 */
                    474:                outb(b+MCR, inb(b+MCR)&MC_OUT2);
                    475: 
                    476:                /*
                    477:                 * Hold dtr low for timeout
                    478:                 */
                    479:                maj = major(dev);
                    480:                drvl[maj].d_time = 1;
                    481: CDUMP("slp DTR", tp)
                    482: #ifdef _I386
                    483:                x_sleep ((char *) & drvl [maj].d_time, pritty, slpriNoSig,
                    484:                         "alxcls2");
                    485: #else
                    486:                v_sleep((char *)&drvl[maj].d_time,
                    487:                  CVTTOUT, IVTTOUT, SVTTOUT, "alxcls2");
                    488: #endif
                    489:                drvl[maj].d_time = 0;
                    490:        }
                    491:        com_usage[AL_NUM].poll = 0;
                    492:        set_poll_rate();
                    493:        RAWIN_FLUSH(in_silo);
                    494:        com_usage[AL_NUM].hcls = 0;     /* allow reopen - done closing */
                    495:        wakeup((char *)(&tp->t_open));
                    496:        spl(s);
                    497: closed:;
                    498:        --com_usage[AL_NUM].in_use;
                    499:        wakeup((char *)(&tp->t_open));
                    500:        CDUMP("closed", tp)
                    501: }
                    502: 
                    503: /*
                    504:  * Common c_timer routine for async ports.
                    505:  */
                    506: alxtimer(dev)
                    507: dev_t dev;
                    508: {
                    509:        if (++drvl[major(dev)].d_time > DTRTMOUT)
                    510:                wakeup((char *)&drvl[major(dev)].d_time);
                    511: }
                    512: 
                    513: 
                    514: /*
                    515:  * Common c_ioctl routine for async ports.
                    516:  */
                    517: alxioctl(dev, com, vec, tp)
                    518: dev_t  dev;
                    519: struct sgttyb *vec;
                    520: register TTY   *tp;
                    521: {
                    522:        register int    s, b;
                    523:        int stat1, stat2;
                    524:        unsigned char   msr;
                    525:        unsigned char ier_save;
                    526:        silo_t * out_silo = &com_usage[AL_NUM].raw_out;
                    527:        silo_t * in_silo = &com_usage[AL_NUM].raw_in;
                    528: 
                    529:        s = sphi();
                    530:        b = ALPORT;
                    531:        ier_save=inb(b+IER);
                    532:        stat1 = inb(b+MCR);             /* get current MCR register status */
                    533:        stat2 = inb(b+LCR);             /* get current LCR register status */
                    534: 
                    535:        switch(com) {
                    536:        case TIOCSBRK:                  /* set BREAK */
                    537:                outb(b+LCR, stat2|LC_SBRK);
                    538:                break;
                    539:        case TIOCCBRK:                  /* clear BREAK */
                    540:                outb(b+LCR, stat2 & ~LC_SBRK);
                    541:                break;
                    542:        case TIOCSDTR:                  /* set DTR */
                    543:                outb(b+MCR, stat1|MC_DTR);
                    544:                break;
                    545:        case TIOCCDTR:                  /* clear DTR */
                    546:                outb(b+MCR, stat1 & ~MC_DTR);
                    547:                break;
                    548:        case TIOCSRTS:                  /* set RTS */
                    549:                outb(b+MCR, stat1|MC_RTS);
                    550:                break;
                    551:        case TIOCCRTS:                  /* clear RTS */
                    552:                outb(b+MCR, stat1 & ~MC_RTS);
                    553:                break;
                    554:        case TIOCRSPEED:                /* set "raw" I/O speed divisor */
                    555:                outb(b+LCR, stat2|LC_DLAB);  /* set speed latch bit */
                    556:                outb(b+DLL, (unsigned) vec);
                    557:                outb(b+DLH, (unsigned) vec >> 8);
                    558:                outb(b+LCR, stat2);       /* reset latch bit */
                    559:                break;
                    560:        case TIOCWORDL:         /* set word length and stop bits */
                    561:                outb(b+LCR, ((stat2&~0x7) | ((unsigned) vec & 0x7)));
                    562:                break;
                    563:        case TIOCRMSR:          /* get CTS/DSR/RI/RLSD (MSR) */
                    564:                msr = inb(b+MSR);
                    565:                stat1 = msr >> 4;
                    566:                kucopy(&stat1, (unsigned *) vec, sizeof(unsigned));
                    567:                break;
                    568:        case TIOCFLUSH:         /* Flush silos here, queues in tty.c */
                    569:                RAWIN_FLUSH(in_silo);
                    570:                RAWOUT_FLUSH(out_silo);
                    571:                /* fall through to default... */
                    572:        default:
                    573:                ttioctl(tp, com, vec);
                    574:        }
                    575:        outb(b+IER, ier_save);
                    576:        spl(s);
                    577: }
                    578: 
                    579: alxparam(tp)
                    580: TTY    *tp;
                    581: {
                    582:        register int    b;
                    583:        register int    baud;
                    584:        int s;
                    585:        char newlcr;
                    586:        int write_baud=1, write_lcr=1;
                    587:        int alnum;
                    588: 
                    589:        b = ALPORT;
                    590: 
                    591:        /*
                    592:         * error if input speed not the same as output speed
                    593:         */
                    594:        if (tp->t_sgttyb.sg_ispeed!=tp->t_sgttyb.sg_ospeed) {
                    595:                u.u_error = ENODEV;
                    596:                return;
                    597:        }
                    598: 
                    599:        if ((baud = albaud[tp->t_sgttyb.sg_ispeed]) == 0) {
                    600:                if (tp->t_flags & T_MODC) {  /* modem control? */
                    601:                        s = sphi();
                    602:                        tp->t_flags &= ~T_CARR;  /* indicate no carrier */
                    603:                        outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
                    604:                        spl(s);
                    605:                }
                    606:                write_baud = 0;
                    607:        }
                    608: 
                    609:        switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
                    610:        case ODDP:
                    611:                newlcr = LC_CS7|LC_PARENB;
                    612:                break;
                    613:        case EVENP:
                    614:                newlcr = LC_CS7|LC_PARENB|LC_PAREVEN;
                    615:                break;
                    616:        default:
                    617:                newlcr = LC_CS8;
                    618:                break;
                    619:        }
                    620: 
                    621:        alnum = AL_NUM;
                    622:        if (alnum >= 0 && alnum < 4) {
                    623:                if (baud == iocbaud[alnum]) {
                    624:                        write_baud = 0;
                    625:                        if (newlcr == ioclcr[alnum]) {
                    626:                                write_lcr = 0;
                    627:                        }
                    628:                }
                    629:                iocbaud[alnum] = baud;
                    630:                ioclcr[alnum] = newlcr;
                    631:        }
                    632: 
                    633:        if (write_lcr) {
                    634:                unsigned char ier_save;
                    635:                s=sphi();
                    636:                ier_save=inb(b+IER);
                    637:                if (write_baud) {
                    638:                        outb(b+LCR, LC_DLAB);
                    639:                        outb(b+DLL, baud);
                    640:                        outb(b+DLH, baud >> 8);
                    641:                }
                    642:                outb(b+LCR, newlcr);
                    643:                if (com_usage[AL_NUM].uart_type == US_16550A)
                    644:                        outb(b+FCR, FC_ENABLE | FC_Rx_RST | FC_Rx_08);
                    645:                outb(b+IER, ier_save);
                    646:                spl(s);
                    647:        }
                    648: 
                    649:        set_poll_rate();
                    650: }
                    651: 
                    652: /*
                    653:  * Middle level processor.
                    654:  *
                    655:  *     Invoked 10 times per second.  (Once every ten clock ticks.)
                    656:  *     Tranfers rawin buffer [from intr level] to canonical input queue.
                    657:  *     Checks modem status for loss of carrier.
                    658:  *     Transfers output queue to rawout buffer [for intr level].
                    659:  */
                    660: alxcycle(tp)
                    661: register TTY * tp;
                    662: {
                    663:        register int b;
                    664:        register int n;
                    665:        unsigned char msr, mcr;
                    666:        int s;
                    667:        silo_t * out_silo = &com_usage[AL_NUM].raw_out;
                    668:        silo_t * in_silo = &com_usage[AL_NUM].raw_in;
                    669: 
                    670:        REPORT_OE;
                    671:        /*
                    672:         * Check Carrier Detect (RLSD).
                    673:         *
                    674:         * Modem status interrupts were not enabled due to 8250 hardware bug.
                    675:         * Enabling modem status and receive interrupts may cause lockup
                    676:         * on older parts.
                    677:         */
                    678:        if (tp->t_flags & T_MODC) {
                    679: 
                    680:                /*
                    681:                 * Get status
                    682:                 */
                    683:                msr = inb(ALPORT+MSR);
                    684: 
                    685:                /*
                    686:                 * Carrier changed.
                    687:                 */
                    688:                if ((msr & MS_RLSD) && !(tp->t_flags & T_CARR)) {
                    689:                        /*
                    690:                         * Carrier is on - wakeup open.
                    691:                         */
                    692:                        s = sphi();
                    693:                        tp->t_flags |= T_CARR;
                    694:                        spl(s);
                    695:                        wakeup((char *)(&tp->t_open));
                    696:                }
                    697: 
                    698:                if (!(msr & MS_RLSD) && (tp->t_flags & T_CARR)) {
                    699:                        s = sphi();
                    700:                        RAWIN_FLUSH(in_silo);
                    701:                        RAWOUT_FLUSH(out_silo);
                    702:                        tp->t_flags &= ~T_CARR;
                    703:                        spl(s);
                    704:                        tthup(tp);
                    705:                }
                    706:        }
                    707: 
                    708:        /*
                    709:         * Empty raw input buffer.
                    710:         *
                    711:         * The line discipline module (tty.c) will set T_ISTOP true when the
                    712:         * tt input queue is nearly full (tp->t_iq.cq_cc >= IHILIM), and make
                    713:         * T_ISTOP false when it's ready for more input.
                    714:         *
                    715:         * When T_ISTOP is true, ttin() simply discards the character passed.
                    716:         */
                    717: #ifndef NOISILO
                    718:        if (!(tp->t_flags & T_ISTOP)) {
                    719:                while (in_silo->SILO_CHAR_COUNT > 0) {
                    720:                        s = sphi();
                    721:                        ttin(tp, in_silo->si_buf[in_silo->si_ox]);
                    722:                        if (in_silo->si_ox < MAX_SILO_INDEX)
                    723:                                in_silo->si_ox++;
                    724:                        else
                    725:                                in_silo->si_ox = 0;
                    726:                        in_silo->SILO_CHAR_COUNT--;
                    727:                        spl(s);
                    728:                }
                    729:        }
                    730: #endif
                    731: 
                    732:        /*
                    733:         * Hardware flow control.
                    734:         *      Check CTS to see if we need to halt output.
                    735:         *      (MS_INTR should have done this - repeat code here to be sure)
                    736:         *      Check input silo to see if we need to raise RTS.
                    737:         */
                    738:        if (tp->t_flags & T_CFLOW) {
                    739: 
                    740:                /*
                    741:                 * Get status
                    742:                 */
                    743:                msr = inb(ALPORT+MSR);
                    744: 
                    745:                s = sphi();
                    746:                if (msr & MS_CTS)
                    747:                        com_usage[AL_NUM].ohlt = 0;
                    748:                else
                    749:                        com_usage[AL_NUM].ohlt = 1;
                    750:                spl(s);
                    751: #if TRACER
                    752: if(t_hal & 4) {static cts = 0;
                    753: if (!cts && (msr & MS_CTS)) {
                    754:        cts = 1;
                    755:        printf("[");
                    756: } else if (cts && !(msr & MS_CTS)) {
                    757:        cts = 0;
                    758:        printf("]");
                    759: }}
                    760: #endif
                    761: 
                    762:                /*
                    763:                 * If using hardware flow control, see if we need to drop RTS.
                    764:                 */
                    765:                if ( (tp->t_flags & T_CFLOW)
                    766: #ifdef NO_ISILO
                    767:                && (tp->t_flags & T_ISTOP)) {
                    768: #else
                    769:                && (in_silo->SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
                    770: #endif
                    771:                        s = sphi();
                    772:                        mcr = inb(ALPORT+MCR);
                    773:                        if (mcr & MC_RTS) {
                    774:                                outb(ALPORT+MCR, mcr & ~MC_RTS);
                    775: #if TRACER
                    776: tprintf("-");
                    777: #endif
                    778:                        }
                    779:                        spl(s);
                    780:                }
                    781: 
                    782:                /*
                    783:                 * If input silo below low mark, assert RTS.
                    784:                 */
                    785: #ifdef NO_ISILO
                    786:                if ((tp->t_flags & T_ISTOP) == 0) {
                    787: #else
                    788:                if (in_silo->SILO_CHAR_COUNT <= SILO_LOW_MARK) {
                    789: #endif
                    790:                        s = sphi();
                    791:                        mcr = inb(ALPORT+MCR);
                    792:                        if ((mcr & MC_RTS) == 0) {
                    793:                                outb(ALPORT+MCR, mcr | MC_RTS);
                    794: #if TRACER
                    795: tprintf("+");
                    796: #endif
                    797:                        }
                    798:                        spl(s);
                    799:                }
                    800:        }
                    801: 
                    802:        /*
                    803:         * Calculate free output slot count.
                    804:         */
                    805:        n  = sizeof(out_silo->si_buf) - 1;
                    806:        n += out_silo->si_ox - out_silo->si_ix;
                    807:        n %= sizeof(out_silo->si_buf);
                    808: 
                    809:        /*
                    810:         * Fill raw output buffer.
                    811:         */
                    812:        for (;;) {
                    813:                if (--n < 0)
                    814:                        break;
                    815:                s = sphi();
                    816:                b = ttout(tp);
                    817:                spl(s);
                    818:                if (b < 0)
                    819:                        break;
                    820: 
                    821:                s = sphi();
                    822:                out_silo->si_buf[out_silo->si_ix] = b;
                    823:                if (out_silo->si_ix >= sizeof(out_silo->si_buf) - 1)
                    824:                        out_silo->si_ix = 0;
                    825:                else
                    826:                        out_silo->si_ix++;
                    827:                spl(s);
                    828:        }
                    829: 
                    830:        /*
                    831:         * (Re)start output, wake sleeping processes, etc.
                    832:         */
                    833:        ttstart(tp);
                    834: 
                    835:        /*
                    836:         * Schedule next cycle.
                    837:         */
                    838:        if (com_usage[AL_NUM].in_use)
                    839:                timeout(&tp->t_rawtim, HZ/10, alxcycle, tp);
                    840: }
                    841: 
                    842: /*
                    843:  * Serial Transmit Start Routine.
                    844:  */
                    845: alxstart(tp)
                    846: register TTY * tp;
                    847: {
                    848:        int b;
                    849:        int s;
                    850:        extern alxbreak();
                    851:        int need_xmit = 1;      /* True if should start sending data now. */
                    852:        silo_t * out_silo = &com_usage[AL_NUM].raw_out;
                    853: 
                    854:        /*
                    855:         * Read line status register AFTER disabling interrupts.
                    856:         */
                    857:        s = sphi();
                    858:        LSR_READ(b, ALPORT);
                    859: 
                    860:        /*
                    861:         * Process break indication.
                    862:         * NOTE: Break indication cleared when line status register was read.
                    863:         */
                    864:        if (b & LS_BREAK)
                    865:                defer(alxbreak, tp);
                    866: 
                    867:        /*
                    868:         * If no output data, it may be time to finish closing the port;
                    869:         * but won't need another xmit interrupt.
                    870:         */
                    871:        if (out_silo->si_ix == out_silo->si_ox) {
                    872:                wakeup((char *)out_silo);
                    873:                need_xmit = 0;
                    874:        }
                    875: 
                    876:        /*
                    877:         * Do nothing if output is stopped.
                    878:         */
                    879:        if (tp->t_flags & T_STOP)
                    880:                need_xmit = 0;
                    881:        if (com_usage[AL_NUM].ohlt)
                    882:                need_xmit = 0;
                    883: 
                    884:        /*
                    885:         * Start data transmission by writing to UART xmit reg.
                    886:         */
                    887:        if ((b & LS_TxRDY) && need_xmit) {
                    888:                int xmit_count;
                    889: 
                    890:                xmit_count = (com_usage[AL_NUM].uart_type == US_16550A)?16:1;
                    891:                alx_send(out_silo, ALPORT+DREG, xmit_count);
                    892:        }
                    893: 
                    894:        spl(s);
                    895: }
                    896: 
                    897: /*
                    898:  * Serial Received Break Handler.
                    899:  */
                    900: alxbreak(tp)
                    901: TTY * tp;
                    902: {
                    903:        int s;
                    904:        silo_t * out_silo = &com_usage[AL_NUM].raw_out;
                    905:        silo_t * in_silo = &com_usage[AL_NUM].raw_in;
                    906: 
                    907:        s = sphi();
                    908:        RAWIN_FLUSH(in_silo);
                    909:        RAWOUT_FLUSH(out_silo);
                    910:        spl(s);
                    911:        ttsignal(tp, SIGINT);
                    912: }
                    913: 
                    914: /*
                    915:  * Serial Interrupt Handler.
                    916:  */
                    917: alxintr(tp)
                    918: register TTY * tp;
                    919: {
                    920:        int c;
                    921:        register int port = ALPORT;
                    922:        unsigned char msr, lsr;
                    923:        int xmit_count;
                    924:        silo_t * in_silo = &com_usage[AL_NUM].raw_in;
                    925:        silo_t * out_silo = &com_usage[AL_NUM].raw_out;
                    926: 
                    927:        if (tp) {
                    928: rescan:
                    929:                switch (inb(port+IIR) & 0x07) {
                    930: 
                    931:                case LS_INTR:
                    932:                        LSR_READ(lsr, port);
                    933:                        if (lsr & LS_BREAK)
                    934:                                defer(alxbreak, tp);
                    935:                        goto rescan;
                    936: 
                    937:                case Rx_INTR:
                    938:                        c = inb(port+DREG);
                    939:                        if (tp->t_open == 0)
                    940:                                goto rescan;
                    941:                        /*
                    942:                         * Must recognize XOFF quickly to avoid transmit overrun.
                    943:                         * Recognize XON here as well to avoid race conditions.
                    944:                         */
                    945:                        if (_IS_IXON_MODE (tp)) {
                    946:                                /*
                    947:                                 * XOFF.
                    948:                                 */
                    949:                                if (_IS_STOP_CHAR (tp, c)) {
                    950:                                        tp->t_flags |= T_STOP;
                    951:                                        goto rescan;
                    952:                                }
                    953: 
                    954:                                /*
                    955:                                 * XON.
                    956:                                 */
                    957:                                if (_IS_START_CHAR (tp, c)) {
                    958:                                        tp->t_flags &= ~T_STOP;
                    959:                                        goto rescan;
                    960:                                }
                    961:                        }
                    962: 
                    963:                        /*
                    964:                         * Save char in raw input buffer.
                    965:                         */
                    966: #ifdef NO_ISILO
                    967:                        if (tp->t_flags & T_ISTOP) {
                    968:                                /*
                    969:                                 * If using hardware flow control, we need to drop RTS.
                    970:                                 */
                    971:                                if (tp->t_flags & T_CFLOW) {
                    972:                                        unsigned char mcr = inb(port+MCR);
                    973:                                        if (mcr & MC_RTS)
                    974:                                                outb(port+MCR, mcr & ~MC_RTS);
                    975:                                }
                    976:                        } else {
                    977:                                ttin(tp, c);
                    978:                        }
                    979: #else
                    980:                        if (in_silo->SILO_CHAR_COUNT < MAX_SILO_CHARS) {
                    981:                                in_silo->si_buf[in_silo->si_ix] = c;
                    982:                                if (in_silo->si_ix < MAX_SILO_INDEX)
                    983:                                        in_silo->si_ix++;
                    984:                                else
                    985:                                        in_silo->si_ix = 0;
                    986:                                in_silo->SILO_CHAR_COUNT++;
                    987:                        }
                    988: 
                    989:                        /*
                    990:                         * If using hardware flow control, see if we need to drop RTS.
                    991:                         */
                    992:                        if ( (tp->t_flags & T_CFLOW)
                    993:                        && (in_silo->SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
                    994:                                unsigned char mcr = inb(port+MCR);
                    995:                                if (mcr & MC_RTS) {
                    996:                                        outb(port+MCR, mcr & ~MC_RTS);
                    997:                                }
                    998:                        }
                    999: #endif
                   1000:                        goto rescan;
                   1001: 
                   1002:                case Tx_INTR:
                   1003:                        /*
                   1004:                         * Do nothing if output is stopped.
                   1005:                         */
                   1006:                        if (tp->t_flags & T_STOP)
                   1007:                                goto rescan;
                   1008:                        if (com_usage[AL_NUM].ohlt)
                   1009:                                goto rescan;
                   1010: 
                   1011:                        /*
                   1012:                         * Transmit next char in raw output buffer.
                   1013:                         */
                   1014:                        xmit_count =
                   1015:                          (com_usage[AL_NUM].uart_type == US_16550A)?16:1;
                   1016:                        alx_send(out_silo, port+DREG, xmit_count);
                   1017:                        goto rescan;
                   1018: 
                   1019:                case MS_INTR:
                   1020:                        /*
                   1021:                         * Get status (and clear interrupt).
                   1022:                         */
                   1023:                        msr = inb(port+MSR);
                   1024: 
                   1025:                        /*
                   1026:                         * Hardware flow control.
                   1027:                         *      Check CTS to see if we need to halt output.
                   1028:                         */
                   1029:                        if (tp->t_flags & T_CFLOW) {
                   1030:                                if (msr & MS_CTS)
                   1031:                                        com_usage[AL_NUM].ohlt = 0;
                   1032:                                else
                   1033:                                        com_usage[AL_NUM].ohlt = 1;
                   1034:                        }
                   1035: 
                   1036:                        goto rescan;
                   1037:                } /* endswitch */
                   1038:        } else {
                   1039:                /*
                   1040:                 * If tp is zero, an interrupt occurred before things
                   1041:                 * are fully set up.  Just try to clear all pending
                   1042:                 * interrupts from ANY serial ports.
                   1043:                 */
                   1044:                int com_num;
                   1045:                for (com_num = 0; com_num < 4; com_num++) {
                   1046:                        port = AL_ADDR[com_num];
                   1047:                        inb(port+IIR);
                   1048:                        inb(port+LSR);
                   1049:                        inb(port+MSR);
                   1050:                        inb(port+DREG);
                   1051:                }
                   1052:        }
                   1053: }
                   1054: 
                   1055: /*
                   1056:  * alxclk will be called every time T0 interrupts - if it returns 0,
                   1057:  * the usual system timer interrupt stuff is done
                   1058:  */
                   1059: static int alxclk()
                   1060: {
                   1061:        static int count;
                   1062:        int i;
                   1063: 
                   1064:        for (i = 0; i < NUM_AL_PORTS;  i++)
                   1065:                if (com_usage[i].poll)
                   1066:                        alxpoll(tp_table[i]);
                   1067:        count++;
                   1068:        if (count >= poll_divisor)
                   1069:                count = 0;
                   1070:        return count;
                   1071: }
                   1072: 
                   1073: /*
                   1074:  * set_poll_rate is called when a port is opened or closed or changes speed
                   1075:  * it sets the polling rate only as fast as needed, and shuts off polling
                   1076:  * whenever possible
                   1077:  */
                   1078: static set_poll_rate()
                   1079: {
                   1080:        int port_num, max_rate, port_rate;
                   1081: 
                   1082:        /*
                   1083:         * If another driver has the polling clock, do nothing.
                   1084:         */
                   1085:        if (poll_owner & ~ POLL_AL)
                   1086:                return;
                   1087: 
                   1088:        /*
                   1089:         * Find highest valid polling rate in units of HZ/10.
                   1090:         * If using FIFO chip, can poll at 1/16 the usual rate.
                   1091:         */
                   1092:        max_rate = 0;
                   1093:        for (port_num = 0; port_num < NUM_AL_PORTS; port_num++) {
                   1094:                if (com_usage[port_num].poll) {
                   1095:                        port_rate = alp_rate[(tp_table[port_num])->t_sgttyb.sg_ispeed];
                   1096:                        if (com_usage[port_num].uart_type == US_16550A) {
                   1097:                                port_rate /= 16;
                   1098:                                if (port_rate % HZ)
                   1099:                                        port_rate += HZ - (port_rate % HZ);
                   1100:                        }
                   1101:                        if (max_rate < port_rate)
                   1102:                                max_rate = port_rate;
                   1103:                }
                   1104:        }
                   1105:        /*
                   1106:         * if max_rate is not current rate, adjust the system clock
                   1107:         */
                   1108:        if (max_rate != poll_rate) {
                   1109:                poll_rate = max_rate;
                   1110:                poll_divisor = poll_rate/HZ;  /* used in alxclk() */
                   1111:                altclk_out();           /* stop previous polling */
                   1112:                poll_owner &= ~ POLL_AL;
                   1113:                if (max_rate) { /* resume polling at new rate if needed */
                   1114:                        poll_owner |= POLL_AL;
                   1115:                        altclk_in(poll_rate, alxclk);
                   1116:                }
                   1117:                CDUMP("new rate", 0)
                   1118:        }
                   1119: }
                   1120: 
                   1121: /*
                   1122:  * alxpoll()
                   1123:  *
                   1124:  * Serial polling handler.  Compare to alxintr().
                   1125:  */
                   1126: static void alxpoll(tp)
                   1127: register TTY * tp;
                   1128: {
                   1129:        int c;
                   1130:        int port = ALPORT;
                   1131:        int xmit_count;
                   1132:        unsigned char lsr;
                   1133:        silo_t * in_silo = &com_usage[AL_NUM].raw_in;
                   1134:        silo_t * out_silo = &com_usage[AL_NUM].raw_out;
                   1135: 
                   1136:        /*
                   1137:         * Check for received break first.
                   1138:         * This status is wiped out on reading the LSR.
                   1139:         */
                   1140:        LSR_READ(lsr, port);
                   1141:        if (lsr & LS_BREAK)
                   1142:                defer(alxbreak, tp);
                   1143: 
                   1144:        /*
                   1145:         * Handle all incoming characters.
                   1146:         */
                   1147:        for (;;) {
                   1148:                LSR_READ(lsr, port);
                   1149:                if ((lsr & LS_RxRDY) == 0)
                   1150:                        break;
                   1151:                c = inb(port+DREG);
                   1152:                if (tp->t_open == 0)
                   1153:                        continue;
                   1154:                /*
                   1155:                 * Must recognize XOFF quickly to avoid transmit overrun.
                   1156:                 * Recognize XON here as well to avoid race conditions.
                   1157:                 */
                   1158:                if (_IS_IXON_MODE (tp)) {
                   1159:                        /*
                   1160:                         * XOFF.
                   1161:                         */
                   1162:                        if (_IS_STOP_CHAR (tp, c)) {
                   1163:                                tp->t_flags |= T_STOP;
                   1164:                                continue;
                   1165:                        }
                   1166: 
                   1167:                        /*
                   1168:                         * XON.
                   1169:                         */
                   1170:                        if (_IS_START_CHAR (tp, c)) {
                   1171:                                tp->t_flags &= ~T_STOP;
                   1172:                                continue;
                   1173:                        }
                   1174:                }
                   1175: 
                   1176:                /*
                   1177:                 * Save char in raw input buffer.
                   1178:                 */
                   1179: #ifdef NO_ISILO
                   1180:                if (tp->t_flags & T_ISTOP) {
                   1181:                        /*
                   1182:                         * If using hardware flow control, we need to drop RTS.
                   1183:                         */
                   1184:                        if (tp->t_flags & T_CFLOW) {
                   1185:                                unsigned char mcr = inb(port+MCR);
                   1186:                                if (mcr & MC_RTS)
                   1187:                                        outb(port+MCR, mcr & ~MC_RTS);
                   1188:                        }
                   1189:                } else {
                   1190:                        ttin(tp, c);
                   1191:                }
                   1192: #else
                   1193:                if (in_silo->SILO_CHAR_COUNT < MAX_SILO_CHARS) {
                   1194:                        in_silo->si_buf[in_silo->si_ix] = c;
                   1195:                        if (in_silo->si_ix < MAX_SILO_INDEX)
                   1196:                                in_silo->si_ix++;
                   1197:                        else
                   1198:                                in_silo->si_ix = 0;
                   1199:                        in_silo->SILO_CHAR_COUNT++;
                   1200:                }
                   1201: 
                   1202:                /*
                   1203:                 * If using hardware flow control, see if we need to drop RTS.
                   1204:                 */
                   1205:                if ( (tp->t_flags & T_CFLOW)
                   1206:                  && (in_silo->SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
                   1207:                        unsigned char mcr = inb(port+MCR);
                   1208:                        if (mcr & MC_RTS) {
                   1209:                                outb(port+MCR, mcr & ~MC_RTS);
                   1210:                        }
                   1211:                }
                   1212: #endif
                   1213:        }
                   1214: 
                   1215:        /*
                   1216:         * Handle outgoing characters.
                   1217:         * Do nothing if output is stopped.
                   1218:         */
                   1219:        LSR_READ(lsr, port);
                   1220:        if ((lsr & LS_TxRDY)
                   1221:          && !(tp->t_flags & T_STOP)
                   1222:          && !(com_usage[AL_NUM].ohlt)) {
                   1223:                /*
                   1224:                 * Transmit next char in raw output buffer.
                   1225:                 */
                   1226:                xmit_count = (com_usage[AL_NUM].uart_type == US_16550A)?16:1;
                   1227:                alx_send(out_silo, port+DREG, xmit_count);
                   1228:        }
                   1229: 
                   1230:        /*
                   1231:         * Hardware flow control.
                   1232:         *      Check CTS to see if we need to halt output.
                   1233:         */
                   1234:        if (tp->t_flags & T_CFLOW) {
                   1235:                if (inb(port+MSR) & MS_CTS)
                   1236:                        com_usage[AL_NUM].ohlt = 0;
                   1237:                else
                   1238:                        com_usage[AL_NUM].ohlt = 1;
                   1239:        }
                   1240: }
                   1241: 
                   1242: /*
                   1243:  * alx_send()
                   1244:  *
                   1245:  * Write to xmit data register of the UART.
                   1246:  * Assume all checking about whether it's time to send has been done already.
                   1247:  * Called by time-critical IRQ and polling routines!
                   1248:  *
                   1249:  * "rawout" is the output silo for the TTY struct supplying data to the port.
                   1250:  * "dreg" is the i/o address of the UART xmit data register.
                   1251:  * "xmit_count" is the max number of chars we can write (16 for FIFO parts).
                   1252:  */
                   1253: static void alx_send(rawout, dreg, xmit_count)
                   1254: register silo_t * rawout;
                   1255: int dreg, xmit_count;
                   1256: {
                   1257:        /*
                   1258:         * Transmit next chars in raw output buffer.
                   1259:         */
                   1260:        for (;(rawout->si_ix != rawout->si_ox) && xmit_count; xmit_count--) {
                   1261:                outb(dreg, rawout->si_buf[rawout->si_ox]);
                   1262:                /*
                   1263:                 * Adjust raw output buffer output index.
                   1264:                 */
                   1265:                if (++rawout->si_ox >= sizeof(rawout->si_buf))
                   1266:                        rawout->si_ox = 0;
                   1267:        }
                   1268: }

unix.superglobalmegacorp.com

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