14d28e78fSSepherosa Ziehau /*
24d28e78fSSepherosa Ziehau * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
34d28e78fSSepherosa Ziehau * All rights reserved.
44d28e78fSSepherosa Ziehau *
54d28e78fSSepherosa Ziehau * Redistribution and use in source and binary forms, with or without
64d28e78fSSepherosa Ziehau * modification, are permitted provided that the following conditions
74d28e78fSSepherosa Ziehau * are met:
84d28e78fSSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright
94d28e78fSSepherosa Ziehau * notice unmodified, this list of conditions, and the following
104d28e78fSSepherosa Ziehau * disclaimer.
114d28e78fSSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright
124d28e78fSSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the
134d28e78fSSepherosa Ziehau * documentation and/or other materials provided with the distribution.
144d28e78fSSepherosa Ziehau *
154d28e78fSSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
164d28e78fSSepherosa Ziehau * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
174d28e78fSSepherosa Ziehau * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
184d28e78fSSepherosa Ziehau * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
194d28e78fSSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
204d28e78fSSepherosa Ziehau * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
214d28e78fSSepherosa Ziehau * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
224d28e78fSSepherosa Ziehau * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
234d28e78fSSepherosa Ziehau * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
244d28e78fSSepherosa Ziehau * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2583c1faaaSSascha Wildner *
2683c1faaaSSascha Wildner * $FreeBSD: src/sys/dev/pci/hostb_pci.c,v 1.1.8.1 2009/04/15 03:14:26 kensmith Exp $
274d28e78fSSepherosa Ziehau */
284d28e78fSSepherosa Ziehau
294d28e78fSSepherosa Ziehau #include <sys/param.h>
304d28e78fSSepherosa Ziehau #include <sys/bus.h>
314d28e78fSSepherosa Ziehau #include <sys/kernel.h>
324d28e78fSSepherosa Ziehau #include <sys/module.h>
334d28e78fSSepherosa Ziehau
344d28e78fSSepherosa Ziehau #include <sys/types.h>
354d28e78fSSepherosa Ziehau #include <sys/systm.h>
364d28e78fSSepherosa Ziehau
374d28e78fSSepherosa Ziehau #include <bus/pci/pcivar.h>
384d28e78fSSepherosa Ziehau #include <bus/pci/pcireg.h>
394d28e78fSSepherosa Ziehau
404d28e78fSSepherosa Ziehau /*
414d28e78fSSepherosa Ziehau * Provide a device to "eat" the host->pci bridge devices that show up
424d28e78fSSepherosa Ziehau * on PCI busses and stop them showing up twice on the probes. This also
434d28e78fSSepherosa Ziehau * stops them showing up as 'none' in pciconf -l. If the host bridge
444d28e78fSSepherosa Ziehau * provides an AGP capability then we create a child agp device for the
454d28e78fSSepherosa Ziehau * agp GART driver to attach to.
464d28e78fSSepherosa Ziehau */
474d28e78fSSepherosa Ziehau static int
pci_hostb_probe(device_t dev)484d28e78fSSepherosa Ziehau pci_hostb_probe(device_t dev)
494d28e78fSSepherosa Ziehau {
504d28e78fSSepherosa Ziehau u_int32_t id;
514d28e78fSSepherosa Ziehau id = pci_get_devid(dev);
524d28e78fSSepherosa Ziehau
534d28e78fSSepherosa Ziehau switch (id) {
544d28e78fSSepherosa Ziehau
554d28e78fSSepherosa Ziehau /* VIA VT82C596 Power Managment Function */
564d28e78fSSepherosa Ziehau case 0x30501106:
574d28e78fSSepherosa Ziehau return (ENXIO);
584d28e78fSSepherosa Ziehau
594d28e78fSSepherosa Ziehau default:
604d28e78fSSepherosa Ziehau break;
614d28e78fSSepherosa Ziehau }
624d28e78fSSepherosa Ziehau
634d28e78fSSepherosa Ziehau if (pci_get_class(dev) == PCIC_BRIDGE &&
644d28e78fSSepherosa Ziehau pci_get_subclass(dev) == PCIS_BRIDGE_HOST) {
654d28e78fSSepherosa Ziehau device_set_desc(dev, "Host to PCI bridge");
664d28e78fSSepherosa Ziehau device_quiet(dev);
674d28e78fSSepherosa Ziehau return (-10000);
684d28e78fSSepherosa Ziehau }
694d28e78fSSepherosa Ziehau return (ENXIO);
704d28e78fSSepherosa Ziehau }
714d28e78fSSepherosa Ziehau
724d28e78fSSepherosa Ziehau static int
pci_hostb_attach(device_t dev)734d28e78fSSepherosa Ziehau pci_hostb_attach(device_t dev)
744d28e78fSSepherosa Ziehau {
754d28e78fSSepherosa Ziehau
764d28e78fSSepherosa Ziehau bus_generic_probe(dev);
774d28e78fSSepherosa Ziehau
784d28e78fSSepherosa Ziehau /*
794d28e78fSSepherosa Ziehau * If AGP capabilities are present on this device, then create
804d28e78fSSepherosa Ziehau * an AGP child.
814d28e78fSSepherosa Ziehau */
824d28e78fSSepherosa Ziehau if (pci_find_extcap(dev, PCIY_AGP, NULL) == 0)
834d28e78fSSepherosa Ziehau device_add_child(dev, "agp", -1);
844d28e78fSSepherosa Ziehau bus_generic_attach(dev);
854d28e78fSSepherosa Ziehau return (0);
864d28e78fSSepherosa Ziehau }
874d28e78fSSepherosa Ziehau
884d28e78fSSepherosa Ziehau /* Bus interface. */
894d28e78fSSepherosa Ziehau
904d28e78fSSepherosa Ziehau static int
pci_hostb_read_ivar(device_t dev,device_t child,int which,uintptr_t * result)914d28e78fSSepherosa Ziehau pci_hostb_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
924d28e78fSSepherosa Ziehau {
934d28e78fSSepherosa Ziehau
944d28e78fSSepherosa Ziehau return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result));
954d28e78fSSepherosa Ziehau }
964d28e78fSSepherosa Ziehau
974d28e78fSSepherosa Ziehau static int
pci_hostb_write_ivar(device_t dev,device_t child,int which,uintptr_t value)984d28e78fSSepherosa Ziehau pci_hostb_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
994d28e78fSSepherosa Ziehau {
1004d28e78fSSepherosa Ziehau
1014d28e78fSSepherosa Ziehau return (EINVAL);
1024d28e78fSSepherosa Ziehau }
1034d28e78fSSepherosa Ziehau
1044d28e78fSSepherosa Ziehau static struct resource *
pci_hostb_alloc_resource(device_t dev,device_t child,int type,int * rid,u_long start,u_long end,u_long count,u_int flags,int cpuid __unused)1054d28e78fSSepherosa Ziehau pci_hostb_alloc_resource(device_t dev, device_t child, int type, int *rid,
1064f7fe8c7SSepherosa Ziehau u_long start, u_long end, u_long count, u_int flags, int cpuid __unused)
1074d28e78fSSepherosa Ziehau {
1084d28e78fSSepherosa Ziehau
1094d28e78fSSepherosa Ziehau return (bus_alloc_resource(dev, type, rid, start, end, count, flags));
1104d28e78fSSepherosa Ziehau }
1114d28e78fSSepherosa Ziehau
1124d28e78fSSepherosa Ziehau static int
pci_hostb_release_resource(device_t dev,device_t child,int type,int rid,struct resource * r)1134d28e78fSSepherosa Ziehau pci_hostb_release_resource(device_t dev, device_t child, int type, int rid,
1144d28e78fSSepherosa Ziehau struct resource *r)
1154d28e78fSSepherosa Ziehau {
1164d28e78fSSepherosa Ziehau
1174d28e78fSSepherosa Ziehau return (bus_release_resource(dev, type, rid, r));
1184d28e78fSSepherosa Ziehau }
1194d28e78fSSepherosa Ziehau
1204d28e78fSSepherosa Ziehau /* PCI interface. */
1214d28e78fSSepherosa Ziehau
1224d28e78fSSepherosa Ziehau static uint32_t
pci_hostb_read_config(device_t dev,device_t child,int reg,int width)1234d28e78fSSepherosa Ziehau pci_hostb_read_config(device_t dev, device_t child, int reg, int width)
1244d28e78fSSepherosa Ziehau {
1254d28e78fSSepherosa Ziehau
1264d28e78fSSepherosa Ziehau return (pci_read_config(dev, reg, width));
1274d28e78fSSepherosa Ziehau }
1284d28e78fSSepherosa Ziehau
1294d28e78fSSepherosa Ziehau static void
pci_hostb_write_config(device_t dev,device_t child,int reg,uint32_t val,int width)1304d28e78fSSepherosa Ziehau pci_hostb_write_config(device_t dev, device_t child, int reg,
1314d28e78fSSepherosa Ziehau uint32_t val, int width)
1324d28e78fSSepherosa Ziehau {
1334d28e78fSSepherosa Ziehau
1344d28e78fSSepherosa Ziehau pci_write_config(dev, reg, val, width);
1354d28e78fSSepherosa Ziehau }
1364d28e78fSSepherosa Ziehau
1374d28e78fSSepherosa Ziehau static int
pci_hostb_enable_busmaster(device_t dev,device_t child)1384d28e78fSSepherosa Ziehau pci_hostb_enable_busmaster(device_t dev, device_t child)
1394d28e78fSSepherosa Ziehau {
1404d28e78fSSepherosa Ziehau
1414d28e78fSSepherosa Ziehau device_printf(dev, "child %s requested pci_enable_busmaster\n",
1424d28e78fSSepherosa Ziehau device_get_nameunit(child));
1434d28e78fSSepherosa Ziehau return (pci_enable_busmaster(dev));
1444d28e78fSSepherosa Ziehau }
1454d28e78fSSepherosa Ziehau
1464d28e78fSSepherosa Ziehau static int
pci_hostb_disable_busmaster(device_t dev,device_t child)1474d28e78fSSepherosa Ziehau pci_hostb_disable_busmaster(device_t dev, device_t child)
1484d28e78fSSepherosa Ziehau {
1494d28e78fSSepherosa Ziehau
1504d28e78fSSepherosa Ziehau device_printf(dev, "child %s requested pci_disable_busmaster\n",
1514d28e78fSSepherosa Ziehau device_get_nameunit(child));
1524d28e78fSSepherosa Ziehau return (pci_disable_busmaster(dev));
1534d28e78fSSepherosa Ziehau }
1544d28e78fSSepherosa Ziehau
1554d28e78fSSepherosa Ziehau static int
pci_hostb_enable_io(device_t dev,device_t child,int space)1564d28e78fSSepherosa Ziehau pci_hostb_enable_io(device_t dev, device_t child, int space)
1574d28e78fSSepherosa Ziehau {
1584d28e78fSSepherosa Ziehau
1594d28e78fSSepherosa Ziehau device_printf(dev, "child %s requested pci_enable_io\n",
1604d28e78fSSepherosa Ziehau device_get_nameunit(child));
1614d28e78fSSepherosa Ziehau return (pci_enable_io(dev, space));
1624d28e78fSSepherosa Ziehau }
1634d28e78fSSepherosa Ziehau
1644d28e78fSSepherosa Ziehau static int
pci_hostb_disable_io(device_t dev,device_t child,int space)1654d28e78fSSepherosa Ziehau pci_hostb_disable_io(device_t dev, device_t child, int space)
1664d28e78fSSepherosa Ziehau {
1674d28e78fSSepherosa Ziehau
1684d28e78fSSepherosa Ziehau device_printf(dev, "child %s requested pci_disable_io\n",
1694d28e78fSSepherosa Ziehau device_get_nameunit(child));
1704d28e78fSSepherosa Ziehau return (pci_disable_io(dev, space));
1714d28e78fSSepherosa Ziehau }
1724d28e78fSSepherosa Ziehau
1734d28e78fSSepherosa Ziehau static int
pci_hostb_set_powerstate(device_t dev,device_t child,int state)1744d28e78fSSepherosa Ziehau pci_hostb_set_powerstate(device_t dev, device_t child, int state)
1754d28e78fSSepherosa Ziehau {
1764d28e78fSSepherosa Ziehau
1774d28e78fSSepherosa Ziehau device_printf(dev, "child %s requested pci_set_powerstate\n",
1784d28e78fSSepherosa Ziehau device_get_nameunit(child));
1794d28e78fSSepherosa Ziehau return (pci_set_powerstate(dev, state));
1804d28e78fSSepherosa Ziehau }
1814d28e78fSSepherosa Ziehau
1824d28e78fSSepherosa Ziehau static int
pci_hostb_get_powerstate(device_t dev,device_t child)1834d28e78fSSepherosa Ziehau pci_hostb_get_powerstate(device_t dev, device_t child)
1844d28e78fSSepherosa Ziehau {
1854d28e78fSSepherosa Ziehau
1864d28e78fSSepherosa Ziehau device_printf(dev, "child %s requested pci_get_powerstate\n",
1874d28e78fSSepherosa Ziehau device_get_nameunit(child));
1884d28e78fSSepherosa Ziehau return (pci_get_powerstate(dev));
1894d28e78fSSepherosa Ziehau }
1904d28e78fSSepherosa Ziehau
1914d28e78fSSepherosa Ziehau static int
pci_hostb_assign_interrupt(device_t dev,device_t child)1924d28e78fSSepherosa Ziehau pci_hostb_assign_interrupt(device_t dev, device_t child)
1934d28e78fSSepherosa Ziehau {
1944d28e78fSSepherosa Ziehau
1954d28e78fSSepherosa Ziehau device_printf(dev, "child %s requested pci_assign_interrupt\n",
1964d28e78fSSepherosa Ziehau device_get_nameunit(child));
1974d28e78fSSepherosa Ziehau return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev));
1984d28e78fSSepherosa Ziehau }
1994d28e78fSSepherosa Ziehau
2004d28e78fSSepherosa Ziehau static int
pci_hostb_find_extcap(device_t dev,device_t child,int capability,int * capreg)2014d28e78fSSepherosa Ziehau pci_hostb_find_extcap(device_t dev, device_t child, int capability,
2024d28e78fSSepherosa Ziehau int *capreg)
2034d28e78fSSepherosa Ziehau {
2044d28e78fSSepherosa Ziehau
2054d28e78fSSepherosa Ziehau return (pci_find_extcap(dev, capability, capreg));
2064d28e78fSSepherosa Ziehau }
2074d28e78fSSepherosa Ziehau
2084d28e78fSSepherosa Ziehau static device_method_t pci_hostb_methods[] = {
2094d28e78fSSepherosa Ziehau /* Device interface */
2104d28e78fSSepherosa Ziehau DEVMETHOD(device_probe, pci_hostb_probe),
2114d28e78fSSepherosa Ziehau DEVMETHOD(device_attach, pci_hostb_attach),
2124d28e78fSSepherosa Ziehau DEVMETHOD(device_shutdown, bus_generic_shutdown),
2134d28e78fSSepherosa Ziehau DEVMETHOD(device_suspend, bus_generic_suspend),
2144d28e78fSSepherosa Ziehau DEVMETHOD(device_resume, bus_generic_resume),
2154d28e78fSSepherosa Ziehau
2164d28e78fSSepherosa Ziehau /* Bus interface */
2174d28e78fSSepherosa Ziehau DEVMETHOD(bus_read_ivar, pci_hostb_read_ivar),
2184d28e78fSSepherosa Ziehau DEVMETHOD(bus_write_ivar, pci_hostb_write_ivar),
2194d28e78fSSepherosa Ziehau DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
2204d28e78fSSepherosa Ziehau DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
2214d28e78fSSepherosa Ziehau
2224d28e78fSSepherosa Ziehau DEVMETHOD(bus_alloc_resource, pci_hostb_alloc_resource),
2234d28e78fSSepherosa Ziehau DEVMETHOD(bus_release_resource, pci_hostb_release_resource),
2244d28e78fSSepherosa Ziehau DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
2254d28e78fSSepherosa Ziehau DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
2264d28e78fSSepherosa Ziehau
2274d28e78fSSepherosa Ziehau /* PCI interface */
2284d28e78fSSepherosa Ziehau DEVMETHOD(pci_read_config, pci_hostb_read_config),
2294d28e78fSSepherosa Ziehau DEVMETHOD(pci_write_config, pci_hostb_write_config),
2304d28e78fSSepherosa Ziehau DEVMETHOD(pci_enable_busmaster, pci_hostb_enable_busmaster),
2314d28e78fSSepherosa Ziehau DEVMETHOD(pci_disable_busmaster, pci_hostb_disable_busmaster),
2324d28e78fSSepherosa Ziehau DEVMETHOD(pci_enable_io, pci_hostb_enable_io),
2334d28e78fSSepherosa Ziehau DEVMETHOD(pci_disable_io, pci_hostb_disable_io),
2344d28e78fSSepherosa Ziehau DEVMETHOD(pci_get_powerstate, pci_hostb_get_powerstate),
2354d28e78fSSepherosa Ziehau DEVMETHOD(pci_set_powerstate, pci_hostb_set_powerstate),
2364d28e78fSSepherosa Ziehau DEVMETHOD(pci_assign_interrupt, pci_hostb_assign_interrupt),
2374d28e78fSSepherosa Ziehau DEVMETHOD(pci_find_extcap, pci_hostb_find_extcap),
2384d28e78fSSepherosa Ziehau
239*d3c9c58eSSascha Wildner DEVMETHOD_END
2404d28e78fSSepherosa Ziehau };
2414d28e78fSSepherosa Ziehau
2424d28e78fSSepherosa Ziehau static driver_t pci_hostb_driver = {
2434d28e78fSSepherosa Ziehau "hostb",
2444d28e78fSSepherosa Ziehau pci_hostb_methods,
2454d28e78fSSepherosa Ziehau 1,
2464d28e78fSSepherosa Ziehau };
2474d28e78fSSepherosa Ziehau
2484d28e78fSSepherosa Ziehau static devclass_t pci_hostb_devclass;
2494d28e78fSSepherosa Ziehau
250aa2b9d05SSascha Wildner DRIVER_MODULE(hostb, pci, pci_hostb_driver, pci_hostb_devclass, NULL, NULL);
251