Annotation of coherent/d/kernel/USRSRC/i8086/drv/alx.c, revision 1.1

1.1     ! root        1: /* (-lgl
        !             2:  *     COHERENT Driver Kit Version 1.1.0
        !             3:  *     Copyright (c) 1982, 1990 by Mark Williams Company.
        !             4:  *     All rights reserved. May not be copied without permission.
        !             5:  *
        !             6:  * $Log:       alx.c,v $
        !             7:  * Revision 1.12  91/08/06  10:32:23  bin
        !             8:  * 2nd rts/cts version form hal
        !             9:  * 
        !            10:  * Revision 1.7  91/08/02  07:59:27  hal
        !            11:  * Raw input silo uses last slot for byte count.
        !            12:  * Modem control now gives RTS/CTS flow control:
        !            13:  *     CTS is checked 10x/sec (probably not often enough).
        !            14:  *     On Rx_INT, check T_ISTOP and rawin silo levels; drop RTS if need to.
        !            15:  * 
        !            16:  * Revision 1.6        91/04/03  18:55:07      root
        !            17:  * alxclose():  do closing state machine BEFORE dropping control lines.
        !            18:  * alxioctl():  save and restore interrupt enable register.
        !            19:  * alxopen():   wait for pending last close (fixes SLOW port bug).
        !            20:  * This version needs al.h 1.3 or later.
        !            21:  *
        !            22:  * Revision 1.5        91/04/02  17:53:37      root
        !            23:  * save MSR delta status; add MS_INTR handling; use al.h 1.2
        !            24:  *
        !            25:  * Revision 1.4        91/02/22  09:21:17      root
        !            26:  * alxintr():  replace repeated use of ALPORT macro by local variable
        !            27:  *
        !            28:  * Revision 1.3        91/02/21  14:58:16      root
        !            29:  * Fix unconditional "hupcl" bug in 3.1.0 version.
        !            30:  *
        !            31:  * Revision 1.2        91/02/21  11:21:40      hal
        !            32:  * Used in COH Release 3.1.0 - add COM3/COM4 and polling
        !            33:  *
        !            34:  * Revision 1.1        91/02/21  11:08:31      hal
        !            35:  * Used in COH Release 3.0.0 - no COM3/COM4
        !            36:  *
        !            37:  -lgl) */
        !            38: /*
        !            39:  * Shared parts of IBM async port drivers.
        !            40:  */
        !            41: #include <sys/coherent.h>
        !            42: #include <sys/i8086.h>
        !            43: #include <sys/al.h>
        !            44: #include <sys/con.h>
        !            45: #include <errno.h>
        !            46: #include <sys/stat.h>
        !            47: #include <sys/tty.h>
        !            48: #include <sys/uproc.h>
        !            49: #include <sys/timeout.h>
        !            50: #include <sys/clist.h>
        !            51: #include <sys/ins8250.h>
        !            52: #include <sys/sched.h>
        !            53: 
        !            54: #define ALPORT (((COM_DDP *)(tp->t_ddp))->port)
        !            55: #define AL_TIM (((COM_DDP *)(tp->t_ddp))->tim)
        !            56: #define AL_NUM (((COM_DDP *)(tp->t_ddp))->com_num)
        !            57: #define AL_MSR_DELTAS  (((COM_DDP *)(tp->t_ddp))->msr_deltas)
        !            58: #define AL_H_CLOSE     (((COM_DDP *)(tp->t_ddp))->h_close)
        !            59: 
        !            60: #define DTRTMOUT  3    /* DTR timeout interval in seconds for close */
        !            61: #define        IENABLE (IE_RxI+IE_TxI+IE_LSI+IE_MSI)
        !            62: 
        !            63: /*
        !            64:  * For rawin silo (see ktty.h), use last element of si_buf to count the number
        !            65:  * of characters in the silo.
        !            66:  */
        !            67: #define SILO_CHAR_COUNT        si_buf[SI_BUFSIZ-1]
        !            68: #define SILO_HIGH_MARK (SI_BUFSIZ-SI_BUFSIZ/4)
        !            69: #define MAX_SILO_INDEX (SI_BUFSIZ-2)
        !            70: #define MAX_SILO_CHARS (SI_BUFSIZ-1)
        !            71: 
        !            72: int    al_sg_set = 0;
        !            73: int    al_sg_clr = 0;
        !            74: static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */
        !            75: 
        !            76: /*
        !            77:  * functions herein
        !            78:  */
        !            79: int    alxopen();
        !            80: int    alxclose();
        !            81: int    alxtimer();
        !            82: int    alxioctl();
        !            83: int    alxparam();
        !            84: int    alxcycle();
        !            85: int    alxstart();
        !            86: int    alxbreak();
        !            87: int    alxintr();
        !            88: static int alxclk();
        !            89: static set_poll_rate();
        !            90: 
        !            91: /*
        !            92:  * Baud rate table and polling rate table.
        !            93:  * Indexed by ioctl bit rates.
        !            94:  */
        !            95: int albaud[] ={
        !            96:        0,                              /* 0 */
        !            97:        2304,                           /* 50 */
        !            98:        1536,                           /* 75 */
        !            99:        1047,                           /* 110 */
        !           100:        857,                            /* 134.5 */
        !           101:        768,                            /* 150 */
        !           102:        576,                            /* 200 */
        !           103:        384,                            /* 300 */
        !           104:        192,                            /* 600 */
        !           105:        96,                             /* 1200 */
        !           106:        64,                             /* 1800 */
        !           107:        58,                             /* 2000 */
        !           108:        48,                             /* 2400 */
        !           109:        32,                             /* 3600 */
        !           110:        24,                             /* 4800 */
        !           111:        16,                             /* 7200 */
        !           112:        12,                             /* 9600 */
        !           113:        6,                              /* 19200 */
        !           114:        0,                              /* EXTA */
        !           115:        0                               /* EXTB */
        !           116: };
        !           117: 
        !           118: /*
        !           119:  *     alp_rate[] is tied to albaud[] - it gives the minimum polling
        !           120:  *     rate for the corresponding port speed; it must be a multiple
        !           121:  *     of 100 (system clock Hz) and >= baud/6
        !           122:  */
        !           123: int alp_rate[] ={                      /* baud/6 or zero */
        !           124:        0,                              /* 0 */
        !           125:        1*HZ,                           /* 50 */
        !           126:        1*HZ,                           /* 75 */
        !           127:        1*HZ,                           /* 110 */
        !           128:        1*HZ,                           /* 134.5 */
        !           129:        1*HZ,                           /* 150 */
        !           130:        1*HZ,                           /* 200 */
        !           131:        1*HZ,                           /* 300 */
        !           132:        1*HZ,                           /* 600 */
        !           133:        2*HZ,                           /* 1200 */
        !           134:        3*HZ,                           /* 1800 */
        !           135:        4*HZ,                           /* 2000 */
        !           136:        4*HZ,                           /* 2400 */
        !           137:        6*HZ,                           /* 3600 */
        !           138:        8*HZ,                           /* 4800 */
        !           139:        12*HZ,                          /* 7200 */
        !           140:        16*HZ,                          /* 9600 */
        !           141:        0,                              /* 19200 */
        !           142:        0,                              /* EXTA */
        !           143:        0                               /* EXTB */
        !           144: };
        !           145: 
        !           146: /*
        !           147:  *     the following is for debug only
        !           148:  */
        !           149: #if 0
        !           150: #define CDUMP(text)    cdump(text);
        !           151: 
        !           152: cdump(message)
        !           153: char *message;
        !           154: {
        !           155:        int i, b;
        !           156: 
        !           157:        for (i = 0; i < NUM_AL_PORTS; i++) {
        !           158:                b = ((COM_DDP *)(tp_table[i]->t_ddp))->port;
        !           159:                printf("%x:%x:%x:%x ", i+1, b, inb(b+MCR), inb(b+IER));
        !           160:        }
        !           161:        printf("poll=%d ", poll_rate);
        !           162:        printf("%s\n", message);
        !           163: }
        !           164: #else
        !           165: #define CDUMP(text)
        !           166: #endif
        !           167: 
        !           168: /*
        !           169:  * alxopen()
        !           170:  */
        !           171: alxopen(dev, mode, tp, irqtty)
        !           172: dev_t  dev;
        !           173: int    mode;
        !           174: register TTY   *tp, **irqtty;
        !           175: {
        !           176:        register int    s;
        !           177:        register int    b;
        !           178:        register int    minor_h;  /* minor device number including high bit */
        !           179:        unsigned char   msr;
        !           180: 
        !           181:        minor_h = minor(dev);     /* complete minor number */
        !           182: 
        !           183:        b = ALPORT;
        !           184: 
        !           185:        if (inb(b+IER) & ~IENABLE) { /* chip not found */
        !           186:                u.u_error = ENXIO;
        !           187:                return;
        !           188:        }
        !           189: 
        !           190:        if ((tp->t_flags & T_EXCL) && !super()) {
        !           191:                u.u_error = ENODEV;
        !           192:                return;
        !           193:        }
        !           194: 
        !           195:        if (drvl[major(dev)].d_time != 0) {     /* Modem settling */
        !           196:                u.u_error = EDBUSY;
        !           197:                return;
        !           198:        }
        !           199: 
        !           200:        /*
        !           201:         * Can't open a polled port if another driver is using polling.
        !           202:         */
        !           203:        if (dev & CPOLL && poll_owner & ~ POLL_AL) {
        !           204:                u.u_error = EDBUSY;
        !           205:                return;
        !           206:        }
        !           207: 
        !           208:        /*
        !           209:         * exclusion conditions:
        !           210:         *      can't have same port polled and IRQ at once
        !           211:         *      can't have both com[13] or both com[24] IRQ at once
        !           212:         */
        !           213:        if (dev & CPOLL) {
        !           214:                if (com_usage[AL_NUM] == COM_IRQ) {
        !           215:                        u.u_error = EDBUSY;
        !           216:                        return;
        !           217:                }
        !           218:        } else {
        !           219:                if (com_usage[AL_NUM] == COM_POLLED
        !           220:                   || com_usage[AL_NUM ^ 2] == COM_IRQ) {
        !           221:                        u.u_error = EDBUSY;
        !           222:                        return;
        !           223:                }
        !           224:        }
        !           225: 
        !           226:        if (tp->t_open == 0) {        /* not already open */
        !           227:                /*
        !           228:                 * Wait for pending last close (if any) to finish.
        !           229:                 */
        !           230:                while (AL_H_CLOSE) {
        !           231:                        sleep((char *)(&AL_H_CLOSE), CVTTOUT, IVTTOUT,
        !           232:                                SVTTOUT);
        !           233:                }
        !           234:                s = sphi();
        !           235:                /*
        !           236:                 * Raise basic modem control lines even if modem
        !           237:                 * control hasn't been specified.
        !           238:                 * MC_OUT2 turns on NON-open-collector IRQ line from the UART.
        !           239:                 * since we can't have two UART's on same IRQ with MC_OUT2 on
        !           240:                 */
        !           241:                if (dev & CPOLL) {
        !           242:                        outb(b+MCR, MC_RTS|MC_DTR);
        !           243:                } else {
        !           244:                        *irqtty = tp_table[AL_NUM];
        !           245:                        outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
        !           246:                }
        !           247: 
        !           248:                outb(b+IER, IENABLE);        /* enable interrupts */
        !           249: 
        !           250:                if ((minor_h & NMODC) == 0) {   /* want modem control? */
        !           251:                        tp->t_flags |= T_MODC | T_HOPEN | T_STOP;
        !           252:                        while (1) {     /* wait for carrier */
        !           253:                                msr = inb(b+MSR);
        !           254:                                AL_MSR_DELTAS |= msr;
        !           255:                                if (msr & MS_RLSD)
        !           256:                                        break;
        !           257:                                sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
        !           258:                                        SVTTOUT);       /* wait for carrier */
        !           259:                                if (SELF->p_ssig && nondsig()) {  /* signal? */
        !           260:                                        outb(b+MCR, inb(b+MCR)&MC_OUT2);
        !           261:                                        /*
        !           262:                                         * make sure port is hungup
        !           263:                                         * disable all ints except for TxI
        !           264:                                         */
        !           265:                                        outb(b+IER, IE_TxI);
        !           266:                                        u.u_error = EINTR;
        !           267:                                        spl(s);
        !           268:                                        return;
        !           269:                                }
        !           270:                        }
        !           271:                        tp->t_flags &= ~T_HOPEN; /* no longer hanging in open */
        !           272:                        if (msr & MS_CTS)
        !           273:                                tp->t_flags &= ~T_STOP;
        !           274:                } else {
        !           275:                        tp->t_flags &= ~T_MODC;         /* no modem control */
        !           276:                }
        !           277:                tp->t_flags |= T_CARR;                  /* carrier on */
        !           278:                ttopen(tp);                             /* stty inits */
        !           279: 
        !           280:                /*
        !           281:                 * Allow custom modification of defaults.
        !           282:                 */
        !           283:                tp->t_sgttyb.sg_flags |=  al_sg_set;
        !           284:                tp->t_sgttyb.sg_flags &= ~al_sg_clr;
        !           285:                alxparam(tp);
        !           286:                spl(s);
        !           287:        } else {                                /* already open */
        !           288:                if ((minor_h & NMODC) == 0) {   /* want modem control? */
        !           289:                    if ((tp->t_flags & T_MODC)==0) { /* already not modem control? */
        !           290:                        u.u_error = ENODEV;     /* yes, don't allow open */
        !           291:                        return;
        !           292:                    }
        !           293:                } else {                         /* don't want modem control */
        !           294:                        if (tp->t_flags & T_MODC) { /* already modem control? */
        !           295:                                u.u_error = ENODEV; /* yes, don't allow open */
        !           296:                                return;
        !           297:                        }
        !           298:                }
        !           299:        }
        !           300:        tp->t_open++;
        !           301:        ttsetgrp(tp, dev);
        !           302: 
        !           303:        /*
        !           304:         * now that we've successfully opened, designate port as
        !           305:         * polled or interrupt driven to avoid future conflicts
        !           306:         */
        !           307:        if (dev & CPOLL) {
        !           308:                com_usage[AL_NUM] = COM_POLLED;
        !           309:                set_poll_rate();
        !           310:        } else {                                /* irq-driven port */
        !           311:                com_usage[AL_NUM] = COM_IRQ;
        !           312:        }
        !           313: 
        !           314:        CDUMP((dev&CPOLL)?"open polled":"open irq")
        !           315: }
        !           316: 
        !           317: /*
        !           318:  * alxclose()
        !           319:  *
        !           320:  *     Called at high priority on last close for the device.
        !           321:  */
        !           322: alxclose(dev, mode, tp)
        !           323: dev_t  dev;
        !           324: int    mode;
        !           325: TTY    *tp;
        !           326: {
        !           327:        register unsigned holdflags;
        !           328:        register int b;
        !           329:        int state, maj;
        !           330:        int s;
        !           331: 
        !           332:        /*
        !           333:         * Called at high priority by alclose after al_buff is drained
        !           334:         */
        !           335:        holdflags = tp->t_flags;        /* save flags */
        !           336:        AL_H_CLOSE = 1;                 /* disallow reopen til done closing */
        !           337:        ttclose(tp);                    /* clear flags */
        !           338:        b = ALPORT;
        !           339:        /*
        !           340:         * ttclose() only emptied the output queue tp->t_oq;
        !           341:         * now wait for the silo tp->rawout to empty
        !           342:         * and allow a delay for the UART on-chip xmit buffer to empty
        !           343:         * state 2: waiting for silo to empty
        !           344:         * state 1: stalling so UART can empty xmit buffer
        !           345:         * state 0: done!  ok to shut off IRQ for this chip by clearing MC_OUT2
        !           346:         */
        !           347:        state = 2;
        !           348:        while (state) {
        !           349:                timeout(&AL_TIM, 10, wakeup, (int)&AL_TIM);
        !           350:                sleep((char *)&AL_TIM, CVTTOUT, IVTTOUT, SVTTOUT);
        !           351:                if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
        !           352:                        state--;
        !           353:        }
        !           354: 
        !           355:        /*
        !           356:         * If not hanging in open
        !           357:         */
        !           358:        if ((holdflags & T_HOPEN) == 0) {
        !           359:                /*
        !           360:                 * Disable all ints except TxI
        !           361:                 */
        !           362:                outb(b+IER, IE_TxI);
        !           363:        } else {
        !           364:                /*
        !           365:                 * Flags for first open
        !           366:                 */
        !           367:                tp->t_flags = T_MODC | T_HOPEN;
        !           368:        }
        !           369: 
        !           370:        /*
        !           371:         * If hupcls
        !           372:         */
        !           373:        if (holdflags & T_HPCL) {
        !           374:                /*
        !           375:                 * Hangup port
        !           376:                 */
        !           377:                s = sphi();
        !           378:                outb(b+MCR, inb(b+MCR)&MC_OUT2);
        !           379:                spl(s);
        !           380: 
        !           381:                /*
        !           382:                 * Hold dtr low for timeout
        !           383:                 */
        !           384:                maj = major(dev);
        !           385:                drvl[maj].d_time = 1;
        !           386:                sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
        !           387:                drvl[maj].d_time = 0;
        !           388:        }
        !           389:        s = sphi();
        !           390:        outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
        !           391:        spl(s);
        !           392:        com_usage[AL_NUM] = COM_UNUSED;
        !           393:        set_poll_rate();
        !           394:        AL_H_CLOSE = 0;         /* allow reopen - done closing */
        !           395:        wakeup((char *)&AL_H_CLOSE);
        !           396:        CDUMP("closed")
        !           397: }
        !           398: 
        !           399: /*
        !           400:  * Common c_timer routine for async ports.
        !           401:  */
        !           402: alxtimer(dev)
        !           403: dev_t dev;
        !           404: {
        !           405:        if (++drvl[major(dev)].d_time > DTRTMOUT)
        !           406:                wakeup((char *)&drvl[major(dev)].d_time);
        !           407: }
        !           408: 
        !           409: 
        !           410: /*
        !           411:  * Common c_ioctl routine for async ports.
        !           412:  */
        !           413: alxioctl(dev, com, vec, tp)
        !           414: dev_t  dev;
        !           415: struct sgttyb *vec;
        !           416: register TTY   *tp;
        !           417: {
        !           418:        register int    s, b;
        !           419:        int stat1, stat2;
        !           420:        unsigned char   msr;
        !           421:        unsigned char ier_save;
        !           422: 
        !           423:        s = sphi();
        !           424:        b = ALPORT;
        !           425:        ier_save=inb(b+IER);
        !           426:        stat1 = inb(b+MCR);             /* get current MCR register status */
        !           427:        stat2 = inb(b+LCR);             /* get current LCR register status */
        !           428: 
        !           429:        switch(com) {
        !           430:        case TIOCSBRK:                  /* set BREAK */
        !           431:                outb(b+LCR, stat2|LC_SBRK);
        !           432:                break;
        !           433:        case TIOCCBRK:                  /* clear BREAK */
        !           434:                outb(b+LCR, stat2 & ~LC_SBRK);
        !           435:                break;
        !           436:        case TIOCSDTR:                  /* set DTR */
        !           437:                outb(b+MCR, stat1|MC_DTR);
        !           438:                break;
        !           439:        case TIOCCDTR:                  /* clear DTR */
        !           440:                outb(b+MCR, stat1 & ~MC_DTR);
        !           441:                break;
        !           442:        case TIOCSRTS:                  /* set RTS */
        !           443:                outb(b+MCR, stat1|MC_RTS);
        !           444:                break;
        !           445:        case TIOCCRTS:                  /* clear RTS */
        !           446:                outb(b+MCR, stat1 & ~MC_RTS);
        !           447:                break;
        !           448:        case TIOCRSPEED:                /* set "raw" I/O speed divisor */
        !           449:                outb(b+LCR, stat2|LC_DLAB);  /* set speed latch bit */
        !           450:                outb(b+DLL, (unsigned) vec);
        !           451:                outb(b+DLH, (unsigned) vec >> 8);
        !           452:                outb(b+LCR, stat2);       /* reset latch bit */
        !           453:                break;
        !           454:        case TIOCWORDL:         /* set word length and stop bits */
        !           455:                outb(b+LCR, ((stat2&~0x7) | ((unsigned) vec & 0x7)));
        !           456:                break;
        !           457:        case TIOCRMSR:          /* get CTS/DSR/RI/RLSD (MSR) */
        !           458:                msr = inb(b+MSR);
        !           459:                AL_MSR_DELTAS |= msr;
        !           460:                stat1 = msr >> 4;
        !           461:                kucopy(&stat1, (unsigned *) vec, sizeof(unsigned));
        !           462:                break;
        !           463:        default:
        !           464:                ttioctl(tp, com, vec);
        !           465:        }
        !           466:        outb(b+IER, ier_save);
        !           467:        spl(s);
        !           468: }
        !           469: 
        !           470: alxparam(tp)
        !           471: TTY    *tp;
        !           472: {
        !           473:        register int    b;
        !           474:        register int    baud;
        !           475:        int s;
        !           476: 
        !           477:        b = ALPORT;
        !           478: 
        !           479:        /*
        !           480:         * error if input speed not the same as output speed
        !           481:         */
        !           482:        if (tp->t_sgttyb.sg_ispeed!=tp->t_sgttyb.sg_ospeed) {
        !           483:                u.u_error = ENODEV;
        !           484:                return;
        !           485:        }
        !           486: 
        !           487:        if ((baud = albaud[tp->t_sgttyb.sg_ispeed]) == 0) {
        !           488:                if (tp->t_flags & T_MODC) {  /* modem control? */
        !           489:                        tp->t_flags &= ~T_CARR;  /* indicate no carrier */
        !           490:                        s = sphi();
        !           491:                        outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
        !           492:                        spl(s);
        !           493:                }
        !           494:        }
        !           495: 
        !           496:        if (baud) {
        !           497:                unsigned char ier_save;
        !           498: 
        !           499:                s=sphi();
        !           500:                ier_save=inb(b+IER);    /* some chips need this */
        !           501:                outb(b+LCR, LC_DLAB);
        !           502:                outb(b+DLL, baud);
        !           503:                outb(b+DLH, baud >> 8);
        !           504:                switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
        !           505:                case EVENP:
        !           506:                        outb(b+LCR, LC_CS7 + LC_PARENB + LC_PAREVEN);
        !           507:                        break;
        !           508: 
        !           509:                case ODDP:
        !           510:                        outb(b+LCR, LC_CS7 + LC_PARENB);
        !           511:                        break;
        !           512: 
        !           513:                default:
        !           514:                        outb(b+LCR, LC_CS8);
        !           515:                        break;
        !           516:                }
        !           517:                outb(b+IER, ier_save);
        !           518:                spl(s);
        !           519:        }
        !           520:        set_poll_rate();
        !           521: }
        !           522: 
        !           523: /*
        !           524:  * Middle level processor.
        !           525:  *
        !           526:  *     Invoked 10 times per second.
        !           527:  *     Checks modem status for loss of carrier.
        !           528:  *     Tranfers rawin buffer [from intr level] to canonical input queue.
        !           529:  *     Transfers output queue to rawout buffer [for intr level].
        !           530:  */
        !           531: alxcycle(tp)
        !           532: register TTY * tp;
        !           533: {
        !           534:        register int b;
        !           535:        register int n;
        !           536:        unsigned char msr, mcr;
        !           537:        int s;
        !           538: 
        !           539:        /*
        !           540:         * Check modem status every ten clock ticks.
        !           541:         *
        !           542:         * Modem status interrupts were not enabled due to 8250 hardware bug.
        !           543:         * Enabling modem status and receive interrupts may cause lockup
        !           544:         * on older parts.
        !           545:         *
        !           546:         * Also check if input silo is nearly full in case we need RTS
        !           547:         * flow control.
        !           548:         */
        !           549:        if (tp->t_flags & T_MODC) {
        !           550: 
        !           551:                /*
        !           552:                 * Get status
        !           553:                 */
        !           554:                msr = inb(ALPORT+MSR);
        !           555:                AL_MSR_DELTAS |= msr;
        !           556: 
        !           557:                /*
        !           558:                 * Carrier changed.
        !           559:                 */
        !           560:                if (AL_MSR_DELTAS & MS_DRLSD) {
        !           561:                        AL_MSR_DELTAS &= ~MS_DRLSD;
        !           562:                        /*
        !           563:                         * wakeup open
        !           564:                         */
        !           565:                        if (tp->t_open == 0) {
        !           566:                                wakeup((char *)(&tp->t_open));
        !           567:                        }
        !           568: 
        !           569:                        /*
        !           570:                         * carrier off?
        !           571:                         */
        !           572:                        else if ((msr & MS_RLSD) == 0) {
        !           573:                                /*
        !           574:                                 * clear carrier flag; send hangup signal
        !           575:                                 */
        !           576:                                s = sphi();
        !           577:                                tp->t_rawin.si_ox = tp->t_rawin.si_ix;
        !           578:                                tp->t_rawin.SILO_CHAR_COUNT = 0;
        !           579:                                spl(s);
        !           580:                                tthup(tp);
        !           581:                        }
        !           582:                }
        !           583: 
        !           584:                /*
        !           585:                 * CTS changed.
        !           586:                 */
        !           587:                if (AL_MSR_DELTAS & MS_DCTS) {
        !           588:                        AL_MSR_DELTAS &= ~MS_DCTS;
        !           589:                        if (msr & MS_CTS)
        !           590:                                tp->t_flags &= ~T_STOP;
        !           591:                        else
        !           592:                                tp->t_flags |= T_STOP;
        !           593:                }
        !           594: 
        !           595:                /*
        !           596:                 * If input silo not nearly full, assert RTS.
        !           597:                 */
        !           598:                if (tp->t_rawin.SILO_CHAR_COUNT <= SILO_HIGH_MARK) {
        !           599:                        mcr = inb(ALPORT+MCR);
        !           600:                        if ((mcr & MC_RTS) == 0) {
        !           601: printf("%x RTS ON\n", ALPORT);
        !           602:                                outb(ALPORT+MCR, mcr | MC_RTS);
        !           603:                        }
        !           604:                }
        !           605:        }
        !           606: 
        !           607:        /*
        !           608:         * Empty raw input buffer.
        !           609:         * If modem control enabled and tt input queue is at high limit
        !           610:         * (e.g., tp->t_iq.cq_cc >= IHILIM), don't copy from rawin silo
        !           611:         * to tt input queue.
        !           612:         */
        !           613:        if (!(tp->t_flags & T_MODC) || !(tp->t_flags & T_ISTOP))
        !           614:                while (tp->t_rawin.SILO_CHAR_COUNT > 0) {
        !           615:                        ttin(tp, tp->t_rawin.si_buf[tp->t_rawin.si_ox]);
        !           616:                        if (tp->t_rawin.si_ox < MAX_SILO_INDEX)
        !           617:                                tp->t_rawin.si_ox++;
        !           618:                        else
        !           619:                                tp->t_rawin.si_ox = 0;
        !           620:                        tp->t_rawin.SILO_CHAR_COUNT--;
        !           621:                }
        !           622: 
        !           623:        /*
        !           624:         * Calculate free output slot count.
        !           625:         */
        !           626:        n  = sizeof(tp->t_rawout.si_buf) - 1;
        !           627:        n += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
        !           628:        n %= sizeof(tp->t_rawout.si_buf);
        !           629: 
        !           630:        /*
        !           631:         * Fill raw output buffer.
        !           632:         */
        !           633:        while ((--n >= 0) && ((b = ttout(tp)) >= 0)) {
        !           634:                tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = b;
        !           635:                if (tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1)
        !           636:                        tp->t_rawout.si_ix = 0;
        !           637:                else
        !           638:                        tp->t_rawout.si_ix++;
        !           639:        }
        !           640: 
        !           641:        /*
        !           642:         * (Re)start output, wake sleeping processes, etc.
        !           643:         */
        !           644:        ttstart(tp);
        !           645: 
        !           646:        /*
        !           647:         * Schedule next cycle.
        !           648:         */
        !           649:        timeout(&tp->t_rawtim, HZ/10, alxcycle, tp);
        !           650: }
        !           651: 
        !           652: /*
        !           653:  * Serial Transmit Start Routine.
        !           654:  */
        !           655: alxstart(tp)
        !           656: register TTY * tp;
        !           657: {
        !           658:        register int b;
        !           659:        register int s;
        !           660:        extern alxbreak();
        !           661: 
        !           662:        /*
        !           663:         * Read line status register AFTER disabling interrupts.
        !           664:         */
        !           665:        s = sphi();
        !           666:        b = inb(ALPORT+LSR);
        !           667: 
        !           668:        /*
        !           669:         * Process break indication.
        !           670:         * NOTE: Break indication cleared when line status register was read.
        !           671:         */
        !           672:        if (b & LS_BREAK)
        !           673:                defer(alxbreak, tp);
        !           674: 
        !           675:        /*
        !           676:         * Transmitter is empty, output data is pending.
        !           677:         */
        !           678:        if ((b & LS_TxRDY) && (tp->t_rawout.si_ix != tp->t_rawout.si_ox)) {
        !           679:                outb(   ALPORT+DREG,
        !           680:                        tp->t_rawout.si_buf[ tp->t_rawout.si_ox ]);
        !           681:                if (++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf))
        !           682:                        tp->t_rawout.si_ox = 0;
        !           683:        }
        !           684:        spl(s);
        !           685: }
        !           686: 
        !           687: /*
        !           688:  * Serial Received Break Handler.
        !           689:  */
        !           690: alxbreak(tp)
        !           691: TTY * tp;
        !           692: {
        !           693:        ttsignal(tp, SIGINT);
        !           694: }
        !           695: 
        !           696: /*
        !           697:  * Serial Interrupt Handler.
        !           698:  */
        !           699: alxintr(tp)
        !           700: register TTY * tp;
        !           701: {
        !           702:        register int    b;
        !           703:        int port = ALPORT;
        !           704:        unsigned char mcr;
        !           705: 
        !           706: rescan:
        !           707:        switch (inb(port+IIR)) {
        !           708: 
        !           709:        case LS_INTR:
        !           710:                if (inb(port+LSR) & LS_BREAK)
        !           711:                        defer(alxbreak, tp);
        !           712:                goto rescan;
        !           713: 
        !           714:        case Rx_INTR:
        !           715:                b = inb(port+DREG);
        !           716:                if (tp->t_open == 0)
        !           717:                        goto rescan;
        !           718:                /*
        !           719:                 * Must recognize XOFF quickly to avoid transmit overrun.
        !           720:                 * Recognize XON here as well to avoid race conditions.
        !           721:                 */
        !           722:                if ((tp->t_sgttyb.sg_flags & RAWIN) == 0) {
        !           723:                        /*
        !           724:                         * XOFF.
        !           725:                         */
        !           726:                        if (tp->t_tchars.t_stopc == (b & 0177)) {
        !           727:                                tp->t_flags |= T_STOP;
        !           728:                                goto rescan;
        !           729:                        }
        !           730: 
        !           731:                        /*
        !           732:                         * XON.
        !           733:                         */
        !           734:                        if (tp->t_tchars.t_startc == (b & 0177)) {
        !           735:                                tp->t_flags &= ~T_STOP;
        !           736:                                goto rescan;
        !           737:                        }
        !           738:                }
        !           739: 
        !           740:                /*
        !           741:                 * Save char in raw input buffer.
        !           742:                 */
        !           743:                if (tp->t_rawin.SILO_CHAR_COUNT < MAX_SILO_CHARS) {
        !           744:                        tp->t_rawin.si_buf[tp->t_rawin.si_ix] = b;
        !           745:                        if (tp->t_rawin.si_ix < MAX_SILO_INDEX)
        !           746:                                tp->t_rawin.si_ix++;
        !           747:                        else
        !           748:                                tp->t_rawin.si_ix = 0;
        !           749:                        tp->t_rawin.SILO_CHAR_COUNT++;
        !           750:                }
        !           751:                if (tp->t_flags & T_MODC)
        !           752:                        if ((tp->t_flags & T_ISTOP)
        !           753:                        || (tp->t_rawin.SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
        !           754:                                mcr = inb(port+MCR);
        !           755:                                if (mcr & MC_RTS) {
        !           756:                                        outb(port+MCR, mcr & ~MC_RTS);
        !           757: printf("%x RTS OFF\n", port);
        !           758:                                }
        !           759:                        }
        !           760:                goto rescan;
        !           761: 
        !           762:        case Tx_INTR:
        !           763:                /*
        !           764:                 * Do nothing if no raw output data or output is stopped.
        !           765:                 */
        !           766:                if (tp->t_rawout.si_ix == tp->t_rawout.si_ox) {
        !           767:                        goto rescan;
        !           768:                }
        !           769:                if (tp->t_flags & T_STOP)
        !           770:                        goto rescan;
        !           771: 
        !           772:                /*
        !           773:                 * Transmit next char in raw output buffer.
        !           774:                 */
        !           775:                outb(port+DREG,
        !           776:                        tp->t_rawout.si_buf[ tp->t_rawout.si_ox ]);
        !           777: 
        !           778:                /*
        !           779:                 * Adjust raw output buffer output index.
        !           780:                 */
        !           781:                if (++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf))
        !           782:                        tp->t_rawout.si_ox = 0;
        !           783: 
        !           784:                /*
        !           785:                 * Try to fill buffer if now empty.
        !           786:                 */
        !           787:                if (tp->t_rawout.si_ox == tp->t_rawout.si_ix) {
        !           788:                        defer(alxcycle, tp);
        !           789:                }
        !           790:                goto rescan;
        !           791: 
        !           792:        case MS_INTR:
        !           793:                AL_MSR_DELTAS |= inb(port+MSR);
        !           794:                defer(alxcycle, tp);
        !           795:                goto rescan;
        !           796:        }
        !           797: }
        !           798: 
        !           799: /*
        !           800:  * alxclk will be called every time T0 interrupts - if it returns 0,
        !           801:  * the usual system timer interrupt stuff is done
        !           802:  */
        !           803: static int alxclk()
        !           804: {
        !           805:        static int count;
        !           806:        int i;
        !           807: 
        !           808:        for (i = 0; i < NUM_AL_PORTS;  i++)
        !           809:                if (com_usage[i] == COM_POLLED)
        !           810:                        alxintr(tp_table[i]);
        !           811:        count++;
        !           812:        if (count >= poll_divisor)
        !           813:                count = 0;
        !           814:        return count;
        !           815: }
        !           816: 
        !           817: /*
        !           818:  * set_poll_rate is called when a port is opened or closed or changes speed
        !           819:  * it sets the polling rate only as fast as needed, and shuts off polling
        !           820:  * whenever possible
        !           821:  */
        !           822: static set_poll_rate()
        !           823: {
        !           824:        int port_num, max_rate, port_rate;
        !           825: 
        !           826:        /*
        !           827:         * If another driver has the polling clock, do nothing.
        !           828:         */
        !           829:        if (poll_owner & ~ POLL_AL)
        !           830:                return;
        !           831: 
        !           832:        /*
        !           833:         * find highest valid polling rate in units of HZ/10
        !           834:         */
        !           835:        max_rate = 0;
        !           836:        for (port_num = 0; port_num < NUM_AL_PORTS; port_num++) {
        !           837:                if (com_usage[port_num] == COM_POLLED) {
        !           838:                        port_rate = alp_rate[(tp_table[port_num])->t_sgttyb.sg_ispeed];
        !           839:                        if (max_rate < port_rate)
        !           840:                                max_rate = port_rate;
        !           841:                }
        !           842:        }
        !           843:        /*
        !           844:         * if max_rate is not current rate, adjust the system clock
        !           845:         */
        !           846:        if (max_rate != poll_rate) {
        !           847:                poll_rate = max_rate;
        !           848:                poll_divisor = poll_rate/HZ;  /* used in alxclk() */
        !           849:                altclk_out();           /* stop previous polling */
        !           850:                poll_owner &= ~ POLL_AL;
        !           851:                if (max_rate) { /* resume polling at new rate if needed */
        !           852:                        poll_owner |= POLL_AL;
        !           853:                        altclk_in(poll_rate, alxclk);
        !           854:                }
        !           855:                CDUMP("new rate")
        !           856:        }
        !           857: }

unix.superglobalmegacorp.com

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