From Ache:
authorAndrey Chernov <ache@FreeBSD.org>
Mon, 30 May 1994 03:13:36 +0000 (03:13 +0000)
committerAndrey Chernov <ache@FreeBSD.org>
Mon, 30 May 1994 03:13:36 +0000 (03:13 +0000)
Better kernel printout for multiport cards

From Bde:
o Get decls of tk_nin, etc. from "dkstat.h" (a stupid place).
o Mallocate sio structs as well as tty structs.
o FAKE_DCD() is now handled by setting CLOCAL in the initial
  and lock states.
o Removed ifdefs for COM_BIDIR.  It is now standard.  Callin
  devices now act identically (except for bug fixes) to the
  old standard devices if the callout devices are not used.
o New magic minors for initial and lock devices.  Better macros
  to handle magic minors.  "ls -l /dev" should show something
  like this:
crw-------   1 uucp     wheel     28,  0 May 26 01:18 /dev/ttyd0
crw-------   1 uucp     wheel     28,  1 May 21 11:25 /dev/ttyd1
crw-r--r--   1 root     wheel     28, 32 May 15 19:36 /dev/ttyid0
crw-r--r--   1 root     wheel     28, 33 May 15 19:36 /dev/ttyid1
crw-r--r--   1 root     wheel     28, 64 May 15 19:36 /dev/ttyld0
crw-r--r--   1 root     wheel     28, 65 May 15 19:36 /dev/ttyld1
crw-------   1 uucp     wheel     28,128 May 26 14:48 /dev/cua00
crw-------   1 uucp     wheel     28,129 May 26 18:57 /dev/cua01
crw-r--r--   1 root     wheel     28,160 May 15 18:58 /dev/cuai00
crw-r--r--   1 root     wheel     28,161 May 15 19:35 /dev/cuai01
crw-r--r--   1 root     wheel     28,192 May 15 18:56 /dev/cual00
crw-r--r--   1 root     wheel     28,193 May 15 19:35 /dev/cual01
  The initial and lock devices are controlled using commands like
  this:
stty </dev/ttyid0 57600        crtscts
stty </dev/ttyld0 57600 clocal crtscts
stty </dev/cuai00 57600        crtscts
stty </dev/cual00 57600        crtscts
  Here the port speed is changed from the default of 9600
  to 57600 and locked (any nonzero speed works as a lock).
  clocal defaults to off and is locked off for the callin
  device to avoid certain security holes.  crtscts is changed
  from the default of off to on and locked on (flag bits are
  locked by setting the same bits in the lock port).  It is
  only necessary to set the initial state for buggy programs
  that don't set it for themself.  It is dangerous to set
  lock bits if the device cannot support them (e.g., locking
  crtscts on for a mouse port will probably hang the X server).
  However, it may be necessary to set lock bits for buggy
  programs that clear nonstandard bits.
o Removed FIFO_TRIGGER.  The fifo trigger level is now set
  automatically.  It is always set to 1 for slow mouses.  It
  is set to 14 for the very first open but drops back to 8
  for first opens and to as low as 1 if overruns occur.  I
  haven't been able to load my system enough to get it to
  drop below 8.  Changes to the levels are logged.  Please
  report if the level ever drops below 8.
o The fifo disable flag still works to disable the fifo
  completely.  Please don't use it.
o Removed ifdefs for 1.1R interrupt handling.
o Removed ifdefs for non-mallocation of tty structs.
o Use timeout instead of sleep to hold down DTR for long
  enough.  Fixed races.  Now opens have to sleep while
  DTR is being held down.
o Urgent input character now depends on the line discipline.
  Previously it only worked for SLIP.  Now it might work
  for PPP to reduce latency by half a tick.
o Attempted to fix initialization of interrupts for 4ports
  (flag bit 0x1 means 4port-compatible, not multiport).  The
  master interrupt control register and ~OUT2 (badly aka
  MCR_IENABLE) have to be initialized before probing for
  interrupts.
o Rewrote sioopen() to simplify it and avoid races.  Too
  many changes to list.  Essentially, an open either succeeds
  immediately or sleeps until it can succeed immediately.
  After every sleep, all the conditions required for success
  are checked again by restarting the open from near the top.
o Callout ports are implemented using trapdoor carrier again.
  You can program their initial state to set CLOCAL if you
  want.
o Use new sleep address macros.  Better names for sleep addresses.
o Removed bidir ioctls.  There are enough important races to
  worry about.
o Special treatment for ioctls to new initial and lock state
  devices.  These devices only support ioctls, not read, write
  or select.  Separate devices work better than would selector
  bits like CIGNORE because ordinary stty(1) works on them, and
  it is impossible to open a callin/callout device while the
  device going in the other direction is active.
o The DTR wait time as seen by ioctls it is now always in
  hundredths of a second (independent of hz).
o Removed TB_*() macros.  There is no point to only using them
  in sio.
o Use ttwwakeup() to handle write-wakeups consistently.

sys/i386/isa/sio.c

