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

unix.superglobalmegacorp.com

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