Annotation of Gnu-Mach/i386/i386at/com.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1994,1993,1991,1990 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: 
                     27: #include <com.h>
                     28: #if NCOM > 0
                     29: 
                     30: #include <mach/std_types.h>
                     31: #include <sys/types.h>
                     32: #include <sys/time.h>
                     33: #include <device/conf.h>
                     34: #include <device/errno.h>
                     35: #include <device/tty.h>
                     36: #include <device/io_req.h>
                     37: 
                     38: #include <i386/ipl.h>
                     39: #include <i386/pio.h>
                     40: #include <i386/machspl.h>
                     41: #include <chips/busses.h>
                     42: #include <i386at/comreg.h>
                     43: 
                     44: #include <rc.h>
                     45: #include <cons.h>
                     46: 
                     47: extern void timeout(), ttrstrt();
                     48: 
                     49: int comprobe(), comintr(), comstart(), commctl();
                     50: void comattach();
                     51: static void comparam();
                     52: int comstop(), comgetstat(), comsetstat();
                     53: 
                     54: static vm_offset_t com_std[NCOM] = { 0 };
                     55: struct bus_device *cominfo[NCOM];
                     56: struct bus_driver comdriver = {
                     57:        comprobe, 0, comattach, 0, com_std, "com", cominfo, 0, 0, 0};
                     58: 
                     59: struct tty com_tty[NCOM];
                     60: int commodem[NCOM];
                     61: int comcarrier[NCOM] = {0, 0,};
                     62: boolean_t comfifo[NCOM];
                     63: boolean_t comtimer_active;
                     64: int comtimer_state[NCOM];
                     65: 
                     66: #if RCLINE >= 0
                     67: #define RCBAUD B9600
                     68: static struct bus_device *comcndev;
                     69: int comcnprobe(struct consdev *cp);
                     70: int comcninit(struct consdev *cp);
                     71: int comcngetc(dev_t dev, int wait);
                     72: int comcnputc(dev_t dev, int c);
                     73: #endif
                     74: 
                     75: #ifndef        PORTSELECTOR
                     76: #define ISPEED B9600
                     77: #define IFLAGS (EVENP|ODDP|ECHO|CRMOD)
                     78: #else
                     79: #define ISPEED B4800
                     80: #define IFLAGS (EVENP|ODDP)
                     81: #endif
                     82: 
                     83: u_short divisorreg[] = {
                     84:        0,      2304,   1536,   1047,           /*     0,    50,    75,   110*/
                     85:        857,     768,    576,    384,    192,   /*   134.5, 150,   200,   300,   600*/
                     86:         96,      64,             48,           /*  1200,  1800,  2000,  2400 */
                     87:                  24,             12,           /*  3600,  4800,  7200,  9600 */
                     88:          6,       3,      2};                  /* 19200, 38400, 56000 */
                     89: 
                     90: 
                     91: /*
                     92:  *
                     93:  * Probes are called during kernel boot: return 1 to mean that
                     94:  * the relevant device is present today.
                     95:  *
                     96:  */
                     97: int
                     98: comprobe_general(struct bus_device *dev, int noisy)
                     99: {
                    100:        u_short addr = dev->address;
                    101:        int     unit = dev->unit;
                    102:        int     oldctl, oldmsb;
                    103:        char    *type = "8250";
                    104:        int     i;
                    105: 
                    106:        if ((unit < 0) || (unit > NCOM)) {
                    107:                printf("com %d out of range\n", unit);
                    108:                return(0);
                    109:        }
                    110:        oldctl = inb(LINE_CTL(addr));    /* Save old value of LINE_CTL */
                    111:        oldmsb = inb(BAUD_MSB(addr));    /* Save old value of BAUD_MSB */
                    112:        outb(LINE_CTL(addr), 0);         /* Select INTR_ENAB */    
                    113:        outb(BAUD_MSB(addr), 0);
                    114:        if (inb(BAUD_MSB(addr)) != 0)
                    115:          {
                    116:            outb(LINE_CTL(addr), oldctl);
                    117:            outb(BAUD_MSB(addr), oldmsb);
                    118:            return 0;
                    119:          }
                    120:        outb(LINE_CTL(addr), iDLAB);     /* Select BAUD_MSB */
                    121:        outb(BAUD_MSB(addr), 255);
                    122:        if (inb(BAUD_MSB(addr)) != 255)
                    123:          {
                    124:            outb(LINE_CTL(addr), oldctl);
                    125:            outb(BAUD_MSB(addr), oldmsb);
                    126:            return 0;
                    127:          }
                    128:        outb(LINE_CTL(addr), 0);         /* Select INTR_ENAB */
                    129:        if (inb(BAUD_MSB(addr)) != 0)    /* Check that it has kept its value*/
                    130:          {
                    131:            outb(LINE_CTL(addr), oldctl);
                    132:            outb(BAUD_MSB(addr), oldmsb);
                    133:            return 0;
                    134:          }
                    135: 
                    136:        /* Com port found, now check what chip it has */
                    137:        
                    138:        for(i = 0; i < 256; i++)         /* Is there Scratch register */
                    139:          {
                    140:            outb(SCR(addr), i);
                    141:            if (inb(SCR(addr)) != i)
                    142:              break;
                    143:          }
                    144:        if (i == 256)
                    145:          {                              /* Yes == 450 or 460 */
                    146:            outb(SCR(addr), 0);
                    147:            type = "82450 or 16450";
                    148:            outb(FIFO_CTL(addr), iFIFOENA | iFIFO14CH);  /* Enable fifo */
                    149:            if ((inb(FIFO_CTL(addr)) & iFIFO14CH) != 0)
                    150:              {                          /* Was it successfull */
                    151:                /* if both bits are not set then broken xx550 */
                    152:                if ((inb(FIFO_CTL(addr)) & iFIFO14CH) == iFIFO14CH)
                    153:                  {
                    154:                    type = "82550 or 16550";
                    155:                    comfifo[unit] = TRUE;
                    156:                  }
                    157:                else
                    158:                  {
                    159:                    type = "82550 or 16550 with non-working FIFO";
                    160:                  }
                    161:                outb(INTR_ID(addr), 0x00); /* Disable fifos */
                    162:              }
                    163:          }
                    164:        if (noisy)
                    165:                printf("com%d: %s chip.\n", unit, type);
                    166:        return 1;
                    167: }
                    168: 
                    169: /*
                    170:  * Probe routine for use during kernel startup when it is probing
                    171:  * all of bus_device_init
                    172:  */
                    173: int
                    174: comprobe(int port, struct bus_device *dev)
                    175: {
                    176:        return comprobe_general(dev, /*noisy*/ 0);
                    177: }
                    178: 
                    179: #if RCLINE >= 0
                    180: /*
                    181:  * Probe routine for use by the console
                    182:  */
                    183: int
                    184: comcnprobe(struct consdev *cp)
                    185: {
                    186:        struct  bus_device *b;
                    187:        int     maj, unit, pri;
                    188: 
                    189:        maj = 0;
                    190:        unit = -1;
                    191:        pri = CN_DEAD;
                    192: 
                    193:        for (b = bus_device_init; b->driver; b++)
                    194:                if (strcmp(b->name, "com") == 0
                    195:                    && b->unit == RCLINE
                    196:                    && comprobe_general(b, /*quiet*/ 0))
                    197:                {
                    198:                        /* Found one */
                    199:                        comcndev = b;
                    200:                        unit = b->unit;
                    201:                        pri = CN_REMOTE;
                    202:                        break;
                    203:                }
                    204: 
                    205:        cp->cn_dev = makedev(maj, unit);
                    206:        cp->cn_pri = pri;
                    207: }
                    208: #endif
                    209: 
                    210: 
                    211: /*
                    212:  *
                    213:  * Device Attach's are called during kernel boot, but only if the matching
                    214:  * device Probe returned a 1.
                    215:  *
                    216:  */
                    217: void
                    218: comattach(struct bus_device *dev)
                    219: {
                    220:        u_char  unit = dev->unit;
                    221:        u_short addr = dev->address;
                    222: 
                    223:        take_dev_irq(dev);
                    224:        printf(", port = %x, spl = %d, pic = %d. (DOS COM%d)",
                    225:               dev->address, dev->sysdep, dev->sysdep1, unit+1);
                    226: 
                    227: /*     comcarrier[unit] = addr->flags;*/
                    228:        commodem[unit] = 0;
                    229: 
                    230:        outb(INTR_ENAB(addr), 0);
                    231:        outb(MODEM_CTL(addr), 0);
                    232:        while (!(inb(INTR_ID(addr))&1)) {
                    233:                (void) inb(LINE_STAT (addr));   /* reset overrun error etc */
                    234:                (void) inb(TXRX      (addr));   /* reset data-ready */
                    235:                (void) inb(MODEM_STAT(addr));   /* reset modem status reg */
                    236:        }
                    237: }
                    238: 
                    239: #if RCLINE >= 0
                    240: /*
                    241:  * Attach/init routine for console.  This isn't called by
                    242:  * configure_bus_device which sets the alive, adaptor, and minfo
                    243:  * fields of the bus_device struct (comattach is), therefore we do
                    244:  * that by hand.
                    245:  */
                    246: int
                    247: comcninit(struct consdev *cp)
                    248: {
                    249:        u_char  unit = comcndev->unit;
                    250:        u_short addr = comcndev->address;
                    251:                      
                    252:        take_dev_irq(comcndev);
                    253: 
                    254:        comcndev->alive = 1;
                    255:        comcndev->adaptor = 0;
                    256:        cominfo[minor(cp->cn_dev)] = comcndev;
                    257: 
                    258:        outb(LINE_CTL(addr), iDLAB);
                    259:        outb(BAUD_LSB(addr), divisorreg[RCBAUD] & 0xff);
                    260:        outb(BAUD_MSB(addr), divisorreg[RCBAUD] >>8);
                    261:        outb(LINE_CTL(addr), i7BITS|iPEN);
                    262:        outb(INTR_ENAB(addr), 0);
                    263:        outb(MODEM_CTL(addr), iDTR|iRTS|iOUT2);
                    264: 
                    265:        {
                    266:                char    msg[128];
                    267:                volatile unsigned char *p = (volatile unsigned char *)0xb8000;
                    268:                int     i;
                    269: 
                    270:                sprintf(msg, "    **** using COM port %d for console ****",
                    271:                        unit+1);
                    272:                for (i = 0; msg[i]; i++) {
                    273:                        p[2*i] = msg[i];
                    274:                        p[2*i+1] = (0<<7)       /* blink */
                    275:                                   | (0x0<<4)   /* bg */
                    276:                                   | (1<<3)     /* hi-intensity */
                    277:                                   | 0x4;       /* fg */
                    278:                }
                    279:        }
                    280: 
                    281: }
                    282: #endif
                    283: 
                    284: /*
                    285:  *     Probe for COM<dev> after autoconfiguration.
                    286:  *     Used to handle PCMCIA modems, which may appear
                    287:  *     at any time.
                    288:  */
                    289: boolean_t com_reprobe(
                    290:        int     unit)
                    291: {
                    292:        struct bus_device       *device;
                    293: 
                    294:        /*
                    295:         *      Look for COM device <unit> in the device
                    296:         *      initialization list.  It must not be alive
                    297:         *      (otherwise we would have opened it already).
                    298:         */
                    299:        for (device = bus_device_init; device->driver; device++) {
                    300:            if (device->driver == &comdriver && device->unit == unit &&
                    301:                !device->alive && device->ctlr == (char)-1)
                    302:            {
                    303:                /*
                    304:                 *      Found an entry for com port <unit>.
                    305:                 *      Probe it.
                    306:                 */
                    307:                if (configure_bus_device(device->name,
                    308:                                         device->address,
                    309:                                         device->phys_address,
                    310:                                         0,
                    311:                                         "atbus"))
                    312:                    return TRUE;
                    313:            }
                    314:        }
                    315:        return FALSE;
                    316: }
                    317: 
                    318: io_return_t comopen(
                    319:        int dev,
                    320:        int flag,
                    321:        io_req_t ior)
                    322: {
                    323:        int             unit = minor(dev);
                    324:        u_short         addr;
                    325:        struct bus_device       *isai;
                    326:        struct tty      *tp;
                    327:        spl_t           s;
                    328:        io_return_t     result;
                    329: 
                    330:        if (unit >= NCOM)
                    331:            return ENXIO;       /* no such device */
                    332:        if ((isai = cominfo[unit]) == 0 || isai->alive == 0) {
                    333:            /*
                    334:             *  Try to probe it again
                    335:             */
                    336:            if (!com_reprobe(unit))
                    337:                return ENXIO;
                    338:        }
                    339:        tp = &com_tty[unit];
                    340: 
                    341:        if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0) {
                    342:                ttychars(tp);
                    343:                tp->t_addr = (char *)isai->address;
                    344:                tp->t_dev = dev;
                    345:                tp->t_oproc = comstart;
                    346:                tp->t_stop = comstop;
                    347:                tp->t_mctl = commctl;
                    348:                tp->t_getstat = comgetstat;
                    349:                tp->t_setstat = comsetstat;
                    350: #ifndef        PORTSELECTOR
                    351:                if (tp->t_ispeed == 0) {
                    352: #else
                    353:                        tp->t_state |= TS_HUPCLS;
                    354: #endif /* PORTSELECTOR */
                    355:                        tp->t_ispeed = ISPEED;
                    356:                        tp->t_ospeed = ISPEED;
                    357:                        tp->t_flags = IFLAGS;
                    358:                        tp->t_state &= ~TS_BUSY;
                    359: #ifndef        PORTSELECTOR
                    360:                }
                    361: #endif /* PORTSELECTOR */
                    362:        }
                    363: /*rvb  tp->t_state |= TS_WOPEN; */
                    364:        if ((tp->t_state & TS_ISOPEN) == 0)
                    365:                comparam(unit);
                    366:        addr = (int)tp->t_addr;
                    367: 
                    368:        s = spltty();
                    369:        if (!comcarrier[unit])  /* not originating */
                    370:                tp->t_state |= TS_CARR_ON;
                    371:        else {
                    372:                int modem_stat = inb(MODEM_STAT(addr));
                    373:                if (modem_stat & iRLSD)
                    374:                        tp->t_state |= TS_CARR_ON;
                    375:                else
                    376:                        tp->t_state &= ~TS_CARR_ON;
                    377:                fix_modem_state(unit, modem_stat);
                    378:        } 
                    379:        splx(s);
                    380: 
                    381:        result = char_open(dev, tp, flag, ior);
                    382: 
                    383:        if (!comtimer_active) {
                    384:                comtimer_active = TRUE;
                    385:                comtimer();
                    386:        }
                    387: 
                    388:        s = spltty();
                    389:        while(!(inb(INTR_ID(addr))&1)) { /* while pending interrupts */
                    390:                (void) inb(LINE_STAT (addr)); /* reset overrun error  */
                    391:                (void) inb(TXRX      (addr)); /* reset data-ready           */
                    392:                (void) inb(MODEM_STAT(addr)); /* reset modem status   */
                    393:        }
                    394:        splx(s);
                    395:        return result;
                    396: }
                    397: 
                    398: io_return_t comclose(dev, flag)
                    399: int dev;
                    400: int flag;
                    401: {
                    402:        struct tty      *tp = &com_tty[minor(dev)];
                    403:        u_short         addr = (int)tp->t_addr;
                    404: 
                    405:        ttyclose(tp);
                    406:        if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) { 
                    407:                outb(INTR_ENAB(addr), 0);
                    408:                outb(MODEM_CTL(addr), 0);
                    409:                tp->t_state &= ~TS_BUSY;
                    410:                commodem[minor(dev)] = 0;
                    411:                if (comfifo[minor(dev)] != 0)
                    412:                        outb(INTR_ID(addr), 0x00); /* Disable fifos */
                    413:        }
                    414:        return 0;
                    415: }
                    416: 
                    417: io_return_t comread(dev, ior)
                    418: int    dev;
                    419: io_req_t ior;
                    420: {
                    421:        return char_read(&com_tty[minor(dev)], ior);
                    422: }
                    423: 
                    424: io_return_t comwrite(dev, ior)
                    425: int    dev;
                    426: io_req_t ior;
                    427: {
                    428:        return char_write(&com_tty[minor(dev)], ior);
                    429: }
                    430: 
                    431: io_return_t comportdeath(dev, port)
                    432: dev_t          dev;
                    433: mach_port_t    port;
                    434: {
                    435:        return (tty_portdeath(&com_tty[minor(dev)], port));
                    436: }
                    437: 
                    438: io_return_t
                    439: comgetstat(dev, flavor, data, count)
                    440: dev_t          dev;
                    441: int            flavor;
                    442: int            *data;          /* pointer to OUT array */
                    443: unsigned int   *count;         /* out */
                    444: {
                    445:        io_return_t     result = D_SUCCESS;
                    446:        int             unit = minor(dev);
                    447: 
                    448:        switch (flavor) {
                    449:        case TTY_MODEM:
                    450:                fix_modem_state(unit, inb(MODEM_STAT(cominfo[unit]->address)));
                    451:                *data = commodem[unit];
                    452:                *count = 1;
                    453:                break;
                    454:        default:
                    455:                result = tty_get_status(&com_tty[unit], flavor, data, count);
                    456:                break;
                    457:        }
                    458:        return (result);
                    459: }
                    460: 
                    461: io_return_t
                    462: comsetstat(dev, flavor, data, count)
                    463: dev_t          dev;
                    464: int            flavor;
                    465: int *          data;
                    466: unsigned int   count;
                    467: {
                    468:        io_return_t     result = D_SUCCESS;
                    469:        int             unit = minor(dev);
                    470:        struct tty      *tp = &com_tty[unit];
                    471: 
                    472:        switch (flavor) {
                    473:        case TTY_SET_BREAK:
                    474:                commctl(tp, TM_BRK, DMBIS);
                    475:                break;
                    476:        case TTY_CLEAR_BREAK:
                    477:                commctl(tp, TM_BRK, DMBIC);
                    478:                break;
                    479:        case TTY_MODEM:
                    480:                commctl(tp, *data, DMSET);
                    481:                break;
                    482:        default:
                    483:                result = tty_set_status(&com_tty[unit], flavor, data, count);
                    484:                if (result == D_SUCCESS && flavor == TTY_STATUS)
                    485:                        comparam(unit);
                    486:                return (result);
                    487:        }
                    488:        return (D_SUCCESS);
                    489: }
                    490: 
                    491: comintr(unit)
                    492: int unit;
                    493: {
                    494:        register struct tty     *tp = &com_tty[unit];
                    495:        u_short                 addr = cominfo[unit]->address;
                    496:        static char             comoverrun = 0;
                    497:        char                    c, line, intr_id;
                    498:        int                     line_stat;
                    499: 
                    500:        while (! ((intr_id=(inb(INTR_ID(addr))&MASKi)) & 1))
                    501:            switch (intr_id) { 
                    502:                case MODi: 
                    503:                    /* modem change */
                    504:                        commodem_intr(unit, inb(MODEM_STAT(addr)));
                    505:                        break;
                    506: 
                    507:                case TRAi:
                    508:                        comtimer_state[unit] = 0;
                    509:                        tp->t_state &= ~(TS_BUSY|TS_FLUSH);
                    510:                        tt_write_wakeup(tp);
                    511:                        (void) comstart(tp);
                    512:                        break;
                    513:                case RECi:
                    514:                case CTIi:         /* Character timeout indication */
                    515:                        if (tp->t_state&TS_ISOPEN) {
                    516:                                while ((line = inb(LINE_STAT(addr))) & iDR) {
                    517:                                        c = inb(TXRX(addr));
                    518:                                        ttyinput(c, tp);
                    519:                                }
                    520:                        } else
                    521:                                tt_open_wakeup(tp);
                    522:                        break;
                    523:                case LINi: 
                    524:                        line_stat = inb(LINE_STAT(addr));
                    525: 
                    526:                        if ((line_stat & iPE) &&
                    527:                            ((tp->t_flags&(EVENP|ODDP)) == EVENP ||
                    528:                             (tp->t_flags&(EVENP|ODDP)) == ODDP)) {
                    529:                                /* parity error */;
                    530:                        } else  if (line&iOR && !comoverrun) {
                    531:                                printf("com%d: overrun\n", unit);
                    532:                                comoverrun = 1;
                    533:                        } else if (line_stat & (iFE | iBRKINTR)) {
                    534:                                /* framing error or break */
                    535:                                ttyinput(tp->t_breakc, tp);
                    536:                        }
                    537:                        break;
                    538:                }
                    539: }
                    540: 
                    541: static void
                    542: comparam(unit)
                    543: register int unit;
                    544: {
                    545:        struct tty      *tp = &com_tty[unit];
                    546:        u_short         addr = (int)tp->t_addr;
                    547:        spl_t           s = spltty();
                    548:        int             mode;
                    549: 
                    550:         if (tp->t_ispeed == B0) {
                    551:                tp->t_state |= TS_HUPCLS;
                    552:                outb(MODEM_CTL(addr), iOUT2);
                    553:                commodem[unit] = 0;
                    554:                splx(s);
                    555:                return;
                    556:        }
                    557: 
                    558:        /* Do input buffering */
                    559:        if (tp->t_ispeed >= B300)
                    560:                tp->t_state |= TS_MIN;
                    561: 
                    562:        outb(LINE_CTL(addr), iDLAB);
                    563:        outb(BAUD_LSB(addr), divisorreg[tp->t_ispeed] & 0xff);
                    564:        outb(BAUD_MSB(addr), divisorreg[tp->t_ispeed] >> 8);
                    565: 
                    566:        if (tp->t_flags & (RAW|LITOUT|PASS8))
                    567:                mode = i8BITS;
                    568:        else
                    569:                mode = i7BITS | iPEN;
                    570:        if (tp->t_flags & EVENP)
                    571:                mode |= iEPS;
                    572:        if (tp->t_ispeed == B110)
                    573:                /*
                    574:                 * 110 baud uses two stop bits -
                    575:                 * all other speeds use one
                    576:                 */
                    577:                mode |= iSTB;
                    578: 
                    579:        outb(LINE_CTL(addr), mode);
                    580: 
                    581:        outb(INTR_ENAB(addr), iTX_ENAB|iRX_ENAB|iMODEM_ENAB|iERROR_ENAB);
                    582:        if (comfifo[unit])
                    583:                outb(FIFO_CTL(addr), iFIFOENA|iFIFO14CH);
                    584:        outb(MODEM_CTL(addr), iDTR|iRTS|iOUT2);
                    585:        commodem[unit] |= (TM_DTR|TM_RTS);
                    586:         splx(s);
                    587: }
                    588: 
                    589: comparm(int unit, int baud, int intr, int mode, int modem)
                    590: {
                    591:        u_short addr = (u_short)(cominfo[unit]->address);
                    592:        spl_t   s = spltty();
                    593: 
                    594:        if (unit != 0 && unit != 1) {
                    595:                printf("comparm(unit, baud, mode, intr, modem)\n");
                    596:                splx(s);
                    597:                return;
                    598:        }
                    599:        outb(LINE_CTL(addr), iDLAB);
                    600:        outb(BAUD_LSB(addr), divisorreg[baud] & 0xff);
                    601:        outb(BAUD_MSB(addr), divisorreg[baud] >> 8);
                    602:        outb(LINE_CTL(addr), mode);
                    603:        outb(INTR_ENAB(addr), intr);
                    604:        outb(MODEM_CTL(addr), modem);
                    605:        splx(s);
                    606: }
                    607: 
                    608: int comst_1, comst_2, comst_3, comst_4, comst_5 = 14;
                    609: 
                    610: int
                    611: comstart(tp)
                    612: struct tty *tp;
                    613: {
                    614:        char nch;
                    615:        int i;
                    616: 
                    617:        if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) {
                    618: comst_1++;
                    619:                return(0);
                    620:        }
                    621:        if ((!queue_empty(&tp->t_delayed_write)) &&
                    622:            (tp->t_outq.c_cc <= TTLOWAT(tp))) {
                    623: comst_2++;
                    624:                tt_write_wakeup(tp);
                    625:        }
                    626:        if (!tp->t_outq.c_cc) {
                    627: comst_3++;
                    628:                return(0);
                    629:        }
                    630: 
                    631: #if 0
                    632:        i = (comfifo[minor(tp->t_dev)]) ? /*14*/comst_5 : 1;
                    633: 
                    634:        tp->t_state |= TS_BUSY;
                    635:        while (i-- > 0) {
                    636:                nch = getc(&tp->t_outq);
                    637:                if (nch == -1) break;
                    638:                if ((nch & 0200) && ((tp->t_flags & LITOUT) == 0)) {
                    639:                    timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
                    640:                    tp->t_state |= TS_TIMEOUT;
                    641: comst_4++;
                    642:                    return(0);
                    643:                }
                    644:                outb(TXRX((int)tp->t_addr), nch);
                    645:        }
                    646: #else
                    647:        nch = getc(&tp->t_outq);
                    648:        if ((nch & 0200) && ((tp->t_flags & LITOUT) == 0)) {
                    649:            timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
                    650:            tp->t_state |= TS_TIMEOUT;
                    651: comst_4++;
                    652:            return(0);
                    653:        }
                    654:        outb(TXRX((int)tp->t_addr), nch);
                    655:        tp->t_state |= TS_BUSY;
                    656: #endif
                    657:        return(0);
                    658: }
                    659: 
                    660: /* Check for stuck xmitters */
                    661: int comtimer_interval = 5;
                    662: 
                    663: comtimer()
                    664: {
                    665:        spl_t   s = spltty();
                    666:        struct tty *tp = com_tty;
                    667:        int i, nch;
                    668: 
                    669:        for (i = 0; i < NCOM; i++, tp++) {
                    670:                if ((tp->t_state & TS_ISOPEN) == 0)
                    671:                        continue;
                    672:                if (!tp->t_outq.c_cc)
                    673:                        continue;
                    674:                if (++comtimer_state[i] < 2)
                    675:                        continue;
                    676:                /* Its stuck */
                    677: printf("Tty %x was stuck\n", tp);
                    678:                nch = getc(&tp->t_outq);
                    679:                outb(TXRX((int)tp->t_addr), nch);
                    680:        }
                    681: 
                    682:        splx(s);
                    683:        timeout(comtimer, 0, comtimer_interval*hz);
                    684: }
                    685: 
                    686: /*
                    687:  * Set receive modem state from modem status register.
                    688:  */
                    689: fix_modem_state(unit, modem_stat)
                    690: int    unit, modem_stat;
                    691: {
                    692:        int     stat = 0;
                    693: 
                    694:        if (modem_stat & iCTS)
                    695:            stat |= TM_CTS;     /* clear to send */
                    696:        if (modem_stat & iDSR)
                    697:            stat |= TM_DSR;     /* data set ready */
                    698:        if (modem_stat & iRI)
                    699:            stat |= TM_RNG;     /* ring indicator */
                    700:        if (modem_stat & iRLSD)
                    701:            stat |= TM_CAR;     /* carrier? */
                    702: 
                    703:        commodem[unit] = (commodem[unit] & ~(TM_CTS|TM_DSR|TM_RNG|TM_CAR))
                    704:                                | stat;
                    705: }
                    706: 
                    707: /*
                    708:  * Modem change (input signals)
                    709:  */
                    710: commodem_intr(
                    711:        int     unit,
                    712:        int     stat)
                    713: {
                    714:        int     changed;
                    715: 
                    716:        changed = commodem[unit];
                    717:        fix_modem_state(unit, stat);
                    718:        stat = commodem[unit];
                    719: 
                    720:        /* Assumption: if the other party can handle
                    721:           modem signals then it should handle all
                    722:           the necessary ones. Else fix the cable. */
                    723: 
                    724:        changed ^= stat;        /* what changed ? */
                    725: 
                    726:        if (changed & TM_CTS)
                    727:                tty_cts( &com_tty[unit], stat & TM_CTS );
                    728: 
                    729: #if 0
                    730:        if (changed & TM_CAR)
                    731:                ttymodem( &com_tty[unit], stat & TM_CAR );
                    732: #endif
                    733: 
                    734: }
                    735: 
                    736: /*
                    737:  * Set/get modem bits
                    738:  */
                    739: commctl(
                    740:        register struct tty     *tp,
                    741:        int     bits,
                    742:        int     how)
                    743: {
                    744:        spl_t           s;
                    745:        int             unit;
                    746:        vm_offset_t     dev_addr;
                    747:        register int    b;
                    748: 
                    749:        unit = minor(tp->t_dev);
                    750: 
                    751:        if (bits == TM_HUP) { /* close line (internal) */
                    752:                bits = TM_DTR | TM_RTS;
                    753:                how = DMBIC;
                    754:        }
                    755: 
                    756:        if (how == DMGET) return commodem[unit];
                    757: 
                    758:        dev_addr = cominfo[unit]->address;
                    759: 
                    760:        s = spltty();
                    761: 
                    762:        switch (how) {
                    763:        case DMSET:
                    764:                b = bits; break;
                    765:        case DMBIS:
                    766:                b = commodem[unit] | bits; break;
                    767:        case DMBIC:
                    768:                b = commodem[unit] & ~bits; break;
                    769:        }
                    770:        commodem[unit] = b;
                    771: 
                    772:        if (bits & TM_BRK) {
                    773:                if (b & TM_BRK) {
                    774:                        outb(LINE_CTL(dev_addr), inb(LINE_CTL(dev_addr)) | iSETBREAK);
                    775:                } else {
                    776:                        outb(LINE_CTL(dev_addr), inb(LINE_CTL(dev_addr)) & ~iSETBREAK);
                    777:                }
                    778:        }
                    779: 
                    780: #if 0
                    781:        /* do I need to do something on this ? */
                    782:        if (bits & TM_LE) {     /* line enable */
                    783:        }
                    784: #endif
                    785: #if 0
                    786:        /* Unsupported */
                    787:        if (bits & TM_ST) {     /* secondary transmit */
                    788:        }
                    789:        if (bits & TM_SR) {     /* secondary receive */
                    790:        }
                    791: #endif
                    792:        if (bits & (TM_DTR|TM_RTS)) {   /* data terminal ready, request to send */
                    793:                how = iOUT2;
                    794:                if (b & TM_DTR) how |= iDTR;
                    795:                if (b & TM_RTS) how |= iRTS;
                    796:                outb(MODEM_CTL(dev_addr), how);
                    797:        }
                    798: 
                    799:        splx(s);
                    800: 
                    801:        /* the rest are inputs */
                    802:        return commodem[unit];
                    803: }
                    804: 
                    805: comstop(tp, flags)
                    806: register struct tty *tp;
                    807: int    flags;
                    808: {
                    809:        if ((tp->t_state & TS_BUSY) && (tp->t_state & TS_TTSTOP) == 0)
                    810:            tp->t_state |= TS_FLUSH;
                    811: }
                    812: 
                    813: /*
                    814:  *
                    815:  * Code to be called from debugger.
                    816:  *
                    817:  */
                    818: void compr_addr(addr)
                    819: {
                    820:        /* The two line_stat prints may show different values, since
                    821:        *  touching some of the registers constitutes changing them.
                    822:        */
                    823:        printf("LINE_STAT(%x) %x\n",
                    824:                LINE_STAT(addr), inb(LINE_STAT(addr)));
                    825: 
                    826:        printf("TXRX(%x) %x, INTR_ENAB(%x) %x, INTR_ID(%x) %x, LINE_CTL(%x) %x,\n\
                    827: MODEM_CTL(%x) %x, LINE_STAT(%x) %x, MODEM_STAT(%x) %x\n",
                    828:        TXRX(addr),      inb(TXRX(addr)),
                    829:        INTR_ENAB(addr), inb(INTR_ENAB(addr)),
                    830:        INTR_ID(addr),   inb(INTR_ID(addr)),
                    831:        LINE_CTL(addr),  inb(LINE_CTL(addr)),
                    832:        MODEM_CTL(addr), inb(MODEM_CTL(addr)),
                    833:        LINE_STAT(addr), inb(LINE_STAT(addr)),
                    834:        MODEM_STAT(addr),inb(MODEM_STAT(addr)));
                    835: }
                    836: 
                    837: int compr(unit)
                    838: {
                    839:        compr_addr(cominfo[unit]->address);
                    840:        return(0);
                    841: }
                    842: 
                    843: int
                    844: comgetc(int unit)
                    845: {
                    846:        u_short addr = (u_short)(cominfo[unit]->address);
                    847:        spl_t   s = spltty();
                    848:        int     c;
                    849: 
                    850:        while((inb(LINE_STAT(addr)) & iDR) == 0) ;
                    851: 
                    852:        c = inb(TXRX(addr));
                    853:        splx(s);
                    854:        return c;
                    855: }
                    856: 
                    857: #if RCLINE >= 0
                    858: /*
                    859:  * Routines for the console
                    860:  */
                    861: int
                    862: comcnputc(dev_t dev, int c)
                    863: {
                    864:        u_short addr = (u_short)(cominfo[minor(dev)]->address);
                    865: 
                    866:        /* Wait for transmitter to empty */
                    867:        while((inb(LINE_STAT(addr)) & iTHRE) == 0)
                    868:                continue;
                    869: 
                    870:        /* send the char */
                    871:        if (c == '\n')
                    872:                comcnputc(dev, '\r');
                    873:        outb(addr, c);
                    874: }
                    875: 
                    876: int
                    877: comcngetc(dev_t dev, int wait)
                    878: {
                    879:        u_short addr = (u_short)(cominfo[minor(dev)]->address);
                    880:        int     c;
                    881: 
                    882:        while((inb(LINE_STAT(addr)) & iDR) == 0)
                    883:                if (! wait)
                    884:                        return 0;
                    885: 
                    886:        c = inb(TXRX(addr));
                    887:        return c & 0x7f;
                    888: }
                    889: #endif /* RCLINE */
                    890: 
                    891: #endif /* NCOM */

unix.superglobalmegacorp.com

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