index ad09f7a..4cbe3f6 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)com.c 7.5 (Berkeley) 5/16/91
  * SUCH DAMAGE.
  *
  *     from: @(#)com.c 7.5 (Berkeley) 5/16/91
- *     $Id: sio.c,v 1.44 1994/04/03 12:25:57 ache Exp $
+ *     $Id: sio.c,v 1.45 1994/04/23 02:11:43 davidg Exp $
  */
 
 #include "sio.h"
  */
 
 #include "sio.h"
 #include "proc.h"
 #include "user.h"
 #include "conf.h"
 #include "proc.h"
 #include "user.h"
 #include "conf.h"
+#include "dkstat.h"
 #include "file.h"
 #include "uio.h"
 #include "kernel.h"
 #include "file.h"
 #include "uio.h"
 #include "kernel.h"
+#include "malloc.h"
 #include "syslog.h"
 
 #include "i386/isa/isa.h"
 #include "syslog.h"
 
 #include "i386/isa/isa.h"
@@ -59,7 +61,6 @@
 #include "i386/isa/comreg.h"
 #include "i386/isa/ic/ns16550.h"
 
 #include "i386/isa/comreg.h"
 #include "i386/isa/ic/ns16550.h"
 
-#define        FAKE_DCD(unit)  ((unit) == comconsole)
 #define        LOTS_OF_EVENTS  64      /* helps separate urgent events from input */
 #define        RB_I_HIGH_WATER (RBSZ - 2 * RS_IBUFSIZE)
 #define        RB_I_LOW_WATER  ((RBSZ - 2 * RS_IBUFSIZE) * 7 / 8)
 #define        LOTS_OF_EVENTS  64      /* helps separate urgent events from input */
 #define        RB_I_HIGH_WATER (RBSZ - 2 * RS_IBUFSIZE)
 #define        RB_I_LOW_WATER  ((RBSZ - 2 * RS_IBUFSIZE) * 7 / 8)
 #define        TTY_BI          TTY_FE          /* XXX */
 #define        TTY_OE          TTY_PE          /* XXX */
 
 #define        TTY_BI          TTY_FE          /* XXX */
 #define        TTY_OE          TTY_PE          /* XXX */
 
-#ifdef COM_BIDIR
-#define        CALLOUT(x)              (minor(x) & COM_CALLOUT_MASK)
-#define        COM_CALLOUT_MASK        0x80
-#define        COM_MINOR_MAGIC_MASK    0x80
-#else /* COM_BIDIR */
-#define        COM_MINOR_MAGIC_MASK    0
-#endif /* COM_BIDIR */
-
-#define        UNIT(x)                 (minor(x) & ~COM_MINOR_MAGIC_MASK)
+#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)
+#define        MINOR_TO_UNIT(mynor)    ((mynor) & ~MINOR_MAGIC_MASK)
 
 #ifdef COM_MULTIPORT
 /* checks in flags for multiport and which is multiport "master chip"
 
 #ifdef COM_MULTIPORT
 /* checks in flags for multiport and which is multiport "master chip"
 
 #define        COM_NOFIFO(dev) ((dev)->id_flags & 0x02)
 
 
 #define        COM_NOFIFO(dev) ((dev)->id_flags & 0x02)
 
-#ifndef        FIFO_TRIGGER
-/*
- * This driver is fast enough to work with any value and for high values
- * to be only slightly more efficient.  Low values may be better because
- * they give lower latency.
- * TODO: always use low values for low speeds.  Mouse movements are jerky
- * if more than one packet arrives at once.  The low speeds used for
- * serial mice help avoid this, but not if (large) fifos are enabled.
- */
-#define        FIFO_TRIGGER    FIFO_TRIGGER_14
-#endif
-
 #define        com_scr         7       /* scratch register for 16450-16550 (R/W) */
 
 #define        com_scr         7       /* scratch register for 16450-16550 (R/W) */
 
-#ifndef setsofttty
-#define        OLD_INTERRUPT_HANDLING  /* XXX FreeBSD-1.1 and earlier */
-#define        setsofttty()    (ipending |= 1 << 4)    /* XXX requires owning IRQ4 */
-extern u_int           ipending;       /* XXX */
-void   softsio1        __P((void));
-#endif
-
 /*
  * Input buffer watermarks.
  * The external device is asked to stop sending when the buffer exactly reaches
 /*
  * Input buffer watermarks.
  * The external device is asked to stop sending when the buffer exactly reaches
@@ -133,17 +113,19 @@ void      softsio1        __P((void));
  *     CS_CTS_OFLOW    = CCTS_OFLOW (maintained by comparam())
  *     CS_RTS_IFLOW    = CRTS_IFLOW (maintained by comparam())
  * TS_FLUSH is not used.
  *     CS_CTS_OFLOW    = CCTS_OFLOW (maintained by comparam())
  *     CS_RTS_IFLOW    = CRTS_IFLOW (maintained by comparam())
  * TS_FLUSH is not used.
- * Bug: I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
+ * 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_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        CS_ODONE        4       /* output completed */
 #define        CS_RTS_IFLOW    8       /* use RTS input flow control */
 
-static char    *error_desc[] = {
+static char const * const      error_desc[] = {
 #define        CE_OVERRUN                      0
        "silo overflow",
 #define        CE_INTERRUPT_BUF_OVERFLOW       1
 #define        CE_OVERRUN                      0
        "silo overflow",
 #define        CE_INTERRUPT_BUF_OVERFLOW       1
@@ -162,20 +144,19 @@ typedef u_char    bool_t;         /* boolean */
 /* com device structure */
 struct com_s {
        u_char  state;          /* miscellaneous flag bits */
 /* com device structure */
 struct com_s {
        u_char  state;          /* miscellaneous flag bits */
+       bool_t  active_out;     /* nonzero if the callout device is open */
        u_char  cfcr_image;     /* copy of value written to CFCR */
        u_char  cfcr_image;     /* copy of value written to CFCR */
+       u_char  ftl;            /* current rx fifo trigger level */
+       u_char  ftl_init;       /* ftl_max for next open() */
+       u_char  ftl_max;        /* maximum ftl for curent open() */
        bool_t  hasfifo;        /* nonzero for 16550 UARTs */
        u_char  mcr_image;      /* copy of value written to MCR */
        bool_t  hasfifo;        /* nonzero for 16550 UARTs */
        u_char  mcr_image;      /* copy of value written to MCR */
-#ifdef COM_BIDIR
-       bool_t  bidir;          /* is this unit bidirectional? */
-       bool_t  active;         /* is the port active _at all_? */
-       bool_t  active_in;      /* is the incoming port in use? */
-       bool_t  active_out;     /* is the outgoing port in use? */
-#endif /* COM_BIDIR */
 #ifdef COM_MULTIPORT
        bool_t  multiport;      /* is this unit part of a multiport device? */
 #endif /* COM_MULTIPORT */
 #ifdef COM_MULTIPORT
        bool_t  multiport;      /* is this unit part of a multiport device? */
 #endif /* COM_MULTIPORT */
-       int     dtr_wait;       /* time to hold DTR down on close (* 1/HZ) */
+       int     dtr_wait;       /* time to hold DTR down on close (* 1/hz) */
        u_int   tx_fifo_size;
        u_int   tx_fifo_size;
+       u_int   wopeners;       /* # processes waiting for DCD in open() */
 
        /*
         * The high level of the driver never reads status registers directly
 
        /*
         * The high level of the driver never reads status registers directly
@@ -186,6 +167,7 @@ struct com_s {
        u_char  last_modem_status;      /* last MSR read by intr handler */
        u_char  prev_modem_status;      /* last MSR handled by high level */
 
        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  *ihighwater;    /* threshold in input buffer */
        u_char  *ibuf;          /* start of input buffer */
        u_char  *ibufend;       /* end of input buffer */
        u_char  *ihighwater;    /* threshold in input buffer */
@@ -204,6 +186,14 @@ struct com_s {
 
        struct tty      *tp;    /* cross reference */
 
 
        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;
+
 #ifdef TIOCTIMESTAMP
        bool_t  do_timestamp;
        struct timeval  timestamp;
 #ifdef TIOCTIMESTAMP
        bool_t  do_timestamp;
        struct timeval  timestamp;
@@ -256,6 +246,7 @@ void        siocnprobe      __P((struct consdev *cp));
 void   siocnputc       __P((Dev_t dev, int c));
 
 static int     sioattach       __P((struct isa_device *dev));
 void   siocnputc       __P((Dev_t dev, int c));
 
 static int     sioattach       __P((struct isa_device *dev));
+static void    siodtrwakeup    __P((caddr_t chan, int ticks));
 static void    comflush        __P((struct com_s *com));
 static void    comhardclose    __P((struct com_s *com));
 static void    siointr1        __P((struct com_s *com));
 static void    comflush        __P((struct com_s *com));
 static void    comhardclose    __P((struct com_s *com));
 static void    siointr1        __P((struct com_s *com));
@@ -270,8 +261,6 @@ static      int     tiocm_xxx2mcr   __P((int tiocm_xxx));
 static struct com_s    *p_com_addr[NSIO];
 #define        com_addr(unit)  (p_com_addr[unit])
 
 static struct com_s    *p_com_addr[NSIO];
 #define        com_addr(unit)  (p_com_addr[unit])
 
-static struct com_s    com_structs[NSIO];
-
 #ifdef TIOCTIMESTAMP
 static  struct timeval intr_timestamp;
 #endif
 #ifdef TIOCTIMESTAMP
 static  struct timeval intr_timestamp;
 #endif
@@ -288,18 +277,8 @@ static     int     comconsole = -1;
 static speed_t comdefaultrate = TTYDEF_SPEED;
 static u_int   com_events;     /* input chars + weighted output completions */
 static int     commajor;
 static speed_t comdefaultrate = TTYDEF_SPEED;
 static u_int   com_events;     /* input chars + weighted output completions */
 static int     commajor;
-#ifdef DONT_MALLOC_TTYS
-#define TB_OUT(tp)     (&(tp)->t_out)
-#define TB_RAW(tp)     (&(tp)->t_raw)
-struct tty     sio_tty[NSIO];
-#else
-#define TB_OUT(tp)     ((tp)->t_out)
-#define TB_RAW(tp)     ((tp)->t_raw)
 struct tty     *sio_tty[NSIO];
 struct tty     *sio_tty[NSIO];
-#endif
-extern struct tty      *constty;
-extern int     tk_nin;         /* XXX */
-extern int     tk_rawcc;       /* XXX */
+extern struct tty      *constty;       /* XXX */
 
 #ifdef KGDB
 #include "machine/remote-sl.h"
 
 #ifdef KGDB
 #include "machine/remote-sl.h"
@@ -341,6 +320,7 @@ sioprobe(dev)
        static bool_t   already_init;
        Port_t          *com_ptr;
        Port_t          iobase;
        static bool_t   already_init;
        Port_t          *com_ptr;
        Port_t          iobase;
+       u_char          mcr_image;
        int             result;
 
        if (!already_init) {
        int             result;
 
        if (!already_init) {
@@ -348,6 +328,7 @@ sioprobe(dev)
                 * Turn off MCR_IENABLE for all likely serial ports.  An unused
                 * port with its MCR_IENABLE gate open will inhibit interrupts
                 * from any used port that shares the interrupt vector.
                 * Turn off MCR_IENABLE for all likely serial ports.  An unused
                 * port with its MCR_IENABLE gate open will inhibit interrupts
                 * from any used port that shares the interrupt vector.
+                * XXX the gate enable is elsewhere for some multiports.
                 */
                for (com_ptr = likely_com_ports;
                     com_ptr < &likely_com_ports[sizeof likely_com_ports
                 */
                for (com_ptr = likely_com_ports;
                     com_ptr < &likely_com_ports[sizeof likely_com_ports
@@ -356,6 +337,27 @@ sioprobe(dev)
                        outb(*com_ptr + com_mcr, 0);
                already_init = TRUE;
        }
                        outb(*com_ptr + com_mcr, 0);
                already_init = TRUE;
        }
+
+       /*
+        * If the port is on a multiport card and has a master port,
+        * initialize the common interrupt control register in the
+        * master and prepare to leave MCR_IENABLE clear.  Otherwise,
+        * prepare to set MCR_IENABLE.
+        */
+       mcr_image = MCR_IENABLE;
+#ifdef COM_MULTIPORT
+       if (COM_ISMULTIPORT(dev) && !COM_NOMASTER(dev)) {
+               struct isa_device *mdev;
+
+               mdev = find_isadev(isa_devtab_tty, &siodriver,
+                                  COM_MPMASTER(dev));
+               if (mdev != NULL) {
+                       outb(mdev->id_iobase + com_scr, 0x80);
+                       mcr_image = 0;
+               }
+       }
+#endif /* COM_MULTIPORT */
+
        iobase = dev->id_iobase;
        result = IO_COMSIZE;
 
        iobase = dev->id_iobase;
        result = IO_COMSIZE;
 
@@ -368,32 +370,74 @@ sioprobe(dev)
        disable_intr();
 
        /*
        disable_intr();
 
        /*
-        * Initialize the speed so that any junk in the THR or output fifo will
-        * be transmitted in a known time.  (There may be lots of junk after a
-        * soft reboot, and output interrupts don't work right after a master
-        * reset, at least for 16550s.  (The speed is undefined after MR, but
-        * MR empties the THR and the TSR so it's not clear why this matters)).
-        * Enable output interrupts (only) and check the following:
+        * Initialize the speed and the word size and wait long enough to
+        * drain the maximum of 16 bytes of junk in device output queues.
+        * The speed is undefined after a master reset and must be set
+        * before relying on anything related to output.  There may be
+        * junk after a (very fast) soft reboot and (apparently) after
+        * master reset.
+        * XXX what about the UART bug avoided by waiting in comparam()?
+        * We don't want to to wait long enough to drain at 2 bps.
+        */
+       outb(iobase + com_cfcr, CFCR_DLAB);
+       outb(iobase + com_dlbl, COMBRD(9600) & 0xff);
+       outb(iobase + com_dlbh, (u_int) COMBRD(9600) >> 8);
+       outb(iobase + com_cfcr, CFCR_8BITS);
+       DELAY((16 + 1) * 9600 / 10);
+
+       /* 
+        * Enable the interrupt gate and disable device interupts.  This
+        * should leave the device driving the interrupt line low and
+        * guarantee an edge trigger if an interrupt can be generated.
+        * Attempt to set loopback mode so that we can send a null byte
+        * without annoying any external device.
+        */
+       outb(iobase + com_mcr, mcr_image | MCR_LOOPBACK);
+       outb(iobase + com_ier, 0);
+
+       /*
+        * Attempt to generate an output interrupt.  On 8250's, setting
+        * IER_ETXRDY generates an interrupt independent of the current
+        * setting and independent of whether the THR is empty.  On 16450's,
+        * setting IER_ETXRDY generates an interrupt independent of the
+        * current setting.  On 16550A's, setting IER_ETXRDY only
+        * generates an interrupt when IER_ETXRDY is not already set.
+        */
+       outb(iobase + com_ier, IER_ETXRDY);
+
+       /*
+        * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate
+        * an interrupt.  They'd better generate one for actually doing
+        * output.  Loopback may be broken on the same incompatibles but
+        * it's unlikely to do more than allow the null byte out.
+        */
+       outb(iobase + com_data, 0);
+       DELAY((1 + 1) * 9600 / 10);
+
+       /*
+        * Turn off loopback mode so that the interrupt gate works again
+        * (MCR_IENABLE was hidden).  This should leave the device driving
+        * an interrupt line high.  It doesn't matter if the interrupt
+        * line oscillates while we are not looking at it, since interrupts
+        * are disabled.
+        * XXX interrupts are NOT disabled for the multiport shared
+        * interrupt case!  isa_configure() enables them after the probe
+        * of the first device on a shared interrupt succeeds.
+        */
+       outb(iobase + com_mcr, mcr_image);
+
+       /*
+        * Check that
         *      o the CFCR, IER and MCR in UART hold the values written to them
         *        (the values happen to be all distinct - this is good for
         *        avoiding false positive tests from bus echoes).
         *      o an output interrupt is generated and its vector is correct.
         *      o the interrupt goes away when the IIR in the UART is read.
         */
         *      o the CFCR, IER and MCR in UART hold the values written to them
         *        (the values happen to be all distinct - this is good for
         *        avoiding false positive tests from bus echoes).
         *      o an output interrupt is generated and its vector is correct.
         *      o the interrupt goes away when the IIR in the UART is read.
         */
-       outb(iobase + com_cfcr, CFCR_DLAB);
-       outb(iobase + com_dlbl, COMBRD(9600) & 0xff);
-       outb(iobase + com_dlbh, (u_int) COMBRD(9600) >> 8);
-       outb(iobase + com_cfcr, CFCR_8BITS);    /* ensure IER is addressed */
-       outb(iobase + com_mcr, MCR_IENABLE);    /* open gate early */
-       outb(iobase + com_ier, 0);              /* ensure edge on next intr */
-       outb(iobase + com_ier, IER_ETXRDY);     /* generate interrupt */
-       DELAY((16 + 1) * 9600 / 10);            /* enough to drain 16 bytes */
        if (   inb(iobase + com_cfcr) != CFCR_8BITS
            || inb(iobase + com_ier) != IER_ETXRDY
        if (   inb(iobase + com_cfcr) != CFCR_8BITS
            || inb(iobase + com_ier) != IER_ETXRDY
-           || inb(iobase + com_mcr) != MCR_IENABLE
-#ifndef COM_MULTIPORT /* XXX - need to do more to enable interrupts */
+           || inb(iobase + com_mcr) != mcr_image
            || !isa_irq_pending(dev)
            || !isa_irq_pending(dev)
-#endif
            || (inb(iobase + com_iir) & IIR_IMASK) != IIR_TXRDY
            || isa_irq_pending(dev)
            || (inb(iobase + com_iir) & IIR_IMASK) != IIR_NOPEND)
            || (inb(iobase + com_iir) & IIR_IMASK) != IIR_TXRDY
            || isa_irq_pending(dev)
            || (inb(iobase + com_iir) & IIR_IMASK) != IIR_NOPEND)
@@ -401,14 +445,15 @@ sioprobe(dev)
 
        /*
         * Turn off all device interrupts and check that they go off properly.
 
        /*
         * Turn off all device interrupts and check that they go off properly.
-        * Leave MCR_IENABLE set.  It gates the OUT2 output of the UART to
+        * Leave MCR_IENABLE alone.  For ports without a master port, it gates
+        * the OUT2 output of the UART to
         * the ICU input.  Closing the gate would give a floating ICU input
         * (unless there is another device driving at) and spurious interrupts.
         * (On the system that this was first tested on, the input floats high
         * and gives a (masked) interrupt as soon as the gate is closed.)
         */
        outb(iobase + com_ier, 0);
         * the ICU input.  Closing the gate would give a floating ICU input
         * (unless there is another device driving at) and spurious interrupts.
         * (On the system that this was first tested on, the input floats high
         * and gives a (masked) interrupt as soon as the gate is closed.)
         */
        outb(iobase + com_ier, 0);
-       outb(iobase + com_mcr, MCR_IENABLE);    /* dummy to avoid bus echo */
+       outb(iobase + com_cfcr, CFCR_8BITS);    /* dummy to avoid bus echo */
        if (   inb(iobase + com_ier) != 0
            || isa_irq_pending(dev)
            || (inb(iobase + com_iir) & IIR_IMASK) != IIR_NOPEND)
        if (   inb(iobase + com_ier) != 0
            || isa_irq_pending(dev)
            || (inb(iobase + com_iir) & IIR_IMASK) != IIR_NOPEND)
@@ -432,7 +477,9 @@ sioattach(isdp)
 
        iobase = isdp->id_iobase;
        unit = isdp->id_unit;
 
        iobase = isdp->id_iobase;
        unit = isdp->id_unit;
-       s = spltty();
+       com = malloc(sizeof *com, M_TTYS, M_NOWAIT);
+       if (com == NULL)
+               return (0);
 
        /*
         * sioprobe() has initialized the device registers as follows:
 
        /*
         * sioprobe() has initialized the device registers as follows:
@@ -441,14 +488,12 @@ sioattach(isdp)
         *        data port is not hidden when we enable interrupts.
         *      o ier = 0.
         *        Interrupts are only enabled when the line is open.
         *        data port is not hidden when we enable interrupts.
         *      o ier = 0.
         *        Interrupts are only enabled when the line is open.
-        *      o mcr = MCR_IENABLE.
+        *      o mcr = MCR_IENABLE, or 0 if the port has a master port.
         *        Keeping MCR_DTR and MCR_RTS off might stop the external
         *        device from sending before we are ready.
         */
         *        Keeping MCR_DTR and MCR_RTS off might stop the external
         *        device from sending before we are ready.
         */
-
-       com = &com_structs[unit];       /* XXX malloc it */
+       bzero(com, sizeof *com);
        com->cfcr_image = CFCR_8BITS;
        com->cfcr_image = CFCR_8BITS;
-       com->mcr_image = MCR_IENABLE;
        com->dtr_wait = 3 * hz;
        com->tx_fifo_size = 1;
        com->iptr = com->ibuf = com->ibuf1;
        com->dtr_wait = 3 * hz;
        com->tx_fifo_size = 1;
        com->iptr = com->ibuf = com->ibuf1;
@@ -458,11 +503,30 @@ sioattach(isdp)
        com->data_port = iobase + com_data;
        com->int_id_port = iobase + com_iir;
        com->modem_ctl_port = iobase + com_mcr;
        com->data_port = iobase + com_data;
        com->int_id_port = iobase + com_iir;
        com->modem_ctl_port = iobase + com_mcr;
+       com->mcr_image = inb(com->modem_ctl_port);
        com->line_status_port = iobase + com_lsr;
        com->modem_status_port = iobase + com_msr;
        com->line_status_port = iobase + com_lsr;
        com->modem_status_port = iobase + com_msr;
-#ifdef DONT_MALLOC_TTYS
-       com->tp = &sio_tty[unit];
-#endif
+
+       /*
+        * 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;
+       }
+       termioschars(&com->it_in);
+       com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
+       com->it_out = com->it_in;
 
        /* attempt to determine UART type */
        printf("sio%d: type", unit);
 
        /* attempt to determine UART type */
        printf("sio%d: type", unit);
@@ -503,6 +567,7 @@ sioattach(isdp)
                        printf(" fifo disabled");
                else {
                        com->hasfifo = TRUE;
                        printf(" fifo disabled");
                else {
                        com->hasfifo = TRUE;
+                       com->ftl_init = FIFO_TRIGGER_14;
                        com->tx_fifo_size = 16;
                }
                break;
                        com->tx_fifo_size = 16;
                }
                break;
@@ -513,25 +578,19 @@ determined_type: ;
 #ifdef COM_MULTIPORT
        if (COM_ISMULTIPORT(isdp)) {
            com->multiport = TRUE;
 #ifdef COM_MULTIPORT
        if (COM_ISMULTIPORT(isdp)) {
            com->multiport = TRUE;
-           printf(" (multiport)");
-
-           /* Note: some cards have no master port (e.g., BocaBoards) */
+               printf(" (multiport");
            if (!COM_NOMASTER(isdp)) {
            if (!COM_NOMASTER(isdp)) {
-               struct isa_device *masterdev;
-
-               /* set the master's common-interrupt-enable reg.,
-                * as appropriate. YYY See your manual
-                */
-               /* enable only common interrupt for port */
-               outb(com->modem_ctl_port, com->mcr_image = 0);
+                       struct isa_device *mdev;
 
 
-               masterdev = find_isadev(isa_devtab_tty, &siodriver,
+                       mdev = find_isadev(isa_devtab_tty, &siodriver,
                                        COM_MPMASTER(isdp));
                                        COM_MPMASTER(isdp));
-               outb(masterdev->id_iobase + com_scr, 0x80);
+                       if (mdev == NULL)
+                               printf(" master not found");
+                       else if (COM_MPMASTER(isdp) == unit)
+                               printf(" master");
+               }
+               printf(")");
            }
            }
-
-       } else
-               com->multiport = FALSE;
 #endif /* COM_MULTIPORT */
        printf("\n");
 
 #endif /* COM_MULTIPORT */
        printf("\n");
 
@@ -569,10 +628,11 @@ determined_type: ;
        }
 #endif
 
        }
 #endif
 
+       s = spltty();
        com_addr(unit) = com;
        splx(s);
        if (!comwakeup_started) {
        com_addr(unit) = com;
        splx(s);
        if (!comwakeup_started) {
-               comwakeup((caddr_t) NULL, 0);
+               comwakeup((caddr_t)NULL, 0);
                comwakeup_started = TRUE;
        }
        return (1);
                comwakeup_started = TRUE;
        }
        return (1);
@@ -586,227 +646,127 @@ sioopen(dev, flag, mode, p)
        int             mode;
        struct proc     *p;
 {
        int             mode;
        struct proc     *p;
 {
-#ifdef COM_BIDIR
-       bool_t          callout;
-#endif /* COM_BIDIR */
        struct com_s    *com;
        struct com_s    *com;
-       int             error = 0;
-       bool_t          got_status = FALSE;
+       int             error;
        Port_t          iobase;
        Port_t          iobase;
+       int             mynor;
        int             s;
        struct tty      *tp;
        int             unit;
 
        int             s;
        struct tty      *tp;
        int             unit;
 
-       unit = UNIT(dev);
+       mynor = minor(dev);
+       unit = MINOR_TO_UNIT(mynor);
        if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
                return (ENXIO);
        if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
                return (ENXIO);
-#ifdef COM_BIDIR
-       /* if it's a callout device, and bidir not possible on that dev, die */
-       callout = CALLOUT(dev);
-       if (callout && !(com->bidir))
-               return (ENXIO);
-#endif /* COM_BIDIR */
-
-#ifdef DONT_MALLOC_TTYS
-       tp = com->tp;
-#else
-       sio_tty[unit] = ttymalloc(sio_tty[unit]);
-       tp = com->tp = sio_tty[unit];
-#endif
+       if (mynor & CONTROL_MASK)
+               return (0);
+       tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]);
        s = spltty();
        s = spltty();
-
-#ifdef COM_BIDIR
-
-bidir_open_top:
-       got_status = FALSE;
-       /* if it's bidirectional, we've gotta deal with it... */
-       if (com->bidir) {
-               if (callout) {
-                       if (com->active_in) {
-                           /* it's busy. die */
-                           splx(s);
-                           return (EBUSY);
-                       } else {
-                           /* it's ours.  lock it down, and set it up */
-                           com->active_out = TRUE;
+       /*
+        * 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((caddr_t)&com->dtr_wait, TTIPRI | PCATCH,
+                              "siodtr", 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) {
                        }
                } else {
                        if (com->active_out) {
-                               /* it's busy, outgoing.  wait, if possible */
                                if (flag & O_NONBLOCK) {
                                if (flag & O_NONBLOCK) {
-                                   /* can't wait; bail */
-                                   splx(s);
-                                   return (EBUSY);
-                               } else {
-                                   /* wait for it... */
+                                       error = EBUSY;
+                                       goto out;
+                               }
                                    error = tsleep((caddr_t)&com->active_out,
                                    error = tsleep((caddr_t)&com->active_out,
-                                                  TTIPRI|PCATCH,
-                                                  "siooth",
-                                                  0);
-                                   /* if there was an error, take off. */
-                                   if (error != 0) {
-                                       splx(s);
-                                       return (error);
+                                              TTIPRI | PCATCH, "siobi", 0);
+                               if (error != 0)
+                                       goto out;
+                               goto open_top;
                                    }
                                    }
-                                   /* else take it from the top */
-                                   goto bidir_open_top;
                                }
                                }
+               if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
+                       error = EBUSY;
+                       goto out;
                        }
                        }
-                       disable_intr();
-                       com->prev_modem_status =
-                       com->last_modem_status = inb(com->modem_status_port);
-                       enable_intr();
-                       got_status = TRUE;
-                       if (com->prev_modem_status & MSR_DCD
-                           || FAKE_DCD(unit)) {
-                               /* there's a carrier on the line; we win */
-                               com->active_in = TRUE;
-                       } else {
-                               /* there is no carrier on the line */
-                               if (flag & O_NONBLOCK) {
-                                   /* can't wait; let it open */
-                                   com->active_in = TRUE;
                                } else {
                                } else {
-                                   /* put DTR & RTS up */
-                                   /* XXX - bring up RTS earlier? */
-                                   commctl(com, MCR_DTR | MCR_RTS, DMSET);
-                                   outb(com->iobase + com_ier, IER_EMSC);
-
-                                   /* wait for it... */
-                                   error = tsleep((caddr_t)&com->active_in,
-                                                  TTIPRI|PCATCH,
-                                                  "siodcd",
-                                                  0);
-
-                                   /* if not active, turn intrs and DTR off */
-                                   if (!com->active) {
-                                       outb(com->iobase + com_ier, 0);
-                                       commctl(com, MCR_DTR, DMBIC);
-                                   }
-
-                                   /* if there was an error, take off. */
-                                   if (error != 0) {
-                                       splx(s);
-                                       return (error);
-                                   }
-                                   /* else take it from the top */
-                                   goto bidir_open_top;
-                               }
-                       }
-               }
-       }
-
-       com->active = TRUE;
-#endif /* COM_BIDIR */
-
+               /*
+                * 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_param = comparam;
        tp->t_dev = dev;
        tp->t_oproc = comstart;
        tp->t_param = comparam;
        tp->t_dev = dev;
-       if (!(tp->t_state & TS_ISOPEN)) {
-               tp->t_state |= TS_WOPEN;
-               ttychars(tp);
-               if (tp->t_ispeed == 0) {
-                       /*
-                        * We don't use all the flags from <sys/ttydefaults.h>
-                        * since those 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.
-                        */
-                       tp->t_iflag = 0;
-                       tp->t_oflag = 0;
-                       tp->t_cflag = CREAD | CS8;
-#ifdef COM_BIDIR
-                       if (com->bidir && !callout)
-                               tp->t_cflag |= HUPCL;
-#endif
-                       tp->t_lflag = 0;
-                       tp->t_ispeed = tp->t_ospeed = comdefaultrate;
-                       if (unit == comconsole) {
-                               tp->t_iflag = TTYDEF_IFLAG;
-                               tp->t_oflag = TTYDEF_OFLAG;
-                               tp->t_cflag = TTYDEF_CFLAG;
-                               tp->t_lflag = TTYDEF_LFLAG;
-                       }
-               }
-
-               /*
-                * XXX the full state after a first open() needs to be
-                * programmable and separate for callin and callout.
-                */
-#ifdef COM_BIDIR
-               if (com->bidir) {
-                       if (callout)
-                               tp->t_cflag |= CLOCAL;
-                       else
-                               tp->t_cflag &= ~CLOCAL;
-               }
-#endif
-
+               tp->t_termios = mynor & CALLOUT_MASK
+                               ? com->it_out : com->it_in;
                commctl(com, MCR_DTR | MCR_RTS, DMSET);
                commctl(com, MCR_DTR | MCR_RTS, DMSET);
+               com->ftl_max = com->ftl_init;
+               ++com->wopeners;
                error = comparam(tp, &tp->t_termios);
                error = comparam(tp, &tp->t_termios);
+               --com->wopeners;
                if (error != 0)
                        goto out;
                if (error != 0)
                        goto out;
+               /*
+                * XXX we should goto open_top if comparam() slept.
+                */
                ttsetwater(tp);
                iobase = com->iobase;
                if (com->hasfifo) {
                ttsetwater(tp);
                iobase = com->iobase;
                if (com->hasfifo) {
-                       /* (re)enable and drain FIFO */
-                       outb(iobase + com_fifo, FIFO_ENABLE | FIFO_TRIGGER
-                                               | FIFO_RCV_RST | FIFO_XMT_RST);
+                       /* Drain fifo. */
+                       outb(iobase + com_fifo,
+                            FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST
+                            | com->ftl);
                        DELAY(100);
                }
                disable_intr();
                (void) inb(com->line_status_port);
                (void) inb(com->data_port);
                        DELAY(100);
                }
                disable_intr();
                (void) inb(com->line_status_port);
                (void) inb(com->data_port);
-               if (!got_status)
                        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();
                        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();
-               if (com->prev_modem_status & MSR_DCD || FAKE_DCD(unit))
-                       tp->t_state |= TS_CARR_ON;
-       } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
-               splx(s);
-               return (EBUSY);
-       }
-       while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL)
-#ifdef COM_BIDIR
-               /* We went through a lot of trouble to open it,
-                * but it's certain we have a carrier now, so
-                * don't spend any time on it now.
+               /*
+                * 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 "siobi"
+                * instead of "siodcd".
                 */
                 */
-              && !(com->bidir)
-#endif /* COM_BIDIR */
-              && !(tp->t_state & TS_CARR_ON)) {
-               tp->t_state |= TS_WOPEN;
-               error = ttysleep(tp, (caddr_t)TB_RAW(tp), TTIPRI | PCATCH,
-                                ttopen, 0);
+               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) && !(flag & O_NONBLOCK)) {
+               ++com->wopeners;
+               error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0);
+               --com->wopeners;
                if (error != 0)
                if (error != 0)
