vga_pci.c revision 183194
1153577Sjhb/*- 2153577Sjhb * Copyright (c) 2005 John Baldwin <jhb@FreeBSD.org> 3153577Sjhb * All rights reserved. 4153577Sjhb * 5153577Sjhb * Redistribution and use in source and binary forms, with or without 6153577Sjhb * modification, are permitted provided that the following conditions 7153577Sjhb * are met: 8153577Sjhb * 1. Redistributions of source code must retain the above copyright 9153577Sjhb * notice, this list of conditions and the following disclaimer. 10153577Sjhb * 2. Redistributions in binary form must reproduce the above copyright 11153577Sjhb * notice, this list of conditions and the following disclaimer in the 12153577Sjhb * documentation and/or other materials provided with the distribution. 13153577Sjhb * 3. Neither the name of the author nor the names of any co-contributors 14153577Sjhb * may be used to endorse or promote products derived from this software 15153577Sjhb * without specific prior written permission. 16153577Sjhb * 17153577Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18153577Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19153577Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20153577Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21153577Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22153577Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23153577Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24153577Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25153577Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26153577Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27153577Sjhb * SUCH DAMAGE. 28153577Sjhb */ 29153577Sjhb 30153577Sjhb#include <sys/cdefs.h> 31153577Sjhb__FBSDID("$FreeBSD: head/sys/dev/pci/vga_pci.c 183194 2008-09-19 19:11:35Z rnoland $"); 32153577Sjhb 33153577Sjhb/* 34153577Sjhb * Simple driver for PCI VGA display devices. Drivers such as agp(4) and 35153577Sjhb * drm(4) should attach as children of this device. 36153577Sjhb * 37153577Sjhb * XXX: The vgapci name is a hack until we somehow merge the isa vga driver 38153577Sjhb * in or rename it. 39153577Sjhb */ 40153577Sjhb 41153577Sjhb#include <sys/param.h> 42153577Sjhb#include <sys/bus.h> 43153577Sjhb#include <sys/kernel.h> 44153577Sjhb#include <sys/module.h> 45153577Sjhb 46153577Sjhb#include <dev/pci/pcireg.h> 47153577Sjhb#include <dev/pci/pcivar.h> 48153577Sjhb 49183095Sjhbstruct vga_pci_softc { 50183095Sjhb device_t vga_msi_child; /* Child driver using MSI. */ 51183095Sjhb}; 52183095Sjhb 53153577Sjhbstatic int 54153577Sjhbvga_pci_probe(device_t dev) 55153577Sjhb{ 56153577Sjhb 57153577Sjhb switch (pci_get_class(dev)) { 58153577Sjhb case PCIC_DISPLAY: 59153577Sjhb break; 60153577Sjhb case PCIC_OLD: 61153577Sjhb if (pci_get_subclass(dev) != PCIS_OLD_VGA) 62153577Sjhb return (ENXIO); 63153577Sjhb break; 64153577Sjhb default: 65153577Sjhb return (ENXIO); 66153577Sjhb } 67153577Sjhb device_set_desc(dev, "VGA-compatible display"); 68153646Sjhb return (BUS_PROBE_GENERIC); 69153577Sjhb} 70153577Sjhb 71153577Sjhbstatic int 72153577Sjhbvga_pci_attach(device_t dev) 73153577Sjhb{ 74153577Sjhb 75153577Sjhb bus_generic_probe(dev); 76153577Sjhb 77153577Sjhb /* Always create a drm child for now to make it easier on drm. */ 78153577Sjhb device_add_child(dev, "drm", -1); 79153577Sjhb bus_generic_attach(dev); 80153577Sjhb return (0); 81153577Sjhb} 82153577Sjhb 83153577Sjhbstatic int 84153577Sjhbvga_pci_suspend(device_t dev) 85153577Sjhb{ 86153577Sjhb 87153577Sjhb return (bus_generic_suspend(dev)); 88153577Sjhb} 89153577Sjhb 90153577Sjhbstatic int 91153577Sjhbvga_pci_resume(device_t dev) 92153577Sjhb{ 93153577Sjhb 94153577Sjhb return (bus_generic_resume(dev)); 95153577Sjhb} 96153577Sjhb 97153577Sjhb/* Bus interface. */ 98153577Sjhb 99153577Sjhbstatic int 100153577Sjhbvga_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 101153577Sjhb{ 102153577Sjhb 103153577Sjhb return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result)); 104153577Sjhb} 105153577Sjhb 106153577Sjhbstatic int 107153577Sjhbvga_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 108153577Sjhb{ 109153577Sjhb 110153577Sjhb return (EINVAL); 111153577Sjhb} 112153577Sjhb 113183194Srnolandstatic int 114183194Srnolandvga_pci_setup_intr(device_t dev, device_t child, struct resource *irq, 115183194Srnoland int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg, 116183194Srnoland void **cookiep) 117183194Srnoland{ 118183194Srnoland return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags, 119183194Srnoland filter, intr, arg, cookiep)); 120183194Srnoland} 121183194Srnoland 122183194Srnolandstatic int 123183194Srnolandvga_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, 124183194Srnoland void *cookie) 125183194Srnoland{ 126183194Srnoland return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie)); 127183194Srnoland} 128183194Srnoland 129153577Sjhbstatic struct resource * 130153577Sjhbvga_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, 131153577Sjhb u_long start, u_long end, u_long count, u_int flags) 132153577Sjhb{ 133153577Sjhb 134153577Sjhb return (bus_alloc_resource(dev, type, rid, start, end, count, flags)); 135153577Sjhb} 136153577Sjhb 137153577Sjhbstatic int 138153577Sjhbvga_pci_release_resource(device_t dev, device_t child, int type, int rid, 139153577Sjhb struct resource *r) 140153577Sjhb{ 141153577Sjhb 142153577Sjhb return (bus_release_resource(dev, type, rid, r)); 143153577Sjhb} 144153577Sjhb 145153577Sjhb/* PCI interface. */ 146153577Sjhb 147153577Sjhbstatic uint32_t 148153577Sjhbvga_pci_read_config(device_t dev, device_t child, int reg, int width) 149153577Sjhb{ 150153577Sjhb 151153577Sjhb return (pci_read_config(dev, reg, width)); 152153577Sjhb} 153153577Sjhb 154153577Sjhbstatic void 155153577Sjhbvga_pci_write_config(device_t dev, device_t child, int reg, 156153577Sjhb uint32_t val, int width) 157153577Sjhb{ 158153577Sjhb 159153577Sjhb pci_write_config(dev, reg, val, width); 160153577Sjhb} 161153577Sjhb 162153577Sjhbstatic int 163153577Sjhbvga_pci_enable_busmaster(device_t dev, device_t child) 164153577Sjhb{ 165153577Sjhb 166153577Sjhb device_printf(dev, "child %s requested pci_enable_busmaster\n", 167153577Sjhb device_get_nameunit(child)); 168153577Sjhb return (pci_enable_busmaster(dev)); 169153577Sjhb} 170153577Sjhb 171153577Sjhbstatic int 172153577Sjhbvga_pci_disable_busmaster(device_t dev, device_t child) 173153577Sjhb{ 174153577Sjhb 175153577Sjhb device_printf(dev, "child %s requested pci_disable_busmaster\n", 176153577Sjhb device_get_nameunit(child)); 177153577Sjhb return (pci_disable_busmaster(dev)); 178153577Sjhb} 179153577Sjhb 180153577Sjhbstatic int 181153577Sjhbvga_pci_enable_io(device_t dev, device_t child, int space) 182153577Sjhb{ 183153577Sjhb 184153577Sjhb device_printf(dev, "child %s requested pci_enable_io\n", 185153577Sjhb device_get_nameunit(child)); 186153577Sjhb return (pci_enable_io(dev, space)); 187153577Sjhb} 188153577Sjhb 189153577Sjhbstatic int 190153577Sjhbvga_pci_disable_io(device_t dev, device_t child, int space) 191153577Sjhb{ 192153577Sjhb 193153577Sjhb device_printf(dev, "child %s requested pci_disable_io\n", 194153577Sjhb device_get_nameunit(child)); 195153577Sjhb return (pci_disable_io(dev, space)); 196153577Sjhb} 197153577Sjhb 198153577Sjhbstatic int 199183095Sjhbvga_pci_get_vpd_ident(device_t dev, device_t child, const char **identptr) 200183095Sjhb{ 201183095Sjhb 202183095Sjhb return (pci_get_vpd_ident(dev, identptr)); 203183095Sjhb} 204183095Sjhb 205183095Sjhbstatic int 206183095Sjhbvga_pci_get_vpd_readonly(device_t dev, device_t child, const char *kw, 207183095Sjhb const char **vptr) 208183095Sjhb{ 209183095Sjhb 210183095Sjhb return (pci_get_vpd_readonly(dev, kw, vptr)); 211183095Sjhb} 212183095Sjhb 213183095Sjhbstatic int 214153577Sjhbvga_pci_set_powerstate(device_t dev, device_t child, int state) 215153577Sjhb{ 216153577Sjhb 217153577Sjhb device_printf(dev, "child %s requested pci_set_powerstate\n", 218153577Sjhb device_get_nameunit(child)); 219153577Sjhb return (pci_set_powerstate(dev, state)); 220153577Sjhb} 221153577Sjhb 222153577Sjhbstatic int 223153577Sjhbvga_pci_get_powerstate(device_t dev, device_t child) 224153577Sjhb{ 225153577Sjhb 226153577Sjhb device_printf(dev, "child %s requested pci_get_powerstate\n", 227153577Sjhb device_get_nameunit(child)); 228153577Sjhb return (pci_get_powerstate(dev)); 229153577Sjhb} 230153577Sjhb 231153577Sjhbstatic int 232153577Sjhbvga_pci_assign_interrupt(device_t dev, device_t child) 233153577Sjhb{ 234153577Sjhb 235153577Sjhb device_printf(dev, "child %s requested pci_assign_interrupt\n", 236153577Sjhb device_get_nameunit(child)); 237153577Sjhb return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev)); 238153577Sjhb} 239153577Sjhb 240153577Sjhbstatic int 241153577Sjhbvga_pci_find_extcap(device_t dev, device_t child, int capability, 242153577Sjhb int *capreg) 243153577Sjhb{ 244153577Sjhb 245153577Sjhb return (pci_find_extcap(dev, capability, capreg)); 246153577Sjhb} 247153577Sjhb 248183095Sjhbstatic int 249183095Sjhbvga_pci_alloc_msi(device_t dev, device_t child, int *count) 250183095Sjhb{ 251183095Sjhb struct vga_pci_softc *sc; 252183095Sjhb int error; 253183095Sjhb 254183095Sjhb sc = device_get_softc(dev); 255183095Sjhb if (sc->vga_msi_child != NULL) 256183095Sjhb return (EBUSY); 257183095Sjhb error = pci_alloc_msi(dev, count); 258183095Sjhb if (error == 0) 259183095Sjhb sc->vga_msi_child = child; 260183095Sjhb return (error); 261183095Sjhb} 262183095Sjhb 263183095Sjhbstatic int 264183095Sjhbvga_pci_alloc_msix(device_t dev, device_t child, int *count) 265183095Sjhb{ 266183095Sjhb struct vga_pci_softc *sc; 267183095Sjhb int error; 268183095Sjhb 269183095Sjhb sc = device_get_softc(dev); 270183095Sjhb if (sc->vga_msi_child != NULL) 271183095Sjhb return (EBUSY); 272183095Sjhb error = pci_alloc_msix(dev, count); 273183095Sjhb if (error == 0) 274183095Sjhb sc->vga_msi_child = child; 275183095Sjhb return (error); 276183095Sjhb} 277183095Sjhb 278183095Sjhbstatic int 279183095Sjhbvga_pci_remap_msix(device_t dev, device_t child, int count, 280183095Sjhb const u_int *vectors) 281183095Sjhb{ 282183095Sjhb struct vga_pci_softc *sc; 283183095Sjhb 284183095Sjhb sc = device_get_softc(dev); 285183095Sjhb if (sc->vga_msi_child != child) 286183095Sjhb return (ENXIO); 287183095Sjhb return (pci_remap_msix(dev, count, vectors)); 288183095Sjhb} 289183095Sjhb 290183095Sjhbstatic int 291183095Sjhbvga_pci_release_msi(device_t dev, device_t child) 292183095Sjhb{ 293183095Sjhb struct vga_pci_softc *sc; 294183095Sjhb int error; 295183095Sjhb 296183095Sjhb sc = device_get_softc(dev); 297183095Sjhb if (sc->vga_msi_child != child) 298183095Sjhb return (ENXIO); 299183095Sjhb error = pci_release_msi(dev); 300183095Sjhb if (error == 0) 301183095Sjhb sc->vga_msi_child = NULL; 302183095Sjhb return (error); 303183095Sjhb} 304183095Sjhb 305183095Sjhbstatic int 306183095Sjhbvga_pci_msi_count(device_t dev, device_t child) 307183095Sjhb{ 308183095Sjhb 309183095Sjhb return (pci_msi_count(dev)); 310183095Sjhb} 311183095Sjhb 312183095Sjhbstatic int 313183095Sjhbvga_pci_msix_count(device_t dev, device_t child) 314183095Sjhb{ 315183095Sjhb 316183095Sjhb return (pci_msix_count(dev)); 317183095Sjhb} 318183095Sjhb 319153577Sjhbstatic device_method_t vga_pci_methods[] = { 320153577Sjhb /* Device interface */ 321153577Sjhb DEVMETHOD(device_probe, vga_pci_probe), 322153577Sjhb DEVMETHOD(device_attach, vga_pci_attach), 323153577Sjhb DEVMETHOD(device_shutdown, bus_generic_shutdown), 324153577Sjhb DEVMETHOD(device_suspend, vga_pci_suspend), 325153577Sjhb DEVMETHOD(device_resume, vga_pci_resume), 326153577Sjhb 327153577Sjhb /* Bus interface */ 328153577Sjhb DEVMETHOD(bus_read_ivar, vga_pci_read_ivar), 329153577Sjhb DEVMETHOD(bus_write_ivar, vga_pci_write_ivar), 330183194Srnoland DEVMETHOD(bus_setup_intr, vga_pci_setup_intr), 331183194Srnoland DEVMETHOD(bus_teardown_intr, vga_pci_teardown_intr), 332153577Sjhb 333153577Sjhb DEVMETHOD(bus_alloc_resource, vga_pci_alloc_resource), 334153577Sjhb DEVMETHOD(bus_release_resource, vga_pci_release_resource), 335153577Sjhb DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 336153577Sjhb DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 337153577Sjhb 338153577Sjhb /* PCI interface */ 339153577Sjhb DEVMETHOD(pci_read_config, vga_pci_read_config), 340153577Sjhb DEVMETHOD(pci_write_config, vga_pci_write_config), 341153577Sjhb DEVMETHOD(pci_enable_busmaster, vga_pci_enable_busmaster), 342153577Sjhb DEVMETHOD(pci_disable_busmaster, vga_pci_disable_busmaster), 343153577Sjhb DEVMETHOD(pci_enable_io, vga_pci_enable_io), 344153577Sjhb DEVMETHOD(pci_disable_io, vga_pci_disable_io), 345183095Sjhb DEVMETHOD(pci_get_vpd_ident, vga_pci_get_vpd_ident), 346183095Sjhb DEVMETHOD(pci_get_vpd_readonly, vga_pci_get_vpd_readonly), 347153577Sjhb DEVMETHOD(pci_get_powerstate, vga_pci_get_powerstate), 348153577Sjhb DEVMETHOD(pci_set_powerstate, vga_pci_set_powerstate), 349153577Sjhb DEVMETHOD(pci_assign_interrupt, vga_pci_assign_interrupt), 350153577Sjhb DEVMETHOD(pci_find_extcap, vga_pci_find_extcap), 351183095Sjhb DEVMETHOD(pci_alloc_msi, vga_pci_alloc_msi), 352183095Sjhb DEVMETHOD(pci_alloc_msix, vga_pci_alloc_msix), 353183095Sjhb DEVMETHOD(pci_remap_msix, vga_pci_remap_msix), 354183095Sjhb DEVMETHOD(pci_release_msi, vga_pci_release_msi), 355183095Sjhb DEVMETHOD(pci_msi_count, vga_pci_msi_count), 356183095Sjhb DEVMETHOD(pci_msix_count, vga_pci_msix_count), 357153577Sjhb 358153577Sjhb { 0, 0 } 359153577Sjhb}; 360153577Sjhb 361153577Sjhbstatic driver_t vga_pci_driver = { 362153577Sjhb "vgapci", 363153577Sjhb vga_pci_methods, 364183095Sjhb sizeof(struct vga_pci_softc), 365153577Sjhb}; 366153577Sjhb 367153577Sjhbstatic devclass_t vga_devclass; 368153577Sjhb 369153577SjhbDRIVER_MODULE(vgapci, pci, vga_pci_driver, vga_devclass, 0, 0); 370