have to include proc.h before socketvar.h
[unix-history] / usr / src / sys / hp300 / dev / dcm.c
index 5a40daa..321d93f 100644 (file)
@@ -9,15 +9,15 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- * from: $Hdr: dcm.c 1.17 89/10/01$
+ * from: $Hdr: dcm.c 1.26 91/01/21$
  *
  *
- *     @(#)dcm.c       7.7 (Berkeley) %G%
+ *     @(#)dcm.c       7.16 (Berkeley) %G%
  */
 
 /*
  * TODO:
  *     Timeouts
  */
 
 /*
  * TODO:
  *     Timeouts
- *     Test console/kgdb support.
+ *     Test console support.
  */
 
 #include "dcm.h"
  */
 
 #include "dcm.h"
 /*
  *  98642/MUX
  */
 /*
  *  98642/MUX
  */
-#include "param.h"
-#include "systm.h"
-#include "ioctl.h"
-#include "tty.h"
-#include "user.h"
-#include "conf.h"
-#include "file.h"
-#include "uio.h"
-#include "kernel.h"
-#include "syslog.h"
-#include "time.h"
+#include "sys/param.h"
+#include "sys/systm.h"
+#include "sys/ioctl.h"
+#include "sys/tty.h"
+#include "sys/proc.h"
+#include "sys/conf.h"
+#include "sys/file.h"
+#include "sys/uio.h"
+#include "sys/kernel.h"
+#include "sys/syslog.h"
+#include "sys/time.h"
 
 #include "device.h"
 #include "dcmreg.h"
 #include "machine/cpu.h"
 
 #include "device.h"
 #include "dcmreg.h"
 #include "machine/cpu.h"
-#include "machine/isr.h"
+#include "../hp300/isr.h"
 
 #ifndef DEFAULT_BAUD_RATE
 #define DEFAULT_BAUD_RATE 9600
 #endif
 
 int    ttrstrt();
 
 #ifndef DEFAULT_BAUD_RATE
 #define DEFAULT_BAUD_RATE 9600
 #endif
 
 int    ttrstrt();
-int    dcmprobe(), dcmstart(), dcmintr(), dcmparam();
-
+int    dcmprobe(), dcmintr(), dcmparam();
+void   dcmstart();
 struct driver dcmdriver = {
        dcmprobe, "dcm",
 };
 struct driver dcmdriver = {
        dcmprobe, "dcm",
 };
@@ -56,6 +56,7 @@ struct        driver dcmdriver = {
 #define NDCMLINE (NDCM*4)
 
 struct tty dcm_tty[NDCMLINE];
 #define NDCMLINE (NDCM*4)
 
 struct tty dcm_tty[NDCMLINE];
+struct modemreg *dcm_modem[NDCMLINE];
 char   mcndlast[NDCMLINE];     /* XXX last modem status for line */
 int    ndcm = NDCMLINE;
 
 char   mcndlast[NDCMLINE];     /* XXX last modem status for line */
 int    ndcm = NDCMLINE;
 
@@ -88,7 +89,7 @@ struct speedtab dcmspeedtab[] = {
 
 /*
  * Per board interrupt scheme.  16.7ms is the polling interrupt rate
 
 /*
  * Per board interrupt scheme.  16.7ms is the polling interrupt rate
- * (16.7ms is about 550 buad, 38.4k is 72 chars in 16.7ms).
+ * (16.7ms is about 550 baud, 38.4k is 72 chars in 16.7ms).
  */
 #define DIS_TIMER      0
 #define DIS_PERCHAR    1
  */
 #define DIS_TIMER      0
 #define DIS_PERCHAR    1
@@ -106,16 +107,24 @@ struct    dcmischeme {
 /*
  * Console support
  */
 /*
  * Console support
  */
+#ifdef DCMCONSOLE
+int    dcmconsole = DCMCONSOLE;
+#else
 int    dcmconsole = -1;
 int    dcmconsole = -1;
+#endif
+int    dcmconsinit;
 int    dcmdefaultrate = DEFAULT_BAUD_RATE;
 int    dcmconbrdbusy = 0;
 int    dcmdefaultrate = DEFAULT_BAUD_RATE;
 int    dcmconbrdbusy = 0;
+int    dcmmajor;
 extern struct tty *constty;
 
 #ifdef KGDB
 /*
  * Kernel GDB support
  */
 extern struct tty *constty;
 
 #ifdef KGDB
 /*
  * Kernel GDB support
  */
-extern int kgdb_dev;
+#include "machine/remote-sl.h"
+
+extern dev_t kgdb_dev;
 extern int kgdb_rate;
 extern int kgdb_debug_init;
 #endif
 extern int kgdb_rate;
 extern int kgdb_debug_init;
 #endif
@@ -123,7 +132,7 @@ extern int kgdb_debug_init;
 /* #define IOSTATS */
 
 #ifdef DEBUG
 /* #define IOSTATS */
 
 #ifdef DEBUG
-int    dcmdebug = 0x00;
+int    dcmdebug = 0x0;
 #define DDB_SIOERR     0x01
 #define DDB_PARAM      0x02
 #define DDB_INPUT      0x04
 #define DDB_SIOERR     0x01
 #define DDB_PARAM      0x02
 #define DDB_INPUT      0x04
@@ -156,13 +165,48 @@ struct    dcmstats {
 #define PORT(x)                ((x) & 3)
 #define MKUNIT(b,p)    (((b) << 2) | (p))
 
 #define PORT(x)                ((x) & 3)
 #define MKUNIT(b,p)    (((b) << 2) | (p))
 
+/*
+ * Conversion from "HP DCE" to almost-normal DCE: on the 638 8-port mux,
+ * the distribution panel uses "HP DCE" conventions.  If requested via
+ * the device flags, we swap the inputs to something closer to normal DCE,
+ * allowing a straight-through cable to a DTE or a reversed cable
+ * to a DCE (reversing 2-3, 4-5, 8-20 and leaving 6 unconnected;
+ * this gets "DCD" on pin 20 and "CTS" on 4, but doesn't connect
+ * DSR or make RTS work, though).  The following gives the full
+ * details of a cable from this mux panel to a modem:
+ *
+ *                  HP             modem
+ *             name    pin     pin     name
+ * HP inputs:
+ *             "Rx"     2       3      Tx
+ *             CTS      4       5      CTS     (only needed for CCTS_OFLOW)
+ *             DCD     20       8      DCD
+ *             "DSR"    9       6      DSR     (unneeded)
+ *             RI      22      22      RI      (unneeded)
+ *
+ * HP outputs:
+ *             "Tx"     3       2      Rx
+ *             "DTR"    6      not connected
+ *             "RTS"    8      20      DTR
+ *             "SR"    23       4      RTS     (often not needed)
+ */
+#define        FLAG_STDDCE     0x10    /* map inputs if this bit is set in flags */
+#define hp2dce_in(ibits)       (iconv[(ibits) & 0xf])
+static char iconv[16] = {
+       0,              MI_DM,          MI_CTS,         MI_CTS|MI_DM,
+       MI_CD,          MI_CD|MI_DM,    MI_CD|MI_CTS,   MI_CD|MI_CTS|MI_DM,
+       MI_RI,          MI_RI|MI_DM,    MI_RI|MI_CTS,   MI_RI|MI_CTS|MI_DM,
+       MI_RI|MI_CD,    MI_RI|MI_CD|MI_DM, MI_RI|MI_CD|MI_CTS,
+       MI_RI|MI_CD|MI_CTS|MI_DM
+};
+
 dcmprobe(hd)
        register struct hp_device *hd;
 {
        register struct dcmdevice *dcm;
        register int i;
        register int timo = 0;
 dcmprobe(hd)
        register struct hp_device *hd;
 {
        register struct dcmdevice *dcm;
        register int i;
        register int timo = 0;
-       int s, brd, isconsole;
+       int s, brd, isconsole, mbits;
 
        dcm = (struct dcmdevice *)hd->hp_addr;
        if ((dcm->dcm_rsid & 0x1f) != DCMID)
 
        dcm = (struct dcmdevice *)hd->hp_addr;
        if ((dcm->dcm_rsid & 0x1f) != DCMID)
@@ -176,7 +220,7 @@ dcmprobe(hd)
         * CONSUNIT).  Don't recognize this card.
         */
        if (isconsole && dcm != dcm_addr[BOARD(dcmconsole)])
         * CONSUNIT).  Don't recognize this card.
         */
        if (isconsole && dcm != dcm_addr[BOARD(dcmconsole)])
-               return(0);
+               return (0);
 
        /*
         * Empirically derived self-test magic
 
        /*
         * Empirically derived self-test magic
@@ -189,17 +233,17 @@ dcmprobe(hd)
        dcm->dcm_cr = CR_SELFT;
        while ((dcm->dcm_ic & IC_IR) == 0)
                if (++timo == 20000)
        dcm->dcm_cr = CR_SELFT;
        while ((dcm->dcm_ic & IC_IR) == 0)
                if (++timo == 20000)
-                       return(0);
+                       return (0);
        DELAY(50000)    /* XXX why is this needed ???? */
        while ((dcm->dcm_iir & IIR_SELFT) == 0)
                if (++timo == 400000)
        DELAY(50000)    /* XXX why is this needed ???? */
        while ((dcm->dcm_iir & IIR_SELFT) == 0)
                if (++timo == 400000)
-                       return(0);
+                       return (0);
        DELAY(50000)    /* XXX why is this needed ???? */
        if (dcm->dcm_stcon != ST_OK) {
                if (!isconsole)
                        printf("dcm%d: self test failed: %x\n",
                               brd, dcm->dcm_stcon);
        DELAY(50000)    /* XXX why is this needed ???? */
        if (dcm->dcm_stcon != ST_OK) {
                if (!isconsole)
                        printf("dcm%d: self test failed: %x\n",
                               brd, dcm->dcm_stcon);
-               return(0);
+               return (0);
        }
        dcm->dcm_ic = IC_ID;
        splx(s);
        }
        dcm->dcm_ic = IC_ID;
        splx(s);
@@ -213,55 +257,74 @@ dcmprobe(hd)
        dcmisr[brd].isr_intr = dcmintr;
        isrlink(&dcmisr[brd]);
 #ifdef KGDB
        dcmisr[brd].isr_intr = dcmintr;
        isrlink(&dcmisr[brd]);
 #ifdef KGDB
-       if (major(kgdb_dev) == 2 && BOARD(kgdb_dev) == brd) {
+       if (major(kgdb_dev) == dcmmajor && BOARD(kgdb_dev) == brd) {
                if (dcmconsole == UNIT(kgdb_dev))
                if (dcmconsole == UNIT(kgdb_dev))
-                       kgdb_dev = -1;  /* can't debug over console port */
+                       kgdb_dev = NODEV; /* can't debug over console port */
+#ifndef KGDB_CHEAT
+               /*
+                * The following could potentially be replaced
+                * by the corresponding code in dcmcnprobe.
+                */
                else {
                        (void) dcminit(kgdb_dev, kgdb_rate);
                        if (kgdb_debug_init) {
                else {
                        (void) dcminit(kgdb_dev, kgdb_rate);
                        if (kgdb_debug_init) {
-                               printf("dcm%d: kgdb waiting...",
-                                      UNIT(kgdb_dev));
-                               /* trap into kgdb */
-                               asm("trap #15;");
-                               printf("connected.\n");
+                               printf("dcm%d: ", UNIT(kgdb_dev));
+                               kgdb_connect(1);
                        } else
                        } else
-                               printf("dcm%d: kgdb enabled\n",
-                                      UNIT(kgdb_dev));
+                               printf("dcm%d: kgdb enabled\n", UNIT(kgdb_dev));
                }
                }
+               /* end could be replaced */
+#endif
        }
 #endif
        if (dcmistype == DIS_TIMER)
                dcmsetischeme(brd, DIS_RESET|DIS_TIMER);
        else
                dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR);
        }
 #endif
        if (dcmistype == DIS_TIMER)
                dcmsetischeme(brd, DIS_RESET|DIS_TIMER);
        else
                dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR);
-       dcm->dcm_mdmmsk = MI_CD|MI_CTS; /* DCD (modem) and CTS (flow ctrl) */
+
+       /* load pointers to modem control */
+       dcm_modem[MKUNIT(brd, 0)] = &dcm->dcm_modem0;
+       dcm_modem[MKUNIT(brd, 1)] = &dcm->dcm_modem1;
+       dcm_modem[MKUNIT(brd, 2)] = &dcm->dcm_modem2;
+       dcm_modem[MKUNIT(brd, 3)] = &dcm->dcm_modem3;
+       /* set DCD (modem) and CTS (flow control) on all ports */
+       if (dcmsoftCAR[brd] & FLAG_STDDCE)
+               mbits = hp2dce_in(MI_CD|MI_CTS);
+       else
+               mbits = MI_CD|MI_CTS;
+       for (i = 0; i < 4; i++)
+               dcm_modem[MKUNIT(brd, i)]->mdmmsk = mbits;
+
        dcm->dcm_ic = IC_IE;            /* turn all interrupts on */
        /*
         * Need to reset baud rate, etc. of next print so reset dcmconsole.
         * Also make sure console is always "hardwired"
         */
        if (isconsole) {
        dcm->dcm_ic = IC_IE;            /* turn all interrupts on */
        /*
         * Need to reset baud rate, etc. of next print so reset dcmconsole.
         * Also make sure console is always "hardwired"
         */
        if (isconsole) {
-               dcmconsole = -1;
+               dcmconsinit = 0;
                dcmsoftCAR[brd] |= (1 << PORT(dcmconsole));
        }
        return (1);
 }
 
                dcmsoftCAR[brd] |= (1 << PORT(dcmconsole));
        }
        return (1);
 }
 
-dcmopen(dev, flag)
+/* ARGSUSED */
+#ifdef __STDC__
+dcmopen(dev_t dev, int flag, int mode, struct proc *p)
+#else
+dcmopen(dev, flag, mode, p)
        dev_t dev;
        dev_t dev;
+       int flag, mode;
+       struct proc *p;
+#endif
 {
        register struct tty *tp;
        register int unit, brd;
 {
        register struct tty *tp;
        register int unit, brd;
-       int error;
+       int error = 0, mbits;
 
        unit = UNIT(dev);
        brd = BOARD(unit);
        if (unit >= NDCMLINE || (dcm_active & (1 << brd)) == 0)
                return (ENXIO);
 
        unit = UNIT(dev);
        brd = BOARD(unit);
        if (unit >= NDCMLINE || (dcm_active & (1 << brd)) == 0)
                return (ENXIO);
-#ifdef KGDB
-       if (unit == UNIT(kgdb_dev))
-               return (EBUSY);
-#endif
        tp = &dcm_tty[unit];
        tp->t_oproc = dcmstart;
        tp->t_param = dcmparam;
        tp = &dcm_tty[unit];
        tp->t_oproc = dcmstart;
        tp->t_param = dcmparam;
@@ -269,32 +332,39 @@ dcmopen(dev, flag)
        if ((tp->t_state & TS_ISOPEN) == 0) {
                tp->t_state |= TS_WOPEN;
                ttychars(tp);
        if ((tp->t_state & TS_ISOPEN) == 0) {
                tp->t_state |= TS_WOPEN;
                ttychars(tp);
-               tp->t_iflag = TTYDEF_IFLAG;
-               tp->t_oflag = TTYDEF_OFLAG;
-               tp->t_cflag = TTYDEF_CFLAG;
-               tp->t_lflag = TTYDEF_LFLAG;
-               tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+               if (tp->t_ispeed == 0) {
+                       tp->t_iflag = TTYDEF_IFLAG;
+                       tp->t_oflag = TTYDEF_OFLAG;
+                       tp->t_cflag = TTYDEF_CFLAG;
+                       tp->t_lflag = TTYDEF_LFLAG;
+                       tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+               }
                (void) dcmparam(tp, &tp->t_termios);
                ttsetwater(tp);
                (void) dcmparam(tp, &tp->t_termios);
                ttsetwater(tp);
-       } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
+       } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
                return (EBUSY);
                return (EBUSY);
-       if (PORT(unit) == 0)    /* enable port 0 */
-               (void) dcmmctl(dev, MO_ON, DMSET);
-       if (dcmsoftCAR[brd] & (1 << PORT(unit)))
-               tp->t_state |= TS_CARR_ON;
-       else if (PORT(unit))            /* Only port 0 has modem control */
-               tp->t_state |= TS_CARR_ON;
-       else if (dcmmctl(dev, MO_OFF, DMGET) & MI_CD)
+       mbits = MO_ON;
+       if (dcmsoftCAR[brd] & FLAG_STDDCE)
+               mbits |= MO_SR;         /* pin 23, could be used as RTS */
+       (void) dcmmctl(dev, mbits, DMSET);      /* enable port */
+       if ((dcmsoftCAR[brd] & (1 << PORT(unit))) ||
+           (dcmmctl(dev, MO_OFF, DMGET) & MI_CD))
                tp->t_state |= TS_CARR_ON;
                tp->t_state |= TS_CARR_ON;
+#ifdef DEBUG
+       if (dcmdebug & DDB_MODEM)
+               printf("dcm%d: dcmopen port %d softcarr %c\n",
+                      brd, unit, (tp->t_state & TS_CARR_ON) ? '1' : '0');
+#endif
        (void) spltty();
        while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
        (void) spltty();
        while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
-              (tp->t_state & TS_CARR_ON) == 0) {
+           (tp->t_state & TS_CARR_ON) == 0) {
                tp->t_state |= TS_WOPEN;
                if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
                    ttopen, 0))
                        break;
        }
        (void) spl0();
                tp->t_state |= TS_WOPEN;
                if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
                    ttopen, 0))
                        break;
        }
        (void) spl0();
