i386 removal, part 29/x: Remove old serial drivers, cy(4) and stl(4).
authorSascha Wildner <saw@online.de>
Mon, 3 Aug 2015 08:16:50 +0000 (10:16 +0200)
committerSascha Wildner <saw@online.de>
Mon, 3 Aug 2015 08:16:50 +0000 (10:16 +0200)
stlstats(8), too.

15 files changed:
Makefile_upgrade.inc
sys/dev/serial/cy/cd1400.h [deleted file]
sys/dev/serial/cy/cy.c [deleted file]
sys/dev/serial/cy/cy_pci.c [deleted file]
sys/dev/serial/cy/cy_pcireg.h [deleted file]
sys/dev/serial/cy/cyreg.h [deleted file]
sys/dev/serial/stl/sc26198.h [deleted file]
sys/dev/serial/stl/scd1400.h [deleted file]
sys/dev/serial/stl/stallion.c [deleted file]
sys/platform/pc64/include/cdk.h [deleted file]
sys/platform/pc64/include/comstats.h [deleted file]
usr.sbin/Makefile
usr.sbin/stlstats/Makefile [deleted file]
usr.sbin/stlstats/stlstats.8 [deleted file]
usr.sbin/stlstats/stlstats.c [deleted file]

index 89738d6..82f723a 100644 (file)
@@ -2161,15 +2161,17 @@ TO_REMOVE+=/usr/share/locale/kk_KZ*
 TO_REMOVE+=/usr/share/locale/UTF-8
 TO_REMOVE+=/usr/sbin/pnpinfo
 TO_REMOVE+=/usr/share/man/man8/pnpinfo.8.gz
-
-.if ${MACHINE_ARCH} == "x86_64"
+TO_REMOVE+=/usr/include/machine/cdk.h
+TO_REMOVE+=/usr/include/machine/comstats.h
 TO_REMOVE+=/usr/sbin/stlstats
 TO_REMOVE+=/usr/share/man/man8/i386/stlstats.8.gz
 TO_REMOVE+=/usr/share/man/man4/i386/stl.4.gz
+TO_REMOVE+=/boot/kernel/pst.ko
+
+.if ${MACHINE_ARCH} == "x86_64"
 TO_REMOVE+=/usr/sbin/kgzip
 TO_REMOVE+=/usr/share/man/man8/kgzip.8.gz
 TO_REMOVE+=/boot/kernel/glxsb.ko
-TO_REMOVE+=/boot/kernel/pst.ko
 .endif
 
 .if !defined(WANT_INSTALLER)
