Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/acpica/acpi_pcib_pci.c
39535 views
1
/*-
2
* Copyright (c) 2000 Michael Smith
3
* Copyright (c) 2000 BSDi
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <sys/cdefs.h>
29
#include "opt_acpi.h"
30
31
#include <sys/param.h>
32
#include <sys/bus.h>
33
#include <sys/kernel.h>
34
#include <sys/malloc.h>
35
#include <sys/module.h>
36
#include <sys/rman.h>
37
38
#include <contrib/dev/acpica/include/acpi.h>
39
#include <contrib/dev/acpica/include/accommon.h>
40
41
#include <dev/acpica/acpivar.h>
42
#include <dev/acpica/acpi_pcibvar.h>
43
44
#include <machine/pci_cfgreg.h>
45
#include <dev/pci/pcivar.h>
46
#include <dev/pci/pcireg.h>
47
#include <dev/pci/pcib_private.h>
48
#include "pcib_if.h"
49
50
/* Hooks for the ACPI CA debugging infrastructure. */
51
#define _COMPONENT ACPI_BUS
52
ACPI_MODULE_NAME("PCI_PCI")
53
54
struct acpi_pcib_softc {
55
struct pcib_softc ap_pcibsc;
56
ACPI_HANDLE ap_handle;
57
ACPI_BUFFER ap_prt; /* interrupt routing table */
58
};
59
60
struct acpi_pcib_lookup_info {
61
UINT32 address;
62
ACPI_HANDLE handle;
63
};
64
65
static int acpi_pcib_pci_probe(device_t bus);
66
static int acpi_pcib_pci_attach(device_t bus);
67
static int acpi_pcib_pci_detach(device_t bus);
68
static int acpi_pcib_read_ivar(device_t dev, device_t child,
69
int which, uintptr_t *result);
70
static int acpi_pcib_pci_route_interrupt(device_t pcib,
71
device_t dev, int pin);
72
73
static device_method_t acpi_pcib_pci_methods[] = {
74
/* Device interface */
75
DEVMETHOD(device_probe, acpi_pcib_pci_probe),
76
DEVMETHOD(device_attach, acpi_pcib_pci_attach),
77
DEVMETHOD(device_detach, acpi_pcib_pci_detach),
78
79
/* Bus interface */
80
DEVMETHOD(bus_read_ivar, acpi_pcib_read_ivar),
81
DEVMETHOD(bus_get_cpus, acpi_pcib_get_cpus),
82
83
/* pcib interface */
84
DEVMETHOD(pcib_route_interrupt, acpi_pcib_pci_route_interrupt),
85
DEVMETHOD(pcib_power_for_sleep, acpi_pcib_power_for_sleep),
86
87
DEVMETHOD_END
88
};
89
90
DEFINE_CLASS_1(pcib, acpi_pcib_pci_driver, acpi_pcib_pci_methods,
91
sizeof(struct acpi_pcib_softc), pcib_driver);
92
DRIVER_MODULE(acpi_pcib, pci, acpi_pcib_pci_driver, 0, 0);
93
MODULE_DEPEND(acpi_pcib, acpi, 1, 1, 1);
94
95
static int
96
acpi_pcib_pci_probe(device_t dev)
97
{
98
99
if (pci_get_class(dev) != PCIC_BRIDGE ||
100
pci_get_subclass(dev) != PCIS_BRIDGE_PCI ||
101
acpi_disabled("pci"))
102
return (ENXIO);
103
if (acpi_get_handle(dev) == NULL)
104
return (ENXIO);
105
if (pci_cfgregopen() == 0)
106
return (ENXIO);
107
108
device_set_desc(dev, "ACPI PCI-PCI bridge");
109
return (-1000);
110
}
111
112
static int
113
acpi_pcib_pci_attach(device_t dev)
114
{
115
struct acpi_pcib_softc *sc;
116
117
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
118
119
pcib_attach_common(dev);
120
sc = device_get_softc(dev);
121
sc->ap_handle = acpi_get_handle(dev);
122
acpi_pcib_fetch_prt(dev, &sc->ap_prt);
123
124
return (pcib_attach_child(dev));
125
}
126
127
static int
128
acpi_pcib_pci_detach(device_t dev)
129
{
130
struct acpi_pcib_softc *sc;
131
int error;
132
133
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
134
135
sc = device_get_softc(dev);
136
error = pcib_detach(dev);
137
if (error == 0)
138
AcpiOsFree(sc->ap_prt.Pointer);
139
return (error);
140
}
141
142
static int
143
acpi_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
144
{
145
struct acpi_pcib_softc *sc = device_get_softc(dev);
146
147
switch (which) {
148
case ACPI_IVAR_HANDLE:
149
*result = (uintptr_t)sc->ap_handle;
150
return (0);
151
}
152
return (pcib_read_ivar(dev, child, which, result));
153
}
154
155
static int
156
acpi_pcib_pci_route_interrupt(device_t pcib, device_t dev, int pin)
157
{
158
struct acpi_pcib_softc *sc;
159
160
sc = device_get_softc(pcib);
161
162
/*
163
* If we don't have a _PRT, fall back to the swizzle method
164
* for routing interrupts.
165
*/
166
if (sc->ap_prt.Pointer == NULL)
167
return (pcib_route_interrupt(pcib, dev, pin));
168
else
169
return (acpi_pcib_route_interrupt(pcib, dev, pin, &sc->ap_prt));
170
}
171
172