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

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

unix.superglobalmegacorp.com

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