diff options
Diffstat (limited to 'sys/arch/hp300/dev/dca.c')
-rw-r--r-- | sys/arch/hp300/dev/dca.c | 1114 |
1 files changed, 0 insertions, 1114 deletions
diff --git a/sys/arch/hp300/dev/dca.c b/sys/arch/hp300/dev/dca.c deleted file mode 100644 index 7653fa6a7a8..00000000000 --- a/sys/arch/hp300/dev/dca.c +++ /dev/null @@ -1,1114 +0,0 @@ -/* $OpenBSD: dca.c,v 1.44 2014/03/11 19:45:27 guenther Exp $ */ -/* $NetBSD: dca.c,v 1.35 1997/05/05 20:58:18 thorpej Exp $ */ - -/* - * Copyright (c) 1995, 1996, 1997 Jason R. Thorpe. 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 - */ - -/* - * Driver for the 98626/98644/internal serial interface on hp300/hp400, - * based on the National Semiconductor INS8250/NS16550AF/WD16C552 UARTs. - * - * N.B. On the hp700 and some hp300s, there is a "secret bit" with - * undocumented behavior. The third bit of the Modem Control Register - * (MCR_IEN == 0x08) must be set to enable interrupts. Failure to do - * so can result in deadlock on those machines, whereas the don't seem to - * be any harmful side-effects from setting this bit on non-affected - * machines. - */ - -#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 <machine/autoconf.h> -#include <machine/bus.h> -#include <machine/cpu.h> -#include <machine/intr.h> - -#include <dev/cons.h> - -#include <hp300/dev/dioreg.h> -#include <hp300/dev/diovar.h> -#include <hp300/dev/diodevs.h> -#include <hp300/dev/dcareg.h> - -#ifdef DDB -#include <ddb/db_var.h> -#endif - -struct dca_softc { - struct device sc_dev; /* generic device glue */ - struct isr sc_isr; - struct dcadevice *sc_dca; /* pointer to hardware */ - struct tty *sc_tty; /* our tty instance */ - int sc_oflows; /* overflow counter */ - short sc_flags; /* state flags */ - u_char sc_cua; /* callout mode */ - - /* - * Bits for sc_flags. - */ -#define DCA_ACTIVE 0x0001 /* indicates live unit */ -#define DCA_SOFTCAR 0x0002 /* indicates soft-carrier */ -#define DCA_HASFIFO 0x0004 /* indicates unit has FIFO */ -#define DCA_ISCONSOLE 0x0008 /* indicates unit is console */ - -}; - -int dcamatch(struct device *, void *, void *); -void dcaattach(struct device *, struct device *, void *); - -struct cfattach dca_ca = { - sizeof(struct dca_softc), dcamatch, dcaattach -}; - -struct cfdriver dca_cd = { - NULL, "dca", DV_TTY -}; - -int dcadefaultrate = TTYDEF_SPEED; -int dcamajor; - -cdev_decl(dca); - -int dcaintr(void *); -void dcaeint(struct dca_softc *, int); -void dcamint(struct dca_softc *); - -int dcaparam(struct tty *, struct termios *); -void dcastart(struct tty *); -int dcastop(struct tty *, int); -int dcamctl(struct dca_softc *, int, int); -void dcainit(struct dcadevice *, int); - -int dca_console_scan(int, caddr_t, void *); -cons_decl(dca); - -/* - * Stuff for DCA console support. - */ -static struct dcadevice *dca_cn = NULL; /* pointer to hardware */ -static int dcaconsinit; /* has been initialized */ - -const struct speedtab dcaspeedtab[] = { - { 0, 0 }, - { 50, DCABRD(50) }, - { 75, DCABRD(75) }, - { 110, DCABRD(110) }, - { 134, DCABRD(134) }, - { 150, DCABRD(150) }, - { 200, DCABRD(200) }, - { 300, DCABRD(300) }, - { 600, DCABRD(600) }, - { 1200, DCABRD(1200) }, - { 1800, DCABRD(1800) }, - { 2400, DCABRD(2400) }, - { 4800, DCABRD(4800) }, - { 9600, DCABRD(9600) }, - { 19200, DCABRD(19200) }, - { 38400, DCABRD(38400) }, - { -1, -1 }, -}; - -#ifdef KGDB -#include <machine/remote-sl.h> - -extern dev_t kgdb_dev; -extern int kgdb_rate; -extern int kgdb_debug_init; -#endif - -#define DCAUNIT(x) (minor(x) & 0x7f) -#define DCACUA(x) (minor(x) & 0x80) - -#ifdef DEBUG -long fifoin[17]; -long fifoout[17]; -long dcaintrcount[16]; -long dcamintcount[16]; -#endif - -void dcainit(struct dcadevice *, int); - -int -dcamatch(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - struct dio_attach_args *da = aux; - - switch (da->da_id) { - case DIO_DEVICE_ID_DCA0: - case DIO_DEVICE_ID_DCA0REM: - case DIO_DEVICE_ID_DCA1: - case DIO_DEVICE_ID_DCA1REM: - return (1); - } - - return (0); -} - -void -dcaattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct dca_softc *sc = (struct dca_softc *)self; - struct dio_attach_args *da = aux; - struct dcadevice *dca; - int unit = self->dv_unit; - int scode = da->da_scode; - int ipl; - - if (scode == conscode) { - dca = (struct dcadevice *)conaddr; - sc->sc_flags |= DCA_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(dcamajor, unit); - } else { - dca = (struct dcadevice *)iomap(dio_scodetopa(da->da_scode), - da->da_size); - if (dca == NULL) { - printf("\n%s: can't map registers\n", - sc->sc_dev.dv_xname); - return; - } - } - - sc->sc_dca = dca; - - ipl = DIO_IPL(dca); - printf(" ipl %d", ipl); - - dca->dca_reset = 0xFF; - DELAY(100); - - /* look for a NS 16550AF UART with FIFOs */ - dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; - DELAY(100); - if ((dca->dca_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK) - sc->sc_flags |= DCA_HASFIFO; - - /* Establish interrupt handler. */ - sc->sc_isr.isr_func = dcaintr; - sc->sc_isr.isr_arg = sc; - sc->sc_isr.isr_ipl = ipl; - sc->sc_isr.isr_priority = IPL_TTY; - dio_intr_establish(&sc->sc_isr, self->dv_xname); - - sc->sc_flags |= DCA_ACTIVE; - if (self->dv_cfdata->cf_flags) - sc->sc_flags |= DCA_SOFTCAR; - - /* Enable interrupts. */ - dca->dca_ic = IC_IE; - - /* - * Need to reset baud rate, etc. of next print so reset dcaconsinit. - * Also make sure console is always "hardwired." - */ - if (sc->sc_flags & DCA_ISCONSOLE) { - dcaconsinit = 0; - sc->sc_flags |= DCA_SOFTCAR; - printf(": console, "); - } else - printf(": "); - - if (sc->sc_flags & DCA_HASFIFO) - printf("working fifo\n"); - else - printf("no fifo\n"); - -#ifdef KGDB - if (kgdb_dev == makedev(dcamajor, unit)) { - if (sc->sc_flags & DCA_ISCONSOLE) - kgdb_dev = NODEV; /* can't debug over console port */ - else { - dcainit(dca, kgdb_rate); - dcaconsinit = 1; /* don't re-init in dcaputc */ - if (kgdb_debug_init) { - /* - * Print prefix of device name, - * let kgdb_connect print the rest. - */ - printf("%s: ", sc->sc_dev.dv_xname); - kgdb_connect(1); - } else - printf("%s: kgdb enabled\n", - sc->sc_dev.dv_xname); - } - } -#endif -} - -/* ARGSUSED */ -int -dcaopen(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - int unit = DCAUNIT(dev); - struct dca_softc *sc; - struct tty *tp; - struct dcadevice *dca; - u_char code; - int s, error = 0; - - if (unit >= dca_cd.cd_ndevs || - (sc = dca_cd.cd_devs[unit]) == NULL) - return (ENXIO); - - if ((sc->sc_flags & DCA_ACTIVE) == 0) - return (ENXIO); - - dca = sc->sc_dca; - - s = spltty(); - if (sc->sc_tty == NULL) { - tp = sc->sc_tty = ttymalloc(0); - } else - tp = sc->sc_tty; - splx(s); - - tp->t_oproc = dcastart; - tp->t_param = dcaparam; - tp->t_dev = dev; - - if ((tp->t_state & TS_ISOPEN) == 0) { - /* - * Sanity clause: reset the card on first open. - * The card might be left in an inconsistent state - * if card memory is read inadvertently. - */ - dcainit(dca, dcadefaultrate); - - 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 = dcadefaultrate; - - s = spltty(); - - dcaparam(tp, &tp->t_termios); - ttsetwater(tp); - - /* Set the FIFO threshold based on the receive speed. */ - if (sc->sc_flags & DCA_HASFIFO) - dca->dca_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 ((dca->dca_iir & IIR_IMASK) == IIR_RXRDY) - code = dca->dca_data; - - } else if (tp->t_state&TS_XCLUDE && suser(p, 0) != 0) - return (EBUSY); - else - s = spltty(); - - /* Set modem control state. */ - (void) dcamctl(sc, MCR_DTR | MCR_RTS, DMSET); - - /* Set soft-carrier if so configured. */ - if ((sc->sc_flags & DCA_SOFTCAR) || DCACUA(dev) || - (dcamctl(sc, 0, DMGET) & MSR_DCD)) - tp->t_state |= TS_CARR_ON; - - if (DCACUA(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 (!DCACUA(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 (!DCACUA(dev) && sc->sc_cua && error == EINTR) - continue; - if (error) { - if (DCACUA(dev)) - sc->sc_cua = 0; - splx(s); - return (error); - } - if (!DCACUA(dev) && sc->sc_cua) - continue; - } - } - splx(s); - - if (error == 0) - error = (*linesw[tp->t_line].l_open)(dev, tp, p); - - return (error); -} - -/*ARGSUSED*/ -int -dcaclose(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - struct dca_softc *sc; - struct tty *tp; - struct dcadevice *dca; - int unit; - int s; - - unit = DCAUNIT(dev); - - sc = dca_cd.cd_devs[unit]; - - dca = sc->sc_dca; - tp = sc->sc_tty; - (*linesw[tp->t_line].l_close)(tp, flag, p); - - s = spltty(); - - dca->dca_cfcr &= ~CFCR_SBREAK; -#ifdef KGDB - /* do not disable interrupts if debugging */ - if (dev != kgdb_dev) -#endif - dca->dca_ier = 0; - if (tp->t_cflag & HUPCL && (sc->sc_flags & DCA_SOFTCAR) == 0) { - /* XXX perhaps only clear DTR */ - (void) dcamctl(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 -dcaread(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; -{ - int unit = DCAUNIT(dev); - struct dca_softc *sc; - struct tty *tp; - int error, of; - - sc = dca_cd.cd_devs[unit]; - - tp = sc->sc_tty; - of = sc->sc_oflows; - error = (*linesw[tp->t_line].l_read)(tp, uio, flag); - /* - * XXX hardly a reasonable thing to do, but reporting overflows - * at interrupt time just exacerbates the problem. - */ - if (sc->sc_oflows != of) - log(LOG_WARNING, "%s: silo overflow\n", sc->sc_dev.dv_xname); - return (error); -} - -int -dcawrite(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; -{ - struct dca_softc *sc = dca_cd.cd_devs[DCAUNIT(dev)]; - struct tty *tp = sc->sc_tty; - - return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); -} - -struct tty * -dcatty(dev) - dev_t dev; -{ - struct dca_softc *sc = dca_cd.cd_devs[DCAUNIT(dev)]; - - return (sc->sc_tty); -} - -int -dcaintr(arg) - void *arg; -{ - struct dca_softc *sc = arg; -#ifdef KGDB - int unit = sc->sc_dev.dv_unit; -#endif - struct dcadevice *dca = sc->sc_dca; - struct tty *tp = sc->sc_tty; - u_char code; - int iflowdone = 0; - - /* - * If interrupts aren't enabled, then the interrupt can't - * be for us. - */ - if ((dca->dca_ic & (IC_IR|IC_IE)) != (IC_IR|IC_IE)) - return (0); - - for (;;) { - code = dca->dca_iir; -#ifdef DEBUG - dcaintrcount[code & IIR_IMASK]++; -#endif - - switch (code & IIR_IMASK) { - case IIR_NOPEND: - return (1); - case IIR_RXTOUT: - case IIR_RXRDY: - /* do time-critical read in-line */ -/* - * Process a received byte. Inline for speed... - */ -#ifdef KGDB -#define RCVBYTE() \ - code = dca->dca_data; \ - if (tp != NULL) { \ - if ((tp->t_state & TS_ISOPEN) == 0) { \ - if (code == FRAME_END && \ - kgdb_dev == makedev(dcamajor, unit)) \ - kgdb_connect(0); /* trap into kgdb */ \ - } else \ - (*linesw[tp->t_line].l_rint)(code, tp) \ - } -#else -#define RCVBYTE() \ - code = dca->dca_data; \ - if (tp != NULL && (tp->t_state & TS_ISOPEN) != 0) \ - (*linesw[tp->t_line].l_rint)(code, tp) -#endif - RCVBYTE(); - if (sc->sc_flags & DCA_HASFIFO) { -#ifdef DEBUG - int fifocnt = 1; -#endif - while ((code = dca->dca_lsr) & LSR_RCV_MASK) { - if (code == LSR_RXRDY) { - RCVBYTE(); - } else - dcaeint(sc, code); -#ifdef DEBUG - fifocnt++; -#endif - } -#ifdef DEBUG - if (fifocnt > 16) - fifoin[0]++; - else - fifoin[fifocnt]++; -#endif - } - if (iflowdone == 0 && tp != NULL && - (tp->t_cflag & CRTS_IFLOW) && - tp->t_rawq.c_cc > (TTYHOG(tp) / 2)) { - dca->dca_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 - dcastart(tp); - } - break; - case IIR_RLS: - dcaeint(sc, dca->dca_lsr); - break; - default: - if (code & IIR_NOPEND) - return (1); - log(LOG_WARNING, "%s: weird interrupt: 0x%x\n", - sc->sc_dev.dv_xname, code); - /* FALLTHROUGH */ - case IIR_MLSC: - dcamint(sc); - break; - } - } -} - -void -dcaeint(sc, stat) - struct dca_softc *sc; - int stat; -{ - struct tty *tp = sc->sc_tty; - struct dcadevice *dca = sc->sc_dca; - int c; - - c = dca->dca_data; - -#if defined(DDB) && !defined(KGDB) - if ((sc->sc_flags & DCA_ISCONSOLE) && db_console && (stat & LSR_BI)) { - Debugger(); - return; - } -#endif - - if (tp == NULL) - return; - - if ((tp->t_state & TS_ISOPEN) == 0) { -#ifdef KGDB - /* we don't care about parity errors */ - if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && - kgdb_dev == makedev(dcamajor, sc->sc_hd->hp_unit) && - c == FRAME_END) - kgdb_connect(0); /* trap into kgdb */ -#endif - return; - } - - if (stat & (LSR_BI | LSR_FE)) - c |= TTY_FE; - else if (stat & LSR_PE) - c |= TTY_PE; - else if (stat & LSR_OE) - sc->sc_oflows++; - (*linesw[tp->t_line].l_rint)(c, tp); -} - -void -dcamint(sc) - struct dca_softc *sc; -{ - struct tty *tp = sc->sc_tty; - struct dcadevice *dca = sc->sc_dca; - u_char stat; - - stat = dca->dca_msr; -#ifdef DEBUG - dcamintcount[stat & 0xf]++; -#endif - - if (tp == NULL) - return; - - if ((stat & MSR_DDCD) && - (sc->sc_flags & DCA_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) - dca->dca_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; - dcastart(tp); - } else { - tp->t_state |= TS_TTSTOP; - } - } -} - -int -dcaioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; -{ - int unit = DCAUNIT(dev); - struct dca_softc *sc = dca_cd.cd_devs[unit]; - struct tty *tp = sc->sc_tty; - struct dcadevice *dca = sc->sc_dca; - 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: - dca->dca_cfcr |= CFCR_SBREAK; - break; - - case TIOCCBRK: - dca->dca_cfcr &= ~CFCR_SBREAK; - break; - - case TIOCSDTR: - (void) dcamctl(sc, MCR_DTR | MCR_RTS, DMBIS); - break; - - case TIOCCDTR: - (void) dcamctl(sc, MCR_DTR | MCR_RTS, DMBIC); - break; - - case TIOCMSET: - (void) dcamctl(sc, *(int *)data, DMSET); - break; - - case TIOCMBIS: - (void) dcamctl(sc, *(int *)data, DMBIS); - break; - - case TIOCMBIC: - (void) dcamctl(sc, *(int *)data, DMBIC); - break; - - case TIOCMGET: - *(int *)data = dcamctl(sc, 0, DMGET); - break; - - case TIOCGFLAGS: { - int bits = 0; - - if (sc->sc_flags & DCA_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 & DCA_ISCONSOLE)) - sc->sc_flags |= DCA_SOFTCAR; - - if (userbits & TIOCFLAG_CLOCAL) - tp->t_cflag |= CLOCAL; - - break; - } - - default: - return (ENOTTY); - } - return (0); -} - -int -dcaparam(tp, t) - struct tty *tp; - struct termios *t; -{ - int unit = DCAUNIT(tp->t_dev); - struct dca_softc *sc = dca_cd.cd_devs[unit]; - struct dcadevice *dca = sc->sc_dca; - int cfcr, cflag = t->c_cflag; - int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); - 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 unitialized... */ - 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) dcamctl(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 & DCA_HASFIFO) - dca->dca_fifo = FIFO_ENABLE | - (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : - FIFO_TRIGGER_14); - } - - if (ospeed != 0) { - dca->dca_cfcr |= CFCR_DLAB; - dca->dca_data = ospeed & 0xFF; - dca->dca_ier = ospeed >> 8; - dca->dca_cfcr = cfcr; - } else - dca->dca_cfcr = cfcr; - - /* and copy to tty */ - tp->t_ispeed = t->c_ispeed; - tp->t_ospeed = t->c_ospeed; - tp->t_cflag = cflag; - - dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; - dca->dca_mcr |= MCR_IEN; - - splx(s); - return (0); -} - -void -dcastart(tp) - struct tty *tp; -{ - int s, c, unit = DCAUNIT(tp->t_dev); - struct dca_softc *sc = dca_cd.cd_devs[unit]; - struct dcadevice *dca = sc->sc_dca; - - s = spltty(); - - if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) - goto out; - ttwakeupwr(tp); - if (tp->t_outq.c_cc == 0) - goto out; - if (dca->dca_lsr & LSR_TXRDY) { - tp->t_state |= TS_BUSY; - if (sc->sc_flags & DCA_HASFIFO) { - for (c = 0; c < 16 && tp->t_outq.c_cc; ++c) - dca->dca_data = getc(&tp->t_outq); -#ifdef DEBUG - if (c > 16) - fifoout[0]++; - else - fifoout[c]++; -#endif - } else - dca->dca_data = getc(&tp->t_outq); - } - -out: - splx(s); -} - -/* - * Stop output on a line. - */ -/*ARGSUSED*/ -int -dcastop(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 -dcamctl(sc, bits, how) - struct dca_softc *sc; - int bits, how; -{ - struct dcadevice *dca = sc->sc_dca; - int s; - - /* - * Always make sure MCR_IEN is set (unless setting to 0) - */ -#ifdef KGDB - if (how == DMSET && kgdb_dev == makedev(dcamajor, sc->sc_hd->hp_unit)) - bits |= MCR_IEN; - else -#endif - if (how == DMBIS || (how == DMSET && bits)) - bits |= MCR_IEN; - else if (how == DMBIC) - bits &= ~MCR_IEN; - s = spltty(); - - switch (how) { - case DMSET: - dca->dca_mcr = bits; - break; - - case DMBIS: - dca->dca_mcr |= bits; - break; - - case DMBIC: - dca->dca_mcr &= ~bits; - break; - - case DMGET: - bits = dca->dca_msr; - break; - } - splx(s); - return (bits); -} - -void -dcainit(dca, rate) - struct dcadevice *dca; - int rate; -{ - int s; - short stat; - - s = splhigh(); - - dca->dca_reset = 0xFF; - DELAY(100); - dca->dca_ic = IC_IE; - - dca->dca_cfcr = CFCR_DLAB; - rate = ttspeedtab(rate, dcaspeedtab); - dca->dca_data = rate & 0xFF; - dca->dca_ier = rate >> 8; - dca->dca_cfcr = CFCR_8BITS; - dca->dca_ier = IER_ERXRDY | IER_ETXRDY; - dca->dca_fifo = - FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1; - dca->dca_mcr = MCR_DTR | MCR_RTS; - DELAY(100); - stat = dca->dca_iir; - splx(s); -} - -/* - * Following are all routines needed for DCA to act as console - */ - -int -dca_console_scan(scode, va, arg) - int scode; - caddr_t va; - void *arg; -{ - struct dcadevice *dca = (struct dcadevice *)va; - struct consdev *cp = arg; - u_int pri; - - switch (dca->dca_id) { - case DCAID0: - case DCAID1: - pri = CN_LOWPRI; - break; - - case DCAID0 | DCACON: - case DCAID1 | DCACON: - pri = CN_HIGHPRI; - break; - - default: - return (0); - } - -#ifdef CONSCODE - /* - * Raise our priority, if appropriate. - */ - if (scode == CONSCODE) - pri = CN_FORCED; -#endif - - /* Only raise priority. */ - if (pri > cp->cn_pri) - cp->cn_pri = pri; - - /* - * If our priority is higher than the currently-remembered - * console, stash our priority, for the benefit of dcacninit(). - */ - if (cn_tab == NULL || cp->cn_pri > cn_tab->cn_pri) { - cn_tab = cp; - conscode = scode; - return (DIO_SIZE(scode, va)); - } - return (0); -} - -void -dcacnprobe(cp) - struct consdev *cp; -{ - - /* locate the major number */ - for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) - if (cdevsw[dcamajor].d_open == dcaopen) - break; - - /* initialize required fields */ - cp->cn_dev = makedev(dcamajor, 0); /* XXX */ - - console_scan(dca_console_scan, cp); - -#ifdef KGDB - /* XXX this needs to be fixed. */ - if (major(kgdb_dev) == 1) /* XXX */ - kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); -#endif -} - -/* ARGSUSED */ -void -dcacninit(cp) - struct consdev *cp; -{ - - /* - * We are not interested by the second console pass. - */ - if (consolepass != 0) - return; - - dca_cn = (struct dcadevice *)conaddr; - dcainit(dca_cn, dcadefaultrate); - dcaconsinit = 1; -} - -/* ARGSUSED */ -int -dcacngetc(dev) - dev_t dev; -{ - u_char stat; - int c, s; - - s = splhigh(); - while (((stat = dca_cn->dca_lsr) & LSR_RXRDY) == 0) - ; - c = dca_cn->dca_data; - stat = dca_cn->dca_iir; - splx(s); - return (c); -} - -/* - * Console kernel output character routine. - */ -/* ARGSUSED */ -void -dcacnputc(dev, c) - dev_t dev; - int c; -{ - int timo; - u_char stat; - int s = splhigh(); - - if (dcaconsinit == 0) { - dcainit(dca_cn, dcadefaultrate); - dcaconsinit = 1; - } - /* wait for any pending transmission to finish */ - timo = 50000; - while (((stat = dca_cn->dca_lsr) & LSR_TXRDY) == 0 && --timo) - ; - dca_cn->dca_data = c; - /* wait for this transmission to complete */ - timo = 1500000; - while (((stat = dca_cn->dca_lsr) & LSR_TXRDY) == 0 && --timo) - ; - /* clear any interrupts generated by this transmission */ - stat = dca_cn->dca_iir; - splx(s); -} |