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

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

unix.superglobalmegacorp.com

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