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.13 2006/10/25 20:55:51 dillon 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 device_t bus; 110 int error; 111 112 /* No pnp support */ 113 if (isa_get_vendorid(dev)) 114 return (ENXIO); 115 116 device_set_desc(dev, "Generic ISA VGA"); 117 error = vga_probe_unit(device_get_unit(dev), &adp, device_get_flags(dev)); 118 if (error == 0) { 119 bus = device_get_parent(dev); 120 bus_set_resource(dev, SYS_RES_IOPORT, 0, 121 adp.va_io_base, adp.va_io_size); 122 bus_set_resource(dev, SYS_RES_MEMORY, 0, 123 adp.va_mem_base, adp.va_mem_size); 124 #if 0 125 isa_set_port(dev, adp.va_io_base); 126 isa_set_portsize(dev, adp.va_io_size); 127 isa_set_maddr(dev, adp.va_mem_base); 128 isa_set_msize(dev, adp.va_mem_size); 129 #endif 130 } 131 return error; 132 } 133 134 static int 135 isavga_attach(device_t dev) 136 { 137 vga_softc_t *sc; 138 struct resource *port; 139 struct resource *mem; 140 int unit; 141 int rid; 142 int error; 143 144 unit = device_get_unit(dev); 145 sc = device_get_softc(dev); 146 147 rid = 0; 148 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 149 0, ~0, 0, RF_ACTIVE | RF_SHAREABLE); 150 rid = 0; 151 mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 152 0, ~0, 0, RF_ACTIVE | RF_SHAREABLE); 153 154 error = vga_attach_unit(unit, sc, device_get_flags(dev)); 155 if (error) 156 return error; 157 158 #ifdef FB_INSTALL_CDEV 159 /* attach a virtual frame buffer device */ 160 dev_ops_add(&isavga_ops, VGA_MKMINOR(-1), VGA_MKMINOR(unit)); 161 sc->devt = make_dev(&isavga_ops, VGA_MKMINOR(unit), 0, 0, 02660, "vga%x", VGA_MKMINOR(unit)); 162 reference_dev(sc->devt); 163 error = fb_attach(sc->devt, sc->adp); 164 if (error) 165 return error; 166 #endif /* FB_INSTALL_CDEV */ 167 168 if (bootverbose) 169 (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose); 170 171 #if experimental 172 device_add_child(dev, "fb", -1); 173 bus_generic_attach(dev); 174 #endif 175 176 return 0; 177 } 178 179 static int 180 isavga_suspend(device_t dev) 181 { 182 vga_softc_t *sc; 183 int err, nbytes; 184 185 sc = device_get_softc(dev); 186 err = bus_generic_suspend(dev); 187 if (err) 188 return (err); 189 190 /* Save the video state across the suspend. */ 191 if (sc->state_buf != NULL) { 192 kfree(sc->state_buf, M_TEMP); 193 sc->state_buf = NULL; 194 } 195 nbytes = (*vidsw[sc->adp->va_index]->save_state)(sc->adp, NULL, 0); 196 if (nbytes <= 0) 197 return (0); 198 sc->state_buf = kmalloc(nbytes, M_TEMP, M_NOWAIT | M_ZERO); 199 if (sc->state_buf == NULL) 200 return (0); 201 if (bootverbose) 202 device_printf(dev, "saving %d bytes of video state\n", nbytes); 203 if ((*vidsw[sc->adp->va_index]->save_state)(sc->adp, sc->state_buf, 204 nbytes) != 0) { 205 device_printf(dev, "failed to save state (nbytes=%d)\n", 206 nbytes); 207 kfree(sc->state_buf, M_TEMP); 208 sc->state_buf = NULL; 209 } 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