ACPI pci-to-pci bridges
- every pci device which implements _PRT acpi method is considered to be a pci-to-pci bridge - acpi driver constructs a hierarchy of pci-to-pci bridges - when pci driver identifies a pci-to-pci bridge it tells acpi driver what is the primary and the secondary bus for this device - when pci requests IRQ routing information from acpi, it passes the bus number too to be able to identify the device accurately
This commit is contained in:
parent
98c93e76d7
commit
40bfed28cd
7 changed files with 392 additions and 159 deletions
|
@ -8,6 +8,7 @@ PROG= acpi
|
|||
|
||||
SRCS= \
|
||||
acpi.c \
|
||||
pci.c \
|
||||
osminixxf.c
|
||||
|
||||
ACPICA_SRCS= \
|
||||
|
|
|
@ -3,17 +3,11 @@
|
|||
#include <assert.h>
|
||||
#include <minix/acpi.h>
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
PUBLIC int acpi_enabled;
|
||||
PUBLIC struct machine machine;
|
||||
|
||||
#define PCI_MAX_DEVICES 32
|
||||
#define PCI_MAX_PINS 4
|
||||
|
||||
#define IRQ_TABLE_ENTRIES (PCI_MAX_DEVICES * PCI_MAX_PINS)
|
||||
|
||||
PRIVATE int irqtable[IRQ_TABLE_ENTRIES];
|
||||
PRIVATE ACPI_HANDLE pci_root_handle;
|
||||
|
||||
/* don't know where ACPI tables are, we may need to access any memory */
|
||||
PRIVATE int init_mem_priv(void)
|
||||
{
|
||||
|
@ -46,152 +40,6 @@ PRIVATE void set_machine_mode(void)
|
|||
machine.apic_enabled ? "APIC" : "PIC");
|
||||
}
|
||||
|
||||
PRIVATE ACPI_STATUS device_get_int(ACPI_HANDLE handle,
|
||||
char * name,
|
||||
ACPI_INTEGER * val)
|
||||
{
|
||||
ACPI_STATUS status;
|
||||
char buff[sizeof(ACPI_OBJECT)];
|
||||
ACPI_BUFFER abuff;
|
||||
|
||||
abuff.Length = sizeof(buff);
|
||||
abuff.Pointer = buff;
|
||||
|
||||
status = AcpiEvaluateObjectTyped(handle, name, NULL,
|
||||
&abuff, ACPI_TYPE_INTEGER);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
*val = ((ACPI_OBJECT *)abuff.Pointer)->Integer.Value;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
PRIVATE void do_get_irq(message *m)
|
||||
{
|
||||
unsigned dev = ((struct acpi_get_irq_req *)m)->dev;
|
||||
unsigned pin = ((struct acpi_get_irq_req *)m)->pin;
|
||||
|
||||
assert(dev < PCI_MAX_DEVICES && pin < PCI_MAX_PINS);
|
||||
|
||||
((struct acpi_get_irq_resp *)m)->irq =
|
||||
irqtable[dev * PCI_MAX_PINS + pin];
|
||||
}
|
||||
|
||||
PRIVATE void add_irq(unsigned dev, unsigned pin, u8_t irq)
|
||||
{
|
||||
assert(dev < PCI_MAX_DEVICES && pin < PCI_MAX_PINS);
|
||||
|
||||
irqtable[dev * PCI_MAX_PINS + pin] = irq;
|
||||
}
|
||||
|
||||
PRIVATE ACPI_STATUS get_irq_resource(ACPI_RESOURCE *res, void *context)
|
||||
{
|
||||
ACPI_PCI_ROUTING_TABLE *tbl = (ACPI_PCI_ROUTING_TABLE *) context;
|
||||
|
||||
if (res->Type == ACPI_RESOURCE_TYPE_IRQ) {
|
||||
ACPI_RESOURCE_IRQ *irq;
|
||||
|
||||
irq = &res->Data.Irq;
|
||||
add_irq(tbl->Address >> 16, tbl->Pin,
|
||||
irq->Interrupts[tbl->SourceIndex]);
|
||||
} else if (res->Type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
|
||||
ACPI_RESOURCE_EXTENDED_IRQ *irq;
|
||||
|
||||
add_irq(tbl->Address >> 16, tbl->Pin,
|
||||
irq->Interrupts[tbl->SourceIndex]);
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
PRIVATE ACPI_STATUS get_pci_irq_routing(ACPI_HANDLE handle)
|
||||
{
|
||||
ACPI_STATUS status;
|
||||
ACPI_BUFFER abuff;
|
||||
char buff[4096];
|
||||
ACPI_PCI_ROUTING_TABLE *tbl;
|
||||
|
||||
abuff.Length = sizeof(buff);
|
||||
abuff.Pointer = buff;
|
||||
|
||||
status = AcpiGetIrqRoutingTable(handle, &abuff);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
for (tbl = (ACPI_PCI_ROUTING_TABLE *)abuff.Pointer; tbl->Length;
|
||||
tbl = (ACPI_PCI_ROUTING_TABLE *)
|
||||
((char *)tbl + tbl->Length)) {
|
||||
ACPI_HANDLE src_handle;
|
||||
|
||||
if (*(char*)tbl->Source == '\0') {
|
||||
add_irq(tbl->Address >> 16, tbl->Pin, tbl->SourceIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
status = AcpiGetHandle(handle, tbl->Source, &src_handle);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printf("Failed AcpiGetHandle\n");
|
||||
continue;
|
||||
}
|
||||
status = AcpiWalkResources(src_handle, METHOD_NAME__CRS,
|
||||
get_irq_resource, tbl);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printf("Failed IRQ resource\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
PRIVATE ACPI_STATUS add_pci_root_dev(ACPI_HANDLE handle,
|
||||
UINT32 level,
|
||||
void *context,
|
||||
void **retval)
|
||||
{
|
||||
int i;
|
||||
static unsigned called;
|
||||
|
||||
if (++called > 1) {
|
||||
printf("ACPI: Warning! Multi rooted PCI is not supported!\n");
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
for (i = 0; i < IRQ_TABLE_ENTRIES; i++)
|
||||
irqtable[i] = -1;
|
||||
|
||||
return get_pci_irq_routing(handle);
|
||||
}
|
||||
|
||||
PRIVATE ACPI_STATUS add_pci_dev(ACPI_HANDLE handle,
|
||||
UINT32 level,
|
||||
void *context,
|
||||
void **retval)
|
||||
{
|
||||
/* skip pci root when we get to it again */
|
||||
if (handle == pci_root_handle)
|
||||
return AE_OK;
|
||||
|
||||
return get_pci_irq_routing(handle);
|
||||
}
|
||||
|
||||
PRIVATE void scan_devices(void)
|
||||
{
|
||||
ACPI_STATUS status;
|
||||
|
||||
/* do not scan devices in PIC mode */
|
||||
if (!machine.apic_enabled)
|
||||
return;
|
||||
|
||||
/* get the root first */
|
||||
status = AcpiGetDevices("PNP0A03", add_pci_root_dev, NULL, NULL);
|
||||
assert(ACPI_SUCCESS(status));
|
||||
|
||||
/* get the rest of the devices that implement _PRT */
|
||||
status = AcpiGetDevices(NULL, add_pci_dev, NULL, NULL);
|
||||
assert(ACPI_SUCCESS(status));
|
||||
}
|
||||
PRIVATE ACPI_STATUS init_acpica(void)
|
||||
{
|
||||
ACPI_STATUS status;
|
||||
|
@ -218,7 +66,7 @@ PRIVATE ACPI_STATUS init_acpica(void)
|
|||
|
||||
set_machine_mode();
|
||||
|
||||
scan_devices();
|
||||
pci_scan_devices();
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
@ -291,6 +139,9 @@ int main(void)
|
|||
case ACPI_REQ_GET_IRQ:
|
||||
do_get_irq(&m);
|
||||
break;
|
||||
case ACPI_REQ_MAP_BRIDGE:
|
||||
do_map_bridge(&m);
|
||||
break;
|
||||
default:
|
||||
printf("ACPI: ignoring unsupported request %d "
|
||||
"from %d\n",
|
||||
|
|
7
drivers/acpi/acpi_globals.h
Normal file
7
drivers/acpi/acpi_globals.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef __ACPI_GLOBALS_H__
|
||||
#define __ACPI_GLOBALS_H__
|
||||
|
||||
EXTERN int acpi_enabled;
|
||||
EXTERN struct machine machine;
|
||||
|
||||
#endif /* __ACPI_GLOBALS_H__ */
|
314
drivers/acpi/pci.c
Normal file
314
drivers/acpi/pci.c
Normal file
|
@ -0,0 +1,314 @@
|
|||
#include <minix/driver.h>
|
||||
#include <acpi.h>
|
||||
#include <assert.h>
|
||||
#include <minix/acpi.h>
|
||||
|
||||
#include "acpi_globals.h"
|
||||
|
||||
#define PCI_MAX_DEVICES 32
|
||||
#define PCI_MAX_PINS 4
|
||||
|
||||
#define IRQ_TABLE_ENTRIES (PCI_MAX_DEVICES * PCI_MAX_PINS)
|
||||
|
||||
struct pci_bridge {
|
||||
ACPI_HANDLE handle;
|
||||
int irqtable[IRQ_TABLE_ENTRIES];
|
||||
int primary_bus;
|
||||
int secondary_bus;
|
||||
unsigned device;
|
||||
struct pci_bridge * parent;
|
||||
struct pci_bridge * children[PCI_MAX_DEVICES];
|
||||
};
|
||||
|
||||
PRIVATE struct pci_bridge pci_root_bridge;
|
||||
|
||||
struct irq_resource {
|
||||
struct pci_bridge * bridge;
|
||||
ACPI_PCI_ROUTING_TABLE * tbl;
|
||||
};
|
||||
|
||||
PRIVATE struct pci_bridge * find_bridge(struct pci_bridge * root,
|
||||
int pbnr,
|
||||
int dev,
|
||||
int sbnr)
|
||||
{
|
||||
if (!root)
|
||||
return NULL;
|
||||
|
||||
if (sbnr == -1) {
|
||||
if (root->secondary_bus == pbnr)
|
||||
return root->children[dev];
|
||||
else {
|
||||
/* serach all children */
|
||||
unsigned d;
|
||||
for (d = 0; d < PCI_MAX_DEVICES; d++) {
|
||||
struct pci_bridge * b;
|
||||
b = find_bridge(root->children[d],
|
||||
pbnr, dev, sbnr);
|
||||
if (b)
|
||||
return b;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (root->secondary_bus == sbnr)
|
||||
return root;
|
||||
else {
|
||||
/* check all children */
|
||||
unsigned d;
|
||||
for (d = 0; d < PCI_MAX_DEVICES; d++) {
|
||||
struct pci_bridge * b;
|
||||
b = find_bridge(root->children[d],
|
||||
pbnr, dev, sbnr);
|
||||
if (b)
|
||||
return b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PUBLIC void do_map_bridge(message *m)
|
||||
{
|
||||
int err = OK;
|
||||
unsigned dev = ((struct acpi_map_bridge_req *)m)->device;
|
||||
unsigned pbnr = ((struct acpi_map_bridge_req *)m)->primary_bus;
|
||||
unsigned sbnr = ((struct acpi_map_bridge_req *)m)->secondary_bus;
|
||||
|
||||
struct pci_bridge * bridge;
|
||||
|
||||
bridge = find_bridge(&pci_root_bridge, pbnr, dev, -1);
|
||||
|
||||
if (!bridge) {
|
||||
err = ENODEV;
|
||||
goto map_error;
|
||||
}
|
||||
|
||||
bridge->primary_bus = pbnr;
|
||||
bridge->secondary_bus = sbnr;
|
||||
|
||||
map_error:
|
||||
((struct acpi_map_bridge_resp *)m)->err = err;
|
||||
}
|
||||
|
||||
PRIVATE ACPI_STATUS device_get_int(ACPI_HANDLE handle,
|
||||
char * name,
|
||||
ACPI_INTEGER * val)
|
||||
{
|
||||
ACPI_STATUS status;
|
||||
char buff[sizeof(ACPI_OBJECT)];
|
||||
ACPI_BUFFER abuff;
|
||||
|
||||
abuff.Length = sizeof(buff);
|
||||
abuff.Pointer = buff;
|
||||
|
||||
status = AcpiEvaluateObjectTyped(handle, name, NULL,
|
||||
&abuff, ACPI_TYPE_INTEGER);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
*val = ((ACPI_OBJECT *)abuff.Pointer)->Integer.Value;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
PUBLIC void do_get_irq(message *m)
|
||||
{
|
||||
struct pci_bridge * bridge;
|
||||
int irq;
|
||||
|
||||
unsigned bus = ((struct acpi_get_irq_req *)m)->bus;
|
||||
unsigned dev = ((struct acpi_get_irq_req *)m)->dev;
|
||||
unsigned pin = ((struct acpi_get_irq_req *)m)->pin;
|
||||
|
||||
assert(dev < PCI_MAX_DEVICES && pin < PCI_MAX_PINS);
|
||||
|
||||
bridge = find_bridge(&pci_root_bridge, -1, -1, bus);
|
||||
|
||||
if (!bridge)
|
||||
irq = -1;
|
||||
else
|
||||
irq = bridge->irqtable[dev * PCI_MAX_PINS + pin];
|
||||
|
||||
((struct acpi_get_irq_resp *)m)->irq = irq;
|
||||
}
|
||||
|
||||
PRIVATE void add_irq(struct pci_bridge * bridge,
|
||||
unsigned dev,
|
||||
unsigned pin,
|
||||
u8_t irq)
|
||||
{
|
||||
assert(dev < PCI_MAX_DEVICES && pin < PCI_MAX_PINS);
|
||||
|
||||
bridge->irqtable[dev * PCI_MAX_PINS + pin] = irq;
|
||||
}
|
||||
|
||||
PRIVATE ACPI_STATUS get_irq_resource(ACPI_RESOURCE *res, void *context)
|
||||
{
|
||||
struct irq_resource * ires = (struct irq_resource *) context;
|
||||
|
||||
if (res->Type == ACPI_RESOURCE_TYPE_IRQ) {
|
||||
ACPI_RESOURCE_IRQ *irq;
|
||||
|
||||
irq = &res->Data.Irq;
|
||||
add_irq(ires->bridge, ires->tbl->Address >> 16, ires->tbl->Pin,
|
||||
irq->Interrupts[ires->tbl->SourceIndex]);
|
||||
} else if (res->Type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
|
||||
ACPI_RESOURCE_EXTENDED_IRQ *irq;
|
||||
|
||||
add_irq(ires->bridge, ires->tbl->Address >> 16, ires->tbl->Pin,
|
||||
irq->Interrupts[ires->tbl->SourceIndex]);
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
PRIVATE ACPI_STATUS get_pci_irq_routing(struct pci_bridge * bridge)
|
||||
{
|
||||
ACPI_STATUS status;
|
||||
ACPI_BUFFER abuff;
|
||||
char buff[4096];
|
||||
ACPI_PCI_ROUTING_TABLE *tbl;
|
||||
ACPI_DEVICE_INFO *info;
|
||||
int i;
|
||||
|
||||
abuff.Length = sizeof(buff);
|
||||
abuff.Pointer = buff;
|
||||
|
||||
status = AcpiGetIrqRoutingTable(bridge->handle, &abuff);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
info = abuff.Pointer;
|
||||
status = AcpiGetObjectInfo(bridge->handle, &info);
|
||||
if (ACPI_FAILURE(status))
|
||||
return status;
|
||||
/*
|
||||
* Decode the device number (upper half of the address) and attach the
|
||||
* new bridge in the children list of its parent
|
||||
*/
|
||||
bridge->device = info->Address >> 16;
|
||||
if (bridge != &pci_root_bridge) {
|
||||
bridge->parent->children[bridge->device] = bridge;
|
||||
bridge->primary_bus = bridge->secondary_bus = -1;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < PCI_MAX_DEVICES; i++)
|
||||
bridge->children[i] = NULL;
|
||||
for (i = 0; i < IRQ_TABLE_ENTRIES; i++)
|
||||
bridge->irqtable[i] = -1;
|
||||
|
||||
for (tbl = (ACPI_PCI_ROUTING_TABLE *)abuff.Pointer; tbl->Length;
|
||||
tbl = (ACPI_PCI_ROUTING_TABLE *)
|
||||
((char *)tbl + tbl->Length)) {
|
||||
ACPI_HANDLE src_handle;
|
||||
struct irq_resource ires;
|
||||
|
||||
if (*(char*)tbl->Source == '\0') {
|
||||
add_irq(bridge, tbl->Address >> 16,
|
||||
tbl->Pin, tbl->SourceIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
status = AcpiGetHandle(bridge->handle, tbl->Source, &src_handle);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printf("Failed AcpiGetHandle\n");
|
||||
continue;
|
||||
}
|
||||
ires.bridge = bridge;
|
||||
ires,tbl = tbl;
|
||||
status = AcpiWalkResources(src_handle, METHOD_NAME__CRS,
|
||||
get_irq_resource, &ires);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printf("Failed IRQ resource\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
PRIVATE ACPI_STATUS add_pci_dev(ACPI_HANDLE handle,
|
||||
UINT32 level,
|
||||
void *context,
|
||||
void **retval)
|
||||
{
|
||||
ACPI_STATUS status;
|
||||
ACPI_BUFFER abuff;
|
||||
char buff[4096];
|
||||
ACPI_HANDLE parent_handle;
|
||||
struct pci_bridge * bridge;
|
||||
struct pci_bridge * parent_bridge = (struct pci_bridge *) context;
|
||||
|
||||
|
||||
/* skip pci root when we get to it again */
|
||||
if (handle == pci_root_bridge.handle)
|
||||
return AE_OK;
|
||||
|
||||
status = AcpiGetParent(handle, &parent_handle);
|
||||
if (!ACPI_SUCCESS(status))
|
||||
return status;
|
||||
/* skip devices that have a different parent */
|
||||
if (parent_handle != parent_bridge->handle)
|
||||
return AE_OK;
|
||||
|
||||
abuff.Length = sizeof(buff);
|
||||
abuff.Pointer = buff;
|
||||
|
||||
bridge = malloc(sizeof(struct pci_bridge));
|
||||
if (!bridge)
|
||||
return AE_NO_MEMORY;
|
||||
bridge->handle = handle;
|
||||
bridge->parent = parent_bridge;
|
||||
|
||||
status = get_pci_irq_routing(bridge);
|
||||
if (!(ACPI_SUCCESS(status))) {
|
||||
free(bridge);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* get the pci bridges */
|
||||
status = AcpiGetDevices(NULL, add_pci_dev, bridge, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
PRIVATE ACPI_STATUS add_pci_root_dev(ACPI_HANDLE handle,
|
||||
UINT32 level,
|
||||
void *context,
|
||||
void **retval)
|
||||
{
|
||||
static unsigned called;
|
||||
ACPI_STATUS status;
|
||||
|
||||
if (++called > 1) {
|
||||
printf("ACPI: Warning! Multi rooted PCI is not supported!\n");
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
pci_root_bridge.handle = handle;
|
||||
pci_root_bridge.primary_bus = -1; /* undefined */
|
||||
pci_root_bridge.secondary_bus = 0; /* root bus is 0 in a single root
|
||||
system */
|
||||
|
||||
status = get_pci_irq_routing(&pci_root_bridge);
|
||||
if (!ACPI_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
/* get the pci bridges */
|
||||
status = AcpiGetDevices(NULL, add_pci_dev, &pci_root_bridge, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
PUBLIC void pci_scan_devices(void)
|
||||
{
|
||||
ACPI_STATUS status;
|
||||
|
||||
/* do not scan devices in PIC mode */
|
||||
if (!machine.apic_enabled)
|
||||
return;
|
||||
|
||||
/* get the root first */
|
||||
status = AcpiGetDevices("PNP0A03", add_pci_root_dev, NULL, NULL);
|
||||
assert(ACPI_SUCCESS(status));
|
||||
}
|
12
drivers/acpi/pci.h
Normal file
12
drivers/acpi/pci.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef __ACPI_PCI_H__
|
||||
#define __ACPI_PCI_H__
|
||||
|
||||
#include <minix/ipc.h>
|
||||
|
||||
_PROTOTYPE(void do_map_bridge, (message *m));
|
||||
_PROTOTYPE(void do_get_irq, (message *m));
|
||||
|
||||
_PROTOTYPE(void pci_scan_devices, (void));
|
||||
|
||||
|
||||
#endif /* __ACPI_PCI_H__ */
|
|
@ -945,12 +945,13 @@ PRIVATE int is_duplicate(u8_t busnr, u8_t dev, u8_t func)
|
|||
return 0;
|
||||
}
|
||||
|
||||
PRIVATE int acpi_get_irq(unsigned dev, unsigned pin)
|
||||
PRIVATE int acpi_get_irq(unsigned bus, unsigned dev, unsigned pin)
|
||||
{
|
||||
int err;
|
||||
message m;
|
||||
|
||||
((struct acpi_get_irq_req *)&m)->hdr.request = ACPI_REQ_GET_IRQ;
|
||||
((struct acpi_get_irq_req *)&m)->bus = bus;
|
||||
((struct acpi_get_irq_req *)&m)->dev = dev;
|
||||
((struct acpi_get_irq_req *)&m)->pin = pin;
|
||||
|
||||
|
@ -973,7 +974,8 @@ PRIVATE int derive_irq(struct pcidev * dev, int pin)
|
|||
*/
|
||||
slot = ((dev->pd_func) >> 3) & 0x1f;
|
||||
|
||||
return acpi_get_irq(parent_bridge->pd_dev, (pin + slot) % 4);
|
||||
return acpi_get_irq(parent_bridge->pd_busnr,
|
||||
parent_bridge->pd_dev, (pin + slot) % 4);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
@ -990,7 +992,8 @@ int devind;
|
|||
if (ipr && machine.apic_enabled) {
|
||||
int irq;
|
||||
|
||||
irq = acpi_get_irq(pcidev[devind].pd_dev, ipr - 1);
|
||||
irq = acpi_get_irq(pcidev[devind].pd_busnr,
|
||||
pcidev[devind].pd_dev, ipr - 1);
|
||||
|
||||
if (irq < 0)
|
||||
irq = derive_irq(&pcidev[devind], ipr - 1);
|
||||
|
@ -1834,6 +1837,29 @@ int busind;
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tells acpi which two busses are connected by this bridge. The primary bus
|
||||
* (pbnr) must be already known to acpi and it must map dev as the connection to
|
||||
* the secondary (sbnr) bus
|
||||
*/
|
||||
PRIVATE void acpi_map_bridge(unsigned pbnr, unsigned dev, unsigned sbnr)
|
||||
{
|
||||
int err;
|
||||
message m;
|
||||
|
||||
((struct acpi_map_bridge_req *)&m)->hdr.request = ACPI_REQ_MAP_BRIDGE;
|
||||
((struct acpi_map_bridge_req *)&m)->primary_bus = pbnr;
|
||||
((struct acpi_map_bridge_req *)&m)->secondary_bus = sbnr;
|
||||
((struct acpi_map_bridge_req *)&m)->device = dev;
|
||||
|
||||
if ((err = sendrec(acpi_ep, &m)) != OK)
|
||||
panic("PCI: error %d while receiveing from ACPI\n", err);
|
||||
|
||||
if (((struct acpi_map_bridge_resp *)&m)->err != OK)
|
||||
panic("PCI: acpi failed to map pci (%d) to pci (%d) bridge\n",
|
||||
pbnr, sbnr);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_pcibridge *
|
||||
*===========================================================================*/
|
||||
|
@ -1963,6 +1989,11 @@ int busind;
|
|||
default:
|
||||
panic("unknown PCI-PCI bridge type: %d", type);
|
||||
}
|
||||
|
||||
if (machine.apic_enabled)
|
||||
acpi_map_bridge(pcidev[devind].pd_busnr,
|
||||
pcidev[devind].pd_dev, sbusn);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
printf(
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <minix/ipc.h>
|
||||
|
||||
#define ACPI_REQ_GET_IRQ 1
|
||||
#define ACPI_REQ_MAP_BRIDGE 2
|
||||
|
||||
struct acpi_request_hdr {
|
||||
endpoint_t m_source; /* message header */
|
||||
|
@ -14,9 +15,10 @@ struct acpi_request_hdr {
|
|||
*/
|
||||
struct acpi_get_irq_req {
|
||||
struct acpi_request_hdr hdr;
|
||||
u32_t bus;
|
||||
u32_t dev;
|
||||
u32_t pin;
|
||||
u32_t __padding[5];
|
||||
u32_t __padding[4];
|
||||
};
|
||||
|
||||
/* response from acpi to acpi_get_irq_req */
|
||||
|
@ -25,3 +27,18 @@ struct acpi_get_irq_resp {
|
|||
i32_t irq;
|
||||
u32_t __padding[7];
|
||||
};
|
||||
|
||||
/* message format for pci bridge mappings to acpi */
|
||||
struct acpi_map_bridge_req {
|
||||
struct acpi_request_hdr hdr;
|
||||
u32_t primary_bus;
|
||||
u32_t secondary_bus;
|
||||
u32_t device;
|
||||
u32_t __padding[4];
|
||||
};
|
||||
|
||||
struct acpi_map_bridge_resp {
|
||||
endpoint_t m_source; /* message header */
|
||||
int err;
|
||||
u32_t __padding[7];
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue