[BACK]Return to apci.c CVS log [TXT][DIR] Up to [local] / sys / arch / hp300 / dev

Annotation of sys/arch/hp300/dev/apci.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: apci.c,v 1.29 2007/01/06 20:09:12 miod Exp $  */
                      2: /*     $NetBSD: apci.c,v 1.9 2000/11/02 00:35:05 eeh Exp $     */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1996, 1997, 1999 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Jason R. Thorpe.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  * Copyright (c) 1997 Michael Smith.  All rights reserved.
                     42:  * Copyright (c) 1982, 1986, 1990, 1993
                     43:  *     The Regents of the University of California.  All rights reserved.
                     44:  *
                     45:  * Redistribution and use in source and binary forms, with or without
                     46:  * modification, are permitted provided that the following conditions
                     47:  * are met:
                     48:  * 1. Redistributions of source code must retain the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer.
                     50:  * 2. Redistributions in binary form must reproduce the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer in the
                     52:  *    documentation and/or other materials provided with the distribution.
                     53:  * 3. Neither the name of the University nor the names of its contributors
                     54:  *    may be used to endorse or promote products derived from this software
                     55:  *    without specific prior written permission.
                     56:  *
                     57:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     58:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     59:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     60:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     61:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     62:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     63:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     64:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     65:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     66:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     67:  * SUCH DAMAGE.
                     68:  *
                     69:  *      @(#)dca.c       8.2 (Berkeley) 1/12/94
                     70:  */
                     71:
                     72: /*
                     73:  * Device driver for the APCI 8250-like UARTs found on the Apollo
                     74:  * Utility Chip on HP 9000/400-series workstations.
                     75:  *
                     76:  * There are 4 APCI UARTs on the Frodo ASIC.  The first one
                     77:  * is used to communicate with the Domain keyboard.  The second
                     78:  * one is the serial console port when the firmware is in Domain/OS
                     79:  * mode, and is mapped to select code 9 by the HP-UX firmware (except
                     80:  * on 425e models).
                     81:  *
                     82:  * We don't bother attaching a tty to the first UART; it lacks modem/flow
                     83:  * control, and is directly connected to the keyboard connector anyhow.
                     84:  */
                     85:
                     86: /*
                     87:  * XXX This driver is very similar to the dca driver, and much
                     88:  * XXX more code could be shared.  (Currently, no code is shared.)
                     89:  * XXX FIXME!
                     90:  */
                     91:
                     92: #include <sys/param.h>
                     93: #include <sys/systm.h>
                     94: #include <sys/ioctl.h>
                     95: #include <sys/proc.h>
                     96: #include <sys/tty.h>
                     97: #include <sys/conf.h>
                     98: #include <sys/file.h>
                     99: #include <sys/uio.h>
                    100: #include <sys/kernel.h>
                    101: #include <sys/syslog.h>
                    102: #include <sys/device.h>
                    103: #include <sys/timeout.h>
                    104:
                    105: #include <machine/autoconf.h>
                    106: #include <machine/bus.h>
                    107: #include <machine/cpu.h>
                    108: #include <machine/hp300spu.h>
                    109:
                    110: #include <dev/cons.h>
                    111:
                    112: #include <hp300/dev/dioreg.h>          /* to check for dca at 9 */
                    113: #include <hp300/dev/diovar.h>
                    114: #include <hp300/dev/diodevs.h>
                    115:
                    116: #include <hp300/dev/frodoreg.h>
                    117: #include <hp300/dev/frodovar.h>
                    118: #include <hp300/dev/apcireg.h>
                    119: #include <hp300/dev/apcivar.h>
                    120: #include <hp300/dev/dcareg.h>          /* register bit definitions */
                    121:
                    122: #ifdef DDB
                    123: #include <ddb/db_var.h>
                    124: #endif
                    125:
                    126: struct apci_softc {
                    127:        struct  device sc_dev;          /* generic device glue */
                    128:        struct  isr sc_isr;
                    129:        struct  apciregs *sc_apci;      /* device registers */
                    130:        struct  tty *sc_tty;            /* tty glue */
                    131:        struct  timeout sc_timeout;     /* timeout */
                    132:        int     sc_ferr,
                    133:                sc_perr,
                    134:                sc_oflow,
                    135:                sc_toterr;              /* stats */
                    136:        int     sc_flags;
                    137:        u_char  sc_cua;                 /* callout mode */
                    138: };
                    139:
                    140: /* sc_flags */
                    141: #define        APCI_HASFIFO    0x01            /* unit has a fifo */
                    142: #define        APCI_ISCONSOLE  0x02            /* unit is console */
                    143: #define        APCI_SOFTCAR    0x04            /* soft carrier */
                    144:
                    145: int    apcimatch(struct device *, void *, void *);
                    146: void   apciattach(struct device *, struct device *, void *);
                    147:
                    148: struct cfattach apci_ca = {
                    149:        sizeof(struct apci_softc), apcimatch, apciattach
                    150: };
                    151:
                    152: struct cfdriver apci_cd = {
                    153:        NULL, "apci", DV_TTY
                    154: };
                    155:
                    156: int    apciintr(void *);
                    157: void   apcieint(struct apci_softc *, int);
                    158: void   apcimint(struct apci_softc *, u_char);
                    159: int    apciparam(struct tty *, struct termios *);
                    160: void   apcistart(struct tty *);
                    161: int    apcimctl(struct apci_softc *, int, int);
                    162: void   apcitimeout(void *);
                    163:
                    164: cdev_decl(apci);
                    165:
                    166: #define        APCIUNIT(x)     (minor(x) & 0x7f)
                    167: #define APCICUA(x)     (minor(x) & 0x80)
                    168:
                    169: int    apcidefaultrate = TTYDEF_SPEED;
                    170:
                    171: /*
                    172:  * Console support.
                    173:  */
                    174: struct apciregs *apci_cn = NULL;       /* console hardware */
                    175: int    apciconsinit;                   /* has been initialized */
                    176: int    apcimajor;                      /* our major number */
                    177:
                    178: cons_decl(apci);
                    179:
                    180: int
                    181: apcimatch(parent, match, aux)
                    182:        struct device *parent;
                    183:        void *match, *aux;
                    184: {
                    185:        struct frodo_attach_args *fa = aux;
                    186:
                    187:        /* Looking for an apci? */
                    188:        if (strcmp(fa->fa_name, apci_cd.cd_name) != 0)
                    189:                return (0);
                    190:
                    191:        /* Are we checking a valid APCI offset? */
                    192:        switch (fa->fa_offset) {
                    193:        case FRODO_APCI_OFFSET(1):
                    194:        case FRODO_APCI_OFFSET(2):
                    195:        case FRODO_APCI_OFFSET(3):
                    196:                /* Yup, we exist! */
                    197:                return (1);
                    198:        }
                    199:
                    200:        return (0);
                    201: }
                    202:
                    203: void
                    204: apciattach(parent, self, aux)
                    205:        struct device *parent, *self;
                    206:        void *aux;
                    207: {
                    208:        struct apci_softc *sc = (struct apci_softc *)self;
                    209:        struct apciregs *apci;
                    210:        struct frodo_attach_args *fa = aux;
                    211:
                    212:        sc->sc_apci = apci =
                    213:            (struct apciregs *)IIOV(FRODO_BASE + fa->fa_offset);
                    214:        sc->sc_flags = 0;
                    215:
                    216:        /* Initialize timeout structure */
                    217:        timeout_set(&sc->sc_timeout, apcitimeout, sc);
                    218:
                    219:        /* Are we the console? */
                    220:        if (apci == apci_cn) {
                    221:                sc->sc_flags |= APCI_ISCONSOLE;
                    222:                delay(100000);
                    223:
                    224:                /*
                    225:                 * We didn't know which unit this would be during
                    226:                 * the console probe, so we have to fixup cn_dev here.
                    227:                 */
                    228:                cn_tab->cn_dev = makedev(apcimajor, self->dv_unit);
                    229:        }
                    230:
                    231:        /* Look for a FIFO. */
                    232:        apci->ap_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14;
                    233:        delay(100);
                    234:        if ((apci->ap_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK)
                    235:                sc->sc_flags |= APCI_HASFIFO;
                    236:
                    237:        /* Establish our interrupt handler. */
                    238:        sc->sc_isr.isr_func = apciintr;
                    239:        sc->sc_isr.isr_arg = sc;
                    240:        sc->sc_isr.isr_priority =
                    241:            (sc->sc_flags & APCI_HASFIFO) ? IPL_TTY : IPL_TTYNOBUF;
                    242:        frodo_intr_establish(parent, fa->fa_line, &sc->sc_isr, self->dv_xname);
                    243:
                    244:        /* Set soft carrier if requested by operator. */
                    245:        if (self->dv_cfdata->cf_flags)
                    246:                sc->sc_flags |= APCI_SOFTCAR;
                    247:
                    248:        /*
                    249:         * Need to reset baud rate, etc. of next print, so reset apciconsinit.
                    250:         * Also make sure console is always "hardwired".
                    251:         */
                    252:        if (sc->sc_flags & APCI_ISCONSOLE) {
                    253:                apciconsinit = 0;
                    254:                sc->sc_flags |= APCI_SOFTCAR;
                    255:                printf(": console, ");
                    256:        } else
                    257:                printf(": ");
                    258:
                    259:        if (sc->sc_flags & APCI_HASFIFO)
                    260:                printf("working fifo\n");
                    261:        else
                    262:                printf("no fifo\n");
                    263: }
                    264:
                    265: /* ARGSUSED */
                    266: int
                    267: apciopen(dev, flag, mode, p)
                    268:        dev_t dev;
                    269:        int flag, mode;
                    270:        struct proc *p;
                    271: {
                    272:        int unit = APCIUNIT(dev);
                    273:        struct apci_softc *sc;
                    274:        struct tty *tp;
                    275:        struct apciregs *apci;
                    276:        u_char code;
                    277:        int s, error = 0;
                    278:
                    279:        if (unit >= apci_cd.cd_ndevs ||
                    280:            (sc = apci_cd.cd_devs[unit]) == NULL)
                    281:                return (ENXIO);
                    282:
                    283:        apci = sc->sc_apci;
                    284:
                    285:        s = spltty();
                    286:        if (sc->sc_tty == NULL) {
                    287:                tp = sc->sc_tty = ttymalloc();
                    288:        } else
                    289:                tp = sc->sc_tty;
                    290:        splx(s);
                    291:
                    292:        tp->t_oproc = apcistart;
                    293:        tp->t_param = apciparam;
                    294:        tp->t_dev = dev;
                    295:
                    296:        if ((tp->t_state & TS_ISOPEN) == 0) {
                    297:                /*
                    298:                 * Sanity clause: reset the chip on first open.
                    299:                 * The chip might be left in an inconsistent state
                    300:                 * if it is read inadventently.
                    301:                 */
                    302:                apciinit(apci, apcidefaultrate, CFCR_8BITS);
                    303:
                    304:                tp->t_state |= TS_WOPEN;
                    305:                ttychars(tp);
                    306:                tp->t_iflag = TTYDEF_IFLAG;
                    307:                tp->t_oflag = TTYDEF_OFLAG;
                    308:                tp->t_cflag = TTYDEF_CFLAG;
                    309:                tp->t_lflag = TTYDEF_LFLAG;
                    310:                tp->t_ispeed = tp->t_ospeed = apcidefaultrate;
                    311:
                    312:                s = spltty();
                    313:
                    314:                apciparam(tp, &tp->t_termios);
                    315:                ttsetwater(tp);
                    316:
                    317:                /* Set the FIFO threshold based on the receive speed. */
                    318:                if (sc->sc_flags & APCI_HASFIFO)
                    319:                        apci->ap_fifo = FIFO_ENABLE | FIFO_RCV_RST |
                    320:                            FIFO_XMT_RST |
                    321:                            (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 :
                    322:                            FIFO_TRIGGER_14);
                    323:
                    324:                /* Flush any pending I/O. */
                    325:                while ((apci->ap_iir & IIR_IMASK) == IIR_RXRDY)
                    326:                        code = apci->ap_data;
                    327:        } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
                    328:                return (EBUSY);
                    329:        else
                    330:                s = spltty();
                    331:
                    332:        /* Set the modem control state. */
                    333:        (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMSET);
                    334:
                    335:        /* Set soft-carrier if so configured. */
                    336:        if ((sc->sc_flags & APCI_SOFTCAR) || APCICUA(dev) ||
                    337:            (apcimctl(sc, 0, DMGET) & MSR_DCD))
                    338:                tp->t_state |= TS_CARR_ON;
                    339:
                    340:        if (APCICUA(dev)) {
                    341:                if (tp->t_state & TS_ISOPEN) {
                    342:                        /* Ah, but someone already is dialed in... */
                    343:                        splx(s);
                    344:                        return (EBUSY);
                    345:                }
                    346:                sc->sc_cua = 1;         /* We go into CUA mode */
                    347:        }
                    348:
                    349:        /* Wait for carrier if necessary. */
                    350:        if (flag & O_NONBLOCK) {
                    351:                if (!APCICUA(dev) && sc->sc_cua) {
                    352:                        /* Opening TTY non-blocking... but the CUA is busy */
                    353:                        splx(s);
                    354:                        return (EBUSY);
                    355:                }
                    356:        } else {
                    357:                while (sc->sc_cua ||
                    358:                    ((tp->t_cflag & CLOCAL) == 0 &&
                    359:                    (tp->t_state & TS_CARR_ON) == 0)) {
                    360:                        tp->t_state |= TS_WOPEN;
                    361:                        error = ttysleep(tp, (caddr_t)&tp->t_rawq,
                    362:                            TTIPRI | PCATCH, ttopen, 0);
                    363:                        if (!APCICUA(dev) && sc->sc_cua && error == EINTR)
                    364:                                continue;
                    365:                        if (error) {
                    366:                                if (APCICUA(dev))
                    367:                                        sc->sc_cua = 0;
                    368:                                splx(s);
                    369:                                return (error);
                    370:                        }
                    371:                        if (!APCICUA(dev) && sc->sc_cua)
                    372:                                continue;
                    373:                }
                    374:        }
                    375:
                    376:        splx(s);
                    377:
                    378:        if (error == 0)
                    379:                error = (*linesw[tp->t_line].l_open)(dev, tp);
                    380:
                    381:        if (error == 0) {
                    382:                /* clear errors, start timeout */
                    383:                sc->sc_ferr = sc->sc_perr = sc->sc_oflow = sc->sc_toterr = 0;
                    384:                timeout_add(&sc->sc_timeout, hz);
                    385:        }
                    386:
                    387:        return (error);
                    388: }
                    389:
                    390: /* ARGSUSED */
                    391: int
                    392: apciclose(dev, flag, mode, p)
                    393:        dev_t dev;
                    394:        int flag, mode;
                    395:        struct proc *p;
                    396: {
                    397:        struct apci_softc *sc;
                    398:        struct tty *tp;
                    399:        struct apciregs *apci;
                    400:        int unit = APCIUNIT(dev);
                    401:        int s;
                    402:
                    403:        sc = apci_cd.cd_devs[unit];
                    404:        apci = sc->sc_apci;
                    405:        tp = sc->sc_tty;
                    406:
                    407:        (*linesw[tp->t_line].l_close)(tp, flag);
                    408:
                    409:        s = spltty();
                    410:
                    411:        apci->ap_cfcr &= ~CFCR_SBREAK;
                    412:        apci->ap_ier = 0;
                    413:        if (tp->t_cflag & HUPCL && (sc->sc_flags & APCI_SOFTCAR) == 0) {
                    414:                /* XXX perhaps only clear DTR */
                    415:                (void) apcimctl(sc, 0, DMSET);
                    416:        }
                    417:        tp->t_state &= ~(TS_BUSY | TS_FLUSH);
                    418:        sc->sc_cua = 0;
                    419:        splx(s);
                    420:        ttyclose(tp);
                    421: #if 0
                    422:        ttyfree(tp);
                    423:        sc->sc_tty = NULL;
                    424: #endif
                    425:        return (0);
                    426: }
                    427:
                    428: int
                    429: apciread(dev, uio, flag)
                    430:        dev_t dev;
                    431:        struct uio *uio;
                    432:        int flag;
                    433: {
                    434:        struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)];
                    435:        struct tty *tp = sc->sc_tty;
                    436:
                    437:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
                    438: }
                    439:
                    440: int
                    441: apciwrite(dev, uio, flag)
                    442:        dev_t dev;
                    443:        struct uio *uio;
                    444:        int flag;
                    445: {
                    446:        struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)];
                    447:        struct tty *tp = sc->sc_tty;
                    448:
                    449:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
                    450: }
                    451:
                    452: struct tty *
                    453: apcitty(dev)
                    454:        dev_t dev;
                    455: {
                    456:        struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)];
                    457:
                    458:        return (sc->sc_tty);
                    459: }
                    460:
                    461: int
                    462: apciintr(arg)
                    463:        void *arg;
                    464: {
                    465:        struct apci_softc *sc = arg;
                    466:        struct apciregs *apci = sc->sc_apci;
                    467:        struct tty *tp = sc->sc_tty;
                    468:        u_char iir, lsr, c;
                    469:        int iflowdone = 0, claimed = 0;
                    470:
                    471: #define        RCVBYTE() \
                    472:        c = apci->ap_data; \
                    473:        if (tp != NULL && (tp->t_state & TS_ISOPEN) != 0) \
                    474:                (*linesw[tp->t_line].l_rint)(c, tp)
                    475:
                    476:        for (;;) {
                    477:                iir = apci->ap_iir;     /* get UART status */
                    478:
                    479:                switch (iir & IIR_IMASK) {
                    480:                case IIR_RLS:
                    481:                        apcieint(sc, apci->ap_lsr);
                    482:                        break;
                    483:
                    484:                case IIR_RXRDY:
                    485:                case IIR_RXTOUT:
                    486:                        RCVBYTE();
                    487:                        if (sc->sc_flags & APCI_HASFIFO) {
                    488:                                while ((lsr = apci->ap_lsr) & LSR_RCV_MASK) {
                    489:                                        if (lsr == LSR_RXRDY) {
                    490:                                                RCVBYTE();
                    491:                                        } else
                    492:                                                apcieint(sc, lsr);
                    493:                                }
                    494:                        }
                    495:                        if (iflowdone == 0 && tp != NULL &&
                    496:                            (tp->t_cflag & CRTS_IFLOW) &&
                    497:                            tp->t_rawq.c_cc > (TTYHOG / 2)) {
                    498:                                apci->ap_mcr &= ~MCR_RTS;
                    499:                                iflowdone = 1;
                    500:                        }
                    501:                        break;
                    502:
                    503:                case IIR_TXRDY:
                    504:                        if (tp != NULL) {
                    505:                                tp->t_state &=~ (TS_BUSY|TS_FLUSH);
                    506:                                if (tp->t_line)
                    507:                                        (*linesw[tp->t_line].l_start)(tp);
                    508:                                else
                    509:                                        apcistart(tp);
                    510:                        }
                    511:                        break;
                    512:
                    513:                default:
                    514:                        if (iir & IIR_NOPEND)
                    515:                                return (claimed);
                    516:                        log(LOG_WARNING, "%s: weird interrupt: 0x%x\n",
                    517:                            sc->sc_dev.dv_xname, iir);
                    518:                        /* FALLTHROUGH */
                    519:
                    520:                case IIR_MLSC:
                    521:                        apcimint(sc, apci->ap_msr);
                    522:                        break;
                    523:                }
                    524:
                    525:                claimed = 1;
                    526:        }
                    527: }
                    528:
                    529: void
                    530: apcieint(sc, stat)
                    531:        struct apci_softc *sc;
                    532:        int stat;
                    533: {
                    534:        struct tty *tp = sc->sc_tty;
                    535:        struct apciregs *apci = sc->sc_apci;
                    536:        int c;
                    537:
                    538:        c = apci->ap_data;
                    539:
                    540: #ifdef DDB
                    541:        if ((sc->sc_flags & APCI_ISCONSOLE) && db_console && (stat & LSR_BI)) {
                    542:                Debugger();
                    543:                return;
                    544:        }
                    545: #endif
                    546:
                    547:        if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
                    548:                return;
                    549:
                    550:        if (stat & (LSR_BI | LSR_FE)) {
                    551:                c |= TTY_FE;
                    552:                sc->sc_ferr++;
                    553:        } else if (stat & LSR_PE) {
                    554:                c |= TTY_PE;
                    555:                sc->sc_perr++;
                    556:        } else if (stat & LSR_OE)
                    557:                sc->sc_oflow++;
                    558:        (*linesw[tp->t_line].l_rint)(c, tp);
                    559: }
                    560:
                    561: void
                    562: apcimint(sc, stat)
                    563:        struct apci_softc *sc;
                    564:        u_char stat;
                    565: {
                    566:        struct tty *tp = sc->sc_tty;
                    567:        struct apciregs *apci = sc->sc_apci;
                    568:
                    569:        if (tp == NULL)
                    570:                return;
                    571:
                    572:        if ((stat & MSR_DDCD) &&
                    573:            (sc->sc_flags & APCI_SOFTCAR) == 0) {
                    574:                if (stat & MSR_DCD)
                    575:                        (void)(*linesw[tp->t_line].l_modem)(tp, 1);
                    576:                else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
                    577:                        apci->ap_mcr &= ~(MCR_DTR | MCR_RTS);
                    578:        }
                    579:
                    580:        /*
                    581:         * CTS change.
                    582:         * If doing HW output flow control, start/stop output as appropriate.
                    583:         */
                    584:        if ((stat & MSR_DCTS) &&
                    585:            (tp->t_state & TS_ISOPEN) && (tp->t_cflag & CCTS_OFLOW)) {
                    586:                if (stat & MSR_CTS) {
                    587:                        tp->t_state &=~ TS_TTSTOP;
                    588:                        apcistart(tp);
                    589:                } else
                    590:                        tp->t_state |= TS_TTSTOP;
                    591:        }
                    592: }
                    593:
                    594: int
                    595: apciioctl(dev, cmd, data, flag, p)
                    596:        dev_t dev;
                    597:        u_long cmd;
                    598:        caddr_t data;
                    599:        int flag;
                    600:        struct proc *p;
                    601: {
                    602:        struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)];
                    603:        struct tty *tp = sc->sc_tty;
                    604:        struct apciregs *apci = sc->sc_apci;
                    605:        int error;
                    606:
                    607:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
                    608:        if (error >= 0)
                    609:                return (error);
                    610:        error = ttioctl(tp, cmd, data, flag, p);
                    611:        if (error >= 0)
                    612:                return (error);
                    613:
                    614:        switch (cmd) {
                    615:        case TIOCSBRK:
                    616:                apci->ap_cfcr |= CFCR_SBREAK;
                    617:                break;
                    618:
                    619:        case TIOCCBRK:
                    620:                apci->ap_cfcr &= ~CFCR_SBREAK;
                    621:                break;
                    622:
                    623:        case TIOCSDTR:
                    624:                (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMBIS);
                    625:                break;
                    626:
                    627:        case TIOCCDTR:
                    628:                (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMBIC);
                    629:                break;
                    630:
                    631:        case TIOCMSET:
                    632:                (void) apcimctl(sc, *(int *)data, DMSET);
                    633:                break;
                    634:
                    635:        case TIOCMBIS:
                    636:                (void) apcimctl(sc, *(int *)data, DMBIS);
                    637:                break;
                    638:
                    639:        case TIOCMBIC:
                    640:                (void) apcimctl(sc, *(int *)data, DMBIC);
                    641:                break;
                    642:
                    643:        case TIOCMGET:
                    644:                *(int *)data = apcimctl(sc, 0, DMGET);
                    645:                break;
                    646:
                    647:        case TIOCGFLAGS: {
                    648:                int bits = 0;
                    649:
                    650:                if (sc->sc_flags & APCI_SOFTCAR)
                    651:                        bits |= TIOCFLAG_SOFTCAR;
                    652:
                    653:                if (tp->t_cflag & CLOCAL)
                    654:                        bits |= TIOCFLAG_CLOCAL;
                    655:
                    656:                *(int *)data = bits;
                    657:                break;
                    658:        }
                    659:
                    660:        case TIOCSFLAGS: {
                    661:                int userbits;
                    662:
                    663:                error = suser(p, 0);
                    664:                if (error)
                    665:                        return (EPERM);
                    666:
                    667:                userbits = *(int *)data;
                    668:
                    669:                if ((userbits & TIOCFLAG_SOFTCAR) ||
                    670:                    (sc->sc_flags & APCI_ISCONSOLE))
                    671:                        sc->sc_flags |= APCI_SOFTCAR;
                    672:
                    673:                if (userbits & TIOCFLAG_CLOCAL)
                    674:                        tp->t_cflag |= CLOCAL;
                    675:
                    676:                break;
                    677:        }
                    678:
                    679:        default:
                    680:                return (ENOTTY);
                    681:        }
                    682:        return (0);
                    683: }
                    684:
                    685: int
                    686: apciparam(tp, t)
                    687:        struct tty *tp;
                    688:        struct termios *t;
                    689: {
                    690:        struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(tp->t_dev)];
                    691:        struct apciregs *apci = sc->sc_apci;
                    692:        int cfcr, cflag = t->c_cflag;
                    693:        int ospeed = ttspeedtab(t->c_ospeed, apcispeedtab);
                    694:        int s;
                    695:
                    696:        /* check requested parameters */
                    697:        if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
                    698:                return (EINVAL);
                    699:
                    700:        switch (cflag & CSIZE) {
                    701:        case CS5:
                    702:                cfcr = CFCR_5BITS;
                    703:                break;
                    704:
                    705:        case CS6:
                    706:                cfcr = CFCR_6BITS;
                    707:                break;
                    708:
                    709:        case CS7:
                    710:                cfcr = CFCR_7BITS;
                    711:                break;
                    712:
                    713:        case CS8:
                    714:        default:        /* XXX gcc whines about cfcr being uninitialized... */
                    715:                cfcr = CFCR_8BITS;
                    716:                break;
                    717:        }
                    718:        if (cflag & PARENB) {
                    719:                cfcr |= CFCR_PENAB;
                    720:                if ((cflag & PARODD) == 0)
                    721:                        cfcr |= CFCR_PEVEN;
                    722:        }
                    723:        if (cflag & CSTOPB)
                    724:                cfcr |= CFCR_STOPB;
                    725:
                    726:        s = spltty();
                    727:
                    728:        if (ospeed == 0)
                    729:                (void) apcimctl(sc, 0, DMSET);  /* hang up line */
                    730:
                    731:        /*
                    732:         * Set the FIFO threshold based on the receive speed, if we
                    733:         * are changing it.
                    734:         */
                    735:        if (tp->t_ispeed != t->c_ispeed) {
                    736:                if (sc->sc_flags & APCI_HASFIFO)
                    737:                        apci->ap_fifo = FIFO_ENABLE |
                    738:                            (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 :
                    739:                            FIFO_TRIGGER_14);
                    740:        }
                    741:
                    742:        if (ospeed != 0) {
                    743:                apci->ap_cfcr |= CFCR_DLAB;
                    744:                apci->ap_data = ospeed & 0xff;
                    745:                apci->ap_ier = (ospeed >> 8) & 0xff;
                    746:                apci->ap_cfcr = cfcr;
                    747:        } else
                    748:                apci->ap_cfcr = cfcr;
                    749:
                    750:        /* and copy to tty */
                    751:        tp->t_ispeed = t->c_ispeed;
                    752:        tp->t_ospeed = t->c_ospeed;
                    753:        tp->t_cflag = cflag;
                    754:
                    755:        apci->ap_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
                    756:
                    757:        splx(s);
                    758:        return (0);
                    759: }
                    760:
                    761: void
                    762: apcistart(tp)
                    763:        struct tty *tp;
                    764: {
                    765:        struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(tp->t_dev)];
                    766:        struct apciregs *apci = sc->sc_apci;
                    767:        int s, c;
                    768:
                    769:        s = spltty();
                    770:
                    771:        if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
                    772:                goto out;
                    773:        if (tp->t_outq.c_cc <= tp->t_lowat) {
                    774:                if (tp->t_state & TS_ASLEEP) {
                    775:                        tp->t_state &= ~TS_ASLEEP;
                    776:                        wakeup((caddr_t)&tp->t_outq);
                    777:                }
                    778:                if (tp->t_outq.c_cc == 0)
                    779:                        goto out;
                    780:                selwakeup(&tp->t_wsel);
                    781:        }
                    782:        if (apci->ap_lsr & LSR_TXRDY) {
                    783:                tp->t_state |= TS_BUSY;
                    784:                if (sc->sc_flags & APCI_HASFIFO) {
                    785:                        for (c = 0; c < 16 && tp->t_outq.c_cc; ++c)
                    786:                                apci->ap_data = getc(&tp->t_outq);
                    787:                } else
                    788:                        apci->ap_data = getc(&tp->t_outq);
                    789:        }
                    790:
                    791:  out:
                    792:        splx(s);
                    793: }
                    794:
                    795: /*
                    796:  * Stop output on a line.
                    797:  */
                    798: /* ARGSUSED */
                    799: int
                    800: apcistop(tp, flag)
                    801:        struct tty *tp;
                    802:        int flag;
                    803: {
                    804:        int s;
                    805:
                    806:        s = spltty();
                    807:        if (tp->t_state & TS_BUSY)
                    808:                if ((tp->t_state & TS_TTSTOP) == 0)
                    809:                        tp->t_state |= TS_FLUSH;
                    810:        splx(s);
                    811:        return (0);
                    812: }
                    813:
                    814: int
                    815: apcimctl(sc, bits, how)
                    816:        struct apci_softc *sc;
                    817:        int bits, how;
                    818: {
                    819:        struct apciregs *apci = sc->sc_apci;
                    820:        int s;
                    821:
                    822:        s = spltty();
                    823:
                    824:        switch (how) {
                    825:        case DMSET:
                    826:                apci->ap_mcr = bits;
                    827:                break;
                    828:
                    829:        case DMBIS:
                    830:                apci->ap_mcr |= bits;
                    831:                break;
                    832:
                    833:        case DMBIC:
                    834:                apci->ap_mcr &= ~bits;
                    835:                break;
                    836:
                    837:        case DMGET:
                    838:                bits = apci->ap_msr;
                    839:                break;
                    840:        }
                    841:
                    842:        splx(s);
                    843:        return (bits);
                    844: }
                    845:
                    846: void
                    847: apcitimeout(arg)
                    848:        void *arg;
                    849: {
                    850:        struct apci_softc *sc = arg;
                    851:        int ferr, perr, oflow, s;
                    852:
                    853:        if (sc->sc_tty == NULL ||
                    854:            (sc->sc_tty->t_state & TS_ISOPEN) == 0)
                    855:                return;
                    856:
                    857:        /* Log any errors. */
                    858:        if (sc->sc_ferr || sc->sc_perr || sc->sc_oflow) {
                    859:                s = spltty();   /* XXX necessary? */
                    860:                ferr = sc->sc_ferr;
                    861:                perr = sc->sc_perr;
                    862:                oflow = sc->sc_oflow;
                    863:                sc->sc_ferr = sc->sc_perr = sc->sc_oflow = 0;
                    864:                splx(s);
                    865:                sc->sc_toterr += ferr + perr + oflow;
                    866:                log(LOG_WARNING,
                    867:                    "%s: %d frame, %d parity, %d overflow, %d total errors\n",
                    868:                    sc->sc_dev.dv_xname, ferr, perr, oflow, sc->sc_toterr);
                    869:        }
                    870:
                    871:        timeout_add(&sc->sc_timeout, hz);
                    872: }
                    873:
                    874: /*
                    875:  * The following routines are required for the APCI to act as the console.
                    876:  */
                    877:
                    878: void
                    879: apcicnprobe(cp)
                    880:        struct consdev *cp;
                    881: {
                    882:        volatile u_int8_t *frodoregs;
                    883:
                    884:        /* locate the major number */
                    885:        for (apcimajor = 0; apcimajor < nchrdev; apcimajor++)
                    886:                if (cdevsw[apcimajor].d_open == apciopen)
                    887:                        break;
                    888:
                    889:        /* initialize the required fields */
                    890:        cp->cn_dev = makedev(apcimajor, 0);     /* XXX */
                    891:
                    892:        /*
                    893:         * The APCI can only be a console on a 425e; on other 4xx
                    894:         * models, the "first" serial port is mapped to the DCA
                    895:         * at select code 9.  See frodo.c for the autoconfiguration
                    896:         * version of this check.
                    897:         */
                    898:        if (machineid != HP_425 || mmuid != MMUID_425_E)
                    899:                return;
                    900:
                    901:        /*
                    902:         * Check the service switch. On the 425e, this is a physical
                    903:         * switch, unlike other frodo-based machines, so we can use it
                    904:         * as a serial vs internal video selector, since the PROM can not
                    905:         * be configured for serial console.
                    906:         */
                    907:        frodoregs = (volatile u_int8_t *)IIOV(FRODO_BASE);
                    908:        if (badaddr((caddr_t)frodoregs) == 0 &&
                    909:            !ISSET(frodoregs[FRODO_IISR], FRODO_IISR_SERVICE))
                    910:                cp->cn_pri = CN_REMOTE;
                    911:        else
                    912:                cp->cn_pri = CN_NORMAL;
                    913:
                    914:        /*
                    915:         * If our priority is higher than the currently-remembered
                    916:         * console, install ourselves.
                    917:         */
                    918:        if (cn_tab == NULL || cp->cn_pri > cn_tab->cn_pri) {
                    919:                cn_tab = cp;
                    920:                conscode = CONSCODE_INVALID;
                    921:        }
                    922: }
                    923:
                    924: /* ARGSUSED */
                    925: void
                    926: apcicninit(cp)
                    927:        struct consdev *cp;
                    928: {
                    929:
                    930:        /*
                    931:         * We are not interested by the second console pass.
                    932:         */
                    933:        if (consolepass != 0)
                    934:                return;
                    935:
                    936:        apci_cn = (struct apciregs *)IIOV(FRODO_BASE + FRODO_APCI_OFFSET(1));
                    937:        apciinit(apci_cn, apcidefaultrate, CFCR_8BITS);
                    938:        apciconsinit = 1;
                    939: }
                    940:
                    941: /* ARGSUSED */
                    942: int
                    943: apcicngetc(dev)
                    944:        dev_t dev;
                    945: {
                    946:        u_char stat;
                    947:        int c, s;
                    948:
                    949:        s = splhigh();
                    950:        while (((stat = apci_cn->ap_lsr) & LSR_RXRDY) == 0)
                    951:                ;
                    952:        c = apci_cn->ap_data;
                    953:
                    954:        /* clear any interrupts generated by this transmission */
                    955:        stat = apci_cn->ap_iir;
                    956:        splx(s);
                    957:        return (c);
                    958: }
                    959:
                    960: /* ARGSUSED */
                    961: void
                    962: apcicnputc(dev, c)
                    963:        dev_t dev;
                    964:        int c;
                    965: {
                    966:        int timo;
                    967:        u_char stat;
                    968:        int s;
                    969:
                    970:        s = splhigh();
                    971:
                    972:        if (apciconsinit == 0) {
                    973:                apciinit(apci_cn, apcidefaultrate, CFCR_8BITS);
                    974:                apciconsinit = 1;
                    975:        }
                    976:
                    977:        /* wait for any pending transmission to finish */
                    978:        timo = 50000;
                    979:        while (((stat = apci_cn->ap_lsr) & LSR_TXRDY) == 0 && --timo)
                    980:                ;
                    981:
                    982:        apci_cn->ap_data = c & 0xff;
                    983:
                    984:        /* wait for this transmission to complete */
                    985:        timo = 1500000;
                    986:        while (((stat = apci_cn->ap_lsr) & LSR_TXRDY) == 0 && --timo)
                    987:                ;
                    988:
                    989:        /* clear any interrupts generated by this transmission */
                    990:        stat = apci_cn->ap_iir;
                    991:        splx(s);
                    992: }

CVSweb