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

unix.superglobalmegacorp.com

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