-                       break;
+                       goto out;
+               goto open_top;
        }
        }
-out:
-       if (error == 0)
                error = (*linesw[tp->t_line].l_open)(dev, tp, 0);
                error = (*linesw[tp->t_line].l_open)(dev, tp, 0);
+       if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
+               com->active_out = TRUE;
+out:
        splx(s);
        splx(s);
-
-#ifdef COM_BIDIR
-       /* wakeup sleepers */
-       wakeup((caddr_t) &com->active_in);
-#endif /* COM_BIDIR */
-
-       /*
-        * XXX - the next step was once not done, so interrupts, DTR and RTS
-        * remained hot if the process was killed while it was sleeping
-        * waiting for carrier.  Now there is the opposite problem.  If several
-        * processes are sleeping waiting for carrier on the same line and one
-        * is killed, interrupts are turned off so the other processes will
-        * never see the carrier rise.
-        */
-       if (error != 0 && !(tp->t_state & TS_ISOPEN))
+       if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
                comhardclose(com);
                comhardclose(com);
-       tp->t_state &= ~TS_WOPEN;
-
        return (error);
 }
 
        return (error);
 }
 
@@ -819,10 +779,14 @@ sioclose(dev, flag, mode, p)
        struct proc     *p;
 {
        struct com_s    *com;
        struct proc     *p;
 {
        struct com_s    *com;
+       int             mynor;
        int             s;
        struct tty      *tp;
 
        int             s;
        struct tty      *tp;
 
-       com = com_addr(UNIT(dev));
+       mynor = minor(dev);
+       if (mynor & CONTROL_MASK)
+               return (0);
+       com = com_addr(MINOR_TO_UNIT(mynor));
        tp = com->tp;
        s = spltty();
        (*linesw[tp->t_line].l_close)(tp, flag);
        tp = com->tp;
        s = spltty();
        (*linesw[tp->t_line].l_close)(tp, flag);
@@ -842,7 +806,7 @@ comhardclose(com)
        struct tty      *tp;
        int             unit;
 
        struct tty      *tp;
        int             unit;
 
-       unit = com - &com_structs[0];
+       unit = DEV_TO_UNIT(com->tp->t_dev);
        iobase = com->iobase;
        s = spltty();
 #ifdef TIOCTIMESTAMP
        iobase = com->iobase;
        s = spltty();
 #ifdef TIOCTIMESTAMP
@@ -856,43 +820,29 @@ comhardclose(com)
        {
                outb(iobase + com_ier, 0);
                tp = com->tp;
        {
                outb(iobase + com_ier, 0);
                tp = com->tp;
-               if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN
-#ifdef COM_BIDIR
+               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
                    /*
                     * 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.  And we shouldn't look at DCD if
-                    * CLOCAL is set (here or for the dialin device ...).
-                    * When the termios state is reinitialized for initial
-                    * opens, the correct CLOCAL bit will be
-                    * ((the bit now) & (the initial bit)).
+                    * we're not watching.
                     */
                     */
-                   || com->active_in
-                      && !(com->prev_modem_status & MSR_DCD) && !FAKE_DCD(unit)
-#endif
+                   || !com->active_out
+                      && !(com->prev_modem_status & MSR_DCD)
+                      && !(com->it_in.c_cflag & CLOCAL)
                    || !(tp->t_state & TS_ISOPEN)) {
                        commctl(com, MCR_RTS, DMSET);
                    || !(tp->t_state & TS_ISOPEN)) {
                        commctl(com, MCR_RTS, DMSET);
-                       if (com->dtr_wait != 0)
-                               /*
-                                * Uninterruptible sleep since we want to
-                                * wait a fixed time.
-                                * XXX - delay in open() (if necessary),
-                                * not here (always).
-                                */
-                               tsleep((caddr_t)&com->dtr_wait, TTIPRI,
-                                      "sioclose", com->dtr_wait);
+                       if (com->dtr_wait != 0) {
+                               timeout(siodtrwakeup, (caddr_t)com,
+                                       com->dtr_wait);
+                               com->state |= CS_DTR_OFF;
                }
        }
                }
        }
-
-#ifdef COM_BIDIR
-       com->active = com->active_in = com->active_out = FALSE;
-
-       /* wakeup sleepers who are waiting for out to finish */
-       wakeup((caddr_t) &com->active_out);
-#endif /* COM_BIDIR */
-
+       }
+       com->active_out = FALSE;
+       wakeup((caddr_t)&com->active_out);
+       wakeup(TSA_CARR_ON(tp));        /* restart any wopeners */
        splx(s);
 }
 
        splx(s);
 }
 
