diff options
Diffstat (limited to 'sys/arch/hp300/dev/apci.c')
-rw-r--r-- | sys/arch/hp300/dev/apci.c | 978 |
1 files changed, 0 insertions, 978 deletions
diff --git a/sys/arch/hp300/dev/apci.c b/sys/arch/hp300/dev/apci.c deleted file mode 100644 index 6bc333b4f4d..00000000000 --- a/sys/arch/hp300/dev/apci.c +++ /dev/null @@ -1,978 +0,0 @@ -/* $OpenBSD: apci.c,v 1.41 2010/07/02 17:27:01 nicm Exp $ */ -/* $NetBSD: apci.c,v 1.9 2000/11/02 00:35:05 eeh Exp $ */ - -/*- - * Copyright (c) 1996, 1997, 1999 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 1997 Michael Smith. All rights reserved. - * Copyright (c) 1982, 1986, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)dca.c 8.2 (Berkeley) 1/12/94 - */ - -/* - * Device driver for the APCI 8250-like UARTs found on the Apollo - * Utility Chip on HP 9000/400-series workstations. - * - * There are 4 APCI UARTs on the Frodo ASIC. The first one - * is used to communicate with the Domain keyboard. The second - * one is the serial console port when the firmware is in Domain/OS - * mode, and is mapped to select code 9 by the HP-UX firmware (except - * on 425e models). - * - * We don't bother attaching a tty to the first UART; it lacks modem/flow - * control, and is directly connected to the keyboard connector anyhow. - */ - -/* - * XXX This driver is very similar to the dca driver, and much - * XXX more code could be shared. (Currently, no code is shared.) - * XXX FIXME! - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/ioctl.h> -#include <sys/proc.h> -#include <sys/tty.h> -#include <sys/conf.h> -#include <sys/file.h> -#include <sys/uio.h> -#include <sys/kernel.h> -#include <sys/syslog.h> -#include <sys/device.h> -#include <sys/timeout.h> - -#include <machine/autoconf.h> -#include <machine/bus.h> -#include <machine/cpu.h> -#include <machine/hp300spu.h> - -#include <dev/cons.h> - -#include <hp300/dev/dioreg.h> /* to check for dca at 9 */ -#include <hp300/dev/diovar.h> -#include <hp300/dev/diodevs.h> - -#include <hp300/dev/frodoreg.h> -#include <hp300/dev/frodovar.h> -#include <hp300/dev/apcireg.h> -#include <hp300/dev/apcivar.h> -#include <hp300/dev/dcareg.h> /* register bit definitions */ - -#ifdef DDB -#include <ddb/db_var.h> -#endif - -struct apci_softc { - struct device sc_dev; /* generic device glue */ - struct isr sc_isr; - struct apciregs *sc_apci; /* device registers */ - struct tty *sc_tty; /* tty glue */ - struct timeout sc_timeout; /* timeout */ - int sc_ferr, - sc_perr, - sc_oflow, - sc_toterr; /* stats */ - int sc_flags; - u_char sc_cua; /* callout mode */ -}; - -/* sc_flags */ -#define APCI_HASFIFO 0x01 /* unit has a fifo */ -#define APCI_ISCONSOLE 0x02 /* unit is console */ -#define APCI_SOFTCAR 0x04 /* soft carrier */ - -int apcimatch(struct device *, void *, void *); -void apciattach(struct device *, struct device *, void *); - -struct cfattach apci_ca = { - sizeof(struct apci_softc), apcimatch, apciattach -}; - -struct cfdriver apci_cd = { - NULL, "apci", DV_TTY -}; - -int apciintr(void *); -void apcieint(struct apci_softc *, int); -void apcimint(struct apci_softc *, u_char); -int apciparam(struct tty *, struct termios *); -void apcistart(struct tty *); -int apcimctl(struct apci_softc *, int, int); -void apcitimeout(void *); - -cdev_decl(apci); - -#define APCIUNIT(x) (minor(x) & 0x7f) -#define APCICUA(x) (minor(x) & 0x80) - -int apcidefaultrate = TTYDEF_SPEED; - -/* - * Console support. - */ -struct apciregs *apci_cn = NULL; /* console hardware */ -int apciconsinit; /* has been initialized */ -int apcimajor; /* our major number */ - -cons_decl(apci); - -int -apcimatch(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - struct frodo_attach_args *fa = aux; - - /* Looking for an apci? */ - if (strcmp(fa->fa_name, apci_cd.cd_name) != 0) - return (0); - - /* Are we checking a valid APCI offset? */ - switch (fa->fa_offset) { - case FRODO_APCI_OFFSET(1): - case FRODO_APCI_OFFSET(2): - case FRODO_APCI_OFFSET(3): - /* Yup, we exist! */ - return (1); - } - - return (0); -} - -void -apciattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct apci_softc *sc = (struct apci_softc *)self; - struct apciregs *apci; - struct frodo_attach_args *fa = aux; - - sc->sc_apci = apci = - (struct apciregs *)IIOV(FRODO_BASE + fa->fa_offset); - sc->sc_flags = 0; - - /* Initialize timeout structure */ - timeout_set(&sc->sc_timeout, apcitimeout, sc); - - /* Are we the console? */ - if (apci == apci_cn) { - sc->sc_flags |= APCI_ISCONSOLE; - delay(100000); - - /* - * We didn't know which unit this would be during - * the console probe, so we have to fixup cn_dev here. - */ - cn_tab->cn_dev = makedev(apcimajor, self->dv_unit); - } - - /* Look for a FIFO. */ - apci->ap_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; - delay(100); - if ((apci->ap_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK) - sc->sc_flags |= APCI_HASFIFO; - - /* Establish our interrupt handler. */ - sc->sc_isr.isr_func = apciintr; - sc->sc_isr.isr_arg = sc; - sc->sc_isr.isr_priority = IPL_TTY; - frodo_intr_establish(parent, fa->fa_line, &sc->sc_isr, self->dv_xname); - - /* Set soft carrier if requested by operator. */ - if (self->dv_cfdata->cf_flags) - sc->sc_flags |= APCI_SOFTCAR; - - /* - * Need to reset baud rate, etc. of next print, so reset apciconsinit. - * Also make sure console is always "hardwired". - */ - if (sc->sc_flags & APCI_ISCONSOLE) { - apciconsinit = 0; - sc->sc_flags |= APCI_SOFTCAR; - printf(": console, "); - } else - printf(": "); - - if (sc->sc_flags & APCI_HASFIFO) - printf("working fifo\n"); - else - printf("no fifo\n"); -} - -/* ARGSUSED */ -int -apciopen(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - int unit = APCIUNIT(dev); - struct apci_softc *sc; - struct tty *tp; - struct apciregs *apci; - u_char code; - int s, error = 0; - - if (unit >= apci_cd.cd_ndevs || - (sc = apci_cd.cd_devs[unit]) == NULL) - return (ENXIO); - - apci = sc->sc_apci; - - s = spltty(); - if (sc->sc_tty == NULL) { - tp = sc->sc_tty = ttymalloc(0); - } else - tp = sc->sc_tty; - splx(s); - - tp->t_oproc = apcistart; - tp->t_param = apciparam; - tp->t_dev = dev; - - if ((tp->t_state & TS_ISOPEN) == 0) { - /* - * Sanity clause: reset the chip on first open. - * The chip might be left in an inconsistent state - * if it is read inadventently. - */ - apciinit(apci, apcidefaultrate, CFCR_8BITS); - - tp->t_state |= TS_WOPEN; - ttychars(tp); - tp->t_iflag = TTYDEF_IFLAG; - tp->t_oflag = TTYDEF_OFLAG; - tp->t_cflag = TTYDEF_CFLAG; - tp->t_lflag = TTYDEF_LFLAG; - tp->t_ispeed = tp->t_ospeed = apcidefaultrate; - - s = spltty(); - - apciparam(tp, &tp->t_termios); - ttsetwater(tp); - - /* Set the FIFO threshold based on the receive speed. */ - if (sc->sc_flags & APCI_HASFIFO) - apci->ap_fifo = FIFO_ENABLE | FIFO_RCV_RST | - FIFO_XMT_RST | - (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : - FIFO_TRIGGER_14); - - /* Flush any pending I/O. */ - while ((apci->ap_iir & IIR_IMASK) == IIR_RXRDY) - code = apci->ap_data; - } else if (tp->t_state & TS_XCLUDE && suser(p, 0) != 0) - return (EBUSY); - else - s = spltty(); - - /* Set the modem control state. */ - (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMSET); - - /* Set soft-carrier if so configured. */ - if ((sc->sc_flags & APCI_SOFTCAR) || APCICUA(dev) || - (apcimctl(sc, 0, DMGET) & MSR_DCD)) - tp->t_state |= TS_CARR_ON; - - if (APCICUA(dev)) { - if (tp->t_state & TS_ISOPEN) { - /* Ah, but someone already is dialed in... */ - splx(s); - return (EBUSY); - } - sc->sc_cua = 1; /* We go into CUA mode */ - } - - /* Wait for carrier if necessary. */ - if (flag & O_NONBLOCK) { - if (!APCICUA(dev) && sc->sc_cua) { - /* Opening TTY non-blocking... but the CUA is busy */ - splx(s); - return (EBUSY); - } - } else { - while (sc->sc_cua || - ((tp->t_cflag & CLOCAL) == 0 && - (tp->t_state & TS_CARR_ON) == 0)) { - tp->t_state |= TS_WOPEN; - error = ttysleep(tp, (caddr_t)&tp->t_rawq, - TTIPRI | PCATCH, ttopen, 0); - if (!APCICUA(dev) && sc->sc_cua && error == EINTR) - continue; - if (error) { - if (APCICUA(dev)) - sc->sc_cua = 0; - splx(s); - return (error); - } - if (!APCICUA(dev) && sc->sc_cua) - continue; - } - } - - splx(s); - - if (error == 0) - error = (*linesw[tp->t_line].l_open)(dev, tp, p); - - if (error == 0) { - /* clear errors, start timeout */ - sc->sc_ferr = sc->sc_perr = sc->sc_oflow = sc->sc_toterr = 0; - timeout_add_sec(&sc->sc_timeout, 1); - } - - return (error); -} - -/* ARGSUSED */ -int -apciclose(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - struct apci_softc *sc; - struct tty *tp; - struct apciregs *apci; - int unit = APCIUNIT(dev); - int s; - - sc = apci_cd.cd_devs[unit]; - apci = sc->sc_apci; - tp = sc->sc_tty; - - (*linesw[tp->t_line].l_close)(tp, flag, p); - - s = spltty(); - - apci->ap_cfcr &= ~CFCR_SBREAK; - apci->ap_ier = 0; - if (tp->t_cflag & HUPCL && (sc->sc_flags & APCI_SOFTCAR) == 0) { - /* XXX perhaps only clear DTR */ - (void) apcimctl(sc, 0, DMSET); - } - tp->t_state &= ~(TS_BUSY | TS_FLUSH); - sc->sc_cua = 0; - splx(s); - ttyclose(tp); -#if 0 - ttyfree(tp); - sc->sc_tty = NULL; -#endif - return (0); -} - -int -apciread(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; -{ - struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)]; - struct tty *tp = sc->sc_tty; - - return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); -} - -int -apciwrite(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; -{ - struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)]; - struct tty *tp = sc->sc_tty; - - return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); -} - -struct tty * -apcitty(dev) - dev_t dev; -{ - struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)]; - - return (sc->sc_tty); -} - -int -apciintr(arg) - void *arg; -{ - struct apci_softc *sc = arg; - struct apciregs *apci = sc->sc_apci; - struct tty *tp = sc->sc_tty; - u_char iir, lsr, c; - int iflowdone = 0, claimed = 0; - -#define RCVBYTE() \ - c = apci->ap_data; \ - if (tp != NULL && (tp->t_state & TS_ISOPEN) != 0) \ - (*linesw[tp->t_line].l_rint)(c, tp) - - for (;;) { - iir = apci->ap_iir; /* get UART status */ - - switch (iir & IIR_IMASK) { - case IIR_RLS: - apcieint(sc, apci->ap_lsr); - break; - - case IIR_RXRDY: - case IIR_RXTOUT: - RCVBYTE(); - if (sc->sc_flags & APCI_HASFIFO) { - while ((lsr = apci->ap_lsr) & LSR_RCV_MASK) { - if (lsr == LSR_RXRDY) { - RCVBYTE(); - } else - apcieint(sc, lsr); - } - } - if (iflowdone == 0 && tp != NULL && - (tp->t_cflag & CRTS_IFLOW) && - tp->t_rawq.c_cc > (TTYHOG(tp) / 2)) { - apci->ap_mcr &= ~MCR_RTS; - iflowdone = 1; - } - break; - - case IIR_TXRDY: - if (tp != NULL) { - tp->t_state &=~ (TS_BUSY|TS_FLUSH); - if (tp->t_line) - (*linesw[tp->t_line].l_start)(tp); - else - apcistart(tp); - } - break; - - default: - if (iir & IIR_NOPEND) - return (claimed); - log(LOG_WARNING, "%s: weird interrupt: 0x%x\n", - sc->sc_dev.dv_xname, iir); - /* FALLTHROUGH */ - - case IIR_MLSC: - apcimint(sc, apci->ap_msr); - break; - } - - claimed = 1; - } -} - -void -apcieint(sc, stat) - struct apci_softc *sc; - int stat; -{ - struct tty *tp = sc->sc_tty; - struct apciregs *apci = sc->sc_apci; - int c; - - c = apci->ap_data; - -#ifdef DDB - if ((sc->sc_flags & APCI_ISCONSOLE) && db_console && (stat & LSR_BI)) { - Debugger(); - return; - } -#endif - - if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) - return; - - if (stat & (LSR_BI | LSR_FE)) { - c |= TTY_FE; - sc->sc_ferr++; - } else if (stat & LSR_PE) { - c |= TTY_PE; - sc->sc_perr++; - } else if (stat & LSR_OE) - sc->sc_oflow++; - (*linesw[tp->t_line].l_rint)(c, tp); -} - -void -apcimint(sc, stat) - struct apci_softc *sc; - u_char stat; -{ - struct tty *tp = sc->sc_tty; - struct apciregs *apci = sc->sc_apci; - - if (tp == NULL) - return; - - if ((stat & MSR_DDCD) && - (sc->sc_flags & APCI_SOFTCAR) == 0) { - if (stat & MSR_DCD) - (void)(*linesw[tp->t_line].l_modem)(tp, 1); - else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) - apci->ap_mcr &= ~(MCR_DTR | MCR_RTS); - } - - /* - * CTS change. - * If doing HW output flow control, start/stop output as appropriate. - */ - if ((stat & MSR_DCTS) && - (tp->t_state & TS_ISOPEN) && (tp->t_cflag & CCTS_OFLOW)) { - if (stat & MSR_CTS) { - tp->t_state &=~ TS_TTSTOP; - apcistart(tp); - } else - tp->t_state |= TS_TTSTOP; - } -} - -int -apciioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; -{ - struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)]; - struct tty *tp = sc->sc_tty; - struct apciregs *apci = sc->sc_apci; - int error; - - error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); - if (error >= 0) - return (error); - error = ttioctl(tp, cmd, data, flag, p); - if (error >= 0) - return (error); - - switch (cmd) { - case TIOCSBRK: - apci->ap_cfcr |= CFCR_SBREAK; - break; - - case TIOCCBRK: - apci->ap_cfcr &= ~CFCR_SBREAK; - break; - - case TIOCSDTR: - (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMBIS); - break; - - case TIOCCDTR: - (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMBIC); - break; - - case TIOCMSET: - (void) apcimctl(sc, *(int *)data, DMSET); - break; - - case TIOCMBIS: - (void) apcimctl(sc, *(int *)data, DMBIS); - break; - - case TIOCMBIC: - (void) apcimctl(sc, *(int *)data, DMBIC); - break; - - case TIOCMGET: - *(int *)data = apcimctl(sc, 0, DMGET); - break; - - case TIOCGFLAGS: { - int bits = 0; - - if (sc->sc_flags & APCI_SOFTCAR) - bits |= TIOCFLAG_SOFTCAR; - - if (tp->t_cflag & CLOCAL) - bits |= TIOCFLAG_CLOCAL; - - *(int *)data = bits; - break; - } - - case TIOCSFLAGS: { - int userbits; - - error = suser(p, 0); - if (error) - return (EPERM); - - userbits = *(int *)data; - - if ((userbits & TIOCFLAG_SOFTCAR) || - (sc->sc_flags & APCI_ISCONSOLE)) - sc->sc_flags |= APCI_SOFTCAR; - - if (userbits & TIOCFLAG_CLOCAL) - tp->t_cflag |= CLOCAL; - - break; - } - - default: - return (ENOTTY); - } - return (0); -} - -int -apciparam(tp, t) - struct tty *tp; - struct termios *t; -{ - struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(tp->t_dev)]; - struct apciregs *apci = sc->sc_apci; - int cfcr, cflag = t->c_cflag; - int ospeed = ttspeedtab(t->c_ospeed, apcispeedtab); - int s; - - /* check requested parameters */ - if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) - return (EINVAL); - - switch (cflag & CSIZE) { - case CS5: - cfcr = CFCR_5BITS; - break; - - case CS6: - cfcr = CFCR_6BITS; - break; - - case CS7: - cfcr = CFCR_7BITS; - break; - - case CS8: - default: /* XXX gcc whines about cfcr being uninitialized... */ - cfcr = CFCR_8BITS; - break; - } - if (cflag & PARENB) { - cfcr |= CFCR_PENAB; - if ((cflag & PARODD) == 0) - cfcr |= CFCR_PEVEN; - } - if (cflag & CSTOPB) - cfcr |= CFCR_STOPB; - - s = spltty(); - - if (ospeed == 0) - (void) apcimctl(sc, 0, DMSET); /* hang up line */ - - /* - * Set the FIFO threshold based on the receive speed, if we - * are changing it. - */ - if (tp->t_ispeed != t->c_ispeed) { - if (sc->sc_flags & APCI_HASFIFO) - apci->ap_fifo = FIFO_ENABLE | - (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : - FIFO_TRIGGER_14); - } - - if (ospeed != 0) { - apci->ap_cfcr |= CFCR_DLAB; - apci->ap_data = ospeed & 0xff; - apci->ap_ier = (ospeed >> 8) & 0xff; - apci->ap_cfcr = cfcr; - } else - apci->ap_cfcr = cfcr; - - /* and copy to tty */ - tp->t_ispeed = t->c_ispeed; - tp->t_ospeed = t->c_ospeed; - tp->t_cflag = cflag; - - apci->ap_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; - - splx(s); - return (0); -} - -void -apcistart(tp) - struct tty *tp; -{ - struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(tp->t_dev)]; - struct apciregs *apci = sc->sc_apci; - int s, c; - - s = spltty(); - - if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) - goto out; - ttwakeupwr(tp); - if (tp->t_outq.c_cc == 0) - goto out; - if (apci->ap_lsr & LSR_TXRDY) { - tp->t_state |= TS_BUSY; - if (sc->sc_flags & APCI_HASFIFO) { - for (c = 0; c < 16 && tp->t_outq.c_cc; ++c) - apci->ap_data = getc(&tp->t_outq); - } else - apci->ap_data = getc(&tp->t_outq); - } - - out: - splx(s); -} - -/* - * Stop output on a line. - */ -/* ARGSUSED */ -int -apcistop(tp, flag) - struct tty *tp; - int flag; -{ - int s; - - s = spltty(); - if (tp->t_state & TS_BUSY) - if ((tp->t_state & TS_TTSTOP) == 0) - tp->t_state |= TS_FLUSH; - splx(s); - return (0); -} - -int -apcimctl(sc, bits, how) - struct apci_softc *sc; - int bits, how; -{ - struct apciregs *apci = sc->sc_apci; - int s; - - s = spltty(); - - switch (how) { - case DMSET: - apci->ap_mcr = bits; - break; - - case DMBIS: - apci->ap_mcr |= bits; - break; - - case DMBIC: - apci->ap_mcr &= ~bits; - break; - - case DMGET: - bits = apci->ap_msr; - break; - } - - splx(s); - return (bits); -} - -void -apcitimeout(arg) - void *arg; -{ - struct apci_softc *sc = arg; - int ferr, perr, oflow, s; - - if (sc->sc_tty == NULL || - (sc->sc_tty->t_state & TS_ISOPEN) == 0) - return; - - /* Log any errors. */ - if (sc->sc_ferr || sc->sc_perr || sc->sc_oflow) { - s = spltty(); /* XXX necessary? */ - ferr = sc->sc_ferr; - perr = sc->sc_perr; - oflow = sc->sc_oflow; - sc->sc_ferr = sc->sc_perr = sc->sc_oflow = 0; - splx(s); - sc->sc_toterr += ferr + perr + oflow; - log(LOG_WARNING, - "%s: %d frame, %d parity, %d overflow, %d total errors\n", - sc->sc_dev.dv_xname, ferr, perr, oflow, sc->sc_toterr); - } - - timeout_add_sec(&sc->sc_timeout, 1); -} - -/* - * The following routines are required for the APCI to act as the console. - */ - -void -apcicnprobe(cp) - struct consdev *cp; -{ - volatile u_int8_t *frodoregs; - - /* locate the major number */ - for (apcimajor = 0; apcimajor < nchrdev; apcimajor++) - if (cdevsw[apcimajor].d_open == apciopen) - break; - - /* initialize the required fields */ - cp->cn_dev = makedev(apcimajor, 0); /* XXX */ - - /* - * The APCI can only be a console on a 425e; on other 4xx - * models, the "first" serial port is mapped to the DCA - * at select code 9. See frodo.c for the autoconfiguration - * version of this check. - */ - if (machineid != HP_425 || mmuid != MMUID_425_E) - return; - - /* - * Check the service switch. On the 425e, this is a physical - * switch, unlike other frodo-based machines, so we can use it - * as a serial vs internal video selector, since the PROM can not - * be configured for serial console. - */ - frodoregs = (volatile u_int8_t *)IIOV(FRODO_BASE); - if (badaddr((caddr_t)frodoregs) == 0 && - !ISSET(frodoregs[FRODO_IISR], FRODO_IISR_SERVICE)) - cp->cn_pri = CN_HIGHPRI; - else - cp->cn_pri = CN_LOWPRI; - - /* - * If our priority is higher than the currently-remembered - * console, install ourselves. - */ - if (cn_tab == NULL || cp->cn_pri > cn_tab->cn_pri) { - cn_tab = cp; - conscode = CONSCODE_INVALID; - } -} - -/* ARGSUSED */ -void -apcicninit(cp) - struct consdev *cp; -{ - - /* - * We are not interested by the second console pass. - */ - if (consolepass != 0) - return; - - apci_cn = (struct apciregs *)IIOV(FRODO_BASE + FRODO_APCI_OFFSET(1)); - apciinit(apci_cn, apcidefaultrate, CFCR_8BITS); - apciconsinit = 1; -} - -/* ARGSUSED */ -int -apcicngetc(dev) - dev_t dev; -{ - u_char stat; - int c, s; - - s = splhigh(); - while (((stat = apci_cn->ap_lsr) & LSR_RXRDY) == 0) - ; - c = apci_cn->ap_data; - - /* clear any interrupts generated by this transmission */ - stat = apci_cn->ap_iir; - splx(s); - return (c); -} - -/* ARGSUSED */ -void -apcicnputc(dev, c) - dev_t dev; - int c; -{ - int timo; - u_char stat; - int s; - - s = splhigh(); - - if (apciconsinit == 0) { - apciinit(apci_cn, apcidefaultrate, CFCR_8BITS); - apciconsinit = 1; - } - - /* wait for any pending transmission to finish */ - timo = 50000; - while (((stat = apci_cn->ap_lsr) & LSR_TXRDY) == 0 && --timo) - ; - - apci_cn->ap_data = c & 0xff; - - /* wait for this transmission to complete */ - timo = 1500000; - while (((stat = apci_cn->ap_lsr) & LSR_TXRDY) == 0 && --timo) - ; - - /* clear any interrupts generated by this transmission */ - stat = apci_cn->ap_iir; - splx(s); -} |