Annotation of Gnu-Mach/i386/i386at/com.c, revision 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.