@@ -902,8 +852,13 @@ sioread(dev, uio, flag)
        struct uio      *uio;
        int             flag;
 {
        struct uio      *uio;
        int             flag;
 {
-       struct tty      *tp = com_addr(UNIT(dev))->tp;
+       int             mynor;
+       struct tty      *tp;
 
 
+       mynor = minor(dev);
+       if (mynor & CONTROL_MASK)
+               return (ENODEV);
+       tp = com_addr(MINOR_TO_UNIT(mynor))->tp;
        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
 }
 
        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
 }
 
@@ -913,9 +868,15 @@ siowrite(dev, uio, flag)
        struct uio      *uio;
        int             flag;
 {
        struct uio      *uio;
        int             flag;
 {
-       int             unit = UNIT(dev);
-       struct tty      *tp = com_addr(unit)->tp;
+       int             mynor;
+       struct tty      *tp;
+       int             unit;
 
 
+       mynor = minor(dev);
+       if (mynor & CONTROL_MASK)
+               return (ENODEV);
+       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
        /*
         * (XXX) We disallow virtual consoles if the physical console is
         * a serial port.  This is in case there is a display attached that
@@ -927,6 +888,18 @@ siowrite(dev, uio, flag)
        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
 }
 
        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
 }
 
+static void
+siodtrwakeup(chan, ticks)
+       caddr_t chan;
+       int     ticks;
+{
+       struct com_s    *com;
+
+       com = (struct com_s *)chan;
+       com->state &= ~CS_DTR_OFF;
+       wakeup((caddr_t)&com->dtr_wait);
+}
+
 #ifdef TIOCTIMESTAMP
 /* Interrupt routine for timekeeping purposes */
 void
 #ifdef TIOCTIMESTAMP
 /* Interrupt routine for timekeeping purposes */
 void
@@ -945,8 +918,8 @@ siointr(unit)
 #ifndef COM_MULTIPORT
        siointr1(com_addr(unit));
 #else /* COM_MULTIPORT */
 #ifndef COM_MULTIPORT
        siointr1(com_addr(unit));
 #else /* COM_MULTIPORT */
-       bool_t          possibly_more_intrs;
        struct com_s    *com;
        struct com_s    *com;
+       bool_t          possibly_more_intrs;
 
        /*
         * Loop until there is no activity on any port.  This is necessary
 
        /*
         * Loop until there is no activity on any port.  This is necessary
@@ -995,9 +968,7 @@ siointr1(com)
                        else
                                recv_data = inb(com->data_port);
                        ++com->bytes_in;
                        else
                                recv_data = inb(com->data_port);
                        ++com->bytes_in;
-                       /* XXX reduce SLIP input latency */
-#define        FRAME_END       0xc0
-                       if (recv_data == FRAME_END)
+                       if (com->hotchar != 0 && recv_data == com->hotchar)
                                setsofttty();
 #ifdef KGDB
                        /* trap into kgdb? (XXX - needs testing and optim) */
                                setsofttty();
 #ifdef KGDB
                        /* trap into kgdb? (XXX - needs testing and optim) */
@@ -1123,26 +1094,75 @@ sioioctl(dev, cmd, data, flag, p)
        Port_t          iobase;
        int             mcr;
        int             msr;
        Port_t          iobase;
        int             mcr;
        int             msr;
+       int             mynor;
        int             s;
        int             tiocm_xxx;
        struct tty      *tp;
 
        int             s;
        int             tiocm_xxx;
        struct tty      *tp;
 
-       com = com_addr(UNIT(dev));
+       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:
+                       return (ENODEV);        /* /dev/nodev */
+               }
+               switch (cmd) {
+               case TIOCSETA:
+                       error = suser(p->p_ucred, &p->p_acflag);
+                       if (error)
+                               return (error);
+                       *ct = *(struct termios *)data;
+                       return (0);
+               case TIOCGETA:
+                       *(struct termios *)data = *ct;
+                       return (0);
+               case TIOCGETD:
+                       *(int *)data = TTYDISC;
+                       return (0);
+               case TIOCGWINSZ:
+                       bzero(data, sizeof(struct winsize));
+                       return (0);
+               default:
+                       return (ENOTTY);
+               }
+       }
        tp = com->tp;
        tp = com->tp;
