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 */ 30 31 #include "opt_vga.h" 32 #include "opt_fb.h" 33 #include "opt_syscons.h" /* should be removed in the future, XXX */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/malloc.h> 39 #include <sys/conf.h> 40 #include <sys/device.h> 41 #include <sys/bus.h> 42 #include <sys/fbio.h> 43 #include <sys/rman.h> 44 #include <sys/thread.h> 45 46 #include <vm/vm.h> 47 #include <vm/pmap.h> 48 49 #include <machine/md_var.h> 50 #include <machine/pc/bios.h> 51 52 #include <dev/video/fb/fbreg.h> 53 #include <dev/video/fb/vgareg.h> 54 55 #include "isareg.h" 56 #include "isavar.h" 57 58 #define VGA_SOFTC(unit) \ 59 ((vga_softc_t *)devclass_get_softc(isavga_devclass, unit)) 60 61 static devclass_t isavga_devclass; 62 63 static int isavga_probe(device_t dev); 64 static int isavga_attach(device_t dev); 65 static int isavga_suspend(device_t dev); 66 static int isavga_resume(device_t dev); 67 68 static device_method_t isavga_methods[] = { 69 DEVMETHOD(device_probe, isavga_probe), 70 DEVMETHOD(device_attach, isavga_attach), 71 DEVMETHOD(device_suspend, isavga_suspend), 72 DEVMETHOD(device_resume, isavga_resume), 73 74 DEVMETHOD(bus_print_child, bus_generic_print_child), 75 { 0, 0 } 76 }; 77 78 static driver_t isavga_driver = { 79 VGA_DRIVER_NAME, 80 isavga_methods, 81 sizeof(vga_softc_t), 82 }; 83 84 DRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, NULL, NULL); 85 86 #ifdef FB_INSTALL_CDEV 87 88 static d_open_t isavga_open; 89 static d_close_t isavga_close; 90 static d_read_t isavga_read; 91 static d_write_t isavga_write; 92 static d_ioctl_t isavga_ioctl; 93 static d_mmap_t isavga_mmap; 94 95 static struct dev_ops isavga_ops = { 96 { VGA_DRIVER_NAME, -1, 0 }, 97 .d_open = isavga_open, 98 .d_close = isavga_close, 99 .d_read = isavga_read, 100 .d_write = isavga_write, 101 .d_ioctl = isavga_ioctl, 102 .d_mmap = isavga_mmap, 103 }; 104 105 #endif /* FB_INSTALL_CDEV */ 106 107 static int 108 isavga_probe(device_t dev) 109 { 110 video_adapter_t adp; 111 int error; 112 113 /* No pnp support */ 114 if (isa_get_vendorid(dev)) 115 return (ENXIO); 116 117 device_set_desc(dev, "Generic ISA VGA"); 118 error = vga_probe_unit(device_get_unit(dev), &adp, device_get_flags(dev)); 119 if (error == 0) { 120 bus_set_resource(dev, SYS_RES_IOPORT, 0, 121 adp.va_io_base, adp.va_io_size, -1); 122 bus_set_resource(dev, SYS_RES_MEMORY, 0, 123 adp.va_mem_base, adp.va_mem_size, -1); 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 int unit; 139 int rid; 140 int error; 141 142 unit = device_get_unit(dev); 143 sc = device_get_softc(dev); 144 145 rid = 0; 146 bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 147 0, ~0, 0, RF_ACTIVE | RF_SHAREABLE); 148 rid = 0; 149 bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 150 0, ~0, 0, RF_ACTIVE | RF_SHAREABLE); 151 152 error = vga_attach_unit(unit, sc, device_get_flags(dev)); 153 if (error) 154 return error; 155 156 #ifdef FB_INSTALL_CDEV 157 /* attach a virtual frame buffer device */ 158 sc->devt = make_dev(&isavga_ops, VGA_MKMINOR(unit), 0, 0, 02660, "vga%x", VGA_MKMINOR(unit)); 159 reference_dev(sc->devt); 160 error = fb_attach(sc->devt, sc->adp); 161 if (error) 162 return error; 163 #endif /* FB_INSTALL_CDEV */ 164 165 if (bootverbose) 166 (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose); 167 168 #if 0 /* experimental */ 169 device_add_child(dev, "fb", -1); 170 bus_generic_attach(dev); 171 #endif 172 173 return 0; 174 } 175 176 static int 177 isavga_suspend(device_t dev) 178 { 179 vga_softc_t *sc; 180 int err, nbytes; 181 182 sc = device_get_softc(dev); 183 err = bus_generic_suspend(dev); 184 if (err) 185 return (err); 186 187 /* Save the video state across the suspend. */ 188 if (sc->state_buf != NULL) { 189 kfree(sc->state_buf, M_TEMP); 190 sc->state_buf = NULL; 191 } 192 nbytes = (*vidsw[sc->adp->va_index]->save_state)(sc->adp, NULL, 0); 193 if (nbytes <= 0) 194 return (0); 195 sc->state_buf = kmalloc(nbytes, M_TEMP, M_NOWAIT | M_ZERO); 196 if (sc->state_buf == NULL) 197 return (0); 198 if (bootverbose) 199 device_printf(dev, "saving %d bytes of video state\n", nbytes); 200 lwkt_gettoken(&tty_token); 201 if ((*vidsw[sc->adp->va_index]->save_state)(sc->adp, sc->state_buf, 202 nbytes) != 0) { 203 device_printf(dev, "failed to save state (nbytes=%d)\n", 204 nbytes); 205 kfree(sc->state_buf, M_TEMP); 206 sc->state_buf = NULL; 207 } 208 lwkt_reltoken(&tty_token); 209 return (0); 210 } 211 212 static int 213 isavga_resume(device_t dev) 214 { 215 vga_softc_t *sc; 216 217 sc = device_get_softc(dev); 218 if (sc->state_buf != NULL) { 219 if ((*vidsw[sc->adp->va_index]->load_state)(sc->adp, 220 sc->state_buf) != 0) 221 device_printf(dev, "failed to reload state\n"); 222 kfree(sc->state_buf, M_TEMP); 223 sc->state_buf = NULL; 224 } 225 226 bus_generic_resume(dev); 227 return 0; 228 } 229 230 #ifdef FB_INSTALL_CDEV 231 232 static int 233 isavga_open(struct dev_open_args *ap) 234 { 235 cdev_t dev = ap->a_head.a_dev; 236 237 return vga_open(dev, VGA_SOFTC(VGA_UNIT(dev)), ap->a_oflags, 238 ap->a_devtype, ap->a_cred); 239 } 240 241 static int 242 isavga_close(struct dev_close_args *ap) 243 { 244 cdev_t dev = ap->a_head.a_dev; 245 246 return vga_close(dev, VGA_SOFTC(VGA_UNIT(dev)), 247 ap->a_fflag, ap->a_devtype); 248 } 249 250 static int 251 isavga_read(struct dev_read_args *ap) 252 { 253 cdev_t dev = ap->a_head.a_dev; 254 255 return vga_read(dev, VGA_SOFTC(VGA_UNIT(dev)), ap->a_uio, ap->a_ioflag); 256 } 257 258 static int 259 isavga_write(struct dev_write_args *ap) 260 { 261 cdev_t dev = ap->a_head.a_dev; 262 263 return vga_write(dev, VGA_SOFTC(VGA_UNIT(dev)), ap->a_uio, ap->a_ioflag); 264 } 265 266 static int 267 isavga_ioctl(struct dev_ioctl_args *ap) 268 { 269 cdev_t dev = ap->a_head.a_dev; 270 271 return vga_ioctl(dev, VGA_SOFTC(VGA_UNIT(dev)), ap->a_cmd, ap->a_data, ap->a_fflag, ap->a_cred); 272 } 273 274 static int 275 isavga_mmap(struct dev_mmap_args *ap) 276 { 277 cdev_t dev = ap->a_head.a_dev; 278 279 ap->a_result = vga_mmap(dev, VGA_SOFTC(VGA_UNIT(dev)), ap->a_offset, ap->a_nprot); 280 return(0); 281 } 282 283 #endif /* FB_INSTALL_CDEV */ 284