tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

machfb MMIO versus SPARCle OFW



Hi,

I tracked down why my SPARCle (SPARC laptop) appears to lock up on halt.
The cause is:

  http://mail-index.NetBSD.org/source-changes/2012/08/15/msg036624.html

where we use the MMIO registers and alter the BUS_CNTL register.  This is
a problem because altering the BUS_CNTL register in this way [*] causes the
OFW console to stop working when we halt.

The solution seemed fairly easy - add a detach routine to machfb to
restore the BUS_CNTL register (patch attached).  However, this fails
because wsdisplay0 attaches at machfb0, so we also need a detach routine
for wsdisplay.  As wsdisplay0 is the console, we have to force the detach,
so it seemed reasonable to add an additional flag for that (wscons patch
also attached).  This works, and halt now returns to the OFW prompt.

However, I have a question about the wscons patch - there is no
wsdisplay_noemul_detach(), so is it sensible to call only
wsdisplay_emul_detach() on detach, or is there configuration where
wsdisplay* at machfb could be wsdisplay_noemul?

Thanks,

J

PS.  Patches against against current from 2012/08/15.
PPS.  Not yet tested on non-console machfb.

[*] cvs rdiff -u -r1.80 -r1.81 src/sys/dev/pci/machfb.c

-- 
   NetBSD: simple; works; documented    /        Sailing at Newbiggin
        http://www.netbsd.org/        /   http://www.newbigginsailingclub.org/
Index: sys/dev/pci/machfb.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/machfb.c,v
retrieving revision 1.82
diff -u -r1.82 machfb.c
--- sys/dev/pci/machfb.c        15 Aug 2012 17:43:59 -0000      1.82
+++ sys/dev/pci/machfb.c        21 Oct 2013 19:36:36 -0000
@@ -141,6 +141,7 @@
        int mclk_post_div;
        int mclk_fb_div;
        int sc_clock;   /* which clock to use */
+       int sc_use_mmio;        /* using MMIO register */
 
        struct videomode *sc_my_mode;
        int sc_edid_size;
@@ -191,6 +192,7 @@
        { PCI_PRODUCT_ATI_RAGE_MOB_M3_AGP, 230000 },
        { PCI_PRODUCT_ATI_RAGE_MOBILITY, 230000 },
 #endif
+       { PCI_PRODUCT_ATI_RAGE_L_MOB_M1_PCI, 230000 },
        { PCI_PRODUCT_ATI_RAGE_LT_PRO_AGP, 230000 },
        { PCI_PRODUCT_ATI_RAGE_LT_PRO, 230000 },
        { PCI_PRODUCT_ATI_RAGE_LT, 230000 },
@@ -235,9 +237,10 @@
 
 static int     mach64_match(device_t, cfdata_t, void *);
 static void    mach64_attach(device_t, device_t, void *);
+static int     mach64_detach(device_t, int);
 
-CFATTACH_DECL_NEW(machfb, sizeof(struct mach64_softc), mach64_match, 
mach64_attach,
-    NULL, NULL);
+CFATTACH_DECL3_NEW(machfb, sizeof(struct mach64_softc), mach64_match,
+    mach64_attach, mach64_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
 
 static void    mach64_init(struct mach64_softc *);
 static int     mach64_get_memsize(struct mach64_softc *);
@@ -521,7 +524,6 @@
        pcireg_t screg;
        uint32_t reg;
        const pcireg_t enables = PCI_COMMAND_MEM_ENABLE;
-       int use_mmio = FALSE;
 
        sc->sc_dev = self;
        sc->sc_pc = pa->pa_pc;
@@ -535,6 +537,7 @@
        sc->sc_iot = pa->pa_iot;
        sc->sc_accessops.ioctl = mach64_ioctl;
        sc->sc_accessops.mmap = mach64_mmap;
+       sc->sc_use_mmio = FALSE;
 
        pci_aprint_devinfo(pa, "Graphics processor");
 #ifdef MACHFB_DEBUG
@@ -578,10 +581,10 @@
                         * functions
                         */
                        aprint_normal_dev(sc->sc_dev, "using MMIO aperture\n");
-                       use_mmio = TRUE;
+                       sc->sc_use_mmio = TRUE;
                }
        } 
