1718cf2ccSPedro F. Giffuni /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3718cf2ccSPedro F. Giffuni * 45b211922SJohn Baldwin * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 55b211922SJohn Baldwin * All rights reserved. 65b211922SJohn Baldwin * 75b211922SJohn Baldwin * Redistribution and use in source and binary forms, with or without 85b211922SJohn Baldwin * modification, are permitted provided that the following conditions 95b211922SJohn Baldwin * are met: 105b211922SJohn Baldwin * 1. Redistributions of source code must retain the above copyright 115b211922SJohn Baldwin * notice unmodified, this list of conditions, and the following 125b211922SJohn Baldwin * disclaimer. 135b211922SJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 145b211922SJohn Baldwin * notice, this list of conditions and the following disclaimer in the 155b211922SJohn Baldwin * documentation and/or other materials provided with the distribution. 165b211922SJohn Baldwin * 175b211922SJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 185b211922SJohn Baldwin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 195b211922SJohn Baldwin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 205b211922SJohn Baldwin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 215b211922SJohn Baldwin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 225b211922SJohn Baldwin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235b211922SJohn Baldwin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245b211922SJohn Baldwin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255b211922SJohn Baldwin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 265b211922SJohn Baldwin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275b211922SJohn Baldwin */ 285b211922SJohn Baldwin 295b211922SJohn Baldwin #include <sys/cdefs.h> 305b211922SJohn Baldwin __FBSDID("$FreeBSD$"); 315b211922SJohn Baldwin 325b211922SJohn Baldwin #include <sys/param.h> 335b211922SJohn Baldwin #include <sys/bus.h> 345b211922SJohn Baldwin #include <sys/kernel.h> 355b211922SJohn Baldwin #include <sys/module.h> 365b211922SJohn Baldwin 375b211922SJohn Baldwin #include <dev/pci/pcivar.h> 385b211922SJohn Baldwin #include <dev/pci/pcireg.h> 395b211922SJohn Baldwin 405b211922SJohn Baldwin /* 415b211922SJohn Baldwin * Provide a device to "eat" the host->pci bridge devices that show up 42db4fcadfSConrad Meyer * on PCI buses and stop them showing up twice on the probes. This also 435b211922SJohn Baldwin * stops them showing up as 'none' in pciconf -l. If the host bridge 445b211922SJohn Baldwin * provides an AGP capability then we create a child agp device for the 455b211922SJohn Baldwin * agp GART driver to attach to. 465b211922SJohn Baldwin */ 475b211922SJohn Baldwin static int 485b211922SJohn Baldwin pci_hostb_probe(device_t dev) 495b211922SJohn Baldwin { 505b211922SJohn Baldwin u_int32_t id; 515b211922SJohn Baldwin 525b211922SJohn Baldwin id = pci_get_devid(dev); 535b211922SJohn Baldwin 545b211922SJohn Baldwin switch (id) { 555b211922SJohn Baldwin 56453130d9SPedro F. Giffuni /* VIA VT82C596 Power Management Function */ 575b211922SJohn Baldwin case 0x30501106: 585b211922SJohn Baldwin return (ENXIO); 595b211922SJohn Baldwin 605b211922SJohn Baldwin default: 615b211922SJohn Baldwin break; 625b211922SJohn Baldwin } 635b211922SJohn Baldwin 645b211922SJohn Baldwin if (pci_get_class(dev) == PCIC_BRIDGE && 655b211922SJohn Baldwin pci_get_subclass(dev) == PCIS_BRIDGE_HOST) { 665b211922SJohn Baldwin device_set_desc(dev, "Host to PCI bridge"); 675b211922SJohn Baldwin device_quiet(dev); 68b7cbd25bSMarcel Moolenaar return (-10000); 695b211922SJohn Baldwin } 705b211922SJohn Baldwin return (ENXIO); 715b211922SJohn Baldwin } 725b211922SJohn Baldwin 735b211922SJohn Baldwin static int 745b211922SJohn Baldwin pci_hostb_attach(device_t dev) 755b211922SJohn Baldwin { 765b211922SJohn Baldwin 775b211922SJohn Baldwin bus_generic_probe(dev); 785b211922SJohn Baldwin 795b211922SJohn Baldwin /* 805b211922SJohn Baldwin * If AGP capabilities are present on this device, then create 815b211922SJohn Baldwin * an AGP child. 825b211922SJohn Baldwin */ 833b0a4aefSJohn Baldwin if (pci_find_cap(dev, PCIY_AGP, NULL) == 0) 845b211922SJohn Baldwin device_add_child(dev, "agp", -1); 855b211922SJohn Baldwin bus_generic_attach(dev); 865b211922SJohn Baldwin return (0); 875b211922SJohn Baldwin } 885b211922SJohn Baldwin 895b211922SJohn Baldwin /* Bus interface. */ 905b211922SJohn Baldwin 915b211922SJohn Baldwin static int 925b211922SJohn Baldwin pci_hostb_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 935b211922SJohn Baldwin { 945b211922SJohn Baldwin 955b211922SJohn Baldwin return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result)); 965b211922SJohn Baldwin } 975b211922SJohn Baldwin 985b211922SJohn Baldwin static int 995b211922SJohn Baldwin pci_hostb_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 1005b211922SJohn Baldwin { 1015b211922SJohn Baldwin 1025b211922SJohn Baldwin return (EINVAL); 1035b211922SJohn Baldwin } 1045b211922SJohn Baldwin 1055b211922SJohn Baldwin static struct resource * 1065b211922SJohn Baldwin pci_hostb_alloc_resource(device_t dev, device_t child, int type, int *rid, 1072dd1bdf1SJustin Hibbits rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 1085b211922SJohn Baldwin { 1095b211922SJohn Baldwin 1105b211922SJohn Baldwin return (bus_alloc_resource(dev, type, rid, start, end, count, flags)); 1115b211922SJohn Baldwin } 1125b211922SJohn Baldwin 1135b211922SJohn Baldwin static int 1145b211922SJohn Baldwin pci_hostb_release_resource(device_t dev, device_t child, int type, int rid, 1155b211922SJohn Baldwin struct resource *r) 1165b211922SJohn Baldwin { 1175b211922SJohn Baldwin 1185b211922SJohn Baldwin return (bus_release_resource(dev, type, rid, r)); 1195b211922SJohn Baldwin } 1205b211922SJohn Baldwin 1215b211922SJohn Baldwin /* PCI interface. */ 1225b211922SJohn Baldwin 1235b211922SJohn Baldwin static uint32_t 1245b211922SJohn Baldwin pci_hostb_read_config(device_t dev, device_t child, int reg, int width) 1255b211922SJohn Baldwin { 1265b211922SJohn Baldwin 1275b211922SJohn Baldwin return (pci_read_config(dev, reg, width)); 1285b211922SJohn Baldwin } 1295b211922SJohn Baldwin 1305b211922SJohn Baldwin static void 1315b211922SJohn Baldwin pci_hostb_write_config(device_t dev, device_t child, int reg, 1325b211922SJohn Baldwin uint32_t val, int width) 1335b211922SJohn Baldwin { 1345b211922SJohn Baldwin 1355b211922SJohn Baldwin pci_write_config(dev, reg, val, width); 1365b211922SJohn Baldwin } 1375b211922SJohn Baldwin 1385b211922SJohn Baldwin static int 1395b211922SJohn Baldwin pci_hostb_enable_busmaster(device_t dev, device_t child) 1405b211922SJohn Baldwin { 1415b211922SJohn Baldwin 1425b211922SJohn Baldwin device_printf(dev, "child %s requested pci_enable_busmaster\n", 1435b211922SJohn Baldwin device_get_nameunit(child)); 1445b211922SJohn Baldwin return (pci_enable_busmaster(dev)); 1455b211922SJohn Baldwin } 1465b211922SJohn Baldwin 1475b211922SJohn Baldwin static int 1485b211922SJohn Baldwin pci_hostb_disable_busmaster(device_t dev, device_t child) 1495b211922SJohn Baldwin { 1505b211922SJohn Baldwin 1515b211922SJohn Baldwin device_printf(dev, "child %s requested pci_disable_busmaster\n", 1525b211922SJohn Baldwin device_get_nameunit(child)); 1535b211922SJohn Baldwin return (pci_disable_busmaster(dev)); 1545b211922SJohn Baldwin } 1555b211922SJohn Baldwin 1565b211922SJohn Baldwin static int 1575b211922SJohn Baldwin pci_hostb_enable_io(device_t dev, device_t child, int space) 1585b211922SJohn Baldwin { 1595b211922SJohn Baldwin 1605b211922SJohn Baldwin device_printf(dev, "child %s requested pci_enable_io\n", 1615b211922SJohn Baldwin device_get_nameunit(child)); 1625b211922SJohn Baldwin return (pci_enable_io(dev, space)); 1635b211922SJohn Baldwin } 1645b211922SJohn Baldwin 1655b211922SJohn Baldwin static int 1665b211922SJohn Baldwin pci_hostb_disable_io(device_t dev, device_t child, int space) 1675b211922SJohn Baldwin { 1685b211922SJohn Baldwin 1695b211922SJohn Baldwin device_printf(dev, "child %s requested pci_disable_io\n", 1705b211922SJohn Baldwin device_get_nameunit(child)); 1715b211922SJohn Baldwin return (pci_disable_io(dev, space)); 1725b211922SJohn Baldwin } 1735b211922SJohn Baldwin 1745b211922SJohn Baldwin static int 1755b211922SJohn Baldwin pci_hostb_set_powerstate(device_t dev, device_t child, int state) 1765b211922SJohn Baldwin { 1775b211922SJohn Baldwin 1785b211922SJohn Baldwin device_printf(dev, "child %s requested pci_set_powerstate\n", 1795b211922SJohn Baldwin device_get_nameunit(child)); 1805b211922SJohn Baldwin return (pci_set_powerstate(dev, state)); 1815b211922SJohn Baldwin } 1825b211922SJohn Baldwin 1835b211922SJohn Baldwin static int 1845b211922SJohn Baldwin pci_hostb_get_powerstate(device_t dev, device_t child) 1855b211922SJohn Baldwin { 1865b211922SJohn Baldwin 1875b211922SJohn Baldwin device_printf(dev, "child %s requested pci_get_powerstate\n", 1885b211922SJohn Baldwin device_get_nameunit(child)); 1895b211922SJohn Baldwin return (pci_get_powerstate(dev)); 1905b211922SJohn Baldwin } 1915b211922SJohn Baldwin 1925b211922SJohn Baldwin static int 1935b211922SJohn Baldwin pci_hostb_assign_interrupt(device_t dev, device_t child) 1945b211922SJohn Baldwin { 1955b211922SJohn Baldwin 1965b211922SJohn Baldwin device_printf(dev, "child %s requested pci_assign_interrupt\n", 1975b211922SJohn Baldwin device_get_nameunit(child)); 1985b211922SJohn Baldwin return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev)); 1995b211922SJohn Baldwin } 2005b211922SJohn Baldwin 2015b211922SJohn Baldwin static int 202c668000bSJohn Baldwin pci_hostb_find_cap(device_t dev, device_t child, int capability, 203c668000bSJohn Baldwin int *capreg) 204c668000bSJohn Baldwin { 205c668000bSJohn Baldwin 206c668000bSJohn Baldwin return (pci_find_cap(dev, capability, capreg)); 207c668000bSJohn Baldwin } 208c668000bSJohn Baldwin 209c668000bSJohn Baldwin static int 210*7a16dacdSBryan Venteicher pci_hostb_find_next_cap(device_t dev, device_t child, int capability, 211*7a16dacdSBryan Venteicher int start, int *capreg) 212*7a16dacdSBryan Venteicher { 213*7a16dacdSBryan Venteicher 214*7a16dacdSBryan Venteicher return (pci_find_next_cap(dev, capability, start, capreg)); 215*7a16dacdSBryan Venteicher } 216*7a16dacdSBryan Venteicher 217*7a16dacdSBryan Venteicher static int 2185b211922SJohn Baldwin pci_hostb_find_extcap(device_t dev, device_t child, int capability, 2195b211922SJohn Baldwin int *capreg) 2205b211922SJohn Baldwin { 2215b211922SJohn Baldwin 2225b211922SJohn Baldwin return (pci_find_extcap(dev, capability, capreg)); 2235b211922SJohn Baldwin } 2245b211922SJohn Baldwin 225c668000bSJohn Baldwin static int 226*7a16dacdSBryan Venteicher pci_hostb_find_next_extcap(device_t dev, device_t child, int capability, 227*7a16dacdSBryan Venteicher int start, int *capreg) 228*7a16dacdSBryan Venteicher { 229*7a16dacdSBryan Venteicher 230*7a16dacdSBryan Venteicher return (pci_find_next_extcap(dev, capability, start, capreg)); 231*7a16dacdSBryan Venteicher } 232*7a16dacdSBryan Venteicher 233*7a16dacdSBryan Venteicher static int 234c668000bSJohn Baldwin pci_hostb_find_htcap(device_t dev, device_t child, int capability, 235c668000bSJohn Baldwin int *capreg) 236c668000bSJohn Baldwin { 237c668000bSJohn Baldwin 238c668000bSJohn Baldwin return (pci_find_htcap(dev, capability, capreg)); 239c668000bSJohn Baldwin } 240c668000bSJohn Baldwin 241*7a16dacdSBryan Venteicher static int 242*7a16dacdSBryan Venteicher pci_hostb_find_next_htcap(device_t dev, device_t child, int capability, 243*7a16dacdSBryan Venteicher int start, int *capreg) 244*7a16dacdSBryan Venteicher { 245*7a16dacdSBryan Venteicher 246*7a16dacdSBryan Venteicher return (pci_find_next_htcap(dev, capability, start, capreg)); 247*7a16dacdSBryan Venteicher } 248*7a16dacdSBryan Venteicher 2495b211922SJohn Baldwin static device_method_t pci_hostb_methods[] = { 2505b211922SJohn Baldwin /* Device interface */ 2515b211922SJohn Baldwin DEVMETHOD(device_probe, pci_hostb_probe), 2525b211922SJohn Baldwin DEVMETHOD(device_attach, pci_hostb_attach), 2535b211922SJohn Baldwin DEVMETHOD(device_shutdown, bus_generic_shutdown), 2545b211922SJohn Baldwin DEVMETHOD(device_suspend, bus_generic_suspend), 2555b211922SJohn Baldwin DEVMETHOD(device_resume, bus_generic_resume), 2565b211922SJohn Baldwin 2575b211922SJohn Baldwin /* Bus interface */ 2585b211922SJohn Baldwin DEVMETHOD(bus_read_ivar, pci_hostb_read_ivar), 2595b211922SJohn Baldwin DEVMETHOD(bus_write_ivar, pci_hostb_write_ivar), 2605b211922SJohn Baldwin DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 2615b211922SJohn Baldwin DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 2625b211922SJohn Baldwin 2635b211922SJohn Baldwin DEVMETHOD(bus_alloc_resource, pci_hostb_alloc_resource), 2645b211922SJohn Baldwin DEVMETHOD(bus_release_resource, pci_hostb_release_resource), 2655b211922SJohn Baldwin DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 2665b211922SJohn Baldwin DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 2675b211922SJohn Baldwin 2685b211922SJohn Baldwin /* PCI interface */ 2695b211922SJohn Baldwin DEVMETHOD(pci_read_config, pci_hostb_read_config), 2705b211922SJohn Baldwin DEVMETHOD(pci_write_config, pci_hostb_write_config), 2715b211922SJohn Baldwin DEVMETHOD(pci_enable_busmaster, pci_hostb_enable_busmaster), 2725b211922SJohn Baldwin DEVMETHOD(pci_disable_busmaster, pci_hostb_disable_busmaster), 2735b211922SJohn Baldwin DEVMETHOD(pci_enable_io, pci_hostb_enable_io), 2745b211922SJohn Baldwin DEVMETHOD(pci_disable_io, pci_hostb_disable_io), 2755b211922SJohn Baldwin DEVMETHOD(pci_get_powerstate, pci_hostb_get_powerstate), 2765b211922SJohn Baldwin DEVMETHOD(pci_set_powerstate, pci_hostb_set_powerstate), 2775b211922SJohn Baldwin DEVMETHOD(pci_assign_interrupt, pci_hostb_assign_interrupt), 278c668000bSJohn Baldwin DEVMETHOD(pci_find_cap, pci_hostb_find_cap), 279*7a16dacdSBryan Venteicher DEVMETHOD(pci_find_next_cap, pci_hostb_find_next_cap), 2805b211922SJohn Baldwin DEVMETHOD(pci_find_extcap, pci_hostb_find_extcap), 281*7a16dacdSBryan Venteicher DEVMETHOD(pci_find_next_extcap, pci_hostb_find_next_extcap), 282c668000bSJohn Baldwin DEVMETHOD(pci_find_htcap, pci_hostb_find_htcap), 283*7a16dacdSBryan Venteicher DEVMETHOD(pci_find_next_htcap, pci_hostb_find_next_htcap), 2845b211922SJohn Baldwin 2855b211922SJohn Baldwin { 0, 0 } 2865b211922SJohn Baldwin }; 2875b211922SJohn Baldwin 2885b211922SJohn Baldwin static driver_t pci_hostb_driver = { 2895b211922SJohn Baldwin "hostb", 2905b211922SJohn Baldwin pci_hostb_methods, 2915b211922SJohn Baldwin 1, 2925b211922SJohn Baldwin }; 2935b211922SJohn Baldwin 2945b211922SJohn Baldwin static devclass_t pci_hostb_devclass; 2955b211922SJohn Baldwin 2965b211922SJohn Baldwin DRIVER_MODULE(hostb, pci, pci_hostb_driver, pci_hostb_devclass, 0, 0); 297