+
 #ifdef DEBUG
        if (dcmdebug & DDB_OPENCLOSE)
                printf("dcmopen: u %x st %x fl %x\n",
 #ifdef DEBUG
        if (dcmdebug & DDB_OPENCLOSE)
                printf("dcmopen: u %x st %x fl %x\n",
@@ -306,16 +376,18 @@ dcmopen(dev, flag)
 }
  
 /*ARGSUSED*/
 }
  
 /*ARGSUSED*/
-dcmclose(dev, flag)
+dcmclose(dev, flag, mode, p)
        dev_t dev;
        dev_t dev;
+       int flag, mode;
+       struct proc *p;
 {
        register struct tty *tp;
        int unit;
  
        unit = UNIT(dev);
        tp = &dcm_tty[unit];
 {
        register struct tty *tp;
        int unit;
  
        unit = UNIT(dev);
        tp = &dcm_tty[unit];
-       (*linesw[tp->t_line].l_close)(tp);
-       if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 
+       (*linesw[tp->t_line].l_close)(tp, flag);
+       if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
            (tp->t_state&TS_ISOPEN) == 0)
                (void) dcmmctl(dev, MO_OFF, DMSET);
 #ifdef DEBUG
            (tp->t_state&TS_ISOPEN) == 0)
                (void) dcmmctl(dev, MO_OFF, DMSET);
 #ifdef DEBUG
