Annotation of coherent/d/PS2_KERNEL/io.386/alx.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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