diff options
author | jkim <jkim@FreeBSD.org> | 2009-11-05 22:58:50 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2009-11-05 22:58:50 +0000 |
commit | bc53678aaf2e4a99efcef14a1b53d0ac50403b83 (patch) | |
tree | 04dc58e4b98fb82187ea223ad1ac4b66c38c4c65 /sys/dev/pci/vga_pci.c | |
parent | b7d759e2ccf64c56e17c806c07398a5a7090df00 (diff) | |
download | FreeBSD-src-bc53678aaf2e4a99efcef14a1b53d0ac50403b83.zip FreeBSD-src-bc53678aaf2e4a99efcef14a1b53d0ac50403b83.tar.gz |
Save/restore VGA state from vga_pci.c instead of relying on vga_isa.c.
It was not working because we were saving its state after the device was
powered down. Simplify vesa_load_state() as the culprit is fixed now.
Diffstat (limited to 'sys/dev/pci/vga_pci.c')
-rw-r--r-- | sys/dev/pci/vga_pci.c | 82 |
1 files changed, 80 insertions, 2 deletions
diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c index 1467bbd..07b5ed0 100644 --- a/sys/dev/pci/vga_pci.c +++ b/sys/dev/pci/vga_pci.c @@ -40,12 +40,17 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/bus.h> +#include <sys/fbio.h> #include <sys/kernel.h> +#include <sys/malloc.h> #include <sys/module.h> #include <sys/rman.h> #include <sys/sysctl.h> #include <sys/systm.h> +#include <dev/fb/fbreg.h> +#include <dev/fb/vgareg.h> + #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -63,7 +68,7 @@ SYSCTL_DECL(_hw_pci); int vga_pci_default_unit = -1; TUNABLE_INT("hw.pci.default_vgapci_unit", &vga_pci_default_unit); -SYSCTL_INT(_hw_pci, OID_AUTO, default_vgapci_unit, CTLFLAG_RD, +SYSCTL_INT(_hw_pci, OID_AUTO, default_vgapci_unit, CTLFLAG_RDTUN, &vga_pci_default_unit, -1, "Default VGA-compatible display"); static int @@ -112,13 +117,86 @@ vga_pci_attach(device_t dev) static int vga_pci_suspend(device_t dev) { + vga_softc_t *sc; + devclass_t dc; + int err, nbytes; + + err = bus_generic_suspend(dev); + if (err) + return (err); + + sc = NULL; + if (device_get_unit(dev) == vga_pci_default_unit) { + dc = devclass_find(VGA_DRIVER_NAME); + if (dc != NULL) + sc = devclass_get_softc(dc, 0); + } + if (sc == NULL) + return (0); + + /* Save the video state across the suspend. */ + if (sc->state_buf != NULL) + goto save_palette; + nbytes = vidd_save_state(sc->adp, NULL, 0); + if (nbytes <= 0) + goto save_palette; + sc->state_buf = malloc(nbytes, M_TEMP, M_NOWAIT); + if (sc->state_buf == NULL) + goto save_palette; + if (bootverbose) + device_printf(dev, "saving %d bytes of video state\n", nbytes); + if (vidd_save_state(sc->adp, sc->state_buf, nbytes) != 0) { + device_printf(dev, "failed to save state (nbytes=%d)\n", + nbytes); + free(sc->state_buf, M_TEMP); + sc->state_buf = NULL; + } + +save_palette: + /* Save the color palette across the suspend. */ + if (sc->pal_buf != NULL) + return (0); + sc->pal_buf = malloc(256 * 3, M_TEMP, M_NOWAIT); + if (sc->pal_buf != NULL) { + if (bootverbose) + device_printf(dev, "saving color palette\n"); + if (vidd_save_palette(sc->adp, sc->pal_buf) != 0) { + device_printf(dev, "failed to save palette\n"); + free(sc->pal_buf, M_TEMP); + sc->pal_buf = NULL; + } + } - return (bus_generic_suspend(dev)); + return (0); } static int vga_pci_resume(device_t dev) { + vga_softc_t *sc; + devclass_t dc; + + sc = NULL; + if (device_get_unit(dev) == vga_pci_default_unit) { + dc = devclass_find(VGA_DRIVER_NAME); + if (dc != NULL) + sc = devclass_get_softc(dc, 0); + } + if (sc == NULL) + return (bus_generic_resume(dev)); + + if (sc->state_buf != NULL) { + if (vidd_load_state(sc->adp, sc->state_buf) != 0) + device_printf(dev, "failed to reload state\n"); + free(sc->state_buf, M_TEMP); + sc->state_buf = NULL; + } + if (sc->pal_buf != NULL) { + if (vidd_load_palette(sc->adp, sc->pal_buf) != 0) + device_printf(dev, "failed to reload palette\n"); + free(sc->pal_buf, M_TEMP); + sc->pal_buf = NULL; + } return (bus_generic_resume(dev)); } |