@@ -324,7 +396,7 @@ dcmclose(dev, flag)
                        unit, tp->t_state, tp->t_flags);
 #endif
        ttyclose(tp);
                        unit, tp->t_state, tp->t_flags);
 #endif
        ttyclose(tp);
-       return(0);
+       return (0);
 }
  
 dcmread(dev, uio, flag)
 }
  
 dcmread(dev, uio, flag)
@@ -361,7 +433,9 @@ dcmintr(brd)
 {
        register struct dcmdevice *dcm = dcm_addr[brd];
        register struct dcmischeme *dis;
 {
        register struct dcmdevice *dcm = dcm_addr[brd];
        register struct dcmischeme *dis;
-       int i, code, pcnd[4], mcnd, delta;
+       register int unit = MKUNIT(brd, 0);
+       register int code, i;
+       int pcnd[4], mcode, mcnd[4];
 
        /*
         * Do all guarded register accesses right off to minimize
 
        /*
         * Do all guarded register accesses right off to minimize
@@ -370,34 +444,50 @@ dcmintr(brd)
        SEM_LOCK(dcm);
        if ((dcm->dcm_ic & IC_IR) == 0) {
                SEM_UNLOCK(dcm);
        SEM_LOCK(dcm);
        if ((dcm->dcm_ic & IC_IR) == 0) {
                SEM_UNLOCK(dcm);
-               return(0);
+               return (0);
        }
        for (i = 0; i < 4; i++) {
                pcnd[i] = dcm->dcm_icrtab[i].dcm_data;
                dcm->dcm_icrtab[i].dcm_data = 0;
        }
        for (i = 0; i < 4; i++) {
                pcnd[i] = dcm->dcm_icrtab[i].dcm_data;
                dcm->dcm_icrtab[i].dcm_data = 0;
+               code = dcm_modem[unit+i]->mdmin;
+               if (dcmsoftCAR[brd] & FLAG_STDDCE)
+                       code = hp2dce_in(code);
+               mcnd[i] = code;
        }
        }
-       mcnd = dcm->dcm_mdmin;
        code = dcm->dcm_iir & IIR_MASK;
        dcm->dcm_iir = 0;       /* XXX doc claims read clears interrupt?! */
        code = dcm->dcm_iir & IIR_MASK;
        dcm->dcm_iir = 0;       /* XXX doc claims read clears interrupt?! */
+       mcode = dcm->dcm_modemintr;
+       dcm->dcm_modemintr = 0;
        SEM_UNLOCK(dcm);
 
 #ifdef DEBUG
        SEM_UNLOCK(dcm);
 
 #ifdef DEBUG
-       if (dcmdebug & DDB_INTR)
-               printf("dcmintr(%d): iir %x p0 %x p1 %x p2 %x p3 %x m %x\n", 
-                      brd, code, pcnd[0], pcnd[1], pcnd[2], pcnd[3], mcnd);
+       if (dcmdebug & DDB_INTR) {
+               printf("dcmintr(%d): iir %x pc %x/%x/%x/%x ",
+                      brd, code, pcnd[0], pcnd[1], pcnd[2], pcnd[3]); 
+               printf("miir %x mc %x/%x/%x/%x\n",
+                      mcode, mcnd[0], mcnd[1], mcnd[2], mcnd[3]);
+       }
 #endif
        if (code & IIR_TIMEO)
                dcmrint(brd, dcm);
        if (code & IIR_PORT0)
 #endif
        if (code & IIR_TIMEO)
                dcmrint(brd, dcm);
        if (code & IIR_PORT0)
-               dcmpint(MKUNIT(brd, 0), pcnd[0], dcm);
+               dcmpint(unit+0, pcnd[0], dcm);
        if (code & IIR_PORT1)
        if (code & IIR_PORT1)
-               dcmpint(MKUNIT(brd, 1), pcnd[1],  dcm);
+               dcmpint(unit+1, pcnd[1], dcm);
        if (code & IIR_PORT2)
        if (code & IIR_PORT2)
-               dcmpint(MKUNIT(brd, 2), pcnd[2], dcm);
+               dcmpint(unit+2, pcnd[2], dcm);
        if (code & IIR_PORT3)
        if (code & IIR_PORT3)
-               dcmpint(MKUNIT(brd, 3), pcnd[3], dcm);
-       if (code & IIR_MODM)
-               dcmmint(MKUNIT(brd, 0), mcnd, dcm);     /* XXX always port 0 */
+               dcmpint(unit+3, pcnd[3], dcm);
+       if (code & IIR_MODM) {
+               if (mcode == 0 || mcode & 0x1)  /* mcode==0 -> 98642 board */
+                       dcmmint(unit+0, mcnd[0], dcm);
+               if (mcode & 0x2)
+                       dcmmint(unit+1, mcnd[1], dcm);
+               if (mcode & 0x4)
+                       dcmmint(unit+2, mcnd[2], dcm);
+               if (mcode & 0x8)
+                       dcmmint(unit+3, mcnd[3], dcm);
+       }
 
        dis = &dcmischeme[brd];
        /*
 
        dis = &dcmischeme[brd];
        /*
@@ -411,7 +501,7 @@ dcmintr(brd)
         * See if it is time to check/change the interrupt rate.
         */
        if (dcmistype < 0 &&
         * See if it is time to check/change the interrupt rate.
         */
        if (dcmistype < 0 &&
-           (delta = time.tv_sec - dis->dis_time) >= dcminterval) {
+           (i = time.tv_sec - dis->dis_time) >= dcminterval) {
                /*
                 * If currently per-character and averaged over 70 interrupts
                 * per-second (66 is threshold of 600 baud) in last interval,
                /*
                 * If currently per-character and averaged over 70 interrupts
                 * per-second (66 is threshold of 600 baud) in last interval,
@@ -419,7 +509,7 @@ dcmintr(brd)
                 *
                 * XXX decay counts ala load average to avoid spikes?
                 */
                 *
                 * XXX decay counts ala load average to avoid spikes?
                 */
-               if (dis->dis_perchar && dis->dis_intr > 70 * delta)
+               if (dis->dis_perchar && dis->dis_intr > 70 * i)
                        dcmsetischeme(brd, DIS_TIMER);
                /*
                 * If currently using timer and had more interrupts than
                        dcmsetischeme(brd, DIS_TIMER);
                /*
                 * If currently using timer and had more interrupts than
@@ -437,7 +527,7 @@ dcmintr(brd)
                dis->dis_intr = dis->dis_char = 0;
                dis->dis_time = time.tv_sec;
        }
                dis->dis_intr = dis->dis_char = 0;
                dis->dis_time = time.tv_sec;
        }
-       return(1);
+       return (1);
 }
 
 /*
 }
 
 /*
@@ -488,16 +578,14 @@ dcmreadbuf(unit, dcm, tp)
 #endif
        if ((tp->t_state & TS_ISOPEN) == 0) {
 #ifdef KGDB
 #endif
        if ((tp->t_state & TS_ISOPEN) == 0) {
 #ifdef KGDB
-               if (unit == UNIT(kgdb_dev) &&
+               if ((makedev(dcmmajor, unit) == kgdb_dev) &&
                    (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) &&
                    (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) &&
-                   dcm->dcm_rfifos[3-port][head>>1].data_char == '!') {
+                   dcm->dcm_rfifos[3-port][head>>1].data_char == FRAME_END) {
                        pp->r_head = (head + 2) & RX_MASK;
                        pp->r_head = (head + 2) & RX_MASK;
-                       printf("kgdb trap from dcm%d\n", unit);
-                       /* trap into kgdb */
-                       asm("trap #15;");
+                       kgdb_connect(0);        /* trap into kgdb */
                        return;
                }
                        return;
                }
-#endif
+#endif /* KGDB */
                pp->r_head = pp->r_tail & RX_MASK;
                return;
        }
                pp->r_head = pp->r_tail & RX_MASK;
                return;
        }
