From Ache
[unix-history] / sys / i386 / isa / sio.c
index 84ff5f0..a54b7bb 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.49 1994/05/30 22:53:41 ache Exp $
+ *     $Id: sio.c,v 1.52 1994/05/31 18:18:46 ache Exp $
  */
 
 #include "sio.h"
  */
 
 #include "sio.h"
@@ -56,6 +56,7 @@
 #include "malloc.h"
 #include "syslog.h"
 
 #include "malloc.h"
 #include "syslog.h"
 
+#include "i386/isa/icu.h"      /* XXX */
 #include "i386/isa/isa.h"
 #include "i386/isa/isa_device.h"
 #include "i386/isa/comreg.h"
 #include "i386/isa/isa.h"
 #include "i386/isa/isa_device.h"
 #include "i386/isa/comreg.h"
@@ -86,6 +87,7 @@
 #endif /* COM_MULTIPORT */
 
 #define        COM_NOFIFO(dev) ((dev)->id_flags & 0x02)
 #endif /* COM_MULTIPORT */
 
 #define        COM_NOFIFO(dev) ((dev)->id_flags & 0x02)
+#define        COM_QUIET(dev)  ((dev)->id_flags & 0x80)
 
 #define        com_scr         7       /* scratch register for 16450-16550 (R/W) */
 
 
 #define        com_scr         7       /* scratch register for 16450-16550 (R/W) */
 
