vga_pci.c revision 279494
14Srgrimes/*- 24Srgrimes * Copyright (c) 2005 John Baldwin <jhb@FreeBSD.org> 3295Sjtc * All rights reserved. 44Srgrimes * 5295Sjtc * Redistribution and use in source and binary forms, with or without 6295Sjtc * modification, are permitted provided that the following conditions 750471Speter * are met: 84Srgrimes * 1. Redistributions of source code must retain the above copyright 9468Sjtc * notice, this list of conditions and the following disclaimer. 1062926Sse * 2. Redistributions in binary form must reproduce the above copyright 1192979Swollman * notice, this list of conditions and the following disclaimer in the 1292979Swollman * documentation and/or other materials provided with the distribution. 1392979Swollman * 1492979Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1592979Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1692979Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1792979Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 184Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 194Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 204Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2162926Sse * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2292979Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2331Salm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2492979Swollman * SUCH DAMAGE. 2592979Swollman */ 2692979Swollman 2792979Swollman#include <sys/cdefs.h> 2892979Swollman__FBSDID("$FreeBSD: head/sys/dev/pci/vga_pci.c 279494 2015-03-01 20:54:29Z dumbbell $"); 2992979Swollman 304Srgrimes/* 3112378Sjoerg * Simple driver for PCI VGA display devices. Drivers such as agp(4) and 324Srgrimes * drm(4) should attach as children of this device. 3331Salm * 344Srgrimes * XXX: The vgapci name is a hack until we somehow merge the isa vga driver 354Srgrimes * in or rename it. 364Srgrimes */ 374Srgrimes 3892979Swollman#include <sys/param.h> 394Srgrimes#include <sys/bus.h> 4031Salm#include <sys/kernel.h> 414Srgrimes#include <sys/module.h> 424Srgrimes#include <sys/rman.h> 434Srgrimes#include <sys/sysctl.h> 4492979Swollman#include <sys/systm.h> 4592979Swollman 4692979Swollman#if defined(__amd64__) || defined(__i386__) 4792979Swollman#include <vm/vm.h> 4890109Simp#include <vm/pmap.h> 4990109Simp#endif 5090109Simp 5192979Swollman#include <dev/pci/pcireg.h> 5290109Simp#include <dev/pci/pcivar.h> 5390109Simp 5490109Simp#include <compat/x86bios/x86bios.h> /* To re-POST the card. */ 5590109Simp 5690109Simpstruct vga_resource { 5790109Simp struct resource *vr_res; 5890109Simp int vr_refs; 5990109Simp}; 6090109Simp 6190109Simpstruct vga_pci_softc { 6290109Simp device_t vga_msi_child; /* Child driver using MSI. */ 6390109Simp struct vga_resource vga_bars[PCIR_MAX_BAR_0 + 1]; 6490109Simp struct vga_resource vga_bios; 6590109Simp}; 6690109Simp 6792979SwollmanSYSCTL_DECL(_hw_pci); 6890109Simp 6990109Simpstatic struct vga_resource *lookup_res(struct vga_pci_softc *sc, int rid); 7090109Simpstatic struct resource *vga_pci_alloc_resource(device_t dev, device_t child, 7190109Simp int type, int *rid, u_long start, u_long end, u_long count, u_int flags); 7277244Skrisstatic int vga_pci_release_resource(device_t dev, device_t child, int type, 734Srgrimes int rid, struct resource *r); 744Srgrimes 754Srgrimesint vga_pci_default_unit = -1; 764SrgrimesSYSCTL_INT(_hw_pci, OID_AUTO, default_vgapci_unit, CTLFLAG_RDTUN, 774Srgrimes &vga_pci_default_unit, -1, "Default VGA-compatible display"); 784Srgrimes 794Srgrimesint 804Srgrimesvga_pci_is_boot_display(device_t dev) 814Srgrimes{ 824Srgrimes int unit; 834Srgrimes device_t pcib; 844Srgrimes uint16_t config; 854Srgrimes 864Srgrimes /* Check that the given device is a video card */ 874Srgrimes if ((pci_get_class(dev) != PCIC_DISPLAY && 884Srgrimes (pci_get_class(dev) != PCIC_OLD || 894Srgrimes pci_get_subclass(dev) != PCIS_OLD_VGA))) 904Srgrimes return (0); 914Srgrimes 924Srgrimes unit = device_get_unit(dev); 934Srgrimes 944Srgrimes if (vga_pci_default_unit >= 0) { 954Srgrimes /* 964Srgrimes * The boot display device was determined by a previous 974Srgrimes * call to this function, or the user forced it using 984Srgrimes * the hw.pci.default_vgapci_unit tunable. 994Srgrimes */ 1004Srgrimes return (vga_pci_default_unit == unit); 1014Srgrimes } 1024Srgrimes 1034Srgrimes /* 1044Srgrimes * The primary video card used as a boot display must have the 1054Srgrimes * "I/O" and "Memory Address Space Decoding" bits set in its 1064Srgrimes * Command register. 1074Srgrimes * 1084Srgrimes * Furthermore, if the card is attached to a bridge, instead of 1094Srgrimes * the root PCI bus, the bridge must have the "VGA Enable" bit 1104Srgrimes * set in its Control register. 1114Srgrimes */ 1124Srgrimes 1134Srgrimes pcib = device_get_parent(device_get_parent(dev)); 1144Srgrimes if (device_get_devclass(device_get_parent(pcib)) == 1154Srgrimes devclass_find("pci")) { 1164Srgrimes /* 11792979Swollman * The parent bridge is a PCI-to-PCI bridge: check the 1184Srgrimes * value of the "VGA Enable" bit. 1194Srgrimes */ 1204Srgrimes config = pci_read_config(pcib, PCIR_BRIDGECTL_1, 2); 1214Srgrimes if ((config & PCIB_BCR_VGA_ENABLE) == 0) 1224Srgrimes return (0); 12392979Swollman } 1244Srgrimes 1254Srgrimes config = pci_read_config(dev, PCIR_COMMAND, 2); 1264Srgrimes if ((config & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN)) == 0) 1274Srgrimes return (0); 1284Srgrimes 1294Srgrimes /* This video card is the boot display: record its unit number. */ 1304Srgrimes vga_pci_default_unit = unit; 1314Srgrimes device_set_flags(dev, 1); 13290109Simp 1334Srgrimes return (1); 1344Srgrimes} 13592979Swollman 1364Srgrimesvoid * 1374Srgrimesvga_pci_map_bios(device_t dev, size_t *size) 1384Srgrimes{ 13992979Swollman int rid; 1404Srgrimes struct resource *res; 1414Srgrimes 14292979Swollman#if defined(__amd64__) || defined(__i386__) 14392979Swollman if (vga_pci_is_boot_display(dev)) { 14492979Swollman /* 14592979Swollman * On x86, the System BIOS copy the default display 14692979Swollman * device's Video BIOS at a fixed location in system 14792979Swollman * memory (0xC0000, 128 kBytes long) at boot time. 14892979Swollman * 14992979Swollman * We use this copy for the default boot device, because 15092979Swollman * the original ROM may not be valid after boot. 15192979Swollman */ 15292979Swollman 15392979Swollman *size = VGA_PCI_BIOS_SHADOW_SIZE; 15492979Swollman return (pmap_mapbios(VGA_PCI_BIOS_SHADOW_ADDR, *size)); 15592979Swollman } 15692979Swollman#endif 15792979Swollman 1589909Sjoerg rid = PCIR_BIOS; 15992979Swollman res = vga_pci_alloc_resource(dev, NULL, SYS_RES_MEMORY, &rid, 0ul, 16092979Swollman ~0ul, 1, RF_ACTIVE); 16192979Swollman if (res == NULL) { 16212378Sjoerg return (NULL); 1639909Sjoerg } 1644Srgrimes 1654Srgrimes *size = rman_get_size(res); 1664Srgrimes return (rman_get_virtual(res)); 1674Srgrimes} 1684Srgrimes 16990109Simpvoid 1704Srgrimesvga_pci_unmap_bios(device_t dev, void *bios) 17112378Sjoerg{ 1724Srgrimes struct vga_resource *vr; 1734Srgrimes 1744Srgrimes if (bios == NULL) { 1754Srgrimes return; 17692979Swollman } 17790109Simp 1784Srgrimes#if defined(__amd64__) || defined(__i386__) 17992979Swollman if (vga_pci_is_boot_display(dev)) { 1804Srgrimes /* We mapped the BIOS shadow copy located at 0xC0000. */ 1814Srgrimes pmap_unmapdev((vm_offset_t)bios, VGA_PCI_BIOS_SHADOW_SIZE); 1824Srgrimes 1834Srgrimes return; 18412378Sjoerg } 18512378Sjoerg#endif 1864Srgrimes 18712378Sjoerg /* 18863755Sse * Look up the PCIR_BIOS resource in our softc. It should match 18992979Swollman * the address we returned previously. 19092979Swollman */ 19192979Swollman vr = lookup_res(device_get_softc(dev), PCIR_BIOS); 19292979Swollman KASSERT(vr->vr_res != NULL, ("vga_pci_unmap_bios: bios not mapped")); 1934Srgrimes KASSERT(rman_get_virtual(vr->vr_res) == bios, 19412378Sjoerg ("vga_pci_unmap_bios: mismatch")); 1954Srgrimes vga_pci_release_resource(dev, NULL, SYS_RES_MEMORY, PCIR_BIOS, 1964Srgrimes vr->vr_res); 1974Srgrimes} 1984Srgrimes 1994Srgrimesint 20090109Simpvga_pci_repost(device_t dev) 2014Srgrimes{ 2024Srgrimes#if defined(__amd64__) || (defined(__i386__) && !defined(PC98)) 2034Srgrimes x86regs_t regs; 20412378Sjoerg 2054Srgrimes if (!vga_pci_is_boot_display(dev)) 2064Srgrimes return (EINVAL); 20792979Swollman 20892979Swollman if (x86bios_get_orm(VGA_PCI_BIOS_SHADOW_ADDR) == NULL) 20992979Swollman return (ENOTSUP); 21092979Swollman 21192979Swollman x86bios_init_regs(®s); 21292979Swollman 21392979Swollman regs.R_AH = pci_get_bus(dev); 21492979Swollman regs.R_AL = (pci_get_slot(dev) << 3) | (pci_get_function(dev) & 0x07); 21592979Swollman regs.R_DL = 0x80; 2164Srgrimes 21792979Swollman device_printf(dev, "REPOSTing\n"); 2184Srgrimes x86bios_call(®s, X86BIOS_PHYSTOSEG(VGA_PCI_BIOS_SHADOW_ADDR + 3), 2194Srgrimes X86BIOS_PHYSTOOFF(VGA_PCI_BIOS_SHADOW_ADDR + 3)); 2204Srgrimes 2214Srgrimes x86bios_get_intr(0x10); 2224Srgrimes 2234Srgrimes return (0); 22490109Simp#else 2254Srgrimes return (ENOTSUP); 22612378Sjoerg#endif 2274Srgrimes} 2284Srgrimes 2294Srgrimesstatic int 2304Srgrimesvga_pci_probe(device_t dev) 2314Srgrimes{ 23290109Simp 2334Srgrimes switch (pci_get_class(dev)) { 2344Srgrimes case PCIC_DISPLAY: 2354Srgrimes break; 2364Srgrimes case PCIC_OLD: 2374Srgrimes if (pci_get_subclass(dev) != PCIS_OLD_VGA) 2384Srgrimes return (ENXIO); 2394Srgrimes break; 2404Srgrimes default: 2414Srgrimes return (ENXIO); 2424Srgrimes } 2434Srgrimes 2444Srgrimes /* Probe default display. */ 2454Srgrimes vga_pci_is_boot_display(dev); 2464Srgrimes 2474Srgrimes device_set_desc(dev, "VGA-compatible display"); 2484Srgrimes return (BUS_PROBE_GENERIC); 2494Srgrimes} 2504Srgrimes 2514Srgrimesstatic int 2524Srgrimesvga_pci_attach(device_t dev) 2534Srgrimes{ 2544Srgrimes 2554Srgrimes bus_generic_probe(dev); 2564Srgrimes 25790109Simp /* Always create a drm child for now to make it easier on drm. */ 2584Srgrimes device_add_child(dev, "drm", -1); 2594Srgrimes device_add_child(dev, "drmn", -1); 2604Srgrimes bus_generic_attach(dev); 2614Srgrimes 262181Sconklin if (vga_pci_is_boot_display(dev)) 2634Srgrimes device_printf(dev, "Boot video device\n"); 2644Srgrimes 2654Srgrimes return (0); 2664Srgrimes} 26712378Sjoerg 26892979Swollmanstatic int 2694Srgrimesvga_pci_suspend(device_t dev) 27092979Swollman{ 27192979Swollman 272468Sjtc return (bus_generic_suspend(dev)); 27392979Swollman} 27492979Swollman 27592979Swollmanstatic int 27692979Swollmanvga_pci_resume(device_t dev) 27792979Swollman{ 27892979Swollman 279468Sjtc return (bus_generic_resume(dev)); 28092979Swollman} 2814Srgrimes 28292979Swollman/* Bus interface. */ 2834Srgrimes 2844Srgrimesstatic int 28592979Swollmanvga_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 2864Srgrimes{ 28792979Swollman 2884Srgrimes return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result)); 28992979Swollman} 2904Srgrimes 2914Srgrimesstatic int 2924Srgrimesvga_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 29390109Simp{ 2944Srgrimes 29592979Swollman return (EINVAL); 2964Srgrimes} 2974Srgrimes 2984Srgrimesstatic int 2994Srgrimesvga_pci_setup_intr(device_t dev, device_t child, struct resource *irq, 30090109Simp int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg, 3014Srgrimes void **cookiep) 3024Srgrimes{ 3034Srgrimes return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags, 3044Srgrimes filter, intr, arg, cookiep)); 3054Srgrimes} 3064Srgrimes 3074Srgrimesstatic int 3084Srgrimesvga_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, 3094Srgrimes void *cookie) 3104Srgrimes{ 3114Srgrimes return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie)); 31290109Simp} 3134Srgrimes 3144Srgrimesstatic struct vga_resource * 3154Srgrimeslookup_res(struct vga_pci_softc *sc, int rid) 3164Srgrimes{ 31792979Swollman int bar; 3184Srgrimes 3194Srgrimes if (rid == PCIR_BIOS) 3204Srgrimes return (&sc->vga_bios); 3214Srgrimes bar = PCI_RID2BAR(rid); 3224Srgrimes if (bar >= 0 && bar <= PCIR_MAX_BAR_0) 3234Srgrimes return (&sc->vga_bars[bar]); 3244Srgrimes return (NULL); 32590109Simp} 3264Srgrimes 3274Srgrimesstatic struct resource * 3284Srgrimesvga_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, 3294Srgrimes u_long start, u_long end, u_long count, u_int flags) 3304Srgrimes{ 3314Srgrimes struct vga_resource *vr; 33292979Swollman 3334Srgrimes switch (type) { 33412378Sjoerg case SYS_RES_MEMORY: 33512378Sjoerg case SYS_RES_IOPORT: 33692979Swollman /* 3374Srgrimes * For BARs, we cache the resource so that we only allocate it 3384Srgrimes * from the PCI bus once. 3394Srgrimes */ 3404Srgrimes vr = lookup_res(device_get_softc(dev), *rid); 3414Srgrimes if (vr == NULL) 3424Srgrimes return (NULL); 3434Srgrimes if (vr->vr_res == NULL) 3444Srgrimes vr->vr_res = bus_alloc_resource(dev, type, rid, start, 34590109Simp end, count, flags); 3464Srgrimes if (vr->vr_res != NULL) 3474Srgrimes vr->vr_refs++; 3484Srgrimes return (vr->vr_res); 3494Srgrimes } 3504Srgrimes return (bus_alloc_resource(dev, type, rid, start, end, count, flags)); 3514Srgrimes} 35292979Swollman 3534Srgrimesstatic int 35412378Sjoergvga_pci_release_resource(device_t dev, device_t child, int type, int rid, 35512378Sjoerg struct resource *r) 35692979Swollman{ 3574Srgrimes struct vga_resource *vr; 3584Srgrimes int error; 3594Srgrimes 3604Srgrimes switch (type) { 3614Srgrimes case SYS_RES_MEMORY: 3624Srgrimes case SYS_RES_IOPORT: 3634Srgrimes /* 3644Srgrimes * For BARs, we release the resource from the PCI bus 36590109Simp * when the last child reference goes away. 3664Srgrimes */ 3674Srgrimes vr = lookup_res(device_get_softc(dev), rid); 3684Srgrimes if (vr == NULL) 3694Srgrimes return (EINVAL); 3704Srgrimes if (vr->vr_res == NULL) 3714Srgrimes return (EINVAL); 37292979Swollman KASSERT(vr->vr_res == r, ("vga_pci resource mismatch")); 3734Srgrimes if (vr->vr_refs > 1) { 37412378Sjoerg vr->vr_refs--; 37512378Sjoerg return (0); 37692979Swollman } 3774Srgrimes KASSERT(vr->vr_refs > 0, 3784Srgrimes ("vga_pci resource reference count underflow")); 3794Srgrimes error = bus_release_resource(dev, type, rid, r); 3804Srgrimes if (error == 0) { 3814Srgrimes vr->vr_res = NULL; 3824Srgrimes vr->vr_refs = 0; 3834Srgrimes } 3844Srgrimes return (error); 38590109Simp } 3864Srgrimes 3874Srgrimes return (bus_release_resource(dev, type, rid, r)); 3884Srgrimes} 3894Srgrimes 3904Srgrimes/* PCI interface. */ 3914Srgrimes 39292979Swollmanstatic uint32_t 3934Srgrimesvga_pci_read_config(device_t dev, device_t child, int reg, int width) 39412378Sjoerg{ 39512378Sjoerg 39692979Swollman return (pci_read_config(dev, reg, width)); 3974Srgrimes} 3984Srgrimes 3994Srgrimesstatic void 4004Srgrimesvga_pci_write_config(device_t dev, device_t child, int reg, 4014Srgrimes uint32_t val, int width) 4024Srgrimes{ 4034Srgrimes 4044Srgrimes pci_write_config(dev, reg, val, width); 40590109Simp} 4064Srgrimes 4074Srgrimesstatic int 4084Srgrimesvga_pci_enable_busmaster(device_t dev, device_t child) 4094Srgrimes{ 4104Srgrimes 4114Srgrimes return (pci_enable_busmaster(dev)); 41292979Swollman} 4134Srgrimes 41412378Sjoergstatic int 41512378Sjoergvga_pci_disable_busmaster(device_t dev, device_t child) 41692979Swollman{ 4174Srgrimes 4184Srgrimes return (pci_disable_busmaster(dev)); 4194Srgrimes} 4204Srgrimes 4214Srgrimesstatic int 4224Srgrimesvga_pci_enable_io(device_t dev, device_t child, int space) 4234Srgrimes{ 4244Srgrimes 42590109Simp device_printf(dev, "child %s requested pci_enable_io\n", 4264Srgrimes device_get_nameunit(child)); 4274Srgrimes return (pci_enable_io(dev, space)); 4284Srgrimes} 4294Srgrimes 4304Srgrimesstatic int 4314Srgrimesvga_pci_disable_io(device_t dev, device_t child, int space) 43292979Swollman{ 4334Srgrimes 43412378Sjoerg device_printf(dev, "child %s requested pci_disable_io\n", 43512378Sjoerg device_get_nameunit(child)); 43692979Swollman return (pci_disable_io(dev, space)); 4374Srgrimes} 4384Srgrimes 4394Srgrimesstatic int 4404Srgrimesvga_pci_get_vpd_ident(device_t dev, device_t child, const char **identptr) 4414Srgrimes{ 4424Srgrimes 4434Srgrimes return (pci_get_vpd_ident(dev, identptr)); 44463755Sse} 44592979Swollman 44663755Ssestatic int 44763755Ssevga_pci_get_vpd_readonly(device_t dev, device_t child, const char *kw, 44863755Sse const char **vptr) 44963755Sse{ 45063755Sse 45163755Sse return (pci_get_vpd_readonly(dev, kw, vptr)); 45263755Sse} 45363755Sse 45463755Ssestatic int 45563755Ssevga_pci_set_powerstate(device_t dev, device_t child, int state) 45663755Sse{ 4574Srgrimes 45890109Simp device_printf(dev, "child %s requested pci_set_powerstate\n", 4594Srgrimes device_get_nameunit(child)); 4604Srgrimes return (pci_set_powerstate(dev, state)); 4614Srgrimes} 4624Srgrimes 46392979Swollmanstatic int 4644Srgrimesvga_pci_get_powerstate(device_t dev, device_t child) 4654Srgrimes{ 46692979Swollman 46763755Sse device_printf(dev, "child %s requested pci_get_powerstate\n", 46892979Swollman device_get_nameunit(child)); 46963755Sse return (pci_get_powerstate(dev)); 4704Srgrimes} 4714Srgrimes 4724Srgrimesstatic int 4734Srgrimesvga_pci_assign_interrupt(device_t dev, device_t child) 47463755Sse{ 47563755Sse 47692979Swollman device_printf(dev, "child %s requested pci_assign_interrupt\n", 47763755Sse device_get_nameunit(child)); 47892979Swollman return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev)); 47992979Swollman} 48063755Sse 48163755Ssestatic int 48263755Ssevga_pci_find_cap(device_t dev, device_t child, int capability, 48363755Sse int *capreg) 48463755Sse{ 48592979Swollman 48663755Sse return (pci_find_cap(dev, capability, capreg)); 48763755Sse} 48863755Sse 4894Srgrimesstatic int 49090109Simpvga_pci_find_extcap(device_t dev, device_t child, int capability, 4914Srgrimes int *capreg) 4924Srgrimes{ 4934Srgrimes 4944Srgrimes return (pci_find_extcap(dev, capability, capreg)); 49592979Swollman} 4964Srgrimes 4974Srgrimesstatic int 49892979Swollmanvga_pci_find_htcap(device_t dev, device_t child, int capability, 49963755Sse int *capreg) 50092979Swollman{ 50163755Sse 5024Srgrimes return (pci_find_htcap(dev, capability, capreg)); 5034Srgrimes} 5044Srgrimes 5054Srgrimesstatic int 50663755Ssevga_pci_alloc_msi(device_t dev, device_t child, int *count) 50763755Sse{ 50892979Swollman struct vga_pci_softc *sc; 50963755Sse int error; 51063755Sse 51163755Sse sc = device_get_softc(dev); 51263755Sse if (sc->vga_msi_child != NULL) 51363755Sse return (EBUSY); 51463755Sse error = pci_alloc_msi(dev, count); 51563755Sse if (error == 0) 51663755Sse sc->vga_msi_child = child; 51763755Sse return (error); 51863755Sse} 5194Srgrimes 52090109Simpstatic int 5214Srgrimesvga_pci_alloc_msix(device_t dev, device_t child, int *count) 5224Srgrimes{ 5234Srgrimes struct vga_pci_softc *sc; 5244Srgrimes int error; 52592979Swollman 5264Srgrimes sc = device_get_softc(dev); 5274Srgrimes if (sc->vga_msi_child != NULL) 52892979Swollman return (EBUSY); 52963755Sse error = pci_alloc_msix(dev, count); 53092979Swollman if (error == 0) 53163755Sse sc->vga_msi_child = child; 5324Srgrimes return (error); 5334Srgrimes} 5344Srgrimes 5354Srgrimesstatic int 53663755Ssevga_pci_remap_msix(device_t dev, device_t child, int count, 53763755Sse const u_int *vectors) 53892979Swollman{ 53963755Sse struct vga_pci_softc *sc; 54063755Sse 54192979Swollman sc = device_get_softc(dev); 54292979Swollman if (sc->vga_msi_child != child) 54363755Sse return (ENXIO); 54463755Sse return (pci_remap_msix(dev, count, vectors)); 54563755Sse} 54663755Sse 54763755Ssestatic int 5484Srgrimesvga_pci_release_msi(device_t dev, device_t child) 54990109Simp{ 5504Srgrimes struct vga_pci_softc *sc; 5514Srgrimes int error; 5524Srgrimes 5534Srgrimes sc = device_get_softc(dev); 55492979Swollman if (sc->vga_msi_child != child) 5554Srgrimes return (ENXIO); 5564Srgrimes error = pci_release_msi(dev); 5574Srgrimes if (error == 0) 55892979Swollman sc->vga_msi_child = NULL; 5594Srgrimes return (error); 5604Srgrimes} 56192979Swollman 56277244Skrisstatic int 56392979Swollmanvga_pci_msi_count(device_t dev, device_t child) 56463755Sse{ 5654Srgrimes 5664Srgrimes return (pci_msi_count(dev)); 5674Srgrimes} 5684Srgrimes 5694Srgrimesstatic int 5704Srgrimesvga_pci_msix_count(device_t dev, device_t child) 57190109Simp{ 5724Srgrimes 5734Srgrimes return (pci_msix_count(dev)); 5744Srgrimes} 5754Srgrimes 57692979Swollmanstatic bus_dma_tag_t 5774Srgrimesvga_pci_get_dma_tag(device_t bus, device_t child) 5784Srgrimes{ 5794Srgrimes 58092979Swollman return (bus_get_dma_tag(bus)); 5814Srgrimes} 5824Srgrimes 58392979Swollmanstatic device_method_t vga_pci_methods[] = { 58463755Sse /* Device interface */ 5854Srgrimes DEVMETHOD(device_probe, vga_pci_probe), 5864Srgrimes DEVMETHOD(device_attach, vga_pci_attach), 5874Srgrimes DEVMETHOD(device_shutdown, bus_generic_shutdown), 5884Srgrimes DEVMETHOD(device_suspend, vga_pci_suspend), 5894Srgrimes DEVMETHOD(device_resume, vga_pci_resume), 5904Srgrimes 59190109Simp /* Bus interface */ 5924Srgrimes DEVMETHOD(bus_read_ivar, vga_pci_read_ivar), 59331Salm DEVMETHOD(bus_write_ivar, vga_pci_write_ivar), 594468Sjtc DEVMETHOD(bus_setup_intr, vga_pci_setup_intr), 59531Salm DEVMETHOD(bus_teardown_intr, vga_pci_teardown_intr), 59631Salm DEVMETHOD(bus_alloc_resource, vga_pci_alloc_resource), 597181Sconklin DEVMETHOD(bus_release_resource, vga_pci_release_resource), 5984Srgrimes DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 599181Sconklin DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 600181Sconklin DEVMETHOD(bus_get_dma_tag, vga_pci_get_dma_tag), 601181Sconklin 602181Sconklin /* PCI interface */ 60331Salm DEVMETHOD(pci_read_config, vga_pci_read_config), 604539Sjtc DEVMETHOD(pci_write_config, vga_pci_write_config), 60531Salm DEVMETHOD(pci_enable_busmaster, vga_pci_enable_busmaster), 60692979Swollman DEVMETHOD(pci_disable_busmaster, vga_pci_disable_busmaster), 6074Srgrimes DEVMETHOD(pci_enable_io, vga_pci_enable_io), 6084Srgrimes DEVMETHOD(pci_disable_io, vga_pci_disable_io), 60931Salm DEVMETHOD(pci_get_vpd_ident, vga_pci_get_vpd_ident), 610539Sjtc DEVMETHOD(pci_get_vpd_readonly, vga_pci_get_vpd_readonly), 61177244Skris DEVMETHOD(pci_get_powerstate, vga_pci_get_powerstate), 61231Salm DEVMETHOD(pci_set_powerstate, vga_pci_set_powerstate), 613295Sjtc DEVMETHOD(pci_assign_interrupt, vga_pci_assign_interrupt), 61431Salm DEVMETHOD(pci_find_cap, vga_pci_find_cap), 61531Salm DEVMETHOD(pci_find_extcap, vga_pci_find_extcap), 6164Srgrimes DEVMETHOD(pci_find_htcap, vga_pci_find_htcap), 61792979Swollman DEVMETHOD(pci_alloc_msi, vga_pci_alloc_msi), 6184Srgrimes DEVMETHOD(pci_alloc_msix, vga_pci_alloc_msix), 6194Srgrimes DEVMETHOD(pci_remap_msix, vga_pci_remap_msix), 620295Sjtc DEVMETHOD(pci_release_msi, vga_pci_release_msi), 62192979Swollman DEVMETHOD(pci_msi_count, vga_pci_msi_count), 622295Sjtc DEVMETHOD(pci_msix_count, vga_pci_msix_count), 623295Sjtc 624295Sjtc { 0, 0 } 6254Srgrimes}; 6264Srgrimes 62731Salmstatic driver_t vga_pci_driver = { 62831Salm "vgapci", 62931Salm vga_pci_methods, 63031Salm sizeof(struct vga_pci_softc), 63131Salm}; 63231Salm 6334Srgrimesstatic devclass_t vga_devclass; 634 635DRIVER_MODULE(vgapci, pci, vga_pci_driver, vga_devclass, 0, 0); 636MODULE_DEPEND(vgapci, x86bios, 1, 1, 1); 637