xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/rscalc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /*******************************************************************************
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Module Name: rscalc - Calculate stream and list lengths
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  ******************************************************************************/
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <acpi/acpi.h>
9*4882a593Smuzhiyun #include "accommon.h"
10*4882a593Smuzhiyun #include "acresrc.h"
11*4882a593Smuzhiyun #include "acnamesp.h"
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #define _COMPONENT          ACPI_RESOURCES
14*4882a593Smuzhiyun ACPI_MODULE_NAME("rscalc")
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun /* Local prototypes */
17*4882a593Smuzhiyun static u8 acpi_rs_count_set_bits(u16 bit_field);
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun static acpi_rs_length
20*4882a593Smuzhiyun acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun static u32
23*4882a593Smuzhiyun acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun /*******************************************************************************
26*4882a593Smuzhiyun  *
27*4882a593Smuzhiyun  * FUNCTION:    acpi_rs_count_set_bits
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * PARAMETERS:  bit_field       - Field in which to count bits
30*4882a593Smuzhiyun  *
31*4882a593Smuzhiyun  * RETURN:      Number of bits set within the field
32*4882a593Smuzhiyun  *
33*4882a593Smuzhiyun  * DESCRIPTION: Count the number of bits set in a resource field. Used for
34*4882a593Smuzhiyun  *              (Short descriptor) interrupt and DMA lists.
35*4882a593Smuzhiyun  *
36*4882a593Smuzhiyun  ******************************************************************************/
37*4882a593Smuzhiyun 
acpi_rs_count_set_bits(u16 bit_field)38*4882a593Smuzhiyun static u8 acpi_rs_count_set_bits(u16 bit_field)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun 	u8 bits_set;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	ACPI_FUNCTION_ENTRY();
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	for (bits_set = 0; bit_field; bits_set++) {
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 		/* Zero the least significant bit that is set */
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 		bit_field &= (u16) (bit_field - 1);
49*4882a593Smuzhiyun 	}
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	return (bits_set);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /*******************************************************************************
55*4882a593Smuzhiyun  *
56*4882a593Smuzhiyun  * FUNCTION:    acpi_rs_struct_option_length
57*4882a593Smuzhiyun  *
58*4882a593Smuzhiyun  * PARAMETERS:  resource_source     - Pointer to optional descriptor field
59*4882a593Smuzhiyun  *
60*4882a593Smuzhiyun  * RETURN:      Status
61*4882a593Smuzhiyun  *
62*4882a593Smuzhiyun  * DESCRIPTION: Common code to handle optional resource_source_index and
63*4882a593Smuzhiyun  *              resource_source fields in some Large descriptors. Used during
64*4882a593Smuzhiyun  *              list-to-stream conversion
65*4882a593Smuzhiyun  *
66*4882a593Smuzhiyun  ******************************************************************************/
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun static acpi_rs_length
acpi_rs_struct_option_length(struct acpi_resource_source * resource_source)69*4882a593Smuzhiyun acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	ACPI_FUNCTION_ENTRY();
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	/*
74*4882a593Smuzhiyun 	 * If the resource_source string is valid, return the size of the string
75*4882a593Smuzhiyun 	 * (string_length includes the NULL terminator) plus the size of the
76*4882a593Smuzhiyun 	 * resource_source_index (1).
77*4882a593Smuzhiyun 	 */
78*4882a593Smuzhiyun 	if (resource_source->string_ptr) {
79*4882a593Smuzhiyun 		return ((acpi_rs_length)(resource_source->string_length + 1));
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	return (0);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun /*******************************************************************************
86*4882a593Smuzhiyun  *
87*4882a593Smuzhiyun  * FUNCTION:    acpi_rs_stream_option_length
88*4882a593Smuzhiyun  *
89*4882a593Smuzhiyun  * PARAMETERS:  resource_length     - Length from the resource header
90*4882a593Smuzhiyun  *              minimum_total_length - Minimum length of this resource, before
91*4882a593Smuzhiyun  *                                    any optional fields. Includes header size
92*4882a593Smuzhiyun  *
93*4882a593Smuzhiyun  * RETURN:      Length of optional string (0 if no string present)
94*4882a593Smuzhiyun  *
95*4882a593Smuzhiyun  * DESCRIPTION: Common code to handle optional resource_source_index and
96*4882a593Smuzhiyun  *              resource_source fields in some Large descriptors. Used during
97*4882a593Smuzhiyun  *              stream-to-list conversion
98*4882a593Smuzhiyun  *
99*4882a593Smuzhiyun  ******************************************************************************/
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun static u32
acpi_rs_stream_option_length(u32 resource_length,u32 minimum_aml_resource_length)102*4882a593Smuzhiyun acpi_rs_stream_option_length(u32 resource_length,
103*4882a593Smuzhiyun 			     u32 minimum_aml_resource_length)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	u32 string_length = 0;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	ACPI_FUNCTION_ENTRY();
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	/*
110*4882a593Smuzhiyun 	 * The resource_source_index and resource_source are optional elements of
111*4882a593Smuzhiyun 	 * some Large-type resource descriptors.
112*4882a593Smuzhiyun 	 */
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	/*
115*4882a593Smuzhiyun 	 * If the length of the actual resource descriptor is greater than the
116*4882a593Smuzhiyun 	 * ACPI spec-defined minimum length, it means that a resource_source_index
117*4882a593Smuzhiyun 	 * exists and is followed by a (required) null terminated string. The
118*4882a593Smuzhiyun 	 * string length (including the null terminator) is the resource length
119*4882a593Smuzhiyun 	 * minus the minimum length, minus one byte for the resource_source_index
120*4882a593Smuzhiyun 	 * itself.
121*4882a593Smuzhiyun 	 */
122*4882a593Smuzhiyun 	if (resource_length > minimum_aml_resource_length) {
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 		/* Compute the length of the optional string */
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 		string_length =
127*4882a593Smuzhiyun 		    resource_length - minimum_aml_resource_length - 1;
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	/*
131*4882a593Smuzhiyun 	 * Round the length up to a multiple of the native word in order to
132*4882a593Smuzhiyun 	 * guarantee that the entire resource descriptor is native word aligned
133*4882a593Smuzhiyun 	 */
134*4882a593Smuzhiyun 	return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length));
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun /*******************************************************************************
138*4882a593Smuzhiyun  *
139*4882a593Smuzhiyun  * FUNCTION:    acpi_rs_get_aml_length
140*4882a593Smuzhiyun  *
141*4882a593Smuzhiyun  * PARAMETERS:  resource            - Pointer to the resource linked list
142*4882a593Smuzhiyun  *              resource_list_size  - Size of the resource linked list
143*4882a593Smuzhiyun  *              size_needed         - Where the required size is returned
144*4882a593Smuzhiyun  *
145*4882a593Smuzhiyun  * RETURN:      Status
146*4882a593Smuzhiyun  *
147*4882a593Smuzhiyun  * DESCRIPTION: Takes a linked list of internal resource descriptors and
148*4882a593Smuzhiyun  *              calculates the size buffer needed to hold the corresponding
149*4882a593Smuzhiyun  *              external resource byte stream.
150*4882a593Smuzhiyun  *
151*4882a593Smuzhiyun  ******************************************************************************/
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun acpi_status
acpi_rs_get_aml_length(struct acpi_resource * resource,acpi_size resource_list_size,acpi_size * size_needed)154*4882a593Smuzhiyun acpi_rs_get_aml_length(struct acpi_resource *resource,
155*4882a593Smuzhiyun 		       acpi_size resource_list_size, acpi_size *size_needed)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	acpi_size aml_size_needed = 0;
158*4882a593Smuzhiyun 	struct acpi_resource *resource_end;
159*4882a593Smuzhiyun 	acpi_rs_length total_size;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(rs_get_aml_length);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	/* Traverse entire list of internal resource descriptors */
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	resource_end =
166*4882a593Smuzhiyun 	    ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size);
167*4882a593Smuzhiyun 	while (resource < resource_end) {
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 		/* Validate the descriptor type */
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
172*4882a593Smuzhiyun 			return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
173*4882a593Smuzhiyun 		}
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 		/* Sanity check the length. It must not be zero, or we loop forever */
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 		if (!resource->length) {
178*4882a593Smuzhiyun 			return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
179*4882a593Smuzhiyun 		}
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 		/* Get the base size of the (external stream) resource descriptor */
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 		total_size = acpi_gbl_aml_resource_sizes[resource->type];
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 		/*
186*4882a593Smuzhiyun 		 * Augment the base size for descriptors with optional and/or
187*4882a593Smuzhiyun 		 * variable-length fields
188*4882a593Smuzhiyun 		 */
189*4882a593Smuzhiyun 		switch (resource->type) {
190*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_IRQ:
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 			/* Length can be 3 or 2 */
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 			if (resource->data.irq.descriptor_length == 2) {
195*4882a593Smuzhiyun 				total_size--;
196*4882a593Smuzhiyun 			}
197*4882a593Smuzhiyun 			break;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 			/* Length can be 1 or 0 */
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 			if (resource->data.irq.descriptor_length == 0) {
204*4882a593Smuzhiyun 				total_size--;
205*4882a593Smuzhiyun 			}
206*4882a593Smuzhiyun 			break;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_VENDOR:
209*4882a593Smuzhiyun 			/*
210*4882a593Smuzhiyun 			 * Vendor Defined Resource:
211*4882a593Smuzhiyun 			 * For a Vendor Specific resource, if the Length is between 1 and 7
212*4882a593Smuzhiyun 			 * it will be created as a Small Resource data type, otherwise it
213*4882a593Smuzhiyun 			 * is a Large Resource data type.
214*4882a593Smuzhiyun 			 */
215*4882a593Smuzhiyun 			if (resource->data.vendor.byte_length > 7) {
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 				/* Base size of a Large resource descriptor */
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 				total_size =
220*4882a593Smuzhiyun 				    sizeof(struct aml_resource_large_header);
221*4882a593Smuzhiyun 			}
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 			/* Add the size of the vendor-specific data */
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 			total_size = (acpi_rs_length)
226*4882a593Smuzhiyun 			    (total_size + resource->data.vendor.byte_length);
227*4882a593Smuzhiyun 			break;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_END_TAG:
230*4882a593Smuzhiyun 			/*
231*4882a593Smuzhiyun 			 * End Tag:
232*4882a593Smuzhiyun 			 * We are done -- return the accumulated total size.
233*4882a593Smuzhiyun 			 */
234*4882a593Smuzhiyun 			*size_needed = aml_size_needed + total_size;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 			/* Normal exit */
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 			return_ACPI_STATUS(AE_OK);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_ADDRESS16:
241*4882a593Smuzhiyun 			/*
242*4882a593Smuzhiyun 			 * 16-Bit Address Resource:
243*4882a593Smuzhiyun 			 * Add the size of the optional resource_source info
244*4882a593Smuzhiyun 			 */
245*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
246*4882a593Smuzhiyun 						      acpi_rs_struct_option_length
247*4882a593Smuzhiyun 						      (&resource->data.
248*4882a593Smuzhiyun 						       address16.
249*4882a593Smuzhiyun 						       resource_source));
250*4882a593Smuzhiyun 			break;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_ADDRESS32:
253*4882a593Smuzhiyun 			/*
254*4882a593Smuzhiyun 			 * 32-Bit Address Resource:
255*4882a593Smuzhiyun 			 * Add the size of the optional resource_source info
256*4882a593Smuzhiyun 			 */
257*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
258*4882a593Smuzhiyun 						      acpi_rs_struct_option_length
259*4882a593Smuzhiyun 						      (&resource->data.
260*4882a593Smuzhiyun 						       address32.
261*4882a593Smuzhiyun 						       resource_source));
262*4882a593Smuzhiyun 			break;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_ADDRESS64:
265*4882a593Smuzhiyun 			/*
266*4882a593Smuzhiyun 			 * 64-Bit Address Resource:
267*4882a593Smuzhiyun 			 * Add the size of the optional resource_source info
268*4882a593Smuzhiyun 			 */
269*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
270*4882a593Smuzhiyun 						      acpi_rs_struct_option_length
271*4882a593Smuzhiyun 						      (&resource->data.
272*4882a593Smuzhiyun 						       address64.
273*4882a593Smuzhiyun 						       resource_source));
274*4882a593Smuzhiyun 			break;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
277*4882a593Smuzhiyun 			/*
278*4882a593Smuzhiyun 			 * Extended IRQ Resource:
279*4882a593Smuzhiyun 			 * Add the size of each additional optional interrupt beyond the
280*4882a593Smuzhiyun 			 * required 1 (4 bytes for each u32 interrupt number)
281*4882a593Smuzhiyun 			 */
282*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
283*4882a593Smuzhiyun 						      ((resource->data.
284*4882a593Smuzhiyun 							extended_irq.
285*4882a593Smuzhiyun 							interrupt_count -
286*4882a593Smuzhiyun 							1) * 4) +
287*4882a593Smuzhiyun 						      /* Add the size of the optional resource_source info */
288*4882a593Smuzhiyun 						      acpi_rs_struct_option_length
289*4882a593Smuzhiyun 						      (&resource->data.
290*4882a593Smuzhiyun 						       extended_irq.
291*4882a593Smuzhiyun 						       resource_source));
292*4882a593Smuzhiyun 			break;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_GPIO:
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
297*4882a593Smuzhiyun 						      (resource->data.gpio.
298*4882a593Smuzhiyun 						       pin_table_length * 2) +
299*4882a593Smuzhiyun 						      resource->data.gpio.
300*4882a593Smuzhiyun 						      resource_source.
301*4882a593Smuzhiyun 						      string_length +
302*4882a593Smuzhiyun 						      resource->data.gpio.
303*4882a593Smuzhiyun 						      vendor_length);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 			break;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_PIN_FUNCTION:
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
310*4882a593Smuzhiyun 						      (resource->data.
311*4882a593Smuzhiyun 						       pin_function.
312*4882a593Smuzhiyun 						       pin_table_length * 2) +
313*4882a593Smuzhiyun 						      resource->data.
314*4882a593Smuzhiyun 						      pin_function.
315*4882a593Smuzhiyun 						      resource_source.
316*4882a593Smuzhiyun 						      string_length +
317*4882a593Smuzhiyun 						      resource->data.
318*4882a593Smuzhiyun 						      pin_function.
319*4882a593Smuzhiyun 						      vendor_length);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 			break;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_SERIAL_BUS:
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 			total_size =
326*4882a593Smuzhiyun 			    acpi_gbl_aml_resource_serial_bus_sizes[resource->
327*4882a593Smuzhiyun 								   data.
328*4882a593Smuzhiyun 								   common_serial_bus.
329*4882a593Smuzhiyun 								   type];
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
332*4882a593Smuzhiyun 						      resource->data.
333*4882a593Smuzhiyun 						      i2c_serial_bus.
334*4882a593Smuzhiyun 						      resource_source.
335*4882a593Smuzhiyun 						      string_length +
336*4882a593Smuzhiyun 						      resource->data.
337*4882a593Smuzhiyun 						      i2c_serial_bus.
338*4882a593Smuzhiyun 						      vendor_length);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 			break;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_PIN_CONFIG:
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
345*4882a593Smuzhiyun 						      (resource->data.
346*4882a593Smuzhiyun 						       pin_config.
347*4882a593Smuzhiyun 						       pin_table_length * 2) +
348*4882a593Smuzhiyun 						      resource->data.pin_config.
349*4882a593Smuzhiyun 						      resource_source.
350*4882a593Smuzhiyun 						      string_length +
351*4882a593Smuzhiyun 						      resource->data.pin_config.
352*4882a593Smuzhiyun 						      vendor_length);
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 			break;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_PIN_GROUP:
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
359*4882a593Smuzhiyun 						      (resource->data.pin_group.
360*4882a593Smuzhiyun 						       pin_table_length * 2) +
361*4882a593Smuzhiyun 						      resource->data.pin_group.
362*4882a593Smuzhiyun 						      resource_label.
363*4882a593Smuzhiyun 						      string_length +
364*4882a593Smuzhiyun 						      resource->data.pin_group.
365*4882a593Smuzhiyun 						      vendor_length);
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 			break;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION:
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
372*4882a593Smuzhiyun 						      resource->data.
373*4882a593Smuzhiyun 						      pin_group_function.
374*4882a593Smuzhiyun 						      resource_source.
375*4882a593Smuzhiyun 						      string_length +
376*4882a593Smuzhiyun 						      resource->data.
377*4882a593Smuzhiyun 						      pin_group_function.
378*4882a593Smuzhiyun 						      resource_source_label.
379*4882a593Smuzhiyun 						      string_length +
380*4882a593Smuzhiyun 						      resource->data.
381*4882a593Smuzhiyun 						      pin_group_function.
382*4882a593Smuzhiyun 						      vendor_length);
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 			break;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 		case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG:
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 			total_size = (acpi_rs_length)(total_size +
389*4882a593Smuzhiyun 						      resource->data.
390*4882a593Smuzhiyun 						      pin_group_config.
391*4882a593Smuzhiyun 						      resource_source.
392*4882a593Smuzhiyun 						      string_length +
393*4882a593Smuzhiyun 						      resource->data.
394*4882a593Smuzhiyun 						      pin_group_config.
395*4882a593Smuzhiyun 						      resource_source_label.
396*4882a593Smuzhiyun 						      string_length +
397*4882a593Smuzhiyun 						      resource->data.
398*4882a593Smuzhiyun 						      pin_group_config.
399*4882a593Smuzhiyun 						      vendor_length);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 			break;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 		default:
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 			break;
406*4882a593Smuzhiyun 		}
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 		/* Update the total */
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 		aml_size_needed += total_size;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 		/* Point to the next object */
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 		resource =
415*4882a593Smuzhiyun 		    ACPI_ADD_PTR(struct acpi_resource, resource,
416*4882a593Smuzhiyun 				 resource->length);
417*4882a593Smuzhiyun 	}
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	/* Did not find an end_tag resource descriptor */
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun /*******************************************************************************
425*4882a593Smuzhiyun  *
426*4882a593Smuzhiyun  * FUNCTION:    acpi_rs_get_list_length
427*4882a593Smuzhiyun  *
428*4882a593Smuzhiyun  * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
429*4882a593Smuzhiyun  *              aml_buffer_length   - Size of aml_buffer
430*4882a593Smuzhiyun  *              size_needed         - Where the size needed is returned
431*4882a593Smuzhiyun  *
432*4882a593Smuzhiyun  * RETURN:      Status
433*4882a593Smuzhiyun  *
434*4882a593Smuzhiyun  * DESCRIPTION: Takes an external resource byte stream and calculates the size
435*4882a593Smuzhiyun  *              buffer needed to hold the corresponding internal resource
436*4882a593Smuzhiyun  *              descriptor linked list.
437*4882a593Smuzhiyun  *
438*4882a593Smuzhiyun  ******************************************************************************/
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun acpi_status
acpi_rs_get_list_length(u8 * aml_buffer,u32 aml_buffer_length,acpi_size * size_needed)441*4882a593Smuzhiyun acpi_rs_get_list_length(u8 *aml_buffer,
442*4882a593Smuzhiyun 			u32 aml_buffer_length, acpi_size *size_needed)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun 	acpi_status status;
445*4882a593Smuzhiyun 	u8 *end_aml;
446*4882a593Smuzhiyun 	u8 *buffer;
447*4882a593Smuzhiyun 	u32 buffer_size;
448*4882a593Smuzhiyun 	u16 temp16;
449*4882a593Smuzhiyun 	u16 resource_length;
450*4882a593Smuzhiyun 	u32 extra_struct_bytes;
451*4882a593Smuzhiyun 	u8 resource_index;
452*4882a593Smuzhiyun 	u8 minimum_aml_resource_length;
453*4882a593Smuzhiyun 	union aml_resource *aml_resource;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(rs_get_list_length);
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	*size_needed = ACPI_RS_SIZE_MIN;	/* Minimum size is one end_tag */
458*4882a593Smuzhiyun 	end_aml = aml_buffer + aml_buffer_length;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	/* Walk the list of AML resource descriptors */
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	while (aml_buffer < end_aml) {
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 		/* Validate the Resource Type and Resource Length */
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 		status =
467*4882a593Smuzhiyun 		    acpi_ut_validate_resource(NULL, aml_buffer,
468*4882a593Smuzhiyun 					      &resource_index);
469*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
470*4882a593Smuzhiyun 			/*
471*4882a593Smuzhiyun 			 * Exit on failure. Cannot continue because the descriptor length
472*4882a593Smuzhiyun 			 * may be bogus also.
473*4882a593Smuzhiyun 			 */
474*4882a593Smuzhiyun 			return_ACPI_STATUS(status);
475*4882a593Smuzhiyun 		}
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 		aml_resource = (void *)aml_buffer;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 		/* Get the resource length and base (minimum) AML size */
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 		resource_length = acpi_ut_get_resource_length(aml_buffer);
482*4882a593Smuzhiyun 		minimum_aml_resource_length =
483*4882a593Smuzhiyun 		    acpi_gbl_resource_aml_sizes[resource_index];
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 		/*
486*4882a593Smuzhiyun 		 * Augment the size for descriptors with optional
487*4882a593Smuzhiyun 		 * and/or variable length fields
488*4882a593Smuzhiyun 		 */
489*4882a593Smuzhiyun 		extra_struct_bytes = 0;
490*4882a593Smuzhiyun 		buffer =
491*4882a593Smuzhiyun 		    aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 		switch (acpi_ut_get_resource_type(aml_buffer)) {
494*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_IRQ:
495*4882a593Smuzhiyun 			/*
496*4882a593Smuzhiyun 			 * IRQ Resource:
497*4882a593Smuzhiyun 			 * Get the number of bits set in the 16-bit IRQ mask
498*4882a593Smuzhiyun 			 */
499*4882a593Smuzhiyun 			ACPI_MOVE_16_TO_16(&temp16, buffer);
500*4882a593Smuzhiyun 			extra_struct_bytes = acpi_rs_count_set_bits(temp16);
501*4882a593Smuzhiyun 			break;
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_DMA:
504*4882a593Smuzhiyun 			/*
505*4882a593Smuzhiyun 			 * DMA Resource:
506*4882a593Smuzhiyun 			 * Get the number of bits set in the 8-bit DMA mask
507*4882a593Smuzhiyun 			 */
508*4882a593Smuzhiyun 			extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
509*4882a593Smuzhiyun 			break;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_VENDOR_SMALL:
512*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_VENDOR_LARGE:
513*4882a593Smuzhiyun 			/*
514*4882a593Smuzhiyun 			 * Vendor Resource:
515*4882a593Smuzhiyun 			 * Get the number of vendor data bytes
516*4882a593Smuzhiyun 			 */
517*4882a593Smuzhiyun 			extra_struct_bytes = resource_length;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 			/*
520*4882a593Smuzhiyun 			 * There is already one byte included in the minimum
521*4882a593Smuzhiyun 			 * descriptor size. If there are extra struct bytes,
522*4882a593Smuzhiyun 			 * subtract one from the count.
523*4882a593Smuzhiyun 			 */
524*4882a593Smuzhiyun 			if (extra_struct_bytes) {
525*4882a593Smuzhiyun 				extra_struct_bytes--;
526*4882a593Smuzhiyun 			}
527*4882a593Smuzhiyun 			break;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_END_TAG:
530*4882a593Smuzhiyun 			/*
531*4882a593Smuzhiyun 			 * End Tag: This is the normal exit
532*4882a593Smuzhiyun 			 */
533*4882a593Smuzhiyun 			return_ACPI_STATUS(AE_OK);
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_ADDRESS32:
536*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_ADDRESS16:
537*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_ADDRESS64:
538*4882a593Smuzhiyun 			/*
539*4882a593Smuzhiyun 			 * Address Resource:
540*4882a593Smuzhiyun 			 * Add the size of the optional resource_source
541*4882a593Smuzhiyun 			 */
542*4882a593Smuzhiyun 			extra_struct_bytes =
543*4882a593Smuzhiyun 			    acpi_rs_stream_option_length(resource_length,
544*4882a593Smuzhiyun 							 minimum_aml_resource_length);
545*4882a593Smuzhiyun 			break;
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
548*4882a593Smuzhiyun 			/*
549*4882a593Smuzhiyun 			 * Extended IRQ Resource:
550*4882a593Smuzhiyun 			 * Using the interrupt_table_length, add 4 bytes for each additional
551*4882a593Smuzhiyun 			 * interrupt. Note: at least one interrupt is required and is
552*4882a593Smuzhiyun 			 * included in the minimum descriptor size (reason for the -1)
553*4882a593Smuzhiyun 			 */
554*4882a593Smuzhiyun 			extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 			/* Add the size of the optional resource_source */
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 			extra_struct_bytes +=
559*4882a593Smuzhiyun 			    acpi_rs_stream_option_length(resource_length -
560*4882a593Smuzhiyun 							 extra_struct_bytes,
561*4882a593Smuzhiyun 							 minimum_aml_resource_length);
562*4882a593Smuzhiyun 			break;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_GPIO:
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 			/* Vendor data is optional */
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 			if (aml_resource->gpio.vendor_length) {
569*4882a593Smuzhiyun 				extra_struct_bytes +=
570*4882a593Smuzhiyun 				    aml_resource->gpio.vendor_offset -
571*4882a593Smuzhiyun 				    aml_resource->gpio.pin_table_offset +
572*4882a593Smuzhiyun 				    aml_resource->gpio.vendor_length;
573*4882a593Smuzhiyun 			} else {
574*4882a593Smuzhiyun 				extra_struct_bytes +=
575*4882a593Smuzhiyun 				    aml_resource->large_header.resource_length +
576*4882a593Smuzhiyun 				    sizeof(struct aml_resource_large_header) -
577*4882a593Smuzhiyun 				    aml_resource->gpio.pin_table_offset;
578*4882a593Smuzhiyun 			}
579*4882a593Smuzhiyun 			break;
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_PIN_FUNCTION:
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 			/* Vendor data is optional */
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 			if (aml_resource->pin_function.vendor_length) {
586*4882a593Smuzhiyun 				extra_struct_bytes +=
587*4882a593Smuzhiyun 				    aml_resource->pin_function.vendor_offset -
588*4882a593Smuzhiyun 				    aml_resource->pin_function.
589*4882a593Smuzhiyun 				    pin_table_offset +
590*4882a593Smuzhiyun 				    aml_resource->pin_function.vendor_length;
591*4882a593Smuzhiyun 			} else {
592*4882a593Smuzhiyun 				extra_struct_bytes +=
593*4882a593Smuzhiyun 				    aml_resource->large_header.resource_length +
594*4882a593Smuzhiyun 				    sizeof(struct aml_resource_large_header) -
595*4882a593Smuzhiyun 				    aml_resource->pin_function.pin_table_offset;
596*4882a593Smuzhiyun 			}
597*4882a593Smuzhiyun 			break;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_SERIAL_BUS:
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 			minimum_aml_resource_length =
602*4882a593Smuzhiyun 			    acpi_gbl_resource_aml_serial_bus_sizes
603*4882a593Smuzhiyun 			    [aml_resource->common_serial_bus.type];
604*4882a593Smuzhiyun 			extra_struct_bytes +=
605*4882a593Smuzhiyun 			    aml_resource->common_serial_bus.resource_length -
606*4882a593Smuzhiyun 			    minimum_aml_resource_length;
607*4882a593Smuzhiyun 			break;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_PIN_CONFIG:
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 			/* Vendor data is optional */
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 			if (aml_resource->pin_config.vendor_length) {
614*4882a593Smuzhiyun 				extra_struct_bytes +=
615*4882a593Smuzhiyun 				    aml_resource->pin_config.vendor_offset -
616*4882a593Smuzhiyun 				    aml_resource->pin_config.pin_table_offset +
617*4882a593Smuzhiyun 				    aml_resource->pin_config.vendor_length;
618*4882a593Smuzhiyun 			} else {
619*4882a593Smuzhiyun 				extra_struct_bytes +=
620*4882a593Smuzhiyun 				    aml_resource->large_header.resource_length +
621*4882a593Smuzhiyun 				    sizeof(struct aml_resource_large_header) -
622*4882a593Smuzhiyun 				    aml_resource->pin_config.pin_table_offset;
623*4882a593Smuzhiyun 			}
624*4882a593Smuzhiyun 			break;
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_PIN_GROUP:
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 			extra_struct_bytes +=
629*4882a593Smuzhiyun 			    aml_resource->pin_group.vendor_offset -
630*4882a593Smuzhiyun 			    aml_resource->pin_group.pin_table_offset +
631*4882a593Smuzhiyun 			    aml_resource->pin_group.vendor_length;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 			break;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION:
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 			extra_struct_bytes +=
638*4882a593Smuzhiyun 			    aml_resource->pin_group_function.vendor_offset -
639*4882a593Smuzhiyun 			    aml_resource->pin_group_function.res_source_offset +
640*4882a593Smuzhiyun 			    aml_resource->pin_group_function.vendor_length;
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 			break;
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 		case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG:
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 			extra_struct_bytes +=
647*4882a593Smuzhiyun 			    aml_resource->pin_group_config.vendor_offset -
648*4882a593Smuzhiyun 			    aml_resource->pin_group_config.res_source_offset +
649*4882a593Smuzhiyun 			    aml_resource->pin_group_config.vendor_length;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 			break;
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 		default:
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 			break;
656*4882a593Smuzhiyun 		}
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 		/*
659*4882a593Smuzhiyun 		 * Update the required buffer size for the internal descriptor structs
660*4882a593Smuzhiyun 		 *
661*4882a593Smuzhiyun 		 * Important: Round the size up for the appropriate alignment. This
662*4882a593Smuzhiyun 		 * is a requirement on IA64.
663*4882a593Smuzhiyun 		 */
664*4882a593Smuzhiyun 		if (acpi_ut_get_resource_type(aml_buffer) ==
665*4882a593Smuzhiyun 		    ACPI_RESOURCE_NAME_SERIAL_BUS) {
666*4882a593Smuzhiyun 			buffer_size =
667*4882a593Smuzhiyun 			    acpi_gbl_resource_struct_serial_bus_sizes
668*4882a593Smuzhiyun 			    [aml_resource->common_serial_bus.type] +
669*4882a593Smuzhiyun 			    extra_struct_bytes;
670*4882a593Smuzhiyun 		} else {
671*4882a593Smuzhiyun 			buffer_size =
672*4882a593Smuzhiyun 			    acpi_gbl_resource_struct_sizes[resource_index] +
673*4882a593Smuzhiyun 			    extra_struct_bytes;
674*4882a593Smuzhiyun 		}
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 		buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
677*4882a593Smuzhiyun 		*size_needed += buffer_size;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
680*4882a593Smuzhiyun 				  "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
681*4882a593Smuzhiyun 				  acpi_ut_get_resource_type(aml_buffer),
682*4882a593Smuzhiyun 				  acpi_ut_get_descriptor_length(aml_buffer),
683*4882a593Smuzhiyun 				  buffer_size));
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 		/*
686*4882a593Smuzhiyun 		 * Point to the next resource within the AML stream using the length
687*4882a593Smuzhiyun 		 * contained in the resource descriptor header
688*4882a593Smuzhiyun 		 */
689*4882a593Smuzhiyun 		aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
690*4882a593Smuzhiyun 	}
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	/* Did not find an end_tag resource descriptor */
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun /*******************************************************************************
698*4882a593Smuzhiyun  *
699*4882a593Smuzhiyun  * FUNCTION:    acpi_rs_get_pci_routing_table_length
700*4882a593Smuzhiyun  *
701*4882a593Smuzhiyun  * PARAMETERS:  package_object          - Pointer to the package object
702*4882a593Smuzhiyun  *              buffer_size_needed      - u32 pointer of the size buffer
703*4882a593Smuzhiyun  *                                        needed to properly return the
704*4882a593Smuzhiyun  *                                        parsed data
705*4882a593Smuzhiyun  *
706*4882a593Smuzhiyun  * RETURN:      Status
707*4882a593Smuzhiyun  *
708*4882a593Smuzhiyun  * DESCRIPTION: Given a package representing a PCI routing table, this
709*4882a593Smuzhiyun  *              calculates the size of the corresponding linked list of
710*4882a593Smuzhiyun  *              descriptions.
711*4882a593Smuzhiyun  *
712*4882a593Smuzhiyun  ******************************************************************************/
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun acpi_status
acpi_rs_get_pci_routing_table_length(union acpi_operand_object * package_object,acpi_size * buffer_size_needed)715*4882a593Smuzhiyun acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
716*4882a593Smuzhiyun 				     acpi_size *buffer_size_needed)
717*4882a593Smuzhiyun {
718*4882a593Smuzhiyun 	u32 number_of_elements;
719*4882a593Smuzhiyun 	acpi_size temp_size_needed = 0;
720*4882a593Smuzhiyun 	union acpi_operand_object **top_object_list;
721*4882a593Smuzhiyun 	u32 index;
722*4882a593Smuzhiyun 	union acpi_operand_object *package_element;
723*4882a593Smuzhiyun 	union acpi_operand_object **sub_object_list;
724*4882a593Smuzhiyun 	u8 name_found;
725*4882a593Smuzhiyun 	u32 table_index;
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	number_of_elements = package_object->package.count;
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	/*
732*4882a593Smuzhiyun 	 * Calculate the size of the return buffer.
733*4882a593Smuzhiyun 	 * The base size is the number of elements * the sizes of the
734*4882a593Smuzhiyun 	 * structures. Additional space for the strings is added below.
735*4882a593Smuzhiyun 	 * The minus one is to subtract the size of the u8 Source[1]
736*4882a593Smuzhiyun 	 * member because it is added below.
737*4882a593Smuzhiyun 	 *
738*4882a593Smuzhiyun 	 * But each PRT_ENTRY structure has a pointer to a string and
739*4882a593Smuzhiyun 	 * the size of that string must be found.
740*4882a593Smuzhiyun 	 */
741*4882a593Smuzhiyun 	top_object_list = package_object->package.elements;
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun 	for (index = 0; index < number_of_elements; index++) {
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 		/* Dereference the subpackage */
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 		package_element = *top_object_list;
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun 		/* We must have a valid Package object */
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 		if (!package_element ||
752*4882a593Smuzhiyun 		    (package_element->common.type != ACPI_TYPE_PACKAGE)) {
753*4882a593Smuzhiyun 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
754*4882a593Smuzhiyun 		}
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 		/*
757*4882a593Smuzhiyun 		 * The sub_object_list will now point to an array of the
758*4882a593Smuzhiyun 		 * four IRQ elements: Address, Pin, Source and source_index
759*4882a593Smuzhiyun 		 */
760*4882a593Smuzhiyun 		sub_object_list = package_element->package.elements;
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 		/* Scan the irq_table_elements for the Source Name String */
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 		name_found = FALSE;
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun 		for (table_index = 0;
767*4882a593Smuzhiyun 		     table_index < package_element->package.count
768*4882a593Smuzhiyun 		     && !name_found; table_index++) {
769*4882a593Smuzhiyun 			if (*sub_object_list &&	/* Null object allowed */
770*4882a593Smuzhiyun 			    ((ACPI_TYPE_STRING ==
771*4882a593Smuzhiyun 			      (*sub_object_list)->common.type) ||
772*4882a593Smuzhiyun 			     ((ACPI_TYPE_LOCAL_REFERENCE ==
773*4882a593Smuzhiyun 			       (*sub_object_list)->common.type) &&
774*4882a593Smuzhiyun 			      ((*sub_object_list)->reference.class ==
775*4882a593Smuzhiyun 			       ACPI_REFCLASS_NAME)))) {
776*4882a593Smuzhiyun 				name_found = TRUE;
777*4882a593Smuzhiyun 			} else {
778*4882a593Smuzhiyun 				/* Look at the next element */
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 				sub_object_list++;
781*4882a593Smuzhiyun 			}
782*4882a593Smuzhiyun 		}
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 		temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 		/* Was a String type found? */
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 		if (name_found) {
789*4882a593Smuzhiyun 			if ((*sub_object_list)->common.type == ACPI_TYPE_STRING) {
790*4882a593Smuzhiyun 				/*
791*4882a593Smuzhiyun 				 * The length String.Length field does not include the
792*4882a593Smuzhiyun 				 * terminating NULL, add 1
793*4882a593Smuzhiyun 				 */
794*4882a593Smuzhiyun 				temp_size_needed += ((acpi_size)
795*4882a593Smuzhiyun 						     (*sub_object_list)->string.
796*4882a593Smuzhiyun 						     length + 1);
797*4882a593Smuzhiyun 			} else {
798*4882a593Smuzhiyun 				temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
799*4882a593Smuzhiyun 			}
800*4882a593Smuzhiyun 		} else {
801*4882a593Smuzhiyun 			/*
802*4882a593Smuzhiyun 			 * If no name was found, then this is a NULL, which is
803*4882a593Smuzhiyun 			 * translated as a u32 zero.
804*4882a593Smuzhiyun 			 */
805*4882a593Smuzhiyun 			temp_size_needed += sizeof(u32);
806*4882a593Smuzhiyun 		}
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 		/* Round up the size since each element must be aligned */
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 		temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 		/* Point to the next union acpi_operand_object */
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 		top_object_list++;
815*4882a593Smuzhiyun 	}
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 	/*
818*4882a593Smuzhiyun 	 * Add an extra element to the end of the list, essentially a
819*4882a593Smuzhiyun 	 * NULL terminator
820*4882a593Smuzhiyun 	 */
821*4882a593Smuzhiyun 	*buffer_size_needed =
822*4882a593Smuzhiyun 	    temp_size_needed + sizeof(struct acpi_pci_routing_table);
823*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
824*4882a593Smuzhiyun }
825