18e8e46ccSJohn Baldwin /*- 28e8e46ccSJohn Baldwin * Copyright (c) 2005 John Baldwin <jhb@FreeBSD.org> 38e8e46ccSJohn Baldwin * All rights reserved. 48e8e46ccSJohn Baldwin * 58e8e46ccSJohn Baldwin * Redistribution and use in source and binary forms, with or without 68e8e46ccSJohn Baldwin * modification, are permitted provided that the following conditions 78e8e46ccSJohn Baldwin * are met: 88e8e46ccSJohn Baldwin * 1. Redistributions of source code must retain the above copyright 98e8e46ccSJohn Baldwin * notice, this list of conditions and the following disclaimer. 108e8e46ccSJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 118e8e46ccSJohn Baldwin * notice, this list of conditions and the following disclaimer in the 128e8e46ccSJohn Baldwin * documentation and/or other materials provided with the distribution. 138e8e46ccSJohn Baldwin * 3. Neither the name of the author nor the names of any co-contributors 148e8e46ccSJohn Baldwin * may be used to endorse or promote products derived from this software 158e8e46ccSJohn Baldwin * without specific prior written permission. 168e8e46ccSJohn Baldwin * 178e8e46ccSJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 188e8e46ccSJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 198e8e46ccSJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 208e8e46ccSJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 218e8e46ccSJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 228e8e46ccSJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 238e8e46ccSJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 248e8e46ccSJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 258e8e46ccSJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 268e8e46ccSJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 278e8e46ccSJohn Baldwin * SUCH DAMAGE. 288e8e46ccSJohn Baldwin */ 298e8e46ccSJohn Baldwin 308e8e46ccSJohn Baldwin #include <sys/cdefs.h> 318e8e46ccSJohn Baldwin __FBSDID("$FreeBSD$"); 328e8e46ccSJohn Baldwin 338e8e46ccSJohn Baldwin /* 348e8e46ccSJohn Baldwin * Simple driver for PCI VGA display devices. Drivers such as agp(4) and 358e8e46ccSJohn Baldwin * drm(4) should attach as children of this device. 368e8e46ccSJohn Baldwin * 378e8e46ccSJohn Baldwin * XXX: The vgapci name is a hack until we somehow merge the isa vga driver 388e8e46ccSJohn Baldwin * in or rename it. 398e8e46ccSJohn Baldwin */ 408e8e46ccSJohn Baldwin 418e8e46ccSJohn Baldwin #include <sys/param.h> 428e8e46ccSJohn Baldwin #include <sys/bus.h> 438e8e46ccSJohn Baldwin #include <sys/kernel.h> 448e8e46ccSJohn Baldwin #include <sys/module.h> 458e8e46ccSJohn Baldwin 468e8e46ccSJohn Baldwin #include <dev/pci/pcireg.h> 478e8e46ccSJohn Baldwin #include <dev/pci/pcivar.h> 488e8e46ccSJohn Baldwin 498e8e46ccSJohn Baldwin static int 508e8e46ccSJohn Baldwin vga_pci_probe(device_t dev) 518e8e46ccSJohn Baldwin { 528e8e46ccSJohn Baldwin 538e8e46ccSJohn Baldwin switch (pci_get_class(dev)) { 548e8e46ccSJohn Baldwin case PCIC_DISPLAY: 558e8e46ccSJohn Baldwin break; 568e8e46ccSJohn Baldwin case PCIC_OLD: 578e8e46ccSJohn Baldwin if (pci_get_subclass(dev) != PCIS_OLD_VGA) 588e8e46ccSJohn Baldwin return (ENXIO); 598e8e46ccSJohn Baldwin break; 608e8e46ccSJohn Baldwin default: 618e8e46ccSJohn Baldwin return (ENXIO); 628e8e46ccSJohn Baldwin } 638e8e46ccSJohn Baldwin device_set_desc(dev, "VGA-compatible display"); 64be7ccc4bSJohn Baldwin return (BUS_PROBE_GENERIC); 658e8e46ccSJohn Baldwin } 668e8e46ccSJohn Baldwin 678e8e46ccSJohn Baldwin static int 688e8e46ccSJohn Baldwin vga_pci_attach(device_t dev) 698e8e46ccSJohn Baldwin { 708e8e46ccSJohn Baldwin 718e8e46ccSJohn Baldwin bus_generic_probe(dev); 728e8e46ccSJohn Baldwin 738e8e46ccSJohn Baldwin /* 748e8e46ccSJohn Baldwin * If AGP capabilities are present on this device, then create 758e8e46ccSJohn Baldwin * an AGP child. 768e8e46ccSJohn Baldwin */ 778e8e46ccSJohn Baldwin if (pci_find_extcap(dev, PCIY_AGP, NULL) == 0) 788e8e46ccSJohn Baldwin device_add_child(dev, "agp", -1); 798e8e46ccSJohn Baldwin 808e8e46ccSJohn Baldwin /* Always create a drm child for now to make it easier on drm. */ 818e8e46ccSJohn Baldwin device_add_child(dev, "drm", -1); 828e8e46ccSJohn Baldwin bus_generic_attach(dev); 838e8e46ccSJohn Baldwin return (0); 848e8e46ccSJohn Baldwin } 858e8e46ccSJohn Baldwin 868e8e46ccSJohn Baldwin static int 878e8e46ccSJohn Baldwin vga_pci_suspend(device_t dev) 888e8e46ccSJohn Baldwin { 898e8e46ccSJohn Baldwin 908e8e46ccSJohn Baldwin return (bus_generic_suspend(dev)); 918e8e46ccSJohn Baldwin } 928e8e46ccSJohn Baldwin 938e8e46ccSJohn Baldwin static int 948e8e46ccSJohn Baldwin vga_pci_resume(device_t dev) 958e8e46ccSJohn Baldwin { 968e8e46ccSJohn Baldwin 978e8e46ccSJohn Baldwin return (bus_generic_resume(dev)); 988e8e46ccSJohn Baldwin } 998e8e46ccSJohn Baldwin 1008e8e46ccSJohn Baldwin /* Bus interface. */ 1018e8e46ccSJohn Baldwin 1028e8e46ccSJohn Baldwin static int 1038e8e46ccSJohn Baldwin vga_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 1048e8e46ccSJohn Baldwin { 1058e8e46ccSJohn Baldwin 1068e8e46ccSJohn Baldwin return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result)); 1078e8e46ccSJohn Baldwin } 1088e8e46ccSJohn Baldwin 1098e8e46ccSJohn Baldwin static int 1108e8e46ccSJohn Baldwin vga_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 1118e8e46ccSJohn Baldwin { 1128e8e46ccSJohn Baldwin 1138e8e46ccSJohn Baldwin return (EINVAL); 1148e8e46ccSJohn Baldwin } 1158e8e46ccSJohn Baldwin 1168e8e46ccSJohn Baldwin static struct resource * 1178e8e46ccSJohn Baldwin vga_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, 1188e8e46ccSJohn Baldwin u_long start, u_long end, u_long count, u_int flags) 1198e8e46ccSJohn Baldwin { 1208e8e46ccSJohn Baldwin 1218e8e46ccSJohn Baldwin return (bus_alloc_resource(dev, type, rid, start, end, count, flags)); 1228e8e46ccSJohn Baldwin } 1238e8e46ccSJohn Baldwin 1248e8e46ccSJohn Baldwin static int 1258e8e46ccSJohn Baldwin vga_pci_release_resource(device_t dev, device_t child, int type, int rid, 1268e8e46ccSJohn Baldwin struct resource *r) 1278e8e46ccSJohn Baldwin { 1288e8e46ccSJohn Baldwin 1298e8e46ccSJohn Baldwin return (bus_release_resource(dev, type, rid, r)); 1308e8e46ccSJohn Baldwin } 1318e8e46ccSJohn Baldwin 1328e8e46ccSJohn Baldwin /* PCI interface. */ 1338e8e46ccSJohn Baldwin 1348e8e46ccSJohn Baldwin static uint32_t 1358e8e46ccSJohn Baldwin vga_pci_read_config(device_t dev, device_t child, int reg, int width) 1368e8e46ccSJohn Baldwin { 1378e8e46ccSJohn Baldwin 1388e8e46ccSJohn Baldwin return (pci_read_config(dev, reg, width)); 1398e8e46ccSJohn Baldwin } 1408e8e46ccSJohn Baldwin 1418e8e46ccSJohn Baldwin static void 1428e8e46ccSJohn Baldwin vga_pci_write_config(device_t dev, device_t child, int reg, 1438e8e46ccSJohn Baldwin uint32_t val, int width) 1448e8e46ccSJohn Baldwin { 1458e8e46ccSJohn Baldwin 1468e8e46ccSJohn Baldwin pci_write_config(dev, reg, val, width); 1478e8e46ccSJohn Baldwin } 1488e8e46ccSJohn Baldwin 1498e8e46ccSJohn Baldwin static int 1508e8e46ccSJohn Baldwin vga_pci_enable_busmaster(device_t dev, device_t child) 1518e8e46ccSJohn Baldwin { 1528e8e46ccSJohn Baldwin 1538e8e46ccSJohn Baldwin device_printf(dev, "child %s requested pci_enable_busmaster\n", 1548e8e46ccSJohn Baldwin device_get_nameunit(child)); 1558e8e46ccSJohn Baldwin return (pci_enable_busmaster(dev)); 1568e8e46ccSJohn Baldwin } 1578e8e46ccSJohn Baldwin 1588e8e46ccSJohn Baldwin static int 1598e8e46ccSJohn Baldwin vga_pci_disable_busmaster(device_t dev, device_t child) 1608e8e46ccSJohn Baldwin { 1618e8e46ccSJohn Baldwin 1628e8e46ccSJohn Baldwin device_printf(dev, "child %s requested pci_disable_busmaster\n", 1638e8e46ccSJohn Baldwin device_get_nameunit(child)); 1648e8e46ccSJohn Baldwin return (pci_disable_busmaster(dev)); 1658e8e46ccSJohn Baldwin } 1668e8e46ccSJohn Baldwin 1678e8e46ccSJohn Baldwin static int 1688e8e46ccSJohn Baldwin vga_pci_enable_io(device_t dev, device_t child, int space) 1698e8e46ccSJohn Baldwin { 1708e8e46ccSJohn Baldwin 1718e8e46ccSJohn Baldwin device_printf(dev, "child %s requested pci_enable_io\n", 1728e8e46ccSJohn Baldwin device_get_nameunit(child)); 1738e8e46ccSJohn Baldwin return (pci_enable_io(dev, space)); 1748e8e46ccSJohn Baldwin } 1758e8e46ccSJohn Baldwin 1768e8e46ccSJohn Baldwin static int 1778e8e46ccSJohn Baldwin vga_pci_disable_io(device_t dev, device_t child, int space) 1788e8e46ccSJohn Baldwin { 1798e8e46ccSJohn Baldwin 1808e8e46ccSJohn Baldwin device_printf(dev, "child %s requested pci_disable_io\n", 1818e8e46ccSJohn Baldwin device_get_nameunit(child)); 1828e8e46ccSJohn Baldwin return (pci_disable_io(dev, space)); 1838e8e46ccSJohn Baldwin } 1848e8e46ccSJohn Baldwin 1858e8e46ccSJohn Baldwin static int 1868e8e46ccSJohn Baldwin vga_pci_set_powerstate(device_t dev, device_t child, int state) 1878e8e46ccSJohn Baldwin { 1888e8e46ccSJohn Baldwin 1898e8e46ccSJohn Baldwin device_printf(dev, "child %s requested pci_set_powerstate\n", 1908e8e46ccSJohn Baldwin device_get_nameunit(child)); 1918e8e46ccSJohn Baldwin return (pci_set_powerstate(dev, state)); 1928e8e46ccSJohn Baldwin } 1938e8e46ccSJohn Baldwin 1948e8e46ccSJohn Baldwin static int 1958e8e46ccSJohn Baldwin vga_pci_get_powerstate(device_t dev, device_t child) 1968e8e46ccSJohn Baldwin { 1978e8e46ccSJohn Baldwin 1988e8e46ccSJohn Baldwin device_printf(dev, "child %s requested pci_get_powerstate\n", 1998e8e46ccSJohn Baldwin device_get_nameunit(child)); 2008e8e46ccSJohn Baldwin return (pci_get_powerstate(dev)); 2018e8e46ccSJohn Baldwin } 2028e8e46ccSJohn Baldwin 2038e8e46ccSJohn Baldwin static int 2048e8e46ccSJohn Baldwin vga_pci_assign_interrupt(device_t dev, device_t child) 2058e8e46ccSJohn Baldwin { 2068e8e46ccSJohn Baldwin 2078e8e46ccSJohn Baldwin device_printf(dev, "child %s requested pci_assign_interrupt\n", 2088e8e46ccSJohn Baldwin device_get_nameunit(child)); 2098e8e46ccSJohn Baldwin return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev)); 2108e8e46ccSJohn Baldwin } 2118e8e46ccSJohn Baldwin 2128e8e46ccSJohn Baldwin static int 2138e8e46ccSJohn Baldwin vga_pci_find_extcap(device_t dev, device_t child, int capability, 2148e8e46ccSJohn Baldwin int *capreg) 2158e8e46ccSJohn Baldwin { 2168e8e46ccSJohn Baldwin 2178e8e46ccSJohn Baldwin return (pci_find_extcap(dev, capability, capreg)); 2188e8e46ccSJohn Baldwin } 2198e8e46ccSJohn Baldwin 2208e8e46ccSJohn Baldwin static device_method_t vga_pci_methods[] = { 2218e8e46ccSJohn Baldwin /* Device interface */ 2228e8e46ccSJohn Baldwin DEVMETHOD(device_probe, vga_pci_probe), 2238e8e46ccSJohn Baldwin DEVMETHOD(device_attach, vga_pci_attach), 2248e8e46ccSJohn Baldwin DEVMETHOD(device_shutdown, bus_generic_shutdown), 2258e8e46ccSJohn Baldwin DEVMETHOD(device_suspend, vga_pci_suspend), 2268e8e46ccSJohn Baldwin DEVMETHOD(device_resume, vga_pci_resume), 2278e8e46ccSJohn Baldwin 2288e8e46ccSJohn Baldwin /* Bus interface */ 2298e8e46ccSJohn Baldwin DEVMETHOD(bus_read_ivar, vga_pci_read_ivar), 2308e8e46ccSJohn Baldwin DEVMETHOD(bus_write_ivar, vga_pci_write_ivar), 2318e8e46ccSJohn Baldwin DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 2328e8e46ccSJohn Baldwin DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 2338e8e46ccSJohn Baldwin 2348e8e46ccSJohn Baldwin DEVMETHOD(bus_alloc_resource, vga_pci_alloc_resource), 2358e8e46ccSJohn Baldwin DEVMETHOD(bus_release_resource, vga_pci_release_resource), 2368e8e46ccSJohn Baldwin DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 2378e8e46ccSJohn Baldwin DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 2388e8e46ccSJohn Baldwin 2398e8e46ccSJohn Baldwin /* PCI interface */ 2408e8e46ccSJohn Baldwin DEVMETHOD(pci_read_config, vga_pci_read_config), 2418e8e46ccSJohn Baldwin DEVMETHOD(pci_write_config, vga_pci_write_config), 2428e8e46ccSJohn Baldwin DEVMETHOD(pci_enable_busmaster, vga_pci_enable_busmaster), 2438e8e46ccSJohn Baldwin DEVMETHOD(pci_disable_busmaster, vga_pci_disable_busmaster), 2448e8e46ccSJohn Baldwin DEVMETHOD(pci_enable_io, vga_pci_enable_io), 2458e8e46ccSJohn Baldwin DEVMETHOD(pci_disable_io, vga_pci_disable_io), 2468e8e46ccSJohn Baldwin DEVMETHOD(pci_get_powerstate, vga_pci_get_powerstate), 2478e8e46ccSJohn Baldwin DEVMETHOD(pci_set_powerstate, vga_pci_set_powerstate), 2488e8e46ccSJohn Baldwin DEVMETHOD(pci_assign_interrupt, vga_pci_assign_interrupt), 2498e8e46ccSJohn Baldwin DEVMETHOD(pci_find_extcap, vga_pci_find_extcap), 2508e8e46ccSJohn Baldwin 2518e8e46ccSJohn Baldwin { 0, 0 } 2528e8e46ccSJohn Baldwin }; 2538e8e46ccSJohn Baldwin 2548e8e46ccSJohn Baldwin static driver_t vga_pci_driver = { 2558e8e46ccSJohn Baldwin "vgapci", 2568e8e46ccSJohn Baldwin vga_pci_methods, 2578e8e46ccSJohn Baldwin 1, 2588e8e46ccSJohn Baldwin }; 2598e8e46ccSJohn Baldwin 2608e8e46ccSJohn Baldwin static devclass_t vga_devclass; 2618e8e46ccSJohn Baldwin 2628e8e46ccSJohn Baldwin DRIVER_MODULE(vgapci, pci, vga_pci_driver, vga_devclass, 0, 0); 263