1718cf2ccSPedro F. Giffuni /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 4fce5d19dSStefan Eßer * Copyright 1997, Stefan Esser <se@freebsd.org> 55b211922SJohn Baldwin * 65b211922SJohn Baldwin * Redistribution and use in source and binary forms, with or without 75b211922SJohn Baldwin * modification, are permitted provided that the following conditions 85b211922SJohn Baldwin * are met: 95b211922SJohn Baldwin * 1. Redistributions of source code must retain the above copyright 105b211922SJohn Baldwin * notice unmodified, this list of conditions, and the following 115b211922SJohn Baldwin * disclaimer. 125b211922SJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 135b211922SJohn Baldwin * notice, this list of conditions and the following disclaimer in the 145b211922SJohn Baldwin * documentation and/or other materials provided with the distribution. 155b211922SJohn Baldwin * 165b211922SJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 175b211922SJohn Baldwin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 185b211922SJohn Baldwin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 195b211922SJohn Baldwin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 205b211922SJohn Baldwin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 215b211922SJohn Baldwin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 225b211922SJohn Baldwin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 235b211922SJohn Baldwin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 245b211922SJohn Baldwin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 255b211922SJohn Baldwin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265b211922SJohn Baldwin */ 275b211922SJohn Baldwin 285b211922SJohn Baldwin #include <sys/param.h> 295b211922SJohn Baldwin #include <sys/bus.h> 305b211922SJohn Baldwin #include <sys/kernel.h> 315b211922SJohn Baldwin #include <sys/module.h> 325b211922SJohn Baldwin 335b211922SJohn Baldwin #include <dev/pci/pcivar.h> 345b211922SJohn Baldwin #include <dev/pci/pcireg.h> 355b211922SJohn Baldwin 365b211922SJohn Baldwin /* 375b211922SJohn Baldwin * Provide a device to "eat" the host->pci bridge devices that show up 38db4fcadfSConrad Meyer * on PCI buses and stop them showing up twice on the probes. This also 395b211922SJohn Baldwin * stops them showing up as 'none' in pciconf -l. If the host bridge 405b211922SJohn Baldwin * provides an AGP capability then we create a child agp device for the 415b211922SJohn Baldwin * agp GART driver to attach to. 425b211922SJohn Baldwin */ 435b211922SJohn Baldwin static int 445b211922SJohn Baldwin pci_hostb_probe(device_t dev) 455b211922SJohn Baldwin { 465b211922SJohn Baldwin u_int32_t id; 475b211922SJohn Baldwin 485b211922SJohn Baldwin id = pci_get_devid(dev); 495b211922SJohn Baldwin 505b211922SJohn Baldwin switch (id) { 51453130d9SPedro F. Giffuni /* VIA VT82C596 Power Management Function */ 525b211922SJohn Baldwin case 0x30501106: 535b211922SJohn Baldwin return (ENXIO); 545b211922SJohn Baldwin 555b211922SJohn Baldwin default: 565b211922SJohn Baldwin break; 575b211922SJohn Baldwin } 585b211922SJohn Baldwin 595b211922SJohn Baldwin if (pci_get_class(dev) == PCIC_BRIDGE && 605b211922SJohn Baldwin pci_get_subclass(dev) == PCIS_BRIDGE_HOST) { 615b211922SJohn Baldwin device_set_desc(dev, "Host to PCI bridge"); 625b211922SJohn Baldwin device_quiet(dev); 63b7cbd25bSMarcel Moolenaar return (-10000); 645b211922SJohn Baldwin } 655b211922SJohn Baldwin return (ENXIO); 665b211922SJohn Baldwin } 675b211922SJohn Baldwin 685b211922SJohn Baldwin static int 695b211922SJohn Baldwin pci_hostb_attach(device_t dev) 705b211922SJohn Baldwin { 715b211922SJohn Baldwin 725b211922SJohn Baldwin bus_generic_probe(dev); 735b211922SJohn Baldwin 745b211922SJohn Baldwin /* 755b211922SJohn Baldwin * If AGP capabilities are present on this device, then create 765b211922SJohn Baldwin * an AGP child. 775b211922SJohn Baldwin */ 783b0a4aefSJohn Baldwin if (pci_find_cap(dev, PCIY_AGP, NULL) == 0) 795b211922SJohn Baldwin device_add_child(dev, "agp", -1); 805b211922SJohn Baldwin bus_generic_attach(dev); 815b211922SJohn Baldwin return (0); 825b211922SJohn Baldwin } 835b211922SJohn Baldwin 845b211922SJohn Baldwin /* Bus interface. */ 855b211922SJohn Baldwin 865b211922SJohn Baldwin static int 875b211922SJohn Baldwin pci_hostb_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 885b211922SJohn Baldwin { 895b211922SJohn Baldwin 905b211922SJohn Baldwin return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result)); 915b211922SJohn Baldwin } 925b211922SJohn Baldwin 935b211922SJohn Baldwin static int 945b211922SJohn Baldwin pci_hostb_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 955b211922SJohn Baldwin { 965b211922SJohn Baldwin 975b211922SJohn Baldwin return (EINVAL); 985b211922SJohn Baldwin } 995b211922SJohn Baldwin 1005b211922SJohn Baldwin static struct resource * 1015b211922SJohn Baldwin pci_hostb_alloc_resource(device_t dev, device_t child, int type, int *rid, 1022dd1bdf1SJustin Hibbits rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 1035b211922SJohn Baldwin { 1045b211922SJohn Baldwin 1055b211922SJohn Baldwin return (bus_alloc_resource(dev, type, rid, start, end, count, flags)); 1065b211922SJohn Baldwin } 1075b211922SJohn Baldwin 1085b211922SJohn Baldwin static int 109*9dbf5b0eSJohn Baldwin pci_hostb_release_resource(device_t dev, device_t child, struct resource *r) 1105b211922SJohn Baldwin { 1115b211922SJohn Baldwin 112*9dbf5b0eSJohn Baldwin return (bus_release_resource(dev, r)); 1135b211922SJohn Baldwin } 1145b211922SJohn Baldwin 1155b211922SJohn Baldwin /* PCI interface. */ 1165b211922SJohn Baldwin 1175b211922SJohn Baldwin static uint32_t 1185b211922SJohn Baldwin pci_hostb_read_config(device_t dev, device_t child, int reg, int width) 1195b211922SJohn Baldwin { 1205b211922SJohn Baldwin 1215b211922SJohn Baldwin return (pci_read_config(dev, reg, width)); 1225b211922SJohn Baldwin } 1235b211922SJohn Baldwin 1245b211922SJohn Baldwin static void 1255b211922SJohn Baldwin pci_hostb_write_config(device_t dev, device_t child, int reg, 1265b211922SJohn Baldwin uint32_t val, int width) 1275b211922SJohn Baldwin { 1285b211922SJohn Baldwin 1295b211922SJohn Baldwin pci_write_config(dev, reg, val, width); 1305b211922SJohn Baldwin } 1315b211922SJohn Baldwin 1325b211922SJohn Baldwin static int 1335b211922SJohn Baldwin pci_hostb_enable_busmaster(device_t dev, device_t child) 1345b211922SJohn Baldwin { 1355b211922SJohn Baldwin 1365b211922SJohn Baldwin device_printf(dev, "child %s requested pci_enable_busmaster\n", 1375b211922SJohn Baldwin device_get_nameunit(child)); 1385b211922SJohn Baldwin return (pci_enable_busmaster(dev)); 1395b211922SJohn Baldwin } 1405b211922SJohn Baldwin 1415b211922SJohn Baldwin static int 1425b211922SJohn Baldwin pci_hostb_disable_busmaster(device_t dev, device_t child) 1435b211922SJohn Baldwin { 1445b211922SJohn Baldwin 1455b211922SJohn Baldwin device_printf(dev, "child %s requested pci_disable_busmaster\n", 1465b211922SJohn Baldwin device_get_nameunit(child)); 1475b211922SJohn Baldwin return (pci_disable_busmaster(dev)); 1485b211922SJohn Baldwin } 1495b211922SJohn Baldwin 1505b211922SJohn Baldwin static int 1515b211922SJohn Baldwin pci_hostb_enable_io(device_t dev, device_t child, int space) 1525b211922SJohn Baldwin { 1535b211922SJohn Baldwin 1545b211922SJohn Baldwin device_printf(dev, "child %s requested pci_enable_io\n", 1555b211922SJohn Baldwin device_get_nameunit(child)); 1565b211922SJohn Baldwin return (pci_enable_io(dev, space)); 1575b211922SJohn Baldwin } 1585b211922SJohn Baldwin 1595b211922SJohn Baldwin static int 1605b211922SJohn Baldwin pci_hostb_disable_io(device_t dev, device_t child, int space) 1615b211922SJohn Baldwin { 1625b211922SJohn Baldwin 1635b211922SJohn Baldwin device_printf(dev, "child %s requested pci_disable_io\n", 1645b211922SJohn Baldwin device_get_nameunit(child)); 1655b211922SJohn Baldwin return (pci_disable_io(dev, space)); 1665b211922SJohn Baldwin } 1675b211922SJohn Baldwin 1685b211922SJohn Baldwin static int 1695b211922SJohn Baldwin pci_hostb_set_powerstate(device_t dev, device_t child, int state) 1705b211922SJohn Baldwin { 1715b211922SJohn Baldwin 1725b211922SJohn Baldwin device_printf(dev, "child %s requested pci_set_powerstate\n", 1735b211922SJohn Baldwin device_get_nameunit(child)); 1745b211922SJohn Baldwin return (pci_set_powerstate(dev, state)); 1755b211922SJohn Baldwin } 1765b211922SJohn Baldwin 1775b211922SJohn Baldwin static int 1785b211922SJohn Baldwin pci_hostb_get_powerstate(device_t dev, device_t child) 1795b211922SJohn Baldwin { 1805b211922SJohn Baldwin 1815b211922SJohn Baldwin device_printf(dev, "child %s requested pci_get_powerstate\n", 1825b211922SJohn Baldwin device_get_nameunit(child)); 1835b211922SJohn Baldwin return (pci_get_powerstate(dev)); 1845b211922SJohn Baldwin } 1855b211922SJohn Baldwin 1865b211922SJohn Baldwin static int 1875b211922SJohn Baldwin pci_hostb_assign_interrupt(device_t dev, device_t child) 1885b211922SJohn Baldwin { 1895b211922SJohn Baldwin 1905b211922SJohn Baldwin device_printf(dev, "child %s requested pci_assign_interrupt\n", 1915b211922SJohn Baldwin device_get_nameunit(child)); 1925b211922SJohn Baldwin return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev)); 1935b211922SJohn Baldwin } 1945b211922SJohn Baldwin 1955b211922SJohn Baldwin static int 196c668000bSJohn Baldwin pci_hostb_find_cap(device_t dev, device_t child, int capability, 197c668000bSJohn Baldwin int *capreg) 198c668000bSJohn Baldwin { 199c668000bSJohn Baldwin 200c668000bSJohn Baldwin return (pci_find_cap(dev, capability, capreg)); 201c668000bSJohn Baldwin } 202c668000bSJohn Baldwin 203c668000bSJohn Baldwin static int 2047a16dacdSBryan Venteicher pci_hostb_find_next_cap(device_t dev, device_t child, int capability, 2057a16dacdSBryan Venteicher int start, int *capreg) 2067a16dacdSBryan Venteicher { 2077a16dacdSBryan Venteicher 2087a16dacdSBryan Venteicher return (pci_find_next_cap(dev, capability, start, capreg)); 2097a16dacdSBryan Venteicher } 2107a16dacdSBryan Venteicher 2117a16dacdSBryan Venteicher static int 2125b211922SJohn Baldwin pci_hostb_find_extcap(device_t dev, device_t child, int capability, 2135b211922SJohn Baldwin int *capreg) 2145b211922SJohn Baldwin { 2155b211922SJohn Baldwin 2165b211922SJohn Baldwin return (pci_find_extcap(dev, capability, capreg)); 2175b211922SJohn Baldwin } 2185b211922SJohn Baldwin 219c668000bSJohn Baldwin static int 2207a16dacdSBryan Venteicher pci_hostb_find_next_extcap(device_t dev, device_t child, int capability, 2217a16dacdSBryan Venteicher int start, int *capreg) 2227a16dacdSBryan Venteicher { 2237a16dacdSBryan Venteicher 2247a16dacdSBryan Venteicher return (pci_find_next_extcap(dev, capability, start, capreg)); 2257a16dacdSBryan Venteicher } 2267a16dacdSBryan Venteicher 2277a16dacdSBryan Venteicher static int 228c668000bSJohn Baldwin pci_hostb_find_htcap(device_t dev, device_t child, int capability, 229c668000bSJohn Baldwin int *capreg) 230c668000bSJohn Baldwin { 231c668000bSJohn Baldwin 232c668000bSJohn Baldwin return (pci_find_htcap(dev, capability, capreg)); 233c668000bSJohn Baldwin } 234c668000bSJohn Baldwin 2357a16dacdSBryan Venteicher static int 2367a16dacdSBryan Venteicher pci_hostb_find_next_htcap(device_t dev, device_t child, int capability, 2377a16dacdSBryan Venteicher int start, int *capreg) 2387a16dacdSBryan Venteicher { 2397a16dacdSBryan Venteicher 2407a16dacdSBryan Venteicher return (pci_find_next_htcap(dev, capability, start, capreg)); 2417a16dacdSBryan Venteicher } 2427a16dacdSBryan Venteicher 2435b211922SJohn Baldwin static device_method_t pci_hostb_methods[] = { 2445b211922SJohn Baldwin /* Device interface */ 2455b211922SJohn Baldwin DEVMETHOD(device_probe, pci_hostb_probe), 2465b211922SJohn Baldwin DEVMETHOD(device_attach, pci_hostb_attach), 2475b211922SJohn Baldwin DEVMETHOD(device_shutdown, bus_generic_shutdown), 2485b211922SJohn Baldwin DEVMETHOD(device_suspend, bus_generic_suspend), 2495b211922SJohn Baldwin DEVMETHOD(device_resume, bus_generic_resume), 2505b211922SJohn Baldwin 2515b211922SJohn Baldwin /* Bus interface */ 2525b211922SJohn Baldwin DEVMETHOD(bus_read_ivar, pci_hostb_read_ivar), 2535b211922SJohn Baldwin DEVMETHOD(bus_write_ivar, pci_hostb_write_ivar), 2545b211922SJohn Baldwin DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 2555b211922SJohn Baldwin DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 2565b211922SJohn Baldwin 2575b211922SJohn Baldwin DEVMETHOD(bus_alloc_resource, pci_hostb_alloc_resource), 2585b211922SJohn Baldwin DEVMETHOD(bus_release_resource, pci_hostb_release_resource), 2595b211922SJohn Baldwin DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 2605b211922SJohn Baldwin DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 2615b211922SJohn Baldwin 2625b211922SJohn Baldwin /* PCI interface */ 2635b211922SJohn Baldwin DEVMETHOD(pci_read_config, pci_hostb_read_config), 2645b211922SJohn Baldwin DEVMETHOD(pci_write_config, pci_hostb_write_config), 2655b211922SJohn Baldwin DEVMETHOD(pci_enable_busmaster, pci_hostb_enable_busmaster), 2665b211922SJohn Baldwin DEVMETHOD(pci_disable_busmaster, pci_hostb_disable_busmaster), 2675b211922SJohn Baldwin DEVMETHOD(pci_enable_io, pci_hostb_enable_io), 2685b211922SJohn Baldwin DEVMETHOD(pci_disable_io, pci_hostb_disable_io), 2695b211922SJohn Baldwin DEVMETHOD(pci_get_powerstate, pci_hostb_get_powerstate), 2705b211922SJohn Baldwin DEVMETHOD(pci_set_powerstate, pci_hostb_set_powerstate), 2715b211922SJohn Baldwin DEVMETHOD(pci_assign_interrupt, pci_hostb_assign_interrupt), 272c668000bSJohn Baldwin DEVMETHOD(pci_find_cap, pci_hostb_find_cap), 2737a16dacdSBryan Venteicher DEVMETHOD(pci_find_next_cap, pci_hostb_find_next_cap), 2745b211922SJohn Baldwin DEVMETHOD(pci_find_extcap, pci_hostb_find_extcap), 2757a16dacdSBryan Venteicher DEVMETHOD(pci_find_next_extcap, pci_hostb_find_next_extcap), 276c668000bSJohn Baldwin DEVMETHOD(pci_find_htcap, pci_hostb_find_htcap), 2777a16dacdSBryan Venteicher DEVMETHOD(pci_find_next_htcap, pci_hostb_find_next_htcap), 2785b211922SJohn Baldwin { 0, 0 } 2795b211922SJohn Baldwin }; 2805b211922SJohn Baldwin 2815b211922SJohn Baldwin static driver_t pci_hostb_driver = { 2825b211922SJohn Baldwin "hostb", 2835b211922SJohn Baldwin pci_hostb_methods, 2845b211922SJohn Baldwin 1, 2855b211922SJohn Baldwin }; 2865b211922SJohn Baldwin 28797a41013SJohn Baldwin DRIVER_MODULE(hostb, pci, pci_hostb_driver, 0, 0); 288