18a997770SDoug Rabson /*- 28a997770SDoug Rabson * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 38a997770SDoug Rabson * All rights reserved. 48a997770SDoug Rabson * 58a997770SDoug Rabson * Redistribution and use in source and binary forms, with or without 68a997770SDoug Rabson * modification, are permitted provided that the following conditions 78a997770SDoug Rabson * are met: 88a997770SDoug Rabson * 1. Redistributions of source code must retain the above copyright 98a997770SDoug Rabson * notice, this list of conditions and the following disclaimer as 108a997770SDoug Rabson * the first lines of this file unmodified. 118a997770SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 128a997770SDoug Rabson * notice, this list of conditions and the following disclaimer in the 138a997770SDoug Rabson * documentation and/or other materials provided with the distribution. 148a997770SDoug Rabson * 158a997770SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 168a997770SDoug Rabson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 178a997770SDoug Rabson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 188a997770SDoug Rabson * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 198a997770SDoug Rabson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 208a997770SDoug Rabson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 218a997770SDoug Rabson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 228a997770SDoug Rabson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 238a997770SDoug Rabson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 248a997770SDoug Rabson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 258a997770SDoug Rabson */ 268a997770SDoug Rabson 278c9bbf48SDavid E. O'Brien #include <sys/cdefs.h> 288c9bbf48SDavid E. O'Brien __FBSDID("$FreeBSD$"); 298c9bbf48SDavid E. O'Brien 308a997770SDoug Rabson #include "opt_vga.h" 318a997770SDoug Rabson #include "opt_fb.h" 328a997770SDoug Rabson #include "opt_syscons.h" /* should be removed in the future, XXX */ 338a997770SDoug Rabson 348a997770SDoug Rabson #include <sys/param.h> 358a997770SDoug Rabson #include <sys/systm.h> 368a997770SDoug Rabson #include <sys/kernel.h> 37528433baSIan Dowse #include <sys/malloc.h> 385dba30f1SPoul-Henning Kamp #include <sys/module.h> 396e8394b8SKazutaka YOKOTA #include <sys/conf.h> 408a997770SDoug Rabson #include <sys/bus.h> 416e8394b8SKazutaka YOKOTA #include <sys/fbio.h> 426e8394b8SKazutaka YOKOTA 436e8394b8SKazutaka YOKOTA #include <machine/bus.h> 446e8394b8SKazutaka YOKOTA #include <machine/resource.h> 456e8394b8SKazutaka YOKOTA 466e8394b8SKazutaka YOKOTA #include <sys/rman.h> 478a997770SDoug Rabson 488a997770SDoug Rabson #include <vm/vm.h> 498a997770SDoug Rabson #include <vm/pmap.h> 508a997770SDoug Rabson 518a997770SDoug Rabson #include <machine/md_var.h> 5233a9fd01SPeter Wemm #ifdef __i386__ 538a997770SDoug Rabson #include <machine/pc/bios.h> 5433a9fd01SPeter Wemm #endif 558a997770SDoug Rabson 568a997770SDoug Rabson #include <dev/fb/fbreg.h> 578a997770SDoug Rabson #include <dev/fb/vgareg.h> 588a997770SDoug Rabson 598a997770SDoug Rabson #include <isa/isareg.h> 608a997770SDoug Rabson #include <isa/isavar.h> 618a997770SDoug Rabson 626e8394b8SKazutaka YOKOTA #define VGA_SOFTC(unit) \ 636e8394b8SKazutaka YOKOTA ((vga_softc_t *)devclass_get_softc(isavga_devclass, unit)) 648a997770SDoug Rabson 656e8394b8SKazutaka YOKOTA static devclass_t isavga_devclass; 668a997770SDoug Rabson 678a997770SDoug Rabson #ifdef FB_INSTALL_CDEV 688a997770SDoug Rabson 696e8394b8SKazutaka YOKOTA static d_open_t isavga_open; 706e8394b8SKazutaka YOKOTA static d_close_t isavga_close; 716e8394b8SKazutaka YOKOTA static d_read_t isavga_read; 726e8394b8SKazutaka YOKOTA static d_write_t isavga_write; 736e8394b8SKazutaka YOKOTA static d_ioctl_t isavga_ioctl; 746e8394b8SKazutaka YOKOTA static d_mmap_t isavga_mmap; 758a997770SDoug Rabson 766e8394b8SKazutaka YOKOTA static struct cdevsw isavga_cdevsw = { 77dc08ffecSPoul-Henning Kamp .d_version = D_VERSION, 78dc08ffecSPoul-Henning Kamp .d_flags = D_NEEDGIANT, 797ac40f5fSPoul-Henning Kamp .d_open = isavga_open, 807ac40f5fSPoul-Henning Kamp .d_close = isavga_close, 817ac40f5fSPoul-Henning Kamp .d_read = isavga_read, 827ac40f5fSPoul-Henning Kamp .d_write = isavga_write, 837ac40f5fSPoul-Henning Kamp .d_ioctl = isavga_ioctl, 847ac40f5fSPoul-Henning Kamp .d_mmap = isavga_mmap, 857ac40f5fSPoul-Henning Kamp .d_name = VGA_DRIVER_NAME, 868a997770SDoug Rabson }; 878a997770SDoug Rabson 888a997770SDoug Rabson #endif /* FB_INSTALL_CDEV */ 898a997770SDoug Rabson 90c20ac811SPeter Wemm static void 91c20ac811SPeter Wemm isavga_identify(driver_t *driver, device_t parent) 92c20ac811SPeter Wemm { 93c20ac811SPeter Wemm BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, VGA_DRIVER_NAME, 0); 94c20ac811SPeter Wemm } 95c20ac811SPeter Wemm 968a997770SDoug Rabson static int 978a997770SDoug Rabson isavga_probe(device_t dev) 988a997770SDoug Rabson { 996e8394b8SKazutaka YOKOTA video_adapter_t adp; 1006e8394b8SKazutaka YOKOTA int error; 1018a997770SDoug Rabson 102f7f2df54SDoug Rabson /* No pnp support */ 103f7f2df54SDoug Rabson if (isa_get_vendorid(dev)) 104f7f2df54SDoug Rabson return (ENXIO); 105f7f2df54SDoug Rabson 1068a997770SDoug Rabson device_set_desc(dev, "Generic ISA VGA"); 107062acdb7SDoug Rabson error = vga_probe_unit(device_get_unit(dev), &adp, device_get_flags(dev)); 1086e8394b8SKazutaka YOKOTA if (error == 0) { 10925afb89bSDoug Rabson bus_set_resource(dev, SYS_RES_IOPORT, 0, 1106e8394b8SKazutaka YOKOTA adp.va_io_base, adp.va_io_size); 11125afb89bSDoug Rabson bus_set_resource(dev, SYS_RES_MEMORY, 0, 1126e8394b8SKazutaka YOKOTA adp.va_mem_base, adp.va_mem_size); 1136e8394b8SKazutaka YOKOTA #if 0 1146e8394b8SKazutaka YOKOTA isa_set_port(dev, adp.va_io_base); 1156e8394b8SKazutaka YOKOTA isa_set_portsize(dev, adp.va_io_size); 1166e8394b8SKazutaka YOKOTA isa_set_maddr(dev, adp.va_mem_base); 1176e8394b8SKazutaka YOKOTA isa_set_msize(dev, adp.va_mem_size); 1186e8394b8SKazutaka YOKOTA #endif 1196e8394b8SKazutaka YOKOTA } 1206e8394b8SKazutaka YOKOTA return error; 1218a997770SDoug Rabson } 1228a997770SDoug Rabson 1238a997770SDoug Rabson static int 1248a997770SDoug Rabson isavga_attach(device_t dev) 1258a997770SDoug Rabson { 1266e8394b8SKazutaka YOKOTA vga_softc_t *sc; 1276e8394b8SKazutaka YOKOTA int unit; 1286e8394b8SKazutaka YOKOTA int rid; 1298a997770SDoug Rabson int error; 1308a997770SDoug Rabson 1316e8394b8SKazutaka YOKOTA unit = device_get_unit(dev); 1326e8394b8SKazutaka YOKOTA sc = device_get_softc(dev); 1338a997770SDoug Rabson 1346e8394b8SKazutaka YOKOTA rid = 0; 13567096659SPoul-Henning Kamp bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 1366e8394b8SKazutaka YOKOTA 0, ~0, 0, RF_ACTIVE | RF_SHAREABLE); 1376e8394b8SKazutaka YOKOTA rid = 0; 13867096659SPoul-Henning Kamp bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 1396e8394b8SKazutaka YOKOTA 0, ~0, 0, RF_ACTIVE | RF_SHAREABLE); 1406e8394b8SKazutaka YOKOTA 141062acdb7SDoug Rabson error = vga_attach_unit(unit, sc, device_get_flags(dev)); 1428a997770SDoug Rabson if (error) 1436e8394b8SKazutaka YOKOTA return error; 1448a997770SDoug Rabson 1458a997770SDoug Rabson #ifdef FB_INSTALL_CDEV 1468a997770SDoug Rabson /* attach a virtual frame buffer device */ 1474866f95dSPoul-Henning Kamp error = fb_attach(VGA_MKMINOR(unit), sc->adp, &isavga_cdevsw); 1488a997770SDoug Rabson if (error) 1498a997770SDoug Rabson return error; 1508a997770SDoug Rabson #endif /* FB_INSTALL_CDEV */ 1518a997770SDoug Rabson 15261eb992fSPoul-Henning Kamp if (0 && bootverbose) 1531c27745fSKazutaka YOKOTA (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose); 1548a997770SDoug Rabson 1556e8394b8SKazutaka YOKOTA #if experimental 156fe0d4089SMatthew N. Dodd device_add_child(dev, "fb", -1); 1576e8394b8SKazutaka YOKOTA bus_generic_attach(dev); 1588a997770SDoug Rabson #endif 1598a997770SDoug Rabson 1608a997770SDoug Rabson return 0; 1618a997770SDoug Rabson } 1628a997770SDoug Rabson 163528433baSIan Dowse static int 164528433baSIan Dowse isavga_suspend(device_t dev) 165528433baSIan Dowse { 166528433baSIan Dowse vga_softc_t *sc; 167528433baSIan Dowse int err, nbytes; 168528433baSIan Dowse 169528433baSIan Dowse sc = device_get_softc(dev); 170528433baSIan Dowse err = bus_generic_suspend(dev); 171528433baSIan Dowse if (err) 172528433baSIan Dowse return (err); 173528433baSIan Dowse 174528433baSIan Dowse /* Save the video state across the suspend. */ 175528433baSIan Dowse if (sc->state_buf != NULL) { 176528433baSIan Dowse free(sc->state_buf, M_TEMP); 177528433baSIan Dowse sc->state_buf = NULL; 178528433baSIan Dowse } 179528433baSIan Dowse nbytes = (*vidsw[sc->adp->va_index]->save_state)(sc->adp, NULL, 0); 180528433baSIan Dowse if (nbytes <= 0) 181528433baSIan Dowse return (0); 182528433baSIan Dowse sc->state_buf = malloc(nbytes, M_TEMP, M_NOWAIT | M_ZERO); 183528433baSIan Dowse if (sc->state_buf == NULL) 184528433baSIan Dowse return (0); 185528433baSIan Dowse if (bootverbose) 186528433baSIan Dowse device_printf(dev, "saving %d bytes of video state\n", nbytes); 187528433baSIan Dowse if ((*vidsw[sc->adp->va_index]->save_state)(sc->adp, sc->state_buf, 188528433baSIan Dowse nbytes) != 0) { 189528433baSIan Dowse device_printf(dev, "failed to save state (nbytes=%d)\n", 190528433baSIan Dowse nbytes); 191528433baSIan Dowse free(sc->state_buf, M_TEMP); 192528433baSIan Dowse sc->state_buf = NULL; 193528433baSIan Dowse } 194528433baSIan Dowse return (0); 195528433baSIan Dowse } 196528433baSIan Dowse 197528433baSIan Dowse static int 198528433baSIan Dowse isavga_resume(device_t dev) 199528433baSIan Dowse { 200528433baSIan Dowse vga_softc_t *sc; 201528433baSIan Dowse 202528433baSIan Dowse sc = device_get_softc(dev); 203528433baSIan Dowse if (sc->state_buf != NULL) { 204528433baSIan Dowse if ((*vidsw[sc->adp->va_index]->load_state)(sc->adp, 205528433baSIan Dowse sc->state_buf) != 0) 206528433baSIan Dowse device_printf(dev, "failed to reload state\n"); 207528433baSIan Dowse free(sc->state_buf, M_TEMP); 208528433baSIan Dowse sc->state_buf = NULL; 209528433baSIan Dowse } 210528433baSIan Dowse 211528433baSIan Dowse bus_generic_resume(dev); 212528433baSIan Dowse return 0; 213528433baSIan Dowse } 214528433baSIan Dowse 2156e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV 2166e8394b8SKazutaka YOKOTA 2178a997770SDoug Rabson static int 21889c9c53dSPoul-Henning Kamp isavga_open(struct cdev *dev, int flag, int mode, struct thread *td) 2198a997770SDoug Rabson { 220b40ce416SJulian Elischer return vga_open(dev, VGA_SOFTC(VGA_UNIT(dev)), flag, mode, td); 2218a997770SDoug Rabson } 2228a997770SDoug Rabson 2238a997770SDoug Rabson static int 22489c9c53dSPoul-Henning Kamp isavga_close(struct cdev *dev, int flag, int mode, struct thread *td) 2258a997770SDoug Rabson { 226b40ce416SJulian Elischer return vga_close(dev, VGA_SOFTC(VGA_UNIT(dev)), flag, mode, td); 2278a997770SDoug Rabson } 2288a997770SDoug Rabson 2298a997770SDoug Rabson static int 23089c9c53dSPoul-Henning Kamp isavga_read(struct cdev *dev, struct uio *uio, int flag) 2318a997770SDoug Rabson { 2326e8394b8SKazutaka YOKOTA return vga_read(dev, VGA_SOFTC(VGA_UNIT(dev)), uio, flag); 2338a997770SDoug Rabson } 2348a997770SDoug Rabson 2358a997770SDoug Rabson static int 23689c9c53dSPoul-Henning Kamp isavga_write(struct cdev *dev, struct uio *uio, int flag) 2378a997770SDoug Rabson { 2386e8394b8SKazutaka YOKOTA return vga_write(dev, VGA_SOFTC(VGA_UNIT(dev)), uio, flag); 2398a997770SDoug Rabson } 2408a997770SDoug Rabson 2418a997770SDoug Rabson static int 24289c9c53dSPoul-Henning Kamp isavga_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) 2438a997770SDoug Rabson { 244b40ce416SJulian Elischer return vga_ioctl(dev, VGA_SOFTC(VGA_UNIT(dev)), cmd, arg, flag, td); 2458a997770SDoug Rabson } 2468a997770SDoug Rabson 2478a997770SDoug Rabson static int 24889c9c53dSPoul-Henning Kamp isavga_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int prot) 2498a997770SDoug Rabson { 25007159f9cSMaxime Henrion return vga_mmap(dev, VGA_SOFTC(VGA_UNIT(dev)), offset, paddr, prot); 2518a997770SDoug Rabson } 2528a997770SDoug Rabson 2536e8394b8SKazutaka YOKOTA #endif /* FB_INSTALL_CDEV */ 254c20ac811SPeter Wemm 255c20ac811SPeter Wemm static device_method_t isavga_methods[] = { 256c20ac811SPeter Wemm DEVMETHOD(device_identify, isavga_identify), 257c20ac811SPeter Wemm DEVMETHOD(device_probe, isavga_probe), 258c20ac811SPeter Wemm DEVMETHOD(device_attach, isavga_attach), 259528433baSIan Dowse DEVMETHOD(device_suspend, isavga_suspend), 260528433baSIan Dowse DEVMETHOD(device_resume, isavga_resume), 261c20ac811SPeter Wemm 262c20ac811SPeter Wemm DEVMETHOD(bus_print_child, bus_generic_print_child), 263c20ac811SPeter Wemm { 0, 0 } 264c20ac811SPeter Wemm }; 265c20ac811SPeter Wemm 266c20ac811SPeter Wemm static driver_t isavga_driver = { 267c20ac811SPeter Wemm VGA_DRIVER_NAME, 268c20ac811SPeter Wemm isavga_methods, 269c20ac811SPeter Wemm sizeof(vga_softc_t), 270c20ac811SPeter Wemm }; 271c20ac811SPeter Wemm 272c20ac811SPeter Wemm DRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0); 273