Module Name: src Committed By: jmcneill Date: Tue Feb 8 10:52:57 UTC 2011
Modified Files: src/sys/arch/x86/x86: genfb_machdep.c x86_autoconf.c src/sys/dev/wsfb: genfb.c genfbvar.h Log Message: add a 'setmode' callback to genfb and use it to setup write-combining MTRRs on x86 whenever switching to WSDISPLAYIO_MODE_EMUL To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/sys/arch/x86/x86/genfb_machdep.c cvs rdiff -u -r1.53 -r1.54 src/sys/arch/x86/x86/x86_autoconf.c cvs rdiff -u -r1.33 -r1.34 src/sys/dev/wsfb/genfb.c cvs rdiff -u -r1.17 -r1.18 src/sys/dev/wsfb/genfbvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/x86/genfb_machdep.c diff -u src/sys/arch/x86/x86/genfb_machdep.c:1.4 src/sys/arch/x86/x86/genfb_machdep.c:1.5 --- src/sys/arch/x86/x86/genfb_machdep.c:1.4 Wed Apr 28 19:17:04 2010 +++ src/sys/arch/x86/x86/genfb_machdep.c Tue Feb 8 10:52:56 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: genfb_machdep.c,v 1.4 2010/04/28 19:17:04 dyoung Exp $ */ +/* $NetBSD: genfb_machdep.c,v 1.5 2011/02/08 10:52:56 jmcneill Exp $ */ /*- * Copyright (c) 2009 Jared D. McNeill <jmcne...@invisible.ca> @@ -31,16 +31,20 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: genfb_machdep.c,v 1.4 2010/04/28 19:17:04 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: genfb_machdep.c,v 1.5 2011/02/08 10:52:56 jmcneill Exp $"); + +#include "opt_mtrr.h" #include <sys/param.h> #include <sys/conf.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/kernel.h> +#include <sys/lwp.h> #include <machine/bus.h> #include <machine/bootinfo.h> +#include <machine/mtrr.h> #include <dev/wscons/wsconsio.h> #include <dev/wscons/wsdisplayvar.h> @@ -70,6 +74,40 @@ NULL }; +void +x86_genfb_mtrr_init(uint64_t physaddr, uint32_t size) +{ +#ifdef MTRR + struct mtrr mtrr; + int error, n; + + if (mtrr_funcs == NULL) { + aprint_debug("%s: no mtrr funcs\n", __func__); + return; + } + + mtrr.base = physaddr; + mtrr.len = size; + mtrr.type = MTRR_TYPE_WC; + mtrr.flags = MTRR_VALID; + mtrr.owner = 0; + + aprint_debug("%s: 0x%llx-0x%llx\n", __func__, + mtrr.base, mtrr.base + mtrr.len - 1); + + n = 1; + KERNEL_LOCK(1, NULL); + error = mtrr_set(&mtrr, &n, curlwp->l_proc, MTRR_GETSET_KERNEL); + if (n != 0) + mtrr_commit(); + KERNEL_UNLOCK_ONE(NULL); + + aprint_debug("%s: mtrr_set returned %d\n", __func__, error); +#else + aprint_debug("%s: kernel lacks MTRR option\n", __func__); +#endif +} + int x86_genfb_cnattach(void) { Index: src/sys/arch/x86/x86/x86_autoconf.c diff -u src/sys/arch/x86/x86/x86_autoconf.c:1.53 src/sys/arch/x86/x86/x86_autoconf.c:1.54 --- src/sys/arch/x86/x86/x86_autoconf.c:1.53 Mon Jan 10 21:26:38 2011 +++ src/sys/arch/x86/x86/x86_autoconf.c Tue Feb 8 10:52:56 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: x86_autoconf.c,v 1.53 2011/01/10 21:26:38 jakllsch Exp $ */ +/* $NetBSD: x86_autoconf.c,v 1.54 2011/02/08 10:52:56 jmcneill Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: x86_autoconf.c,v 1.53 2011/01/10 21:26:38 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: x86_autoconf.c,v 1.54 2011/02/08 10:52:56 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -72,6 +72,7 @@ #include <dev/pci/pcivar.h> #endif #include <dev/wsfb/genfbvar.h> +#include <arch/x86/include/genfb_machdep.h> #if NPCI > 0 #include <dev/pci/genfb_pcivar.h> #endif @@ -80,6 +81,7 @@ #if NPCI > 0 static struct genfb_colormap_callback gfb_cb; static struct genfb_pmf_callback pmf_cb; +static struct genfb_mode_callback mode_cb; #endif #ifdef VGA_POST static struct vga_post *vga_posth = NULL; @@ -99,6 +101,15 @@ } static bool +x86_genfb_setmode(struct genfb_softc *sc, int newmode) +{ + if (newmode == WSDISPLAYIO_MODE_EMUL) + x86_genfb_mtrr_init(sc->sc_fboffset, + sc->sc_height * sc->sc_stride); + return true; +} + +static bool x86_genfb_suspend(device_t dev, const pmf_qual_t *qual) { return true; @@ -675,6 +686,12 @@ prop_dictionary_set_uint64(dict, "cmap_callback", (uint64_t)&gfb_cb); } + if (fbinfo->physaddr != 0) { + mode_cb.gmc_setmode = x86_genfb_setmode; + prop_dictionary_set_uint64(dict, + "mode_callback", + (uint64_t)&mode_cb); + } } prop_dictionary_set_bool(dict, "is_console", true); prop_dictionary_set_bool(dict, "clear-screen", false); Index: src/sys/dev/wsfb/genfb.c diff -u src/sys/dev/wsfb/genfb.c:1.33 src/sys/dev/wsfb/genfb.c:1.34 --- src/sys/dev/wsfb/genfb.c:1.33 Sun Feb 6 23:25:17 2011 +++ src/sys/dev/wsfb/genfb.c Tue Feb 8 10:52:56 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: genfb.c,v 1.33 2011/02/06 23:25:17 jmcneill Exp $ */ +/* $NetBSD: genfb.c,v 1.34 2011/02/08 10:52:56 jmcneill Exp $ */ /*- * Copyright (c) 2007 Michael Lorenz @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: genfb.c,v 1.33 2011/02/06 23:25:17 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: genfb.c,v 1.34 2011/02/08 10:52:56 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -102,7 +102,7 @@ genfb_init(struct genfb_softc *sc) { prop_dictionary_t dict; - uint64_t cmap_cb, pmf_cb, bl_cb; + uint64_t cmap_cb, pmf_cb, mode_cb, bl_cb; uint32_t fboffset; bool console; @@ -159,6 +159,13 @@ sc->sc_pmfcb = (void *)(vaddr_t)pmf_cb; } + /* optional mode callback */ + sc->sc_modecb = NULL; + if (prop_dictionary_get_uint64(dict, "mode_callback", &mode_cb)) { + if (mode_cb != 0) + sc->sc_modecb = (void *)(vaddr_t)mode_cb; + } + /* optional backlight control callback */ sc->sc_backlight = NULL; if (prop_dictionary_get_uint64(dict, "backlight_callback", &bl_cb)) { @@ -228,6 +235,8 @@ sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; memcpy(&sc->sc_ops, ops, sizeof(struct genfb_ops)); sc->sc_mode = WSDISPLAYIO_MODE_EMUL; + if (sc->sc_modecb->gmc_setmode) + sc->sc_modecb->gmc_setmode(sc, sc->sc_mode); #ifdef GENFB_SHADOWFB sc->sc_shadowfb = kmem_alloc(sc->sc_fbsize, KM_SLEEP); @@ -377,6 +386,9 @@ if (new_mode != sc->sc_mode) { sc->sc_mode = new_mode; + if (sc->sc_modecb->gmc_setmode) + sc->sc_modecb->gmc_setmode(sc, + sc->sc_mode); if (new_mode == WSDISPLAYIO_MODE_EMUL) { genfb_restore_palette(sc); vcons_redraw_screen(ms); Index: src/sys/dev/wsfb/genfbvar.h diff -u src/sys/dev/wsfb/genfbvar.h:1.17 src/sys/dev/wsfb/genfbvar.h:1.18 --- src/sys/dev/wsfb/genfbvar.h:1.17 Thu Oct 7 07:53:53 2010 +++ src/sys/dev/wsfb/genfbvar.h Tue Feb 8 10:52:56 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: genfbvar.h,v 1.17 2010/10/07 07:53:53 macallan Exp $ */ +/* $NetBSD: genfbvar.h,v 1.18 2011/02/08 10:52:56 jmcneill Exp $ */ /*- * Copyright (c) 2007 Michael Lorenz @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: genfbvar.h,v 1.17 2010/10/07 07:53:53 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: genfbvar.h,v 1.18 2011/02/08 10:52:56 jmcneill Exp $"); #ifndef GENFBVAR_H #define GENFBVAR_H @@ -51,10 +51,10 @@ #ifdef SPLASHSCREEN #define GENFB_DISABLE_TEXT #include <dev/splash/splash.h> -/* XXX */ -extern const char _splash_header_data_cmap[64+32][3]; #endif +struct genfb_softc; + struct genfb_ops { int (*genfb_ioctl)(void *, void *, u_long, void *, int, struct lwp *); paddr_t (*genfb_mmap)(void *, void *, off_t, int); @@ -77,6 +77,10 @@ bool (*gpc_resume)(device_t, const pmf_qual_t *); }; +struct genfb_mode_callback { + bool (*gmc_setmode)(struct genfb_softc *, int); +}; + struct genfb_softc { device_t sc_dev; struct vcons_data vd; @@ -88,6 +92,7 @@ struct genfb_colormap_callback *sc_cmcb; struct genfb_pmf_callback *sc_pmfcb; struct genfb_parameter_callback *sc_backlight; + struct genfb_mode_callback *sc_modecb; int sc_backlight_level, sc_backlight_on; void *sc_fbaddr; /* kva */ #ifdef GENFB_SHADOWFB @@ -103,9 +108,6 @@ bool sc_want_clear; #ifdef SPLASHSCREEN struct splash_info sc_splash; -#ifdef SPLASHSCREEN_PROGRESS - struct splash_progress sc_progress; -#endif #endif };