@@ -565,10 +653,7 @@ dcmxint(unit, dcm, tp)
        tp->t_state &= ~TS_BUSY;
        if (tp->t_state & TS_FLUSH)
                tp->t_state &= ~TS_FLUSH;
        tp->t_state &= ~TS_BUSY;
        if (tp->t_state & TS_FLUSH)
                tp->t_state &= ~TS_FLUSH;
-       if (tp->t_line)
-               (*linesw[tp->t_line].l_start)(tp);
-       else
-               dcmstart(tp);
+       (*linesw[tp->t_line].l_start)(tp);
 }
 
 dcmmint(unit, mcnd, dcm)
 }
 
 dcmmint(unit, mcnd, dcm)
@@ -581,36 +666,41 @@ dcmmint(unit, mcnd, dcm)
 
 #ifdef DEBUG
        if (dcmdebug & DDB_MODEM)
 
 #ifdef DEBUG
        if (dcmdebug & DDB_MODEM)
-               printf("dcmmint: unit %x mcnd %x mcndlast\n",
+               printf("dcmmint: port %d mcnd %x mcndlast %x\n",
                       unit, mcnd, mcndlast[unit]);
 #endif
        tp = &dcm_tty[unit];
        delta = mcnd ^ mcndlast[unit];
        mcndlast[unit] = mcnd;
                       unit, mcnd, mcndlast[unit]);
 #endif
        tp = &dcm_tty[unit];
        delta = mcnd ^ mcndlast[unit];
        mcndlast[unit] = mcnd;
