Annotation of coherent/d/286_KERNEL/USRSRC/io/alx.c, revision 1.1

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