1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "resources.h"
6
resource_parse_memory(ACPI_RESOURCE * res,resource_memory_t * out)7 zx_status_t resource_parse_memory(ACPI_RESOURCE* res, resource_memory_t* out) {
8 switch (res->Type) {
9 case ACPI_RESOURCE_TYPE_MEMORY24: {
10 ACPI_RESOURCE_MEMORY24* m24 = &res->Data.Memory24;
11 out->writeable = !m24->WriteProtect;
12 out->minimum = (uint32_t)m24->Minimum << 8;
13 out->maximum = (uint32_t)m24->Maximum << 8;
14 out->alignment = m24->Alignment ? m24->Alignment : 1U<<16;
15 out->address_length = (uint32_t)m24->AddressLength << 8;
16 break;
17 }
18 case ACPI_RESOURCE_TYPE_MEMORY32: {
19 ACPI_RESOURCE_MEMORY32* m32 = &res->Data.Memory32;
20 out->writeable = !m32->WriteProtect;
21 out->minimum = m32->Minimum;
22 out->maximum = m32->Maximum;
23 out->alignment = m32->Alignment;
24 out->address_length = m32->AddressLength;
25 break;
26 }
27 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: {
28 ACPI_RESOURCE_FIXED_MEMORY32* m32 = &res->Data.FixedMemory32;
29 out->writeable = !m32->WriteProtect;
30 out->minimum = m32->Address;
31 out->maximum = m32->Address;
32 out->alignment = 1;
33 out->address_length = m32->AddressLength;
34 break;
35 }
36 default: return ZX_ERR_INVALID_ARGS;
37 }
38
39 return ZX_OK;
40 }
41
42 #define EXTRACT_ADDRESS_FIELDS(src, out) do { \
43 (out)->minimum = (src)->Address.Minimum; \
44 (out)->maximum = (src)->Address.Maximum; \
45 (out)->address_length = (src)->Address.AddressLength; \
46 (out)->translation_offset = (src)->Address.TranslationOffset; \
47 (out)->granularity = (src)->Address.Granularity; \
48 (out)->consumed_only = ((src)->ProducerConsumer == ACPI_CONSUMER); \
49 (out)->subtractive_decode = ((src)->Decode == ACPI_SUB_DECODE); \
50 (out)->min_address_fixed = (src)->MinAddressFixed; \
51 (out)->max_address_fixed = (src)->MaxAddressFixed; \
52 } while (0)
53
resource_parse_address(ACPI_RESOURCE * res,resource_address_t * out)54 zx_status_t resource_parse_address(ACPI_RESOURCE* res, resource_address_t* out) {
55 uint8_t resource_type;
56 switch (res->Type) {
57 case ACPI_RESOURCE_TYPE_ADDRESS16: {
58 ACPI_RESOURCE_ADDRESS16* a16 = &res->Data.Address16;
59 EXTRACT_ADDRESS_FIELDS(a16, out);
60 resource_type = a16->ResourceType;
61 break;
62 }
63 case ACPI_RESOURCE_TYPE_ADDRESS32: {
64 ACPI_RESOURCE_ADDRESS32* a32 = &res->Data.Address32;
65 EXTRACT_ADDRESS_FIELDS(a32, out);
66 resource_type = a32->ResourceType;
67 break;
68 }
69 case ACPI_RESOURCE_TYPE_ADDRESS64: {
70 ACPI_RESOURCE_ADDRESS64* a64 = &res->Data.Address64;
71 EXTRACT_ADDRESS_FIELDS(a64, out);
72 resource_type = a64->ResourceType;
73 break;
74 }
75 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: {
76 ACPI_RESOURCE_EXTENDED_ADDRESS64* a64 = &res->Data.ExtAddress64;
77 EXTRACT_ADDRESS_FIELDS(a64, out);
78 resource_type = a64->ResourceType;
79 break;
80 }
81 default: return ZX_ERR_INVALID_ARGS;
82 }
83
84 switch (resource_type) {
85 case ACPI_MEMORY_RANGE: out->resource_type = RESOURCE_ADDRESS_MEMORY; break;
86 case ACPI_IO_RANGE: out->resource_type = RESOURCE_ADDRESS_IO; break;
87 case ACPI_BUS_NUMBER_RANGE: out->resource_type = RESOURCE_ADDRESS_BUS_NUMBER; break;
88 default: out->resource_type = RESOURCE_ADDRESS_UNKNOWN;
89 }
90
91 return ZX_OK;
92 }
93
resource_parse_io(ACPI_RESOURCE * res,resource_io_t * out)94 zx_status_t resource_parse_io(ACPI_RESOURCE* res, resource_io_t* out) {
95 switch (res->Type) {
96 case ACPI_RESOURCE_TYPE_IO: {
97 ACPI_RESOURCE_IO* io = &res->Data.Io;
98 out->decodes_full_space = (io->IoDecode == ACPI_DECODE_16);
99 out->alignment = io->Alignment;
100 out->address_length = io->AddressLength;
101 out->minimum = io->Minimum;
102 out->maximum = io->Maximum;
103 break;
104 }
105 case ACPI_RESOURCE_TYPE_FIXED_IO: {
106 ACPI_RESOURCE_FIXED_IO* io = &res->Data.FixedIo;
107 out->decodes_full_space = false;
108 out->alignment = 1;
109 out->address_length = io->AddressLength;
110 out->minimum = io->Address;
111 out->maximum = io->Address;
112 break;
113 }
114 default: return ZX_ERR_INVALID_ARGS;
115 }
116
117 return ZX_OK;
118 }
119
resource_parse_irq(ACPI_RESOURCE * res,resource_irq_t * out)120 zx_status_t resource_parse_irq(ACPI_RESOURCE* res, resource_irq_t* out) {
121 switch (res->Type) {
122 case ACPI_RESOURCE_TYPE_IRQ: {
123 ACPI_RESOURCE_IRQ* irq = &res->Data.Irq;
124 out->trigger = irq->Triggering;
125 out->polarity = irq->Polarity;
126 out->sharable = irq->Sharable;
127 out->wake_capable = irq->WakeCapable;
128 out->pin_count = irq->InterruptCount;
129 if (irq->InterruptCount > countof(out->pins)) {
130 return ZX_ERR_OUT_OF_RANGE;
131 }
132 for (uint8_t i = 0;
133 (i < irq->InterruptCount) && (i < countof(out->pins)); i++) {
134 out->pins[i] = irq->Interrupts[i];
135 }
136 break;
137 }
138 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: {
139 ACPI_RESOURCE_EXTENDED_IRQ* irq = &res->Data.ExtendedIrq;
140 out->trigger = irq->Triggering;
141 out->polarity = irq->Polarity;
142 out->sharable = irq->Sharable;
143 out->wake_capable = irq->WakeCapable;
144 out->pin_count = irq->InterruptCount;
145 if (irq->InterruptCount > countof(out->pins)) {
146 return ZX_ERR_OUT_OF_RANGE;
147 }
148 for (uint8_t i = 0;
149 (i < irq->InterruptCount) && (i < countof(out->pins)); i++) {
150 out->pins[i] = irq->Interrupts[i];
151 }
152 break;
153 }
154 default: return ZX_ERR_INVALID_ARGS;
155 }
156
157 return ZX_OK;
158 }
159