-       if ((delta & MI_CD) &&
-           (dcmsoftCAR[BOARD(unit)] & (1 << PORT(unit))) == 0) {
+       if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) &&
+           (tp->t_flags & CCTS_OFLOW)) {
+               if (mcnd & MI_CTS) {
+                       tp->t_state &= ~TS_TTSTOP;
+                       ttstart(tp);
+               } else
+                       tp->t_state |= TS_TTSTOP;       /* inline dcmstop */
+       }
+       if (delta & MI_CD) {
                if (mcnd & MI_CD)
                        (void)(*linesw[tp->t_line].l_modem)(tp, 1);
                if (mcnd & MI_CD)
                        (void)(*linesw[tp->t_line].l_modem)(tp, 1);
-               else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
-                       dcm->dcm_mdmout &= ~(MO_DTR|MO_RTS);
+               else if ((dcmsoftCAR[BOARD(unit)] & (1 << PORT(unit))) == 0 &&
+                   (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
+                       dcm_modem[unit]->mdmout = MO_OFF;
                        SEM_LOCK(dcm);
                        SEM_LOCK(dcm);
+                       dcm->dcm_modemchng |= 1<<(unit & 3);
                        dcm->dcm_cr |= CR_MODM;
                        SEM_UNLOCK(dcm);
                        DELAY(10); /* time to change lines */
                }
                        dcm->dcm_cr |= CR_MODM;
                        SEM_UNLOCK(dcm);
                        DELAY(10); /* time to change lines */
                }
-       } else if ((delta & MI_CTS) &&
-                  (tp->t_state & TS_ISOPEN) && (tp->t_flags & CRTSCTS)) {
-               if (mcnd & MI_CTS) {
-                       tp->t_state &= ~TS_TTSTOP;
-                       ttstart(tp);
-               } else
-                       tp->t_state |= TS_TTSTOP;       /* inline dcmstop */
        }
 }
 
        }
 }
 
