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