Do not register an interrupt handler unless we know that we can clear
authorbriggs <briggs@openbsd.org>
Sat, 29 Mar 1997 23:47:13 +0000 (23:47 +0000)
committerbriggs <briggs@openbsd.org>
Sat, 29 Mar 1997 23:47:13 +0000 (23:47 +0000)
interrupts properly.
Take a stab at clearing interrupts correctly for stupid Samsung video
card that masquerades as a Toby Frame Buffer card.
Break out interrupt routines by card type, including the cards that just
need a byte cleared to clear the interrupt.

sys/arch/mac68k/dev/grf_mv.c
sys/arch/mac68k/dev/grfvar.h

index 0f4a011..f498eef 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: grf_mv.c,v 1.9 1997/03/14 14:16:52 briggs Exp $       */
+/*     $OpenBSD: grf_mv.c,v 1.10 1997/03/29 23:47:13 briggs Exp $      */
 /*     $NetBSD: grf_mv.c,v 1.17 1997/02/24 06:20:06 scottr Exp $       */
 
 /*
 #include "grfvar.h"
 
 static void    load_image_data __P((caddr_t data, struct image_data *image));
-static void    grfmv_intr __P((void *vsc, int slot));
 
-#ifndef MYSTERY
 static char zero = 0;
+static void    grfmv_intr_generic __P((void *vsc, int slot));
+static void    grfmv_intr_cti __P((void *vsc, int slot));
+
+#ifdef MYSTERY
+static void    grfmv_intr_mystery __P((void *vsc, int slot));
 #endif
 
 static int     grfmv_mode __P((struct grf_softc *gp, int cmd, void *arg));
@@ -95,72 +98,6 @@ load_image_data(data, image)
        bcopy(data + 42, &image->planeBytes, 4);
 }
 
-/*ARGSUSED*/
-static void
-grfmv_intr(vsc, slot)
-       void    *vsc;
-       int     slot;
-{
-#ifdef MYSTERY
-       struct grfbus_softc *sc;
-       caddr_t slotbase;
-
-       sc = (struct grfbus_softc *) vsc;
-       slotbase = (caddr_t) sc->sc_slot.virtual_base;
-       asm volatile("  movl    %0,a0
-                       movl    a0@(0xff6028),d0
-                       andl    #0x2,d0
-                       beq     _mv_intr0
-                       movql   #0x3,d0
-               _mv_intr0:
-                       movl    a0@(0xff600c),d1
-                       andl    #0x3,d1
-                       cmpl    d1,d0
-                       beq     _mv_intr_fin
-                       movl    d0,a0@(0xff600c)
-                       nop
-                       tstb    d0
-                       beq     _mv_intr1
-                       movl    #0x0002,a0@(0xff6040)
-                       movl    #0x0102,a0@(0xff6044)
-                       movl    #0x0105,a0@(0xff6048)
-                       movl    #0x000e,a0@(0xff604c)
-                       movl    #0x001c,a0@(0xff6050)
-                       movl    #0x00bc,a0@(0xff6054)
-                       movl    #0x00c3,a0@(0xff6058)
-                       movl    #0x0061,a0@(0xff605c)
-                       movl    #0x0012,a0@(0xff6060)
-                       bra     _mv_intr_fin
-               _mv_intr1:
-                       movl    #0x0002,a0@(0xff6040)
-                       movl    #0x0209,a0@(0xff6044)
-                       movl    #0x020c,a0@(0xff6048)
-                       movl    #0x000f,a0@(0xff604c)
-                       movl    #0x0027,a0@(0xff6050)
-                       movl    #0x00c7,a0@(0xff6054)
-                       movl    #0x00d7,a0@(0xff6058)
-                       movl    #0x006b,a0@(0xff605c)
-                       movl    #0x0029,a0@(0xff6060)
-               _mv_intr_fin:
-                       movl    #0x1,a0@(0xff6014)"
-               : : "g" (slotbase) : "a0","d0","d1");
-#else
-       caddr_t                  slotbase;
-       struct grfbus_softc     *sc;
-
-       sc = (struct grfbus_softc *) vsc;
-       slotbase = (caddr_t) sc->sc_slot.virtual_base;
-       switch (sc->card_id) {
-       case NUBUS_DRHW_WVC:
-               slotbase[0xa00000] = zero;
-               break;
-       default:
-               slotbase[0xa0000] = zero;
-               break;
-       }
-#endif
-}
-
 static int
 grfmv_match(parent, vcf, aux)
        struct device *parent;
@@ -264,9 +201,43 @@ grfmv_attach(parent, self, aux)
                CARD_NAME_LEN);
        cardname[CARD_NAME_LEN-1] = '\0';
 
+       if (sc->card_id == NUBUS_DRHW_TFB) {
+               /*
+                * This is the Toby card, but apparently some manufacturers
+                * (like Cornerstone) didn't bother to get/use their own
+                * value here, even though the cards are different, so we
+                * so we try to differentiate here.
+                */
+               if (strncmp(cardname, "Samsung 768", 11) == 0) {
+                       sc->card_id = NUBUS_DRHW_SAM768;
+               } else if (strncmp(cardname, "Toby frame", 10) == 0) {
+               } else {
+                       printf(": (evil card pretending to be TFB)");
+               }
+       }
+
        printf(": %s\n", cardname);
 