-dcmioctl(dev, cmd, data, flag)
+dcmioctl(dev, cmd, data, flag, p)
        dev_t dev;
        dev_t dev;
+       int cmd;
        caddr_t data;
        caddr_t data;
+       int flag;
+       struct proc *p;
 {
        register struct tty *tp;
        register int unit = UNIT(dev);
 {
        register struct tty *tp;
        register int unit = UNIT(dev);
@@ -624,7 +714,7 @@ dcmioctl(dev, cmd, data, flag)
                       unit, cmd, *data, flag);
 #endif
        tp = &dcm_tty[unit];
                       unit, cmd, *data, flag);
 #endif
        tp = &dcm_tty[unit];
-       error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
+       error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
        if (error >= 0)
                return (error);
        error = ttioctl(tp, cmd, data, flag);
        if (error >= 0)
                return (error);
        error = ttioctl(tp, cmd, data, flag);
@@ -695,14 +785,14 @@ dcmparam(tp, t)
 
        /* check requested parameters */
         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
 
        /* check requested parameters */
         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
-                return(EINVAL);
+                return (EINVAL);
         /* and copy to tty */
         tp->t_ispeed = t->c_ispeed;
         tp->t_ospeed = t->c_ospeed;
         tp->t_cflag = cflag;
        if (ospeed == 0) {
                (void) dcmmctl(UNIT(tp->t_dev), MO_OFF, DMSET);
         /* and copy to tty */
         tp->t_ispeed = t->c_ispeed;
         tp->t_ospeed = t->c_ospeed;
         tp->t_cflag = cflag;
        if (ospeed == 0) {
                (void) dcmmctl(UNIT(tp->t_dev), MO_OFF, DMSET);
-               return(0);
+               return (0);
        }
 
        mode = 0;
        }
 
        mode = 0;