+       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, flag);
        if (error >= 0)
                return (error);
        error = ttioctl(tp, cmd, data, flag);
        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
        if (error >= 0)
                return (error);
        error = ttioctl(tp, cmd, data, flag);
-
-#ifdef COM_BIDIR
-       /* XXX: plug security hole while sticky bits not yet implemented */
-       if (com->bidir && com->active_in && p->p_ucred->cr_uid != 0)
-               tp->t_cflag &= ~CLOCAL;
-#endif
-
        if (error >= 0)
                return (error);
        if (error >= 0)
                return (error);
-
        iobase = com->iobase;
        s = spltty();
        switch (cmd) {
        iobase = com->iobase;
        s = spltty();
        switch (cmd) {
@@ -1190,52 +1210,14 @@ sioioctl(dev, cmd, data, flag, p)
                        tiocm_xxx |= TIOCM_RI;
                *(int *)data = tiocm_xxx;
                break;
                        tiocm_xxx |= TIOCM_RI;
                *(int *)data = tiocm_xxx;
                break;
-#ifdef COM_BIDIR
-       case TIOCMSBIDIR:
-               /* must be root to set bidir. capability */
-               error = suser(p->p_ucred, &p->p_acflag);
-               if (error != 0) {
-                       splx(s);
-                       return(EPERM);
-               }
-
-               /* if it's the console, can't do it (XXX why?) */
-               if (UNIT(dev) == comconsole) {
-                       splx(s);
-                       return(ENOTTY);
-               }
-
-#if 0
-               /* XXX - can't do the next, for obvious reasons...
-                * but there are problems to be looked at...
-                */
-               /* if the port is active, don't do it */
-               if (com->active) {
-                       splx(s);
-                       return(EBUSY);
-               }
-#endif
-
-               com->bidir = *(int *)data;
-               break;
-       case TIOCMGBIDIR:
-               *(int *)data = com->bidir;
-               break;
-#endif /* COM_BIDIR */
        case TIOCMSDTRWAIT:
                /* must be root since the wait applies to following logins */
                error = suser(p->p_ucred, &p->p_acflag);
                if (error != 0) {
                        splx(s);
        case TIOCMSDTRWAIT:
                /* must be root since the wait applies to following logins */
                error = suser(p->p_ucred, &p->p_acflag);
                if (error != 0) {
                        splx(s);
-                       return(EPERM);
-               }
-
-               /* if it's the console, can't do it (XXX why?) */
-               if (UNIT(dev) == comconsole) {
-                       splx(s);
-                       return(ENOTTY);
+                       return (EPERM);
                }
                }
-               com->dtr_wait = *(int *)data;
+               com->dtr_wait = *(int *)data * 100 / hz;
                break;
        case TIOCMGDTRWAIT:
                *(int *)data = com->dtr_wait;
                break;
        case TIOCMGDTRWAIT:
                *(int *)data = com->dtr_wait;
@@ -1266,7 +1248,7 @@ comflush(com)
                com_events -= LOTS_OF_EVENTS;
        com->state &= ~(CS_ODONE | CS_BUSY);
        enable_intr();
                com_events -= LOTS_OF_EVENTS;
        com->state &= ~(CS_ODONE | CS_BUSY);
        enable_intr();
-       rbp = TB_OUT(com->tp);
+       rbp = com->tp->t_out;
        rbp->rb_hd += com->ocount;
        rbp->rb_hd = RB_ROLLOVER(rbp, rbp->rb_hd);
        com->ocount = 0;
        rbp->rb_hd += com->ocount;
        rbp->rb_hd = RB_ROLLOVER(rbp, rbp->rb_hd);
        com->ocount = 0;
@@ -1276,26 +1258,10 @@ comflush(com)
 void
 siopoll()
 {
 void
 siopoll()
 {
-#ifdef OLD_INTERRUPT_HANDLING
-       static bool_t   awake = FALSE;
-       int             s;
-#endif
        int             unit;
 
        if (com_events == 0)
                return;
        int             unit;
 
        if (com_events == 0)
                return;
-
-#ifdef OLD_INTERRUPT_HANDLING
-       disable_intr();
-       if (awake) {
-               enable_intr();
-               return;
-       }
-       awake = TRUE;
-       enable_intr();
-       s = spltty();
-#endif
-
 repeat:
        for (unit = 0; unit < NSIO; ++unit) {
                u_char          *buf;
 repeat:
        for (unit = 0; unit < NSIO; ++unit) {
                u_char          *buf;
@@ -1308,16 +1274,25 @@ repeat:
                if (com == NULL)
                        continue;
                tp = com->tp;
                if (com == NULL)
                        continue;
                tp = com->tp;
-#ifdef DONT_MALLOC_TTYS
                if (tp == NULL)
                        continue;
                if (tp == NULL)
                        continue;
-#endif
 
                /* switch the role of the low-level input buffers */
                if (com->iptr == (ibuf = com->ibuf)) {
                        buf = NULL;     /* not used, but compiler can't tell */
                        incc = 0;
                } else {
 
                /* switch the role of the low-level input buffers */
                if (com->iptr == (ibuf = com->ibuf)) {
                        buf = NULL;     /* not used, but compiler can't tell */
                        incc = 0;
                } else {
+                       /*
+                        * Prepare to reduce input latency for packet
+                        * discplines with a end of packet character.
+                        * XXX should be elsewhere.
+                        */
+                       if (tp->t_line == SLIPDISC)
+                               com->hotchar = 0xc0;
+                       else if (tp->t_line == PPPDISC)
+                               com->hotchar = 0x7e;
+                       else
+                               com->hotchar = 0;
                        buf = ibuf;
                        disable_intr();
                        incc = com->iptr - buf;
                        buf = ibuf;
                        disable_intr();
                        incc = com->iptr - buf;
@@ -1361,15 +1336,9 @@ repeat:
                        com_events -= LOTS_OF_EVENTS;
                        com->state &= ~CS_CHECKMSR;
                        enable_intr();
                        com_events -= LOTS_OF_EVENTS;
                        com->state &= ~CS_CHECKMSR;
                        enable_intr();
-                       if (delta_modem_status & MSR_DCD && !FAKE_DCD(unit)) {
-                               if (com->prev_modem_status & MSR_DCD) {
-                                       (*linesw[tp->t_line].l_modem)(tp, 1);
-#ifdef COM_BIDIR
-                                       wakeup((caddr_t) &com->active_in);
-#endif /* COM_BIDIR */
-                               } else
-                                       (*linesw[tp->t_line].l_modem)(tp, 0);
-                       }
+                       if (delta_modem_status & MSR_DCD)
+                               (*linesw[tp->t_line].l_modem)
+                                       (tp, com->prev_modem_status & MSR_DCD);
                }
 
                /* XXX */
                }
 
                /* XXX */
@@ -1383,13 +1352,29 @@ repeat:
                                delta = com->delta_error_counts[errnum];
                                com->delta_error_counts[errnum] = 0;
                                enable_intr();
                                delta = com->delta_error_counts[errnum];
                                com->delta_error_counts[errnum] = 0;
                                enable_intr();
-                               if (delta != 0) {
-                                       total =
-                                       com->error_counts[errnum] += delta;
+                               if (delta == 0 || !(tp->t_state & TS_ISOPEN))
+                                       continue;
+                               total = com->error_counts[errnum] += delta;
                                        log(LOG_WARNING,
                                        "sio%d: %u more %s%s (total %lu)\n",
                                            unit, delta, error_desc[errnum],
                                            delta == 1 ? "" : "s", total);
                                        log(LOG_WARNING,
                                        "sio%d: %u more %s%s (total %lu)\n",
                                            unit, delta, error_desc[errnum],
                                            delta == 1 ? "" : "s", total);
+                               if (errnum == CE_OVERRUN && com->hasfifo
+                                   && com->ftl > FIFO_TRIGGER_1) {
+                                       static  u_char ftl_in_bytes[] =
+                                               { 1, 4, 8, 14, };
+
+                                       com->ftl_init = FIFO_TRIGGER_8;
+#define        FIFO_TRIGGER_DELTA      FIFO_TRIGGER_4
+                                       com->ftl_max =
+                                       com->ftl -= FIFO_TRIGGER_DELTA;
+                                       outb(com->iobase + com_fifo,
+                                            FIFO_ENABLE | com->ftl);
+                                       log(LOG_WARNING,
+                               "sio%d: reduced fifo trigger level to %d\n",
+                                           unit,
+                                           ftl_in_bytes[com->ftl
+                                                        / FIFO_TRIGGER_DELTA]);
                                }
                        }
                }
                                }
                        }
                }
@@ -1404,7 +1389,7 @@ repeat:
                if (incc <= 0 || !(tp->t_state & TS_ISOPEN))
                        continue;
                if (com->state & CS_RTS_IFLOW
                if (incc <= 0 || !(tp->t_state & TS_ISOPEN))
                        continue;
                if (com->state & CS_RTS_IFLOW
-                   && RB_LEN(TB_RAW(tp)) + incc >= RB_I_HIGH_WATER
+                   && RB_LEN(tp->t_raw) + incc >= RB_I_HIGH_WATER
                    && !(tp->t_state & TS_RTS_IFLOW)
                    /*
                     * XXX - need RTS flow control for all line disciplines.
                    && !(tp->t_state & TS_RTS_IFLOW)
                    /*
                     * XXX - need RTS flow control for all line disciplines.
@@ -1431,7 +1416,7 @@ repeat:
                        tk_rawcc += incc;
                        tp->t_rawcc += incc;
                        com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
                        tk_rawcc += incc;
                        tp->t_rawcc += incc;
                        com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
-                               += incc - rb_write(TB_RAW(tp), (char *) buf,
+                               += incc - rb_write(tp->t_raw, (char *) buf,
                                                   incc);
                        ttwakeup(tp);
                        if (tp->t_state & TS_TTSTOP
                                                   incc);
                        ttwakeup(tp);
                        if (tp->t_state & TS_TTSTOP
@@ -1467,11 +1452,6 @@ repeat:
        }
        if (com_events >= LOTS_OF_EVENTS)
                goto repeat;
        }
        if (com_events >= LOTS_OF_EVENTS)
                goto repeat;
-
-#ifdef OLD_INTERRUPT_HANDLING
-       splx(s);
-       awake = FALSE;
-#endif
 }
 
 static int
 }
 
 static int
@@ -1496,7 +1476,7 @@ comparam(tp, t)
                return (EINVAL);
 
        /* parameters are OK, convert them to the com struct and the device */
                return (EINVAL);
 
        /* parameters are OK, convert them to the com struct and the device */
-       unit = UNIT(tp->t_dev);
+       unit = DEV_TO_UNIT(tp->t_dev);
        com = com_addr(unit);
        iobase = com->iobase;
        s = spltty();
        com = com_addr(unit);
        iobase = com->iobase;
        s = spltty();
@@ -1527,6 +1507,22 @@ comparam(tp, t)
        if (cflag & CSTOPB)
                cfcr |= CFCR_STOPB;
 
        if (cflag & CSTOPB)
                cfcr |= CFCR_STOPB;
 
+       if (com->hasfifo) {
+               /*
+                * Use a fifo trigger level low enough so that the input
+                * latency from the fifo is less than about 16 msec and
+                * the total latency is less than about 30 msec.  These
+                * latencies are reasonable for humans.  Serial comms
+                * protocols shouldn't expect anything better since modem
+                * latencies are larger.
+                */
+               com->ftl = t->c_ospeed <= 4800
+                          ? FIFO_TRIGGER_1 : FIFO_TRIGGER_14;
+               if (com->ftl > com->ftl_max)
+                       com->ftl = com->ftl_max;
+               outb(iobase + com_fifo, FIFO_ENABLE | com->ftl);
+       }
+
        /*
         * Some UARTs lock up if the divisor latch registers are selected
         * while the UART is doing output (they refuse to transmit anything
        /*
         * Some UARTs lock up if the divisor latch registers are selected
         * while the UART is doing output (they refuse to transmit anything
@@ -1541,8 +1537,8 @@ retry:
        enable_intr();
        while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
               != (LSR_TSRE | LSR_TXRDY)) {
        enable_intr();
        while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
               != (LSR_TSRE | LSR_TXRDY)) {
-               error = ttysleep(tp, (caddr_t)TB_RAW(tp), TTIPRI | PCATCH,
-                                "sioparam", 1);
+               error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH,
+                                "siotx", hz / 100);
                if (error != 0 && error != EAGAIN) {
                        if (!(tp->t_state & TS_TTSTOP)) {
                                disable_intr();
                if (error != 0 && error != EAGAIN) {
                        if (!(tp->t_state & TS_TTSTOP)) {
                                disable_intr();
@@ -1582,7 +1578,7 @@ retry:
        /*
         * Set up state to handle output flow control.
         * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
        /*
         * Set up state to handle output flow control.
         * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
-        * Now has 16+ msec latency, while CTS flow has 50- usec latency.
+        * Now has 10+ msec latency, while CTS flow has 50- usec latency.
         */
        com->state &= ~CS_CTS_OFLOW;
        com->state |= CS_ODEVREADY;
         */
        com->state &= ~CS_CTS_OFLOW;
        com->state |= CS_ODEVREADY;
@@ -1596,9 +1592,6 @@ retry:
         * Recover from fiddling with CS_TTGO.  We used to call siointr1()
         * unconditionally, but that defeated the careful discarding of
         * stale input in sioopen().
         * Recover from fiddling with CS_TTGO.  We used to call siointr1()
         * unconditionally, but that defeated the careful discarding of
         * stale input in sioopen().
-        *
-        * XXX sioopen() is not careful waiting for carrier for the callout
-        * case.
         */
        if (com->state >= (CS_BUSY | CS_TTGO))
                siointr1(com);
         */
        if (com->state >= (CS_BUSY | CS_TTGO))
                siointr1(com);
@@ -1616,7 +1609,7 @@ comstart(tp)
        int             s;
        int             unit;
 
        int             s;
        int             unit;
 
-       unit = UNIT(tp->t_dev);
+       unit = DEV_TO_UNIT(tp->t_dev);
        com = com_addr(unit);
        s = spltty();
        disable_intr();
        com = com_addr(unit);
        s = spltty();
        disable_intr();
@@ -1639,26 +1632,17 @@ comstart(tp)
        enable_intr();
        if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))
                goto out;
        enable_intr();
        if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))
                goto out;
