Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/acpica/acpi.c
Show First 20 Lines • Show All 173 Lines • ▼ Show 20 Lines | |||||
static int acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); | static int acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); | static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int acpi_debug_objects_sysctl(SYSCTL_HANDLER_ARGS); | static int acpi_debug_objects_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int acpi_pm_func(u_long cmd, void *arg, ...); | static int acpi_pm_func(u_long cmd, void *arg, ...); | ||||
static int acpi_child_location_str_method(device_t acdev, device_t child, | static int acpi_child_location_str_method(device_t acdev, device_t child, | ||||
char *buf, size_t buflen); | char *buf, size_t buflen); | ||||
static int acpi_child_pnpinfo_str_method(device_t acdev, device_t child, | static int acpi_child_pnpinfo_str_method(device_t acdev, device_t child, | ||||
char *buf, size_t buflen); | char *buf, size_t buflen); | ||||
#if defined(__i386__) || defined(__amd64__) | |||||
static void acpi_enable_pcie(void); | static void acpi_enable_pcie(void); | ||||
#endif | |||||
static void acpi_hint_device_unit(device_t acdev, device_t child, | static void acpi_hint_device_unit(device_t acdev, device_t child, | ||||
const char *name, int *unitp); | const char *name, int *unitp); | ||||
static void acpi_reset_interfaces(device_t dev); | static void acpi_reset_interfaces(device_t dev); | ||||
static device_method_t acpi_methods[] = { | static device_method_t acpi_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, acpi_probe), | DEVMETHOD(device_probe, acpi_probe), | ||||
DEVMETHOD(device_attach, acpi_attach), | DEVMETHOD(device_attach, acpi_attach), | ||||
▲ Show 20 Lines • Show All 304 Lines • ▼ Show 20 Lines | #endif | ||||
/* Load ACPI name space. */ | /* Load ACPI name space. */ | ||||
status = AcpiLoadTables(); | status = AcpiLoadTables(); | ||||
if (ACPI_FAILURE(status)) { | if (ACPI_FAILURE(status)) { | ||||
device_printf(dev, "Could not load Namespace: %s\n", | device_printf(dev, "Could not load Namespace: %s\n", | ||||
AcpiFormatException(status)); | AcpiFormatException(status)); | ||||
goto out; | goto out; | ||||
} | } | ||||
#if defined(__i386__) || defined(__amd64__) | |||||
/* Handle MCFG table if present. */ | /* Handle MCFG table if present. */ | ||||
acpi_enable_pcie(); | acpi_enable_pcie(); | ||||
#endif | |||||
/* | /* | ||||
* Note that some systems (specifically, those with namespace evaluation | * Note that some systems (specifically, those with namespace evaluation | ||||
* issues that require the avoidance of parts of the namespace) must | * issues that require the avoidance of parts of the namespace) must | ||||
* avoid running _INI and _STA on everything, as well as dodging the final | * avoid running _INI and _STA on everything, as well as dodging the final | ||||
* object init pass. | * object init pass. | ||||
* | * | ||||
* For these devices, we set ACPI_NO_DEVICE_INIT and ACPI_NO_OBJECT_INIT). | * For these devices, we set ACPI_NO_DEVICE_INIT and ACPI_NO_OBJECT_INIT). | ||||
▲ Show 20 Lines • Show All 764 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
acpi_set_resource(device_t dev, device_t child, int type, int rid, | acpi_set_resource(device_t dev, device_t child, int type, int rid, | ||||
rman_res_t start, rman_res_t count) | rman_res_t start, rman_res_t count) | ||||
{ | { | ||||
struct acpi_softc *sc = device_get_softc(dev); | struct acpi_softc *sc = device_get_softc(dev); | ||||
struct acpi_device *ad = device_get_ivars(child); | struct acpi_device *ad = device_get_ivars(child); | ||||
struct resource_list *rl = &ad->ad_rl; | struct resource_list *rl = &ad->ad_rl; | ||||
#if defined(__i386__) || defined(__amd64__) | |||||
ACPI_DEVICE_INFO *devinfo; | ACPI_DEVICE_INFO *devinfo; | ||||
#endif | |||||
rman_res_t end; | rman_res_t end; | ||||
int allow; | |||||
/* Ignore IRQ resources for PCI link devices. */ | /* Ignore IRQ resources for PCI link devices. */ | ||||
if (type == SYS_RES_IRQ && | if (type == SYS_RES_IRQ && | ||||
ACPI_ID_PROBE(dev, child, pcilink_ids, NULL) <= 0) | ACPI_ID_PROBE(dev, child, pcilink_ids, NULL) <= 0) | ||||
return (0); | return (0); | ||||
/* | /* | ||||
* Ignore most resources for PCI root bridges. Some BIOSes | * Ignore most resources for PCI root bridges. Some BIOSes | ||||
* incorrectly enumerate the memory ranges they decode as plain | * incorrectly enumerate the memory ranges they decode as plain | ||||
* memory resources instead of as ResourceProducer ranges. Other | * memory resources instead of as ResourceProducer ranges. Other | ||||
* BIOSes incorrectly list system resource entries for I/O ranges | * BIOSes incorrectly list system resource entries for I/O ranges | ||||
* under the PCI bridge. Do allow the one known-correct case on | * under the PCI bridge. Do allow the one known-correct case on | ||||
* x86 of a PCI bridge claiming the I/O ports used for PCI config | * x86 of a PCI bridge claiming the I/O ports used for PCI config | ||||
* access. | * access. | ||||
*/ | */ | ||||
#if defined(__i386__) || defined(__amd64__) | |||||
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { | if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { | ||||
if (ACPI_SUCCESS(AcpiGetObjectInfo(ad->ad_handle, &devinfo))) { | if (ACPI_SUCCESS(AcpiGetObjectInfo(ad->ad_handle, &devinfo))) { | ||||
if ((devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) { | if ((devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) { | ||||
if (!(type == SYS_RES_IOPORT && start == CONF1_ADDR_PORT)) { | #if defined(__i386__) || defined(__amd64__) | ||||
allow = (type == SYS_RES_IOPORT && start == CONF1_ADDR_PORT); | |||||
#else | |||||
allow = 0; | |||||
#endif | |||||
if (!allow) { | |||||
AcpiOsFree(devinfo); | AcpiOsFree(devinfo); | ||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
AcpiOsFree(devinfo); | AcpiOsFree(devinfo); | ||||
} | } | ||||
} | } | ||||
#endif | |||||
#ifdef INTRNG | #ifdef INTRNG | ||||
/* map with default for now */ | /* map with default for now */ | ||||
if (type == SYS_RES_IRQ) | if (type == SYS_RES_IRQ) | ||||
start = (rman_res_t)acpi_map_intr(child, (u_int)start, | start = (rman_res_t)acpi_map_intr(child, (u_int)start, | ||||
acpi_get_handle(child)); | acpi_get_handle(child)); | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 540 Lines • ▼ Show 20 Lines | |||||
out: | out: | ||||
if (result == 0 && ids->ip_desc) | if (result == 0 && ids->ip_desc) | ||||
device_set_desc(child, ids->ip_desc); | device_set_desc(child, ids->ip_desc); | ||||
return_VALUE (result); | return_VALUE (result); | ||||
} | } | ||||
#if defined(__i386__) || defined(__amd64__) | |||||
/* | /* | ||||
* Look for a MCFG table. If it is present, use the settings for | * Look for a MCFG table. If it is present, use the settings for | ||||
* domain (segment) 0 to setup PCI config space access via the memory | * domain (segment) 0 to setup PCI config space access via the memory | ||||
* map. | * map. | ||||
* | |||||
* On non-x86 architectures (arm64 for now), this will be done from the | |||||
* PCI host bridge driver. | |||||
*/ | */ | ||||
static void | static void | ||||
acpi_enable_pcie(void) | acpi_enable_pcie(void) | ||||
{ | { | ||||
#if defined(__i386__) || defined(__amd64__) | |||||
ACPI_TABLE_HEADER *hdr; | ACPI_TABLE_HEADER *hdr; | ||||
ACPI_MCFG_ALLOCATION *alloc, *end; | ACPI_MCFG_ALLOCATION *alloc, *end; | ||||
ACPI_STATUS status; | ACPI_STATUS status; | ||||
status = AcpiGetTable(ACPI_SIG_MCFG, 1, &hdr); | status = AcpiGetTable(ACPI_SIG_MCFG, 1, &hdr); | ||||
if (ACPI_FAILURE(status)) | if (ACPI_FAILURE(status)) | ||||
return; | return; | ||||
end = (ACPI_MCFG_ALLOCATION *)((char *)hdr + hdr->Length); | end = (ACPI_MCFG_ALLOCATION *)((char *)hdr + hdr->Length); | ||||
alloc = (ACPI_MCFG_ALLOCATION *)((ACPI_TABLE_MCFG *)hdr + 1); | alloc = (ACPI_MCFG_ALLOCATION *)((ACPI_TABLE_MCFG *)hdr + 1); | ||||
while (alloc < end) { | while (alloc < end) { | ||||
if (alloc->PciSegment == 0) { | if (alloc->PciSegment == 0) { | ||||
pcie_cfgregopen(alloc->Address, alloc->StartBusNumber, | pcie_cfgregopen(alloc->Address, alloc->StartBusNumber, | ||||
alloc->EndBusNumber); | alloc->EndBusNumber); | ||||
return; | return; | ||||
} | } | ||||
alloc++; | alloc++; | ||||
} | } | ||||
#endif | |||||
} | } | ||||
#elif defined(__aarch64__) | |||||
static void | |||||
acpi_enable_pcie(device_t child, int segment) | |||||
{ | |||||
ACPI_TABLE_HEADER *hdr; | |||||
ACPI_MCFG_ALLOCATION *alloc, *end; | |||||
ACPI_STATUS status; | |||||
status = AcpiGetTable(ACPI_SIG_MCFG, 1, &hdr); | |||||
if (ACPI_FAILURE(status)) | |||||
return; | |||||
end = (ACPI_MCFG_ALLOCATION *)((char *)hdr + hdr->Length); | |||||
alloc = (ACPI_MCFG_ALLOCATION *)((ACPI_TABLE_MCFG *)hdr + 1); | |||||
while (alloc < end) { | |||||
if (alloc->PciSegment == segment) { | |||||
bus_set_resource(child, SYS_RES_MEMORY, 0, | |||||
alloc->Address, 0x10000000); | |||||
return; | |||||
} | |||||
alloc++; | |||||
} | |||||
} | |||||
#endif | |||||
/* | /* | ||||
* Scan all of the ACPI namespace and attach child devices. | * Scan all of the ACPI namespace and attach child devices. | ||||
* | * | ||||
* We should only expect to find devices in the \_PR, \_TZ, \_SI, and | * We should only expect to find devices in the \_PR, \_TZ, \_SI, and | ||||
* \_SB scopes, and \_PR and \_TZ became obsolete in the ACPI 2.0 spec. | * \_SB scopes, and \_PR and \_TZ became obsolete in the ACPI 2.0 spec. | ||||
* However, in violation of the spec, some systems place their PCI link | * However, in violation of the spec, some systems place their PCI link | ||||
* devices in \, so we have to walk the whole namespace. We check the | * devices in \, so we have to walk the whole namespace. We check the | ||||
* type of namespace nodes, so this should be ok. | * type of namespace nodes, so this should be ok. | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | |||||
* Evaluate a child device and determine whether we might attach a device to | * Evaluate a child device and determine whether we might attach a device to | ||||
* it. | * it. | ||||
*/ | */ | ||||
static ACPI_STATUS | static ACPI_STATUS | ||||
acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status) | acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status) | ||||
{ | { | ||||
ACPI_DEVICE_INFO *devinfo; | ACPI_DEVICE_INFO *devinfo; | ||||
struct acpi_device *ad; | struct acpi_device *ad; | ||||
#ifdef __aarch64__ | |||||
int segment; | |||||
#endif | |||||
struct acpi_prw_data prw; | struct acpi_prw_data prw; | ||||
ACPI_OBJECT_TYPE type; | ACPI_OBJECT_TYPE type; | ||||
ACPI_HANDLE h; | ACPI_HANDLE h; | ||||
device_t bus, child; | device_t bus, child; | ||||
char *handle_str; | char *handle_str; | ||||
int order; | int order; | ||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | break; | ||||
ad = device_get_ivars(child); | ad = device_get_ivars(child); | ||||
ad->ad_cls_class = 0xffffff; | ad->ad_cls_class = 0xffffff; | ||||
if (ACPI_SUCCESS(AcpiGetObjectInfo(handle, &devinfo))) { | if (ACPI_SUCCESS(AcpiGetObjectInfo(handle, &devinfo))) { | ||||
if ((devinfo->Valid & ACPI_VALID_CLS) != 0 && | if ((devinfo->Valid & ACPI_VALID_CLS) != 0 && | ||||
devinfo->ClassCode.Length >= ACPI_PCICLS_STRING_SIZE) { | devinfo->ClassCode.Length >= ACPI_PCICLS_STRING_SIZE) { | ||||
ad->ad_cls_class = strtoul(devinfo->ClassCode.String, | ad->ad_cls_class = strtoul(devinfo->ClassCode.String, | ||||
NULL, 16); | NULL, 16); | ||||
} | } | ||||
#ifdef __aarch64__ | |||||
if ((devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) { | |||||
if (ACPI_SUCCESS(acpi_GetInteger(handle, "_SEG", &segment))) { | |||||
acpi_enable_pcie(child, segment); | |||||
} | |||||
} | |||||
#endif | |||||
AcpiOsFree(devinfo); | AcpiOsFree(devinfo); | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return_ACPI_STATUS (AE_OK); | return_ACPI_STATUS (AE_OK); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 2,174 Lines • Show Last 20 Lines |