diff options
Diffstat (limited to 'drivers/acpi/resources/rsirq.c')
-rw-r--r-- | drivers/acpi/resources/rsirq.c | 393 |
1 files changed, 125 insertions, 268 deletions
diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c index 4e854ba70811..79e71257b69a 100644 --- a/drivers/acpi/resources/rsirq.c +++ b/drivers/acpi/resources/rsirq.c | |||
@@ -49,325 +49,182 @@ ACPI_MODULE_NAME("rsirq") | |||
49 | 49 | ||
50 | /******************************************************************************* | 50 | /******************************************************************************* |
51 | * | 51 | * |
52 | * FUNCTION: acpi_rs_get_irq | 52 | * acpi_rs_get_irq |
53 | * | ||
54 | * PARAMETERS: Aml - Pointer to the AML resource descriptor | ||
55 | * aml_resource_length - Length of the resource from the AML header | ||
56 | * Resource - Where the internal resource is returned | ||
57 | * | ||
58 | * RETURN: Status | ||
59 | * | ||
60 | * DESCRIPTION: Convert a raw AML resource descriptor to the corresponding | ||
61 | * internal resource descriptor, simplifying bitflags and handling | ||
62 | * alignment and endian issues if necessary. | ||
63 | * | 53 | * |
64 | ******************************************************************************/ | 54 | ******************************************************************************/ |
65 | acpi_status | 55 | struct acpi_rsconvert_info acpi_rs_get_irq[7] = { |
66 | acpi_rs_get_irq(union aml_resource *aml, | 56 | {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, |
67 | u16 aml_resource_length, struct acpi_resource *resource) | 57 | ACPI_RS_SIZE(struct acpi_resource_irq), |
68 | { | 58 | ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, |
69 | u16 temp16 = 0; | ||
70 | u32 interrupt_count = 0; | ||
71 | u32 i; | ||
72 | u32 resource_length; | ||
73 | |||
74 | ACPI_FUNCTION_TRACE("rs_get_irq"); | ||
75 | 59 | ||
76 | /* Get the IRQ mask (bytes 1:2) */ | 60 | /* Get the IRQ mask (bytes 1:2) */ |
77 | 61 | ||
78 | ACPI_MOVE_16_TO_16(&temp16, &aml->irq.irq_mask); | 62 | {ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]), |
79 | 63 | AML_OFFSET(irq.irq_mask), | |
80 | /* Decode the IRQ bits (up to 16 possible) */ | 64 | ACPI_RS_OFFSET(data.irq.interrupt_count)}, |
81 | 65 | ||
82 | for (i = 0; i < 16; i++) { | 66 | /* Set default flags (others are zero) */ |
83 | if ((temp16 >> i) & 0x01) { | 67 | |
84 | resource->data.irq.interrupts[interrupt_count] = i; | 68 | {ACPI_RSC_SET8, ACPI_RS_OFFSET(data.irq.triggering), |
85 | interrupt_count++; | 69 | ACPI_EDGE_SENSITIVE, |
86 | } | 70 | 1}, |
87 | } | 71 | |
88 | 72 | /* All done if no flag byte present in descriptor */ | |
89 | /* Zero interrupts is valid */ | 73 | |
90 | 74 | {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, | |
91 | resource_length = 0; | 75 | |
92 | resource->data.irq.interrupt_count = interrupt_count; | 76 | /* Get flags: Triggering[0], Polarity[3], Sharing[4] */ |
93 | if (interrupt_count > 0) { | 77 | |
94 | /* Calculate the structure size based upon the number of interrupts */ | 78 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), |
95 | 79 | AML_OFFSET(irq.flags), | |
96 | resource_length = (u32) (interrupt_count - 1) * 4; | 80 | 0}, |
97 | } | 81 | |
98 | 82 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity), | |
99 | /* Get Flags (Byte 3) if it is used */ | 83 | AML_OFFSET(irq.flags), |
100 | 84 | 3}, | |
101 | if (aml_resource_length == 3) { | 85 | |
102 | /* Check for HE, LL interrupts */ | 86 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), |
103 | 87 | AML_OFFSET(irq.flags), | |
104 | switch (aml->irq.flags & 0x09) { | 88 | 4} |
105 | case 0x01: /* HE */ | 89 | }; |
106 | resource->data.irq.triggering = ACPI_EDGE_SENSITIVE; | ||
107 | resource->data.irq.polarity = ACPI_ACTIVE_HIGH; | ||
108 | break; | ||
109 | |||
110 | case 0x08: /* LL */ | ||
111 | resource->data.irq.triggering = ACPI_LEVEL_SENSITIVE; | ||
112 | resource->data.irq.polarity = ACPI_ACTIVE_LOW; | ||
113 | break; | ||
114 | |||
115 | default: | ||
116 | /* | ||
117 | * Only _LL and _HE polarity/trigger interrupts | ||
118 | * are allowed (ACPI spec, section "IRQ Format") | ||
119 | * so 0x00 and 0x09 are illegal. | ||
120 | */ | ||
121 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
122 | "Invalid interrupt polarity/trigger in resource list, %X\n", | ||
123 | aml->irq.flags)); | ||
124 | return_ACPI_STATUS(AE_BAD_DATA); | ||
125 | } | ||
126 | |||
127 | /* Get Sharing flag */ | ||
128 | |||
129 | resource->data.irq.sharable = (aml->irq.flags >> 3) & 0x01; | ||
130 | } else { | ||
131 | /* | ||
132 | * Default configuration: assume Edge Sensitive, Active High, | ||
133 | * Non-Sharable as per the ACPI Specification | ||
134 | */ | ||
135 | resource->data.irq.triggering = ACPI_EDGE_SENSITIVE; | ||
136 | resource->data.irq.polarity = ACPI_ACTIVE_HIGH; | ||
137 | resource->data.irq.sharable = ACPI_EXCLUSIVE; | ||
138 | } | ||
139 | |||
140 | /* Complete the resource header */ | ||
141 | |||
142 | resource->type = ACPI_RESOURCE_TYPE_IRQ; | ||
143 | resource->length = | ||
144 | resource_length + ACPI_SIZEOF_RESOURCE(struct acpi_resource_irq); | ||
145 | return_ACPI_STATUS(AE_OK); | ||
146 | } | ||
147 | 90 | ||
148 | /******************************************************************************* | 91 | /******************************************************************************* |
149 | * | 92 | * |
150 | * FUNCTION: acpi_rs_set_irq | 93 | * acpi_rs_set_irq |
151 | * | ||
152 | * PARAMETERS: Resource - Pointer to the resource descriptor | ||
153 | * Aml - Where the AML descriptor is returned | ||
154 | * | ||
155 | * RETURN: Status | ||
156 | * | ||
157 | * DESCRIPTION: Convert an internal resource descriptor to the corresponding | ||
158 | * external AML resource descriptor. | ||
159 | * | 94 | * |
160 | ******************************************************************************/ | 95 | ******************************************************************************/ |
161 | 96 | ||
162 | acpi_status | 97 | struct acpi_rsconvert_info acpi_rs_set_irq[9] = { |
163 | acpi_rs_set_irq(struct acpi_resource *resource, union aml_resource *aml) | 98 | {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, |
164 | { | 99 | sizeof(struct aml_resource_irq), |
165 | acpi_size descriptor_length; | 100 | ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)}, |
166 | u16 irq_mask; | ||
167 | u8 i; | ||
168 | |||
169 | ACPI_FUNCTION_TRACE("rs_set_irq"); | ||
170 | 101 | ||
171 | /* Convert interrupt list to 16-bit IRQ bitmask */ | 102 | /* Convert interrupt list to 16-bit IRQ bitmask */ |
172 | 103 | ||
173 | irq_mask = 0; | 104 | {ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]), |
174 | for (i = 0; i < resource->data.irq.interrupt_count; i++) { | 105 | AML_OFFSET(irq.irq_mask), |
175 | irq_mask |= (1 << resource->data.irq.interrupts[i]); | 106 | ACPI_RS_OFFSET(data.irq.interrupt_count)}, |
176 | } | 107 | |
108 | /* Set the flags byte by default */ | ||
177 | 109 | ||
178 | /* Set the interrupt mask */ | 110 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), |
111 | AML_OFFSET(irq.flags), | ||
112 | 0}, | ||
179 | 113 | ||
180 | ACPI_MOVE_16_TO_16(&aml->irq.irq_mask, &irq_mask); | 114 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity), |
115 | AML_OFFSET(irq.flags), | ||
116 | 3}, | ||
181 | 117 | ||
118 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), | ||
119 | AML_OFFSET(irq.flags), | ||
120 | 4}, | ||
182 | /* | 121 | /* |
183 | * The descriptor field is set based upon whether a third byte is | 122 | * Check if the flags byte is necessary. Not needed if the flags are: |
184 | * needed to contain the IRQ Information. | 123 | * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE |
185 | */ | 124 | */ |
186 | if ((resource->data.irq.triggering == ACPI_EDGE_SENSITIVE) && | 125 | {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, |
187 | (resource->data.irq.polarity == ACPI_ACTIVE_HIGH) && | 126 | ACPI_RS_OFFSET(data.irq.triggering), |
188 | (resource->data.irq.sharable == ACPI_EXCLUSIVE)) { | 127 | ACPI_EDGE_SENSITIVE}, |
189 | /* irq_no_flags() descriptor can be used */ | ||
190 | |||
191 | descriptor_length = sizeof(struct aml_resource_irq_noflags); | ||
192 | } else { | ||
193 | /* Irq() descriptor must be used */ | ||
194 | |||
195 | descriptor_length = sizeof(struct aml_resource_irq); | ||
196 | |||
197 | /* Set the IRQ Info byte */ | ||
198 | 128 | ||
199 | aml->irq.flags = (u8) | 129 | {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, |
200 | ((resource->data.irq.sharable & 0x01) << 4); | 130 | ACPI_RS_OFFSET(data.irq.polarity), |
131 | ACPI_ACTIVE_HIGH}, | ||
201 | 132 | ||
202 | if (ACPI_LEVEL_SENSITIVE == resource->data.irq.triggering && | 133 | {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, |
203 | ACPI_ACTIVE_LOW == resource->data.irq.polarity) { | 134 | ACPI_RS_OFFSET(data.irq.sharable), |
204 | aml->irq.flags |= 0x08; | 135 | ACPI_EXCLUSIVE}, |
205 | } else { | ||
206 | aml->irq.flags |= 0x01; | ||
207 | } | ||
208 | } | ||
209 | 136 | ||
210 | /* Complete the AML descriptor header */ | 137 | /* irq_no_flags() descriptor can be used */ |
211 | 138 | ||
212 | acpi_rs_set_resource_header(ACPI_RESOURCE_NAME_IRQ, descriptor_length, | 139 | {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)} |
213 | aml); | 140 | }; |
214 | return_ACPI_STATUS(AE_OK); | ||
215 | } | ||
216 | 141 | ||
217 | /******************************************************************************* | 142 | /******************************************************************************* |
218 | * | 143 | * |
219 | * FUNCTION: acpi_rs_get_ext_irq | 144 | * acpi_rs_convert_ext_irq |
220 | * | ||
221 | * PARAMETERS: Aml - Pointer to the AML resource descriptor | ||
222 | * aml_resource_length - Length of the resource from the AML header | ||
223 | * Resource - Where the internal resource is returned | ||
224 | * | ||
225 | * RETURN: Status | ||
226 | * | ||
227 | * DESCRIPTION: Convert a raw AML resource descriptor to the corresponding | ||
228 | * internal resource descriptor, simplifying bitflags and handling | ||
229 | * alignment and endian issues if necessary. | ||
230 | * | 145 | * |
231 | ******************************************************************************/ | 146 | ******************************************************************************/ |
232 | 147 | ||
233 | acpi_status | 148 | struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { |
234 | acpi_rs_get_ext_irq(union aml_resource *aml, | 149 | {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ, |
235 | u16 aml_resource_length, struct acpi_resource *resource) | 150 | ACPI_RS_SIZE(struct acpi_resource_extended_irq), |
236 | { | 151 | ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_irq)}, |
237 | char *out_resource_string; | ||
238 | u8 temp8; | ||
239 | |||
240 | ACPI_FUNCTION_TRACE("rs_get_ext_irq"); | ||
241 | |||
242 | /* Get the flag bits */ | ||
243 | 152 | ||
244 | temp8 = aml->extended_irq.flags; | 153 | {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_IRQ, |
245 | resource->data.extended_irq.producer_consumer = temp8 & 0x01; | 154 | sizeof(struct aml_resource_extended_irq), |
246 | resource->data.extended_irq.polarity = (temp8 >> 2) & 0x01; | 155 | 0}, |
247 | resource->data.extended_irq.sharable = (temp8 >> 3) & 0x01; | ||
248 | 156 | ||
249 | /* | 157 | /* Flag bits */ |
250 | * Check for Interrupt Mode | ||
251 | * | ||
252 | * The definition of an Extended IRQ changed between ACPI spec v1.0b | ||
253 | * and ACPI spec 2.0 (section 6.4.3.6 in both). | ||
254 | * | ||
255 | * - Edge/Level are defined opposite in the table vs the headers | ||
256 | */ | ||
257 | resource->data.extended_irq.triggering = | ||
258 | (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; | ||
259 | 158 | ||
260 | /* Get the IRQ Table length (Byte4) */ | 159 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.producer_consumer), |
160 | AML_OFFSET(extended_irq.flags), | ||
161 | 0}, | ||
261 | 162 | ||
262 | temp8 = aml->extended_irq.table_length; | 163 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.triggering), |
263 | resource->data.extended_irq.interrupt_count = temp8; | 164 | AML_OFFSET(extended_irq.flags), |
264 | if (temp8 < 1) { | 165 | 1}, |
265 | /* Must have at least one IRQ */ | ||
266 | 166 | ||
267 | return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); | 167 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.polarity), |
268 | } | 168 | AML_OFFSET(extended_irq.flags), |
169 | 2}, | ||
269 | 170 | ||
270 | /* | 171 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.sharable), |
271 | * Add any additional structure size to properly calculate | 172 | AML_OFFSET(extended_irq.flags), |
272 | * the next pointer at the end of this function | 173 | 3}, |
273 | */ | ||
274 | resource->length = (temp8 - 1) * 4; | ||
275 | out_resource_string = ACPI_CAST_PTR(char, | ||
276 | (&resource->data.extended_irq. | ||
277 | interrupts[0] + temp8)); | ||
278 | 174 | ||
279 | /* Get every IRQ in the table, each is 32 bits */ | 175 | /* IRQ Table length (Byte4) */ |
280 | 176 | ||
281 | acpi_rs_move_data(resource->data.extended_irq.interrupts, | 177 | {ACPI_RSC_COUNT, ACPI_RS_OFFSET(data.extended_irq.interrupt_count), |
282 | aml->extended_irq.interrupt_number, | 178 | AML_OFFSET(extended_irq.interrupt_count), |
283 | (u16) temp8, ACPI_MOVE_TYPE_32_TO_32); | 179 | sizeof(u32)} |
180 | , | ||
284 | 181 | ||
285 | /* Get the optional resource_source (index and string) */ | 182 | /* Copy every IRQ in the table, each is 32 bits */ |
286 | 183 | ||
287 | resource->length += | 184 | {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), |
288 | acpi_rs_get_resource_source(aml_resource_length, | 185 | AML_OFFSET(extended_irq.interrupts[0]), |
289 | (acpi_size) resource->length + | 186 | 0} |
290 | sizeof(struct | 187 | , |
291 | aml_resource_extended_irq), | ||
292 | &resource->data.extended_irq. | ||
293 | resource_source, aml, | ||
294 | out_resource_string); | ||
295 | 188 | ||
296 | /* Complete the resource header */ | 189 | /* Optional resource_source (Index and String) */ |
297 | 190 | ||
298 | resource->type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ; | 191 | {ACPI_RSC_SOURCEX, ACPI_RS_OFFSET(data.extended_irq.resource_source), |
299 | resource->length += | 192 | ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), |
300 | ACPI_SIZEOF_RESOURCE(struct acpi_resource_extended_irq); | 193 | sizeof(struct aml_resource_extended_irq)} |
301 | return_ACPI_STATUS(AE_OK); | 194 | }; |
302 | } | ||
303 | 195 | ||
304 | /******************************************************************************* | 196 | /******************************************************************************* |
305 | * | 197 | * |
306 | * FUNCTION: acpi_rs_set_ext_irq | 198 | * acpi_rs_convert_dma |
307 | * | ||
308 | * PARAMETERS: Resource - Pointer to the resource descriptor | ||
309 | * Aml - Where the AML descriptor is returned | ||
310 | * | ||
311 | * RETURN: Status | ||
312 | * | ||
313 | * DESCRIPTION: Convert an internal resource descriptor to the corresponding | ||
314 | * external AML resource descriptor. | ||
315 | * | 199 | * |
316 | ******************************************************************************/ | 200 | ******************************************************************************/ |
317 | 201 | ||
318 | acpi_status | 202 | struct acpi_rsconvert_info acpi_rs_convert_dma[6] = { |
319 | acpi_rs_set_ext_irq(struct acpi_resource *resource, union aml_resource *aml) | 203 | {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_DMA, |
320 | { | 204 | ACPI_RS_SIZE(struct acpi_resource_dma), |
321 | acpi_size descriptor_length; | 205 | ACPI_RSC_TABLE_SIZE(acpi_rs_convert_dma)}, |
322 | |||
323 | ACPI_FUNCTION_TRACE("rs_set_ext_irq"); | ||
324 | |||
325 | /* Set the Interrupt vector flags */ | ||
326 | |||
327 | aml->extended_irq.flags = (u8) | ||
328 | ((resource->data.extended_irq.producer_consumer & 0x01) | | ||
329 | ((resource->data.extended_irq.sharable & 0x01) << 3) | | ||
330 | ((resource->data.extended_irq.polarity & 0x1) << 2)); | ||
331 | |||
332 | /* | ||
333 | * Set the Interrupt Mode | ||
334 | * | ||
335 | * The definition of an Extended IRQ changed between ACPI spec v1.0b | ||
336 | * and ACPI spec 2.0 (section 6.4.3.6 in both). This code does not | ||
337 | * implement the more restrictive definition of 1.0b | ||
338 | * | ||
339 | * - Edge/Level are defined opposite in the table vs the headers | ||
340 | */ | ||
341 | if (resource->data.extended_irq.triggering == ACPI_EDGE_SENSITIVE) { | ||
342 | aml->extended_irq.flags |= 0x02; | ||
343 | } | ||
344 | |||
345 | /* Set the Interrupt table length */ | ||
346 | |||
347 | aml->extended_irq.table_length = (u8) | ||
348 | resource->data.extended_irq.interrupt_count; | ||
349 | 206 | ||
350 | descriptor_length = (sizeof(struct aml_resource_extended_irq) - 4) + | 207 | {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_DMA, |
351 | ((acpi_size) resource->data.extended_irq.interrupt_count * | 208 | sizeof(struct aml_resource_dma), |
352 | sizeof(u32)); | 209 | 0}, |
353 | 210 | ||
354 | /* Set each interrupt value */ | 211 | /* Flags: transfer preference, bus mastering, channel speed */ |
355 | 212 | ||
356 | acpi_rs_move_data(aml->extended_irq.interrupt_number, | 213 | {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.transfer), |
357 | resource->data.extended_irq.interrupts, | 214 | AML_OFFSET(dma.flags), |
358 | (u16) resource->data.extended_irq.interrupt_count, | 215 | 0}, |
359 | ACPI_MOVE_TYPE_32_TO_32); | ||
360 | 216 | ||
361 | /* Resource Source Index and Resource Source are optional */ | 217 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.dma.bus_master), |
218 | AML_OFFSET(dma.flags), | ||
219 | 2}, | ||
362 | 220 | ||
363 | descriptor_length = acpi_rs_set_resource_source(aml, descriptor_length, | 221 | {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.type), |
364 | &resource->data. | 222 | AML_OFFSET(dma.flags), |
365 | extended_irq. | 223 | 5}, |
366 | resource_source); | ||
367 | 224 | ||
368 | /* Complete the AML descriptor header */ | 225 | /* DMA channel mask bits */ |
369 | 226 | ||
370 | acpi_rs_set_resource_header(ACPI_RESOURCE_NAME_EXTENDED_IRQ, | 227 | {ACPI_RSC_BITMASK, ACPI_RS_OFFSET(data.dma.channels[0]), |
371 | descriptor_length, aml); | 228 | AML_OFFSET(dma.dma_channel_mask), |
372 | return_ACPI_STATUS(AE_OK); | 229 | ACPI_RS_OFFSET(data.dma.channel_count)} |
373 | } | 230 | }; |