1 /*- 2 * (MPSAFE) 3 * 4 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer as 12 * the first lines of this file unmodified. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD: src/sys/isa/vga_isa.c,v 1.17 2000/01/29 15:08:56 peter Exp $ 29 * $DragonFly: src/sys/bus/isa/vga_isa.c,v 1.14 2008/03/20 21:25:30 swildner Exp $ 30 */ 31 32 #include "opt_vga.h" 33 #include "opt_fb.h" 34 #include "opt_syscons.h" /* should be removed in the future, XXX */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/malloc.h> 40 #include <sys/conf.h> 41 #include <sys/device.h> 42 #include <sys/bus.h> 43 #include <sys/fbio.h> 44 #include <sys/rman.h> 45 #include <sys/thread.h> 46 47 #include <vm/vm.h> 48 #include <vm/pmap.h> 49 50 #include <machine/md_var.h> 51 #include <machine/pc/bios.h> 52 53 #include <dev/video/fb/fbreg.h> 54 #include <dev/video/fb/vgareg.h> 55 56 #include "isareg.h" 57 #include "isavar.h" 58 59 #define VGA_SOFTC(unit) \ 60 ((vga_softc_t *)devclass_get_softc(isavga_devclass, unit)) 61 62 static devclass_t isavga_devclass; 63 64 static int isavga_probe(device_t dev); 65 static int isavga_attach(device_t dev); 66 static int isavga_suspend(device_t dev); 67 static int isavga_resume(device_t dev); 68 69 static device_method_t isavga_methods[] = { 70 DEVMETHOD(device_probe, isavga_probe), 71 DEVMETHOD(device_attach, isavga_attach), 72 DEVMETHOD(device_suspend, isavga_suspend), 73 DEVMETHOD(device_resume, isavga_resume), 74 75 DEVMETHOD(bus_print_child, bus_generic_print_child), 76 { 0, 0 } 77 }; 78 79 static driver_t isavga_driver = { 80 VGA_DRIVER_NAME, 81 isavga_methods, 82 sizeof(vga_softc_t), 83 }; 84 85 DRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0); 86 87 #ifdef FB_INSTALL_CDEV 88 89 static d_open_t isavga_open; 90 static d_close_t isavga_close; 91 static d_read_t isavga_read; 92 static d_write_t isavga_write; 93 static d_ioctl_t isavga_ioctl; 94 static d_mmap_t isavga_mmap; 95 96 static struct dev_ops isavga_ops = { 97 { VGA_DRIVER_NAME, -1, 0 }, 98 .d_open = isavga_open, 99 .d_close = isavga_close, 100 .d_read = isavga_read, 101 .d_write = isavga_write, 102 .d_ioctl = isavga_ioctl, 103 .d_mmap = isavga_mmap, 104 }; 105 106 #endif /* FB_INSTALL_CDEV */ 107 108 static int 109 isavga_probe(device_t dev) 110 { 111 video_adapter_t adp; 112 int error; 113 114 /* No pnp support */ 115 if (isa_get_vendorid(dev)) 116 return (ENXIO); 117 118 device_set_desc(dev, "Generic ISA VGA"); 119 error = vga_probe_unit(device_get_unit(dev), &adp, device_get_flags(dev)); 120 if (error == 0) { 121 bus_set_resource(dev, SYS_RES_IOPORT, 0, 122 adp.va_io_base, adp.va_io_size); 123 bus_set_resource(dev, SYS_RES_MEMORY, 0, 124 adp.va_mem_base, adp.va_mem_size); 125 #if 0 126 isa_set_port(dev, adp.va_io_base); 127 isa_set_portsize(dev, adp.va_io_size); 128 isa_set_maddr(dev, adp.va_mem_base); 129 isa_set_msize(dev, adp.va_mem_size); 130 #endif 131 } 132 return error; 133 } 134 135 static int 136 isavga_attach(device_t dev) 137 { 138 vga_softc_t *sc; 139 int unit; 140 int rid; 141 int error; 142 143 unit = device_get_unit(dev); 144 sc = device_get_softc(dev); 145 146 rid = 0; 147 bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 148 0, ~0, 0, RF_ACTIVE | RF_SHAREABLE); 149 rid = 0; 150 bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 151 0, ~0, 0, RF_ACTIVE | RF_SHAREABLE); 152 153 error = vga_attach_unit(unit, sc, device_get_flags(dev)); 154 if (error) 155 return error; 156 157 #ifdef FB_INSTALL_CDEV 158 /* attach a virtual frame buffer device */ 159 sc->devt = make_dev(&isavga_ops, VGA_MKMINOR(unit), 0, 0, 02660, "vga%x", VGA_MKMINOR(unit)); 160 reference_dev(sc->devt); 161 error = fb_attach(sc->devt, sc->adp); 162 if (error) 163 return error; 164 #endif /* FB_INSTALL_CDEV */ 165 166 if (bootverbose) 167 (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose); 168 169 #if experimental 170 device_add_child(dev, "fb", -1); 171 bus_generic_attach(dev); 172 #endif 173 174 return 0; 175 } 176 177 static int 178 isavga_suspend(device_t dev) 179 { 180 vga_softc_t *sc; 181 int err, nbytes; 182 183 sc = device_get_softc(dev); 184 err = bus_generic_suspend(dev); 185 if (err) 186 return (err); 187 188 /* Save the video state across the suspend. */ 189 if (sc->state_buf != NULL) { 190 kfree(sc->state_buf, M_TEMP); 191 sc->state_buf = NULL; 192 } 193 nbytes = (*vidsw[sc->adp->va_index]->save_state)(sc->adp, NULL, 0); 194 if (nbytes <= 0) 195 return (0); 196 sc->state_buf = kmalloc(nbytes, M_TEMP, M_NOWAIT | M_ZERO); 197 if (sc->state_buf == NULL) 198 return (0); 199 if (bootverbose) 200 device_printf(dev, "saving %d bytes of video state\n", nbytes); 201 lwkt_gettoken(&tty_token); 202 if ((*vidsw[sc->adp->va_index]->save_state)(sc->adp, sc->state_buf, 203 nbytes) != 0) { 204 device_printf(dev, "failed to save state (nbytes=%d)\n", 205 nbytes); 206 kfree(sc->state_buf, M_TEMP); 207 sc->state_buf = NULL; 208 } 209 lwkt_reltoken(&tty_token); 210 return (0); 211 } 212 213 static int 214 isavga_resume(device_t dev) 215 { 216 vga_softc_t *sc; 217 218 sc = device_get_softc(dev); 219 if (sc->state_buf != NULL) { 220 if ((*vidsw[sc->adp->va_index]->load_state)(sc->adp, 221 sc->state_buf) != 0) 222 device_printf(dev, "failed to reload state\n"); 223 kfree(sc->state_buf, M_TEMP); 224 sc->state_buf = NULL; 225 } 226 227 bus_generic_resume(dev); 228 return 0; 229 } 230 231 #ifdef FB_INSTALL_CDEV 232 233 static int 234 isavga_open(struct dev_open_args *ap) 235 { 236 cdev_t dev = ap->a_head.a_dev; 237 238 return vga_open(dev, VGA_SOFTC(VGA_UNIT(dev)), ap->a_oflags, 239 ap->a_devtype, ap->a_cred); 240 } 241 242 static int 243 isavga_close(struct dev_close_args *ap) 244 { 245 cdev_t dev = ap->a_head.a_dev; 246 247 return vga_close(dev, VGA_SOFTC(VGA_UNIT(dev)), 248 ap->a_fflag, ap->a_devtype); 249 } 250 251 static int 252 isavga_read(struct dev_read_args *ap) 253 { 254 cdev_t dev = ap->a_head.a_dev; 255 256 return vga_read(dev, VGA_SOFTC(VGA_UNIT(dev)), ap->a_uio, ap->a_ioflag); 257 } 258 259 static int 260 isavga_write(struct dev_write_args *ap) 261 { 262 cdev_t dev = ap->a_head.a_dev; 263 264 return vga_write(dev, VGA_SOFTC(VGA_UNIT(dev)), ap->a_uio, ap->a_ioflag); 265 } 266 267 static int 268 isavga_ioctl(struct dev_ioctl_args *ap) 269 { 270 cdev_t dev = ap->a_head.a_dev; 271 272 return vga_ioctl(dev, VGA_SOFTC(VGA_UNIT(dev)), ap->a_cmd, ap->a_data, ap->a_fflag, ap->a_cred); 273 } 274 275 static int 276 isavga_mmap(struct dev_mmap_args *ap) 277 { 278 cdev_t dev = ap->a_head.a_dev; 279 280 ap->a_result = vga_mmap(dev, VGA_SOFTC(VGA_UNIT(dev)), ap->a_offset, ap->a_nprot); 281 return(0); 282 } 283 284 #endif /* FB_INSTALL_CDEV */ 285