-       if (RB_LEN(TB_OUT(tp)) <= tp->t_lowat) {
-               if (tp->t_state & TS_ASLEEP) {
-                       tp->t_state &= ~TS_ASLEEP;
-                       wakeup((caddr_t)TB_OUT(tp));
-               }
-               if (tp->t_wsel) {
-                       selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
-                       tp->t_wsel = 0;
-                       tp->t_state &= ~TS_WCOLL;
-               }
-       }
+       if (tp->t_state & (TS_SO_OCOMPLETE | TS_SO_OLOWAT) || tp->t_wsel)
+               ttwwakeup(tp);
        if (com->ocount != 0) {
                disable_intr();
                siointr1(com);
                enable_intr();
        if (com->ocount != 0) {
                disable_intr();
                siointr1(com);
                enable_intr();
-       } else if (RB_LEN(TB_OUT(tp)) != 0) {
+       } else if (RB_LEN(tp->t_out) != 0) {
                tp->t_state |= TS_BUSY;
                tp->t_state |= TS_BUSY;
-               com->ocount = RB_CONTIGGET(TB_OUT(tp));
+               com->ocount = RB_CONTIGGET(tp->t_out);
                disable_intr();
                disable_intr();
-               com->obufend = (com->optr = (u_char *)TB_OUT(tp)->rb_hd)
+               com->obufend = (com->optr = (u_char *)tp->t_out->rb_hd)
                              + com->ocount;
                com->state |= CS_BUSY;
                siointr1(com);  /* fake interrupt to start output */
                              + com->ocount;
                com->state |= CS_BUSY;
                siointr1(com);  /* fake interrupt to start output */
@@ -1675,7 +1659,7 @@ siostop(tp, rw)
 {
        struct com_s    *com;
 
 {
        struct com_s    *com;
 
-       com = com_addr(UNIT(tp->t_dev));
+       com = com_addr(DEV_TO_UNIT(tp->t_dev));
        if (rw & FWRITE)
                comflush(com);
        disable_intr();
        if (rw & FWRITE)
                comflush(com);
        disable_intr();
@@ -1696,7 +1680,9 @@ sioselect(dev, rw, p)
        int             rw;
        struct proc     *p;
 {
        int             rw;
        struct proc     *p;
 {
-       return (ttselect(dev & ~COM_MINOR_MAGIC_MASK, rw, p));
+       if (minor(dev) & CONTROL_MASK)
+               return (ENODEV);
+       return (ttselect(dev & ~MINOR_MAGIC_MASK, rw, p));
 }
 
 static void
 }
 
 static void
@@ -1728,16 +1714,14 @@ comwakeup(chan, ticks)
 {
        int     unit;
 
 {
        int     unit;
 
-       timeout(comwakeup, (caddr_t) NULL, hz / 100);
+       timeout(comwakeup, (caddr_t)NULL, hz / 100);
 
        if (com_events != 0) {
 
        if (com_events != 0) {
-#ifndef OLD_INTERRUPT_HANDLING
-               int     s = splsofttty();
-#endif
+               int     s;
+
+               s = splsofttty();
                siopoll();
                siopoll();
-#ifndef OLD_INTERRUPT_HANDLING
                splx(s);
                splx(s);
-#endif
        }
 
        /* recover from lost output interrupts */
        }
 
        /* recover from lost output interrupts */
@@ -1753,14 +1737,6 @@ comwakeup(chan, ticks)
        }
 }
 
        }
 }
 
-#ifdef OLD_INTERRUPT_HANDLING
-void
-softsio1()
-{
-       siopoll();
-}
-#endif
-
 /*
  * Following are all routines needed for SIO to act as console
  */
 /*
  * Following are all routines needed for SIO to act as console
  */
@@ -1776,6 +1752,10 @@ struct siocnstate {
 
 static Port_t  siocniobase;
 
 
 static Port_t  siocniobase;
 
+static void siocnclose __P((struct siocnstate *sp));
+static void siocnopen  __P((struct siocnstate *sp));
+static void siocntxwait        __P((void));
+
 static void
 siocntxwait()
 {
 static void
 siocntxwait()
 {
@@ -1836,7 +1816,7 @@ siocnclose(sp)
        outb(iobase + com_dlbh, sp->dlbh);
        outb(iobase + com_cfcr, sp->cfcr);
        /*
        outb(iobase + com_dlbh, sp->dlbh);
        outb(iobase + com_cfcr, sp->cfcr);
        /*
-        * XXX damp osicllations of MCR_DTR or MCR_RTS by not restoring them.
+        * XXX damp oscllations of MCR_DTR and MCR_RTS by not restoring them.
         */
        outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
        outb(iobase + com_ier, sp->ier);
         */
        outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
        outb(iobase + com_ier, sp->ier);
@@ -1855,7 +1835,7 @@ siocnprobe(cp)
                        break;
 
        /* XXX: ick */
                        break;
 
        /* XXX: ick */
-       unit = UNIT(CONUNIT);
+       unit = DEV_TO_UNIT(CONUNIT);
        siocniobase = CONADDR;
 
        /* make sure hardware exists?  XXX */
        siocniobase = CONADDR;
 
        /* make sure hardware exists?  XXX */
@@ -1877,7 +1857,7 @@ siocninit(cp)
         * XXX can delete more comconsole stuff now that i/o routines are
         * fairly reentrant.
         */
         * XXX can delete more comconsole stuff now that i/o routines are
         * fairly reentrant.
         */
-       comconsole = UNIT(cp->cn_dev);
+       comconsole = DEV_TO_UNIT(cp->cn_dev);
 }
 
 int
 }
 
 int