[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     ! 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