-       if (!use_mmio) {
+       if (!sc->sc_use_mmio) {
                if (bus_space_map(sc->sc_memt, sc->sc_aperbase, sc->sc_apersize,
                        BUS_SPACE_MAP_LINEAR, &sc->sc_memh)) {
                        panic("%s: failed to map aperture",
@@ -824,7 +827,7 @@
        aa.accesscookie = &sc->vd;
 
        config_found(self, &aa, wsemuldisplaydevprint);
-       if (use_mmio) {
+       if (sc->sc_use_mmio) {
                /*
                 * Now that we took over, turn off the aperture registers if we 
                 * don't use them. Can't do this earlier since on some hardware
@@ -840,6 +843,24 @@
 }
 
 static int
+mach64_detach(device_t self, int flags)
+{
+       struct mach64_softc *sc = device_private(self);
+       uint32_t reg;
+
+       if (sc->sc_use_mmio) {
+               reg = regr(sc, BUS_CNTL);
+               aprint_debug_dev(sc->sc_dev, "BUS_CNTL: %08x\n", reg);
+               reg &= ~BUS_APER_REG_DIS;
+               regw(sc, BUS_CNTL, reg);
+
+               bus_space_unmap(sc->sc_regt, sc->sc_regh, sc->sc_regsize);
+       } else
+               bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_apersize);
+       return 0;
+}
+
+static int
 machfb_drm_print(void *aux, const char *pnp)
 {
        if (pnp)
Index: sys/dev/wscons/wsconsio.h
===================================================================
RCS file: /cvsroot/src/sys/dev/wscons/wsconsio.h,v
retrieving revision 1.104
diff -u -r1.104 wsconsio.h
--- sys/dev/wscons/wsconsio.h   17 Apr 2012 10:19:57 -0000      1.104
+++ sys/dev/wscons/wsconsio.h   21 Oct 2013 19:36:54 -0000
@@ -433,6 +433,7 @@
        int idx; /* screen index */
        int flags;
 #define        WSDISPLAY_DELSCR_FORCE 1
+#define        WSDISPLAY_DELSCR_SHUTDOWN 4
 };
 #define        WSDISPLAYIO_DELSCREEN   _IOW('W', 79, struct 
wsdisplay_delscreendata)
 
Index: sys/dev/wscons/wsdisplay.c
===================================================================
RCS file: /cvsroot/src/sys/dev/wscons/wsdisplay.c,v
retrieving revision 1.135
diff -u -r1.135 wsdisplay.c
--- sys/dev/wscons/wsdisplay.c  2 Feb 2012 13:11:25 -0000       1.135
+++ sys/dev/wscons/wsdisplay.c  21 Oct 2013 19:36:55 -0000
@@ -171,8 +171,9 @@
 static void wsdisplay_noemul_attach(device_t, device_t, void *);
 static bool wsdisplay_suspend(device_t, const pmf_qual_t *);
 
-CFATTACH_DECL_NEW(wsdisplay_emul, sizeof (struct wsdisplay_softc),
-    wsdisplay_emul_match, wsdisplay_emul_attach, wsdisplay_emul_detach, NULL);
+CFATTACH_DECL3_NEW(wsdisplay_emul, sizeof (struct wsdisplay_softc),
+    wsdisplay_emul_match, wsdisplay_emul_attach, wsdisplay_emul_detach,
+    NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
   
 CFATTACH_DECL_NEW(wsdisplay_noemul, sizeof (struct wsdisplay_softc),
     wsdisplay_noemul_match, wsdisplay_noemul_attach, NULL, NULL);
@@ -478,8 +479,9 @@
        if ((scr = sc->sc_scr[idx]) == NULL)
                return (ENXIO);
 
-       if (scr->scr_dconf == &wsdisplay_console_conf ||
-           scr->scr_syncops ||
+       if (((scr->scr_dconf == &wsdisplay_console_conf) &&
+            !(flags & WSDISPLAY_DELSCR_SHUTDOWN)) ||
+            scr->scr_syncops ||
            ((scr->scr_flags & SCR_OPEN) && !(flags & WSDISPLAY_DELSCR_FORCE)))
                return(EBUSY);
 
@@ -594,7 +596,8 @@
        struct wsdisplay_softc *sc = device_private(dev);
        int flag, i, res;
 
-       flag = (how & DETACH_FORCE ? WSDISPLAY_DELSCR_FORCE : 0);
+       flag = ((how & DETACH_FORCE) ? WSDISPLAY_DELSCR_FORCE : 0) |
+           ((how & DETACH_SHUTDOWN) ? WSDISPLAY_DELSCR_SHUTDOWN : 0);
        for (i = 0; i < WSDISPLAY_MAXSCREEN; i++)
                if (sc->sc_scr[i]) {
                        res = wsdisplay_delscreen(sc, i, flag);


Home | Main Index | Thread Index | Old Index