diff --git a/sys/dev/serial/cy/cd1400.h b/sys/dev/serial/cy/cd1400.h
deleted file mode 100644 (file)
index d257b25..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*-
- * cyclades cyclom-y serial driver
- *     Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993
- *
- * Copyright (c) 1993 Andrew Herbert.
- * 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. The name Andrew Herbert may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY ``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 I 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.
- *
- * $FreeBSD: src/sys/i386/isa/ic/cd1400.h,v 1.6 1999/08/28 00:45:12 peter Exp $
- */
-
-/*
- * Definitions for Cirrus Logic CD1400 serial/parallel chips.
- */
-
-#define        CD1400_NO_OF_CHANNELS   4       /* 4 serial channels per chip */
-#define        CD1400_RX_FIFO_SIZE     12
-#define        CD1400_TX_FIFO_SIZE     12
-
-/*
- * Global registers.
- */
-#define        CD1400_GFRCR            0x40    /* global firmware revision code */
-#define        CD1400_CAR              0x68    /* channel access */
-#define        CD1400_CAR_CHAN                 (3<<0)  /* channel select */
-#define        CD1400_GCR              0x4B    /* global configuration */
-#define        CD1400_GCR_PARALLEL             (1<<7)  /* channel 0 is parallel */
-#define        CD1400_SVRR             0x67    /* service request */
-#define        CD1400_SVRR_MDMCH               (1<<2)
-#define        CD1400_SVRR_TXRDY               (1<<1)
-#define        CD1400_SVRR_RXRDY               (1<<0)
-#define        CD1400_RICR             0x44    /* receive interrupting channel */
-#define        CD1400_TICR             0x45    /* transmit interrupting channel */
-#define        CD1400_MICR             0x46    /* modem interrupting channel */
-#define        CD1400_RIR              0x6B    /* receive interrupt status */
-#define        CD1400_RIR_RDIREQ               (1<<7)  /* rx service required */
-#define        CD1400_RIR_RBUSY                (1<<6)  /* rx service in progress */
-#define        CD1400_RIR_CHAN                 (3<<0)  /* channel select */
-#define        CD1400_TIR              0x6A    /* transmit interrupt status */
-#define        CD1400_TIR_RDIREQ               (1<<7)  /* tx service required */
-#define        CD1400_TIR_RBUSY                (1<<6)  /* tx service in progress */
-#define        CD1400_TIR_CHAN                 (3<<0)  /* channel select */
-#define        CD1400_MIR              0x69    /* modem interrupt status */
-#define        CD1400_MIR_RDIREQ               (1<<7)  /* modem service required */
-#define        CD1400_MIR_RBUSY                (1<<6)  /* modem service in progress */
-#define        CD1400_MIR_CHAN                 (3<<0)  /* channel select */
-#define        CD1400_PPR              0x7E    /* prescaler period */
-#define        CD1400_PPR_PRESCALER            512
-
-/*
- * Virtual registers.
- */
-#define        CD1400_RIVR             0x43    /* receive interrupt vector */
-#define        CD1400_RIVR_EXCEPTION           (1<<2)  /* receive exception bit */
-#define        CD1400_TIVR             0x42    /* transmit interrupt vector */
-#define        CD1400_MIVR             0x41    /* modem interrupt vector */
-#define        CD1400_TDR              0x63    /* transmit data */
-#define        CD1400_RDSR             0x62    /* receive data/status */
-#define        CD1400_RDSR_TIMEOUT             (1<<7)  /* rx timeout */
-#define        CD1400_RDSR_SPECIAL_SHIFT       4       /* rx special char shift */
-#define        CD1400_RDSR_SPECIAL             (7<<4)  /* rx special char */
-#define        CD1400_RDSR_BREAK               (1<<3)  /* rx break */
-#define        CD1400_RDSR_PE                  (1<<2)  /* rx parity error */
-#define        CD1400_RDSR_FE                  (1<<1)  /* rx framing error */
-#define        CD1400_RDSR_OE                  (1<<0)  /* rx overrun error */
-#define        CD1400_MISR             0x4C    /* modem interrupt status */
-#define        CD1400_MISR_DSRd                (1<<7)  /* DSR delta */
-#define        CD1400_MISR_CTSd                (1<<6)  /* CTS delta */
-#define        CD1400_MISR_RId                 (1<<5)  /* RI delta */
-#define        CD1400_MISR_CDd                 (1<<4)  /* CD delta */
-#define        CD1400_EOSRR            0x60    /* end of service request */
-
-/*
- * Channel registers.
- */
-#define        CD1400_LIVR             0x18    /* local interrupt vector */
-#define        CD1400_CCR              0x05    /* channel control */
-#define        CD1400_CCR_CMDRESET             (1<<7)  /* enables following: */
-#define        CD1400_CCR_FTF                          (1<<1)  /* flush tx fifo */
-#define        CD1400_CCR_FULLRESET                    (1<<0)  /* full reset */
-#define        CD1400_CCR_CHANRESET                    0       /*  current channel */
-#define        CD1400_CCR_CMDCORCHG            (1<<6)  /* enables following: */
-#define        CD1400_CCR_COR3                         (1<<3)  /* COR3 changed */
-#define        CD1400_CCR_COR2                         (1<<2)  /* COR2 changed */
-#define        CD1400_CCR_COR1                         (1<<1)  /* COR1 changed */
-#define        CD1400_CCR_CMDSENDSC            (1<<5)  /* enables following: */
-#define        CD1400_CCR_SC                           (7<<0)  /* special char 1-4 */
-#define        CD1400_CCR_CMDCHANCTL           (1<<4)  /* enables following: */
-#define        CD1400_CCR_XMTEN                        (1<<3)  /* tx enable */
-#define        CD1400_CCR_XMTDIS                       (1<<2)  /* tx disable */
-#define        CD1400_CCR_RCVEN                        (1<<1)  /* rx enable */
-#define        CD1400_CCR_RCVDIS                       (1<<0)  /* rx disable */
-#define        CD1400_SRER             0x06    /* service request enable */
-#define        CD1400_SRER_MDMCH               (1<<7)  /* modem change */
-#define        CD1400_SRER_RXDATA              (1<<4)  /* rx data */
-#define        CD1400_SRER_TXRDY               (1<<2)  /* tx fifo empty */
-#define        CD1400_SRER_TXMPTY              (1<<1)  /* tx shift reg empty */
-#define        CD1400_SRER_NNDT                (1<<0)  /* no new data */
-#define        CD1400_COR1             0x08    /* channel option 1 */
-#define        CD1400_COR1_PARODD              (1<<7)
-#define        CD1400_COR1_PARNORMAL           (2<<5)
-#define        CD1400_COR1_PARFORCE            (1<<5)  /* odd/even = force 1/0 */
-#define        CD1400_COR1_PARNONE             (0<<5)
-#define        CD1400_COR1_NOINPCK             (1<<4)
-#define        CD1400_COR1_STOP2               (2<<2)
-#define        CD1400_COR1_STOP15              (1<<2)  /* 1.5 stop bits */
-#define        CD1400_COR1_STOP1               (0<<2)
-#define        CD1400_COR1_CS8                 (3<<0)
-#define        CD1400_COR1_CS7                 (2<<0)
-#define        CD1400_COR1_CS6                 (1<<0)
-#define        CD1400_COR1_CS5                 (0<<0)
-#define        CD1400_COR2             0x09    /* channel option 2 */
-#define        CD1400_COR2_IXANY               (1<<7)  /* implied XON mode */
-#define        CD1400_COR2_IXOFF               (1<<6)  /* in-band tx flow control */
-#define        CD1400_COR2_ETC                 (1<<5)  /* embedded tx command */
-#define        CD1400_ETC_CMD                          0x00    /* start an ETC */
-#define        CD1400_ETC_SENDBREAK                    0x81
-#define        CD1400_ETC_INSERTDELAY                  0x82
-#define        CD1400_ETC_STOPBREAK                    0x83
-#define        CD1400_COR2_LLM                 (1<<4)  /* local loopback mode */
-#define        CD1400_COR2_RLM                 (1<<3)  /* remote loopback mode */
-#define        CD1400_COR2_RTSAO               (1<<2)  /* RTS auto output */
-#define        CD1400_COR2_CCTS_OFLOW          (1<<1)  /* CTS auto enable */
-#define        CD1400_COR2_CDSR_OFLOW          (1<<0)  /* DSR auto enable */
-#define        CD1400_COR3             0x0A    /* channel option 3 */
-#define        CD1400_COR3_SCDRNG              (1<<7)  /* special char detect range */
-#define        CD1400_COR3_SCD34               (1<<6)  /* special char detect 3-4 */
-#define        CD1400_COR3_FTC                 (1<<5)  /* flow control transparency */
-#define        CD1400_COR3_SCD12               (1<<4)  /* special char detect 1-2 */
-#define        CD1400_COR3_RXTH                (15<<0) /* rx fifo threshold */
-#define        CD1400_COR4             0x1E    /* channel option 4 */
-#define        CD1400_COR4_IGNCR               (1<<7)
-#define        CD1400_COR4_ICRNL               (1<<6)
-#define        CD1400_COR4_INLCR               (1<<5)
-#define        CD1400_COR4_IGNBRK              (1<<4)
-#define        CD1400_COR4_NOBRKINT            (1<<3)
-#define        CD1400_COR4_PFO_ESC             (4<<0)  /* parity/framing/overrun... */
-#define        CD1400_COR4_PFO_NUL             (3<<0)
-#define        CD1400_COR4_PFO_DISCARD         (2<<0)
-#define        CD1400_COR4_PFO_GOOD            (1<<0)
-#define        CD1400_COR4_PFO_EXCEPTION       (0<<0)
-#define        CD1400_COR5             0x1F    /* channel option 5 */
-#define        CD1400_COR5_ISTRIP              (1<<7)
-#define        CD1400_COR5_LNEXT               (1<<6)
-#define        CD1400_COR5_CMOE                (1<<5)  /* char matching on error */
-#define        CD1400_COR5_EBD                 (1<<2)  /* end of break detected */
-#define        CD1400_COR5_ONLCR               (1<<1)
-#define        CD1400_COR5_OCRNL               (1<<0)
-#define        CD1400_CCSR             0x0B    /* channel control status */
-#define        CD1400_RDCR             0x0E    /* received data count */
-#define        CD1400_SCHR1            0x1A    /* special character 1 */
-#define        CD1400_SCHR2            0x1B    /* special character 2 */
-#define        CD1400_SCHR3            0x1C    /* special character 3 */
-#define        CD1400_SCHR4            0x1D    /* special character 4 */
-#define        CD1400_SCRL             0x22    /* special character range, low */
-#define        CD1400_SCRH             0x23    /* special character range, high */
-#define        CD1400_LNC              0x24    /* lnext character */
-#define        CD1400_MCOR1            0x15    /* modem change option 1 */
-#define        CD1400_MCOR1_DSRzd              (1<<7)  /* DSR one-to-zero delta */
-#define        CD1400_MCOR1_CTSzd              (1<<6)
-#define        CD1400_MCOR1_RIzd               (1<<5)
-#define        CD1400_MCOR1_CDzd               (1<<4)
-#define        CD1400_MCOR1_DTRth              (15<<0) /* dtrflow threshold */
-#define        CD1400_MCOR2            0x16    /* modem change option 2 */
-#define        CD1400_MCOR2_DSRod              (1<<7)  /* DSR zero-to-one delta */
-#define        CD1400_MCOR2_CTSod              (1<<6)
-#define        CD1400_MCOR2_RIod               (1<<5)
-#define        CD1400_MCOR2_CDod               (1<<4)
-#define        CD1400_RTPR             0x21    /* receive timeout period */
-#define        CD1400_MSVR1            0x6C    /* modem signal value 1 */
-#define        CD1400_MSVR1_RTS                (1<<0)  /* RTS line (r/w) */
-#define        CD1400_MSVR2            0x6D    /* modem signal value 2 */
-#define        CD1400_MSVR2_DSR                (1<<7)  /* !DSR line (r) */
-#define        CD1400_MSVR2_CTS                (1<<6)  /* !CTS line (r) */
-#define        CD1400_MSVR2_RI                 (1<<5)  /* !RI line (r) */
-#define        CD1400_MSVR2_CD                 (1<<4)  /* !CD line (r) */
-#define        CD1400_MSVR2_DTR                (1<<1)  /* DTR line (r/w) */
-#define        CD1400_PSVR             0x6F    /* printer signal value */
-#define        CD1400_RBPR             0x78    /* receive baud rate period */
-#define        CD1400_RCOR             0x7C    /* receive clock option */
-#define        CD1400_TBPR             0x72    /* transmit baud rate period */
-#define        CD1400_TCOR             0x76    /* transmit clock option */
diff --git a/sys/dev/serial/cy/cy.c b/sys/dev/serial/cy/cy.c
deleted file mode 100644 (file)
index 95465fb..0000000
+++ /dev/null
@@ -1,2886 +0,0 @@
-/*-
- * (MPSAFE)
- *
- * cyclades cyclom-y serial driver
- *     Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993
- *
- * Copyright (c) 1993 Andrew Herbert.
- * 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. The name Andrew Herbert may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY ``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 I 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.
- *
- * $FreeBSD: src/sys/i386/isa/cy.c,v 1.97.2.2 2001/08/22 13:04:58 bde Exp $
- */
-
-#include "opt_compat.h"
-#include "use_cy.h"
-
-/*
- * TODO:
- * Atomic COR change.
- * Consoles.
- */
-
-/*
- * Temporary compile-time configuration options.
- */
-#define        RxFifoThreshold (CD1400_RX_FIFO_SIZE / 2)
-                       /* Number of chars in the receiver FIFO before an
-                        * an interrupt is generated.  Should depend on
-                        * line speed.  Needs to be about 6 on a 486DX33
-                        * for 4 active ports at 115200 bps.  Why doesn't
-                        * 10 work?
-                        */
-#define        PollMode        /* Use polling-based irq service routine, not the
-                        * hardware svcack lines.  Must be defined for
-                        * Cyclom-16Y boards.  Less efficient for Cyclom-8Ys,
-                        * and stops 4 * 115200 bps from working.
-                        */
-#undef Smarts          /* Enable slightly more CD1400 intelligence.  Mainly
-                        * the output CR/LF processing, plus we can avoid a
-                        * few checks usually done in ttyinput().
-                        *
-                        * XXX not fully implemented, and not particularly
-                        * worthwhile.
-                        */
-#undef CyDebug         /* Include debugging code (not very expensive). */
-
-/* These will go away. */
-#undef SOFT_CTS_OFLOW
-#define        SOFT_HOTCHAR
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/tty.h>
-#include <sys/proc.h>
-#include <sys/priv.h>
-#include <sys/conf.h>
-#include <sys/dkstat.h>
-#include <sys/fcntl.h>
-#include <sys/interrupt.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/syslog.h>
-#include <sys/thread2.h>
-#include <machine/clock.h>
-#include <machine/psl.h>
-
-#include "cyreg.h"
-#include "cd1400.h"
-
-#define disable_intr() com_lock()
-#define enable_intr()  com_unlock()
-
-/*
- * Dictionary so that I can name everything *sio* or *com* to compare with
- * sio.c.  There is also lots of ugly formatting and unnecessary ifdefs to
- * simplify the comparision.  These will go away.
- */
-#define        LSR_BI          CD1400_RDSR_BREAK
-#define        LSR_FE          CD1400_RDSR_FE
-#define        LSR_OE          CD1400_RDSR_OE
-#define        LSR_PE          CD1400_RDSR_PE
-#define        MCR_DTR         CD1400_MSVR2_DTR
-#define        MCR_RTS         CD1400_MSVR1_RTS
-#define        MSR_CTS         CD1400_MSVR2_CTS
-#define        MSR_DCD         CD1400_MSVR2_CD
-#define        MSR_DSR         CD1400_MSVR2_DSR
-#define        MSR_RI          CD1400_MSVR2_RI
-#define        NSIO            (NCY * CY_MAX_PORTS)
-#define        comconsole      cyconsole
-#define        comdefaultrate  cydefaultrate
-#define        com_events      cy_events
-#define        comhardclose    cyhardclose
-#define        commctl         cymctl
-#define        comparam        cyparam
-#define        comspeed        cyspeed
-#define        comstart        cystart
-#define        comwakeup       cywakeup
-#define        nsio_tty        ncy_tty
-#define        p_com_addr      p_cy_addr
-#define        sioattach       cyattach
-#define        sioclose        cyclose
-#define        siodriver       cydriver
-#define        siodtrwakeup    cydtrwakeup
-#define        sioinput        cyinput
-#define        siointr         cyintr
-#define        siointr1        cyintr1
-#define        sioioctl        cyioctl
-#define        sioopen         cyopen
-#define        siopoll         cypoll
-#define        sioprobe        cyprobe
-#define        siosettimeout   cysettimeout
-#define        siosetwater     cysetwater
-#define        comstop         cystop
-#define        siowrite        cywrite
-#define        sio_registered  cy_registered
-#define        sio_timeout     cy_timeout
-#define        sio_timeout_handle cy_timeout_handle
-#define        sio_timeouts_until_log  cy_timeouts_until_log
-#define        sio_tty         cy_tty
-
-#define        CY_MAX_PORTS            (CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s)
-
-/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */
-#define        CD1400_xIVR_CHAN_SHIFT  3
-#define        CD1400_xIVR_CHAN        0x1F
-
-/*
- * ETC states.  com->etc may also contain a hardware ETC command value,
- * meaning that execution of that command is pending.
- */
-#define        ETC_NONE                0       /* we depend on bzero() setting this */
-#define        ETC_BREAK_STARTING      1
-#define        ETC_BREAK_STARTED       2
-#define        ETC_BREAK_ENDING        3
-#define        ETC_BREAK_ENDED         4
-
-#define        LOTS_OF_EVENTS  64      /* helps separate urgent events from input */
-
-#define        CALLOUT_MASK            0x80
-#define        CONTROL_MASK            0x60
-#define        CONTROL_INIT_STATE      0x20
-#define        CONTROL_LOCK_STATE      0x40
-#define        DEV_TO_UNIT(dev)        (MINOR_TO_UNIT(minor(dev)))
-#define        MINOR_MAGIC_MASK        (CALLOUT_MASK | CONTROL_MASK)
-/*
- * Not all of the magic is parametrized in the following macros.  16 and
- * 0xff are related to the bitfields in a udev_t.  CY_MAX_PORTS must be
- * ((0xff & ~MINOR_MAGIC_MASK) + 1) for things to work.
- */
-#define        MINOR_TO_UNIT(mynor)    (((mynor) >> 16) * CY_MAX_PORTS \
-                                | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK))
-#define        UNIT_TO_MINOR(unit)     (((unit) / CY_MAX_PORTS) << 16 \
-                                | (((unit) & 0xff) & ~MINOR_MAGIC_MASK))
-
-/*
- * com state bits.
- * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
- * than the other bits so that they can be tested as a group without masking
- * off the low bits.
- *
- * The following com and tty flags correspond closely:
- *     CS_BUSY         = TS_BUSY (maintained by comstart(), siopoll() and
- *                                comstop())
- *     CS_TTGO         = ~TS_TTSTOP (maintained by comparam() and comstart())
- *     CS_CTS_OFLOW    = CCTS_OFLOW (maintained by comparam())
- *     CS_RTS_IFLOW    = CRTS_IFLOW (maintained by comparam())
- * TS_FLUSH is not used.
- * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
- * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
- */
-#define        CS_BUSY         0x80    /* output in progress */
-#define        CS_TTGO         0x40    /* output not stopped by XOFF */
-#define        CS_ODEVREADY    0x20    /* external device h/w ready (CTS) */
-#define        CS_CHECKMSR     1       /* check of MSR scheduled */
-#define        CS_CTS_OFLOW    2       /* use CTS output flow control */
-#define        CS_DTR_OFF      0x10    /* DTR held off */
-#define        CS_ODONE        4       /* output completed */
-#define        CS_RTS_IFLOW    8       /* use RTS input flow control */
-#define        CSE_ODONE       1       /* output transmitted */
-
-static char const * const      error_desc[] = {
-#define        CE_OVERRUN                      0
-       "silo overflow",
-#define        CE_INTERRUPT_BUF_OVERFLOW       1
-       "interrupt-level buffer overflow",
-#define        CE_TTY_BUF_OVERFLOW             2
-       "tty-level buffer overflow",
-};
-
-#define        CE_NTYPES                       3
-#define        CE_RECORD(com, errnum)          (++(com)->delta_error_counts[errnum])
-
-/* types.  XXX - should be elsewhere */
-typedef u_char bool_t;         /* boolean */
-typedef u_char volatile *cy_addr;
-
-/* queue of linear buffers */
-struct lbq {
-       u_char  *l_head;        /* next char to process */
-       u_char  *l_tail;        /* one past the last char to process */
-       struct lbq *l_next;     /* next in queue */
-       bool_t  l_queued;       /* nonzero if queued */
-};
-
-/* com device structure */
-struct com_s {
-       u_char  state;          /* miscellaneous flag bits */
-       bool_t  active_out;     /* nonzero if the callout device is open */
-#if 0
-       u_char  cfcr_image;     /* copy of value written to CFCR */
-#endif
-       u_char  etc;            /* pending Embedded Transmit Command */
-       u_char  extra_state;    /* more flag bits, separate for order trick */
-#if 0
-       u_char  fifo_image;     /* copy of value written to FIFO */
-#endif
-       u_char  gfrcr_image;    /* copy of value read from GFRCR */
-#if 0
-       bool_t  hasfifo;        /* nonzero for 16550 UARTs */
-       bool_t  loses_outints;  /* nonzero if device loses output interrupts */
-#endif
-       u_char  mcr_dtr;        /* MCR bit that is wired to DTR */
-       u_char  mcr_image;      /* copy of value written to MCR */
-       u_char  mcr_rts;        /* MCR bit that is wired to RTS */
-#if 0
-#ifdef COM_MULTIPORT
-       bool_t  multiport;      /* is this unit part of a multiport device? */
-#endif /* COM_MULTIPORT */
-       bool_t  no_irq;         /* nonzero if irq is not attached */
-       bool_t  poll;           /* nonzero if polling is required */
-       bool_t  poll_output;    /* nonzero if polling for output is required */
-#endif
-       int     unit;           /* unit number */
-       int     dtr_wait;       /* time to hold DTR down on close (* 1/hz) */
-       struct callout dtr_ch;
-#if 0
-       u_int   tx_fifo_size;
-#endif
-       u_int   wopeners;       /* # processes waiting for DCD in open() */
-
-       /*
-        * The high level of the driver never reads status registers directly
-        * because there would be too many side effects to handle conveniently.
-        * Instead, it reads copies of the registers stored here by the
-        * interrupt handler.
-        */
-       u_char  last_modem_status;      /* last MSR read by intr handler */
-       u_char  prev_modem_status;      /* last MSR handled by high level */
-
-       u_char  hotchar;        /* ldisc-specific char to be handled ASAP */
-       u_char  *ibuf;          /* start of input buffer */
-       u_char  *ibufend;       /* end of input buffer */
-       u_char  *ibufold;       /* old input buffer, to be freed */
-       u_char  *ihighwater;    /* threshold in input buffer */
-       u_char  *iptr;          /* next free spot in input buffer */
-       int     ibufsize;       /* size of ibuf (not include error bytes) */
-       int     ierroff;        /* offset of error bytes in ibuf */
-
-       struct lbq      obufq;  /* head of queue of output buffers */
-       struct lbq      obufs[2];       /* output buffers */
-
-       int     cy_align;       /* index for register alignment */
-       cy_addr cy_iobase;      /* base address of this port's cyclom */
-       cy_addr iobase;         /* base address of this port's cd1400 */
-       int     mcr_rts_reg;    /* cd1400 reg number of reg holding mcr_rts */
-
-       struct tty      *tp;    /* cross reference */
-
-       /* Initial state. */
-       struct termios  it_in;  /* should be in struct tty */
-       struct termios  it_out;
-
-       /* Lock state. */
-       struct termios  lt_in;  /* should be in struct tty */
-       struct termios  lt_out;
-
-       bool_t  do_timestamp;
-       bool_t  do_dcd_timestamp;
-       struct timeval  timestamp;
-       struct timeval  dcd_timestamp;
-
-       u_long  bytes_in;       /* statistics */
-       u_long  bytes_out;
-       u_int   delta_error_counts[CE_NTYPES];
-       u_long  error_counts[CE_NTYPES];
-
-       u_int   recv_exception; /* exception chars received */
-       u_int   mdm;            /* modem signal changes */
-#ifdef CyDebug
-       u_int   start_count;    /* no. of calls to comstart() */
-       u_int   start_real;     /* no. of calls that did something */
-#endif
-       u_char  car;            /* CD1400 CAR shadow (if first unit in cd) */
-       u_char  channel_control;/* CD1400 CCR control command shadow */
-       u_char  cor[3];         /* CD1400 COR1-3 shadows */
-       u_char  intr_enable;    /* CD1400 SRER shadow */
-
-       /*
-        * Data area for output buffers.  Someday we should build the output
-        * buffer queue without copying data.
-        */
-       u_char  obuf1[256];
-       u_char  obuf2[256];
-};
-
-/* PCI driver entry point. */
-int    cyattach_common         (cy_addr cy_iobase, int cy_align);
-void   siointr(void *);
-
-static int     cy_units        (cy_addr cy_iobase, int cy_align);
-static void    cd1400_channel_cmd (struct com_s *com, int cmd);
-static void    cd1400_channel_cmd_wait (struct com_s *com);
-static void    cd_etc          (struct com_s *com, int etc);
-static int     cd_getreg       (struct com_s *com, int reg);
-static void    cd_setreg       (struct com_s *com, int reg, int val);
-static timeout_t siodtrwakeup;
-static void    comhardclose    (struct com_s *com);
-static void    sioinput        (struct com_s *com);
-#if 0
-static void    siointr1        (struct com_s *com);
-#endif
-static int     commctl         (struct com_s *com, int bits, int how);
-static int     comparam        (struct tty *tp, struct termios *t);
-static inthand2_t siopoll;
-static void    siosettimeout   (void);
-static int     siosetwater     (struct com_s *com, speed_t speed);
-static int     comspeed        (speed_t speed, u_long cy_clock,
-                                    int *prescaler_io);
-static void    comstart        (struct tty *tp);
-static void    comstop         (struct tty *tp, int rw);
-static timeout_t comwakeup;
-static void    disc_optim      (struct tty     *tp, struct termios *t,
-                                    struct com_s *com);
-
-#ifdef CyDebug
-void   cystatus        (int unit);
-#endif
-
-static char driver_name[] = "cy";
-
-/* table and macro for fast conversion from a unit number to its com struct */
-static struct com_s    *p_com_addr[NSIO];
-#define        com_addr(unit)  (p_com_addr[unit])
-
-static d_open_t        sioopen;
-static d_close_t       sioclose;
-static d_write_t       siowrite;
-static d_ioctl_t       sioioctl;
-
-static struct dev_ops sio_ops = {
-       { driver_name, 0, D_TTY },
-       .d_open =       sioopen,
-       .d_close =      sioclose,
-       .d_read =       ttyread,
-       .d_write =      siowrite,
-       .d_ioctl =      sioioctl,
-       .d_kqfilter =   ttykqfilter,
-       .d_revoke =     ttyrevoke
-};
-
-static int     comconsole = -1;
-static speed_t comdefaultrate = TTYDEF_SPEED;
-static u_int   com_events;     /* input chars + weighted output completions */
-static bool_t  sio_registered;
-static int     sio_timeout;
-static int     sio_timeouts_until_log;
-static struct  callout sio_timeout_handle;
-#if 0 /* XXX */
-static struct tty      *sio_tty[NSIO];
-#else
-static struct tty      sio_tty[NSIO];
-#endif
-static const int       nsio_tty = NSIO;
-
-#ifdef CyDebug
-static u_int   cd_inbs;
-static u_int   cy_inbs;
-static u_int   cd_outbs;
-static u_int   cy_outbs;
-static u_int   cy_svrr_probes;
-static u_int   cy_timeouts;
-#endif
-
-static int     cy_chip_offset[] = {
-       0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00,
-};
-static int     cy_nr_cd1400s[NCY];
-static int     cy_total_devices;
-#undef RxFifoThreshold
-static int     volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2);
-
-static int
-cy_units(cy_addr cy_iobase, int cy_align)
-{
-       int     cyu;
-       u_char  firmware_version = 0;  /* assign to avoid warning */
-       int     i;
-       cy_addr iobase;
-
-       for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) {
-               iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align);
-
-               /* wait for chip to become ready for new command */
-               for (i = 0; i < 10; i++) {
-                       DELAY(50);
-                       if (!cd_inb(iobase, CD1400_CCR, cy_align))
-                               break;
-               }
-
-               /* clear the GFRCR register */
-               cd_outb(iobase, CD1400_GFRCR, cy_align, 0);
-
-               /* issue a reset command */
-               cd_outb(iobase, CD1400_CCR, cy_align,
-                       CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
-
-               /* wait for the CD1400 to initialize itself */
-               for (i = 0; i < 200; i++) {
-                       DELAY(50);
-
-                       /* retrieve firmware version */
-                       firmware_version = cd_inb(iobase, CD1400_GFRCR,
-                                                 cy_align);
-                       if ((firmware_version & 0xf0) == 0x40)
-                               break;
-               }
-
-               /*
-                * Anything in the 0x40-0x4F range is fine.
-                * If one CD1400 is bad then we don't support higher
-                * numbered good ones on this board.
-                */
-               if ((firmware_version & 0xf0) != 0x40)
-                       break;
-       }
-       return (cyu);
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-int
-cyattach_common(cy_addr cy_iobase, int cy_align)
-{
-       int     adapter;
-       int     cyu;
-       u_char  firmware_version;
-       cy_addr iobase;
-       int     minorbase;
-       int     ncyu;
-       int     unit;
-
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-
-       adapter = cy_total_devices;
-       if ((u_int)adapter >= NCY) {
-               kprintf(
-       "cy%d: can't attach adapter: insufficient cy devices configured\n",
-                      adapter);
-               return (-1);
-       }
-       ncyu = cy_units(cy_iobase, cy_align);
-       if (ncyu == 0)
-               return (-1);
-       cy_nr_cd1400s[adapter] = ncyu;
-       cy_total_devices++;
-
-       unit = adapter * CY_MAX_PORTS;
-       for (cyu = 0; cyu < ncyu; ++cyu) {
-               int     cdu;
-
-               iobase = (cy_addr) (cy_iobase
-                                   + (cy_chip_offset[cyu] << cy_align));
-               firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align);
-
-               /* Set up a receive timeout period of than 1+ ms. */
-               cd_outb(iobase, CD1400_PPR, cy_align,
-                       howmany(CY_CLOCK(firmware_version)
-                               / CD1400_PPR_PRESCALER, 1000));
-
-               for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) {
-                       struct com_s    *com;
-
-       com = kmalloc(sizeof *com, M_DEVBUF, M_WAITOK | M_ZERO);
-       com->unit = unit;
-                       callout_init_mp(&com->dtr_ch);
-                       com->gfrcr_image = firmware_version;
-                       if (CY_RTS_DTR_SWAPPED(firmware_version)) {
-                               com->mcr_dtr = MCR_RTS;
-                               com->mcr_rts = MCR_DTR;
-                               com->mcr_rts_reg = CD1400_MSVR2;
-                       } else {
-                               com->mcr_dtr = MCR_DTR;
-                               com->mcr_rts = MCR_RTS;
-                               com->mcr_rts_reg = CD1400_MSVR1;
-                       }
-       com->dtr_wait = 3 * hz;
-       com->obufs[0].l_head = com->obuf1;
-       com->obufs[1].l_head = com->obuf2;
-
-                       com->cy_align = cy_align;
-                       com->cy_iobase = cy_iobase;
-       com->iobase = iobase;
-                       com->car = ~CD1400_CAR_CHAN;
-
-       /*
-        * We don't use all the flags from <sys/ttydefaults.h> since they
-        * are only relevant for logins.  It's important to have echo off
-        * initially so that the line doesn't start blathering before the
-        * echo flag can be turned off.
-        */
-       com->it_in.c_iflag = 0;
-       com->it_in.c_oflag = 0;
-       com->it_in.c_cflag = TTYDEF_CFLAG;
-       com->it_in.c_lflag = 0;
-       if (unit == comconsole) {
-               com->it_in.c_iflag = TTYDEF_IFLAG;
-               com->it_in.c_oflag = TTYDEF_OFLAG;
-               com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
-               com->it_in.c_lflag = TTYDEF_LFLAG;
-               com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
-       }
-       if (siosetwater(com, com->it_in.c_ispeed) != 0) {
-               enable_intr();
-               kfree(com, M_DEVBUF);
-               return (0);
-       }
-       enable_intr();
-       termioschars(&com->it_in);
-       com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
-       com->it_out = com->it_in;
-
-       crit_enter();
-       com_addr(unit) = com;
-       crit_exit();
-
-       if (!sio_registered) {
-               callout_init_mp(&sio_timeout_handle);
-               register_swi_mp(SWI_TTY, siopoll, NULL, "cy", NULL, -1);
-               sio_registered = TRUE;
-       }
-       minorbase = UNIT_TO_MINOR(unit);
-       make_dev(&sio_ops, minorbase,
-               UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter,
-               unit % CY_MAX_PORTS);
-       make_dev(&sio_ops, minorbase | CONTROL_INIT_STATE,
-               UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter,
-               unit % CY_MAX_PORTS);
-       make_dev(&sio_ops, minorbase | CONTROL_LOCK_STATE,
-               UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter,
-               unit % CY_MAX_PORTS);
-       make_dev(&sio_ops, minorbase | CALLOUT_MASK,
-               UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter,
-               unit % CY_MAX_PORTS);
-       make_dev(&sio_ops, minorbase | CALLOUT_MASK | CONTROL_INIT_STATE,
-               UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter,
-               unit % CY_MAX_PORTS);
-       make_dev(&sio_ops, minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE,
-               UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter,
-               unit % CY_MAX_PORTS);
-
-       /* for(cdu...), for(cyu...) terminating blocks */
-               }
-       }
-
-       /* ensure an edge for the next interrupt */
-       cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
-
-       return (adapter);
-}
-
-static int
-sioopen(struct dev_open_args *ap)
-{
-       cdev_t dev = ap->a_head.a_dev;
-       struct com_s    *com;
-       int             error;
-       int             mynor;
-       struct tty      *tp;
-       int             unit;
-
-       mynor = minor(dev);
-       unit = MINOR_TO_UNIT(mynor);
-       if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
-               return (ENXIO);
-       if (mynor & CONTROL_MASK)
-               return (0);
-
-       lwkt_gettoken(&tty_token);
-#if 0 /* XXX */
-       tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]);
-#else
-       tp = com->tp = &sio_tty[unit];
-#endif
-       dev->si_tty = tp;
-       crit_enter();
-       /*
-        * We jump to this label after all non-interrupted sleeps to pick
-        * up any changes of the device state.
-        */
-open_top:
-       while (com->state & CS_DTR_OFF) {
-               error = tsleep(&com->dtr_wait, PCATCH, "cydtr", 0);
-               if (error != 0)
-                       goto out;
-       }
-       if (tp->t_state & TS_ISOPEN) {
-               /*
-                * The device is open, so everything has been initialized.
-                * Handle conflicts.
-                */
-               if (mynor & CALLOUT_MASK) {
-                       if (!com->active_out) {
-                               error = EBUSY;
-                               goto out;
-                       }
-               } else {
-                       if (com->active_out) {
-                               if (ap->a_oflags & O_NONBLOCK) {
-                                       error = EBUSY;
-                                       goto out;
-                               }
-                               error = tsleep(&com->active_out,
-                                              PCATCH, "cybi", 0);
-                               if (error != 0)
-                                       goto out;
-                               goto open_top;
-                       }
-               }
-               if (tp->t_state & TS_XCLUDE &&
-                   priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) {
-                       error = EBUSY;
-                       goto out;
-               }
-       } else {
-               /*
-                * The device isn't open, so there are no conflicts.
-                * Initialize it.  Initialization is done twice in many
-                * cases: to preempt sleeping callin opens if we are
-                * callout, and to complete a callin open after DCD rises.
-                */
-               tp->t_oproc = comstart;
-               tp->t_stop = comstop;
-               tp->t_param = comparam;
-               tp->t_dev = dev;
-               tp->t_termios = mynor & CALLOUT_MASK
-                               ? com->it_out : com->it_in;
-
-               /* Encode per-board unit in LIVR for access in intr routines. */
-               cd_setreg(com, CD1400_LIVR,
-                         (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT);
-
-               (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
-#if 0
-               com->poll = com->no_irq;
-               com->poll_output = com->loses_outints;
-#endif
-               ++com->wopeners;
-               error = comparam(tp, &tp->t_termios);
-               --com->wopeners;
-               if (error != 0)
-                       goto out;
-#if 0
-               if (com->hasfifo) {
-                       /*
-                        * (Re)enable and flush fifos.
-                        *
-                        * Certain SMC chips cause problems if the fifos
-                        * are enabled while input is ready.  Turn off the
-                        * fifo if necessary to clear the input.  We test
-                        * the input ready bit after enabling the fifos
-                        * since we've already enabled them in comparam()
-                        * and to handle races between enabling and fresh
-                        * input.
-                        */
-                       while (TRUE) {
-                               outb(iobase + com_fifo,
-                                    FIFO_RCV_RST | FIFO_XMT_RST
-                                    | com->fifo_image);
-                               DELAY(100);
-                               if (!(inb(com->line_status_port) & LSR_RXRDY))
-                                       break;
-                               outb(iobase + com_fifo, 0);
-                               DELAY(100);
-                               (void) inb(com->data_port);
-                       }
-               }
-
-               disable_intr();
-               (void) inb(com->line_status_port);
-               (void) inb(com->data_port);
-               com->prev_modem_status = com->last_modem_status
-                   = inb(com->modem_status_port);
-               outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS
-                                      | IER_EMSC);
-               enable_intr();
-#else /* !0 */
-               /*
-                * Flush fifos.  This requires a full channel reset which
-                * also disables the transmitter and receiver.  Recover
-                * from this.
-                */
-               cd1400_channel_cmd(com,
-                                  CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET);
-               cd1400_channel_cmd(com, com->channel_control);
-
-               disable_intr();
-               com->prev_modem_status = com->last_modem_status
-                   = cd_getreg(com, CD1400_MSVR2);
-               cd_setreg(com, CD1400_SRER,
-                         com->intr_enable
-                         = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
-               enable_intr();
-#endif /* 0 */
-               /*
-                * Handle initial DCD.  Callout devices get a fake initial
-                * DCD (trapdoor DCD).  If we are callout, then any sleeping
-                * callin opens get woken up and resume sleeping on "cybi"
-                * instead of "cydcd".
-                */
-               /*
-                * XXX `mynor & CALLOUT_MASK' should be
-                * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
-                * TRAPDOOR_CARRIER is the default initial state for callout
-                * devices and SOFT_CARRIER is like CLOCAL except it hides
-                * the true carrier.
-                */
-               if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
-                       (*linesw[tp->t_line].l_modem)(tp, 1);
-       }
-       /*
-        * Wait for DCD if necessary.
-        */
-       if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
-           && !(tp->t_cflag & CLOCAL) && !(ap->a_oflags & O_NONBLOCK)) {
-               ++com->wopeners;
-               error = tsleep(TSA_CARR_ON(tp), PCATCH, "cydcd", 0);
-               --com->wopeners;
-               if (error != 0)
-                       goto out;
-               goto open_top;
-       }
-       error = (*linesw[tp->t_line].l_open)(dev, tp);
-       disc_optim(tp, &tp->t_termios, com);
-       if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
-               com->active_out = TRUE;
-       siosettimeout();
-out:
-       crit_exit();
-       if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
-               comhardclose(com);
-       lwkt_reltoken(&tty_token);
-       return (error);
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static int
-sioclose(struct dev_close_args *ap)
-{
-       cdev_t dev = ap->a_head.a_dev;
-       struct com_s    *com;
-       int             mynor;
-       struct tty      *tp;
-
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-       mynor = minor(dev);
-       if (mynor & CONTROL_MASK)
-               return (0);
-       lwkt_gettoken(&tty_token);
-       com = com_addr(MINOR_TO_UNIT(mynor));
-       tp = com->tp;
-       crit_enter();
-       cd_etc(com, CD1400_ETC_STOPBREAK);
-       (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
-       disc_optim(tp, &tp->t_termios, com);
-       comstop(tp, FREAD | FWRITE);
-       comhardclose(com);
-       ttyclose(tp);
-       siosettimeout();
-       crit_exit();
-#ifdef broken /* session holds a ref to the tty; can't deallocate */
-       ttyfree(tp);
-       com->tp = sio_tty[unit] = NULL;
-#endif
-       lwkt_reltoken(&tty_token);
-       return (0);
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static void
-comhardclose(struct com_s *com)
-{
-       struct tty      *tp;
-
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-
-       crit_enter();
-#if 0
-       com->poll = FALSE;
-       com->poll_output = FALSE;
-#endif
-       com->do_timestamp = 0;
-#if 0
-       outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
-#else
-       /* XXX */
-       disable_intr();
-       com->etc = ETC_NONE;
-       cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC);
-       enable_intr();
-       cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
-#endif
-
-       {
-#if 0
-               outb(iobase + com_ier, 0);
-#else
-               disable_intr();
-               cd_setreg(com, CD1400_SRER, com->intr_enable = 0);
-               enable_intr();
-#endif
-               tp = com->tp;
-               if ((tp->t_cflag & HUPCL)
-                   /*
-                    * XXX we will miss any carrier drop between here and the
-                    * next open.  Perhaps we should watch DCD even when the
-                    * port is closed; it is not sufficient to check it at
-                    * the next open because it might go up and down while
-                    * we're not watching.
-                    */
-                   || (!com->active_out
-                      && !(com->prev_modem_status & MSR_DCD)
-                      && !(com->it_in.c_cflag & CLOCAL))
-                   || !(tp->t_state & TS_ISOPEN)) {
-                       (void)commctl(com, TIOCM_DTR, DMBIC);
-
-                       /* Disable receiver (leave transmitter enabled). */
-                       com->channel_control = CD1400_CCR_CMDCHANCTL
-                                              | CD1400_CCR_XMTEN
-                                              | CD1400_CCR_RCVDIS;
-                       cd1400_channel_cmd(com, com->channel_control);
-
-                       if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
-                               callout_reset(&com->dtr_ch, com->dtr_wait,
-                                               siodtrwakeup, com);
-                               com->state |= CS_DTR_OFF;
-                       }
-               }
-       }
-#if 0
-       if (com->hasfifo) {
-               /*
-                * Disable fifos so that they are off after controlled
-                * reboots.  Some BIOSes fail to detect 16550s when the
-                * fifos are enabled.
-                */
-               outb(iobase + com_fifo, 0);
-       }
-#endif
-       com->active_out = FALSE;
-       wakeup(&com->active_out);
-       wakeup(TSA_CARR_ON(tp));        /* restart any wopeners */
-       crit_exit();
-}
-
-static int
-siowrite(struct dev_write_args *ap)
-{
-       cdev_t dev = ap->a_head.a_dev;
-       struct uio *uio = ap->a_uio;
-       int             mynor;
-       struct tty      *tp;
-       int             unit;
-       int             ret;
-
-       mynor = minor(dev);
-       if (mynor & CONTROL_MASK)
-               return (ENODEV);
-
-       lwkt_gettoken(&tty_token);
-       unit = MINOR_TO_UNIT(mynor);
-       tp = com_addr(unit)->tp;
-       /*
-        * (XXX) We disallow virtual consoles if the physical console is
-        * a serial port.  This is in case there is a display attached that
-        * is not the console.  In that situation we don't need/want the X
-        * server taking over the console.
-        */
-       if (constty != NULL && unit == comconsole)
-               constty = NULL;
-#ifdef Smarts
-       /* XXX duplicate ttwrite(), but without so much output processing on
-        * CR & LF chars.  Hardly worth the effort, given that high-throughput
-        * sessions are raw anyhow.
-        */
-       ret = 0;
-#else
-       ret = (*linesw[tp->t_line].l_write)(tp, uio, ap->a_ioflag);
-#endif
-       lwkt_reltoken(&tty_token);
-       return(ret);
-}
-
-static void
-siodtrwakeup(void *chan)
-{
-       struct com_s    *com;
-
-       lwkt_gettoken(&tty_token);
-       com = (struct com_s *)chan;
-       com->state &= ~CS_DTR_OFF;
-       wakeup(&com->dtr_wait);
-       lwkt_reltoken(&tty_token);
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static void
-sioinput(struct com_s *com)
-{
-       u_char          *buf;
-       int             incc;
-       u_char          line_status;
-       int             recv_data;
-       struct tty      *tp;
-
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-
-       buf = com->ibuf;
-       tp = com->tp;
-       if (!(tp->t_state & TS_ISOPEN)) {
-               com_events -= (com->iptr - com->ibuf);
-               com->iptr = com->ibuf;
-               return;
-       }
-       if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
-               /*
-                * Avoid the grotesquely inefficient lineswitch routine
-                * (ttyinput) in "raw" mode.  It usually takes about 450
-                * instructions (that's without canonical processing or echo!).
-                * slinput is reasonably fast (usually 40 instructions plus
-                * call overhead).
-                */
-               do {
-                       enable_intr();
-                       incc = com->iptr - buf;
-                       if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
-                           && (com->state & CS_RTS_IFLOW
-                               || tp->t_iflag & IXOFF)
-                           && !(tp->t_state & TS_TBLOCK))
-                               ttyblock(tp);
-                       com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
-                               += b_to_q((char *)buf, incc, &tp->t_rawq);
-                       buf += incc;
-                       tk_nin += incc;
-                       tk_rawcc += incc;
-                       tp->t_rawcc += incc;
-                       ttwakeup(tp);
-                       if (tp->t_state & TS_TTSTOP
-                           && (tp->t_iflag & IXANY
-                               || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
-                               tp->t_state &= ~TS_TTSTOP;
-                               tp->t_lflag &= ~FLUSHO;
-                               comstart(tp);
-                       }
-                       disable_intr();
-               } while (buf < com->iptr);
-       } else {
-               do {
-                       enable_intr();
-                       line_status = buf[com->ierroff];
-                       recv_data = *buf++;
-                       if (line_status
-                           & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
-                               if (line_status & LSR_BI)
-                                       recv_data |= TTY_BI;
-                               if (line_status & LSR_FE)
-                                       recv_data |= TTY_FE;
-                               if (line_status & LSR_OE)
-                                       recv_data |= TTY_OE;
-                               if (line_status & LSR_PE)
-                                       recv_data |= TTY_PE;
-                       }
-                       (*linesw[tp->t_line].l_rint)(recv_data, tp);
-                       disable_intr();
-               } while (buf < com->iptr);
-       }
-       com_events -= (com->iptr - com->ibuf);
-       com->iptr = com->ibuf;
-
-       /*
-        * There is now room for another low-level buffer full of input,
-        * so enable RTS if it is now disabled and there is room in the
-        * high-level buffer.
-        */
-       if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) &&
-           !(tp->t_state & TS_TBLOCK))
-#if 0
-               outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
-#else
-               cd_setreg(com, com->mcr_rts_reg,
-                         com->mcr_image |= com->mcr_rts);
-#endif
-}
-
-void
-siointr(void *arg)
-{
-       int     unit = (int)arg;
-       int     baseu;
-       int     cy_align;
-       cy_addr cy_iobase;
-       int     cyu;
-       cy_addr iobase;
-       u_char  status;
-
-       lwkt_gettoken(&tty_token);
-       com_lock();     /* XXX could this be placed down lower in the loop? */
-
-       baseu = unit * CY_MAX_PORTS;
-       cy_align = com_addr(baseu)->cy_align;
-       cy_iobase = com_addr(baseu)->cy_iobase;
-
-       /* check each CD1400 in turn */
-       for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) {
-               iobase = (cy_addr) (cy_iobase
-                                   + (cy_chip_offset[cyu] << cy_align));
-               /* poll to see if it has any work */
-               status = cd_inb(iobase, CD1400_SVRR, cy_align);
-               if (status == 0)
-                       continue;
-#ifdef CyDebug
-               ++cy_svrr_probes;
-#endif
-               /* service requests as appropriate, giving priority to RX */
-               if (status & CD1400_SVRR_RXRDY) {
-                       struct com_s    *com;
-                       u_int           count;
-                       u_char          *ioptr;
-                       u_char          line_status;
-                       u_char          recv_data;
-                       u_char          serv_type;
-#ifdef PollMode
-                       u_char          save_rir;
-#endif
-
-#ifdef PollMode
-                       save_rir = cd_inb(iobase, CD1400_RIR, cy_align);
-
-                       /* enter rx service */
-                       cd_outb(iobase, CD1400_CAR, cy_align, save_rir);
-                       com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
-                       = save_rir & CD1400_CAR_CHAN;
-
-                       serv_type = cd_inb(iobase, CD1400_RIVR, cy_align);
-                       com = com_addr(baseu
-                                      + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
-                                         & CD1400_xIVR_CHAN));
-#else
-                       /* ack receive service */
-                       serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align);
-
-                       com = com_addr(baseu +
-                                      + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
-                                         & CD1400_xIVR_CHAN));
-#endif
-
-               if (serv_type & CD1400_RIVR_EXCEPTION) {
-                       ++com->recv_exception;
-                       line_status = cd_inb(iobase, CD1400_RDSR, cy_align);
-                       /* break/unnattached error bits or real input? */
-                       recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
-#ifndef SOFT_HOTCHAR
-                       if (line_status & CD1400_RDSR_SPECIAL
-                           && com->hotchar != 0)
-                               setsofttty();
-#endif
-#if 1 /* XXX "intelligent" PFO error handling would break O error handling */
-                       if (line_status & (LSR_PE|LSR_FE|LSR_BI)) {
-                               /*
-                                 Don't store PE if IGNPAR and BI if IGNBRK,
-                                 this hack allows "raw" tty optimization
-                                 works even if IGN* is set.
-                               */
-                               if (   com->tp == NULL
-                                   || !(com->tp->t_state & TS_ISOPEN)
-                                   || ((line_status & (LSR_PE|LSR_FE))
-                                   &&  (com->tp->t_iflag & IGNPAR))
-                                   || ((line_status & LSR_BI)
-                                   &&  (com->tp->t_iflag & IGNBRK)))
-                                       goto cont;
-                               if (   (line_status & (LSR_PE|LSR_FE))
-                                   && (com->tp->t_state & TS_CAN_BYPASS_L_RINT)
-                                   && ((line_status & LSR_FE)
-                                   ||  ((line_status & LSR_PE)
-                                   &&  (com->tp->t_iflag & INPCK))))
-                                       recv_data = 0;
-                       }
-#endif /* 1 */
-                       ++com->bytes_in;
-#ifdef SOFT_HOTCHAR
-                       if (com->hotchar != 0 && recv_data == com->hotchar)
-                               setsofttty();
-#endif
-                       ioptr = com->iptr;
-                       if (ioptr >= com->ibufend)
-                               CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
-                       else {
-                               if (com->do_timestamp)
-                                       microtime(&com->timestamp);
-                               ++com_events;
-                               ioptr[0] = recv_data;
-                               ioptr[com->ierroff] = line_status;
-                               com->iptr = ++ioptr;
-                               if (ioptr == com->ihighwater
-                                   && com->state & CS_RTS_IFLOW)
-#if 0
-                                       outb(com->modem_ctl_port,
-                                            com->mcr_image &= ~MCR_RTS);
-#else
-                                       cd_outb(iobase, com->mcr_rts_reg,
-                                               cy_align,
-                                               com->mcr_image &=
-                                               ~com->mcr_rts);
-#endif
-                               if (line_status & LSR_OE)
-                                       CE_RECORD(com, CE_OVERRUN);
-                       }
-                       goto cont;
-               } else {
-                       int     ifree;
-
-                       count = cd_inb(iobase, CD1400_RDCR, cy_align);
-                       if (!count)
-                               goto cont;
-                       com->bytes_in += count;
-                       ioptr = com->iptr;
-                       ifree = com->ibufend - ioptr;
-                       if (count > ifree) {
-                               count -= ifree;
-                               com_events += ifree;
-                               if (ifree != 0) {
-                                       if (com->do_timestamp)
-                                               microtime(&com->timestamp);
-                                       do {
-                                               recv_data = cd_inb(iobase,
-                                                                  CD1400_RDSR,
-                                                                  cy_align);
-#ifdef SOFT_HOTCHAR
-                                               if (com->hotchar != 0
-                                                   && recv_data
-                                                      == com->hotchar)
-                                                       setsofttty();
-#endif
-                                               ioptr[0] = recv_data;
-                                               ioptr[com->ierroff] = 0;
-                                               ++ioptr;
-                                       } while (--ifree != 0);
-                               }
-                               com->delta_error_counts
-                                   [CE_INTERRUPT_BUF_OVERFLOW] += count;
-                               do {
-                                       recv_data = cd_inb(iobase, CD1400_RDSR,
-                                                          cy_align);
-#ifdef SOFT_HOTCHAR
-                                       if (com->hotchar != 0
-                                           && recv_data == com->hotchar)
-                                               setsofttty();
-#endif
-                               } while (--count != 0);
-                       } else {
-                               if (com->do_timestamp)
-                                       microtime(&com->timestamp);
-                               if (ioptr <= com->ihighwater
-                                   && ioptr + count > com->ihighwater
-                                   && com->state & CS_RTS_IFLOW)
-#if 0
-                                       outb(com->modem_ctl_port,
-                                            com->mcr_image &= ~MCR_RTS);
-#else
-                                       cd_outb(iobase, com->mcr_rts_reg,
-                                               cy_align,
-                                               com->mcr_image
-                                               &= ~com->mcr_rts);
-#endif
-                               com_events += count;
-                               do {
-                                       recv_data = cd_inb(iobase, CD1400_RDSR,
-                                                          cy_align);
-#ifdef SOFT_HOTCHAR
-                                       if (com->hotchar != 0
-                                           && recv_data == com->hotchar)
-                                               setsofttty();
-#endif
-                                       ioptr[0] = recv_data;
-                                       ioptr[com->ierroff] = 0;
-                                       ++ioptr;
-                               } while (--count != 0);
-                       }
-                       com->iptr = ioptr;
-               }
-cont:
-
-                       /* terminate service context */
-#ifdef PollMode
-                       cd_outb(iobase, CD1400_RIR, cy_align,
-                               save_rir
-                               & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY));
-#else
-                       cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
-#endif
-               }
-               if (status & CD1400_SVRR_MDMCH) {
-                       struct com_s    *com;
-                       u_char  modem_status;
-#ifdef PollMode
-                       u_char  save_mir;
-#else
-                       u_char  vector;
-#endif
-
-#ifdef PollMode
-                       save_mir = cd_inb(iobase, CD1400_MIR, cy_align);
-
-                       /* enter modem service */
-                       cd_outb(iobase, CD1400_CAR, cy_align, save_mir);
-                       com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
-                       = save_mir & CD1400_CAR_CHAN;
-
-                       com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS
-                                      + (save_mir & CD1400_MIR_CHAN));
-#else
-                       /* ack modem service */
-                       vector = cy_inb(iobase, CY8_SVCACKM, cy_align);
-
-                       com = com_addr(baseu
-                                      + ((vector >> CD1400_xIVR_CHAN_SHIFT)
-                                         & CD1400_xIVR_CHAN));
-#endif
-                       ++com->mdm;
-                       modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align);
-               if (modem_status != com->last_modem_status) {
-                       if (com->do_dcd_timestamp
-                           && !(com->last_modem_status & MSR_DCD)
-                           && modem_status & MSR_DCD)
-                               microtime(&com->dcd_timestamp);
-
-                       /*
-                        * Schedule high level to handle DCD changes.  Note
-                        * that we don't use the delta bits anywhere.  Some
-                        * UARTs mess them up, and it's easy to remember the
-                        * previous bits and calculate the delta.
-                        */
-                       com->last_modem_status = modem_status;
-                       if (!(com->state & CS_CHECKMSR)) {
-                               com_events += LOTS_OF_EVENTS;
-                               com->state |= CS_CHECKMSR;
-                               setsofttty();
-                       }
-
-#ifdef SOFT_CTS_OFLOW
-                       /* handle CTS change immediately for crisp flow ctl */
-                       if (com->state & CS_CTS_OFLOW) {
-                               if (modem_status & MSR_CTS) {
-                                       com->state |= CS_ODEVREADY;
-                                       if (com->state >= (CS_BUSY | CS_TTGO
-                                                          | CS_ODEVREADY)
-                                           && !(com->intr_enable
-                                                & CD1400_SRER_TXRDY))
-                                               cd_outb(iobase, CD1400_SRER,
-                                                       cy_align,
-                                                       com->intr_enable
-                                                       = com->intr_enable
-                                                         & ~CD1400_SRER_TXMPTY
-                                                         | CD1400_SRER_TXRDY);
-                               } else {
-                                       com->state &= ~CS_ODEVREADY;
-                                       if (com->intr_enable
-                                           & CD1400_SRER_TXRDY)
-                                               cd_outb(iobase, CD1400_SRER,
-                                                       cy_align,
-                                                       com->intr_enable
-                                                       = com->intr_enable
-                                                         & ~CD1400_SRER_TXRDY
-                                                         | CD1400_SRER_TXMPTY);
-                               }
-                       }
-#endif
-               }
-
-                       /* terminate service context */
-#ifdef PollMode
-                       cd_outb(iobase, CD1400_MIR, cy_align,
-                               save_mir
-                               & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY));
-#else
-                       cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
-#endif
-               }
-               if (status & CD1400_SVRR_TXRDY) {
-                       struct com_s    *com;
-#ifdef PollMode
-                       u_char  save_tir;
-#else
-                       u_char  vector;
-#endif
-
-#ifdef PollMode
-                       save_tir = cd_inb(iobase, CD1400_TIR, cy_align);
-
-                       /* enter tx service */
-                       cd_outb(iobase, CD1400_CAR, cy_align, save_tir);
-                       com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
-                       = save_tir & CD1400_CAR_CHAN;
-
-                       com = com_addr(baseu
-                                      + cyu * CD1400_NO_OF_CHANNELS
-                                      + (save_tir & CD1400_TIR_CHAN));
-#else
-                       /* ack transmit service */
-                       vector = cy_inb(iobase, CY8_SVCACKT, cy_align);
-
-                       com = com_addr(baseu
-                                      + ((vector >> CD1400_xIVR_CHAN_SHIFT)
-                                         & CD1400_xIVR_CHAN));
-#endif
-
-                       if (com->etc != ETC_NONE) {
-                               if (com->intr_enable & CD1400_SRER_TXRDY) {
-                                       /*
-                                        * Here due to sloppy SRER_TXRDY
-                                        * enabling.  Ignore.  Come back when
-                                        * tx is empty.
-                                        */
-                                       cd_outb(iobase, CD1400_SRER, cy_align,
-                                               com->intr_enable
-                                               = (com->intr_enable
-                                                 & ~CD1400_SRER_TXRDY)
-                                                 | CD1400_SRER_TXMPTY);
-                                       goto terminate_tx_service;
-                               }
-                               switch (com->etc) {
-                               case CD1400_ETC_SENDBREAK:
-                               case CD1400_ETC_STOPBREAK:
-                                       /*
-                                        * Start the command.  Come back on
-                                        * next tx empty interrupt, hopefully
-                                        * after command has been executed.
-                                        */
-                                       cd_outb(iobase, CD1400_COR2, cy_align,
-                                               com->cor[1] |= CD1400_COR2_ETC);
-                                       cd_outb(iobase, CD1400_TDR, cy_align,
-                                               CD1400_ETC_CMD);
-                                       cd_outb(iobase, CD1400_TDR, cy_align,
-                                               com->etc);
-                                       if (com->etc == CD1400_ETC_SENDBREAK)
-                                               com->etc = ETC_BREAK_STARTING;
-                                       else
-                                               com->etc = ETC_BREAK_ENDING;
-                                       goto terminate_tx_service;
-                               case ETC_BREAK_STARTING:
-                                       /*
-                                        * BREAK is now on.  Continue with
-                                        * SRER_TXMPTY processing, hopefully
-                                        * don't come back.
-                                        */
-                                       com->etc = ETC_BREAK_STARTED;
-                                       break;
-                               case ETC_BREAK_STARTED:
-                                       /*
-                                        * Came back due to sloppy SRER_TXMPTY
-                                        * enabling.  Hope again.
-                                        */
-                                       break;
-                               case ETC_BREAK_ENDING:
-                                       /*
-                                        * BREAK is now off.  Continue with
-                                        * SRER_TXMPTY processing and don't
-                                        * come back.  The SWI handler will
-                                        * restart tx interrupts if necessary.
-                                        */
-                                       cd_outb(iobase, CD1400_COR2, cy_align,
-                                               com->cor[1]
-                                               &= ~CD1400_COR2_ETC);
-                                       com->etc = ETC_BREAK_ENDED;
-                                       if (!(com->state & CS_ODONE)) {
-                                               com_events += LOTS_OF_EVENTS;
-                                               com->state |= CS_ODONE;
-                                               setsofttty();
-                                       }
-                                       break;
-                               case ETC_BREAK_ENDED:
-                                       /*
-                                        * Shouldn't get here.  Hope again.
-                                        */
-                                       break;
-                               }
-                       }
-                       if (com->intr_enable & CD1400_SRER_TXMPTY) {
-                               if (!(com->extra_state & CSE_ODONE)) {
-                                       com_events += LOTS_OF_EVENTS;
-                                       com->extra_state |= CSE_ODONE;
-                                       setsofttty();
-                               }
-                               cd_outb(iobase, CD1400_SRER, cy_align,
-                                       com->intr_enable
-                                       &= ~CD1400_SRER_TXMPTY);
-                               goto terminate_tx_service;
-                       }
-               if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
-                       u_char  *ioptr;
-                       u_int   ocount;
-
-                       ioptr = com->obufq.l_head;
-                               ocount = com->obufq.l_tail - ioptr;
-                               if (ocount > CD1400_TX_FIFO_SIZE)
-                                       ocount = CD1400_TX_FIFO_SIZE;
-                               com->bytes_out += ocount;
-                               do
-                                       cd_outb(iobase, CD1400_TDR, cy_align,
-                                               *ioptr++);
-                               while (--ocount != 0);
-                       com->obufq.l_head = ioptr;
-                       if (ioptr >= com->obufq.l_tail) {
-                               struct lbq      *qp;
-
-                               qp = com->obufq.l_next;
-                               qp->l_queued = FALSE;
-                               qp = qp->l_next;
-                               if (qp != NULL) {
-                                       com->obufq.l_head = qp->l_head;
-                                       com->obufq.l_tail = qp->l_tail;
-                                       com->obufq.l_next = qp;
-                               } else {
-                                       /* output just completed */
-                                       com->state &= ~CS_BUSY;
-
-                                       /*
-                                        * The setting of CSE_ODONE may be
-                                        * stale here.  We currently only
-                                        * use it when CS_BUSY is set, and
-                                        * fixing it when we clear CS_BUSY
-                                        * is easiest.
-                                        */
-                                       if (com->extra_state & CSE_ODONE) {
-                                               com_events -= LOTS_OF_EVENTS;
-                                               com->extra_state &= ~CSE_ODONE;
-                                       }
-
-                                       cd_outb(iobase, CD1400_SRER, cy_align,
-                                               com->intr_enable
-                                               = (com->intr_enable
-                                                 & ~CD1400_SRER_TXRDY)
-                                                 | CD1400_SRER_TXMPTY);
-                               }
-                               if (!(com->state & CS_ODONE)) {
-                                       com_events += LOTS_OF_EVENTS;
-                                       com->state |= CS_ODONE;
-
-                                       /* handle at high level ASAP */
-                                       setsofttty();
-                               }
-                       }
-               }
-
-                       /* terminate service context */
-terminate_tx_service:
-#ifdef PollMode
-                       cd_outb(iobase, CD1400_TIR, cy_align,
-                               save_tir
-                               & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY));
-#else
-                       cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
-#endif
-               }
-       }
-
-       /* ensure an edge for the next interrupt */
-       cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
-
-       schedsofttty();
-
-       com_unlock();
-       lwkt_reltoken(&tty_token);
-}
-
-#if 0
-static void
-siointr1(struct com_s *com)
-{
-}
-#endif
-
-static int
-sioioctl(struct dev_ioctl_args *ap)
-{
-       cdev_t dev = ap->a_head.a_dev;
-       caddr_t data = ap->a_data;
-       u_long cmd = ap->a_cmd;
-       struct com_s    *com;
-       int             error;
-       int             mynor;
-       struct tty      *tp;
-#if defined(COMPAT_43)
-       int             oldcmd;
-       struct termios  term;
-#endif
-
-       lwkt_gettoken(&tty_token);
-       mynor = minor(dev);
-       com = com_addr(MINOR_TO_UNIT(mynor));
-       if (mynor & CONTROL_MASK) {
-               struct termios  *ct;
-
-               switch (mynor & CONTROL_MASK) {
-               case CONTROL_INIT_STATE:
-                       ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
-                       break;
-               case CONTROL_LOCK_STATE:
-                       ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
-                       break;
-               default:
-                       lwkt_reltoken(&tty_token);
-                       return (ENODEV);        /* /dev/nodev */
-               }
-               switch (cmd) {
-               case TIOCSETA:
-                       error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
-                       if (error != 0) {
-                               lwkt_reltoken(&tty_token);
-                               return (error);
-                       }
-                       *ct = *(struct termios *)data;
-                       lwkt_reltoken(&tty_token);
-                       return (0);
-               case TIOCGETA:
-                       *(struct termios *)data = *ct;
-                       lwkt_reltoken(&tty_token);
-                       return (0);
-               case TIOCGETD:
-                       *(int *)data = TTYDISC;
-                       lwkt_reltoken(&tty_token);
-                       return (0);
-               case TIOCGWINSZ:
-                       bzero(data, sizeof(struct winsize));
-                       lwkt_reltoken(&tty_token);
-                       return (0);
-               default:
-                       lwkt_reltoken(&tty_token);
-                       return (ENOTTY);
-               }
-       }
-       tp = com->tp;
-#if defined(COMPAT_43)
-       term = tp->t_termios;
-       oldcmd = cmd;
-       error = ttsetcompat(tp, &cmd, data, &term);
-       if (error != 0) {
-               lwkt_reltoken(&tty_token);
-               return (error);
-       }
-       if (cmd != oldcmd)
-               data = (caddr_t)&term;
-#endif
-       if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
-               int     cc;
-               struct termios *dt = (struct termios *)data;
-               struct termios *lt = mynor & CALLOUT_MASK
-                                    ? &com->lt_out : &com->lt_in;
-
-               dt->c_iflag = (tp->t_iflag & lt->c_iflag)
-                             | (dt->c_iflag & ~lt->c_iflag);
-               dt->c_oflag = (tp->t_oflag & lt->c_oflag)
-                             | (dt->c_oflag & ~lt->c_oflag);
-               dt->c_cflag = (tp->t_cflag & lt->c_cflag)
-                             | (dt->c_cflag & ~lt->c_cflag);
-               dt->c_lflag = (tp->t_lflag & lt->c_lflag)
-                             | (dt->c_lflag & ~lt->c_lflag);
-               for (cc = 0; cc < NCCS; ++cc)
-                       if (lt->c_cc[cc] != 0)
-                               dt->c_cc[cc] = tp->t_cc[cc];
-               if (lt->c_ispeed != 0)
-                       dt->c_ispeed = tp->t_ispeed;
-               if (lt->c_ospeed != 0)
-                       dt->c_ospeed = tp->t_ospeed;
-       }
-       error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data,
-                                             ap->a_fflag, ap->a_cred);
-       if (error != ENOIOCTL) {
-               lwkt_reltoken(&tty_token);
-               return (error);
-       }
-       crit_enter();
-       error = ttioctl(tp, cmd, data, ap->a_fflag);
-       disc_optim(tp, &tp->t_termios, com);
-       if (error != ENOIOCTL) {
-               crit_exit();
-               lwkt_reltoken(&tty_token);
-               return (error);
-       }
-       switch (cmd) {
-       case TIOCSBRK:
-#if 0
-               outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK);
-#else
-               cd_etc(com, CD1400_ETC_SENDBREAK);
-#endif
-               break;
-       case TIOCCBRK:
-#if 0
-               outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
-#else
-               cd_etc(com, CD1400_ETC_STOPBREAK);
-#endif
-               break;
-       case TIOCSDTR:
-               (void)commctl(com, TIOCM_DTR, DMBIS);
-               break;
-       case TIOCCDTR:
-               (void)commctl(com, TIOCM_DTR, DMBIC);
-               break;
-       /*
-        * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
-        * changes get undone on the next call to comparam().
-        */
-       case TIOCMSET:
-               (void)commctl(com, *(int *)data, DMSET);
-               break;
-       case TIOCMBIS:
-               (void)commctl(com, *(int *)data, DMBIS);
-               break;
-       case TIOCMBIC:
-               (void)commctl(com, *(int *)data, DMBIC);
-               break;
-       case TIOCMGET:
-               *(int *)data = commctl(com, 0, DMGET);
-               break;
-       case TIOCMSDTRWAIT:
-               /* must be root since the wait applies to following logins */
-               error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
-               if (error != 0) {
-                       crit_exit();
-                       lwkt_reltoken(&tty_token);
-                       return (error);
-               }
-               com->dtr_wait = *(int *)data * hz / 100;
-               break;
-       case TIOCMGDTRWAIT:
-               *(int *)data = com->dtr_wait * 100 / hz;
-               break;
-       case TIOCTIMESTAMP:
-               com->do_timestamp = TRUE;
-               *(struct timeval *)data = com->timestamp;
-               break;
-       case TIOCDCDTIMESTAMP:
-               com->do_dcd_timestamp = TRUE;
-               *(struct timeval *)data = com->dcd_timestamp;
-               break;
-       default:
-               crit_exit();
-               lwkt_reltoken(&tty_token);
-               return (ENOTTY);
-       }
-       crit_exit();
-       lwkt_reltoken(&tty_token);
-       return (0);
-}
-
-static void
-siopoll(void *data, void *frame)
-{
-       int             unit;
-
-       lwkt_gettoken(&tty_token);
-#ifdef CyDebug
-       ++cy_timeouts;
-#endif
-       if (com_events == 0) {
-               lwkt_reltoken(&tty_token);
-               return;
-       }
-repeat:
-       for (unit = 0; unit < NSIO; ++unit) {
-               struct com_s    *com;
-               int             incc;
-               struct tty      *tp;
-
-               com = com_addr(unit);
-               if (com == NULL)
-                       continue;
-               tp = com->tp;
-               if (tp == NULL) {
-                       /*
-                        * XXX forget any events related to closed devices
-                        * (actually never opened devices) so that we don't
-                        * loop.
-                        */
-                       disable_intr();
-                       incc = com->iptr - com->ibuf;
-                       com->iptr = com->ibuf;
-                       if (com->state & CS_CHECKMSR) {
-                               incc += LOTS_OF_EVENTS;
-                               com->state &= ~CS_CHECKMSR;
-                       }
-                       com_events -= incc;
-                       enable_intr();
-                       if (incc != 0)
-                               log(LOG_DEBUG,
-                                   "sio%d: %d events for device with no tp\n",
-                                   unit, incc);
-                       continue;
-               }
-               if (com->iptr != com->ibuf) {
-                       disable_intr();
-                       sioinput(com);
-                       enable_intr();
-               }
-               if (com->state & CS_CHECKMSR) {
-                       u_char  delta_modem_status;
-
-                       disable_intr();
-                       delta_modem_status = com->last_modem_status
-                                            ^ com->prev_modem_status;
-                       com->prev_modem_status = com->last_modem_status;
-                       com_events -= LOTS_OF_EVENTS;
-                       com->state &= ~CS_CHECKMSR;
-                       enable_intr();
-                       if (delta_modem_status & MSR_DCD)
-                               (*linesw[tp->t_line].l_modem)
-                                       (tp, com->prev_modem_status & MSR_DCD);
-               }
-               if (com->extra_state & CSE_ODONE) {
-                       disable_intr();
-                       com_events -= LOTS_OF_EVENTS;
-                       com->extra_state &= ~CSE_ODONE;
-                       enable_intr();
-                       if (!(com->state & CS_BUSY)) {
-                               tp->t_state &= ~TS_BUSY;
-                               ttwwakeup(com->tp);
-                       }
-                       if (com->etc != ETC_NONE) {
-                               if (com->etc == ETC_BREAK_ENDED)
-                                       com->etc = ETC_NONE;
-                               wakeup(&com->etc);
-                       }
-               }
-               if (com->state & CS_ODONE) {
-                       disable_intr();
-                       com_events -= LOTS_OF_EVENTS;
-                       com->state &= ~CS_ODONE;
-                       enable_intr();
-                       (*linesw[tp->t_line].l_start)(tp);
-               }
-               if (com_events == 0)
-                       break;
-       }
-       if (com_events >= LOTS_OF_EVENTS)
-               goto repeat;
-       lwkt_reltoken(&tty_token);
-}
-
-static int
-comparam(struct tty *tp, struct termios *t)
-{
-       int             bits;
-       int             cflag;
-       struct com_s    *com;
-       u_char          cor_change;
-       u_long          cy_clock;
-       int             idivisor;
-       int             iflag;
-       int             iprescaler;
-       int             itimeout;
-       int             odivisor;
-       int             oprescaler;
-       u_char          opt;
-       int             unit;
-
-       lwkt_gettoken(&tty_token);
-       /* do historical conversions */
-       if (t->c_ispeed == 0)
-               t->c_ispeed = t->c_ospeed;
-
-       unit = DEV_TO_UNIT(tp->t_dev);
-       com = com_addr(unit);
-
-       /* check requested parameters */
-       cy_clock = CY_CLOCK(com->gfrcr_image);
-       idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler);
-       if (idivisor < 0) {
-               lwkt_reltoken(&tty_token);
-               return (EINVAL);
-       }
-       odivisor = comspeed(t->c_ospeed, cy_clock, &oprescaler);
-       if (odivisor < 0) {
-               lwkt_reltoken(&tty_token);
-               return (EINVAL);
-       }
-
-       /* parameters are OK, convert them to the com struct and the device */
-       crit_enter();
-       if (odivisor == 0)
-               (void)commctl(com, TIOCM_DTR, DMBIC);   /* hang up line */
-       else
-               (void)commctl(com, TIOCM_DTR, DMBIS);
-
-       /*
-        * This returns with interrupts disabled so that we can complete
-        * the speed change atomically.
-        */
-       (void) siosetwater(com, t->c_ispeed);
-
-       /* XXX we don't actually change the speed atomically. */
-       enable_intr();
-
-       if (idivisor != 0) {
-               cd_setreg(com, CD1400_RBPR, idivisor);
-               cd_setreg(com, CD1400_RCOR, iprescaler);
-       }
-       if (odivisor != 0) {
-               cd_setreg(com, CD1400_TBPR, odivisor);
-               cd_setreg(com, CD1400_TCOR, oprescaler);
-       }
-
-       /*
-        * channel control
-        *      receiver enable
-        *      transmitter enable (always set)
-        */
-       cflag = t->c_cflag;
-       opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN
-             | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
-       if (opt != com->channel_control) {
-               com->channel_control = opt;
-               cd1400_channel_cmd(com, opt);
-       }
-
-#ifdef Smarts
-       /* set special chars */
-       /* XXX if one is _POSIX_VDISABLE, can't use some others */
-       if (t->c_cc[VSTOP] != _POSIX_VDISABLE)
-               cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]);
-       if (t->c_cc[VSTART] != _POSIX_VDISABLE)
-               cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]);
-       if (t->c_cc[VINTR] != _POSIX_VDISABLE)
-               cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]);
-       if (t->c_cc[VSUSP] != _POSIX_VDISABLE)
-               cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]);
-#endif
-
-       /*
-        * set channel option register 1 -
-        *      parity mode
-        *      stop bits
-        *      char length
-        */
-       opt = 0;
-       /* parity */
-       if (cflag & PARENB) {
-               if (cflag & PARODD)
-                       opt |= CD1400_COR1_PARODD;
-               opt |= CD1400_COR1_PARNORMAL;
-       }
-       iflag = t->c_iflag;
-       if (!(iflag & INPCK))
-               opt |= CD1400_COR1_NOINPCK;
-       bits = 1 + 1;
-       /* stop bits */
-       if (cflag & CSTOPB) {
-               ++bits;
-               opt |= CD1400_COR1_STOP2;
-       }
-       /* char length */
-       switch (cflag & CSIZE) {
-       case CS5:
-               bits += 5;
-               opt |= CD1400_COR1_CS5;
-               break;
-       case CS6:
-               bits += 6;
-               opt |= CD1400_COR1_CS6;
-               break;
-       case CS7:
-               bits += 7;
-               opt |= CD1400_COR1_CS7;
-               break;
-       default:
-               bits += 8;
-               opt |= CD1400_COR1_CS8;
-               break;
-       }
-       cor_change = 0;
-       if (opt != com->cor[0]) {
-               cor_change |= CD1400_CCR_COR1;
-               cd_setreg(com, CD1400_COR1, com->cor[0] = opt);
-       }
-
-       /*
-        * Set receive time-out period, normally to max(one char time, 5 ms).
-        */
-       if (t->c_ispeed == 0)
-               itimeout = cd_getreg(com, CD1400_RTPR);
-       else {
-               itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed;
-#ifdef SOFT_HOTCHAR
-#define        MIN_RTP         1
-#else
-#define        MIN_RTP         5
-#endif
-               if (itimeout < MIN_RTP)
-                       itimeout = MIN_RTP;
-       }
-       if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0
-           && t->c_cc[VTIME] * 10 > itimeout)
-               itimeout = t->c_cc[VTIME] * 10;
-       if (itimeout > 255)
-               itimeout = 255;
-       cd_setreg(com, CD1400_RTPR, itimeout);
-
-       /*
-        * set channel option register 2 -
-        *      flow control
-        */
-       opt = 0;
-#ifdef Smarts
-       if (iflag & IXANY)
-               opt |= CD1400_COR2_IXANY;
-       if (iflag & IXOFF)
-               opt |= CD1400_COR2_IXOFF;
-#endif
-#ifndef SOFT_CTS_OFLOW
-       if (cflag & CCTS_OFLOW)
-               opt |= CD1400_COR2_CCTS_OFLOW;
-#endif
-       disable_intr();
-       if (opt != com->cor[1]) {
-               cor_change |= CD1400_CCR_COR2;
-               cd_setreg(com, CD1400_COR2, com->cor[1] = opt);
-       }
-       enable_intr();
-
-       /*
-        * set channel option register 3 -
-        *      receiver FIFO interrupt threshold
-        *      flow control
-        */
-       opt = RxFifoThreshold;
-#ifdef Smarts
-       if (t->c_lflag & ICANON)
-               opt |= CD1400_COR3_SCD34;       /* detect INTR & SUSP chars */
-       if (iflag & IXOFF)
-               /* detect and transparently handle START and STOP chars */
-               opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12;
-#endif
-       if (opt != com->cor[2]) {
-               cor_change |= CD1400_CCR_COR3;
-               cd_setreg(com, CD1400_COR3, com->cor[2] = opt);
-       }
-
-       /* notify the CD1400 if COR1-3 have changed */
-       if (cor_change)
-               cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change);
-
-       /*
-        * set channel option register 4 -
-        *      CR/NL processing
-        *      break processing
-        *      received exception processing
-        */
-       opt = 0;
-       if (iflag & IGNCR)
-               opt |= CD1400_COR4_IGNCR;
-#ifdef Smarts
-       /*
-        * we need a new ttyinput() for this, as we don't want to
-        * have ICRNL && INLCR being done in both layers, or to have
-        * synchronisation problems
-        */
-       if (iflag & ICRNL)
-               opt |= CD1400_COR4_ICRNL;
-       if (iflag & INLCR)
-               opt |= CD1400_COR4_INLCR;
-#endif
-       if (iflag & IGNBRK)
-               opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT;
-       /*
-        * The `-ignbrk -brkint parmrk' case is not handled by the hardware,
-        * so only tell the hardware about -brkint if -parmrk.
-        */
-       if (!(iflag & (BRKINT | PARMRK)))
-               opt |= CD1400_COR4_NOBRKINT;
-#if 0
-       /* XXX using this "intelligence" breaks reporting of overruns. */
-       if (iflag & IGNPAR)
-               opt |= CD1400_COR4_PFO_DISCARD;
-       else {
-               if (iflag & PARMRK)
-                       opt |= CD1400_COR4_PFO_ESC;
-               else
-                       opt |= CD1400_COR4_PFO_NUL;
-       }
-#else
-       opt |= CD1400_COR4_PFO_EXCEPTION;
-#endif
-       cd_setreg(com, CD1400_COR4, opt);
-
-       /*
-        * set channel option register 5 -
-        */
-       opt = 0;
-       if (iflag & ISTRIP)
-               opt |= CD1400_COR5_ISTRIP;
-       if (t->c_iflag & IEXTEN)
-               /* enable LNEXT (e.g. ctrl-v quoting) handling */
-               opt |= CD1400_COR5_LNEXT;
-#ifdef Smarts
-       if (t->c_oflag & ONLCR)
-               opt |= CD1400_COR5_ONLCR;
-       if (t->c_oflag & OCRNL)
-               opt |= CD1400_COR5_OCRNL;
-#endif
-       cd_setreg(com, CD1400_COR5, opt);
-
-       /*
-        * We always generate modem status change interrupts for CD changes.
-        * Among other things, this is necessary to track TS_CARR_ON for
-        * pstat to print even when the driver doesn't care.  CD changes
-        * should be rare so interrupts for them are not worth extra code to
-        * avoid.  We avoid interrupts for other modem status changes (except
-        * for CTS changes when SOFT_CTS_OFLOW is configured) since this is
-        * simplest and best.
-        */
-
-       /*
-        * set modem change option register 1
-        *      generate modem interrupts on which 1 -> 0 input transitions
-        *      also controls auto-DTR output flow-control, which we don't use
-        */
-       opt = CD1400_MCOR1_CDzd;
-#ifdef SOFT_CTS_OFLOW
-       if (cflag & CCTS_OFLOW)
-               opt |= CD1400_MCOR1_CTSzd;
-#endif
-       cd_setreg(com, CD1400_MCOR1, opt);
-
-       /*
-        * set modem change option register 2
-        *      generate modem interrupts on specific 0 -> 1 input transitions
-        */
-       opt = CD1400_MCOR2_CDod;
-#ifdef SOFT_CTS_OFLOW
-       if (cflag & CCTS_OFLOW)
-               opt |= CD1400_MCOR2_CTSod;
-#endif
-       cd_setreg(com, CD1400_MCOR2, opt);
-
-       /*
-        * XXX should have done this long ago, but there is too much state
-        * to change all atomically.
-        */
-       disable_intr();
-
-       com->state &= ~CS_TTGO;
-       if (!(tp->t_state & TS_TTSTOP))
-               com->state |= CS_TTGO;
-       if (cflag & CRTS_IFLOW) {
-               com->state |= CS_RTS_IFLOW;
-               /*
-                * If CS_RTS_IFLOW just changed from off to on, the change
-                * needs to be propagated to MCR_RTS.  This isn't urgent,
-                * so do it later by calling comstart() instead of repeating
-                * a lot of code from comstart() here.
-                */
-       } else if (com->state & CS_RTS_IFLOW) {
-               com->state &= ~CS_RTS_IFLOW;
-               /*
-                * CS_RTS_IFLOW just changed from on to off.  Force MCR_RTS
-                * on here, since comstart() won't do it later.
-                */
-#if 0
-               outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
-#else
-               cd_setreg(com, com->mcr_rts_reg,
-                         com->mcr_image |= com->mcr_rts);
-#endif
-       }
-
-       /*
-        * Set up state to handle output flow control.
-        * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
-        * Now has 10+ msec latency, while CTS flow has 50- usec latency.
-        */
-       com->state |= CS_ODEVREADY;
-#ifdef SOFT_CTS_OFLOW
-       com->state &= ~CS_CTS_OFLOW;
-       if (cflag & CCTS_OFLOW) {
-               com->state |= CS_CTS_OFLOW;
-               if (!(com->last_modem_status & MSR_CTS))
-                       com->state &= ~CS_ODEVREADY;
-       }
-#endif
-       /* XXX shouldn't call functions while intrs are disabled. */
-       disc_optim(tp, t, com);
-#if 0
-       /*
-        * Recover from fiddling with CS_TTGO.  We used to call siointr1()
-        * unconditionally, but that defeated the careful discarding of
-        * stale input in sioopen().
-        */
-       if (com->state >= (CS_BUSY | CS_TTGO))
-               siointr1(com);
-#endif
-       if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
-               if (!(com->intr_enable & CD1400_SRER_TXRDY))
-                       cd_setreg(com, CD1400_SRER,
-                                 com->intr_enable
-                                 = (com->intr_enable & ~CD1400_SRER_TXMPTY)
-                                   | CD1400_SRER_TXRDY);
-       } else {
-               if (com->intr_enable & CD1400_SRER_TXRDY)
-                       cd_setreg(com, CD1400_SRER,
-                                 com->intr_enable
-                                 = (com->intr_enable & ~CD1400_SRER_TXRDY)
-                                   | CD1400_SRER_TXMPTY);
-       }
-
-       enable_intr();
-       crit_exit();
-       comstart(tp);
-       if (com->ibufold != NULL) {
-               kfree(com->ibufold, M_DEVBUF);
-               com->ibufold = NULL;
-       }
-       lwkt_reltoken(&tty_token);
-       return (0);
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static int
-siosetwater(struct com_s *com, speed_t speed)
-{
-       int             cp4ticks;
-       u_char          *ibuf;
-       int             ibufsize;
-       struct tty      *tp;
-
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-
-       /*
-        * Make the buffer size large enough to handle a softtty interrupt
-        * latency of about 2 ticks without loss of throughput or data
-        * (about 3 ticks if input flow control is not used or not honoured,
-        * but a bit less for CS5-CS7 modes).
-        */
-       cp4ticks = speed / 10 / hz * 4;
-       for (ibufsize = 128; ibufsize < cp4ticks;)
-               ibufsize <<= 1;
-       if (ibufsize == com->ibufsize) {
-               disable_intr();
-               return (0);
-       }
-
-       /*
-        * Allocate input buffer.  The extra factor of 2 in the size is
-        * to allow for an error byte for each input byte.
-        */
-       ibuf = kmalloc(2 * ibufsize, M_DEVBUF, M_WAITOK);
-
-       /* Initialize non-critical variables. */
-       com->ibufold = com->ibuf;
-       com->ibufsize = ibufsize;
-       tp = com->tp;
-       if (tp != NULL) {
-               tp->t_ififosize = 2 * ibufsize;
-               tp->t_ispeedwat = (speed_t)-1;
-               tp->t_ospeedwat = (speed_t)-1;
-       }
-
-       /*
-        * Read current input buffer, if any.  Continue with interrupts
-        * disabled.
-        */
-       disable_intr();
-       if (com->iptr != com->ibuf)
-               sioinput(com);
-
-       /*-
-        * Initialize critical variables, including input buffer watermarks.
-        * The external device is asked to stop sending when the buffer
-        * exactly reaches high water, or when the high level requests it.
-        * The high level is notified immediately (rather than at a later
-        * clock tick) when this watermark is reached.
-        * The buffer size is chosen so the watermark should almost never
-        * be reached.
-        * The low watermark is invisibly 0 since the buffer is always
-        * emptied all at once.
-        */
-       com->iptr = com->ibuf = ibuf;
-       com->ibufend = ibuf + ibufsize;
-       com->ierroff = ibufsize;
-       com->ihighwater = ibuf + 3 * ibufsize / 4;
-       return (0);
-}
-
-static void
-comstart(struct tty *tp)
-{
-       struct com_s    *com;
-#ifdef CyDebug
-       bool_t          started;
-#endif
-       int             unit;
-
-       unit = DEV_TO_UNIT(tp->t_dev);
-       com = com_addr(unit);
-       crit_enter();
-       lwkt_gettoken(&tty_token);
-
-#ifdef CyDebug
-       ++com->start_count;
-       started = FALSE;
-#endif
-
-       disable_intr();
-       if (tp->t_state & TS_TTSTOP) {
-               com->state &= ~CS_TTGO;
-               if (com->intr_enable & CD1400_SRER_TXRDY)
-                       cd_setreg(com, CD1400_SRER,
-                                 com->intr_enable
-                                 = (com->intr_enable & ~CD1400_SRER_TXRDY)
-                                   | CD1400_SRER_TXMPTY);
-       } else {
-               com->state |= CS_TTGO;
-               if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)
-                   && !(com->intr_enable & CD1400_SRER_TXRDY))
-                       cd_setreg(com, CD1400_SRER,
-                                 com->intr_enable
-                                 = (com->intr_enable & ~CD1400_SRER_TXMPTY)
-                                   | CD1400_SRER_TXRDY);
-       }
-       if (tp->t_state & TS_TBLOCK) {
-               if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW)
-#if 0
-                       outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
-#else
-                       cd_setreg(com, com->mcr_rts_reg,
-                                 com->mcr_image &= ~com->mcr_rts);
-#endif
-       } else {
-               if (!(com->mcr_image & com->mcr_rts)
-                   && com->iptr < com->ihighwater
-                   && com->state & CS_RTS_IFLOW)
-#if 0
-                       outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
-#else
-                       cd_setreg(com, com->mcr_rts_reg,
-                                 com->mcr_image |= com->mcr_rts);
-#endif
-       }
-       enable_intr();
-       if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
-               ttwwakeup(tp);
-               lwkt_reltoken(&tty_token);
-               crit_exit();
-               return;
-       }
-       if (tp->t_outq.c_cc != 0) {
-               struct lbq      *qp;
-               struct lbq      *next;
-
-               if (!com->obufs[0].l_queued) {
-#ifdef CyDebug
-                       started = TRUE;
-#endif
-                       com->obufs[0].l_tail
-                           = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
-                                                 sizeof com->obuf1);
-                       com->obufs[0].l_next = NULL;
-                       com->obufs[0].l_queued = TRUE;
-                       disable_intr();
-                       if (com->state & CS_BUSY) {
-                               qp = com->obufq.l_next;
-                               while ((next = qp->l_next) != NULL)
-                                       qp = next;
-                               qp->l_next = &com->obufs[0];
-                       } else {
-                               com->obufq.l_head = com->obufs[0].l_head;
-                               com->obufq.l_tail = com->obufs[0].l_tail;
-                               com->obufq.l_next = &com->obufs[0];
-                               com->state |= CS_BUSY;
-                               if (com->state >= (CS_BUSY | CS_TTGO
-                                                  | CS_ODEVREADY))
-                                       cd_setreg(com, CD1400_SRER,
-                                                 com->intr_enable
-                                                 = (com->intr_enable
-                                                   & ~CD1400_SRER_TXMPTY)
-                                                   | CD1400_SRER_TXRDY);
-                       }
-                       enable_intr();
-               }
-               if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
-#ifdef CyDebug
-                       started = TRUE;
-#endif
-                       com->obufs[1].l_tail
-                           = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
-                                                 sizeof com->obuf2);
-                       com->obufs[1].l_next = NULL;
-                       com->obufs[1].l_queued = TRUE;
-                       disable_intr();
-                       if (com->state & CS_BUSY) {
-                               qp = com->obufq.l_next;
-                               while ((next = qp->l_next) != NULL)
-                                       qp = next;
-                               qp->l_next = &com->obufs[1];
-                       } else {
-                               com->obufq.l_head = com->obufs[1].l_head;
-                               com->obufq.l_tail = com->obufs[1].l_tail;
-                               com->obufq.l_next = &com->obufs[1];
-                               com->state |= CS_BUSY;
-                               if (com->state >= (CS_BUSY | CS_TTGO
-                                                  | CS_ODEVREADY))
-                                       cd_setreg(com, CD1400_SRER,
-                                                 com->intr_enable
-                                                 = (com->intr_enable
-                                                   & ~CD1400_SRER_TXMPTY)
-                                                   | CD1400_SRER_TXRDY);
-                       }
-                       enable_intr();
-               }
-               tp->t_state |= TS_BUSY;
-       }
-#ifdef CyDebug
-       if (started)
-               ++com->start_real;
-#endif
-#if 0
-       disable_intr();
-       if (com->state >= (CS_BUSY | CS_TTGO))
-               siointr1(com);  /* fake interrupt to start output */
-       enable_intr();
-#endif
-       ttwwakeup(tp);
-       lwkt_reltoken(&tty_token);
-       crit_exit();
-}
-
-static void
-comstop(struct tty *tp, int rw)
-{
-       struct com_s    *com;
-       bool_t          wakeup_etc;
-
-       lwkt_gettoken(&tty_token);
-       com = com_addr(DEV_TO_UNIT(tp->t_dev));
-       wakeup_etc = FALSE;
-       disable_intr();
-       if (rw & FWRITE) {
-               com->obufs[0].l_queued = FALSE;
-               com->obufs[1].l_queued = FALSE;
-               if (com->extra_state & CSE_ODONE) {
-                       com_events -= LOTS_OF_EVENTS;
-                       com->extra_state &= ~CSE_ODONE;
-                       if (com->etc != ETC_NONE) {
-                               if (com->etc == ETC_BREAK_ENDED)
-                                       com->etc = ETC_NONE;
-                               wakeup_etc = TRUE;
-                       }
-               }
-               com->tp->t_state &= ~TS_BUSY;
-               if (com->state & CS_ODONE)
-                       com_events -= LOTS_OF_EVENTS;
-               com->state &= ~(CS_ODONE | CS_BUSY);
-       }
-       if (rw & FREAD) {
-               /* XXX no way to reset only input fifo. */
-               com_events -= (com->iptr - com->ibuf);
-               com->iptr = com->ibuf;
-       }
-       enable_intr();
-       if (wakeup_etc)
-               wakeup(&com->etc);
-       if (rw & FWRITE && com->etc == ETC_NONE)
-               cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
-       comstart(tp);
-       lwkt_reltoken(&tty_token);
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static int
-commctl(struct com_s *com, int bits, int how)
-{
-       int     mcr;
-       int     msr;
-
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-
-       if (how == DMGET) {
-               if (com->channel_control & CD1400_CCR_RCVEN)
-                       bits |= TIOCM_LE;
-               mcr = com->mcr_image;
-               if (mcr & com->mcr_dtr)
-                       bits |= TIOCM_DTR;
-               if (mcr & com->mcr_rts)
-                       /* XXX wired on for Cyclom-8Ys */
-                       bits |= TIOCM_RTS;
-
-               /*
-                * We must read the modem status from the hardware because
-                * we don't generate modem status change interrupts for all
-                * changes, so com->prev_modem_status is not guaranteed to
-                * be up to date.  This is safe, unlike for sio, because
-                * reading the status register doesn't clear pending modem
-                * status change interrupts.
-                */
-               msr = cd_getreg(com, CD1400_MSVR2);
-
-               if (msr & MSR_CTS)
-                       bits |= TIOCM_CTS;
-               if (msr & MSR_DCD)
-                       bits |= TIOCM_CD;
-               if (msr & MSR_DSR)
-                       bits |= TIOCM_DSR;
-               if (msr & MSR_RI)
-                       /* XXX not connected except for Cyclom-16Y? */
-                       bits |= TIOCM_RI;
-               return (bits);
-       }
-       mcr = 0;
-       if (bits & TIOCM_DTR)
-               mcr |= com->mcr_dtr;
-       if (bits & TIOCM_RTS)
-               mcr |= com->mcr_rts;
-       disable_intr();
-       switch (how) {
-       case DMSET:
-               com->mcr_image = mcr;
-               cd_setreg(com, CD1400_MSVR1, mcr);
-               cd_setreg(com, CD1400_MSVR2, mcr);
-               break;
-       case DMBIS:
-               com->mcr_image = mcr = com->mcr_image | mcr;
-               cd_setreg(com, CD1400_MSVR1, mcr);
-               cd_setreg(com, CD1400_MSVR2, mcr);
-               break;
-       case DMBIC:
-               com->mcr_image = mcr = com->mcr_image & ~mcr;
-               cd_setreg(com, CD1400_MSVR1, mcr);
-               cd_setreg(com, CD1400_MSVR2, mcr);
-               break;
-       }
-       enable_intr();
-       return (0);
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static void
-siosettimeout(void)
-{
-       struct com_s    *com;
-       bool_t          someopen;
-       int             unit;
-
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-       /*
-        * Set our timeout period to 1 second if no polled devices are open.
-        * Otherwise set it to max(1/200, 1/hz).
-        * Enable timeouts iff some device is open.
-        */
-       callout_stop(&sio_timeout_handle);
-       sio_timeout = hz;
-       someopen = FALSE;
-       for (unit = 0; unit < NSIO; ++unit) {
-               com = com_addr(unit);
-               if (com != NULL && com->tp != NULL
-                   && com->tp->t_state & TS_ISOPEN) {
-                       someopen = TRUE;
-#if 0
-                       if (com->poll || com->poll_output) {
-                               sio_timeout = hz > 200 ? hz / 200 : 1;
-                               break;
-                       }
-#endif
-               }
-       }
-       if (someopen) {
-               sio_timeouts_until_log = hz / sio_timeout;
-               callout_reset(&sio_timeout_handle, sio_timeout,
-                               comwakeup, NULL);
-       } else {
-               /* Flush error messages, if any. */
-               sio_timeouts_until_log = 1;
-               comwakeup(NULL);
-               callout_stop(&sio_timeout_handle);
-       }
-}
-
-static void
-comwakeup(void *chan)
-{
-       struct com_s    *com;
-       int             unit;
-
-       lwkt_gettoken(&tty_token);
-       callout_reset(&sio_timeout_handle, sio_timeout, comwakeup, NULL);
-
-#if 0
-       /*
-        * Recover from lost output interrupts.
-        * Poll any lines that don't use interrupts.
-        */
-       for (unit = 0; unit < NSIO; ++unit) {
-               com = com_addr(unit);
-               if (com != NULL
-                   && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
-                       disable_intr();
-                       siointr1(com);
-                       enable_intr();
-               }
-       }
-#endif
-
-       /*
-        * Check for and log errors, but not too often.
-        */
-       if (--sio_timeouts_until_log > 0) {
-               lwkt_reltoken(&tty_token);
-               return;
-       }
-       sio_timeouts_until_log = hz / sio_timeout;
-       for (unit = 0; unit < NSIO; ++unit) {
-               int     errnum;
-
-               com = com_addr(unit);
-               if (com == NULL)
-                       continue;
-               for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
-                       u_int   delta;
-                       u_long  total;
-
-                       disable_intr();
-                       delta = com->delta_error_counts[errnum];
-                       com->delta_error_counts[errnum] = 0;
-                       enable_intr();
-                       if (delta == 0)
-                               continue;
-                       total = com->error_counts[errnum] += delta;
-                       log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n",
-                           unit, delta, error_desc[errnum],
-                           delta == 1 ? "" : "s", total);
-               }
-       }
-       lwkt_reltoken(&tty_token);
-}
-
-static void
-disc_optim(struct tty *tp, struct termios *t, struct com_s *com)
-{
-#ifndef SOFT_HOTCHAR
-       u_char  opt;
-#endif
-
-       lwkt_gettoken(&tty_token);
-       /*
-        * XXX can skip a lot more cases if Smarts.  Maybe
-        * (IGNCR | ISTRIP | IXON) in c_iflag.  But perhaps we
-        * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state.
-        */
-       if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
-           && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
-           && (!(t->c_iflag & PARMRK)
-               || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
-           && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
-           && linesw[tp->t_line].l_rint == ttyinput)
-               tp->t_state |= TS_CAN_BYPASS_L_RINT;
-       else
-               tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
-       com->hotchar = linesw[tp->t_line].l_hotchar;
-#ifndef SOFT_HOTCHAR
-       opt = com->cor[2] & ~CD1400_COR3_SCD34;
-       if (com->hotchar != 0) {
-               cd_setreg(com, CD1400_SCHR3, com->hotchar);
-               cd_setreg(com, CD1400_SCHR4, com->hotchar);
-               opt |= CD1400_COR3_SCD34;
-       }
-       if (opt != com->cor[2]) {
-               cd_setreg(com, CD1400_COR3, com->cor[2] = opt);
-               cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3);
-       }
-#endif
-       lwkt_reltoken(&tty_token);
-}
-
-#ifdef Smarts
-/* standard line discipline input routine */
-int
-cyinput(int c, struct tty *tp)
-{
-       /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK
-        * bits, as they are done by the CD1400.  Hardly worth the effort,
-        * given that high-throughput sessions are raw anyhow.
-        */
-}
-#endif /* Smarts */
-
-static int
-comspeed(speed_t speed, u_long cy_clock, int *prescaler_io)
-{
-       int     actual;
-       int     error;
-       int     divider;
-       int     prescaler;
-       int     prescaler_unit;
-
-       if (speed == 0)
-               return (0);
-       if (speed < 0 || speed > 150000)
-               return (-1);
-
-       /* determine which prescaler to use */
-       for (prescaler_unit = 4, prescaler = 2048; prescaler_unit;
-               prescaler_unit--, prescaler >>= 2) {
-               if (cy_clock / prescaler / speed > 63)
-                       break;
-       }
-
-       divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */
-       if (divider > 255)
-               divider = 255;
-       actual = cy_clock/prescaler/divider;
-
-       /* 10 times error in percent: */
-       error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2;
-
-       /* 3.0% max error tolerance */
-       if (error < -30 || error > 30)
-               return (-1);
-
-#if 0
-       kprintf("prescaler = %d (%d)\n", prescaler, prescaler_unit);
-       kprintf("divider = %d (%x)\n", divider, divider);
-       kprintf("actual = %d\n", actual);
-       kprintf("error = %d\n", error);
-#endif
-
-       *prescaler_io = prescaler_unit;
-       return (divider);
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static void
-cd1400_channel_cmd(struct com_s *com, int cmd)
-{
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-       cd1400_channel_cmd_wait(com);
-       cd_setreg(com, CD1400_CCR, cmd);
-       cd1400_channel_cmd_wait(com);
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static void
-cd1400_channel_cmd_wait(struct com_s *com)
-{
-       struct timeval  start;
-       struct timeval  tv;
-       long            usec;
-
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-
-       if (cd_getreg(com, CD1400_CCR) == 0)
-               return;
-       microtime(&start);
-       for (;;) {
-               if (cd_getreg(com, CD1400_CCR) == 0)
-                       return;
-               microtime(&tv);
-               usec = 1000000 * (tv.tv_sec - start.tv_sec) +
-                   tv.tv_usec - start.tv_usec;
-               if (usec >= 5000) {
-                       log(LOG_ERR,
-                           "cy%d: channel command timeout (%ld usec)\n",
-                           com->unit, usec);
-                       return;
-               }
-       }
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static void
-cd_etc(struct com_s *com, int etc)
-{
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-       /*
-        * We can't change the hardware's ETC state while there are any
-        * characters in the tx fifo, since those characters would be
-        * interpreted as commands!  Unputting characters from the fifo
-        * is difficult, so we wait up to 12 character times for the fifo
-        * to drain.  The command will be delayed for up to 2 character
-        * times for the tx to become empty.  Unputting characters from
-        * the tx holding and shift registers is impossible, so we wait
-        * for the tx to become empty so that the command is sure to be
-        * executed soon after we issue it.
-        */
-       disable_intr();
-       if (com->etc == etc) {
-               enable_intr();
-               goto wait;
-       }
-       if ((etc == CD1400_ETC_SENDBREAK
-           && (com->etc == ETC_BREAK_STARTING
-               || com->etc == ETC_BREAK_STARTED))
-           || (etc == CD1400_ETC_STOPBREAK
-              && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED
-                  || com->etc == ETC_NONE))) {
-               enable_intr();
-               return;
-       }
-       com->etc = etc;
-       cd_setreg(com, CD1400_SRER,
-                 com->intr_enable
-                 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY);
-       enable_intr();
-wait:
-       while (com->etc == etc
-              && tsleep(&com->etc, PCATCH, "cyetc", 0) == 0)
-               continue;
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static int
-cd_getreg(struct com_s *com, int reg)
-{
-       struct com_s    *basecom;
-       u_char  car;
-       int     cy_align;
-       u_long  ef;
-       cy_addr iobase;
-       int     val;
-
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-
-       basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
-       car = com->unit & CD1400_CAR_CHAN;
-       cy_align = com->cy_align;
-       iobase = com->iobase;
-       ef = read_eflags();
-       if (ef & PSL_I)
-               disable_intr();
-       if (basecom->car != car)
-               cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
-       val = cd_inb(iobase, reg, cy_align);
-       if (ef & PSL_I)
-               enable_intr();
-       return (val);
-}
-
-/*
- * NOTE: Must be called with tty_token held
- */
-static void
-cd_setreg(struct com_s *com, int reg, int val)
-{
-       struct com_s    *basecom;
-       u_char  car;
-       int     cy_align;
-       u_long  ef;
-       cy_addr iobase;
-
-       ASSERT_LWKT_TOKEN_HELD(&tty_token);
-
-       basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
-       car = com->unit & CD1400_CAR_CHAN;
-       cy_align = com->cy_align;
-       iobase = com->iobase;
-       ef = read_eflags();
-       if (ef & PSL_I)
-               disable_intr();
-       if (basecom->car != car)
-               cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
-       cd_outb(iobase, reg, cy_align, val);
-       if (ef & PSL_I)
-               enable_intr();
-}
-
-#ifdef CyDebug
-/* useful in ddb */
-void
-cystatus(int unit)
-{
-       struct com_s    *com;
-       cy_addr         iobase;
-       u_int           ocount;
-       struct tty      *tp;
-
-       com = com_addr(unit);
-       kprintf("info for channel %d\n", unit);
-       kprintf("------------------\n");
-       kprintf("total cyclom service probes:\t%d\n", cy_svrr_probes);
-       kprintf("calls to upper layer:\t\t%d\n", cy_timeouts);
-       if (com == NULL)
-               return;
-       lwkt_gettoken(&tty_token);
-       iobase = com->iobase;
-       kprintf("\n");
-       kprintf("cd1400 base address:\\tt%p\n", iobase);
-       kprintf("saved channel_control:\t\t0x%02x\n", com->channel_control);
-       kprintf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n",
-              com->cor[0], com->cor[1], com->cor[2]);
-       kprintf("service request enable reg:\t0x%02x (0x%02x cached)\n",
-              cd_getreg(com, CD1400_SRER), com->intr_enable);
-       kprintf("service request register:\t0x%02x\n",
-              cd_inb(iobase, CD1400_SVRR, com->cy_align));
-       kprintf("modem status:\t\t\t0x%02x (0x%02x cached)\n",
-              cd_getreg(com, CD1400_MSVR2), com->prev_modem_status);
-       kprintf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n",
-              cd_inb(iobase, CD1400_RIR, com->cy_align),
-              cd_inb(iobase, CD1400_TIR, com->cy_align),
-              cd_inb(iobase, CD1400_MIR, com->cy_align));
-       kprintf("\n");
-       kprintf("com state:\t\t\t0x%02x\n", com->state);
-       kprintf("calls to comstart():\t\t%d (%d useful)\n",
-              com->start_count, com->start_real);
-       kprintf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf);
-       ocount = 0;
-       if (com->obufs[0].l_queued)
-               ocount += com->obufs[0].l_tail - com->obufs[0].l_head;
-       if (com->obufs[1].l_queued)
-               ocount += com->obufs[1].l_tail - com->obufs[1].l_head;
-       kprintf("tx buffer chars:\t\t%u\n", ocount);
-       kprintf("received chars:\t\t\t%d\n", com->bytes_in);
-       kprintf("received exceptions:\t\t%d\n", com->recv_exception);
-       kprintf("modem signal deltas:\t\t%d\n", com->mdm);
-       kprintf("transmitted chars:\t\t%d\n", com->bytes_out);
-       kprintf("\n");
-       tp = com->tp;
-       if (tp != NULL) {
-               kprintf("tty state:\t\t\t0x%08x\n", tp->t_state);
-               kprintf(
-               "upper layer queue lengths:\t%d raw, %d canon, %d output\n",
-                      tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc);
-       } else {
-               kprintf("tty state:\t\t\tclosed\n");
-       }
-       lwkt_reltoken(&tty_token);
-}
-#endif /* CyDebug */
diff --git a/sys/dev/serial/cy/cy_pci.c b/sys/dev/serial/cy/cy_pci.c
deleted file mode 100644 (file)
index 69cacce..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 1996, David Greenman
- * 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 unmodified, 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 AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD: src/sys/pci/cy_pci.c,v 1.17.2.1 2002/03/17 04:14:18 bde Exp $
- * $DragonFly: src/sys/dev/serial/cy/cy_pci.c,v 1.10 2007/04/12 18:35:08 swildner Exp $
- */
-
-/*
- * Cyclades Y PCI serial interface driver
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/bus.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#include <bus/pci/pcivar.h>
-
-#include "cy_pcireg.h"
-
-static const char *cy_probe            (pcici_t, pcidi_t);
-static void cy_attach          (pcici_t, int);
-
-extern int cyattach_common(void *, int); /* Not exactly correct */
-extern void cyintr(int);
-
-static u_long cy_count;
-
-static struct pci_device cy_device = {
-        "cy",
-        cy_probe,
-        cy_attach,
-        &cy_count,
-        NULL
-};
-COMPAT_PCI_DRIVER(cy_pci, cy_device);
-
-static const char *
-cy_probe(pcici_t config_id, pcidi_t device_id)
-{
-       device_id &= ~0x00060000;
-       if (device_id == 0x0100120e || device_id == 0x0101120e)
-               return ("Cyclades Cyclom-Y Serial Adapter");
-       return (NULL);
-}
-
-static void
-cy_attach(pcici_t config_id, int unit)
-{
-       vm_offset_t paddr;
-       void *vaddr;
-       u_int32_t ioport;
-       int adapter;
-       u_char plx_ver;
-
-       ioport = (u_int32_t) pci_conf_read(config_id, CY_PCI_BASE_ADDR1) & ~0x3;
-       paddr = pci_conf_read(config_id, CY_PCI_BASE_ADDR2) & ~0xf;
-#if 0
-       if (!pci_map_mem(config_id, CY_PCI_BASE_ADDR2, &vaddr, &paddr)) {
-               kprintf("cy%d: couldn't map shared memory\n", unit);
-               return;
-       };
-#endif
-       vaddr = pmap_mapdev(paddr, 0x4000);
-
-       adapter = cyattach_common(vaddr, 1);
-       if (adapter < 0) {
-               /*
-                * No ports found. Release resources and punt.
-                */
-               kprintf("cy%d: no ports found!\n", unit);
-               goto fail;
-       }
-
-       /*
-        * Allocate our interrupt.
-        * XXX  Using the ISA interrupt handler directly is a bit of a violation
-        *      since it doesn't actually take the same argument. For PCI, the
-        *      argument is a void * token, but for ISA it is a unit. Since
-        *      there is no overlap in PCI/ISA unit numbers for this driver, and
-        *      since the ISA driver must handle the interrupt anyway, we use
-        *      the unit number as the token even for PCI.
-        */
-       if (!pci_map_int_right(config_id, (pci_inthand_t *)cyintr,
-                              (void *)adapter, INTR_MPSAFE)) {
-               kprintf("cy%d: couldn't map interrupt\n", unit);
-               goto fail;
-       }
-
-       /*
-        * Enable the "local" interrupt input to generate a
-        * PCI interrupt.
-        */
-       plx_ver = *((u_char *)vaddr + PLX_VER) & 0x0f;
-       switch (plx_ver) {
-       case PLX_9050:
-               outw(ioport + CY_PLX_9050_ICS,
-                   CY_PLX_9050_ICS_IENABLE | CY_PLX_9050_ICS_LOCAL_IENABLE |
-                   CY_PLX_9050_ICS_LOCAL_IPOLARITY);
-               break;
-       case PLX_9060:
-       case PLX_9080:
-       default:                /* Old board, use PLX_9060 values. */
-               outw(ioport + CY_PLX_9060_ICS,
-                   inw(ioport + CY_PLX_9060_ICS) | CY_PLX_9060_ICS_IENABLE |
-                   CY_PLX_9060_ICS_LOCAL_IENABLE);
-               break;
-       }
-
-       return;
-
-fail:
-       /* XXX should release any allocated virtual memory */
-       return;
-}
diff --git a/sys/dev/serial/cy/cy_pcireg.h b/sys/dev/serial/cy/cy_pcireg.h
deleted file mode 100644 (file)
index 851d37c..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 1996, David Greenman
- * 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 unmodified, 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 AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD: src/sys/pci/cy_pcireg.h,v 1.7.2.1 2002/03/17 04:14:18 bde Exp $
- * $DragonFly: src/sys/dev/serial/cy/cy_pcireg.h,v 1.2 2003/06/17 04:28:56 dillon Exp $
- */
-
-#define CY_PCI_BASE_ADDR0              0x10
-#define CY_PCI_BASE_ADDR1              0x14
-#define CY_PCI_BASE_ADDR2              0x18
-
-#define CY_PLX_9050_ICS                        0x4c
-#define CY_PLX_9060_ICS                        0x68
-#define CY_PLX_9050_ICS_IENABLE                0x040
-#define CY_PLX_9050_ICS_LOCAL_IENABLE  0x001
-#define CY_PLX_9050_ICS_LOCAL_IPOLARITY        0x002
-#define CY_PLX_9060_ICS_IENABLE                0x100
-#define CY_PLX_9060_ICS_LOCAL_IENABLE  0x800
-
-/* Cyclom-Y Custom Register for PLX ID. */
-#define        PLX_VER                         0x3400
-#define        PLX_9050                        0x0b
-#define        PLX_9060                        0x0c
-#define        PLX_9080                        0x0d
diff --git a/sys/dev/serial/cy/cyreg.h b/sys/dev/serial/cy/cyreg.h
deleted file mode 100644 (file)
index 99c483f..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*-
- * Copyright (c) 1995 Bruce Evans.
- * 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 author nor the names of contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD: src/sys/i386/isa/cyreg.h,v 1.9 1999/08/28 00:44:40 peter Exp $
- * $DragonFly: src/sys/dev/serial/cy/cyreg.h,v 1.2 2003/06/17 04:28:37 dillon Exp $
- */
-
-/*
- * Definitions for Cyclades Cyclom-Y serial boards.
- */
-
-/*
- * Cyclades register offsets.  These are physical offsets for ISA boards
- * and physical offsets divided by 2 for PCI boards.
- */
-#define        CY8_SVCACKR             0x100   /* (r) */
-#define        CY8_SVCACKT             0x200   /* (r) */
-#define        CY8_SVCACKM             0x300   /* (r) */
-#define        CY16_RESET              0x1400  /* (r) */
-#define        CY_CLEAR_INTR           0x1800  /* intr ack address (w) */
-
-#define        CY_MAX_CD1400s          8       /* for Cyclom-32Y */
-
-#define        CY_CLOCK(version)       ((version) >= 0x48 ? 60000000 : 25000000)
-#define        CY_RTS_DTR_SWAPPED(version)     ((version) >= 0x48)
-
-/*
- * The `cd' macros are for access to cd1400 registers.  The `cy' macros
- * are for access to Cyclades registers.  Both sets of macros scale the
- * register number to get an offset, but the scales are different for
- * mostly historical reasons.
- */
-#ifdef CyDebug
-#define        cd_inb(iobase, reg, cy_align) \
-       (++cd_inbs, *((iobase) + (2 * (reg) << (cy_align))))
-#define        cy_inb(iobase, reg, cy_align) \
-       (++cy_inbs, *((iobase) + ((reg) << (cy_align))))
-#define        cd_outb(iobase, reg, cy_align, val) \
-       (++cd_outbs, (void)(*((iobase) + (2 * (reg) << (cy_align))) = (val)))
-#define        cy_outb(iobase, reg, cy_align, val) \
-       (++cy_outbs, (void)(*((iobase) + ((reg) << (cy_align))) = (val)))
-#else
-#define        cd_inb(iobase, reg, cy_align) \
-       (*((iobase) + (2 * (reg) << (cy_align))))
-#define        cy_inb(iobase, reg, cy_align) \
-       (*((iobase) + ((reg) << (cy_align))))
-#define        cd_outb(iobase, reg, cy_align, val) \
-       ((void)(*((iobase) + (2 * (reg) << (cy_align))) = (val)))
-#define        cy_outb(iobase, reg, cy_align, val) \
-       ((void)(*((iobase) + ((reg) << (cy_align))) = (val)))
-#endif
diff --git a/sys/dev/serial/stl/sc26198.h b/sys/dev/serial/stl/sc26198.h
deleted file mode 100644 (file)
index d059734..0000000
+++ /dev/null
@@ -1,546 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sc26198.h  -- SC26198 UART hardware info.
- *
- * Copyright (c) 1995-1998 Greg Ungerer (gerg@stallion.oz.au).
- * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by Greg Ungerer.
- * 4. Neither the name of the author nor the names of any co-contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD: src/sys/i386/isa/ic/sc26198.h,v 1.1.2.1 2001/08/30 12:29:55 murray Exp $
- */
-
-/*****************************************************************************/
-#ifndef        _SC26198_H
-#define        _SC26198_H
-/*****************************************************************************/
-
-/*
- *     Define the number of async ports per sc26198 uart device.
- */
-#define        SC26198_PORTS           8
-
-/*
- *     Baud rate timing clocks. All derived from a master 14.7456 MHz clock.
- */
-#define        SC26198_MASTERCLOCK     14745600L
-#define        SC26198_DCLK            (SC26198_MASTERCLOCK)
-#define        SC26198_CCLK            (SC26198_MASTERCLOCK / 2)
-#define        SC26198_BCLK            (SC26198_MASTERCLOCK / 4)
-
-/*
- *     Define internal FIFO sizes for the 26198 ports.
- */
-#define        SC26198_TXFIFOSIZE      16
-#define        SC26198_RXFIFOSIZE      16
-
-/*****************************************************************************/
-
-/*
- *     Global register definitions. These registers are global to each 26198
- *     device, not specific ports on it.
- */
-#define        TSTR            0x0d
-#define        GCCR            0x0f
-#define        ICR             0x1b
-#define        WDTRCR          0x1d
-#define        IVR             0x1f
-#define        BRGTRUA         0x84
-#define        GPOSR           0x87
-#define        GPOC            0x8b
-#define        UCIR            0x8c
-#define        CIR             0x8c
-#define        BRGTRUB         0x8d
-#define        GRXFIFO         0x8e
-#define        GTXFIFO         0x8e
-#define        GCCR2           0x8f
-#define        BRGTRLA         0x94
-#define        GPOR            0x97
-#define        GPOD            0x9b
-#define        BRGTCR          0x9c
-#define        GICR            0x9c
-#define        BRGTRLB         0x9d
-#define        GIBCR           0x9d
-#define        GITR            0x9f
-
-/*
- *     Per port channel registers. These are the register offsets within
- *     the port address space, so need to have the port address (0 to 7)
- *     inserted in bit positions 4:6.
- */
-#define        MR0             0x00
-#define        MR1             0x01
-#define        IOPCR           0x02
-#define        BCRBRK          0x03
-#define        BCRCOS          0x04
-#define        BCRX            0x06
-#define        BCRA            0x07
-#define        XONCR           0x08
-#define        XOFFCR          0x09
-#define        ARCR            0x0a
-#define        RXCSR           0x0c
-#define        TXCSR           0x0e
-#define        MR2             0x80
-#define        SR              0x81
-#define SCCR           0x81
-#define        ISR             0x82
-#define        IMR             0x82
-#define        TXFIFO          0x83
-#define        RXFIFO          0x83
-#define        IPR             0x84
-#define        IOPIOR          0x85
-#define        XISR            0x86
-
-/*
- *     For any given port calculate the address to use to access a specified
- *     register. This is only used for unusual access...
- */
-#define        SC26198_PORTREG(port,reg)       ((((port) & 0x07) << 4) | (reg))
-
-/*****************************************************************************/
-
-/*
- *     Global configuration control register bit definitions.
- */
-#define        GCCR_NOACK              0x00
-#define        GCCR_IVRACK             0x02
-#define        GCCR_IVRCHANACK         0x04
-#define        GCCR_IVRTYPCHANACK      0x06
-#define        GCCR_ASYNCCYCLE         0x00
-#define        GCCR_SYNCCYCLE          0x40
-
-/*****************************************************************************/
-
-/*
- *     Mode register 0 bit definitions.
- */
-#define        MR0_ADDRNONE            0x00
-#define        MR0_AUTOWAKE            0x01
-#define        MR0_AUTODOZE            0x02
-#define        MR0_AUTOWAKEDOZE        0x03
-#define        MR0_SWFNONE             0x00
-#define        MR0_SWFTX               0x04
-#define        MR0_SWFRX               0x08
-#define        MR0_SWFRXTX             0x0c
-#define        MR0_TXMASK              0x30
-#define        MR0_TXEMPTY             0x00
-#define        MR0_TXHIGH              0x10
-#define        MR0_TXHALF              0x20
-#define        MR0_TXRDY               0x00
-#define        MR0_ADDRNT              0x00
-#define        MR0_ADDRT               0x40
-#define        MR0_SWFNT               0x00
-#define        MR0_SWFT                0x80
-
-/*
- *     Mode register 1 bit definitions.
- */
-#define        MR1_CS5                 0x00
-#define        MR1_CS6                 0x01
-#define        MR1_CS7                 0x02
-#define        MR1_CS8                 0x03
-#define        MR1_PAREVEN             0x00
-#define        MR1_PARODD              0x04
-#define        MR1_PARENB              0x00
-#define        MR1_PARFORCE            0x08
-#define        MR1_PARNONE             0x10
-#define        MR1_PARSPECIAL          0x18
-#define        MR1_ERRCHAR             0x00
-#define        MR1_ERRBLOCK            0x20
-#define        MR1_ISRUNMASKED         0x00
-#define        MR1_ISRMASKED           0x40
-#define        MR1_AUTORTS             0x80
-
-/*
- *     Mode register 2 bit definitions.
- */
-#define        MR2_STOP1               0x00
-#define        MR2_STOP15              0x01
-#define        MR2_STOP2               0x02
-#define        MR2_STOP916             0x03
-#define        MR2_RXFIFORDY           0x00
-#define        MR2_RXFIFOHALF          0x04
-#define        MR2_RXFIFOHIGH          0x08
-#define        MR2_RXFIFOFULL          0x0c
-#define        MR2_AUTOCTS             0x10
-#define        MR2_TXRTS               0x20
-#define        MR2_MODENORM            0x00
-#define        MR2_MODEAUTOECHO        0x40
-#define        MR2_MODELOOP            0x80
-#define        MR2_MODEREMECHO         0xc0
-
-/*****************************************************************************/
-
-/*
- *     Baud Rate Generator (BRG) selector values.
- */
-#define        BRG_50                  0x00
-#define        BRG_75                  0x01
-#define        BRG_150                 0x02
-#define        BRG_200                 0x03
-#define        BRG_300                 0x04
-#define        BRG_450                 0x05
-#define        BRG_600                 0x06
-#define        BRG_900                 0x07
-#define        BRG_1200                0x08
-#define        BRG_1800                0x09
-#define        BRG_2400                0x0a
-#define        BRG_3600                0x0b
-#define        BRG_4800                0x0c
-#define        BRG_7200                0x0d
-#define        BRG_9600                0x0e
-#define        BRG_14400               0x0f
-#define        BRG_19200               0x10
-#define        BRG_28200               0x11
-#define        BRG_38400               0x12
-#define        BRG_57600               0x13
-#define        BRG_115200              0x14
-#define        BRG_230400              0x15
-#define        BRG_GIN0                0x16
-#define        BRG_GIN1                0x17
-#define        BRG_CT0                 0x18
-#define        BRG_CT1                 0x19
-#define        BRG_RX2TX316            0x1b
-#define        BRG_RX2TX31             0x1c
-
-/*****************************************************************************/
-
-/*
- *     Command register command definitions.
- */
-#define        CR_NULL                 0x04
-#define        CR_ADDRNORMAL           0x0c
-#define        CR_RXRESET              0x14
-#define        CR_TXRESET              0x1c
-#define        CR_CLEARRXERR           0x24
-#define        CR_BREAKRESET           0x2c
-#define        CR_TXSTARTBREAK         0x34
-#define        CR_TXSTOPBREAK          0x3c
-#define        CR_RTSON                0x44
-#define        CR_RTSOFF               0x4c
-#define        CR_ADDRINIT             0x5c
-#define        CR_RXERRBLOCK           0x6c
-#define        CR_TXSENDXON            0x84
-#define        CR_TXSENDXOFF           0x8c
-#define        CR_GANGXONSET           0x94
-#define        CR_GANGXOFFSET          0x9c
-#define        CR_GANGXONINIT          0xa4
-#define        CR_GANGXOFFINIT         0xac
-#define        CR_HOSTXON              0xb4
-#define        CR_HOSTXOFF             0xbc
-#define        CR_CANCELXOFF           0xc4
-#define        CR_ADDRRESET            0xdc
-#define        CR_RESETALLPORTS        0xf4
-#define        CR_RESETALL             0xfc
-
-#define        CR_RXENABLE             0x01
-#define        CR_TXENABLE             0x02
-
-/*****************************************************************************/
-
-/*
- *     Channel status register.
- */
-#define        SR_RXRDY                0x01
-#define        SR_RXFULL               0x02
-#define        SR_TXRDY                0x04
-#define        SR_TXEMPTY              0x08
-#define        SR_RXOVERRUN            0x10
-#define        SR_RXPARITY             0x20
-#define        SR_RXFRAMING            0x40
-#define        SR_RXBREAK              0x80
-
-#define        SR_RXERRS               (SR_RXPARITY | SR_RXFRAMING | SR_RXOVERRUN)
-
-/*****************************************************************************/
-
-/*
- *     Interrupt status register and interrupt mask register bit definitions.
- */
-#define        IR_TXRDY                0x01
-#define        IR_RXRDY                0x02
-#define        IR_RXBREAK              0x04
-#define        IR_XONXOFF              0x10
-#define        IR_ADDRRECOG            0x20
-#define        IR_RXWATCHDOG           0x40
-#define        IR_IOPORT               0x80
-
-/*****************************************************************************/
-
-/*
- *     Interrupt vector register field definitions.
- */
-#define        IVR_CHANMASK            0x07
-#define        IVR_TYPEMASK            0x18
-#define        IVR_CONSTMASK           0xc0
-
-#define        IVR_RXDATA              0x10
-#define        IVR_RXBADDATA           0x18
-#define        IVR_TXDATA              0x08
-#define        IVR_OTHER               0x00
-
-/*****************************************************************************/
-
-/*
- *     BRG timer control register bit definitions.
- */
-#define        BRGCTCR_DISABCLK0       0x00
-#define        BRGCTCR_ENABCLK0        0x08
-#define        BRGCTCR_DISABCLK1       0x00
-#define        BRGCTCR_ENABCLK1        0x80
-
-#define        BRGCTCR_0SCLK16         0x00
-#define        BRGCTCR_0SCLK32         0x01
-#define        BRGCTCR_0SCLK64         0x02
-#define        BRGCTCR_0SCLK128        0x03
-#define        BRGCTCR_0X1             0x04
-#define        BRGCTCR_0X12            0x05
-#define        BRGCTCR_0IO1A           0x06
-#define        BRGCTCR_0GIN0           0x07
-
-#define        BRGCTCR_1SCLK16         0x00
-#define        BRGCTCR_1SCLK32         0x10
-#define        BRGCTCR_1SCLK64         0x20
-#define        BRGCTCR_1SCLK128        0x30
-#define        BRGCTCR_1X1             0x40
-#define        BRGCTCR_1X12            0x50
-#define        BRGCTCR_1IO1B           0x60
-#define        BRGCTCR_1GIN1           0x70
-
-/*****************************************************************************/
-
-/*
- *     Watch dog timer enable register.
- */
-#define        WDTRCR_ENABALL          0xff
-
-/*****************************************************************************/
-
-/*
- *     XON/XOFF interrupt status register.
- */
-#define        XISR_TXCHARMASK         0x03
-#define        XISR_TXCHARNORMAL       0x00
-#define        XISR_TXWAIT             0x01
-#define        XISR_TXXOFFPEND         0x02
-#define        XISR_TXXONPEND          0x03
-
-#define        XISR_TXFLOWMASK         0x0c
-#define        XISR_TXNORMAL           0x00
-#define        XISR_TXSTOPPEND         0x04
-#define        XISR_TXSTARTED          0x08
-#define        XISR_TXSTOPPED          0x0c
-
-#define        XISR_RXFLOWMASK         0x30
-#define        XISR_RXFLOWNONE         0x00
-#define        XISR_RXXONSENT          0x10
-#define        XISR_RXXOFFSENT         0x20
-
-#define        XISR_RXXONGOT           0x40
-#define        XISR_RXXOFFGOT          0x80
-
-/*****************************************************************************/
-
-/*
- *     Current interrupt register.
- */
-#define        CIR_TYPEMASK            0xc0
-#define        CIR_TYPEOTHER           0x00
-#define        CIR_TYPETX              0x40
-#define        CIR_TYPERXGOOD          0x80
-#define        CIR_TYPERXBAD           0xc0
-
-#define        CIR_RXDATA              0x80
-#define        CIR_RXBADDATA           0x40
-#define        CIR_TXDATA              0x40
-
-#define        CIR_CHANMASK            0x07
-#define        CIR_CNTMASK             0x38
-
-#define        CIR_SUBTYPEMASK         0x38
-#define        CIR_SUBNONE             0x00
-#define        CIR_SUBCOS              0x08
-#define        CIR_SUBADDR             0x10
-#define        CIR_SUBXONXOFF          0x18
-#define        CIR_SUBBREAK            0x28
-
-/*****************************************************************************/
-
-/*
- *     Global interrupting channel register.
- */
-#define        GICR_CHANMASK           0x07
-
-/*****************************************************************************/
-
-/*
- *     Global interrupting byte count register.
- */
-#define        GICR_COUNTMASK          0x0f
-
-/*****************************************************************************/
-
-/*
- *     Global interrupting type register.
- */
-#define        GITR_RXMASK             0xc0
-#define        GITR_RXNONE             0x00
-#define        GITR_RXBADDATA          0x80
-#define        GITR_RXGOODDATA         0xc0
-#define        GITR_TXDATA             0x20
-
-#define        GITR_SUBTYPEMASK        0x07
-#define        GITR_SUBNONE            0x00
-#define        GITR_SUBCOS             0x01
-#define        GITR_SUBADDR            0x02
-#define        GITR_SUBXONXOFF         0x03
-#define        GITR_SUBBREAK           0x05
-
-/*****************************************************************************/
-
-/*
- *     Input port change register.
- */
-#define        IPR_CTS                 0x01
-#define        IPR_DTR                 0x02
-#define        IPR_RTS                 0x04
-#define        IPR_DCD                 0x08
-#define        IPR_CTSCHANGE           0x10
-#define        IPR_DTRCHANGE           0x20
-#define        IPR_RTSCHANGE           0x40
-#define        IPR_DCDCHANGE           0x80
-
-#define        IPR_CHANGEMASK          0xf0
-
-/*****************************************************************************/
-
-/*
- *     IO port interrupt and output register.
- */
-#define        IOPR_CTS                0x01
-#define        IOPR_DTR                0x02
-#define        IOPR_RTS                0x04
-#define        IOPR_DCD                0x08
-#define        IOPR_CTSCOS             0x10
-#define        IOPR_DTRCOS             0x20
-#define        IOPR_RTSCOS             0x40
-#define        IOPR_DCDCOS             0x80
-
-/*****************************************************************************/
-
-/*
- *     IO port configuration register.
- */
-#define        IOPCR_SETCTS            0x00
-#define        IOPCR_SETDTR            0x04
-#define        IOPCR_SETRTS            0x10
-#define        IOPCR_SETDCD            0x00
-
-#define        IOPCR_SETSIGS           (IOPCR_SETRTS | IOPCR_SETRTS | IOPCR_SETDTR | IOPCR_SETDCD)
-
-/*****************************************************************************/
-
-/*
- *     General purpose output select register.
- */
-#define        GPORS_TXC1XA            0x08
-#define        GPORS_TXC16XA           0x09
-#define        GPORS_RXC16XA           0x0a
-#define        GPORS_TXC16XB           0x0b
-#define        GPORS_GPOR3             0x0c
-#define        GPORS_GPOR2             0x0d
-#define        GPORS_GPOR1             0x0e
-#define        GPORS_GPOR0             0x0f
-
-/*****************************************************************************/
-
-/*
- *     General purpose output register.
- */
-#define        GPOR_0                  0x01
-#define        GPOR_1                  0x02
-#define        GPOR_2                  0x04
-#define        GPOR_3                  0x08
-
-/*****************************************************************************/
-
-/*
- *     General purpose output clock register.
- */
-#define        GPORC_0NONE             0x00
-#define        GPORC_0GIN0             0x01
-#define        GPORC_0GIN1             0x02
-#define        GPORC_0IO3A             0x02
-
-#define        GPORC_1NONE             0x00
-#define        GPORC_1GIN0             0x04
-#define        GPORC_1GIN1             0x08
-#define        GPORC_1IO3C             0x0c
-
-#define        GPORC_2NONE             0x00
-#define        GPORC_2GIN0             0x10
-#define        GPORC_2GIN1             0x20
-#define        GPORC_2IO3E             0x20
-
-#define        GPORC_3NONE             0x00
-#define        GPORC_3GIN0             0x40
-#define        GPORC_3GIN1             0x80
-#define        GPORC_3IO3G             0xc0
-
-/*****************************************************************************/
-
-/*
- *     General purpose output data register.
- */
-#define        GPOD_0MASK              0x03
-#define        GPOD_0SET1              0x00
-#define        GPOD_0SET0              0x01
-#define        GPOD_0SETR0             0x02
-#define        GPOD_0SETIO3B           0x03
-
-#define        GPOD_1MASK              0x0c
-#define        GPOD_1SET1              0x00
-#define        GPOD_1SET0              0x04
-#define        GPOD_1SETR0             0x08
-#define        GPOD_1SETIO3D           0x0c
-
-#define        GPOD_2MASK              0x30
-#define        GPOD_2SET1              0x00
-#define        GPOD_2SET0              0x10
-#define        GPOD_2SETR0             0x20
-#define        GPOD_2SETIO3F           0x30
-
-#define        GPOD_3MASK              0xc0
-#define        GPOD_3SET1              0x00
-#define        GPOD_3SET0              0x40
-#define        GPOD_3SETR0             0x80
-#define        GPOD_3SETIO3H           0xc0
-
-/*****************************************************************************/
-#endif
diff --git a/sys/dev/serial/stl/scd1400.h b/sys/dev/serial/stl/scd1400.h
deleted file mode 100644 (file)
index 4d6a470..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-/*****************************************************************************/
-
-/*
- *     cd1400.h  -- cd1400 UART hardware info.
- *
- * Copyright (c) 1995 Greg Ungerer (gerg@stallion.oz.au).
- * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by Greg Ungerer.
- * 4. Neither the name of the author nor the names of any co-contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD: src/sys/i386/isa/ic/scd1400.h,v 1.5 1999/08/28 00:45:15 peter Exp $
- */
-
-/*****************************************************************************/
-#ifndef        _CD1400_H
-#define        _CD1400_H
-/*****************************************************************************/
-
-/*
- *     Define the number of async ports per cd1400 uart chip.
- */
-#define        CD1400_PORTS            4
-
-/*
- *     Define the cd1400 uarts internal FIFO sizes.
- */
-#define        CD1400_TXFIFOSIZE       12
-#define        CD1400_RXFIFOSIZE       12
-
-/*
- *     Local RX FIFO thresh hold level. Also define the RTS thresh hold
- *     based on the RX thresh hold.
- */
-#define        FIFO_RXTHRESHOLD        6
-#define        FIFO_RTSTHRESHOLD       7
-
-/*****************************************************************************/
-
-/*
- *     Define the cd1400 register addresses. These are all the valid
- *     registers with the cd1400. Some are global, some virtual, some
- *     per port.
- */
-#define        GFRCR           0x40
-#define        CAR             0x68
-#define        GCR             0x4b
-#define        SVRR            0x67
-#define        RICR            0x44
-#define        TICR            0x45
-#define        MICR            0x46
-#define        RIR             0x6b
-#define        TIR             0x6a
-#define        MIR             0x69
-#define        PPR             0x7e
-
-#define        RIVR            0x43
-#define        TIVR            0x42
-#define        MIVR            0x41
-#define        TDR             0x63
-#define        RDSR            0x62
-#define        MISR            0x4c
-#define        EOSRR           0x60
-
-#define        LIVR            0x18
-#define        CCR             0x05
-#define        SRER            0x06
-#define        COR1            0x08
-#define        COR2            0x09
-#define        COR3            0x0a
-#define        COR4            0x1e
-#define        COR5            0x1f
-#define        CCSR            0x0b
-#define        RDCR            0x0e
-#define        SCHR1           0x1a
-#define        SCHR2           0x1b
-#define        SCHR3           0x1c
-#define        SCHR4           0x1d
-#define        SCRL            0x22
-#define        SCRH            0x23
-#define        LNC             0x24
-#define        MCOR1           0x15
-#define        MCOR2           0x16
-#define        RTPR            0x21
-#define        MSVR1           0x6c
-#define        MSVR2           0x6d
-#define        PSVR            0x6f
-#define        RBPR            0x78
-#define        RCOR            0x7c
-#define        TBPR            0x72
-#define        TCOR            0x76
-
-/*****************************************************************************/
-
-/*
- *     Define the set of baud rate clock divisors.
- */
-#define        CD1400_CLK0     8
-#define        CD1400_CLK1     32
-#define        CD1400_CLK2     128
-#define        CD1400_CLK3     512
-#define        CD1400_CLK4     2048
-
-#define        CD1400_NUMCLKS  5
-
-/*****************************************************************************/
-
-/*
- *     Define the clock pre-scalar value to be a 5 ms clock. This should be
- *     OK for now. It would probably be better to make it 10 ms, but we
- *     can't fit that divisor into 8 bits!
- */
-#define        PPR_SCALAR      244
-
-/*****************************************************************************/
-
-/*
- *     Define values used to set character size options.
- */
-#define        COR1_CHL5       0x00
-#define        COR1_CHL6       0x01
-#define        COR1_CHL7       0x02
-#define        COR1_CHL8       0x03
-
-/*
- *     Define values used to set the number of stop bits.
- */
-#define        COR1_STOP1      0x00
-#define        COR1_STOP15     0x04
-#define        COR1_STOP2      0x08
-
-/*
- *     Define values used to set the parity scheme in use.
- */
-#define        COR1_PARNONE    0x00
-#define        COR1_PARFORCE   0x20
-#define        COR1_PARENB     0x40
-#define        COR1_PARIGNORE  0x10
-
-#define        COR1_PARODD     0x80
-#define        COR1_PAREVEN    0x00
-
-#define        COR2_IXM        0x80
-#define        COR2_TXIBE      0x40
-#define        COR2_ETC        0x20
-#define        COR2_LLM        0x10
-#define        COR2_RLM        0x08
-#define        COR2_RTSAO      0x04
-#define        COR2_CTSAE      0x02
-
-#define        COR3_SCDRNG     0x80
-#define        COR3_SCD34      0x40
-#define        COR3_FCT        0x20
-#define        COR3_SCD12      0x10
-
-/*
- *     Define the bit values of COR4.
- */
-#define        COR4_BRKINT     0x08
-#define        COR4_IGNBRK     0x18
-
-/*
- *     Define the bit values of COR5.
- */
-#define        COR5_ISTRIP     0x80
-
-/*****************************************************************************/
-
-/*
- *     Define the modem control register values.
- *     Note that the actual hardware is a little different to the conventional
- *     pin names on the cd1400.
- */
-#define        MSVR1_DTR       0x01
-#define        MSVR1_DSR       0x10
-#define        MSVR1_RI        0x20
-#define        MSVR1_CTS       0x40
-#define        MSVR1_DCD       0x80
-
-#define        MSVR2_RTS       0x02
-#define        MSVR2_DSR       0x10
-#define        MSVR2_RI        0x20
-#define        MSVR2_CTS       0x40
-#define        MSVR2_DCD       0x80
-
-#define        MCOR1_DCD       0x80
-#define        MCOR1_CTS       0x40
-#define        MCOR1_RI        0x20
-#define        MCOR1_DSR       0x10
-
-#define        MCOR2_DCD       0x80
-#define        MCOR2_CTS       0x40
-#define        MCOR2_RI        0x20
-#define        MCOR2_DSR       0x10
-
-/*****************************************************************************/
-
-/*
- *     Define the bits used with the service (interrupt) enable register.
- */
-#define        SRER_NNDT       0x01
-#define        SRER_TXEMPTY    0x02
-#define        SRER_TXDATA     0x04
-#define        SRER_RXDATA     0x10
-#define        SRER_MODEM      0x80
-
-/*****************************************************************************/
-
-/*
- *     Define operational commands for the command register.
- */
-#define        CCR_RESET       0x80
-#define        CCR_CORCHANGE   0x4e
-#define        CCR_SENDCH      0x20
-#define        CCR_CHANCTRL    0x10
-
-#define        CCR_TXENABLE    (CCR_CHANCTRL | 0x08)
-#define        CCR_TXDISABLE   (CCR_CHANCTRL | 0x04)
-#define        CCR_RXENABLE    (CCR_CHANCTRL | 0x02)
-#define        CCR_RXDISABLE   (CCR_CHANCTRL | 0x01)
-
-#define        CCR_SENDSCHR1   (CCR_SENDCH | 0x01)
-#define        CCR_SENDSCHR2   (CCR_SENDCH | 0x02)
-#define        CCR_SENDSCHR3   (CCR_SENDCH | 0x03)
-#define        CCR_SENDSCHR4   (CCR_SENDCH | 0x04)
-
-#define        CCR_RESETCHAN   (CCR_RESET | 0x00)
-#define        CCR_RESETFULL   (CCR_RESET | 0x01)
-#define        CCR_TXFLUSHFIFO (CCR_RESET | 0x02)
-
-#define        CCR_MAXWAIT     10000
-
-/*****************************************************************************/
-
-/*
- *     Define the valid acknowledgement types (for hw ack cycle).
- */
-#define        ACK_TYPMASK     0x07
-#define        ACK_TYPTX       0x02
-#define        ACK_TYPMDM      0x01
-#define        ACK_TYPRXGOOD   0x03
-#define        ACK_TYPRXBAD    0x07
-
-#define        SVRR_RX         0x01
-#define        SVRR_TX         0x02
-#define        SVRR_MDM        0x04
-
-#define        ST_OVERRUN      0x01
-#define        ST_FRAMING      0x02
-#define        ST_PARITY       0x04
-#define        ST_BREAK        0x08
-#define        ST_SCHAR1       0x10
-#define        ST_SCHAR2       0x20
-#define        ST_SCHAR3       0x30
-#define        ST_SCHAR4       0x40
-#define        ST_RANGE        0x70
-#define        ST_SCHARMASK    0x70
-#define        ST_TIMEOUT      0x80
-
-#define        MISR_DCD        0x80
-#define        MISR_CTS        0x40
-#define        MISR_RI         0x20
-#define        MISR_DSR        0x10
-
-/*****************************************************************************/
-
-/*
- *     Defines for the CCSR status register.
- */
-#define        CCSR_RXENABLED  0x80
-#define        CCSR_RXFLOWON   0x40
-#define        CCSR_RXFLOWOFF  0x20
-#define        CCSR_TXENABLED  0x08
-#define        CCSR_TXFLOWON   0x04
-#define        CCSR_TXFLOWOFF  0x02
-
-/*****************************************************************************/
-
-/*
- *     Define the embedded commands.
- */
-#define        ETC_CMD         0x00
-#define        ETC_STARTBREAK  0x81
-#define        ETC_DELAY       0x82
-#define        ETC_STOPBREAK   0x83
-
-/*****************************************************************************/
-#endif
diff --git a/sys/dev/serial/stl/stallion.c b/sys/dev/serial/stl/stallion.c
deleted file mode 100644 (file)
index 7d490a3..0000000
+++ /dev/null
@@ -1,4449 +0,0 @@
-/*****************************************************************************/
-
-/*
- * stallion.c  -- stallion multiport serial driver.
- *
- * Copyright (c) 1995-1996 Greg Ungerer (gerg@stallion.oz.au).
- * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by Greg Ungerer.
- * 4. Neither the name of the author nor the names of any co-contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD: src/sys/i386/isa/stallion.c,v 1.39.2.2 2001/08/30 12:29:57 murray Exp $
- */
-
-/*****************************************************************************/
-
-#define        TTYDEFCHARS     1
-
-#include "opt_compat.h"
-
-#include <sys/param.h>
-#include <sys/bus.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/tty.h>
-#include <sys/proc.h>
-#include <sys/priv.h>
-#include <sys/conf.h>
-#include <sys/fcntl.h>
-#include <sys/thread2.h>
-#include <dev/serial/stl/scd1400.h>
-#include <dev/serial/stl/sc26198.h>
-#include <machine/comstats.h>
-
-#include <bus/pci/pcivar.h>
-#include <bus/pci/pcireg.h>
-
-#undef STLDEBUG
-
-/*****************************************************************************/
-
-/*
- *     Define different board types. At the moment I have only declared
- *     those boards that this driver supports. But I will use the standard
- *     "assigned" board numbers. In the future this driver will support
- *     some of the other Stallion boards. Currently supported boards are
- *     abbreviated as EIO = EasyIO and ECH = EasyConnection 8/32.
- */
-#define        BRD_EASYIO      20
-#define        BRD_ECH         21
-#define        BRD_ECHMC       22
-#define        BRD_ECHPCI      26
-#define        BRD_ECH64PCI    27
-#define        BRD_EASYIOPCI   28
-
-/*****************************************************************************/
-
-/*
- *     Define important driver limitations.
- */
-#define        STL_MAXBRDS             8
-#define        STL_MAXPANELS           4
-#define        STL_MAXBANKS            8
-#define        STL_PORTSPERPANEL       16
-#define        STL_PORTSPERBRD         64
-
-/*
- *     Define the important minor number break down bits. These have been
- *     chosen to be "compatible" with the standard sio driver minor numbers.
- *     Extra high bits are used to distinguish between boards.
- */
-#define        STL_CALLOUTDEV          0x80
-#define        STL_CTRLLOCK            0x40
-#define        STL_CTRLINIT            0x20
-#define        STL_CTRLDEV             (STL_CTRLLOCK | STL_CTRLINIT)
-
-#define        STL_MEMDEV      0x07000000
-
-#define        STL_DEFSPEED    TTYDEF_SPEED
-#define        STL_DEFCFLAG    (CS8 | CREAD | HUPCL)
-
-/*
- *     I haven't really decided (or measured) what buffer sizes give
- *     a good balance between performance and memory usage. These seem
- *     to work pretty well...
- */
-#define        STL_RXBUFSIZE           2048
-#define        STL_TXBUFSIZE           2048
-
-#define        STL_TXBUFLOW            (STL_TXBUFSIZE / 4)
-#define        STL_RXBUFHIGH           (3 * STL_RXBUFSIZE / 4)
-
-/*****************************************************************************/
-
-/*
- *     Define our local driver identity first. Set up stuff to deal with
- *     all the local structures required by a serial tty driver.
- */
-static const char      stl_drvname[] = "stl";
-static const char      stl_longdrvname[] = "Stallion Multiport Serial Driver";
-static const char      stl_drvversion[] = "2.0.0";
-
-static int             stl_nrbrds = 0;
-static int             stl_doingtimeout = 0;
-static struct callout  stl_poll_ch;
-
-static const char      __file__[] = /*__FILE__*/ "stallion.c";
-
-/*
- *     Define global stats structures. Not used often, and can be
- *     re-used for each stats call.
- */
-static combrd_t                stl_brdstats;
-static comstats_t      stl_comstats;
-
-/*****************************************************************************/
-
-/*
- *     Define a set of structures to hold all the board/panel/port info
- *     for our ports. These will be dynamically allocated as required.
- */
-
-/*
- *     Define a ring queue structure for each port. This will hold the
- *     TX data waiting to be output. Characters are fed into this buffer
- *     from the line discipline (or even direct from user space!) and
- *     then fed into the UARTs during interrupts. Will use a clasic ring
- *     queue here for this. The good thing about this type of ring queue
- *     is that the head and tail pointers can be updated without interrupt
- *     protection - since "write" code only needs to change the head, and
- *     interrupt code only needs to change the tail.
- */
-typedef struct {
-       char    *buf;
-       char    *endbuf;
-       char    *head;
-       char    *tail;
-} stlrq_t;
-
-/*
- *     Port, panel and board structures to hold status info about each.
- *     The board structure contains pointers to structures for each panel
- *     connected to it, and in turn each panel structure contains pointers
- *     for each port structure for each port on that panel. Note that
- *     the port structure also contains the board and panel number that it
- *     is associated with, this makes it (fairly) easy to get back to the
- *     board/panel info for a port. Also note that the tty struct is at
- *     the top of the structure, this is important, since the code uses
- *     this fact to get the port struct pointer from the tty struct
- *     pointer!
- */
-typedef struct stlport {
-       struct tty      tty;
-       int             portnr;
-       int             panelnr;
-       int             brdnr;
-       int             ioaddr;
-       int             uartaddr;
-       int             pagenr;
-       int             callout;
-       int             brklen;
-       int             dtrwait;
-       int             dotimestamp;
-       int             waitopens;
-       int             hotchar;
-       void            *uartp;
-       unsigned int    state;
-       unsigned int    hwid;
-       unsigned int    sigs;
-       unsigned int    rxignoremsk;
-       unsigned int    rxmarkmsk;
-       unsigned int    crenable;
-       unsigned int    imr;
-       unsigned long   clk;
-       struct termios  initintios;
-       struct termios  initouttios;
-       struct termios  lockintios;
-       struct termios  lockouttios;
-       struct timeval  timestamp;
-       comstats_t      stats;
-       stlrq_t         tx;
-       stlrq_t         rx;
-       stlrq_t         rxstatus;
-       struct callout  dtr_ch;
-} stlport_t;
-
-typedef struct stlpanel {
-       int             panelnr;
-       int             brdnr;
-       int             pagenr;
-       int             nrports;
-       int             iobase;
-       unsigned int    hwid;
-       unsigned int    ackmask;
-       void            (*isr)(struct stlpanel *panelp, unsigned int iobase);
-       void            *uartp;
-       stlport_t       *ports[STL_PORTSPERPANEL];
-} stlpanel_t;
-
-typedef struct stlbrd {
-       int             brdnr;
-       int             brdtype;
-       int             unitid;
-       int             state;
-       int             nrpanels;
-       int             nrports;
-       int             nrbnks;
-       int             irq;
-       int             irqtype;
-       unsigned int    ioaddr1;
-       unsigned int    ioaddr2;
-       unsigned int    iostatus;
-       unsigned int    ioctrl;
-       unsigned int    ioctrlval;
-       unsigned int    hwid;
-       unsigned long   clk;
-       void            (*isr)(struct stlbrd *brdp);
-       unsigned int    bnkpageaddr[STL_MAXBANKS];
-       unsigned int    bnkstataddr[STL_MAXBANKS];
-       stlpanel_t      *bnk2panel[STL_MAXBANKS];
-       stlpanel_t      *panels[STL_MAXPANELS];
-       stlport_t       *ports[STL_PORTSPERBRD];
-} stlbrd_t;
-
-static stlbrd_t                *stl_brds[STL_MAXBRDS];
-
-/*
- *     Per board state flags. Used with the state field of the board struct.
- *     Not really much here yet!
- */
-#define        BRD_FOUND       0x1
-
-/*
- *     Define the port structure state flags. These set of flags are
- *     modified at interrupt time - so setting and reseting them needs
- *     to be atomic.
- */
-#define        ASY_TXLOW       0x1
-#define        ASY_RXDATA      0x2
-#define        ASY_DCDCHANGE   0x4
-#define        ASY_DTRWAIT     0x8
-#define        ASY_RTSFLOW     0x10
-#define        ASY_RTSFLOWMODE 0x20
-#define        ASY_CTSFLOWMODE 0x40
-#define        ASY_TXFLOWED    0x80
-#define        ASY_TXBUSY      0x100
-#define        ASY_TXEMPTY     0x200
-
-#define        ASY_ACTIVE      (ASY_TXLOW | ASY_RXDATA | ASY_DCDCHANGE)
-
-/*
- *     Define an array of board names as printable strings. Handy for
- *     referencing boards when printing trace and stuff.
- */
-static char    *stl_brdnames[] = {
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       "EasyIO",
-       "EC8/32-AT",
-       "EC8/32-MC",
-       NULL,
-       NULL,
-       NULL,
-       "EC8/32-PCI",
-       "EC8/64-PCI",
-       "EasyIO-PCI",
-};
-
-/*****************************************************************************/
-
-/*
- *     Hardware ID bits for the EasyIO and ECH boards. These defines apply
- *     to the directly accessable io ports of these boards (not the cd1400
- *     uarts - they are in scd1400.h).
- */
-#define        EIO_8PORTRS     0x04
-#define        EIO_4PORTRS     0x05
-#define        EIO_8PORTDI     0x00
-#define        EIO_8PORTM      0x06
-#define        EIO_MK3         0x03
-#define        EIO_IDBITMASK   0x07
-
-#define        EIO_BRDMASK     0xf0
-#define        ID_BRD4         0x10
-#define        ID_BRD8         0x20
-#define        ID_BRD16        0x30
-
-#define        EIO_INTRPEND    0x08
-#define        EIO_INTEDGE     0x00
-#define        EIO_INTLEVEL    0x08
-
-#define        ECH_ID          0xa0
-#define        ECH_IDBITMASK   0xe0
-#define        ECH_BRDENABLE   0x08
-#define        ECH_BRDDISABLE  0x00
-#define        ECH_INTENABLE   0x01
-#define        ECH_INTDISABLE  0x00
-#define        ECH_INTLEVEL    0x02
-#define        ECH_INTEDGE     0x00
-#define        ECH_INTRPEND    0x01
-#define        ECH_BRDRESET    0x01
-
-#define        ECHMC_INTENABLE 0x01
-#define        ECHMC_BRDRESET  0x02
-
-#define        ECH_PNLSTATUS   2
-#define        ECH_PNL16PORT   0x20
-#define        ECH_PNLIDMASK   0x07
-#define        ECH_PNLXPID     0x40
-#define        ECH_PNLINTRPEND 0x80
-#define        ECH_ADDR2MASK   0x1e0
-
-#define        EIO_CLK         25000000
-#define        EIO_CLK8M       20000000
-#define        ECH_CLK         EIO_CLK
-
-/*
- *      Define the PCI vendor and device ID for Stallion PCI boards.
- */
-#define        STL_PCINSVENDID 0x100b
-#define        STL_PCINSDEVID  0xd001
-
-#define        STL_PCIVENDID   0x124d
-#define        STL_PCI32DEVID  0x0000
-#define        STL_PCI64DEVID  0x0002
-#define        STL_PCIEIODEVID 0x0003
-
-#define        STL_PCIBADCLASS 0x0101
-
-typedef struct stlpcibrd {
-        unsigned short          vendid;
-        unsigned short          devid;
-        int                     brdtype;
-} stlpcibrd_t;
-
-static stlpcibrd_t     stl_pcibrds[] = {
-       { STL_PCIVENDID, STL_PCI64DEVID, BRD_ECH64PCI },
-       { STL_PCIVENDID, STL_PCIEIODEVID, BRD_EASYIOPCI },
-       { STL_PCIVENDID, STL_PCI32DEVID, BRD_ECHPCI },
-       { STL_PCINSVENDID, STL_PCINSDEVID, BRD_ECHPCI },
-};
-
-static int      stl_nrpcibrds = NELEM(stl_pcibrds);
-
-/*****************************************************************************/
-
-/*
- *     Define the vector mapping bits for the programmable interrupt board
- *     hardware. These bits encode the interrupt for the board to use - it
- *     is software selectable (except the EIO-8M).
- */
-static unsigned char   stl_vecmap[] = {
-       0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
-       0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
-};
-
-/*
- *     Set up enable and disable macros for the ECH boards. They require
- *     the secondary io address space to be activated and deactivated.
- *     This way all ECH boards can share their secondary io region.
- *     If this is an ECH-PCI board then also need to set the page pointer
- *     to point to the correct page.
- */
-#define        BRDENABLE(brdnr,pagenr)                                         \
-       if (stl_brds[(brdnr)]->brdtype == BRD_ECH)                      \
-               outb(stl_brds[(brdnr)]->ioctrl,                         \
-                       (stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE));\
-       else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI)              \
-               outb(stl_brds[(brdnr)]->ioctrl, (pagenr));
-
-#define        BRDDISABLE(brdnr)                                               \
-       if (stl_brds[(brdnr)]->brdtype == BRD_ECH)                      \
-               outb(stl_brds[(brdnr)]->ioctrl,                         \
-                       (stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE));
-
-/*
- *      Define some spare buffer space for un-wanted received characters.
- */
-static char     stl_unwanted[SC26198_RXFIFOSIZE];
-
-/*****************************************************************************/
-
-/*
- *     Define macros to extract a brd and port number from a minor number.
- *     This uses the extended minor number range in the upper 2 bytes of
- *     the device number. This gives us plenty of minor numbers to play
- *     with...
- */
-#define        MKDEV2BRD(m)    ((minor(m) & 0x00700000) >> 20)
-#define        MKDEV2PORT(m)   ((minor(m) & 0x1f) | ((minor(m) & 0x00010000) >> 11))
-
-/*
- *     Define some handy local macros...
- */
-#ifndef        MIN
-#define        MIN(a,b)        (((a) <= (b)) ? (a) : (b))
-#endif
-
-/*****************************************************************************/
-
-/*
- *     Declare all those functions in this driver!  First up is the set of
- *     externally visible functions.
- */
-
-static d_open_t        stlopen;
-static d_close_t       stlclose;
-static d_ioctl_t       stlioctl;
-
-/*
- *     Internal function prototypes.
- */
-static stlport_t *stl_dev2port(cdev_t dev);
-static int     stl_findfreeunit(void);
-static int     stl_rawopen(stlport_t *portp);
-static int     stl_rawclose(stlport_t *portp);
-static void    stl_flush(stlport_t *portp, int flag);
-static int     stl_param(struct tty *tp, struct termios *tiosp);
-static void    stl_start(struct tty *tp);
-static void    stl_stop(struct tty *tp, int);
-static void    stl_ttyoptim(stlport_t *portp, struct termios *tiosp);
-static void    stl_dotimeout(void);
-static void    stl_poll(void *arg);
-static void    stl_rxprocess(stlport_t *portp);
-static void    stl_flowcontrol(stlport_t *portp, int hw, int sw);
-static void    stl_dtrwakeup(void *arg);
-static int     stl_brdinit(stlbrd_t *brdp);
-static int     stl_initeio(stlbrd_t *brdp);
-static int     stl_initech(stlbrd_t *brdp);
-static int     stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);
-static void    stl_eiointr(stlbrd_t *brdp);
-static void    stl_echatintr(stlbrd_t *brdp);
-static void    stl_echmcaintr(stlbrd_t *brdp);
-static void    stl_echpciintr(stlbrd_t *brdp);
-static void    stl_echpci64intr(stlbrd_t *brdp);
-static int     stl_memioctl(cdev_t dev, unsigned long cmd, caddr_t data,
-                       int flag);
-static int     stl_getbrdstats(caddr_t data);
-static int     stl_getportstats(stlport_t *portp, caddr_t data);
-static int     stl_clrportstats(stlport_t *portp, caddr_t data);
-static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
-static void    stlintr(void *);
-
-static const char *stlpciprobe(pcici_t tag, pcidi_t type);
-static void    stlpciattach(pcici_t tag, int unit);
-static void    stlpciintr(void * arg);
-
-/*
- *     CD1400 uart specific handling functions.
- */
-static void    stl_cd1400setreg(stlport_t *portp, int regnr, int value);
-static int     stl_cd1400getreg(stlport_t *portp, int regnr);
-static int     stl_cd1400updatereg(stlport_t *portp, int regnr, int value);
-static int     stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp);
-static void    stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
-static int     stl_cd1400setport(stlport_t *portp, struct termios *tiosp);
-static int     stl_cd1400getsignals(stlport_t *portp);
-static void    stl_cd1400setsignals(stlport_t *portp, int dtr, int rts);
-static void    stl_cd1400ccrwait(stlport_t *portp);
-static void    stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx);
-static void    stl_cd1400startrxtx(stlport_t *portp, int rx, int tx);
-static void    stl_cd1400disableintrs(stlport_t *portp);
-static void    stl_cd1400sendbreak(stlport_t *portp, long len);
-static void    stl_cd1400sendflow(stlport_t *portp, int hw, int sw);
-static int     stl_cd1400datastate(stlport_t *portp);
-static void    stl_cd1400flush(stlport_t *portp, int flag);
-static __inline void   stl_cd1400txisr(stlpanel_t *panelp, int ioaddr);
-static void    stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr);
-static void    stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr);
-static void    stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase);
-static void    stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase);
-
-/*
- *     SC26198 uart specific handling functions.
- */
-static void    stl_sc26198setreg(stlport_t *portp, int regnr, int value);
-static int     stl_sc26198getreg(stlport_t *portp, int regnr);
-static int     stl_sc26198updatereg(stlport_t *portp, int regnr, int value);
-static int     stl_sc26198getglobreg(stlport_t *portp, int regnr);
-static int     stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp);
-static void    stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
-static int     stl_sc26198setport(stlport_t *portp, struct termios *tiosp);
-static int     stl_sc26198getsignals(stlport_t *portp);
-static void    stl_sc26198setsignals(stlport_t *portp, int dtr, int rts);
-static void    stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx);
-static void    stl_sc26198startrxtx(stlport_t *portp, int rx, int tx);
-static void    stl_sc26198disableintrs(stlport_t *portp);
-static void    stl_sc26198sendbreak(stlport_t *portp, long len);
-static void    stl_sc26198sendflow(stlport_t *portp, int hw, int sw);
-static int     stl_sc26198datastate(stlport_t *portp);
-static void    stl_sc26198flush(stlport_t *portp, int flag);
-static void    stl_sc26198txunflow(stlport_t *portp);
-static void    stl_sc26198wait(stlport_t *portp);
-static void    stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase);
-static void    stl_sc26198txisr(stlport_t *port);
-static void    stl_sc26198rxisr(stlport_t *port, unsigned int iack);
-static void    stl_sc26198rxgoodchars(stlport_t *portp);
-static void    stl_sc26198rxbadchars(stlport_t *portp);
-static void    stl_sc26198otherisr(stlport_t *port, unsigned int iack);
-
-/*****************************************************************************/
-
-/*
- *      Generic UART support structure.
- */
-typedef struct uart {
-       int     (*panelinit)(stlbrd_t *brdp, stlpanel_t *panelp);
-       void    (*portinit)(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
-       int     (*setport)(stlport_t *portp, struct termios *tiosp);
-       int     (*getsignals)(stlport_t *portp);
-       void    (*setsignals)(stlport_t *portp, int dtr, int rts);
-       void    (*enablerxtx)(stlport_t *portp, int rx, int tx);
-       void    (*startrxtx)(stlport_t *portp, int rx, int tx);
-       void    (*disableintrs)(stlport_t *portp);
-       void    (*sendbreak)(stlport_t *portp, long len);
-       void    (*sendflow)(stlport_t *portp, int hw, int sw);
-       void    (*flush)(stlport_t *portp, int flag);
-       int     (*datastate)(stlport_t *portp);
-       void    (*intr)(stlpanel_t *panelp, unsigned int iobase);
-} uart_t;
-
-/*
- *     Define some macros to make calling these functions nice and clean.
- */
-#define stl_panelinit          (* ((uart_t *) panelp->uartp)->panelinit)
-#define stl_portinit           (* ((uart_t *) portp->uartp)->portinit)
-#define stl_setport            (* ((uart_t *) portp->uartp)->setport)
-#define stl_getsignals         (* ((uart_t *) portp->uartp)->getsignals)
-#define stl_setsignals         (* ((uart_t *) portp->uartp)->setsignals)
-#define stl_enablerxtx         (* ((uart_t *) portp->uartp)->enablerxtx)
-#define stl_startrxtx          (* ((uart_t *) portp->uartp)->startrxtx)
-#define stl_disableintrs       (* ((uart_t *) portp->uartp)->disableintrs)
-#define stl_sendbreak          (* ((uart_t *) portp->uartp)->sendbreak)
-#define stl_sendflow           (* ((uart_t *) portp->uartp)->sendflow)
-#define stl_uartflush          (* ((uart_t *) portp->uartp)->flush)
-#define stl_datastate          (* ((uart_t *) portp->uartp)->datastate)
-
-/*****************************************************************************/
-
-/*
- *      CD1400 UART specific data initialization.
- */
-static uart_t stl_cd1400uart = {
-       stl_cd1400panelinit,
-       stl_cd1400portinit,
-       stl_cd1400setport,
-       stl_cd1400getsignals,
-       stl_cd1400setsignals,
-       stl_cd1400enablerxtx,
-       stl_cd1400startrxtx,
-       stl_cd1400disableintrs,
-       stl_cd1400sendbreak,
-       stl_cd1400sendflow,
-       stl_cd1400flush,
-       stl_cd1400datastate,
-       stl_cd1400eiointr
-};
-
-/*
- *      Define the offsets within the register bank of a cd1400 based panel.
- *      These io address offsets are common to the EasyIO board as well.
- */
-#define        EREG_ADDR       0
-#define        EREG_DATA       4
-#define        EREG_RXACK      5
-#define        EREG_TXACK      6
-#define        EREG_MDACK      7
-
-#define        EREG_BANKSIZE   8
-
-#define        CD1400_CLK      25000000
-#define        CD1400_CLK8M    20000000
-
-/*
- *      Define the cd1400 baud rate clocks. These are used when calculating
- *      what clock and divisor to use for the required baud rate. Also
- *      define the maximum baud rate allowed, and the default base baud.
- */
-static int     stl_cd1400clkdivs[] = {
-       CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
-};
-
-/*
- *      Define the maximum baud rate of the cd1400 devices.
- */
-#define        CD1400_MAXBAUD  230400
-
-/*****************************************************************************/
-
-/*
- *      SC26198 UART specific data initization.
- */
-static uart_t stl_sc26198uart = {
-       stl_sc26198panelinit,
-       stl_sc26198portinit,
-       stl_sc26198setport,
-       stl_sc26198getsignals,
-       stl_sc26198setsignals,
-       stl_sc26198enablerxtx,
-       stl_sc26198startrxtx,
-       stl_sc26198disableintrs,
-       stl_sc26198sendbreak,
-       stl_sc26198sendflow,
-       stl_sc26198flush,
-       stl_sc26198datastate,
-       stl_sc26198intr
-};
-
-/*
- *      Define the offsets within the register bank of a sc26198 based panel.
- */
-#define        XP_DATA         0
-#define        XP_ADDR         1
-#define        XP_MODID        2
-#define        XP_STATUS       2
-#define        XP_IACK         3
-
-#define        XP_BANKSIZE     4
-
-/*
- *      Define the sc26198 baud rate table. Offsets within the table
- *      represent the actual baud rate selector of sc26198 registers.
- */
-static unsigned int    sc26198_baudtable[] = {
-       50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
-       4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
-       230400, 460800
-};
-
-#define        SC26198_NRBAUDS NELEM(sc26198_baudtable)
-
-/*
- *      Define the maximum baud rate of the sc26198 devices.
- */
-#define        SC26198_MAXBAUD 460800
-
-/*****************************************************************************/
-
-/*
- *     Declare the driver pci structure.
- */
-static unsigned long   stl_count;
-
-static struct pci_device       stlpcidriver = {
-       "stl",
-       stlpciprobe,
-       stlpciattach,
-       &stl_count,
-       NULL,
-};
-
-COMPAT_PCI_DRIVER (stlpci, stlpcidriver);
-
-/*****************************************************************************/
-
-/*
- *     FreeBSD-2.2+ kernel linkage.
- */
-
-#define        CDEV_MAJOR      72
-static struct dev_ops stl_ops = {
-       { "stl", 0, D_TTY },
-       .d_open =       stlopen,
-       .d_close =      stlclose,
-       .d_read =       ttyread,
-       .d_write =      ttywrite,
-       .d_ioctl =      stlioctl,
-       .d_kqfilter =   ttykqfilter,
-       .d_revoke =     ttyrevoke
-};
-
-static void stl_drvinit(void *unused)
-{
-}
-
-SYSINIT(sidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,stl_drvinit,NULL);
-
-/*****************************************************************************/
-
-/*
- *     Find an available internal board number (unit number). The problem
- *     is that the same unit numbers can be assigned to different boards
- *     detected during the ISA and PCI initialization phases.
- */
-
-static int stl_findfreeunit(void)
-{
-       int     i;
-
-       for (i = 0; (i < STL_MAXBRDS); i++)
-               if (stl_brds[i] == NULL)
-                       break;
-       return((i >= STL_MAXBRDS) ? -1 : i);
-}
-
-/*****************************************************************************/
-
-/*
- *     Probe specifically for the PCI boards. We need to be a little
- *     carefull here, since it looks sort like a Nat Semi IDE chip...
- */
-
-static const char *stlpciprobe(pcici_t tag, pcidi_t type)
-{
-       unsigned long   class;
-       int             i, brdtype;
-
-#ifdef STLDEBUG
-       kprintf("stlpciprobe(tag=%x,type=%x)\n", (int) &tag, (int) type);
-#endif
-
-       brdtype = 0;
-       for (i = 0; (i < stl_nrpcibrds); i++) {
-               if (((type & 0xffff) == stl_pcibrds[i].vendid) &&
-                    (((type >> 16) & 0xffff) == stl_pcibrds[i].devid)) {
-                        brdtype = stl_pcibrds[i].brdtype;
-                        break;
-                }
-        }
-
-        if (brdtype == 0)
-                return(NULL);
-
-        class = pci_conf_read(tag, PCI_CLASS_REG);
-        if ((class & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE)
-                return(NULL);
-
-        return(stl_brdnames[brdtype]);
-}
-
-/*****************************************************************************/
-
-/*
- *     Allocate resources for and initialize the specified PCI board.
- */
-
-void stlpciattach(pcici_t tag, int unit)
-{
-       stlbrd_t        *brdp;
-        unsigned int    bar[4];
-        unsigned int    id;
-        int             i;
-       int             boardnr, portnr, minor_dev;
-
-#ifdef STLDEBUG
-       kprintf("stlpciattach(tag=%x,unit=%x)\n", (int) &tag, unit);
-#endif
-
-       brdp = kmalloc(sizeof(stlbrd_t), M_TTYS, M_WAITOK | M_ZERO);
-
-       if ((unit < 0) || (unit > STL_MAXBRDS)) {
-               kprintf("STALLION: bad PCI board unit number=%d\n", unit);
-               return;
-       }
-
-/*
- *     Allocate us a new driver unique unit number.
- */
-       if ((brdp->brdnr = stl_findfreeunit()) < 0) {
-               kprintf("STALLION: too many boards found, max=%d\n",
-                       STL_MAXBRDS);
-               return;
-       }
-       if (brdp->brdnr >= stl_nrbrds)
-               stl_nrbrds = brdp->brdnr + 1;
-
-/*
- *      Determine what type of PCI board this is...
- */
-        id = (unsigned int) pci_conf_read(tag, 0x0);
-        for (i = 0; (i < stl_nrpcibrds); i++) {
-                if (((id & 0xffff) == stl_pcibrds[i].vendid) &&
-                    (((id >> 16) & 0xffff) == stl_pcibrds[i].devid)) {
-                        brdp->brdtype = stl_pcibrds[i].brdtype;
-                        break;
-                }
-        }
-
-        if (i >= stl_nrpcibrds) {
-                kprintf("STALLION: probed PCI board unknown type=%x\n", id);
-                return;
-        }
-
-        for (i = 0; (i < 4); i++)
-                bar[i] = (unsigned int) pci_conf_read(tag, 0x10 + (i * 4)) &
-                        0xfffc;
-
-        switch (brdp->brdtype) {
-        case BRD_ECH64PCI:
-                brdp->ioaddr1 = bar[1];
-                brdp->ioaddr2 = bar[2];
-                break;
-        case BRD_EASYIOPCI:
-                brdp->ioaddr1 = bar[2];
-                brdp->ioaddr2 = bar[1];
-                break;
-        case BRD_ECHPCI:
-                brdp->ioaddr1 = bar[1];
-                brdp->ioaddr2 = bar[0];
-                break;
-        default:
-                kprintf("STALLION: unknown PCI board type=%d\n", brdp->brdtype);
-                return;
-                break;
-        }
-
-        brdp->unitid = brdp->brdnr; /* PCI units auto-assigned */
-        brdp->irq = ((int) pci_conf_read(tag, 0x3c)) & 0xff;
-        brdp->irqtype = 0;
-        if (pci_map_int(tag, stlpciintr, NULL) == 0) {
-                kprintf("STALLION: failed to map interrupt irq=%d for unit=%d\n",
-                        brdp->irq, brdp->brdnr);
-                return;
-        }
-
-        stl_brdinit(brdp);
-
-       /* register devices for DEVFS */
-       boardnr = brdp->brdnr;
-       make_dev(&stl_ops, boardnr + 0x1000000, UID_ROOT, GID_WHEEL,
-                0600, "staliomem%d", boardnr);
-
-       for (portnr = 0, minor_dev = boardnr * 0x100000;
-             portnr < 32; portnr++, minor_dev++) {
-               /* hw ports */
-               make_dev(&stl_ops, minor_dev,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "ttyE%d", portnr + (boardnr * 64));
-               make_dev(&stl_ops, minor_dev + 32,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "ttyiE%d", portnr + (boardnr * 64));
-               make_dev(&stl_ops, minor_dev + 64,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "ttylE%d", portnr + (boardnr * 64));
-               make_dev(&stl_ops, minor_dev + 128,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "cue%d", portnr + (boardnr * 64));
-               make_dev(&stl_ops, minor_dev + 160,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "cuie%d", portnr + (boardnr * 64));
-               make_dev(&stl_ops, minor_dev + 192,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "cule%d", portnr + (boardnr * 64));
-
-               /* sw ports */
-               make_dev(&stl_ops, minor_dev + 0x10000,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "ttyE%d", portnr + (boardnr * 64) + 32);
-               make_dev(&stl_ops, minor_dev + 32 + 0x10000,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "ttyiE%d", portnr + (boardnr * 64) + 32);
-               make_dev(&stl_ops, minor_dev + 64 + 0x10000,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "ttylE%d", portnr + (boardnr * 64) + 32);
-               make_dev(&stl_ops, minor_dev + 128 + 0x10000,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "cue%d", portnr + (boardnr * 64) + 32);
-               make_dev(&stl_ops, minor_dev + 160 + 0x10000,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "cuie%d", portnr + (boardnr * 64) + 32);
-               make_dev(&stl_ops, minor_dev + 192 + 0x10000,
-                        UID_ROOT, GID_WHEEL, 0600,
-                        "cule%d", portnr + (boardnr * 64) + 32);
-       }
-}
-
-/*****************************************************************************/
-
-static int stlopen(struct dev_open_args *ap)
-{
-       cdev_t dev = ap->a_head.a_dev;
-       struct tty      *tp;
-       stlport_t       *portp;
-       int             error, callout;
-
-#ifdef STLDEBUG
-       kprintf("stlopen(dev=%x,flag=%x,mode=%x,p=%x)\n", (int) dev, flag,
-               mode, (int) p);
-#endif
-
-/*
- *     Firstly check if the supplied device number is a valid device.
- */
-       if (minor(dev) & STL_MEMDEV)
-               return(0);
-
-       portp = stl_dev2port(dev);
-       if (portp == NULL)
-               return(ENXIO);
-        if (minor(dev) & STL_CTRLDEV)
-                return(0);
-       tp = &portp->tty;
-       dev->si_tty = tp;
-       callout = minor(dev) & STL_CALLOUTDEV;
-       error = 0;
-
-       crit_enter();
-
-stlopen_restart:
-/*
- *     Wait here for the DTR drop timeout period to expire.
- */
-       while (portp->state & ASY_DTRWAIT) {
-               error = tsleep(&portp->dtrwait, PCATCH, "stldtr", 0);
-               if (error)
-                       goto stlopen_end;
-       }
-       
-/*
- *     We have a valid device, so now we check if it is already open.
- *     If not then initialize the port hardware and set up the tty
- *     struct as required.
- */
-       if ((tp->t_state & TS_ISOPEN) == 0) {
-               tp->t_oproc = stl_start;
-               tp->t_stop = stl_stop;
-               tp->t_param = stl_param;
-               tp->t_dev = dev;
-               tp->t_termios = callout ? portp->initouttios :
-                       portp->initintios;
-               stl_rawopen(portp);
-                ttsetwater(tp);
-               if ((portp->sigs & TIOCM_CD) || callout)
-                       (*linesw[tp->t_line].l_modem)(tp, 1);
-       } else {
-               if (callout) {
-                       if (portp->callout == 0) {
-                               error = EBUSY;
-                               goto stlopen_end;
-                       }
-               } else {
-                       if (portp->callout != 0) {
-                               if (ap->a_oflags & O_NONBLOCK) {
-                                       error = EBUSY;
-                                       goto stlopen_end;
-                               }
-                               error = tsleep(&portp->callout,
-                                           PCATCH, "stlcall", 0);
-                               if (error)
-                                       goto stlopen_end;
-                               goto stlopen_restart;
-                       }
-               }
-               if ((tp->t_state & TS_XCLUDE) && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) {
-                       error = EBUSY;
-                       goto stlopen_end;
-               }
-       }
-
-/*
- *     If this port is not the callout device and we do not have carrier
- *     then we need to sleep, waiting for it to be asserted.
- */
-       if (((tp->t_state & TS_CARR_ON) == 0) && !callout &&
-                       ((tp->t_cflag & CLOCAL) == 0) &&
-                       ((ap->a_oflags & O_NONBLOCK) == 0)) {
-               portp->waitopens++;
-               error = tsleep(TSA_CARR_ON(tp), PCATCH, "stldcd", 0);
-               portp->waitopens--;
-               if (error)
-                       goto stlopen_end;
-               goto stlopen_restart;
-       }
-
-/*
- *     Open the line discipline.
- */
-       error = (*linesw[tp->t_line].l_open)(dev, tp);
-       stl_ttyoptim(portp, &tp->t_termios);
-       if ((tp->t_state & TS_ISOPEN) && callout)
-               portp->callout = 1;
-
-/*
- *     If for any reason we get to here and the port is not actually
- *     open then close of the physical hardware - no point leaving it
- *     active when the open failed...
- */
-stlopen_end:
-       crit_exit();
-       if (((tp->t_state & TS_ISOPEN) == 0) && (portp->waitopens == 0))
-               stl_rawclose(portp);
-
-       return(error);
-}
-
-/*****************************************************************************/
-
-static int stlclose(struct dev_close_args *ap)
-{
-       cdev_t dev = ap->a_head.a_dev;
-       struct tty      *tp;
-       stlport_t       *portp;
-
-#ifdef STLDEBUG
-       kprintf("stlclose(dev=%s,flag=%x,mode=%x,p=%p)\n", devtoname(dev),
-               flag, mode, (void *) p);
-#endif
-
-       if (minor(dev) & STL_MEMDEV)
-               return(0);
-        if (minor(dev) & STL_CTRLDEV)
-                return(0);
-
-       portp = stl_dev2port(dev);
-       if (portp == NULL)
-               return(ENXIO);
-       tp = &portp->tty;
-
-       crit_enter();
-       (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
-       stl_ttyoptim(portp, &tp->t_termios);
-       stl_rawclose(portp);
-       ttyclose(tp);
-       crit_exit();
-       return(0);
-}
-
-/*****************************************************************************/
-
-static void stl_stop(struct tty *tp, int rw)
-{
-#ifdef STLDEBUG
-       kprintf("stl_stop(tp=%x,rw=%x)\n", (int) tp, rw);
-#endif
-
-       stl_flush((stlport_t *) tp, rw);
-}
-
-/*****************************************************************************/
-
-static int stlioctl(struct dev_ioctl_args *ap)
-{
-       cdev_t dev = ap->a_head.a_dev;
-       u_long cmd = ap->a_cmd;
-       caddr_t data = ap->a_data;
-       struct termios  *newtios, *localtios;
-       struct tty      *tp;
-       stlport_t       *portp;
-       int             error, i;
-
-#ifdef STLDEBUG
-       kprintf("stlioctl(dev=%s,cmd=%lx,data=%p,flag=%x)\n",
-               devtoname(dev), cmd, (void *) data, ap->a_fflag);
-#endif
-
-       if (minor(dev) & STL_MEMDEV)
-               return(stl_memioctl(dev, cmd, data, ap->a_fflag));
-
-       portp = stl_dev2port(dev);
-       if (portp == NULL)
-               return(ENODEV);
-       tp = &portp->tty;
-       error = 0;
-       
-/*
- *     First up handle ioctls on the control devices.
- */
-       if (minor(dev) & STL_CTRLDEV) {
-               if ((minor(dev) & STL_CTRLDEV) == STL_CTRLINIT)
-                       localtios = (minor(dev) & STL_CALLOUTDEV) ?
-                               &portp->initouttios : &portp->initintios;
-               else if ((minor(dev) & STL_CTRLDEV) == STL_CTRLLOCK)
-                       localtios = (minor(dev) & STL_CALLOUTDEV) ?
-                               &portp->lockouttios : &portp->lockintios;
-               else
-                       return(ENODEV);
-
-               switch (cmd) {
-               case TIOCSETA:
-                       if ((error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) == 0)
-                               *localtios = *((struct termios *) data);
-                       break;
-               case TIOCGETA:
-                       *((struct termios *) data) = *localtios;
-                       break;
-               case TIOCGETD:
-                       *((int *) data) = TTYDISC;
-                       break;
-               case TIOCGWINSZ:
-                       bzero(data, sizeof(struct winsize));
-                       break;
-               default:
-                       error = ENOTTY;
-                       break;
-               }
-               return(error);
-       }
-
-/*
- *     Deal with 4.3 compatibility issues if we have too...
- */
-#if defined(COMPAT_43)
-       if (1) {
-               struct termios  tios;
-               unsigned long   oldcmd;
-
-               tios = tp->t_termios;
-               oldcmd = cmd;
-               if ((error = ttsetcompat(tp, &cmd, data, &tios)))
-                       return(error);
-               if (cmd != oldcmd)
-                       data = (caddr_t) &tios;
-       }
-#endif
-
-/*
- *     Carry out some pre-cmd processing work first...
- *     Hmmm, not so sure we want this, disable for now...
- */
-       if ((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
-               newtios = (struct termios *) data;
-               localtios = (minor(dev) & STL_CALLOUTDEV) ? 
-                       &portp->lockouttios : &portp->lockintios;
-
-               newtios->c_iflag = (tp->t_iflag & localtios->c_iflag) |
-                       (newtios->c_iflag & ~localtios->c_iflag);
-               newtios->c_oflag = (tp->t_oflag & localtios->c_oflag) |
-                       (newtios->c_oflag & ~localtios->c_oflag);
-               newtios->c_cflag = (tp->t_cflag & localtios->c_cflag) |
-                       (newtios->c_cflag & ~localtios->c_cflag);
-               newtios->c_lflag = (tp->t_lflag & localtios->c_lflag) |
-                       (newtios->c_lflag & ~localtios->c_lflag);
-               for (i = 0; (i < NCCS); i++) {
-                       if (localtios->c_cc[i] != 0)
-                               newtios->c_cc[i] = tp->t_cc[i];
-               }
-               if (localtios->c_ispeed != 0)
-                       newtios->c_ispeed = tp->t_ispeed;
-               if (localtios->c_ospeed != 0)
-                       newtios->c_ospeed = tp->t_ospeed;
-       }
-
-/*
- *     Call the line discipline and the common command processing to
- *     process this command (if they can).
- */
-       error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data,
-                                             ap->a_fflag, ap->a_cred);
-       if (error != ENOIOCTL)
-               return(error);
-
-       crit_enter();
-       error = ttioctl(tp, cmd, data, ap->a_fflag);
-       stl_ttyoptim(portp, &tp->t_termios);
-       if (error != ENOIOCTL) {
-               crit_exit();
-               return(error);
-       }
-
-       error = 0;
-
-/*
- *     Process local commands here. These are all commands that only we
- *     can take care of (they all rely on actually doing something special
- *     to the actual hardware).
- */
-       switch (cmd) {
-       case TIOCSBRK:
-               stl_sendbreak(portp, -1);
-               break;
-       case TIOCCBRK:
-               stl_sendbreak(portp, -2);
-               break;
-       case TIOCSDTR:
-               stl_setsignals(portp, 1, -1);
-               break;
-       case TIOCCDTR:
-               stl_setsignals(portp, 0, -1);
-               break;
-       case TIOCMSET:
-               i = *((int *) data);
-               stl_setsignals(portp, ((i & TIOCM_DTR) ? 1 : 0),
-                       ((i & TIOCM_RTS) ? 1 : 0));
-               break;
-       case TIOCMBIS:
-               i = *((int *) data);
-               stl_setsignals(portp, ((i & TIOCM_DTR) ? 1 : -1),
-                       ((i & TIOCM_RTS) ? 1 : -1));
-               break;
-       case TIOCMBIC:
-               i = *((int *) data);
-               stl_setsignals(portp, ((i & TIOCM_DTR) ? 0 : -1),
-                       ((i & TIOCM_RTS) ? 0 : -1));
-               break;
-       case TIOCMGET:
-               *((int *) data) = (stl_getsignals(portp) | TIOCM_LE);
-               break;
-       case TIOCMSDTRWAIT:
-               if ((error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) == 0)
-                       portp->dtrwait = *((int *) data) * hz / 100;
-               break;
-       case TIOCMGDTRWAIT:
-               *((int *) data) = portp->dtrwait * 100 / hz;
-               break;
-       case TIOCTIMESTAMP:
-               portp->dotimestamp = 1;
-               *((struct timeval *) data) = portp->timestamp;
-               break;
-       default:
-               error = ENOTTY;
-               break;
-       }
-       crit_exit();
-
-       return(error);
-}
-/*****************************************************************************/
-
-/*
- *     Convert the specified minor device number into a port struct
- *     pointer. Return NULL if the device number is not a valid port.
- */
-
-static stlport_t *stl_dev2port(cdev_t dev)
-{
-       stlbrd_t        *brdp;
-
-       brdp = stl_brds[MKDEV2BRD(dev)];
-       if (brdp == NULL)
-               return(NULL);
-       return(brdp->ports[MKDEV2PORT(dev)]);
-}
-
-/*****************************************************************************/
-
-/*
- *     Initialize the port hardware. This involves enabling the transmitter
- *     and receiver, setting the port configuration, and setting the initial
- *     signal state.
- */
-
-static int stl_rawopen(stlport_t *portp)
-{
-#ifdef STLDEBUG
-       kprintf("stl_rawopen(portp=%p): brdnr=%d panelnr=%d portnr=%d\n",
-               (void *) portp, portp->brdnr, portp->panelnr, portp->portnr);
-#endif
-
-        stl_setport(portp, &portp->tty.t_termios);
-       portp->sigs = stl_getsignals(portp);
-       stl_setsignals(portp, 1, 1);
-       stl_enablerxtx(portp, 1, 1);
-       stl_startrxtx(portp, 1, 0);
-       return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *     Shutdown the hardware of a port. Disable its transmitter and
- *     receiver, and maybe drop signals if appropriate.
- */
-
-static int stl_rawclose(stlport_t *portp)
-{
-       struct tty      *tp;
-
-#ifdef STLDEBUG
-       kprintf("stl_rawclose(portp=%p): brdnr=%d panelnr=%d portnr=%d\n",
-               (void *) portp, portp->brdnr, portp->panelnr, portp->portnr);
-#endif
-
-       tp = &portp->tty;
-       stl_disableintrs(portp);
-       stl_enablerxtx(portp, 0, 0);
-       stl_flush(portp, (FWRITE | FREAD));
-       if (tp->t_cflag & HUPCL) {
-               stl_setsignals(portp, 0, 0);
-               if (portp->dtrwait != 0) {
-                       portp->state |= ASY_DTRWAIT;
-                       callout_reset(&portp->dtr_ch, portp->dtrwait,
-                                       stl_dtrwakeup, portp);
-               }
-       }
-       portp->callout = 0;
-       portp->brklen = 0;
-       portp->state &= ~(ASY_ACTIVE | ASY_RTSFLOW);
-       wakeup(&portp->callout);
-       wakeup(TSA_CARR_ON(tp));
-       return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *     Clear the DTR waiting flag, and wake up any sleepers waiting for
- *     DTR wait period to finish.
- */
-
-static void stl_dtrwakeup(void *arg)
-{
-       stlport_t       *portp;
-
-       portp = (stlport_t *) arg;
-       portp->state &= ~ASY_DTRWAIT;
-       wakeup(&portp->dtrwait);
-}
-
-/*****************************************************************************/
-
-/*
- *     Start (or continue) the transfer of TX data on this port. If the
- *     port is not currently busy then load up the interrupt ring queue
- *     buffer and kick of the transmitter. If the port is running low on
- *     TX data then refill the ring queue. This routine is also used to
- *     activate input flow control!
- */
-
-static void stl_start(struct tty *tp)
-{
-       stlport_t       *portp;
-       unsigned int    len, stlen;
-       char            *head, *tail;
-       int             count;
-
-       portp = (stlport_t *) tp;
-
-#ifdef STLDEBUG
-       kprintf("stl_start(tp=%x): brdnr=%d portnr=%d\n", (int) tp, 
-               portp->brdnr, portp->portnr);
-#endif
-
-       crit_enter();
-
-/*
- *     Check if the ports input has been blocked, and take appropriate action.
- *     Not very often do we really need to do anything, so make it quick.
- */
-       if (tp->t_state & TS_TBLOCK) {
-                if ((portp->state & ASY_RTSFLOWMODE) &&
-                    ((portp->state & ASY_RTSFLOW) == 0))
-                       stl_flowcontrol(portp, 0, -1);
-       } else {
-               if (portp->state & ASY_RTSFLOW)
-                       stl_flowcontrol(portp, 1, -1);
-       }
-
-       if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
-               crit_exit();
-               return;
-       }
-
-/*
- *     Copy data from the clists into the interrupt ring queue. This will
- *     require at most 2 copys... What we do is calculate how many chars
- *     can fit into the ring queue, and how many can fit in 1 copy. If after
- *     the first copy there is still more room then do the second copy. 
- *     The beauty of this type of ring queue is that we do not need to
- *     spl protect our-selves, since we only ever update the head pointer,
- *     and the interrupt routine only ever updates the tail pointer.
- */
-       if (tp->t_outq.c_cc != 0) {
-               head = portp->tx.head;
-               tail = portp->tx.tail;
-               if (head >= tail) {
-                       len = STL_TXBUFSIZE - (head - tail) - 1;
-                       stlen = portp->tx.endbuf - head;
-               } else {
-                       len = tail - head - 1;
-                       stlen = len;
-               }
-
-               if (len > 0) {
-                       stlen = MIN(len, stlen);
-                       count = q_to_b(&tp->t_outq, head, stlen);
-                       len -= count;
-                       head += count;
-                       if (head >= portp->tx.endbuf) {
-                               head = portp->tx.buf;
-                               if (len > 0) {
-                                       stlen = q_to_b(&tp->t_outq, head, len);
-                                       head += stlen;
-                                       count += stlen;
-                               }
-                       }
-                       portp->tx.head = head;
-                       if (count > 0)
-                               stl_startrxtx(portp, -1, 1);
-               }
-
-/*
- *             If we sent something, make sure we are called again.
- */
-               tp->t_state |= TS_BUSY;
-       }
-
-/*
- *     Do any writer wakeups.
- */
-       ttwwakeup(tp);
-
-       crit_exit();
-}
-
-/*****************************************************************************/
-
-static void stl_flush(stlport_t *portp, int flag)
-{
-       char    *head, *tail;
-       int     len;
-
-#ifdef STLDEBUG
-       kprintf("stl_flush(portp=%x,flag=%x)\n", (int) portp, flag);
-#endif
-
-       if (portp == NULL)
-               return;
-
-       crit_enter();
-
-       if (flag & FWRITE) {
-                stl_uartflush(portp, FWRITE);
-                portp->tx.tail = portp->tx.head;
-       }
-
-/*
- *     The only thing to watch out for when flushing the read side is
- *     the RX status buffer. The interrupt code relys on the status
- *     bytes as being zeroed all the time (it does not bother setting
- *     a good char status to 0, it expects that it already will be).
- *     We also need to un-flow the RX channel if flow control was
- *     active.
- */
-       if (flag & FREAD) {
-               head = portp->rx.head;
-               tail = portp->rx.tail;
-               if (head != tail) {
-                       if (head >= tail) {
-                               len = head - tail;
-                       } else {
-                               len = portp->rx.endbuf - tail;
-                               bzero(portp->rxstatus.buf,
-                                       (head - portp->rx.buf));
-                       }
-                       bzero((tail + STL_RXBUFSIZE), len);
-                       portp->rx.tail = head;
-               }
-
-               if ((portp->state & ASY_RTSFLOW) &&
-                               ((portp->tty.t_state & TS_TBLOCK) == 0))
-                       stl_flowcontrol(portp, 1, -1);
-       }
-
-       crit_exit();
-}
-
-/*****************************************************************************/
-
-/*
- *      Interrupt handler for host based boards. Interrupts for all boards
- *      are vectored through here.
- */
-
-void stlintr(void *arg)
-{
-        stlbrd_t        *brdp;
-        int             i;
-
-#ifdef STLDEBUG
-       kprintf("stlintr(unit=%d)\n", (int)arg);
-#endif
-
-        for (i = 0; (i < stl_nrbrds); i++) {
-                if ((brdp = stl_brds[i]) == NULL)
-                        continue;
-                if (brdp->state == 0)
-                        continue;
-                (* brdp->isr)(brdp);
-        }
-}
-
-/*****************************************************************************/
-
-static void stlpciintr(void *arg)
-{
-       stlintr(NULL);
-}
-
-/*****************************************************************************/
-
-/*
- *      Interrupt service routine for EasyIO boards.
- */
-
-static void stl_eiointr(stlbrd_t *brdp)
-{
-        stlpanel_t      *panelp;
-        int             iobase;
-
-#ifdef STLDEBUG
-        kprintf("stl_eiointr(brdp=%p)\n", brdp);
-#endif
-
-        panelp = brdp->panels[0];
-        iobase = panelp->iobase;
-        while (inb(brdp->iostatus) & EIO_INTRPEND)
-                (* panelp->isr)(panelp, iobase);
-}
-
-/*
- *      Interrupt service routine for ECH-AT board types.
- */
-
-static void stl_echatintr(stlbrd_t *brdp)
-{
-        stlpanel_t      *panelp;
-        unsigned int    ioaddr;
-        int             bnknr;
-
-        outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDENABLE));
-
-        while (inb(brdp->iostatus) & ECH_INTRPEND) {
-                for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
-                        ioaddr = brdp->bnkstataddr[bnknr];
-                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
-                                panelp = brdp->bnk2panel[bnknr];
-                                (* panelp->isr)(panelp, (ioaddr & 0xfffc));
-                        }
-                }
-        }
-
-        outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDDISABLE));
-}
-
-/*****************************************************************************/
-
-/*
- *      Interrupt service routine for ECH-MCA board types.
- */
-
-static void stl_echmcaintr(stlbrd_t *brdp)
-{
-        stlpanel_t      *panelp;
-        unsigned int    ioaddr;
-        int             bnknr;
-
-        while (inb(brdp->iostatus) & ECH_INTRPEND) {
-                for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
-                        ioaddr = brdp->bnkstataddr[bnknr];
-                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
-                                panelp = brdp->bnk2panel[bnknr];
-                                (* panelp->isr)(panelp, (ioaddr & 0xfffc));
-                        }
-                }
-        }
-}
-
-/*****************************************************************************/
-
-/*
- *      Interrupt service routine for ECH-PCI board types.
- */
-
-static void stl_echpciintr(stlbrd_t *brdp)
-{
-        stlpanel_t      *panelp;
-        unsigned int    ioaddr;
-        int             bnknr, recheck;
-
-#ifdef STLDEBUG
-        kprintf("stl_echpciintr(brdp=%x)\n", (int) brdp);
-#endif
-
-        for (;;) {
-                recheck = 0;
-                for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
-                        outb(brdp->ioctrl, brdp->bnkpageaddr[bnknr]);
-                        ioaddr = brdp->bnkstataddr[bnknr];
-                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
-                                panelp = brdp->bnk2panel[bnknr];
-                                (* panelp->isr)(panelp, (ioaddr & 0xfffc));
-                                recheck++;
-                        }
-                }
-                if (! recheck)
-                        break;
-        }
-}
-
-/*****************************************************************************/
-
-/*
- *      Interrupt service routine for EC8/64-PCI board types.
- */
-
-static void stl_echpci64intr(stlbrd_t *brdp)
-{
-        stlpanel_t      *panelp;
-        unsigned int    ioaddr;
-        int             bnknr;
-
-#ifdef STLDEBUG
-        kprintf("stl_echpci64intr(brdp=%p)\n", brdp);
-#endif
-
-        while (inb(brdp->ioctrl) & 0x1) {
-                for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
-                        ioaddr = brdp->bnkstataddr[bnknr];
-#ifdef STLDEBUG
-       kprintf("    --> ioaddr=%x status=%x(%x)\n", ioaddr, inb(ioaddr) & ECH_PNLINTRPEND, inb(ioaddr));
-#endif
-                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
-                                panelp = brdp->bnk2panel[bnknr];
-                                (* panelp->isr)(panelp, (ioaddr & 0xfffc));
-                        }
-                }
-        }
-}
-
-/*****************************************************************************/
-
-/*
- *     If we haven't scheduled a timeout then do it, some port needs high
- *     level processing.
- */
-
-static void stl_dotimeout(void)
-{
-#ifdef STLDEBUG
-       kprintf("stl_dotimeout()\n");
-#endif
-       if (stl_doingtimeout == 0) {
-               if ((stl_poll_ch.c_flags & CALLOUT_DID_INIT) == 0)
-                       callout_init(&stl_poll_ch);
-               callout_reset(&stl_poll_ch, 1, stl_poll, NULL);
-               stl_doingtimeout++;
-       }
-}
-
-/*****************************************************************************/
-
-/*
- *     Service "software" level processing. Too slow or painfull to be done
- *     at real hardware interrupt time. This way we might also be able to
- *     do some service on other waiting ports as well...
- */
-
-static void stl_poll(void *arg)
-{
-       stlbrd_t        *brdp;
-       stlport_t       *portp;
-       struct tty      *tp;
-       int             brdnr, portnr, rearm;
-
-#ifdef STLDEBUG
-       kprintf("stl_poll()\n");
-#endif
-
-       stl_doingtimeout = 0;
-       rearm = 0;
-
-       crit_enter();
-       for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
-               if ((brdp = stl_brds[brdnr]) == NULL)
-                       continue;
-               for (portnr = 0; (portnr < brdp->nrports); portnr++) {
-                       if ((portp = brdp->ports[portnr]) == NULL)
-                               continue;
-                       if ((portp->state & ASY_ACTIVE) == 0)
-                               continue;
-                       tp = &portp->tty;
-
-                       if (portp->state & ASY_RXDATA)
-                               stl_rxprocess(portp);
-                       if (portp->state & ASY_DCDCHANGE) {
-                               portp->state &= ~ASY_DCDCHANGE;
-                               portp->sigs = stl_getsignals(portp);
-                               (*linesw[tp->t_line].l_modem)(tp,
-                                       (portp->sigs & TIOCM_CD));
-                       }
-                        if (portp->state & ASY_TXEMPTY) {
-                                if (stl_datastate(portp) == 0) {
-                                        portp->state &= ~ASY_TXEMPTY;
-                                        tp->t_state &= ~TS_BUSY;
-                                        (*linesw[tp->t_line].l_start)(tp);
-                                }
-                        }
-                       if (portp->state & ASY_TXLOW) {
-                               portp->state &= ~ASY_TXLOW;
-                               (*linesw[tp->t_line].l_start)(tp);
-                       }
-
-                       if (portp->state & ASY_ACTIVE)
-                               rearm++;
-               }
-       }
-       crit_exit();
-
-       if (rearm)
-               stl_dotimeout();
-}
-
-/*****************************************************************************/
-
-/*
- *     Process the RX data that has been buffered up in the RX ring queue.
- */
-
-static void stl_rxprocess(stlport_t *portp)
-{
-       struct tty      *tp;
-       unsigned int    len, stlen, lostlen;
-       char            *head, *tail;
-       char            status;
-       int             ch;
-
-#ifdef STLDEBUG
-       kprintf("stl_rxprocess(portp=%x): brdnr=%d portnr=%d\n", (int) portp, 
-               portp->brdnr, portp->portnr);
-#endif
-
-       tp = &portp->tty;
-       portp->state &= ~ASY_RXDATA;
-
-       if ((tp->t_state & TS_ISOPEN) == 0) {
-               stl_flush(portp, FREAD);
-               return;
-       }
-
-/*
- *     Calculate the amount of data in the RX ring queue. Also calculate
- *     the largest single copy size...
- */
-       head = portp->rx.head;
-       tail = portp->rx.tail;
-       if (head >= tail) {
-               len = head - tail;
-               stlen = len;
-       } else {
-               len = STL_RXBUFSIZE - (tail - head);
-               stlen = portp->rx.endbuf - tail;
-       }
-
-       if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
-               if (len > 0) {
-                       if (((tp->t_rawq.c_cc + len) >= TTYHOG) &&
-                                       ((portp->state & ASY_RTSFLOWMODE) ||
-                                       (tp->t_iflag & IXOFF)) &&
-                                       ((tp->t_state & TS_TBLOCK) == 0)) {
-                               ch = TTYHOG - tp->t_rawq.c_cc - 1;
-                               len = (ch > 0) ? ch : 0;
-                               stlen = MIN(stlen, len);
-                               ttyblock(tp);
-                       }
-                       lostlen = b_to_q(tail, stlen, &tp->t_rawq);
-                       tail += stlen;
-                       len -= stlen;
-                       if (tail >= portp->rx.endbuf) {
-                               tail = portp->rx.buf;
-                               lostlen += b_to_q(tail, len, &tp->t_rawq);
-                               tail += len;
-                       }
-                       portp->stats.rxlost += lostlen;
-                       ttwakeup(tp);
-                       portp->rx.tail = tail;
-               }
-       } else {
-               while (portp->rx.tail != head) {
-                       ch = (unsigned char) *(portp->rx.tail);
-                       status = *(portp->rx.tail + STL_RXBUFSIZE);
-                       if (status) {
-                               *(portp->rx.tail + STL_RXBUFSIZE) = 0;
-                               if (status & ST_BREAK)
-                                       ch |= TTY_BI;
-                               if (status & ST_FRAMING)
-                                       ch |= TTY_FE;
-                               if (status & ST_PARITY)
-                                       ch |= TTY_PE;
-                               if (status & ST_OVERRUN)
-                                       ch |= TTY_OE;
-                       }
-                       (*linesw[tp->t_line].l_rint)(ch, tp);
-                       if (portp->rx.tail == head)
-                               break;
-
-                       if (++(portp->rx.tail) >= portp->rx.endbuf)
-                               portp->rx.tail = portp->rx.buf;
-               }
-       }
-
-       if (head != portp->rx.tail)
-               portp->state |= ASY_RXDATA;
-
-/*
- *     If we were flow controled then maybe the buffer is low enough that
- *     we can re-activate it.
- */
-       if ((portp->state & ASY_RTSFLOW) && ((tp->t_state & TS_TBLOCK) == 0))
-               stl_flowcontrol(portp, 1, -1);
-}
-
-/*****************************************************************************/
-
-static int stl_param(struct tty *tp, struct termios *tiosp)
-{
-        stlport_t       *portp;
-
-        portp = (stlport_t *) tp;
-        if (portp == NULL)
-                return(ENODEV);
-
-        return(stl_setport(portp, tiosp));
-}
-
-/*****************************************************************************/
-
-/*
- *     Action the flow control as required. The hw and sw args inform the
- *     routine what flow control methods it should try.
- */
-
-static void stl_flowcontrol(stlport_t *portp, int hw, int sw)
-{
-       unsigned char   *head, *tail;
-       int             len, hwflow;
-
-#ifdef STLDEBUG
-       kprintf("stl_flowcontrol(portp=%x,hw=%d,sw=%d)\n", (int) portp, hw, sw);
-#endif
-
-       hwflow = -1;
-
-       if (portp->state & ASY_RTSFLOWMODE) {
-               if (hw == 0) {
-                       if ((portp->state & ASY_RTSFLOW) == 0)
-                               hwflow = 0;
-               } else if (hw > 0) {
-                       if (portp->state & ASY_RTSFLOW) {
-                               head = portp->rx.head;
-                               tail = portp->rx.tail;
-                               len = (head >= tail) ? (head - tail) :
-                                       (STL_RXBUFSIZE - (tail - head));
-                               if (len < STL_RXBUFHIGH)
-                                       hwflow = 1;
-                       }
-               }
-       }
-
-/*
- *     We have worked out what to do, if anything. So now apply it to the
- *     UART port.
- */
-        stl_sendflow(portp, hwflow, sw);
-}
-
-/*****************************************************************************/
-
-/*
- *     Enable l_rint processing bypass mode if tty modes allow it.
- */
-
-static void stl_ttyoptim(stlport_t *portp, struct termios *tiosp)
-{
-       struct tty      *tp;
-
-       tp = &portp->tty;
-       if (((tiosp->c_iflag &
-             (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP)) == 0) &&
-           (((tiosp->c_iflag & BRKINT) == 0) || (tiosp->c_iflag & IGNBRK)) &&
-           (((tiosp->c_iflag & PARMRK) == 0) ||
-               ((tiosp->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))) &&
-           ((tiosp->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) ==0) &&
-           (linesw[tp->t_line].l_rint == ttyinput))
-               tp->t_state |= TS_CAN_BYPASS_L_RINT;
-       else
-               tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
-       portp->hotchar = linesw[tp->t_line].l_hotchar;
-}
-
-/*****************************************************************************/
-
-/*
- *     Try and find and initialize all the ports on a panel. We don't care
- *     what sort of board these ports are on - since the port io registers
- *     are almost identical when dealing with ports.
- */
-
-static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
-{
-       stlport_t       *portp;
-       int             i, j;
-
-#ifdef STLDEBUG
-       kprintf("stl_initports(panelp=%x)\n", (int) panelp);
-#endif
-
-/*
- *      All UART's are initialized if found. Now go through and setup
- *      each ports data structures. Also initialize each individual
- *      UART port.
- */
-        for (i = 0; (i < panelp->nrports); i++) {
-                portp = kmalloc(sizeof(stlport_t), M_TTYS, M_WAITOK | M_ZERO);
-
-                portp->portnr = i;
-                portp->brdnr = panelp->brdnr;
-                portp->panelnr = panelp->panelnr;
-                portp->uartp = panelp->uartp;
-                portp->clk = brdp->clk;
-                panelp->ports[i] = portp;
-
-                j = STL_TXBUFSIZE + (2 * STL_RXBUFSIZE);
-                portp->tx.buf = kmalloc(j, M_TTYS, M_WAITOK);
-                portp->tx.endbuf = portp->tx.buf + STL_TXBUFSIZE;
-                portp->tx.head = portp->tx.buf;
-                portp->tx.tail = portp->tx.buf;
-                portp->rx.buf = portp->tx.buf + STL_TXBUFSIZE;
-                portp->rx.endbuf = portp->rx.buf + STL_RXBUFSIZE;
-                portp->rx.head = portp->rx.buf;
-                portp->rx.tail = portp->rx.buf;
-                portp->rxstatus.buf = portp->rx.buf + STL_RXBUFSIZE;
-                portp->rxstatus.endbuf = portp->rxstatus.buf + STL_RXBUFSIZE;
-                portp->rxstatus.head = portp->rxstatus.buf;
-                portp->rxstatus.tail = portp->rxstatus.buf;
-                bzero(portp->rxstatus.head, STL_RXBUFSIZE);
-
-                portp->initintios.c_ispeed = STL_DEFSPEED;
-                portp->initintios.c_ospeed = STL_DEFSPEED;
-                portp->initintios.c_cflag = STL_DEFCFLAG;
-                portp->initintios.c_iflag = 0;
-                portp->initintios.c_oflag = 0;
-                portp->initintios.c_lflag = 0;
-                bcopy(&ttydefchars[0], &portp->initintios.c_cc[0],
-                        sizeof(portp->initintios.c_cc));
-                portp->initouttios = portp->initintios;
-                portp->dtrwait = 3 * hz;
-               callout_init(&portp->dtr_ch);
-
-                stl_portinit(brdp, panelp, portp);
-        }
-
-        return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *     Try to find and initialize an EasyIO board.
- */
-
-static int stl_initeio(stlbrd_t *brdp)
-{
-       stlpanel_t      *panelp;
-       unsigned int    status;
-
-#ifdef STLDEBUG
-       kprintf("stl_initeio(brdp=%x)\n", (int) brdp);
-#endif
-
-       brdp->ioctrl = brdp->ioaddr1 + 1;
-       brdp->iostatus = brdp->ioaddr1 + 2;
-       brdp->clk = EIO_CLK;
-        brdp->isr = stl_eiointr;
-
-       status = inb(brdp->iostatus);
-       switch (status & EIO_IDBITMASK) {
-       case EIO_8PORTM:
-               brdp->clk = EIO_CLK8M;
-               /* fall thru */
-       case EIO_8PORTRS:
-       case EIO_8PORTDI:
-               brdp->nrports = 8;
-               break;
-       case EIO_4PORTRS:
-               brdp->nrports = 4;
-               break;
-        case EIO_MK3:
-                switch (status & EIO_BRDMASK) {
-                case ID_BRD4:
-                        brdp->nrports = 4;
-                        break;
-                case ID_BRD8:
-                        brdp->nrports = 8;
-                        break;
-                case ID_BRD16:
-                        brdp->nrports = 16;
-                        break;
-                default:
-                        return(ENODEV);
-                }
-                brdp->ioctrl++;
-                break;
-       default:
-               return(ENODEV);
-       }
-
-        if (brdp->brdtype == BRD_EASYIOPCI) {
-                outb((brdp->ioaddr2 + 0x4c), 0x41);
-        } else {
-/*
- *     Check that the supplied IRQ is good and then use it to setup the
- *     programmable interrupt bits on EIO board. Also set the edge/level
- *     triggered interrupt bit.
- */
-               if ((brdp->irq < 0) || (brdp->irq > 15) ||
-                       (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-                       kprintf("STALLION: invalid irq=%d for brd=%d\n",
-                              brdp->irq, brdp->brdnr);
-                       return(EINVAL);
-               }
-               outb(brdp->ioctrl, (stl_vecmap[brdp->irq] |
-                       ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)));
-       }
-
-       panelp = kmalloc(sizeof(stlpanel_t), M_TTYS, M_WAITOK | M_ZERO);
-       panelp->brdnr = brdp->brdnr;
-       panelp->panelnr = 0;
-       panelp->nrports = brdp->nrports;
-       panelp->iobase = brdp->ioaddr1;
-       panelp->hwid = status;
-        if ((status & EIO_IDBITMASK) == EIO_MK3) {
-                panelp->uartp = (void *) &stl_sc26198uart;
-                panelp->isr = stl_sc26198intr;
-        } else {
-                panelp->uartp = (void *) &stl_cd1400uart;
-                panelp->isr = stl_cd1400eiointr;
-        }
-       brdp->panels[0] = panelp;
-       brdp->nrpanels = 1;
-       brdp->hwid = status;
-       brdp->state |= BRD_FOUND;
-       return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *     Try to find an ECH board and initialize it. This code is capable of
- *     dealing with all types of ECH board.
- */
-
-static int stl_initech(stlbrd_t *brdp)
-{
-       stlpanel_t      *panelp;
-       unsigned int    status, nxtid;
-       int             panelnr, ioaddr, banknr, i;
-
-#ifdef STLDEBUG
-       kprintf("stl_initech(brdp=%x)\n", (int) brdp);
-#endif
-
-/*
- *     Set up the initial board register contents for boards. This varys a
- *     bit between the different board types. So we need to handle each
- *     separately. Also do a check that the supplied IRQ is good.
- */
-        switch (brdp->brdtype) {
-
-        case BRD_ECH:
-                brdp->isr = stl_echatintr;
-                brdp->ioctrl = brdp->ioaddr1 + 1;
-                brdp->iostatus = brdp->ioaddr1 + 1;
-                status = inb(brdp->iostatus);
-                if ((status & ECH_IDBITMASK) != ECH_ID)
-                        return(ENODEV);
-                brdp->hwid = status;
-
-                if ((brdp->irq < 0) || (brdp->irq > 15) ||
-                    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-                        kprintf("STALLION: invalid irq=%d for brd=%d\n",
-                                brdp->irq, brdp->brdnr);
-                        return(EINVAL);
-                }
-                status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
-                status |= (stl_vecmap[brdp->irq] << 1);
-                outb(brdp->ioaddr1, (status | ECH_BRDRESET));
-                brdp->ioctrlval = ECH_INTENABLE |
-                        ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
-                outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDENABLE));
-                outb(brdp->ioaddr1, status);
-                break;
-
-        case BRD_ECHMC:
-                brdp->isr = stl_echmcaintr;
-                brdp->ioctrl = brdp->ioaddr1 + 0x20;
-                brdp->iostatus = brdp->ioctrl;
-                status = inb(brdp->iostatus);
-                if ((status & ECH_IDBITMASK) != ECH_ID)
-                        return(ENODEV);
-                brdp->hwid = status;
-
-                if ((brdp->irq < 0) || (brdp->irq > 15) ||
-                    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-                        kprintf("STALLION: invalid irq=%d for brd=%d\n",
-                                brdp->irq, brdp->brdnr);
-                        return(EINVAL);
-                }
-                outb(brdp->ioctrl, ECHMC_BRDRESET);
-                outb(brdp->ioctrl, ECHMC_INTENABLE);
-                break;
-
-        case BRD_ECHPCI:
-                brdp->isr = stl_echpciintr;
-                brdp->ioctrl = brdp->ioaddr1 + 2;
-                break;
-
-        case BRD_ECH64PCI:
-                brdp->isr = stl_echpci64intr;
-                brdp->ioctrl = brdp->ioaddr2 + 0x40;
-                outb((brdp->ioaddr1 + 0x4c), 0x43);
-                break;
-
-        default:
-                kprintf("STALLION: unknown board type=%d\n", brdp->brdtype);
-                break;
-        }
-
-       brdp->clk = ECH_CLK;
-
-/*
- *     Scan through the secondary io address space looking for panels.
- *     As we find'em allocate and initialize panel structures for each.
- */
-       ioaddr = brdp->ioaddr2;
-       panelnr = 0;
-       nxtid = 0;
-       banknr = 0;
-
-       for (i = 0; (i < STL_MAXPANELS); i++) {
-               if (brdp->brdtype == BRD_ECHPCI) {
-                       outb(brdp->ioctrl, nxtid);
-                       ioaddr = brdp->ioaddr2;
-               }
-               status = inb(ioaddr + ECH_PNLSTATUS);
-               if ((status & ECH_PNLIDMASK) != nxtid)
-                       break;
-               panelp = kmalloc(sizeof(stlpanel_t), M_TTYS, M_WAITOK | M_ZERO);
-               panelp->brdnr = brdp->brdnr;
-               panelp->panelnr = panelnr;
-               panelp->iobase = ioaddr;
-               panelp->pagenr = nxtid;
-               panelp->hwid = status;
-                brdp->bnk2panel[banknr] = panelp;
-                brdp->bnkpageaddr[banknr] = nxtid;
-                brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
-
-                if (status & ECH_PNLXPID) {
-                        panelp->uartp = (void *) &stl_sc26198uart;
-                        panelp->isr = stl_sc26198intr;
-                        if (status & ECH_PNL16PORT) {
-                                panelp->nrports = 16;
-                                brdp->bnk2panel[banknr] = panelp;
-                                brdp->bnkpageaddr[banknr] = nxtid;
-                                brdp->bnkstataddr[banknr++] = ioaddr + 4 +
-                                        ECH_PNLSTATUS;
-                        } else {
-                                panelp->nrports = 8;
-                        }
-                } else {
-                        panelp->uartp = (void *) &stl_cd1400uart;
-                        panelp->isr = stl_cd1400echintr;
-                        if (status & ECH_PNL16PORT) {
-                                panelp->nrports = 16;
-                                panelp->ackmask = 0x80;
-                                if (brdp->brdtype != BRD_ECHPCI)
-                                        ioaddr += EREG_BANKSIZE;
-                                brdp->bnk2panel[banknr] = panelp;
-                                brdp->bnkpageaddr[banknr] = ++nxtid;
-                                brdp->bnkstataddr[banknr++] = ioaddr +
-                                        ECH_PNLSTATUS;
-                        } else {
-                                panelp->nrports = 8;
-                                panelp->ackmask = 0xc0;
-                        }
-               }
-
-                nxtid++;
-                ioaddr += EREG_BANKSIZE;
-                brdp->nrports += panelp->nrports;
-                brdp->panels[panelnr++] = panelp;
-                if ((brdp->brdtype == BRD_ECH) || (brdp->brdtype == BRD_ECHMC)){
-                        if (ioaddr >= (brdp->ioaddr2 + 0x20)) {
-                                kprintf("STALLION: too many ports attached "
-                                        "to board %d, remove last module\n",
-                                        brdp->brdnr);
-                                break;
-                        }
-                }
-       }
-
-        brdp->nrpanels = panelnr;
-        brdp->nrbnks = banknr;
-       if (brdp->brdtype == BRD_ECH)
-               outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDDISABLE));
-
-       brdp->state |= BRD_FOUND;
-       return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *     Initialize and configure the specified board. This firstly probes
- *     for the board, if it is found then the board is initialized and
- *     then all its ports are initialized as well.
- */
-
-static int stl_brdinit(stlbrd_t *brdp)
-{
-       stlpanel_t      *panelp;
-       int             i, j, k;
-
-#ifdef STLDEBUG
-       kprintf("stl_brdinit(brdp=%x): unit=%d type=%d io1=%x io2=%x irq=%d\n",
-               (int) brdp, brdp->brdnr, brdp->brdtype, brdp->ioaddr1,
-               brdp->ioaddr2, brdp->irq);
-#endif
-
-       switch (brdp->brdtype) {
-       case BRD_EASYIO:
-        case BRD_EASYIOPCI:
-               stl_initeio(brdp);
-               break;
-       case BRD_ECH:
-       case BRD_ECHMC:
-       case BRD_ECHPCI:
-        case BRD_ECH64PCI:
-               stl_initech(brdp);
-               break;
-       default:
-               kprintf("STALLION: unit=%d is unknown board type=%d\n",
-                       brdp->brdnr, brdp->brdtype);
-               return(ENODEV);
-       }
-
-       stl_brds[brdp->brdnr] = brdp;
-       if ((brdp->state & BRD_FOUND) == 0) {
-#if 0
-               kprintf("STALLION: %s board not found, unit=%d io=%x irq=%d\n",
-                       stl_brdnames[brdp->brdtype], brdp->brdnr,
-                       brdp->ioaddr1, brdp->irq);
-#endif
-               return(ENODEV);
-       }
-
-       for (i = 0, k = 0; (i < STL_MAXPANELS); i++) {
-               panelp = brdp->panels[i];
-               if (panelp != NULL) {
-                       stl_initports(brdp, panelp);
-                       for (j = 0; (j < panelp->nrports); j++)
-                               brdp->ports[k++] = panelp->ports[j];
-               }
-       }
-
-       kprintf("stl%d: %s (driver version %s) unit=%d nrpanels=%d nrports=%d\n",
-               brdp->unitid, stl_brdnames[brdp->brdtype], stl_drvversion,
-               brdp->brdnr, brdp->nrpanels, brdp->nrports);
-       return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *     Return the board stats structure to user app.
- */
-
-static int stl_getbrdstats(caddr_t data)
-{
-       stlbrd_t        *brdp;
-       stlpanel_t      *panelp;
-       int             i;
-
-       stl_brdstats = *((combrd_t *) data);
-       if (stl_brdstats.brd >= STL_MAXBRDS)
-               return(-ENODEV);
-       brdp = stl_brds[stl_brdstats.brd];
-       if (brdp == NULL)
-               return(-ENODEV);
-
-       bzero(&stl_brdstats, sizeof(combrd_t));
-       stl_brdstats.brd = brdp->brdnr;
-       stl_brdstats.type = brdp->brdtype;
-       stl_brdstats.hwid = brdp->hwid;
-       stl_brdstats.state = brdp->state;
-       stl_brdstats.ioaddr = brdp->ioaddr1;
-       stl_brdstats.ioaddr2 = brdp->ioaddr2;
-       stl_brdstats.irq = brdp->irq;
-       stl_brdstats.nrpanels = brdp->nrpanels;
-       stl_brdstats.nrports = brdp->nrports;
-       for (i = 0; (i < brdp->nrpanels); i++) {
-               panelp = brdp->panels[i];
-               stl_brdstats.panels[i].panel = i;
-               stl_brdstats.panels[i].hwid = panelp->hwid;
-               stl_brdstats.panels[i].nrports = panelp->nrports;
-       }
-
-       *((combrd_t *) data) = stl_brdstats;
-       return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *     Resolve the referenced port number into a port struct pointer.
- */
-
-static stlport_t *stl_getport(int brdnr, int panelnr, int portnr)
-{
-       stlbrd_t        *brdp;
-       stlpanel_t      *panelp;
-
-       if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
-               return(NULL);
-       brdp = stl_brds[brdnr];
-       if (brdp == NULL)
-               return(NULL);
-       if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
-               return(NULL);
-       panelp = brdp->panels[panelnr];
-       if (panelp == NULL)
-               return(NULL);
-       if ((portnr < 0) || (portnr >= panelp->nrports))
-               return(NULL);
-       return(panelp->ports[portnr]);
-}
-
-/*****************************************************************************/
-
-/*
- *     Return the port stats structure to user app. A NULL port struct
- *     pointer passed in means that we need to find out from the app
- *     what port to get stats for (used through board control device).
- */
-
-static int stl_getportstats(stlport_t *portp, caddr_t data)
-{
-       unsigned char   *head, *tail;
-
-       if (portp == NULL) {
-               stl_comstats = *((comstats_t *) data);
-               portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
-                       stl_comstats.port);
-               if (portp == NULL)
-                       return(-ENODEV);
-       }
-
-       portp->stats.state = portp->state;
-       /*portp->stats.flags = portp->flags;*/
-       portp->stats.hwid = portp->hwid;
-       portp->stats.ttystate = portp->tty.t_state;
-       portp->stats.cflags = portp->tty.t_cflag;
-       portp->stats.iflags = portp->tty.t_iflag;
-       portp->stats.oflags = portp->tty.t_oflag;
-       portp->stats.lflags = portp->tty.t_lflag;
-
-       head = portp->tx.head;
-       tail = portp->tx.tail;
-       portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
-               (STL_TXBUFSIZE - (tail - head)));
-
-       head = portp->rx.head;
-       tail = portp->rx.tail;
-       portp->stats.rxbuffered = (head >= tail) ? (head - tail) :
-               (STL_RXBUFSIZE - (tail - head));
-
-       portp->stats.signals = (unsigned long) stl_getsignals(portp);
-
-       *((comstats_t *) data) = portp->stats;
-       return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *     Clear the port stats structure. We also return it zeroed out...
- */
-
-static int stl_clrportstats(stlport_t *portp, caddr_t data)
-{
-       if (portp == NULL) {
-               stl_comstats = *((comstats_t *) data);
-               portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
-                       stl_comstats.port);
-               if (portp == NULL)
-                       return(ENODEV);
-       }
-
-       bzero(&portp->stats, sizeof(comstats_t));
-       portp->stats.brd = portp->brdnr;
-       portp->stats.panel = portp->panelnr;
-       portp->stats.port = portp->portnr;
-       *((comstats_t *) data) = stl_comstats;
-       return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *     The "staliomem" device is used for stats collection in this driver.
- */
-
-static int stl_memioctl(cdev_t dev, unsigned long cmd, caddr_t data, int flag)
-{
-       int             rc;
-
-#ifdef STLDEBUG
-       kprintf("stl_memioctl(dev=%s,cmd=%lx,data=%p,flag=%x)\n",
-               devtoname(dev), cmd, (void *) data, flag);
-#endif
-
-        rc = 0;
-
-        switch (cmd) {
-        case COM_GETPORTSTATS:
-                rc = stl_getportstats(NULL, data);
-                break;
-        case COM_CLRPORTSTATS:
-                rc = stl_clrportstats(NULL, data);
-                break;
-        case COM_GETBRDSTATS:
-                rc = stl_getbrdstats(data);
-                break;
-        default:
-                rc = ENOTTY;
-                break;
-        }
-
-        return(rc);
-}
-
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                         CD1400 UART CODE                                  */
-/*****************************************************************************/
-
-/*
- *      These functions get/set/update the registers of the cd1400 UARTs.
- *      Access to the cd1400 registers is via an address/data io port pair.
- */
-
-static int stl_cd1400getreg(stlport_t *portp, int regnr)
-{
-        outb(portp->ioaddr, (regnr + portp->uartaddr));
-        return(inb(portp->ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-
-static void stl_cd1400setreg(stlport_t *portp, int regnr, int value)
-{
-        outb(portp->ioaddr, (regnr + portp->uartaddr));
-        outb((portp->ioaddr + EREG_DATA), value);
-}
-
-/*****************************************************************************/
-
-static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value)
-{
-        outb(portp->ioaddr, (regnr + portp->uartaddr));
-        if (inb(portp->ioaddr + EREG_DATA) != value) {
-                outb((portp->ioaddr + EREG_DATA), value);
-                return(1);
-        }
-        return(0);
-}
-
-/*****************************************************************************/
-
-static void stl_cd1400flush(stlport_t *portp, int flag)
-{
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400flush(portp=%x,flag=%x)\n", (int) portp, flag);
-#endif
-
-        if (portp == NULL)
-                return;
-
-        crit_enter();
-
-        if (flag & FWRITE) {
-                BRDENABLE(portp->brdnr, portp->pagenr);
-                stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-                stl_cd1400ccrwait(portp);
-                stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
-                stl_cd1400ccrwait(portp);
-                BRDDISABLE(portp->brdnr);
-        }
-
-        if (flag & FREAD) {
-                /* Hmmm */
-        }
-
-        crit_exit();
-}
-
-/*****************************************************************************/
-
-static void stl_cd1400ccrwait(stlport_t *portp)
-{
-        int     i;
-
-        for (i = 0; (i < CCR_MAXWAIT); i++) {
-                if (stl_cd1400getreg(portp, CCR) == 0)
-                        return;
-        }
-
-        kprintf("stl%d: cd1400 device not responding, panel=%d port=%d\n",
-            portp->brdnr, portp->panelnr, portp->portnr);
-}
-
-/*****************************************************************************/
-
-/*
- *      Transmit interrupt handler. This has gotta be fast!  Handling TX
- *      chars is pretty simple, stuff as many as possible from the TX buffer
- *      into the cd1400 FIFO. Must also handle TX breaks here, since they
- *      are embedded as commands in the data stream. Oh no, had to use a goto!
- */
-
-static __inline void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr)
-{
-        stlport_t       *portp;
-        unsigned char   ioack, srer;
-        char            *head, *tail;
-        int             len, stlen;
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400txisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
-#endif
-
-        ioack = inb(ioaddr + EREG_TXACK);
-        if (((ioack & panelp->ackmask) != 0) ||
-            ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
-                kprintf("STALLION: bad TX interrupt ack value=%x\n",
-                        ioack);
-                return;
-        }
-        portp = panelp->ports[(ioack >> 3)];
-
-/*
- *      Unfortunately we need to handle breaks in the data stream, since
- *      this is the only way to generate them on the cd1400. Do it now if
- *      a break is to be sent. Some special cases here: brklen is -1 then
- *      start sending an un-timed break, if brklen is -2 then stop sending
- *      an un-timed break, if brklen is -3 then we have just sent an
- *      un-timed break and do not want any data to go out, if brklen is -4
- *      then a break has just completed so clean up the port settings.
- */
-        if (portp->brklen != 0) {
-                if (portp->brklen >= -1) {
-                        outb(ioaddr, (TDR + portp->uartaddr));
-                        outb((ioaddr + EREG_DATA), ETC_CMD);
-                        outb((ioaddr + EREG_DATA), ETC_STARTBREAK);
-                        if (portp->brklen > 0) {
-                                outb((ioaddr + EREG_DATA), ETC_CMD);
-                                outb((ioaddr + EREG_DATA), ETC_DELAY);
-                                outb((ioaddr + EREG_DATA), portp->brklen);
-                                outb((ioaddr + EREG_DATA), ETC_CMD);
-                                outb((ioaddr + EREG_DATA), ETC_STOPBREAK);
-                                portp->brklen = -4;
-                        } else {
-                                portp->brklen = -3;
-                        }
-                } else if (portp->brklen == -2) {
-                        outb(ioaddr, (TDR + portp->uartaddr));
-                        outb((ioaddr + EREG_DATA), ETC_CMD);
-                        outb((ioaddr + EREG_DATA), ETC_STOPBREAK);
-                        portp->brklen = -4;
-                } else if (portp->brklen == -3) {
-                        outb(ioaddr, (SRER + portp->uartaddr));
-                        srer = inb(ioaddr + EREG_DATA);
-                        srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
-                        outb((ioaddr + EREG_DATA), srer);
-                } else {
-                        outb(ioaddr, (COR2 + portp->uartaddr));
-                        outb((ioaddr + EREG_DATA),
-                                (inb(ioaddr + EREG_DATA) & ~COR2_ETC));
-                        portp->brklen = 0;
-                }
-                goto stl_txalldone;
-        }
-
-        head = portp->tx.head;
-        tail = portp->tx.tail;
-        len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
-        if ((len == 0) || ((len < STL_TXBUFLOW) &&
-            ((portp->state & ASY_TXLOW) == 0))) {
-                portp->state |= ASY_TXLOW;
-                stl_dotimeout();
-        }
-
-        if (len == 0) {
-                outb(ioaddr, (SRER + portp->uartaddr));
-                srer = inb(ioaddr + EREG_DATA);
-                if (srer & SRER_TXDATA) {
-                        srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
-                } else {
-                        srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
-                        portp->state |= ASY_TXEMPTY;
-                        portp->state &= ~ASY_TXBUSY;
-                }
-                outb((ioaddr + EREG_DATA), srer);
-        } else {
-                len = MIN(len, CD1400_TXFIFOSIZE);
-                portp->stats.txtotal += len;
-                stlen = MIN(len, (portp->tx.endbuf - tail));
-                outb(ioaddr, (TDR + portp->uartaddr));
-                outsb((ioaddr + EREG_DATA), tail, stlen);
-                len -= stlen;
-                tail += stlen;
-                if (tail >= portp->tx.endbuf)
-                        tail = portp->tx.buf;
-                if (len > 0) {
-                        outsb((ioaddr + EREG_DATA), tail, len);
-                        tail += len;
-                }
-                portp->tx.tail = tail;
-        }
-
-stl_txalldone:
-        outb(ioaddr, (EOSRR + portp->uartaddr));
-        outb((ioaddr + EREG_DATA), 0);
-}
-
-/*****************************************************************************/
-
-/*
- *      Receive character interrupt handler. Determine if we have good chars
- *      or bad chars and then process appropriately.
- */
-
-static __inline void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
-{
-        stlport_t       *portp;
-        struct tty      *tp;
-        unsigned int    ioack, len, buflen, stlen;
-        unsigned char   status;
-        char            ch;
-        char            *head, *tail;
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400rxisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
-#endif
-
-        ioack = inb(ioaddr + EREG_RXACK);
-        if ((ioack & panelp->ackmask) != 0) {
-                kprintf("STALLION: bad RX interrupt ack value=%x\n", ioack);
-                return;
-        }
-        portp = panelp->ports[(ioack >> 3)];
-        tp = &portp->tty;
-
-/*
- *      First up, calculate how much room there is in the RX ring queue.
- *      We also want to keep track of the longest possible copy length,
- *      this has to allow for the wrapping of the ring queue.
- */
-        head = portp->rx.head;
-        tail = portp->rx.tail;
-        if (head >= tail) {
-                buflen = STL_RXBUFSIZE - (head - tail) - 1;
-                stlen = portp->rx.endbuf - head;
-        } else {
-                buflen = tail - head - 1;
-                stlen = buflen;
-        }
-
-/*
- *      Check if the input buffer is near full. If so then we should take
- *      some flow control action... It is very easy to do hardware and
- *      software flow control from here since we have the port selected on
- *      the UART.
- */
-        if (buflen <= (STL_RXBUFSIZE - STL_RXBUFHIGH)) {
-                if (((portp->state & ASY_RTSFLOW) == 0) &&
-                    (portp->state & ASY_RTSFLOWMODE)) {
-                        portp->state |= ASY_RTSFLOW;
-                        stl_cd1400setreg(portp, MCOR1,
-                                (stl_cd1400getreg(portp, MCOR1) & 0xf0));
-                        stl_cd1400setreg(portp, MSVR2, 0);
-                        portp->stats.rxrtsoff++;
-                }
-        }
-
-/*
- *      OK we are set, process good data... If the RX ring queue is full
- *      just chuck the chars - don't leave them in the UART.
- */
-        if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
-                outb(ioaddr, (RDCR + portp->uartaddr));
-                len = inb(ioaddr + EREG_DATA);
-                if (buflen == 0) {
-                        outb(ioaddr, (RDSR + portp->uartaddr));
-                        insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
-                        portp->stats.rxlost += len;
-                        portp->stats.rxtotal += len;
-                } else {
-                        len = MIN(len, buflen);
-                        portp->stats.rxtotal += len;
-                        stlen = MIN(len, stlen);
-                        if (len > 0) {
-                                outb(ioaddr, (RDSR + portp->uartaddr));
-                                insb((ioaddr + EREG_DATA), head, stlen);
-                                head += stlen;
-                                if (head >= portp->rx.endbuf) {
-                                        head = portp->rx.buf;
-                                        len -= stlen;
-                                        insb((ioaddr + EREG_DATA), head, len);
-                                        head += len;
-                                }
-                        }
-                }
-        } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
-                outb(ioaddr, (RDSR + portp->uartaddr));
-                status = inb(ioaddr + EREG_DATA);
-                ch = inb(ioaddr + EREG_DATA);
-                if (status & ST_BREAK)
-                        portp->stats.rxbreaks++;
-                if (status & ST_FRAMING)
-                        portp->stats.rxframing++;
-                if (status & ST_PARITY)
-                        portp->stats.rxparity++;
-                if (status & ST_OVERRUN)
-                        portp->stats.rxoverrun++;
-                if (status & ST_SCHARMASK) {
-                        if ((status & ST_SCHARMASK) == ST_SCHAR1)
-                                portp->stats.txxon++;
-                        if ((status & ST_SCHARMASK) == ST_SCHAR2)
-                                portp->stats.txxoff++;
-                        goto stl_rxalldone;
-                }
-                if ((portp->rxignoremsk & status) == 0) {
-                        if ((tp->t_state & TS_CAN_BYPASS_L_RINT) &&
-                            ((status & ST_FRAMING) ||
-                            ((status & ST_PARITY) && (tp->t_iflag & INPCK))))
-                                ch = 0;
-                        if ((portp->rxmarkmsk & status) == 0)
-                                status = 0;
-                        *(head + STL_RXBUFSIZE) = status;
-                        *head++ = ch;
-                        if (head >= portp->rx.endbuf)
-                                head = portp->rx.buf;
-                }
-        } else {
-                kprintf("STALLION: bad RX interrupt ack value=%x\n", ioack);
-                return;
-        }
-
-        portp->rx.head = head;
-        portp->state |= ASY_RXDATA;
-        stl_dotimeout();
-
-stl_rxalldone:
-        outb(ioaddr, (EOSRR + portp->uartaddr));
-        outb((ioaddr + EREG_DATA), 0);
-}
-
-/*****************************************************************************/
-
-/*
- *      Modem interrupt handler. The is called when the modem signal line
- *      (DCD) has changed state.
- */
-
-static __inline void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
-{
-        stlport_t       *portp;
-        unsigned int    ioack;
-        unsigned char   misr;
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400mdmisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
-#endif
-
-        ioack = inb(ioaddr + EREG_MDACK);
-        if (((ioack & panelp->ackmask) != 0) ||
-            ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
-                kprintf("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
-                return;
-        }
-        portp = panelp->ports[(ioack >> 3)];
-
-        outb(ioaddr, (MISR + portp->uartaddr));
-        misr = inb(ioaddr + EREG_DATA);
-        if (misr & MISR_DCD) {
-                portp->state |= ASY_DCDCHANGE;
-                portp->stats.modem++;
-                stl_dotimeout();
-        }
-
-        outb(ioaddr, (EOSRR + portp->uartaddr));
-        outb((ioaddr + EREG_DATA), 0);
-}
-
-/*****************************************************************************/
-
-/*
- *      Interrupt service routine for cd1400 EasyIO boards.
- */
-
-static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
-{
-        unsigned char   svrtype;
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400eiointr(panelp=%x,iobase=%x)\n", (int) panelp,
-                iobase);
-#endif
-
-        outb(iobase, SVRR);
-        svrtype = inb(iobase + EREG_DATA);
-        if (panelp->nrports > 4) {
-                outb(iobase, (SVRR + 0x80));
-                svrtype |= inb(iobase + EREG_DATA);
-        }
-#ifdef STLDEBUG
-kprintf("stl_cd1400eiointr(panelp=%x,iobase=%x): svrr=%x\n", (int) panelp, iobase, svrtype);
-#endif
-
-        if (svrtype & SVRR_RX)
-                stl_cd1400rxisr(panelp, iobase);
-        else if (svrtype & SVRR_TX)
-                stl_cd1400txisr(panelp, iobase);
-        else if (svrtype & SVRR_MDM)
-                stl_cd1400mdmisr(panelp, iobase);
-}
-
-/*****************************************************************************/
-
-/*
- *      Interrupt service routine for cd1400 panels.
- */
-
-static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase)
-{
-        unsigned char   svrtype;
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400echintr(panelp=%x,iobase=%x)\n", (int) panelp,
-                iobase);
-#endif
-
-        outb(iobase, SVRR);
-        svrtype = inb(iobase + EREG_DATA);
-        outb(iobase, (SVRR + 0x80));
-        svrtype |= inb(iobase + EREG_DATA);
-        if (svrtype & SVRR_RX)
-                stl_cd1400rxisr(panelp, iobase);
-        else if (svrtype & SVRR_TX)
-                stl_cd1400txisr(panelp, iobase);
-        else if (svrtype & SVRR_MDM)
-                stl_cd1400mdmisr(panelp, iobase);
-}
-
-/*****************************************************************************/
-
-/*
- *      Set up the cd1400 registers for a port based on the termios port
- *      settings.
- */
-
-static int stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
-{
-        unsigned int    clkdiv;
-        unsigned char   cor1, cor2, cor3;
-        unsigned char   cor4, cor5, ccr;
-        unsigned char   srer, sreron, sreroff;
-        unsigned char   mcor1, mcor2, rtpr;
-        unsigned char   clk, div;
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400setport(portp=%x,tiosp=%x): brdnr=%d portnr=%d\n",
-                (int) portp, (int) tiosp, portp->brdnr, portp->portnr);
-#endif
-
-        cor1 = 0;
-        cor2 = 0;
-        cor3 = 0;
-        cor4 = 0;
-        cor5 = 0;
-        ccr = 0;
-        rtpr = 0;
-        clk = 0;
-        div = 0;
-        mcor1 = 0;
-        mcor2 = 0;
-        sreron = 0;
-        sreroff = 0;
-
-/*
- *      Set up the RX char ignore mask with those RX error types we
- *      can ignore. We could have used some special modes of the cd1400
- *      UART to help, but it is better this way because we can keep stats
- *      on the number of each type of RX exception event.
- */
-        portp->rxignoremsk = 0;
-        if (tiosp->c_iflag & IGNPAR)
-                portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
-        if (tiosp->c_iflag & IGNBRK)
-                portp->rxignoremsk |= ST_BREAK;
-
-        portp->rxmarkmsk = ST_OVERRUN;
-        if (tiosp->c_iflag & (INPCK | PARMRK))
-                portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
-        if (tiosp->c_iflag & BRKINT)
-                portp->rxmarkmsk |= ST_BREAK;
-
-/*
- *      Go through the char size, parity and stop bits and set all the
- *      option registers appropriately.
- */
-        switch (tiosp->c_cflag & CSIZE) {
-        case CS5:
-                cor1 |= COR1_CHL5;
-                break;
-        case CS6:
-                cor1 |= COR1_CHL6;
-                break;
-        case CS7:
-                cor1 |= COR1_CHL7;
-                break;
-        default:
-                cor1 |= COR1_CHL8;
-                break;
-        }
-
-        if (tiosp->c_cflag & CSTOPB)
-                cor1 |= COR1_STOP2;
-        else
-                cor1 |= COR1_STOP1;
-
-        if (tiosp->c_cflag & PARENB) {
-                if (tiosp->c_cflag & PARODD)
-                        cor1 |= (COR1_PARENB | COR1_PARODD);
-                else
-                        cor1 |= (COR1_PARENB | COR1_PAREVEN);
-        } else {
-                cor1 |= COR1_PARNONE;
-        }
-
-/*
- *      Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
- *      space for hardware flow control and the like. This should be set to
- *      VMIN. Also here we will set the RX data timeout to 10ms - this should
- *      really be based on VTIME...
- */
-        cor3 |= FIFO_RXTHRESHOLD;
-        rtpr = 2;
-
-/*
- *      Calculate the baud rate timers. For now we will just assume that
- *      the input and output baud are the same. Could have used a baud
- *      table here, but this way we can generate virtually any baud rate
- *      we like!
- */
-        if (tiosp->c_ispeed == 0)
-                tiosp->c_ispeed = tiosp->c_ospeed;
-        if ((tiosp->c_ospeed < 0) || (tiosp->c_ospeed > CD1400_MAXBAUD))
-                return(EINVAL);
-
-        if (tiosp->c_ospeed > 0) {
-                for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
-                        clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) /
-                                tiosp->c_ospeed);
-                        if (clkdiv < 0x100)
-                                break;
-                }
-                div = (unsigned char) clkdiv;
-        }
-
-/*
- *      Check what form of modem signaling is required and set it up.
- */
-        if ((tiosp->c_cflag & CLOCAL) == 0) {
-                mcor1 |= MCOR1_DCD;
-                mcor2 |= MCOR2_DCD;
-                sreron |= SRER_MODEM;
-        }
-
-/*
- *      Setup cd1400 enhanced modes if we can. In particular we want to
- *      handle as much of the flow control as possbile automatically. As
- *      well as saving a few CPU cycles it will also greatly improve flow
- *      control reliablilty.
- */
-        if (tiosp->c_iflag & IXON) {
-                cor2 |= COR2_TXIBE;
-                cor3 |= COR3_SCD12;
-                if (tiosp->c_iflag & IXANY)
-                        cor2 |= COR2_IXM;
-        }
-
-        if (tiosp->c_cflag & CCTS_OFLOW)
-                cor2 |= COR2_CTSAE;
-        if (tiosp->c_cflag & CRTS_IFLOW)
-                mcor1 |= FIFO_RTSTHRESHOLD;
-
-/*
- *      All cd1400 register values calculated so go through and set them
- *      all up.
- */
-#ifdef STLDEBUG
-        kprintf("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr,
-                portp->panelnr, portp->brdnr);
-        kprintf("    cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", cor1, cor2,
-                cor3, cor4, cor5);
-        kprintf("    mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
-                mcor1, mcor2, rtpr, sreron, sreroff);
-        kprintf("    tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
-        kprintf("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
-                tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], tiosp->c_cc[VSTART],
-                tiosp->c_cc[VSTOP]);
-#endif
-
-        crit_enter();
-        BRDENABLE(portp->brdnr, portp->pagenr);
-        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
-        srer = stl_cd1400getreg(portp, SRER);
-        stl_cd1400setreg(portp, SRER, 0);
-        ccr += stl_cd1400updatereg(portp, COR1, cor1);
-        ccr += stl_cd1400updatereg(portp, COR2, cor2);
-        ccr += stl_cd1400updatereg(portp, COR3, cor3);
-        if (ccr) {
-                stl_cd1400ccrwait(portp);
-                stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
-        }
-        stl_cd1400setreg(portp, COR4, cor4);
-        stl_cd1400setreg(portp, COR5, cor5);
-        stl_cd1400setreg(portp, MCOR1, mcor1);
-        stl_cd1400setreg(portp, MCOR2, mcor2);
-        if (tiosp->c_ospeed == 0) {
-                stl_cd1400setreg(portp, MSVR1, 0);
-        } else {
-                stl_cd1400setreg(portp, MSVR1, MSVR1_DTR);
-                stl_cd1400setreg(portp, TCOR, clk);
-                stl_cd1400setreg(portp, TBPR, div);
-                stl_cd1400setreg(portp, RCOR, clk);
-                stl_cd1400setreg(portp, RBPR, div);
-        }
-        stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
-        stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
-        stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
-        stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
-        stl_cd1400setreg(portp, RTPR, rtpr);
-        mcor1 = stl_cd1400getreg(portp, MSVR1);
-        if (mcor1 & MSVR1_DCD)
-                portp->sigs |= TIOCM_CD;
-        else
-                portp->sigs &= ~TIOCM_CD;
-        stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
-        BRDDISABLE(portp->brdnr);
-        portp->state &= ~(ASY_RTSFLOWMODE | ASY_CTSFLOWMODE);
-        portp->state |= ((tiosp->c_cflag & CRTS_IFLOW) ? ASY_RTSFLOWMODE : 0);
-        portp->state |= ((tiosp->c_cflag & CCTS_OFLOW) ? ASY_CTSFLOWMODE : 0);
-        stl_ttyoptim(portp, tiosp);
-        crit_exit();
-
-        return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *      Action the flow control as required. The hw and sw args inform the
- *      routine what flow control methods it should try.
- */
-
-static void stl_cd1400sendflow(stlport_t *portp, int hw, int sw)
-{
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400sendflow(portp=%x,hw=%d,sw=%d)\n",
-                (int) portp, hw, sw);
-#endif
-
-        crit_enter();
-        BRDENABLE(portp->brdnr, portp->pagenr);
-        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-
-        if (sw >= 0) {
-                stl_cd1400ccrwait(portp);
-                if (sw) {
-                        stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
-                        portp->stats.rxxoff++;
-                } else {
-                        stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
-                        portp->stats.rxxon++;
-                }
-                stl_cd1400ccrwait(portp);
-        }
-
-        if (hw == 0) {
-                portp->state |= ASY_RTSFLOW;
-                stl_cd1400setreg(portp, MCOR1,
-                        (stl_cd1400getreg(portp, MCOR1) & 0xf0));
-                stl_cd1400setreg(portp, MSVR2, 0);
-                portp->stats.rxrtsoff++;
-        } else if (hw > 0) {
-                portp->state &= ~ASY_RTSFLOW;
-                stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
-                stl_cd1400setreg(portp, MCOR1,
-                        (stl_cd1400getreg(portp, MCOR1) | FIFO_RTSTHRESHOLD));
-                portp->stats.rxrtson++;
-        }
-
-        BRDDISABLE(portp->brdnr);
-        crit_exit();
-}
-
-/*****************************************************************************/
-
-/*
- *      Return the current state of data flow on this port. This is only
- *      really interresting when determining if data has fully completed
- *      transmission or not... This is easy for the cd1400, it accurately
- *      maintains the busy port flag.
- */
-
-static int stl_cd1400datastate(stlport_t *portp)
-{
-#ifdef STLDEBUG
-        kprintf("stl_cd1400datastate(portp=%x)\n", (int) portp);
-#endif
-
-        if (portp == NULL)
-                return(0);
-
-        return((portp->state & ASY_TXBUSY) ? 1 : 0);
-}
-
-/*****************************************************************************/
-
-/*
- *      Set the state of the DTR and RTS signals. Got to do some extra
- *      work here to deal hardware flow control.
- */
-
-static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts)
-{
-        unsigned char   msvr1, msvr2;
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400setsignals(portp=%x,dtr=%d,rts=%d)\n", (int) portp,
-                dtr, rts);
-#endif
-
-        msvr1 = 0;
-        msvr2 = 0;
-        if (dtr > 0)
-                msvr1 = MSVR1_DTR;
-        if (rts > 0)
-                msvr2 = MSVR2_RTS;
-
-        crit_enter();
-        BRDENABLE(portp->brdnr, portp->pagenr);
-        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-        if (rts >= 0) {
-                if (portp->tty.t_cflag & CRTS_IFLOW) {
-                        if (rts == 0) {
-                                stl_cd1400setreg(portp, MCOR1,
-                                      (stl_cd1400getreg(portp, MCOR1) & 0xf0));
-                                portp->stats.rxrtsoff++;
-                        } else {
-                                stl_cd1400setreg(portp, MCOR1,
-                                        (stl_cd1400getreg(portp, MCOR1) |
-                                        FIFO_RTSTHRESHOLD));
-                                portp->stats.rxrtson++;
-                        }
-                }
-                stl_cd1400setreg(portp, MSVR2, msvr2);
-        }
-        if (dtr >= 0)
-                stl_cd1400setreg(portp, MSVR1, msvr1);
-        BRDDISABLE(portp->brdnr);
-        crit_exit();
-}
-
-/*****************************************************************************/
-
-/*
- *      Get the state of the signals.
- */
-
-static int stl_cd1400getsignals(stlport_t *portp)
-{
-        unsigned char   msvr1, msvr2;
-        int             sigs;
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400getsignals(portp=%x)\n", (int) portp);
-#endif
-
-        crit_enter();
-        BRDENABLE(portp->brdnr, portp->pagenr);
-        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
-        msvr1 = stl_cd1400getreg(portp, MSVR1);
-        msvr2 = stl_cd1400getreg(portp, MSVR2);
-        BRDDISABLE(portp->brdnr);
-        crit_exit();
-
-        sigs = 0;
-        sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
-        sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
-        sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
-        sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
-#if 0
-        sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
-        sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
-#else
-        sigs |= TIOCM_DSR;
-#endif
-        return(sigs);
-}
-
-/*****************************************************************************/
-
-/*
- *      Enable or disable the Transmitter and/or Receiver.
- */
-
-static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx)
-{
-        unsigned char   ccr;
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400enablerxtx(portp=%x,rx=%d,tx=%d)\n",
-                (int) portp, rx, tx);
-#endif
-
-        ccr = 0;
-        if (tx == 0)
-                ccr |= CCR_TXDISABLE;
-        else if (tx > 0)
-                ccr |= CCR_TXENABLE;
-        if (rx == 0)
-                ccr |= CCR_RXDISABLE;
-        else if (rx > 0)
-                ccr |= CCR_RXENABLE;
-
-        crit_enter();
-        BRDENABLE(portp->brdnr, portp->pagenr);
-        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-        stl_cd1400ccrwait(portp);
-        stl_cd1400setreg(portp, CCR, ccr);
-        stl_cd1400ccrwait(portp);
-        BRDDISABLE(portp->brdnr);
-        crit_exit();
-}
-
-/*****************************************************************************/
-
-/*
- *      Start or stop the Transmitter and/or Receiver.
- */
-
-static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx)
-{
-        unsigned char   sreron, sreroff;
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400startrxtx(portp=%x,rx=%d,tx=%d)\n",
-                (int) portp, rx, tx);
-#endif
-
-        sreron = 0;
-        sreroff = 0;
-        if (tx == 0)
-                sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
-        else if (tx == 1)
-                sreron |= SRER_TXDATA;
-        else if (tx >= 2)
-                sreron |= SRER_TXEMPTY;
-        if (rx == 0)
-                sreroff |= SRER_RXDATA;
-        else if (rx > 0)
-                sreron |= SRER_RXDATA;
-
-        crit_enter();
-        BRDENABLE(portp->brdnr, portp->pagenr);
-        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
-        stl_cd1400setreg(portp, SRER,
-                ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
-        BRDDISABLE(portp->brdnr);
-        if (tx > 0) {
-                portp->state |= ASY_TXBUSY;
-                portp->tty.t_state |= TS_BUSY;
-        }
-        crit_exit();
-}
-
-/*****************************************************************************/
-
-/*
- *      Disable all interrupts from this port.
- */
-
-static void stl_cd1400disableintrs(stlport_t *portp)
-{
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400disableintrs(portp=%x)\n", (int) portp);
-#endif
-
-        crit_enter();
-        BRDENABLE(portp->brdnr, portp->pagenr);
-        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
-        stl_cd1400setreg(portp, SRER, 0);
-        BRDDISABLE(portp->brdnr);
-        crit_exit();
-}
-
-/*****************************************************************************/
-
-static void stl_cd1400sendbreak(stlport_t *portp, long len)
-{
-
-#ifdef STLDEBUG
-        kprintf("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp,
-                (int) len);
-#endif
-
-        crit_enter();
-        BRDENABLE(portp->brdnr, portp->pagenr);
-        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
-        stl_cd1400setreg(portp, COR2,
-                (stl_cd1400getreg(portp, COR2) | COR2_ETC));
-        stl_cd1400setreg(portp, SRER,
-                ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
-                SRER_TXEMPTY));
-        BRDDISABLE(portp->brdnr);
-        if (len > 0) {
-                len = len / 5;
-                portp->brklen = (len > 255) ? 255 : len;
-        } else {
-                portp->brklen = len;
-        }
-        crit_exit();
-        portp->stats.txbreaks++;
-}
-
-/*****************************************************************************/
-
-/*
- *      Try and find and initialize all the ports on a panel. We don't care
- *      what sort of board these ports are on - since the port io registers
- *      are almost identical when dealing with ports.
- */
-
-static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp)
-{
-#ifdef STLDEBUG
-        kprintf("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n",
-                (int) brdp, (int) panelp, (int) portp);
-#endif
-
-        if ((brdp == NULL) || (panelp == NULL) ||
-            (portp == NULL))
-                return;
-
-        portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
-                (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
-        portp->uartaddr = (portp->portnr & 0x04) << 5;
-        portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
-
-        BRDENABLE(portp->brdnr, portp->pagenr);
-        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
-        stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
-        portp->hwid = stl_cd1400getreg(portp, GFRCR);
-        BRDDISABLE(portp->brdnr);
-}
-
-/*****************************************************************************/
-
-/*
- *      Inbitialize the UARTs in a panel. We don't care what sort of board
- *    &