From: briggs Date: Sat, 29 Mar 1997 23:47:13 +0000 (+0000) Subject: Do not register an interrupt handler unless we know that we can clear X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=7ecf6d7fd8afc6b7a2930d1d6bb36f5bbeb5e1d4;p=openbsd Do not register an interrupt handler unless we know that we can clear 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. --- diff --git a/sys/arch/mac68k/dev/grf_mv.c b/sys/arch/mac68k/dev/grf_mv.c index 0f4a0110010..f498eef8ccc 100644 --- a/sys/arch/mac68k/dev/grf_mv.c +++ b/sys/arch/mac68k/dev/grf_mv.c @@ -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 $ */ /* @@ -52,10 +52,13 @@ #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 + */ +/*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 diff --git a/sys/arch/mac68k/dev/grfvar.h b/sys/arch/mac68k/dev/grfvar.h index 63862fb3539..301a9c3fc98 100644 --- a/sys/arch/mac68k/dev/grfvar.h +++ b/sys/arch/mac68k/dev/grfvar.h @@ -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 */ };