@@ -750,13 +840,14 @@ dcmparam(tp, t)
        dcm->dcm_cr |= (1 << port);
        SEM_UNLOCK(dcm);
        /*
        dcm->dcm_cr |= (1 << port);
        SEM_UNLOCK(dcm);
        /*
-        * Delay for config change to take place. Weighted by buad.
+        * Delay for config change to take place. Weighted by baud.
         * XXX why do we do this?
         */
        DELAY(16 * DCM_USPERCH(tp->t_ospeed));
         * XXX why do we do this?
         */
        DELAY(16 * DCM_USPERCH(tp->t_ospeed));
-       return(0);
+       return (0);
 }
  
 }
  
+void
 dcmstart(tp)
        register struct tty *tp;
 {
 dcmstart(tp)
        register struct tty *tp;
 {
@@ -854,6 +945,7 @@ again:
                head = pp->t_head & TX_MASK;
                goto again;
        }
                head = pp->t_head & TX_MASK;
                goto again;
        }
+
        /*
         * Kick it one last time in case it finished while we were
         * loading the last bunch.
        /*
         * Kick it one last time in case it finished while we were
         * loading the last bunch.
@@ -898,53 +990,58 @@ dcmstop(tp, flag)
        splx(s);
 }
  
        splx(s);
 }
  
-/* Modem control */
-
+/*
+ * Modem control
+ */
 dcmmctl(dev, bits, how)
        dev_t dev;
        int bits, how;
 {
        register struct dcmdevice *dcm;
 dcmmctl(dev, bits, how)
        dev_t dev;
        int bits, how;
 {
        register struct dcmdevice *dcm;
-       int s, hit = 0;
+       int s, unit, brd, hit = 0;
 
 
-       /*
-        * Only port 0 has modem control lines.
-        * XXX ok for now but needs to changed for the 8 port board.
-        */
-       if (PORT(UNIT(dev)) != 0)
-               return(bits);
+       unit = UNIT(dev);
+#ifdef DEBUG
+       if (dcmdebug & DDB_MODEM)
+               printf("dcmmctl(%d) unit %d  bits 0x%x how %x\n",
+                      BOARD(unit), unit, bits, how);
+#endif
 
 
-       dcm = dcm_addr[BOARD(UNIT(dev))];
+       brd = BOARD(unit);
+       dcm = dcm_addr[brd];
        s = spltty();
        switch (how) {
 
        case DMSET:
        s = spltty();
        switch (how) {
 
        case DMSET:
-               dcm->dcm_mdmout = bits;
+               dcm_modem[unit]->mdmout = bits;
                hit++;
                break;
 
        case DMBIS:
                hit++;
                break;
 
        case DMBIS:
-               dcm->dcm_mdmout |= bits;
+               dcm_modem[unit]->mdmout |= bits;
                hit++;
                break;
 
        case DMBIC:
                hit++;
                break;
 
        case DMBIC:
-               dcm->dcm_mdmout &= ~bits;
+               dcm_modem[unit]->mdmout &= ~bits;
                hit++;
                break;
 
        case DMGET:
                hit++;
                break;
 
        case DMGET:
-               bits = dcm->dcm_mdmin;
+               bits = dcm_modem[unit]->mdmin;
+               if (dcmsoftCAR[brd] & FLAG_STDDCE)
+                       bits = hp2dce_in(bits);
                break;
        }
        if (hit) {
                SEM_LOCK(dcm);
                break;
        }
        if (hit) {
                SEM_LOCK(dcm);
+               dcm->dcm_modemchng |= 1<<(unit & 3);
                dcm->dcm_cr |= CR_MODM;
                SEM_UNLOCK(dcm);
                DELAY(10); /* delay until done */
                (void) splx(s);
        }
                dcm->dcm_cr |= CR_MODM;
                SEM_UNLOCK(dcm);
                DELAY(10); /* delay until done */
                (void) splx(s);
        }
-       return(bits);
+       return (bits);
 }
 
 /*
 }
 
 /*
@@ -1014,14 +1111,18 @@ dcmsetischeme(brd, flags)
 /*
  * Following are all routines needed for DCM to act as console
  */
 /*
  * Following are all routines needed for DCM to act as console
  */
-#include "machine/cons.h"
+#include "../hp300/cons.h"
 
 dcmcnprobe(cp)
        struct consdev *cp;
 {
        register struct hp_hw *hw;
 
 dcmcnprobe(cp)
        struct consdev *cp;
 {
        register struct hp_hw *hw;
-       int unit, i;
-       extern int dcmopen();
+       int unit;
+
+       /* locate the major number */
+       for (dcmmajor = 0; dcmmajor < nchrdev; dcmmajor++)
+               if (cdevsw[dcmmajor].d_open == dcmopen)
+                       break;
 
        /*
         * Implicitly assigns the lowest select code DCM card found to be
 
        /*
         * Implicitly assigns the lowest select code DCM card found to be
@@ -1029,22 +1130,17 @@ dcmcnprobe(cp)
         * anything different, you're screwed.
         */
        for (hw = sc_table; hw->hw_type; hw++)
         * anything different, you're screwed.
         */
        for (hw = sc_table; hw->hw_type; hw++)
-               if (hw->hw_type == COMMDCM && !badaddr((short *)hw->hw_addr))
+               if (HW_ISDEV(hw, D_COMMDCM) && !badaddr((short *)hw->hw_kva))
                        break;
                        break;
-       if (hw->hw_type != COMMDCM) {
+       if (!HW_ISDEV(hw, D_COMMDCM)) {
                cp->cn_pri = CN_DEAD;
                return;
        }
        unit = CONUNIT;
                cp->cn_pri = CN_DEAD;
                return;
        }
        unit = CONUNIT;
-       dcm_addr[BOARD(CONUNIT)] = (struct dcmdevice *)hw->hw_addr;
-
-       /* locate the major number */
-       for (i = 0; i < nchrdev; i++)
-               if (cdevsw[i].d_open == dcmopen)
-                       break;
+       dcm_addr[BOARD(CONUNIT)] = (struct dcmdevice *)hw->hw_kva;
 
        /* initialize required fields */
 
        /* initialize required fields */
-       cp->cn_dev = makedev(i, unit);
+       cp->cn_dev = makedev(dcmmajor, unit);
        cp->cn_tp = &dcm_tty[unit];
        switch (dcm_addr[BOARD(unit)]->dcm_rsid) {
        case DCMID:
        cp->cn_tp = &dcm_tty[unit];
        switch (dcm_addr[BOARD(unit)]->dcm_rsid) {
        case DCMID:
@@ -1055,14 +1151,39 @@ dcmcnprobe(cp)
                break;
        default:
                cp->cn_pri = CN_DEAD;
                break;
        default:
                cp->cn_pri = CN_DEAD;
-               break;
+               return;
        }
        }
+       /*
+        * If dcmconsole is initialized, raise our priority.
+        */
+       if (dcmconsole == UNIT(unit))
+               cp->cn_pri = CN_REMOTE;
+#ifdef KGDB_CHEAT
+       /*
+        * This doesn't currently work, at least not with ite consoles;
+        * the console hasn't been initialized yet.
+        */
+       if (major(kgdb_dev) == dcmmajor && BOARD(kgdb_dev) == BOARD(unit)) {
+               (void) dcminit(kgdb_dev, kgdb_rate);
+               if (kgdb_debug_init) {
+                       /*
+                        * We assume that console is ready for us...
+                        * this assumes that a dca or ite console
+                        * has been selected already and will init
+                        * on the first putc.
+                        */
+                       printf("dcm%d: ", UNIT(kgdb_dev));
+                       kgdb_connect(1);
+               }
+       }
+#endif
 }
 
 dcmcninit(cp)
        struct consdev *cp;
 {
        dcminit(cp->cn_dev, dcmdefaultrate);
 }
 
 dcmcninit(cp)
        struct consdev *cp;
 {
        dcminit(cp->cn_dev, dcmdefaultrate);
+       dcmconsinit = 1;
        dcmconsole = UNIT(cp->cn_dev);
 }
 
        dcmconsole = UNIT(cp->cn_dev);
 }
 
@@ -1091,7 +1212,7 @@ dcminit(dev, rate)
        dcm->dcm_cr |= (1 << port);
        SEM_UNLOCK(dcm);
        /*
        dcm->dcm_cr |= (1 << port);
        SEM_UNLOCK(dcm);
        /*
-        * Delay for config change to take place. Weighted by buad.
+        * Delay for config change to take place. Weighted by baud.
         * XXX why do we do this?
         */
        DELAY(16 * DCM_USPERCH(rate));
         * XXX why do we do this?
         */
        DELAY(16 * DCM_USPERCH(rate));
@@ -1127,7 +1248,7 @@ dcmcngetc(dev)
        stat = fifo->data_stat;
        pp->r_head = (head + 2) & RX_MASK;
        splx(s);
        stat = fifo->data_stat;
        pp->r_head = (head + 2) & RX_MASK;
        splx(s);
-       return(c);
+       return (c);
 }
 
 /*
 }
 
 /*
@@ -1148,9 +1269,9 @@ dcmcnputc(dev, c)
 #ifdef KGDB
        if (dev != kgdb_dev)
 #endif
 #ifdef KGDB
        if (dev != kgdb_dev)
 #endif
-       if (dcmconsole == -1) {
+       if (dcmconsinit == 0) {
                (void) dcminit(dev, dcmdefaultrate);
                (void) dcminit(dev, dcmdefaultrate);
-               dcmconsole = UNIT(dev);
+               dcmconsinit = 1;
        }
        tail = pp->t_tail & TX_MASK;
        while (tail != (pp->t_head & TX_MASK))
        }
        tail = pp->t_tail & TX_MASK;
        while (tail != (pp->t_head & TX_MASK))