1 #include <minix/driver.h>
4 #include <minix/acpi.h>
6 #include "acpi_globals.h"
8 #define PCI_MAX_DEVICES 32
11 #define IRQ_TABLE_ENTRIES (PCI_MAX_DEVICES * PCI_MAX_PINS)
15 int irqtable
[IRQ_TABLE_ENTRIES
];
19 struct pci_bridge
* parent
;
20 struct pci_bridge
* children
[PCI_MAX_DEVICES
];
23 static struct pci_bridge pci_root_bridge
;
26 struct pci_bridge
* bridge
;
27 ACPI_PCI_ROUTING_TABLE
* tbl
;
30 static struct pci_bridge
* find_bridge(struct pci_bridge
* root
,
39 if (root
->secondary_bus
== pbnr
)
40 return root
->children
[dev
];
42 /* serach all children */
44 for (d
= 0; d
< PCI_MAX_DEVICES
; d
++) {
45 struct pci_bridge
* b
;
46 b
= find_bridge(root
->children
[d
],
53 if (root
->secondary_bus
== sbnr
)
56 /* check all children */
58 for (d
= 0; d
< PCI_MAX_DEVICES
; d
++) {
59 struct pci_bridge
* b
;
60 b
= find_bridge(root
->children
[d
],
71 void do_map_bridge(message
*m
)
74 unsigned dev
= ((struct acpi_map_bridge_req
*)m
)->device
;
75 unsigned pbnr
= ((struct acpi_map_bridge_req
*)m
)->primary_bus
;
76 unsigned sbnr
= ((struct acpi_map_bridge_req
*)m
)->secondary_bus
;
78 struct pci_bridge
* bridge
;
80 bridge
= find_bridge(&pci_root_bridge
, pbnr
, dev
, -1);
87 bridge
->primary_bus
= pbnr
;
88 bridge
->secondary_bus
= sbnr
;
91 ((struct acpi_map_bridge_resp
*)m
)->err
= err
;
95 static ACPI_STATUS
device_get_int(ACPI_HANDLE handle
,
100 char buff
[sizeof(ACPI_OBJECT
)];
103 abuff
.Length
= sizeof(buff
);
104 abuff
.Pointer
= buff
;
106 status
= AcpiEvaluateObjectTyped(handle
, name
, NULL
,
107 &abuff
, ACPI_TYPE_INTEGER
);
108 if (ACPI_SUCCESS(status
)) {
109 *val
= ((ACPI_OBJECT
*)abuff
.Pointer
)->Integer
.Value
;
116 void do_get_irq(message
*m
)
118 struct pci_bridge
* bridge
;
121 unsigned bus
= ((struct acpi_get_irq_req
*)m
)->bus
;
122 unsigned dev
= ((struct acpi_get_irq_req
*)m
)->dev
;
123 unsigned pin
= ((struct acpi_get_irq_req
*)m
)->pin
;
125 assert(dev
< PCI_MAX_DEVICES
&& pin
< PCI_MAX_PINS
);
127 bridge
= find_bridge(&pci_root_bridge
, -1, -1, bus
);
132 irq
= bridge
->irqtable
[dev
* PCI_MAX_PINS
+ pin
];
134 ((struct acpi_get_irq_resp
*)m
)->irq
= irq
;
137 static void add_irq(struct pci_bridge
* bridge
,
142 assert(dev
< PCI_MAX_DEVICES
&& pin
< PCI_MAX_PINS
);
144 bridge
->irqtable
[dev
* PCI_MAX_PINS
+ pin
] = irq
;
147 static ACPI_STATUS
get_irq_resource(ACPI_RESOURCE
*res
, void *context
)
149 struct irq_resource
* ires
= (struct irq_resource
*) context
;
151 if (res
->Type
== ACPI_RESOURCE_TYPE_IRQ
) {
152 ACPI_RESOURCE_IRQ
*irq
;
154 irq
= &res
->Data
.Irq
;
155 add_irq(ires
->bridge
, ires
->tbl
->Address
>> 16, ires
->tbl
->Pin
,
156 irq
->Interrupts
[ires
->tbl
->SourceIndex
]);
157 } else if (res
->Type
== ACPI_RESOURCE_TYPE_EXTENDED_IRQ
) {
158 ACPI_RESOURCE_EXTENDED_IRQ
*irq
;
160 irq
= &res
->Data
.ExtendedIrq
;
161 add_irq(ires
->bridge
, ires
->tbl
->Address
>> 16, ires
->tbl
->Pin
,
162 irq
->Interrupts
[ires
->tbl
->SourceIndex
]);
168 static ACPI_STATUS
get_pci_irq_routing(struct pci_bridge
* bridge
)
173 ACPI_PCI_ROUTING_TABLE
*tbl
;
174 ACPI_DEVICE_INFO
*info
;
177 abuff
.Length
= sizeof(buff
);
178 abuff
.Pointer
= buff
;
180 status
= AcpiGetIrqRoutingTable(bridge
->handle
, &abuff
);
181 if (ACPI_FAILURE(status
)) {
185 info
= abuff
.Pointer
;
186 status
= AcpiGetObjectInfo(bridge
->handle
, &info
);
187 if (ACPI_FAILURE(status
))
190 * Decode the device number (upper half of the address) and attach the
191 * new bridge in the children list of its parent
193 bridge
->device
= info
->Address
>> 16;
194 if (bridge
!= &pci_root_bridge
) {
195 bridge
->parent
->children
[bridge
->device
] = bridge
;
196 bridge
->primary_bus
= bridge
->secondary_bus
= -1;
200 for (i
= 0; i
< PCI_MAX_DEVICES
; i
++)
201 bridge
->children
[i
] = NULL
;
203 for (tbl
= (ACPI_PCI_ROUTING_TABLE
*)abuff
.Pointer
; tbl
->Length
;
204 tbl
= (ACPI_PCI_ROUTING_TABLE
*)
205 ((char *)tbl
+ tbl
->Length
)) {
206 ACPI_HANDLE src_handle
;
207 struct irq_resource ires
;
209 if (*(char*)tbl
->Source
== '\0') {
210 add_irq(bridge
, tbl
->Address
>> 16,
211 tbl
->Pin
, tbl
->SourceIndex
);
215 status
= AcpiGetHandle(bridge
->handle
, tbl
->Source
, &src_handle
);
216 if (ACPI_FAILURE(status
)) {
217 printf("Failed AcpiGetHandle\n");
220 ires
.bridge
= bridge
;
222 status
= AcpiWalkResources(src_handle
, METHOD_NAME__CRS
,
223 get_irq_resource
, &ires
);
224 if (ACPI_FAILURE(status
)) {
225 printf("Failed IRQ resource\n");
233 static void bridge_init_irqtable(struct pci_bridge
* bridge
)
237 for (i
= 0; i
< IRQ_TABLE_ENTRIES
; i
++)
238 bridge
->irqtable
[i
] = -1;
241 static ACPI_STATUS
add_pci_dev(ACPI_HANDLE handle
,
249 ACPI_HANDLE parent_handle
;
250 struct pci_bridge
* bridge
;
251 struct pci_bridge
* parent_bridge
= (struct pci_bridge
*) context
;
254 /* skip pci root when we get to it again */
255 if (handle
== pci_root_bridge
.handle
)
258 status
= AcpiGetParent(handle
, &parent_handle
);
259 if (!ACPI_SUCCESS(status
))
261 /* skip devices that have a different parent */
262 if (parent_handle
!= parent_bridge
->handle
)
265 abuff
.Length
= sizeof(buff
);
266 abuff
.Pointer
= buff
;
268 bridge
= malloc(sizeof(struct pci_bridge
));
271 bridge
->handle
= handle
;
272 bridge
->parent
= parent_bridge
;
273 bridge_init_irqtable(bridge
);
275 status
= get_pci_irq_routing(bridge
);
276 if (!(ACPI_SUCCESS(status
))) {
281 /* get the pci bridges */
282 status
= AcpiGetDevices(NULL
, add_pci_dev
, bridge
, NULL
);
286 static ACPI_STATUS
add_pci_root_dev(ACPI_HANDLE handle
,
291 static unsigned called
;
295 printf("ACPI: Warning! Multi rooted PCI is not supported!\n");
299 pci_root_bridge
.handle
= handle
;
300 pci_root_bridge
.primary_bus
= -1; /* undefined */
301 pci_root_bridge
.secondary_bus
= 0; /* root bus is 0 in a single root
303 bridge_init_irqtable(&pci_root_bridge
);
305 status
= get_pci_irq_routing(&pci_root_bridge
);
306 if (!ACPI_SUCCESS(status
))
309 /* get the pci bridges */
310 status
= AcpiGetDevices(NULL
, add_pci_dev
, &pci_root_bridge
, NULL
);
314 void pci_scan_devices(void)
318 /* do not scan devices in PIC mode */
319 if (!machine
.apic_enabled
)
322 /* get the root first */
323 status
= AcpiGetDevices("PNP0A03", add_pci_root_dev
, NULL
, NULL
);
324 assert(ACPI_SUCCESS(status
));