2005-01-05 20:17:21 +00:00
|
|
|
/*-
|
Completely replace the PCI bus driver code to make it better reflect
reality. There will be a new call interface, but for now the file
pci_compat.c (which is to be deleted, after all drivers are converted)
provides an emulation of the old PCI bus driver functions. The only
change that might be visible to drivers is, that the type pcici_t
(which had been meant to be just a handle, whose exact definition
should not be relied on), has been converted into a pcicfgregs* .
The Tekram AMD SCSI driver bogusly relied on the definition of pcici_t
and has been converted to just call the PCI drivers functions to access
configuration space register, instead of inventing its own ...
This code is by no means complete, but assumed to be fully operational,
and brings the official code base more in line with my development code.
A new generic device descriptor data type has to be agreed on. The PCI
code will then use that data type to provide new functionality:
1) userconfig support
2) "wired" PCI devices
3) conflicts checking against ISA/EISA
4) maps will depend on the command register enable bits
5) PCI to Anything bridges can be defined as devices,
and are probed like any "standard" PCI device.
The following features are currently missing, but will be added back,
soon:
1) unknown device probe message
2) suppression of "mirrored" devices caused by ancient, broken chip-sets
This code relies on generic shared interrupt support just commited to
kern_intr.c (plus the modifications of isa.c and isa_device.h).
1997-05-26 15:08:43 +00:00
|
|
|
* Copyright (c) 1997, Stefan Esser <se@freebsd.org>
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice unmodified, this list of conditions, and the following
|
|
|
|
* disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2003-07-25 21:19:19 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2002-09-09 08:44:52 +00:00
|
|
|
#include "opt_cpu.h"
|
|
|
|
|
1999-05-18 20:48:43 +00:00
|
|
|
#include <sys/param.h>
|
1995-02-26 05:14:53 +00:00
|
|
|
#include <sys/systm.h>
|
1999-05-18 20:48:43 +00:00
|
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/kernel.h>
|
2000-08-31 23:11:35 +00:00
|
|
|
#include <sys/malloc.h>
|
2004-06-03 05:58:30 +00:00
|
|
|
#include <sys/module.h>
|
2004-10-11 21:51:27 +00:00
|
|
|
#include <sys/sysctl.h>
|
1995-02-01 23:06:58 +00:00
|
|
|
|
2003-08-22 07:39:05 +00:00
|
|
|
#include <dev/pci/pcivar.h>
|
|
|
|
#include <dev/pci/pcireg.h>
|
|
|
|
#include <dev/pci/pcib_private.h>
|
2000-06-23 07:44:33 +00:00
|
|
|
#include <isa/isavar.h>
|
2002-09-23 15:52:30 +00:00
|
|
|
#include <machine/legacyvar.h>
|
2000-10-02 07:11:13 +00:00
|
|
|
#include <machine/pci_cfgreg.h>
|
2004-10-11 21:51:27 +00:00
|
|
|
#include <machine/resource.h>
|
2000-04-16 20:48:33 +00:00
|
|
|
|
2000-08-28 21:48:13 +00:00
|
|
|
#include "pcib_if.h"
|
|
|
|
|
2003-09-23 00:03:44 +00:00
|
|
|
int
|
|
|
|
legacy_pcib_maxslots(device_t dev)
|
2000-08-28 21:48:13 +00:00
|
|
|
{
|
|
|
|
return 31;
|
|
|
|
}
|
|
|
|
|
2000-10-02 07:11:13 +00:00
|
|
|
/* read configuration space register */
|
|
|
|
|
2009-02-08 07:02:42 +00:00
|
|
|
uint32_t
|
|
|
|
legacy_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
|
|
|
|
u_int reg, int bytes)
|
2000-04-16 20:48:33 +00:00
|
|
|
{
|
2000-10-02 07:11:13 +00:00
|
|
|
return(pci_cfgregread(bus, slot, func, reg, bytes));
|
2000-04-16 20:48:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* write configuration space register */
|
|
|
|
|
2003-09-23 00:03:44 +00:00
|
|
|
void
|
2009-02-08 07:02:42 +00:00
|
|
|
legacy_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
|
|
|
|
u_int reg, uint32_t data, int bytes)
|
2000-04-16 20:48:33 +00:00
|
|
|
{
|
2000-10-02 07:11:13 +00:00
|
|
|
pci_cfgregwrite(bus, slot, func, reg, data, bytes);
|
1995-02-01 23:06:58 +00:00
|
|
|
}
|
1999-05-18 20:48:43 +00:00
|
|
|
|
2000-10-16 07:25:08 +00:00
|
|
|
/* route interrupt */
|
|
|
|
|
|
|
|
static int
|
2003-09-23 00:03:44 +00:00
|
|
|
legacy_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
|
2000-10-16 07:25:08 +00:00
|
|
|
{
|
2003-05-01 01:05:25 +00:00
|
|
|
|
|
|
|
/* No routing possible */
|
|
|
|
return (PCI_INVALID_IRQ);
|
2000-10-16 07:25:08 +00:00
|
|
|
}
|
|
|
|
|
2007-05-02 17:50:36 +00:00
|
|
|
/* Pass MSI requests up to the nexus. */
|
2006-12-12 19:27:01 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
legacy_pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount,
|
|
|
|
int *irqs)
|
|
|
|
{
|
|
|
|
device_t bus;
|
|
|
|
|
|
|
|
bus = device_get_parent(pcib);
|
|
|
|
return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount,
|
|
|
|
irqs));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2007-05-02 17:50:36 +00:00
|
|
|
legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
|
2006-12-12 19:27:01 +00:00
|
|
|
{
|
|
|
|
device_t bus;
|
|
|
|
|
|
|
|
bus = device_get_parent(pcib);
|
2007-05-02 17:50:36 +00:00
|
|
|
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
|
|
|
|
uint32_t *data)
|
|
|
|
{
|
|
|
|
device_t bus;
|
|
|
|
|
|
|
|
bus = device_get_parent(pcib);
|
|
|
|
return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
|
2006-12-12 19:27:01 +00:00
|
|
|
}
|
|
|
|
|
1999-07-16 01:00:30 +00:00
|
|
|
static const char *
|
2003-09-23 00:03:44 +00:00
|
|
|
legacy_pcib_is_host_bridge(int bus, int slot, int func,
|
2004-10-11 21:51:27 +00:00
|
|
|
uint32_t id, uint8_t class, uint8_t subclass,
|
|
|
|
uint8_t *busnum)
|
1999-07-16 01:00:30 +00:00
|
|
|
{
|
1999-08-09 21:12:18 +00:00
|
|
|
const char *s = NULL;
|
1999-07-16 01:00:30 +00:00
|
|
|
|
|
|
|
*busnum = 0;
|
2004-03-13 19:21:35 +00:00
|
|
|
if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST)
|
|
|
|
s = "Host to PCI bridge";
|
1999-07-16 01:00:30 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Scan the first pci bus for host-pci bridges and add pcib instances
|
|
|
|
* to the nexus for each bridge.
|
|
|
|
*/
|
|
|
|
static void
|
2003-09-23 00:03:44 +00:00
|
|
|
legacy_pcib_identify(driver_t *driver, device_t parent)
|
1999-07-16 01:00:30 +00:00
|
|
|
{
|
2000-08-28 21:48:13 +00:00
|
|
|
int bus, slot, func;
|
2000-02-09 20:05:30 +00:00
|
|
|
u_int8_t hdrtype;
|
1999-11-18 08:58:37 +00:00
|
|
|
int found = 0;
|
2000-02-09 20:05:30 +00:00
|
|
|
int pcifunchigh;
|
2000-02-23 20:25:06 +00:00
|
|
|
int found824xx = 0;
|
2000-11-08 11:25:15 +00:00
|
|
|
int found_orion = 0;
|
2000-08-31 23:11:35 +00:00
|
|
|
device_t child;
|
2000-10-09 00:44:41 +00:00
|
|
|
devclass_t pci_devclass;
|
1999-07-16 01:00:30 +00:00
|
|
|
|
2000-10-02 07:11:13 +00:00
|
|
|
if (pci_cfgregopen() == 0)
|
1999-08-04 13:38:24 +00:00
|
|
|
return;
|
2000-10-09 00:44:41 +00:00
|
|
|
/*
|
|
|
|
* Check to see if we haven't already had a PCI bus added
|
|
|
|
* via some other means. If we have, bail since otherwise
|
|
|
|
* we're going to end up duplicating it.
|
|
|
|
*/
|
2004-10-31 15:02:53 +00:00
|
|
|
if ((pci_devclass = devclass_find("pci")) &&
|
2000-10-09 00:44:41 +00:00
|
|
|
devclass_get_device(pci_devclass, 0))
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
2000-08-28 21:48:13 +00:00
|
|
|
bus = 0;
|
2000-02-23 20:25:06 +00:00
|
|
|
retry:
|
2000-08-28 21:48:13 +00:00
|
|
|
for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
|
|
|
|
func = 0;
|
2003-09-23 00:03:44 +00:00
|
|
|
hdrtype = legacy_pcib_read_config(0, bus, slot, func,
|
2003-08-28 21:22:25 +00:00
|
|
|
PCIR_HDRTYPE, 1);
|
|
|
|
/*
|
|
|
|
* When enumerating bus devices, the standard says that
|
|
|
|
* one should check the header type and ignore the slots whose
|
|
|
|
* header types that the software doesn't know about. We use
|
|
|
|
* this to filter out devices.
|
|
|
|
*/
|
|
|
|
if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
|
|
|
|
continue;
|
2004-10-31 15:02:53 +00:00
|
|
|
if ((hdrtype & PCIM_MFDEV) &&
|
2000-11-08 11:25:15 +00:00
|
|
|
(!found_orion || hdrtype != 0xff))
|
2003-08-28 21:22:25 +00:00
|
|
|
pcifunchigh = PCI_FUNCMAX;
|
2000-02-09 20:05:30 +00:00
|
|
|
else
|
|
|
|
pcifunchigh = 0;
|
2000-08-28 21:48:13 +00:00
|
|
|
for (func = 0; func <= pcifunchigh; func++) {
|
1999-07-16 01:00:30 +00:00
|
|
|
/*
|
|
|
|
* Read the IDs and class from the device.
|
|
|
|
*/
|
|
|
|
u_int32_t id;
|
|
|
|
u_int8_t class, subclass, busnum;
|
|
|
|
const char *s;
|
2000-09-05 00:53:34 +00:00
|
|
|
device_t *devs;
|
|
|
|
int ndevs, i;
|
1999-07-16 01:00:30 +00:00
|
|
|
|
2003-09-23 00:03:44 +00:00
|
|
|
id = legacy_pcib_read_config(0, bus, slot, func,
|
2000-08-28 21:48:13 +00:00
|
|
|
PCIR_DEVVENDOR, 4);
|
2002-10-20 17:54:17 +00:00
|
|
|
if (id == -1)
|
|
|
|
continue;
|
2003-09-23 00:03:44 +00:00
|
|
|
class = legacy_pcib_read_config(0, bus, slot, func,
|
2000-08-28 21:48:13 +00:00
|
|
|
PCIR_CLASS, 1);
|
2003-09-23 00:03:44 +00:00
|
|
|
subclass = legacy_pcib_read_config(0, bus, slot, func,
|
2000-08-28 21:48:13 +00:00
|
|
|
PCIR_SUBCLASS, 1);
|
1999-07-16 01:00:30 +00:00
|
|
|
|
2003-09-23 00:03:44 +00:00
|
|
|
s = legacy_pcib_is_host_bridge(bus, slot, func,
|
2000-08-28 21:48:13 +00:00
|
|
|
id, class, subclass,
|
1999-07-16 01:00:30 +00:00
|
|
|
&busnum);
|
2000-09-05 00:53:34 +00:00
|
|
|
if (s == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check to see if the physical bus has already
|
|
|
|
* been seen. Eg: hybrid 32 and 64 bit host
|
|
|
|
* bridges to the same logical bus.
|
|
|
|
*/
|
|
|
|
if (device_get_children(parent, &devs, &ndevs) == 0) {
|
|
|
|
for (i = 0; s != NULL && i < ndevs; i++) {
|
|
|
|
if (strcmp(device_get_name(devs[i]),
|
|
|
|
"pcib") != 0)
|
|
|
|
continue;
|
2002-09-23 15:52:30 +00:00
|
|
|
if (legacy_get_pcibus(devs[i]) == busnum)
|
2000-09-05 00:53:34 +00:00
|
|
|
s = NULL;
|
|
|
|
}
|
|
|
|
free(devs, M_TEMP);
|
1999-07-16 01:00:30 +00:00
|
|
|
}
|
2000-09-05 00:53:34 +00:00
|
|
|
|
|
|
|
if (s == NULL)
|
|
|
|
continue;
|
|
|
|
/*
|
|
|
|
* Add at priority 100 to make sure we
|
|
|
|
* go after any motherboard resources
|
|
|
|
*/
|
|
|
|
child = BUS_ADD_CHILD(parent, 100,
|
|
|
|
"pcib", busnum);
|
|
|
|
device_set_desc(child, s);
|
2002-09-23 15:52:30 +00:00
|
|
|
legacy_set_pcibus(child, busnum);
|
2000-09-05 00:53:34 +00:00
|
|
|
|
|
|
|
found = 1;
|
|
|
|
if (id == 0x12258086)
|
|
|
|
found824xx = 1;
|
2000-11-08 11:25:15 +00:00
|
|
|
if (id == 0x84c48086)
|
|
|
|
found_orion = 1;
|
1999-07-16 01:00:30 +00:00
|
|
|
}
|
|
|
|
}
|
2000-08-28 21:48:13 +00:00
|
|
|
if (found824xx && bus == 0) {
|
|
|
|
bus++;
|
2000-02-23 20:25:06 +00:00
|
|
|
goto retry;
|
|
|
|
}
|
1999-11-18 08:58:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure we add at least one bridge since some old
|
|
|
|
* hardware doesn't actually have a host-pci bridge device.
|
2000-10-02 07:11:13 +00:00
|
|
|
* Note that pci_cfgregopen() thinks we have PCI devices..
|
1999-11-18 08:58:37 +00:00
|
|
|
*/
|
|
|
|
if (!found) {
|
|
|
|
if (bootverbose)
|
|
|
|
printf(
|
2003-09-23 00:03:44 +00:00
|
|
|
"legacy_pcib_identify: no bridge found, adding pcib0 anyway\n");
|
2000-08-31 23:11:35 +00:00
|
|
|
child = BUS_ADD_CHILD(parent, 100, "pcib", 0);
|
2002-09-23 15:52:30 +00:00
|
|
|
legacy_set_pcibus(child, 0);
|
1999-11-18 08:58:37 +00:00
|
|
|
}
|
1999-07-16 01:00:30 +00:00
|
|
|
}
|
|
|
|
|
1999-05-18 20:48:43 +00:00
|
|
|
static int
|
2003-09-23 00:03:44 +00:00
|
|
|
legacy_pcib_probe(device_t dev)
|
1999-05-18 20:48:43 +00:00
|
|
|
{
|
2000-08-31 23:11:35 +00:00
|
|
|
|
2000-10-09 00:44:41 +00:00
|
|
|
if (pci_cfgregopen() == 0)
|
|
|
|
return ENXIO;
|
2003-11-17 08:58:16 +00:00
|
|
|
return -100;
|
1999-05-18 20:48:43 +00:00
|
|
|
}
|
|
|
|
|
2004-05-16 20:30:47 +00:00
|
|
|
static int
|
2003-09-23 00:03:44 +00:00
|
|
|
legacy_pcib_attach(device_t dev)
|
2000-08-31 23:11:35 +00:00
|
|
|
{
|
2004-03-13 19:21:35 +00:00
|
|
|
int bus;
|
2000-08-31 23:11:35 +00:00
|
|
|
|
2004-03-13 19:21:35 +00:00
|
|
|
bus = pcib_get_bus(dev);
|
|
|
|
device_add_child(dev, "pci", bus);
|
2000-08-31 23:11:35 +00:00
|
|
|
return bus_generic_attach(dev);
|
|
|
|
}
|
|
|
|
|
2003-09-23 00:03:44 +00:00
|
|
|
int
|
|
|
|
legacy_pcib_read_ivar(device_t dev, device_t child, int which,
|
|
|
|
uintptr_t *result)
|
2000-08-28 21:48:13 +00:00
|
|
|
{
|
2000-08-31 23:11:35 +00:00
|
|
|
|
|
|
|
switch (which) {
|
2007-09-30 11:05:18 +00:00
|
|
|
case PCIB_IVAR_DOMAIN:
|
|
|
|
*result = 0;
|
|
|
|
return 0;
|
2000-08-31 23:11:35 +00:00
|
|
|
case PCIB_IVAR_BUS:
|
2002-09-23 15:52:30 +00:00
|
|
|
*result = legacy_get_pcibus(dev);
|
2000-08-31 23:11:35 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return ENOENT;
|
|
|
|
}
|
|
|
|
|
2003-09-23 00:03:44 +00:00
|
|
|
int
|
|
|
|
legacy_pcib_write_ivar(device_t dev, device_t child, int which,
|
|
|
|
uintptr_t value)
|
2000-08-31 23:11:35 +00:00
|
|
|
{
|
|
|
|
|
2000-08-28 21:48:13 +00:00
|
|
|
switch (which) {
|
2007-09-30 11:05:18 +00:00
|
|
|
case PCIB_IVAR_DOMAIN:
|
|
|
|
return EINVAL;
|
2000-08-28 21:48:13 +00:00
|
|
|
case PCIB_IVAR_BUS:
|
2002-09-23 15:52:30 +00:00
|
|
|
legacy_set_pcibus(dev, value);
|
2000-08-28 21:48:13 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return ENOENT;
|
|
|
|
}
|
|
|
|
|
2004-10-11 21:51:27 +00:00
|
|
|
SYSCTL_DECL(_hw_pci);
|
|
|
|
|
2004-10-31 15:50:33 +00:00
|
|
|
static unsigned long legacy_host_mem_start = 0x80000000;
|
|
|
|
TUNABLE_ULONG("hw.pci.host_mem_start", &legacy_host_mem_start);
|
|
|
|
SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN,
|
2004-10-11 21:51:27 +00:00
|
|
|
&legacy_host_mem_start, 0x80000000,
|
|
|
|
"Limit the host bridge memory to being above this address. Must be\n\
|
|
|
|
set at boot via a tunable.");
|
|
|
|
|
2005-09-18 01:42:43 +00:00
|
|
|
struct resource *
|
2004-10-11 21:51:27 +00:00
|
|
|
legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
|
|
|
u_long start, u_long end, u_long count, u_int flags)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If no memory preference is given, use upper 32MB slot most
|
|
|
|
* bioses use for their memory window. Typically other bridges
|
|
|
|
* before us get in the way to assert their preferences on memory.
|
|
|
|
* Hardcoding like this sucks, so a more MD/MI way needs to be
|
|
|
|
* found to do it. This is typically only used on older laptops
|
|
|
|
* that don't have pci busses behind pci bridge, so assuming > 32MB
|
|
|
|
* is liekly OK.
|
|
|
|
*
|
|
|
|
* However, this can cause problems for other chipsets, so we make
|
|
|
|
* this tunable by hw.pci.host_mem_start.
|
|
|
|
*/
|
|
|
|
if (type == SYS_RES_MEMORY && start == 0UL && end == ~0UL)
|
|
|
|
start = legacy_host_mem_start;
|
2005-09-18 01:42:43 +00:00
|
|
|
if (type == SYS_RES_IOPORT && start == 0UL && end == ~0UL)
|
|
|
|
start = 0x1000;
|
2004-10-11 21:51:27 +00:00
|
|
|
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
|
|
|
|
count, flags));
|
|
|
|
}
|
2000-08-31 23:11:35 +00:00
|
|
|
|
2003-09-23 00:03:44 +00:00
|
|
|
static device_method_t legacy_pcib_methods[] = {
|
1999-05-18 20:48:43 +00:00
|
|
|
/* Device interface */
|
2003-09-23 00:03:44 +00:00
|
|
|
DEVMETHOD(device_identify, legacy_pcib_identify),
|
|
|
|
DEVMETHOD(device_probe, legacy_pcib_probe),
|
|
|
|
DEVMETHOD(device_attach, legacy_pcib_attach),
|
1999-05-18 20:48:43 +00:00
|
|
|
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
|
|
|
DEVMETHOD(device_suspend, bus_generic_suspend),
|
|
|
|
DEVMETHOD(device_resume, bus_generic_resume),
|
|
|
|
|
|
|
|
/* Bus interface */
|
|
|
|
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
2003-09-23 00:03:44 +00:00
|
|
|
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
|
|
|
|
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
|
2004-10-11 21:51:27 +00:00
|
|
|
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
|
1999-05-18 20:48:43 +00:00
|
|
|
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
|
|
|
|
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
|
|
|
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
|
|
|
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
|
|
|
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
|
|
|
|
2000-08-28 21:48:13 +00:00
|
|
|
/* pcib interface */
|
2003-09-23 00:03:44 +00:00
|
|
|
DEVMETHOD(pcib_maxslots, legacy_pcib_maxslots),
|
|
|
|
DEVMETHOD(pcib_read_config, legacy_pcib_read_config),
|
|
|
|
DEVMETHOD(pcib_write_config, legacy_pcib_write_config),
|
|
|
|
DEVMETHOD(pcib_route_interrupt, legacy_pcib_route_interrupt),
|
2006-12-12 19:27:01 +00:00
|
|
|
DEVMETHOD(pcib_alloc_msi, legacy_pcib_alloc_msi),
|
2006-11-13 22:23:34 +00:00
|
|
|
DEVMETHOD(pcib_release_msi, pcib_release_msi),
|
2006-12-12 19:27:01 +00:00
|
|
|
DEVMETHOD(pcib_alloc_msix, legacy_pcib_alloc_msix),
|
2006-11-13 22:23:34 +00:00
|
|
|
DEVMETHOD(pcib_release_msix, pcib_release_msix),
|
2007-05-02 17:50:36 +00:00
|
|
|
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
|
2000-08-28 21:48:13 +00:00
|
|
|
|
1999-05-18 20:48:43 +00:00
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
2006-03-13 23:58:40 +00:00
|
|
|
static devclass_t hostb_devclass;
|
1999-05-18 20:48:43 +00:00
|
|
|
|
2006-01-06 19:22:19 +00:00
|
|
|
DEFINE_CLASS_0(pcib, legacy_pcib_driver, legacy_pcib_methods, 1);
|
2006-03-13 23:58:40 +00:00
|
|
|
DRIVER_MODULE(pcib, legacy, legacy_pcib_driver, hostb_devclass, 0, 0);
|
2000-06-23 07:44:33 +00:00
|
|
|
|
2000-09-05 00:53:34 +00:00
|
|
|
|
2000-06-23 07:44:33 +00:00
|
|
|
/*
|
|
|
|
* Install placeholder to claim the resources owned by the
|
2004-10-31 15:02:53 +00:00
|
|
|
* PCI bus interface. This could be used to extract the
|
2000-06-23 07:44:33 +00:00
|
|
|
* config space registers in the extreme case where the PnP
|
|
|
|
* ID is available and the PCI BIOS isn't, but for now we just
|
|
|
|
* eat the PnP ID and do nothing else.
|
|
|
|
*
|
2004-10-31 15:02:53 +00:00
|
|
|
* XXX we should silence this probe, as it will generally confuse
|
2000-06-23 07:44:33 +00:00
|
|
|
* people.
|
|
|
|
*/
|
|
|
|
static struct isa_pnp_id pcibus_pnp_ids[] = {
|
2002-04-24 15:22:53 +00:00
|
|
|
{ 0x030ad041 /* PNP0A03 */, "PCI Bus" },
|
2009-07-13 21:36:31 +00:00
|
|
|
{ 0x080ad041 /* PNP0A08 */, "PCIe Bus" },
|
2000-06-23 07:44:33 +00:00
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
pcibus_pnp_probe(device_t dev)
|
|
|
|
{
|
|
|
|
int result;
|
2004-10-31 15:02:53 +00:00
|
|
|
|
2000-06-23 07:44:33 +00:00
|
|
|
if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, pcibus_pnp_ids)) <= 0)
|
|
|
|
device_quiet(dev);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
pcibus_pnp_attach(device_t dev)
|
|
|
|
{
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static device_method_t pcibus_pnp_methods[] = {
|
|
|
|
/* Device interface */
|
|
|
|
DEVMETHOD(device_probe, pcibus_pnp_probe),
|
|
|
|
DEVMETHOD(device_attach, pcibus_pnp_attach),
|
|
|
|
DEVMETHOD(device_detach, bus_generic_detach),
|
|
|
|
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
|
|
|
DEVMETHOD(device_suspend, bus_generic_suspend),
|
|
|
|
DEVMETHOD(device_resume, bus_generic_resume),
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static devclass_t pcibus_pnp_devclass;
|
|
|
|
|
2006-01-06 19:22:19 +00:00
|
|
|
DEFINE_CLASS_0(pcibus_pnp, pcibus_pnp_driver, pcibus_pnp_methods, 1);
|
2000-06-23 07:44:33 +00:00
|
|
|
DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0);
|