-       add_nubus_intr(sc->sc_slot.slot, grfmv_intr, sc);
+       switch (sc->card_id) {
+       case NUBUS_DRHW_M2HRVC:
+       case NUBUS_DRHW_TFB:
+               sc->cli_offset = 0xa0000;
+               add_nubus_intr(sc->sc_slot.slot, grfmv_intr_generic, sc);
+               break;
+       case NUBUS_DRHW_WVC:
+               sc->cli_offset = 0xa00000;
+               add_nubus_intr(sc->sc_slot.slot, grfmv_intr_generic, sc);
+               break;
+       case NUBUS_DRHW_SAM768:
+               add_nubus_intr(sc->sc_slot.slot, grfmv_intr_cti, sc);
+               break;
+       case NUBUS_DRHW_MICRON:
+               /* What do we know about this one? */
+       default:
+               printf("        Unknown video card 0x%x--", sc->card_id);
+               printf("Not installing interrupt routine.\n");
+               break;
+       }
 
        /* Perform common video attachment. */
        grf_establish(sc, &sc->sc_slot, grfmv_mode, grfmv_phys);
@@ -300,3 +271,99 @@ grfmv_phys(gp, addr)
        return (caddr_t) (NUBUS_SLOT2PA(gp->sc_slot->slot) +
                                (addr - gp->sc_slot->virtual_base));
 }
+
+/* Interrupt handlers... */
+/*
+ * Generic routine to clear interrupts for cards where it simply takes
+ * a CLR.B to clear the interrupt.  The offset of this byte varies between
+ * cards.
+ */
+/*ARGSUSED*/
+static void
+grfmv_intr_generic(vsc, slot)
+       void    *vsc;
+       int     slot;
+{
+       caddr_t                  slotbase;
+       struct grfbus_softc     *sc;
+
+       sc = (struct grfbus_softc *) vsc;
+       slotbase = (caddr_t) sc->sc_slot.virtual_base;
+       slotbase[sc->cli_offset] = zero;
+}
+
+/*
+ * Routine to clear interrupts on Samsung 768x1006 video controller.
+ * This controller was manufactured by Cornerstone Technology, Inc.,
+ * now known as Cornerstone Imaging.
+ *
+ * To clear this interrupt, we apparently have to set, then clear,
+ * bit 2 at byte offset 0x80000 from the card's base.
+ *     Information for this provided by Brad Salai <bsalai@servtech.com>
+ */
+/*ARGSUSED*/
+static void
+grfmv_intr_cti(vsc, slot)
+       void    *vsc;
+       int     slot;
+{
+       volatile char           *slotbase;
+       struct grfbus_softc     *sc;
+
+       sc = (struct grfbus_softc *) vsc;
+       slotbase = ((volatile char *) sc->sc_slot.virtual_base) + 0x00080000;
+       *slotbase = (*slotbase | 0x02);
+       *slotbase = (*slotbase & 0xFD);
+}
+
+#ifdef MYSTERY
+/*ARGSUSED*/
+static void
+grfmv_intr_mystery(vsc, slot)
+       void    *vsc;
+       int     slot;
+{
+       struct grfbus_softc *sc;
+       caddr_t slotbase;
+
+       sc = (struct grfbus_softc *) vsc;
+       slotbase = (caddr_t) sc->sc_slot.virtual_base;
+       asm volatile("  movl    %0,a0
+                       movl    a0@(0xff6028),d0
+                       andl    #0x2,d0
+                       beq     _mv_intr0
+                       movql   #0x3,d0
+               _mv_intr0:
+                       movl    a0@(0xff600c),d1
+                       andl    #0x3,d1
+                       cmpl    d1,d0
+                       beq     _mv_intr_fin
+                       movl    d0,a0@(0xff600c)
+                       nop
+                       tstb    d0
+                       beq     _mv_intr1
+                       movl    #0x0002,a0@(0xff6040)
+                       movl    #0x0102,a0@(0xff6044)
+                       movl    #0x0105,a0@(0xff6048)
+                       movl    #0x000e,a0@(0xff604c)
+                       movl    #0x001c,a0@(0xff6050)
+                       movl    #0x00bc,a0@(0xff6054)
+                       movl    #0x00c3,a0@(0xff6058)
+                       movl    #0x0061,a0@(0xff605c)
+                       movl    #0x0012,a0@(0xff6060)
+                       bra     _mv_intr_fin
+               _mv_intr1:
+                       movl    #0x0002,a0@(0xff6040)
+                       movl    #0x0209,a0@(0xff6044)
+                       movl    #0x020c,a0@(0xff6048)
+                       movl    #0x000f,a0@(0xff604c)
+                       movl    #0x0027,a0@(0xff6050)
+                       movl    #0x00c7,a0@(0xff6054)
+                       movl    #0x00d7,a0@(0xff6058)
+                       movl    #0x006b,a0@(0xff605c)
+                       movl    #0x0029,a0@(0xff6060)
+               _mv_intr_fin:
+                       movl    #0x1,a0@(0xff6014)"
+               : : "g" (slotbase) : "a0","d0","d1");
+}
+#endif
index 63862fb..301a9c3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: grfvar.h,v 1.6 1997/03/18 05:35:24 briggs Exp $       */
+/*     $OpenBSD: grfvar.h,v 1.7 1997/03/29 23:47:13 briggs Exp $       */
 /*     $NetBSD: grfvar.h,v 1.11 1996/08/04 06:03:58 scottr Exp $       */
 
 /*
@@ -57,7 +57,9 @@ struct grfbus_softc {
        bus_space_handle_t      sc_fbh;
 
        struct  grfmode curr_mode;      /* hardware desc(for ioctl)     */
-       u_int16_t       card_id;        /* DrHW value for nubus cards   */
+       u_int32_t       card_id;        /* DrHW value for nubus cards   */
+       u_int32_t       cli_offset;     /* Offset of byte to clear intr */
+                                       /* for cards where that's suff.  */
        nubus_dir       board_dir;      /* Nubus dir for curr board     */
 };