143105Sdfr/*- 243105Sdfr * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 343105Sdfr * All rights reserved. 443105Sdfr * 543105Sdfr * Redistribution and use in source and binary forms, with or without 643105Sdfr * modification, are permitted provided that the following conditions 743105Sdfr * are met: 843105Sdfr * 1. Redistributions of source code must retain the above copyright 943105Sdfr * notice, this list of conditions and the following disclaimer as 1043105Sdfr * the first lines of this file unmodified. 1143105Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1243105Sdfr * notice, this list of conditions and the following disclaimer in the 1343105Sdfr * documentation and/or other materials provided with the distribution. 1443105Sdfr * 1543105Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1643105Sdfr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1743105Sdfr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1843105Sdfr * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 1943105Sdfr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2043105Sdfr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2143105Sdfr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2243105Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2343105Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2443105Sdfr * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2543105Sdfr */ 2643105Sdfr 27116181Sobrien#include <sys/cdefs.h> 28116181Sobrien__FBSDID("$FreeBSD$"); 29116181Sobrien 3043105Sdfr#include "opt_vga.h" 3143105Sdfr#include "opt_fb.h" 3243105Sdfr#include "opt_syscons.h" /* should be removed in the future, XXX */ 3343105Sdfr 3443105Sdfr#include <sys/param.h> 3543105Sdfr#include <sys/systm.h> 3643105Sdfr#include <sys/kernel.h> 37142833Siedowse#include <sys/malloc.h> 38129880Sphk#include <sys/module.h> 3948104Syokota#include <sys/conf.h> 4043105Sdfr#include <sys/bus.h> 4148104Syokota#include <sys/fbio.h> 4243105Sdfr 4348104Syokota#include <machine/bus.h> 4448104Syokota#include <machine/resource.h> 4548104Syokota 4648104Syokota#include <sys/rman.h> 4748104Syokota 4843105Sdfr#include <vm/vm.h> 4943105Sdfr#include <vm/pmap.h> 5043105Sdfr 5143105Sdfr#include <machine/md_var.h> 52114384Speter#ifdef __i386__ 5343105Sdfr#include <machine/pc/bios.h> 54114384Speter#endif 5543105Sdfr 5643105Sdfr#include <dev/fb/fbreg.h> 5743105Sdfr#include <dev/fb/vgareg.h> 5843105Sdfr 5943105Sdfr#include <isa/isareg.h> 6043105Sdfr#include <isa/isavar.h> 6143105Sdfr 62199229Sjkimstatic void 63199229Sjkimvga_suspend(device_t dev) 64199229Sjkim{ 65199229Sjkim vga_softc_t *sc; 66199229Sjkim int nbytes; 67199229Sjkim 68199229Sjkim sc = device_get_softc(dev); 69199229Sjkim 70199229Sjkim /* Save the video state across the suspend. */ 71199229Sjkim if (sc->state_buf != NULL) 72199229Sjkim goto save_palette; 73199229Sjkim nbytes = vidd_save_state(sc->adp, NULL, 0); 74199229Sjkim if (nbytes <= 0) 75199229Sjkim goto save_palette; 76199229Sjkim sc->state_buf = malloc(nbytes, M_TEMP, M_NOWAIT); 77199229Sjkim if (sc->state_buf == NULL) 78199229Sjkim goto save_palette; 79199229Sjkim if (bootverbose) 80199229Sjkim device_printf(dev, "saving %d bytes of video state\n", nbytes); 81199229Sjkim if (vidd_save_state(sc->adp, sc->state_buf, nbytes) != 0) { 82199229Sjkim device_printf(dev, "failed to save state (nbytes=%d)\n", 83199229Sjkim nbytes); 84199229Sjkim free(sc->state_buf, M_TEMP); 85199229Sjkim sc->state_buf = NULL; 86199229Sjkim } 87199229Sjkim 88199229Sjkimsave_palette: 89199229Sjkim /* Save the color palette across the suspend. */ 90199229Sjkim if (sc->pal_buf != NULL) 91199229Sjkim return; 92199229Sjkim sc->pal_buf = malloc(256 * 3, M_TEMP, M_NOWAIT); 93199229Sjkim if (sc->pal_buf == NULL) 94199229Sjkim return; 95199229Sjkim if (bootverbose) 96199229Sjkim device_printf(dev, "saving color palette\n"); 97199229Sjkim if (vidd_save_palette(sc->adp, sc->pal_buf) != 0) { 98199229Sjkim device_printf(dev, "failed to save palette\n"); 99199229Sjkim free(sc->pal_buf, M_TEMP); 100199229Sjkim sc->pal_buf = NULL; 101199229Sjkim } 102199229Sjkim} 103199229Sjkim 104199229Sjkimstatic void 105199229Sjkimvga_resume(device_t dev) 106199229Sjkim{ 107199229Sjkim vga_softc_t *sc; 108199229Sjkim 109199229Sjkim sc = device_get_softc(dev); 110199229Sjkim 111199229Sjkim if (sc->state_buf != NULL) { 112199229Sjkim if (vidd_load_state(sc->adp, sc->state_buf) != 0) 113199229Sjkim device_printf(dev, "failed to reload state\n"); 114199229Sjkim free(sc->state_buf, M_TEMP); 115199229Sjkim sc->state_buf = NULL; 116199229Sjkim } 117199229Sjkim if (sc->pal_buf != NULL) { 118199229Sjkim if (vidd_load_palette(sc->adp, sc->pal_buf) != 0) 119199229Sjkim device_printf(dev, "failed to reload palette\n"); 120199229Sjkim free(sc->pal_buf, M_TEMP); 121199229Sjkim sc->pal_buf = NULL; 122199229Sjkim } 123199229Sjkim} 124199229Sjkim 12548104Syokota#define VGA_SOFTC(unit) \ 12648104Syokota ((vga_softc_t *)devclass_get_softc(isavga_devclass, unit)) 12743105Sdfr 12848104Syokotastatic devclass_t isavga_devclass; 12943105Sdfr 13043105Sdfr#ifdef FB_INSTALL_CDEV 13143105Sdfr 13248104Syokotastatic d_open_t isavga_open; 13348104Syokotastatic d_close_t isavga_close; 13448104Syokotastatic d_read_t isavga_read; 13548104Syokotastatic d_write_t isavga_write; 13648104Syokotastatic d_ioctl_t isavga_ioctl; 13748104Syokotastatic d_mmap_t isavga_mmap; 13843105Sdfr 13948104Syokotastatic struct cdevsw isavga_cdevsw = { 140126080Sphk .d_version = D_VERSION, 141126080Sphk .d_flags = D_NEEDGIANT, 142111815Sphk .d_open = isavga_open, 143111815Sphk .d_close = isavga_close, 144111815Sphk .d_read = isavga_read, 145111815Sphk .d_write = isavga_write, 146111815Sphk .d_ioctl = isavga_ioctl, 147111815Sphk .d_mmap = isavga_mmap, 148111815Sphk .d_name = VGA_DRIVER_NAME, 14943105Sdfr}; 15043105Sdfr 15143105Sdfr#endif /* FB_INSTALL_CDEV */ 15243105Sdfr 15362225Speterstatic void 15462225Speterisavga_identify(driver_t *driver, device_t parent) 15562225Speter{ 15662225Speter BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, VGA_DRIVER_NAME, 0); 15762225Speter} 15862225Speter 15943105Sdfrstatic int 16043105Sdfrisavga_probe(device_t dev) 16143105Sdfr{ 16248104Syokota video_adapter_t adp; 16348104Syokota int error; 16443105Sdfr 16547618Sdfr /* No pnp support */ 16647618Sdfr if (isa_get_vendorid(dev)) 16747618Sdfr return (ENXIO); 16847618Sdfr 16951052Sdfr error = vga_probe_unit(device_get_unit(dev), &adp, device_get_flags(dev)); 17048104Syokota if (error == 0) { 171199229Sjkim device_set_desc(dev, "Generic ISA VGA"); 17252174Sdfr bus_set_resource(dev, SYS_RES_IOPORT, 0, 17348104Syokota adp.va_io_base, adp.va_io_size); 17452174Sdfr bus_set_resource(dev, SYS_RES_MEMORY, 0, 17548104Syokota adp.va_mem_base, adp.va_mem_size); 17648104Syokota#if 0 17748104Syokota isa_set_port(dev, adp.va_io_base); 17848104Syokota isa_set_portsize(dev, adp.va_io_size); 17948104Syokota isa_set_maddr(dev, adp.va_mem_base); 18048104Syokota isa_set_msize(dev, adp.va_mem_size); 18148104Syokota#endif 18248104Syokota } 183199002Sjkim return (error); 18443105Sdfr} 18543105Sdfr 18643105Sdfrstatic int 18743105Sdfrisavga_attach(device_t dev) 18843105Sdfr{ 18948104Syokota vga_softc_t *sc; 19048104Syokota int unit; 19148104Syokota int rid; 19248104Syokota int error; 19343105Sdfr 19448104Syokota unit = device_get_unit(dev); 19543105Sdfr sc = device_get_softc(dev); 19643105Sdfr 19748104Syokota rid = 0; 198295790Sjhibbits bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 199295790Sjhibbits RF_ACTIVE | RF_SHAREABLE); 20048104Syokota rid = 0; 201295790Sjhibbits bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 202295790Sjhibbits RF_ACTIVE | RF_SHAREABLE); 20343105Sdfr 20451052Sdfr error = vga_attach_unit(unit, sc, device_get_flags(dev)); 20543105Sdfr if (error) 206199002Sjkim return (error); 20743105Sdfr 20843105Sdfr#ifdef FB_INSTALL_CDEV 20943105Sdfr /* attach a virtual frame buffer device */ 210120465Sphk error = fb_attach(VGA_MKMINOR(unit), sc->adp, &isavga_cdevsw); 21143105Sdfr if (error) 212199002Sjkim return (error); 21343105Sdfr#endif /* FB_INSTALL_CDEV */ 21443105Sdfr 215137148Sphk if (0 && bootverbose) 216174985Swkoszek vidd_diag(sc->adp, bootverbose); 21743105Sdfr 218153072Sru#if 0 /* experimental */ 21954073Smdodd device_add_child(dev, "fb", -1); 22048104Syokota bus_generic_attach(dev); 22143105Sdfr#endif 22243105Sdfr 223199002Sjkim return (0); 22443105Sdfr} 22543105Sdfr 226142833Siedowsestatic int 227142833Siedowseisavga_suspend(device_t dev) 228142833Siedowse{ 229199229Sjkim int error; 230142833Siedowse 231199229Sjkim error = bus_generic_suspend(dev); 232199229Sjkim if (error != 0) 233199229Sjkim return (error); 234199229Sjkim vga_suspend(dev); 235142833Siedowse 236199229Sjkim return (error); 237142833Siedowse} 238142833Siedowse 239142833Siedowsestatic int 240142833Siedowseisavga_resume(device_t dev) 241142833Siedowse{ 242142833Siedowse 243199229Sjkim vga_resume(dev); 244198964Sjkim 245199229Sjkim return (bus_generic_resume(dev)); 246142833Siedowse} 247142833Siedowse 24848104Syokota#ifdef FB_INSTALL_CDEV 24943105Sdfr 25043105Sdfrstatic int 251130585Sphkisavga_open(struct cdev *dev, int flag, int mode, struct thread *td) 25243105Sdfr{ 253199002Sjkim return (vga_open(dev, VGA_SOFTC(VGA_UNIT(dev)), flag, mode, td)); 25443105Sdfr} 25543105Sdfr 25643105Sdfrstatic int 257130585Sphkisavga_close(struct cdev *dev, int flag, int mode, struct thread *td) 25843105Sdfr{ 259199002Sjkim return (vga_close(dev, VGA_SOFTC(VGA_UNIT(dev)), flag, mode, td)); 26043105Sdfr} 26143105Sdfr 26243105Sdfrstatic int 263130585Sphkisavga_read(struct cdev *dev, struct uio *uio, int flag) 26443105Sdfr{ 265199002Sjkim return (vga_read(dev, VGA_SOFTC(VGA_UNIT(dev)), uio, flag)); 26643105Sdfr} 26743105Sdfr 26843105Sdfrstatic int 269130585Sphkisavga_write(struct cdev *dev, struct uio *uio, int flag) 27043105Sdfr{ 271199002Sjkim return (vga_write(dev, VGA_SOFTC(VGA_UNIT(dev)), uio, flag)); 27243105Sdfr} 27343105Sdfr 27443105Sdfrstatic int 275130585Sphkisavga_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) 27643105Sdfr{ 277199002Sjkim return (vga_ioctl(dev, VGA_SOFTC(VGA_UNIT(dev)), cmd, arg, flag, td)); 27843105Sdfr} 27943105Sdfr 28043105Sdfrstatic int 281201223Srnolandisavga_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, 282201223Srnoland int prot, vm_memattr_t *memattr) 28343105Sdfr{ 284201223Srnoland return (vga_mmap(dev, VGA_SOFTC(VGA_UNIT(dev)), offset, paddr, prot, 285201223Srnoland memattr)); 28643105Sdfr} 28743105Sdfr 28848104Syokota#endif /* FB_INSTALL_CDEV */ 28962225Speter 29062225Speterstatic device_method_t isavga_methods[] = { 29162225Speter DEVMETHOD(device_identify, isavga_identify), 29262225Speter DEVMETHOD(device_probe, isavga_probe), 29362225Speter DEVMETHOD(device_attach, isavga_attach), 294142833Siedowse DEVMETHOD(device_suspend, isavga_suspend), 295142833Siedowse DEVMETHOD(device_resume, isavga_resume), 29662225Speter 297227843Smarius DEVMETHOD_END 29862225Speter}; 29962225Speter 30062225Speterstatic driver_t isavga_driver = { 30162225Speter VGA_DRIVER_NAME, 30262225Speter isavga_methods, 30362225Speter sizeof(vga_softc_t), 30462225Speter}; 30562225Speter 30662225SpeterDRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0); 307199229Sjkim 308199229Sjkimstatic devclass_t vgapm_devclass; 309199229Sjkim 310199229Sjkimstatic void 311199229Sjkimvgapm_identify(driver_t *driver, device_t parent) 312199229Sjkim{ 313199229Sjkim 314199229Sjkim if (device_get_flags(parent) != 0) 315199229Sjkim device_add_child(parent, "vgapm", 0); 316199229Sjkim} 317199229Sjkim 318199229Sjkimstatic int 319199229Sjkimvgapm_probe(device_t dev) 320199229Sjkim{ 321199229Sjkim 322199229Sjkim device_set_desc(dev, "VGA suspend/resume"); 323199229Sjkim device_quiet(dev); 324199229Sjkim 325199229Sjkim return (BUS_PROBE_DEFAULT); 326199229Sjkim} 327199229Sjkim 328199229Sjkimstatic int 329199229Sjkimvgapm_attach(device_t dev) 330199229Sjkim{ 331199229Sjkim 332200584Sjkim bus_generic_probe(dev); 333200584Sjkim bus_generic_attach(dev); 334200584Sjkim 335199229Sjkim return (0); 336199229Sjkim} 337199229Sjkim 338199229Sjkimstatic int 339199229Sjkimvgapm_suspend(device_t dev) 340199229Sjkim{ 341199229Sjkim device_t vga_dev; 342199229Sjkim int error; 343199229Sjkim 344199229Sjkim error = bus_generic_suspend(dev); 345199229Sjkim if (error != 0) 346199229Sjkim return (error); 347199229Sjkim vga_dev = devclass_get_device(isavga_devclass, 0); 348199229Sjkim if (vga_dev == NULL) 349199229Sjkim return (0); 350199229Sjkim vga_suspend(vga_dev); 351199229Sjkim 352199229Sjkim return (0); 353199229Sjkim} 354199229Sjkim 355199229Sjkimstatic int 356199229Sjkimvgapm_resume(device_t dev) 357199229Sjkim{ 358199229Sjkim device_t vga_dev; 359199229Sjkim 360199229Sjkim vga_dev = devclass_get_device(isavga_devclass, 0); 361199229Sjkim if (vga_dev != NULL) 362199229Sjkim vga_resume(vga_dev); 363199229Sjkim 364199229Sjkim return (bus_generic_resume(dev)); 365199229Sjkim} 366199229Sjkim 367199229Sjkimstatic device_method_t vgapm_methods[] = { 368199229Sjkim DEVMETHOD(device_identify, vgapm_identify), 369199229Sjkim DEVMETHOD(device_probe, vgapm_probe), 370199229Sjkim DEVMETHOD(device_attach, vgapm_attach), 371199229Sjkim DEVMETHOD(device_suspend, vgapm_suspend), 372199229Sjkim DEVMETHOD(device_resume, vgapm_resume), 373199229Sjkim { 0, 0 } 374199229Sjkim}; 375199229Sjkim 376199229Sjkimstatic driver_t vgapm_driver = { 377199229Sjkim "vgapm", 378199229Sjkim vgapm_methods, 379199229Sjkim 0 380199229Sjkim}; 381199229Sjkim 382199229SjkimDRIVER_MODULE(vgapm, vgapci, vgapm_driver, vgapm_devclass, 0, 0); 383