// Copyright 2016 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "resources.h" zx_status_t resource_parse_memory(ACPI_RESOURCE* res, resource_memory_t* out) { switch (res->Type) { case ACPI_RESOURCE_TYPE_MEMORY24: { ACPI_RESOURCE_MEMORY24* m24 = &res->Data.Memory24; out->writeable = !m24->WriteProtect; out->minimum = (uint32_t)m24->Minimum << 8; out->maximum = (uint32_t)m24->Maximum << 8; out->alignment = m24->Alignment ? m24->Alignment : 1U<<16; out->address_length = (uint32_t)m24->AddressLength << 8; break; } case ACPI_RESOURCE_TYPE_MEMORY32: { ACPI_RESOURCE_MEMORY32* m32 = &res->Data.Memory32; out->writeable = !m32->WriteProtect; out->minimum = m32->Minimum; out->maximum = m32->Maximum; out->alignment = m32->Alignment; out->address_length = m32->AddressLength; break; } case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: { ACPI_RESOURCE_FIXED_MEMORY32* m32 = &res->Data.FixedMemory32; out->writeable = !m32->WriteProtect; out->minimum = m32->Address; out->maximum = m32->Address; out->alignment = 1; out->address_length = m32->AddressLength; break; } default: return ZX_ERR_INVALID_ARGS; } return ZX_OK; } #define EXTRACT_ADDRESS_FIELDS(src, out) do { \ (out)->minimum = (src)->Address.Minimum; \ (out)->maximum = (src)->Address.Maximum; \ (out)->address_length = (src)->Address.AddressLength; \ (out)->translation_offset = (src)->Address.TranslationOffset; \ (out)->granularity = (src)->Address.Granularity; \ (out)->consumed_only = ((src)->ProducerConsumer == ACPI_CONSUMER); \ (out)->subtractive_decode = ((src)->Decode == ACPI_SUB_DECODE); \ (out)->min_address_fixed = (src)->MinAddressFixed; \ (out)->max_address_fixed = (src)->MaxAddressFixed; \ } while (0) zx_status_t resource_parse_address(ACPI_RESOURCE* res, resource_address_t* out) { uint8_t resource_type; switch (res->Type) { case ACPI_RESOURCE_TYPE_ADDRESS16: { ACPI_RESOURCE_ADDRESS16* a16 = &res->Data.Address16; EXTRACT_ADDRESS_FIELDS(a16, out); resource_type = a16->ResourceType; break; } case ACPI_RESOURCE_TYPE_ADDRESS32: { ACPI_RESOURCE_ADDRESS32* a32 = &res->Data.Address32; EXTRACT_ADDRESS_FIELDS(a32, out); resource_type = a32->ResourceType; break; } case ACPI_RESOURCE_TYPE_ADDRESS64: { ACPI_RESOURCE_ADDRESS64* a64 = &res->Data.Address64; EXTRACT_ADDRESS_FIELDS(a64, out); resource_type = a64->ResourceType; break; } case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: { ACPI_RESOURCE_EXTENDED_ADDRESS64* a64 = &res->Data.ExtAddress64; EXTRACT_ADDRESS_FIELDS(a64, out); resource_type = a64->ResourceType; break; } default: return ZX_ERR_INVALID_ARGS; } switch (resource_type) { case ACPI_MEMORY_RANGE: out->resource_type = RESOURCE_ADDRESS_MEMORY; break; case ACPI_IO_RANGE: out->resource_type = RESOURCE_ADDRESS_IO; break; case ACPI_BUS_NUMBER_RANGE: out->resource_type = RESOURCE_ADDRESS_BUS_NUMBER; break; default: out->resource_type = RESOURCE_ADDRESS_UNKNOWN; } return ZX_OK; } zx_status_t resource_parse_io(ACPI_RESOURCE* res, resource_io_t* out) { switch (res->Type) { case ACPI_RESOURCE_TYPE_IO: { ACPI_RESOURCE_IO* io = &res->Data.Io; out->decodes_full_space = (io->IoDecode == ACPI_DECODE_16); out->alignment = io->Alignment; out->address_length = io->AddressLength; out->minimum = io->Minimum; out->maximum = io->Maximum; break; } case ACPI_RESOURCE_TYPE_FIXED_IO: { ACPI_RESOURCE_FIXED_IO* io = &res->Data.FixedIo; out->decodes_full_space = false; out->alignment = 1; out->address_length = io->AddressLength; out->minimum = io->Address; out->maximum = io->Address; break; } default: return ZX_ERR_INVALID_ARGS; } return ZX_OK; } zx_status_t resource_parse_irq(ACPI_RESOURCE* res, resource_irq_t* out) { switch (res->Type) { case ACPI_RESOURCE_TYPE_IRQ: { ACPI_RESOURCE_IRQ* irq = &res->Data.Irq; out->trigger = irq->Triggering; out->polarity = irq->Polarity; out->sharable = irq->Sharable; out->wake_capable = irq->WakeCapable; out->pin_count = irq->InterruptCount; if (irq->InterruptCount > countof(out->pins)) { return ZX_ERR_OUT_OF_RANGE; } for (uint8_t i = 0; (i < irq->InterruptCount) && (i < countof(out->pins)); i++) { out->pins[i] = irq->Interrupts[i]; } break; } case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: { ACPI_RESOURCE_EXTENDED_IRQ* irq = &res->Data.ExtendedIrq; out->trigger = irq->Triggering; out->polarity = irq->Polarity; out->sharable = irq->Sharable; out->wake_capable = irq->WakeCapable; out->pin_count = irq->InterruptCount; if (irq->InterruptCount > countof(out->pins)) { return ZX_ERR_OUT_OF_RANGE; } for (uint8_t i = 0; (i < irq->InterruptCount) && (i < countof(out->pins)); i++) { out->pins[i] = irq->Interrupts[i]; } break; } default: return ZX_ERR_INVALID_ARGS; } return ZX_OK; }