@@ -313,25 +315,18 @@ static    struct speedtab comspeedtab[] = {
 /* XXX - configure this list */
 static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
 
 /* XXX - configure this list */
 static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
 
-#if 0
-#define        FAIL(x) 1
-#else
-#define        FAIL(x) (printf("sioprobe flunked test %d\n", (x)), 1)
-#endif
-
 static int
 sioprobe(dev)
        struct isa_device       *dev;
 {
        static bool_t   already_init;
        Port_t          *com_ptr;
 static int
 sioprobe(dev)
        struct isa_device       *dev;
 {
        static bool_t   already_init;
        Port_t          *com_ptr;
+       bool_t          failures[10];
+       int             fn;
+       struct isa_device       *idev;
        Port_t          iobase;
        u_char          mcr_image;
        int             result;
        Port_t          iobase;
        u_char          mcr_image;
        int             result;
-#ifdef COM_MULTIPORT
-       struct  isa_device      *mdev;
-#endif /* COM_MULTIPORT */
-       struct  isa_device      *tdev;
 
        if (!already_init) {
                /*
 
        if (!already_init) {
                /*
@@ -351,25 +346,41 @@ sioprobe(dev)
        /*
         * If the port is on a multiport card and has a master port,
         * initialize the common interrupt control register in the
        /*
         * 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.
+        * master and prepare to leave MCR_IENABLE clear in the mcr.
+        * Otherwise, prepare to set MCR_IENABLE in the mcr.
+        * Point idev to the device struct giving the correct id_irq.
+        * This is the struct for the master device if there is one.
         */
         */
+       idev = dev;
        mcr_image = MCR_IENABLE;
 #ifdef COM_MULTIPORT
        mcr_image = MCR_IENABLE;
 #ifdef COM_MULTIPORT
-       if (COM_ISMULTIPORT(dev) && !COM_NOMASTER(dev)) {
-               mdev = find_isadev(isa_devtab_tty, &siodriver,
-                                  COM_MPMASTER(dev));
-               if (mdev != NULL) {
-                       outb(mdev->id_iobase + com_scr, 0x80);
+       if (COM_ISMULTIPORT(dev)) {
+               if (!COM_NOMASTER(dev)) {
+                       idev = find_isadev(isa_devtab_tty, &siodriver,
+                                          COM_MPMASTER(dev));
+                       if (idev == NULL) {
+                               printf("sio%d: master device %d not found\n",
+                                      dev->id_unit, COM_MPMASTER(dev));
+                               return (0);
+                       }
+                       if (idev->id_irq == 0) {
+                               printf("sio%d: master device %d irq not configured\n",
+                                      dev->id_unit, COM_MPMASTER(dev));
+                               return (0);
+                       }
+                       outb(idev->id_iobase + com_scr, 0x80);
                        mcr_image = 0;
                }
                        mcr_image = 0;
                }
-               else
-                       return (0);
        }
        }
+       else
 #endif /* COM_MULTIPORT */
 #endif /* COM_MULTIPORT */
+       if (idev->id_irq == 0) {
+               printf("sio%d: irq not configured\n", dev->id_unit);
+               return (0);
+       }
 
 
+       bzero(failures, sizeof failures);
        iobase = dev->id_iobase;
        iobase = dev->id_iobase;
-       result = IO_COMSIZE;
 
        /*
         * We don't want to get actual interrupts, just masked ones.
 
        /*
         * We don't want to get actual interrupts, just masked ones.
@@ -379,6 +390,14 @@ sioprobe(dev)
         */
        disable_intr();
 
         */
        disable_intr();
 
+       /*
+        * XXX DELAY() reenables CPU interrupts.  This is a problem for
+        * shared interrupts after the first device using one has been
+        * successfully probed - config_isadev() has enabled the interrupt
+        * in the ICU.
+        */
+       outb(IO_ICU1 + 1, 0xff);
+
        /*
         * Initialize the speed and the word size and wait long enough to
         * drain the maximum of 16 bytes of junk in device output queues.
        /*
         * Initialize the speed and the word size and wait long enough to
         * drain the maximum of 16 bytes of junk in device output queues.
@@ -434,18 +453,9 @@ sioprobe(dev)
         * an interrupt line high.  It doesn't matter if the interrupt
         * line oscillates while we are not looking at it, since interrupts
         * are disabled.
         * 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!  DELAY() reenables them for the CPU.
-        * config_isadev() enables for the ICU them after the probe of the
-        * first device on a shared interrupt succeeds.
         */
        outb(iobase + com_mcr, mcr_image);
 
         */
        outb(iobase + com_mcr, mcr_image);
 
-       tdev = dev;
-#ifdef COM_MULTIPORT
-       if (COM_ISMULTIPORT(dev) && !COM_NOMASTER(dev))
-               tdev = mdev;
-#endif /*COM_MULTIPORT*/
        /*
         * Check that
         *      o the CFCR, IER and MCR in UART hold the values written to them
        /*
         * Check that
         *      o the CFCR, IER and MCR in UART hold the values written to them
@@ -454,14 +464,14 @@ sioprobe(dev)
         *      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 an output interrupt is generated and its vector is correct.
         *      o the interrupt goes away when the IIR in the UART is read.
         */
-       if (   inb(iobase + com_cfcr) != CFCR_8BITS && FAIL(0)
-           || inb(iobase + com_ier) != IER_ETXRDY && FAIL(1)
-           || inb(iobase + com_mcr) != mcr_image && FAIL(2)
-           || !isa_irq_pending(tdev) && FAIL(3)
-           || (inb(iobase + com_iir) & IIR_IMASK) != IIR_TXRDY && FAIL(4)
-           || isa_irq_pending(tdev) && FAIL(5)
-           || (inb(iobase + com_iir) & IIR_IMASK) != IIR_NOPEND && FAIL(6))
-               result = 0;
+       failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS;
+       failures[1] = inb(iobase + com_ier) - IER_ETXRDY;
+       failures[2] = inb(iobase + com_mcr) - mcr_image;
+       if (idev->id_irq != 0)
+               failures[3] = isa_irq_pending(idev) ? 0 : 1;
+       failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY;
+       failures[5] = isa_irq_pending(idev) ? 1 : 0;
+       failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND;
 
        /*
         * Turn off all device interrupts and check that they go off properly.
 
        /*
         * Turn off all device interrupts and check that they go off properly.
@@ -474,14 +484,22 @@ sioprobe(dev)
         */
        outb(iobase + com_ier, 0);
        outb(iobase + com_cfcr, CFCR_8BITS);    /* dummy to avoid bus echo */
         */
        outb(iobase + com_ier, 0);
        outb(iobase + com_cfcr, CFCR_8BITS);    /* dummy to avoid bus echo */
-       if (   inb(iobase + com_ier) != 0 && FAIL(7)
-           || isa_irq_pending(tdev) && FAIL(8)
-           || (inb(iobase + com_iir) & IIR_IMASK) != IIR_NOPEND && FAIL(9))
-               result = 0;
-       if (result == 0)
-               outb(iobase + com_mcr, 0);
+       failures[7] = inb(iobase + com_ier);
+       failures[8] = isa_irq_pending(idev) ? 1 : 0;
+       failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND;
 
 
+       outb(IO_ICU1 + 1, imen);        /* XXX */
        enable_intr();
        enable_intr();
+
+       result = IO_COMSIZE;
+       for (fn = 0; fn < sizeof failures; ++fn)
+               if (failures[fn]) {
+                       outb(iobase + com_mcr, 0);
+                       result = 0;
+                       if (!COM_QUIET(dev))
+                               printf("sio%d: probe test %d failed\n",
+                                      dev->id_unit, fn);
+               }
        return (result);
 }
 
        return (result);
 }
 
@@ -599,7 +617,7 @@ determined_type: ;
        if (COM_ISMULTIPORT(isdp)) {
                com->multiport = TRUE;
                printf(" (multiport");
        if (COM_ISMULTIPORT(isdp)) {
                com->multiport = TRUE;
                printf(" (multiport");
-               if (!COM_NOMASTER(isdp) && COM_MPMASTER(isdp) == unit)
+               if (!COM_NOMASTER(isdp) && unit == COM_MPMASTER(isdp))
                        printf(" master");
                printf(")");
         }
                        printf(" master");
                printf(")");
         }
@@ -608,7 +626,7 @@ determined_type: ;
 
 #ifdef KGDB
        if (kgdb_dev == makedev(commajor, unit)) {
 
 #ifdef KGDB
        if (kgdb_dev == makedev(commajor, unit)) {
-               if (comconsole == unit)
+               if (unit == comconsole)
                        kgdb_dev = -1;  /* can't debug over console port */
                else {
                        int divisor;
                        kgdb_dev = -1;  /* can't debug over console port */
                else {
                        int divisor;
@@ -701,27 +719,27 @@ open_top:
                                        error = EBUSY;
                                        goto out;
                                }
                                        error = EBUSY;
                                        goto out;
                                }
-                                   error = tsleep((caddr_t)&com->active_out,
+                               error = tsleep((caddr_t)&com->active_out,
                                               TTIPRI | PCATCH, "siobi", 0);
                                if (error != 0)
                                        goto out;
                                goto open_top;
                                               TTIPRI | PCATCH, "siobi", 0);
                                if (error != 0)
                                        goto out;
                                goto open_top;
-                                   }
-                               }
+                       }
+               }
                if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
                        error = EBUSY;
                        goto out;
                if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
                        error = EBUSY;
                        goto out;
