18a997770SDoug Rabson /*- 2fe267a55SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3fe267a55SPedro F. Giffuni * 48a997770SDoug Rabson * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 58a997770SDoug Rabson * All rights reserved. 68a997770SDoug Rabson * 78a997770SDoug Rabson * Redistribution and use in source and binary forms, with or without 88a997770SDoug Rabson * modification, are permitted provided that the following conditions 98a997770SDoug Rabson * are met: 108a997770SDoug Rabson * 1. Redistributions of source code must retain the above copyright 118a997770SDoug Rabson * notice, this list of conditions and the following disclaimer as 128a997770SDoug Rabson * the first lines of this file unmodified. 138a997770SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 148a997770SDoug Rabson * notice, this list of conditions and the following disclaimer in the 158a997770SDoug Rabson * documentation and/or other materials provided with the distribution. 168a997770SDoug Rabson * 178a997770SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 188a997770SDoug Rabson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 198a997770SDoug Rabson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 208a997770SDoug Rabson * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 218a997770SDoug Rabson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 228a997770SDoug Rabson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 238a997770SDoug Rabson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 248a997770SDoug Rabson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258a997770SDoug Rabson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 268a997770SDoug Rabson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278a997770SDoug Rabson */ 288a997770SDoug Rabson 298c9bbf48SDavid E. O'Brien #include <sys/cdefs.h> 308c9bbf48SDavid E. O'Brien __FBSDID("$FreeBSD$"); 318c9bbf48SDavid E. O'Brien 328a997770SDoug Rabson #include "opt_vga.h" 338a997770SDoug Rabson #include "opt_fb.h" 348a997770SDoug Rabson #include "opt_syscons.h" /* should be removed in the future, XXX */ 358a997770SDoug Rabson 368a997770SDoug Rabson #include <sys/param.h> 378a997770SDoug Rabson #include <sys/systm.h> 388a997770SDoug Rabson #include <sys/kernel.h> 39528433baSIan Dowse #include <sys/malloc.h> 405dba30f1SPoul-Henning Kamp #include <sys/module.h> 416e8394b8SKazutaka YOKOTA #include <sys/conf.h> 428a997770SDoug Rabson #include <sys/bus.h> 436e8394b8SKazutaka YOKOTA #include <sys/fbio.h> 446e8394b8SKazutaka YOKOTA 456e8394b8SKazutaka YOKOTA #include <machine/bus.h> 466e8394b8SKazutaka YOKOTA #include <machine/resource.h> 476e8394b8SKazutaka YOKOTA 486e8394b8SKazutaka YOKOTA #include <sys/rman.h> 498a997770SDoug Rabson 508a997770SDoug Rabson #include <vm/vm.h> 518a997770SDoug Rabson #include <vm/pmap.h> 528a997770SDoug Rabson 538a997770SDoug Rabson #include <machine/md_var.h> 5433a9fd01SPeter Wemm #ifdef __i386__ 558a997770SDoug Rabson #include <machine/pc/bios.h> 5633a9fd01SPeter Wemm #endif 578a997770SDoug Rabson 588a997770SDoug Rabson #include <dev/fb/fbreg.h> 598a997770SDoug Rabson #include <dev/fb/vgareg.h> 608a997770SDoug Rabson 618a997770SDoug Rabson #include <isa/isareg.h> 628a997770SDoug Rabson #include <isa/isavar.h> 638a997770SDoug Rabson 64d6b66397SWarner Losh #define VGA_ID 0x0009d041 /* PNP0900 */ 65d6b66397SWarner Losh 66d6b66397SWarner Losh static struct isa_pnp_id vga_ids[] = { 67d6b66397SWarner Losh { VGA_ID, NULL }, /* PNP0900 */ 68d6b66397SWarner Losh { 0, NULL }, 69d6b66397SWarner Losh }; 70d6b66397SWarner Losh 71bf71c25fSJung-uk Kim static void 72bf71c25fSJung-uk Kim vga_suspend(device_t dev) 73bf71c25fSJung-uk Kim { 74bf71c25fSJung-uk Kim vga_softc_t *sc; 75bf71c25fSJung-uk Kim int nbytes; 76bf71c25fSJung-uk Kim 77bf71c25fSJung-uk Kim sc = device_get_softc(dev); 78bf71c25fSJung-uk Kim 79bf71c25fSJung-uk Kim /* Save the video state across the suspend. */ 80bf71c25fSJung-uk Kim if (sc->state_buf != NULL) 81bf71c25fSJung-uk Kim goto save_palette; 82bf71c25fSJung-uk Kim nbytes = vidd_save_state(sc->adp, NULL, 0); 83bf71c25fSJung-uk Kim if (nbytes <= 0) 84bf71c25fSJung-uk Kim goto save_palette; 85bf71c25fSJung-uk Kim sc->state_buf = malloc(nbytes, M_TEMP, M_NOWAIT); 86bf71c25fSJung-uk Kim if (sc->state_buf == NULL) 87bf71c25fSJung-uk Kim goto save_palette; 88bf71c25fSJung-uk Kim if (bootverbose) 89bf71c25fSJung-uk Kim device_printf(dev, "saving %d bytes of video state\n", nbytes); 90bf71c25fSJung-uk Kim if (vidd_save_state(sc->adp, sc->state_buf, nbytes) != 0) { 91bf71c25fSJung-uk Kim device_printf(dev, "failed to save state (nbytes=%d)\n", 92bf71c25fSJung-uk Kim nbytes); 93bf71c25fSJung-uk Kim free(sc->state_buf, M_TEMP); 94bf71c25fSJung-uk Kim sc->state_buf = NULL; 95bf71c25fSJung-uk Kim } 96bf71c25fSJung-uk Kim 97bf71c25fSJung-uk Kim save_palette: 98bf71c25fSJung-uk Kim /* Save the color palette across the suspend. */ 99bf71c25fSJung-uk Kim if (sc->pal_buf != NULL) 100bf71c25fSJung-uk Kim return; 101bf71c25fSJung-uk Kim sc->pal_buf = malloc(256 * 3, M_TEMP, M_NOWAIT); 102bf71c25fSJung-uk Kim if (sc->pal_buf == NULL) 103bf71c25fSJung-uk Kim return; 104bf71c25fSJung-uk Kim if (bootverbose) 105bf71c25fSJung-uk Kim device_printf(dev, "saving color palette\n"); 106bf71c25fSJung-uk Kim if (vidd_save_palette(sc->adp, sc->pal_buf) != 0) { 107bf71c25fSJung-uk Kim device_printf(dev, "failed to save palette\n"); 108bf71c25fSJung-uk Kim free(sc->pal_buf, M_TEMP); 109bf71c25fSJung-uk Kim sc->pal_buf = NULL; 110bf71c25fSJung-uk Kim } 111bf71c25fSJung-uk Kim } 112bf71c25fSJung-uk Kim 113bf71c25fSJung-uk Kim static void 114bf71c25fSJung-uk Kim vga_resume(device_t dev) 115bf71c25fSJung-uk Kim { 116bf71c25fSJung-uk Kim vga_softc_t *sc; 117bf71c25fSJung-uk Kim 118bf71c25fSJung-uk Kim sc = device_get_softc(dev); 119bf71c25fSJung-uk Kim 120bf71c25fSJung-uk Kim if (sc->state_buf != NULL) { 121bf71c25fSJung-uk Kim if (vidd_load_state(sc->adp, sc->state_buf) != 0) 122bf71c25fSJung-uk Kim device_printf(dev, "failed to reload state\n"); 123bf71c25fSJung-uk Kim free(sc->state_buf, M_TEMP); 124bf71c25fSJung-uk Kim sc->state_buf = NULL; 125bf71c25fSJung-uk Kim } 126bf71c25fSJung-uk Kim if (sc->pal_buf != NULL) { 127bf71c25fSJung-uk Kim if (vidd_load_palette(sc->adp, sc->pal_buf) != 0) 128bf71c25fSJung-uk Kim device_printf(dev, "failed to reload palette\n"); 129bf71c25fSJung-uk Kim free(sc->pal_buf, M_TEMP); 130bf71c25fSJung-uk Kim sc->pal_buf = NULL; 131bf71c25fSJung-uk Kim } 132bf71c25fSJung-uk Kim } 133bf71c25fSJung-uk Kim 1346e8394b8SKazutaka YOKOTA static devclass_t isavga_devclass; 1358a997770SDoug Rabson 136c20ac811SPeter Wemm static void 137c20ac811SPeter Wemm isavga_identify(driver_t *driver, device_t parent) 138c20ac811SPeter Wemm { 139c20ac811SPeter Wemm BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, VGA_DRIVER_NAME, 0); 140c20ac811SPeter Wemm } 141c20ac811SPeter Wemm 1428a997770SDoug Rabson static int 1438a997770SDoug Rabson isavga_probe(device_t dev) 1448a997770SDoug Rabson { 1456e8394b8SKazutaka YOKOTA video_adapter_t adp; 1466e8394b8SKazutaka YOKOTA int error; 1478a997770SDoug Rabson 148f7f2df54SDoug Rabson /* No pnp support */ 149f7f2df54SDoug Rabson if (isa_get_vendorid(dev)) 150f7f2df54SDoug Rabson return (ENXIO); 151f7f2df54SDoug Rabson 152062acdb7SDoug Rabson error = vga_probe_unit(device_get_unit(dev), &adp, device_get_flags(dev)); 1536e8394b8SKazutaka YOKOTA if (error == 0) { 154bf71c25fSJung-uk Kim device_set_desc(dev, "Generic ISA VGA"); 15525afb89bSDoug Rabson bus_set_resource(dev, SYS_RES_IOPORT, 0, 1566e8394b8SKazutaka YOKOTA adp.va_io_base, adp.va_io_size); 15725afb89bSDoug Rabson bus_set_resource(dev, SYS_RES_MEMORY, 0, 1586e8394b8SKazutaka YOKOTA adp.va_mem_base, adp.va_mem_size); 159d6b66397SWarner Losh isa_set_vendorid(dev, VGA_ID); 160d6b66397SWarner Losh isa_set_logicalid(dev, VGA_ID); 1616e8394b8SKazutaka YOKOTA #if 0 1626e8394b8SKazutaka YOKOTA isa_set_port(dev, adp.va_io_base); 1636e8394b8SKazutaka YOKOTA isa_set_portsize(dev, adp.va_io_size); 1646e8394b8SKazutaka YOKOTA isa_set_maddr(dev, adp.va_mem_base); 1656e8394b8SKazutaka YOKOTA isa_set_msize(dev, adp.va_mem_size); 1666e8394b8SKazutaka YOKOTA #endif 1676e8394b8SKazutaka YOKOTA } 168b66e2b8eSJung-uk Kim return (error); 1698a997770SDoug Rabson } 1708a997770SDoug Rabson 1718a997770SDoug Rabson static int 1728a997770SDoug Rabson isavga_attach(device_t dev) 1738a997770SDoug Rabson { 1746e8394b8SKazutaka YOKOTA vga_softc_t *sc; 1756e8394b8SKazutaka YOKOTA int unit; 1766e8394b8SKazutaka YOKOTA int rid; 1778a997770SDoug Rabson int error; 1788a997770SDoug Rabson 1796e8394b8SKazutaka YOKOTA unit = device_get_unit(dev); 1806e8394b8SKazutaka YOKOTA sc = device_get_softc(dev); 1818a997770SDoug Rabson 1826e8394b8SKazutaka YOKOTA rid = 0; 18343cd6160SJustin Hibbits bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 18443cd6160SJustin Hibbits RF_ACTIVE | RF_SHAREABLE); 1856e8394b8SKazutaka YOKOTA rid = 0; 18643cd6160SJustin Hibbits bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 18743cd6160SJustin Hibbits RF_ACTIVE | RF_SHAREABLE); 1886e8394b8SKazutaka YOKOTA 189062acdb7SDoug Rabson error = vga_attach_unit(unit, sc, device_get_flags(dev)); 1908a997770SDoug Rabson if (error) 191b66e2b8eSJung-uk Kim return (error); 1928a997770SDoug Rabson 19361eb992fSPoul-Henning Kamp if (0 && bootverbose) 1949336e069SWojciech A. Koszek vidd_diag(sc->adp, bootverbose); 1958a997770SDoug Rabson 196f4e98881SRuslan Ermilov #if 0 /* experimental */ 197fe0d4089SMatthew N. Dodd device_add_child(dev, "fb", -1); 1986e8394b8SKazutaka YOKOTA bus_generic_attach(dev); 1998a997770SDoug Rabson #endif 2008a997770SDoug Rabson 201b66e2b8eSJung-uk Kim return (0); 2028a997770SDoug Rabson } 2038a997770SDoug Rabson 204528433baSIan Dowse static int 205528433baSIan Dowse isavga_suspend(device_t dev) 206528433baSIan Dowse { 207bf71c25fSJung-uk Kim int error; 208528433baSIan Dowse 209bf71c25fSJung-uk Kim error = bus_generic_suspend(dev); 210bf71c25fSJung-uk Kim if (error != 0) 211bf71c25fSJung-uk Kim return (error); 212bf71c25fSJung-uk Kim vga_suspend(dev); 2132259d74cSJung-uk Kim 214bf71c25fSJung-uk Kim return (error); 215528433baSIan Dowse } 216528433baSIan Dowse 217528433baSIan Dowse static int 218528433baSIan Dowse isavga_resume(device_t dev) 219528433baSIan Dowse { 220528433baSIan Dowse 221bf71c25fSJung-uk Kim vga_resume(dev); 2222259d74cSJung-uk Kim 223bf71c25fSJung-uk Kim return (bus_generic_resume(dev)); 224528433baSIan Dowse } 225528433baSIan Dowse 226c20ac811SPeter Wemm static device_method_t isavga_methods[] = { 227c20ac811SPeter Wemm DEVMETHOD(device_identify, isavga_identify), 228c20ac811SPeter Wemm DEVMETHOD(device_probe, isavga_probe), 229c20ac811SPeter Wemm DEVMETHOD(device_attach, isavga_attach), 230528433baSIan Dowse DEVMETHOD(device_suspend, isavga_suspend), 231528433baSIan Dowse DEVMETHOD(device_resume, isavga_resume), 232c20ac811SPeter Wemm 2334b7ec270SMarius Strobl DEVMETHOD_END 234c20ac811SPeter Wemm }; 235c20ac811SPeter Wemm 236c20ac811SPeter Wemm static driver_t isavga_driver = { 237c20ac811SPeter Wemm VGA_DRIVER_NAME, 238c20ac811SPeter Wemm isavga_methods, 239c20ac811SPeter Wemm sizeof(vga_softc_t), 240c20ac811SPeter Wemm }; 241c20ac811SPeter Wemm 242c20ac811SPeter Wemm DRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0); 243bf71c25fSJung-uk Kim 244bf71c25fSJung-uk Kim static devclass_t vgapm_devclass; 245bf71c25fSJung-uk Kim 246bf71c25fSJung-uk Kim static void 247bf71c25fSJung-uk Kim vgapm_identify(driver_t *driver, device_t parent) 248bf71c25fSJung-uk Kim { 249bf71c25fSJung-uk Kim 250bf71c25fSJung-uk Kim if (device_get_flags(parent) != 0) 251bf71c25fSJung-uk Kim device_add_child(parent, "vgapm", 0); 252bf71c25fSJung-uk Kim } 253bf71c25fSJung-uk Kim 254bf71c25fSJung-uk Kim static int 255bf71c25fSJung-uk Kim vgapm_probe(device_t dev) 256bf71c25fSJung-uk Kim { 257bf71c25fSJung-uk Kim 258bf71c25fSJung-uk Kim device_set_desc(dev, "VGA suspend/resume"); 259bf71c25fSJung-uk Kim device_quiet(dev); 260bf71c25fSJung-uk Kim 261bf71c25fSJung-uk Kim return (BUS_PROBE_DEFAULT); 262bf71c25fSJung-uk Kim } 263bf71c25fSJung-uk Kim 264bf71c25fSJung-uk Kim static int 265bf71c25fSJung-uk Kim vgapm_attach(device_t dev) 266bf71c25fSJung-uk Kim { 267bf71c25fSJung-uk Kim 2681ce5efd4SJung-uk Kim bus_generic_probe(dev); 2691ce5efd4SJung-uk Kim bus_generic_attach(dev); 2701ce5efd4SJung-uk Kim 271bf71c25fSJung-uk Kim return (0); 272bf71c25fSJung-uk Kim } 273bf71c25fSJung-uk Kim 274bf71c25fSJung-uk Kim static int 275bf71c25fSJung-uk Kim vgapm_suspend(device_t dev) 276bf71c25fSJung-uk Kim { 277bf71c25fSJung-uk Kim device_t vga_dev; 278bf71c25fSJung-uk Kim int error; 279bf71c25fSJung-uk Kim 280bf71c25fSJung-uk Kim error = bus_generic_suspend(dev); 281bf71c25fSJung-uk Kim if (error != 0) 282bf71c25fSJung-uk Kim return (error); 283c1d90b2dSJohn Baldwin vga_dev = devclass_get_device(devclass_find(VGA_DRIVER_NAME), 0); 284bf71c25fSJung-uk Kim if (vga_dev == NULL) 285bf71c25fSJung-uk Kim return (0); 286bf71c25fSJung-uk Kim vga_suspend(vga_dev); 287bf71c25fSJung-uk Kim 288bf71c25fSJung-uk Kim return (0); 289bf71c25fSJung-uk Kim } 290bf71c25fSJung-uk Kim 291bf71c25fSJung-uk Kim static int 292bf71c25fSJung-uk Kim vgapm_resume(device_t dev) 293bf71c25fSJung-uk Kim { 294bf71c25fSJung-uk Kim device_t vga_dev; 295bf71c25fSJung-uk Kim 296c1d90b2dSJohn Baldwin vga_dev = devclass_get_device(devclass_find(VGA_DRIVER_NAME), 0); 297bf71c25fSJung-uk Kim if (vga_dev != NULL) 298bf71c25fSJung-uk Kim vga_resume(vga_dev); 299bf71c25fSJung-uk Kim 300bf71c25fSJung-uk Kim return (bus_generic_resume(dev)); 301bf71c25fSJung-uk Kim } 302bf71c25fSJung-uk Kim 303bf71c25fSJung-uk Kim static device_method_t vgapm_methods[] = { 304bf71c25fSJung-uk Kim DEVMETHOD(device_identify, vgapm_identify), 305bf71c25fSJung-uk Kim DEVMETHOD(device_probe, vgapm_probe), 306bf71c25fSJung-uk Kim DEVMETHOD(device_attach, vgapm_attach), 307bf71c25fSJung-uk Kim DEVMETHOD(device_suspend, vgapm_suspend), 308bf71c25fSJung-uk Kim DEVMETHOD(device_resume, vgapm_resume), 309bf71c25fSJung-uk Kim { 0, 0 } 310bf71c25fSJung-uk Kim }; 311bf71c25fSJung-uk Kim 312bf71c25fSJung-uk Kim static driver_t vgapm_driver = { 313bf71c25fSJung-uk Kim "vgapm", 314bf71c25fSJung-uk Kim vgapm_methods, 315bf71c25fSJung-uk Kim 0 316bf71c25fSJung-uk Kim }; 317bf71c25fSJung-uk Kim 318bf71c25fSJung-uk Kim DRIVER_MODULE(vgapm, vgapci, vgapm_driver, vgapm_devclass, 0, 0); 319d6b66397SWarner Losh ISA_PNP_INFO(vga_ids); 320