15b211922SJohn Baldwin /* 25b211922SJohn Baldwin * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 35b211922SJohn Baldwin * All rights reserved. 45b211922SJohn Baldwin * 55b211922SJohn Baldwin * Redistribution and use in source and binary forms, with or without 65b211922SJohn Baldwin * modification, are permitted provided that the following conditions 75b211922SJohn Baldwin * are met: 85b211922SJohn Baldwin * 1. Redistributions of source code must retain the above copyright 95b211922SJohn Baldwin * notice unmodified, this list of conditions, and the following 105b211922SJohn Baldwin * disclaimer. 115b211922SJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 125b211922SJohn Baldwin * notice, this list of conditions and the following disclaimer in the 135b211922SJohn Baldwin * documentation and/or other materials provided with the distribution. 145b211922SJohn Baldwin * 155b211922SJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 165b211922SJohn Baldwin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 175b211922SJohn Baldwin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 185b211922SJohn Baldwin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 195b211922SJohn Baldwin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 205b211922SJohn Baldwin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 215b211922SJohn Baldwin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 225b211922SJohn Baldwin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 235b211922SJohn Baldwin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 245b211922SJohn Baldwin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 255b211922SJohn Baldwin */ 265b211922SJohn Baldwin 275b211922SJohn Baldwin #include <sys/cdefs.h> 285b211922SJohn Baldwin __FBSDID("$FreeBSD$"); 295b211922SJohn Baldwin 305b211922SJohn Baldwin #include <sys/param.h> 315b211922SJohn Baldwin #include <sys/bus.h> 325b211922SJohn Baldwin #include <sys/kernel.h> 335b211922SJohn Baldwin #include <sys/module.h> 345b211922SJohn Baldwin 355b211922SJohn Baldwin #include <dev/pci/pcivar.h> 365b211922SJohn Baldwin #include <dev/pci/pcireg.h> 375b211922SJohn Baldwin 385b211922SJohn Baldwin /* 395b211922SJohn Baldwin * Provide a device to "eat" the host->pci bridge devices that show up 405b211922SJohn Baldwin * on PCI busses and stop them showing up twice on the probes. This also 415b211922SJohn Baldwin * stops them showing up as 'none' in pciconf -l. If the host bridge 425b211922SJohn Baldwin * provides an AGP capability then we create a child agp device for the 435b211922SJohn Baldwin * agp GART driver to attach to. 445b211922SJohn Baldwin */ 455b211922SJohn Baldwin static int 465b211922SJohn Baldwin pci_hostb_probe(device_t dev) 475b211922SJohn Baldwin { 485b211922SJohn Baldwin u_int32_t id; 495b211922SJohn Baldwin 505b211922SJohn Baldwin id = pci_get_devid(dev); 515b211922SJohn Baldwin 525b211922SJohn Baldwin switch (id) { 535b211922SJohn Baldwin 545b211922SJohn Baldwin /* VIA VT82C596 Power Managment Function */ 555b211922SJohn Baldwin case 0x30501106: 565b211922SJohn Baldwin return (ENXIO); 575b211922SJohn Baldwin 585b211922SJohn Baldwin default: 595b211922SJohn Baldwin break; 605b211922SJohn Baldwin } 615b211922SJohn Baldwin 625b211922SJohn Baldwin if (pci_get_class(dev) == PCIC_BRIDGE && 635b211922SJohn Baldwin pci_get_subclass(dev) == PCIS_BRIDGE_HOST) { 645b211922SJohn Baldwin device_set_desc(dev, "Host to PCI bridge"); 655b211922SJohn Baldwin device_quiet(dev); 665b211922SJohn Baldwin return (-10000); 675b211922SJohn Baldwin } 685b211922SJohn Baldwin return (ENXIO); 695b211922SJohn Baldwin } 705b211922SJohn Baldwin 715b211922SJohn Baldwin static int 725b211922SJohn Baldwin pci_hostb_attach(device_t dev) 735b211922SJohn Baldwin { 745b211922SJohn Baldwin 755b211922SJohn Baldwin bus_generic_probe(dev); 765b211922SJohn Baldwin 775b211922SJohn Baldwin /* 785b211922SJohn Baldwin * If AGP capabilities are present on this device, then create 795b211922SJohn Baldwin * an AGP child. 805b211922SJohn Baldwin */ 81*3b0a4aefSJohn Baldwin if (pci_find_cap(dev, PCIY_AGP, NULL) == 0) 825b211922SJohn Baldwin device_add_child(dev, "agp", -1); 835b211922SJohn Baldwin bus_generic_attach(dev); 845b211922SJohn Baldwin return (0); 855b211922SJohn Baldwin } 865b211922SJohn Baldwin 875b211922SJohn Baldwin /* Bus interface. */ 885b211922SJohn Baldwin 895b211922SJohn Baldwin static int 905b211922SJohn Baldwin pci_hostb_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 915b211922SJohn Baldwin { 925b211922SJohn Baldwin 935b211922SJohn Baldwin return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result)); 945b211922SJohn Baldwin } 955b211922SJohn Baldwin 965b211922SJohn Baldwin static int 975b211922SJohn Baldwin pci_hostb_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 985b211922SJohn Baldwin { 995b211922SJohn Baldwin 1005b211922SJohn Baldwin return (EINVAL); 1015b211922SJohn Baldwin } 1025b211922SJohn Baldwin 1035b211922SJohn Baldwin static struct resource * 1045b211922SJohn Baldwin pci_hostb_alloc_resource(device_t dev, device_t child, int type, int *rid, 1055b211922SJohn Baldwin u_long start, u_long end, u_long count, u_int flags) 1065b211922SJohn Baldwin { 1075b211922SJohn Baldwin 1085b211922SJohn Baldwin return (bus_alloc_resource(dev, type, rid, start, end, count, flags)); 1095b211922SJohn Baldwin } 1105b211922SJohn Baldwin 1115b211922SJohn Baldwin static int 1125b211922SJohn Baldwin pci_hostb_release_resource(device_t dev, device_t child, int type, int rid, 1135b211922SJohn Baldwin struct resource *r) 1145b211922SJohn Baldwin { 1155b211922SJohn Baldwin 1165b211922SJohn Baldwin return (bus_release_resource(dev, type, rid, r)); 1175b211922SJohn Baldwin } 1185b211922SJohn Baldwin 1195b211922SJohn Baldwin /* PCI interface. */ 1205b211922SJohn Baldwin 1215b211922SJohn Baldwin static uint32_t 1225b211922SJohn Baldwin pci_hostb_read_config(device_t dev, device_t child, int reg, int width) 1235b211922SJohn Baldwin { 1245b211922SJohn Baldwin 1255b211922SJohn Baldwin return (pci_read_config(dev, reg, width)); 1265b211922SJohn Baldwin } 1275b211922SJohn Baldwin 1285b211922SJohn Baldwin static void 1295b211922SJohn Baldwin pci_hostb_write_config(device_t dev, device_t child, int reg, 1305b211922SJohn Baldwin uint32_t val, int width) 1315b211922SJohn Baldwin { 1325b211922SJohn Baldwin 1335b211922SJohn Baldwin pci_write_config(dev, reg, val, width); 1345b211922SJohn Baldwin } 1355b211922SJohn Baldwin 1365b211922SJohn Baldwin static int 1375b211922SJohn Baldwin pci_hostb_enable_busmaster(device_t dev, device_t child) 1385b211922SJohn Baldwin { 1395b211922SJohn Baldwin 1405b211922SJohn Baldwin device_printf(dev, "child %s requested pci_enable_busmaster\n", 1415b211922SJohn Baldwin device_get_nameunit(child)); 1425b211922SJohn Baldwin return (pci_enable_busmaster(dev)); 1435b211922SJohn Baldwin } 1445b211922SJohn Baldwin 1455b211922SJohn Baldwin static int 1465b211922SJohn Baldwin pci_hostb_disable_busmaster(device_t dev, device_t child) 1475b211922SJohn Baldwin { 1485b211922SJohn Baldwin 1495b211922SJohn Baldwin device_printf(dev, "child %s requested pci_disable_busmaster\n", 1505b211922SJohn Baldwin device_get_nameunit(child)); 1515b211922SJohn Baldwin return (pci_disable_busmaster(dev)); 1525b211922SJohn Baldwin } 1535b211922SJohn Baldwin 1545b211922SJohn Baldwin static int 1555b211922SJohn Baldwin pci_hostb_enable_io(device_t dev, device_t child, int space) 1565b211922SJohn Baldwin { 1575b211922SJohn Baldwin 1585b211922SJohn Baldwin device_printf(dev, "child %s requested pci_enable_io\n", 1595b211922SJohn Baldwin device_get_nameunit(child)); 1605b211922SJohn Baldwin return (pci_enable_io(dev, space)); 1615b211922SJohn Baldwin } 1625b211922SJohn Baldwin 1635b211922SJohn Baldwin static int 1645b211922SJohn Baldwin pci_hostb_disable_io(device_t dev, device_t child, int space) 1655b211922SJohn Baldwin { 1665b211922SJohn Baldwin 1675b211922SJohn Baldwin device_printf(dev, "child %s requested pci_disable_io\n", 1685b211922SJohn Baldwin device_get_nameunit(child)); 1695b211922SJohn Baldwin return (pci_disable_io(dev, space)); 1705b211922SJohn Baldwin } 1715b211922SJohn Baldwin 1725b211922SJohn Baldwin static int 1735b211922SJohn Baldwin pci_hostb_set_powerstate(device_t dev, device_t child, int state) 1745b211922SJohn Baldwin { 1755b211922SJohn Baldwin 1765b211922SJohn Baldwin device_printf(dev, "child %s requested pci_set_powerstate\n", 1775b211922SJohn Baldwin device_get_nameunit(child)); 1785b211922SJohn Baldwin return (pci_set_powerstate(dev, state)); 1795b211922SJohn Baldwin } 1805b211922SJohn Baldwin 1815b211922SJohn Baldwin static int 1825b211922SJohn Baldwin pci_hostb_get_powerstate(device_t dev, device_t child) 1835b211922SJohn Baldwin { 1845b211922SJohn Baldwin 1855b211922SJohn Baldwin device_printf(dev, "child %s requested pci_get_powerstate\n", 1865b211922SJohn Baldwin device_get_nameunit(child)); 1875b211922SJohn Baldwin return (pci_get_powerstate(dev)); 1885b211922SJohn Baldwin } 1895b211922SJohn Baldwin 1905b211922SJohn Baldwin static int 1915b211922SJohn Baldwin pci_hostb_assign_interrupt(device_t dev, device_t child) 1925b211922SJohn Baldwin { 1935b211922SJohn Baldwin 1945b211922SJohn Baldwin device_printf(dev, "child %s requested pci_assign_interrupt\n", 1955b211922SJohn Baldwin device_get_nameunit(child)); 1965b211922SJohn Baldwin return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev)); 1975b211922SJohn Baldwin } 1985b211922SJohn Baldwin 1995b211922SJohn Baldwin static int 2005b211922SJohn Baldwin pci_hostb_find_extcap(device_t dev, device_t child, int capability, 2015b211922SJohn Baldwin int *capreg) 2025b211922SJohn Baldwin { 2035b211922SJohn Baldwin 2045b211922SJohn Baldwin return (pci_find_extcap(dev, capability, capreg)); 2055b211922SJohn Baldwin } 2065b211922SJohn Baldwin 2075b211922SJohn Baldwin static device_method_t pci_hostb_methods[] = { 2085b211922SJohn Baldwin /* Device interface */ 2095b211922SJohn Baldwin DEVMETHOD(device_probe, pci_hostb_probe), 2105b211922SJohn Baldwin DEVMETHOD(device_attach, pci_hostb_attach), 2115b211922SJohn Baldwin DEVMETHOD(device_shutdown, bus_generic_shutdown), 2125b211922SJohn Baldwin DEVMETHOD(device_suspend, bus_generic_suspend), 2135b211922SJohn Baldwin DEVMETHOD(device_resume, bus_generic_resume), 2145b211922SJohn Baldwin 2155b211922SJohn Baldwin /* Bus interface */ 2165b211922SJohn Baldwin DEVMETHOD(bus_read_ivar, pci_hostb_read_ivar), 2175b211922SJohn Baldwin DEVMETHOD(bus_write_ivar, pci_hostb_write_ivar), 2185b211922SJohn Baldwin DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 2195b211922SJohn Baldwin DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 2205b211922SJohn Baldwin 2215b211922SJohn Baldwin DEVMETHOD(bus_alloc_resource, pci_hostb_alloc_resource), 2225b211922SJohn Baldwin DEVMETHOD(bus_release_resource, pci_hostb_release_resource), 2235b211922SJohn Baldwin DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 2245b211922SJohn Baldwin DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 2255b211922SJohn Baldwin 2265b211922SJohn Baldwin /* PCI interface */ 2275b211922SJohn Baldwin DEVMETHOD(pci_read_config, pci_hostb_read_config), 2285b211922SJohn Baldwin DEVMETHOD(pci_write_config, pci_hostb_write_config), 2295b211922SJohn Baldwin DEVMETHOD(pci_enable_busmaster, pci_hostb_enable_busmaster), 2305b211922SJohn Baldwin DEVMETHOD(pci_disable_busmaster, pci_hostb_disable_busmaster), 2315b211922SJohn Baldwin DEVMETHOD(pci_enable_io, pci_hostb_enable_io), 2325b211922SJohn Baldwin DEVMETHOD(pci_disable_io, pci_hostb_disable_io), 2335b211922SJohn Baldwin DEVMETHOD(pci_get_powerstate, pci_hostb_get_powerstate), 2345b211922SJohn Baldwin DEVMETHOD(pci_set_powerstate, pci_hostb_set_powerstate), 2355b211922SJohn Baldwin DEVMETHOD(pci_assign_interrupt, pci_hostb_assign_interrupt), 2365b211922SJohn Baldwin DEVMETHOD(pci_find_extcap, pci_hostb_find_extcap), 2375b211922SJohn Baldwin 2385b211922SJohn Baldwin { 0, 0 } 2395b211922SJohn Baldwin }; 2405b211922SJohn Baldwin 2415b211922SJohn Baldwin static driver_t pci_hostb_driver = { 2425b211922SJohn Baldwin "hostb", 2435b211922SJohn Baldwin pci_hostb_methods, 2445b211922SJohn Baldwin 1, 2455b211922SJohn Baldwin }; 2465b211922SJohn Baldwin 2475b211922SJohn Baldwin static devclass_t pci_hostb_devclass; 2485b211922SJohn Baldwin 2495b211922SJohn Baldwin DRIVER_MODULE(hostb, pci, pci_hostb_driver, pci_hostb_devclass, 0, 0); 250