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

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

unix.superglobalmegacorp.com

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