Annotation of coherent/d/kernel/USRSRC/i8086/drv/alx.c, revision 1.1.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.