-                       }
-                               } else {
+               }
+       } else {
                /*
                 * The device isn't open, so there are no conflicts.
                 * Initialize it.  Initialization is done twice in many
                 * cases: to preempt sleeping callin opens if we are
                 * callout, and to complete a callin open after DCD rises.
                 */
                /*
                 * 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;
                tp->t_termios = mynor & CALLOUT_MASK
                                ? com->it_out : com->it_in;
                commctl(com, MCR_DTR | MCR_RTS, DMSET);
                tp->t_termios = mynor & CALLOUT_MASK
                                ? com->it_out : com->it_in;
                commctl(com, MCR_DTR | MCR_RTS, DMSET);
@@ -772,7 +790,7 @@ open_top:
                        goto out;
                goto open_top;
        }
                        goto out;
                goto open_top;
        }
-               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:
        if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
                com->active_out = TRUE;
 out:
@@ -849,9 +867,9 @@ comhardclose(com)
                                timeout(siodtrwakeup, (caddr_t)com,
                                        com->dtr_wait);
                                com->state |= CS_DTR_OFF;
                                timeout(siodtrwakeup, (caddr_t)com,
                                        com->dtr_wait);
                                com->state |= CS_DTR_OFF;
+                       }
                }
        }
                }
        }
-       }
        com->active_out = FALSE;
        wakeup((caddr_t)&com->active_out);
        wakeup(TSA_CARR_ON(tp));        /* restart any wopeners */
        com->active_out = FALSE;
        wakeup((caddr_t)&com->active_out);
        wakeup(TSA_CARR_ON(tp));        /* restart any wopeners */