aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/resources/rsirq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/resources/rsirq.c')
-rw-r--r--drivers/acpi/resources/rsirq.c393
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 ******************************************************************************/
65acpi_status 55struct acpi_rsconvert_info acpi_rs_get_irq[7] = {
66acpi_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
162acpi_status 97struct acpi_rsconvert_info acpi_rs_set_irq[9] = {
163acpi_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
233acpi_status 148struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = {
234acpi_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
318acpi_status 202struct acpi_rsconvert_info acpi_rs_convert_dma[6] = {
319acpi_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};