minix/drivers/acpi/acpi.c
Tomas Hruby 40bfed28cd 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
2010-10-21 17:07:09 +00:00

158 lines
3.1 KiB
C

#include <minix/driver.h>
#include <acpi.h>
#include <assert.h>
#include <minix/acpi.h>
#include "pci.h"
PUBLIC int acpi_enabled;
PUBLIC struct machine machine;
/* don't know where ACPI tables are, we may need to access any memory */
PRIVATE int init_mem_priv(void)
{
struct mem_range mr;
mr.mr_base = 0;
mr.mr_limit = 0xffffffff;
return sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr);
}
PRIVATE void set_machine_mode(void)
{
ACPI_OBJECT arg1;
ACPI_OBJECT_LIST args;
ACPI_STATUS as;
arg1.Type = ACPI_TYPE_INTEGER;
arg1.Integer.Value = machine.apic_enabled ? 1 : 0;
args.Count = 1;
args.Pointer = &arg1;
as = AcpiEvaluateObject(ACPI_ROOT_OBJECT, "_PIC", &args, NULL);
/*
* We can silently ignore failure as it may not be implemented, ACPI should
* provide us with correct information anyway
*/
if (ACPI_SUCCESS(as))
printf("ACPI: machine set to %s mode\n",
machine.apic_enabled ? "APIC" : "PIC");
}
PRIVATE ACPI_STATUS init_acpica(void)
{
ACPI_STATUS status;
status = AcpiInitializeSubsystem();
if (ACPI_FAILURE(status))
return status;
status = AcpiInitializeTables(NULL, 16, FALSE);
if (ACPI_FAILURE(status))
return status;
status = AcpiLoadTables();
if (ACPI_FAILURE(status))
return status;
status = AcpiEnableSubsystem(0);
if (ACPI_FAILURE(status))
return status;
status = AcpiInitializeObjects(0);
if (ACPI_FAILURE(status))
return status;
set_machine_mode();
pci_scan_devices();
return AE_OK;
}
PUBLIC void init_acpi(void)
{
ACPI_STATUS acpi_err;
/* test conditions for acpi */
if (sys_getmachine(&machine)) {
printf("ACPI: no machine\n");
return;
}
if (machine.acpi_rsdp == 0) {
printf("ACPI: no RSDP\n");
return;
}
if (init_mem_priv()) {
printf("ACPI: no mem access\n");
return;
}
if ((acpi_err = init_acpica()) == AE_OK) {
acpi_enabled = 1;
printf("ACPI: ACPI enabled\n");
}
else {
acpi_enabled = 0;
printf("ACPI: ACPI failed with err %d\n", acpi_err);
}
}
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
{
init_acpi();
return OK;
}
PRIVATE void sef_local_startup()
{
/* Register init callbacks. */
sef_setcb_init_fresh(sef_cb_init_fresh);
sef_setcb_init_lu(sef_cb_init_fresh);
sef_setcb_init_restart(sef_cb_init_fresh);
/* Register live update callbacks. */
sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
/* Let SEF perform startup. */
sef_startup();
}
int main(void)
{
int err;
message m;
int ipc_status;
sef_local_startup();
for(;;) {
err = driver_receive(ANY, &m, &ipc_status);
if (err != OK) {
printf("ACPI: driver_receive failed: %d\n", err);
continue;
}
switch (((struct acpi_request_hdr *)&m)->request) {
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",
((struct acpi_request_hdr *)&m)->request,
((struct acpi_request_hdr *)&m)->m_source);
}
err = send(m.m_source, &m);
if (err != OK) {
printf("ACPI: send failed: %d\n", err);
}
}
}