xref: /titanic_51/usr/src/uts/intel/io/acpica/resources/rsxface.c (revision a9478106a12424322498e53cf7cd75bd8a4d6004)
1 /*******************************************************************************
2  *
3  * Module Name: rsxface - Public interfaces to the resource manager
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2011, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 
45 #define __RSXFACE_C__
46 
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "acresrc.h"
50 #include "acnamesp.h"
51 
52 #define _COMPONENT          ACPI_RESOURCES
53         ACPI_MODULE_NAME    ("rsxface")
54 
55 /* Local macros for 16,32-bit to 64-bit conversion */
56 
57 #define ACPI_COPY_FIELD(Out, In, Field)  ((Out)->Field = (In)->Field)
58 #define ACPI_COPY_ADDRESS(Out, In)                      \
59     ACPI_COPY_FIELD(Out, In, ResourceType);              \
60     ACPI_COPY_FIELD(Out, In, ProducerConsumer);          \
61     ACPI_COPY_FIELD(Out, In, Decode);                    \
62     ACPI_COPY_FIELD(Out, In, MinAddressFixed);           \
63     ACPI_COPY_FIELD(Out, In, MaxAddressFixed);           \
64     ACPI_COPY_FIELD(Out, In, Info);                      \
65     ACPI_COPY_FIELD(Out, In, Granularity);               \
66     ACPI_COPY_FIELD(Out, In, Minimum);                   \
67     ACPI_COPY_FIELD(Out, In, Maximum);                   \
68     ACPI_COPY_FIELD(Out, In, TranslationOffset);         \
69     ACPI_COPY_FIELD(Out, In, AddressLength);             \
70     ACPI_COPY_FIELD(Out, In, ResourceSource);
71 
72 
73 /* Local prototypes */
74 
75 static ACPI_STATUS
76 AcpiRsMatchVendorResource (
77     ACPI_RESOURCE           *Resource,
78     void                    *Context);
79 
80 static ACPI_STATUS
81 AcpiRsValidateParameters (
82     ACPI_HANDLE             DeviceHandle,
83     ACPI_BUFFER             *Buffer,
84     ACPI_NAMESPACE_NODE     **ReturnNode);
85 
86 
87 /*******************************************************************************
88  *
89  * FUNCTION:    AcpiRsValidateParameters
90  *
91  * PARAMETERS:  DeviceHandle    - Handle to a device
92  *              Buffer          - Pointer to a data buffer
93  *              ReturnNode      - Pointer to where the device node is returned
94  *
95  * RETURN:      Status
96  *
97  * DESCRIPTION: Common parameter validation for resource interfaces
98  *
99  ******************************************************************************/
100 
101 static ACPI_STATUS
102 AcpiRsValidateParameters (
103     ACPI_HANDLE             DeviceHandle,
104     ACPI_BUFFER             *Buffer,
105     ACPI_NAMESPACE_NODE     **ReturnNode)
106 {
107     ACPI_STATUS             Status;
108     ACPI_NAMESPACE_NODE     *Node;
109 
110 
111     ACPI_FUNCTION_TRACE (RsValidateParameters);
112 
113 
114     /*
115      * Must have a valid handle to an ACPI device
116      */
117     if (!DeviceHandle)
118     {
119         return_ACPI_STATUS (AE_BAD_PARAMETER);
120     }
121 
122     Node = AcpiNsValidateHandle (DeviceHandle);
123     if (!Node)
124     {
125         return_ACPI_STATUS (AE_BAD_PARAMETER);
126     }
127 
128     if (Node->Type != ACPI_TYPE_DEVICE)
129     {
130         return_ACPI_STATUS (AE_TYPE);
131     }
132 
133     /*
134      * Validate the user buffer object
135      *
136      * if there is a non-zero buffer length we also need a valid pointer in
137      * the buffer. If it's a zero buffer length, we'll be returning the
138      * needed buffer size (later), so keep going.
139      */
140     Status = AcpiUtValidateBuffer (Buffer);
141     if (ACPI_FAILURE (Status))
142     {
143         return_ACPI_STATUS (Status);
144     }
145 
146     *ReturnNode = Node;
147     return_ACPI_STATUS (AE_OK);
148 }
149 
150 
151 /*******************************************************************************
152  *
153  * FUNCTION:    AcpiGetIrqRoutingTable
154  *
155  * PARAMETERS:  DeviceHandle    - Handle to the Bus device we are querying
156  *              RetBuffer       - Pointer to a buffer to receive the
157  *                                current resources for the device
158  *
159  * RETURN:      Status
160  *
161  * DESCRIPTION: This function is called to get the IRQ routing table for a
162  *              specific bus. The caller must first acquire a handle for the
163  *              desired bus. The routine table is placed in the buffer pointed
164  *              to by the RetBuffer variable parameter.
165  *
166  *              If the function fails an appropriate status will be returned
167  *              and the value of RetBuffer is undefined.
168  *
169  *              This function attempts to execute the _PRT method contained in
170  *              the object indicated by the passed DeviceHandle.
171  *
172  ******************************************************************************/
173 
174 ACPI_STATUS
175 AcpiGetIrqRoutingTable  (
176     ACPI_HANDLE             DeviceHandle,
177     ACPI_BUFFER             *RetBuffer)
178 {
179     ACPI_STATUS             Status;
180     ACPI_NAMESPACE_NODE     *Node;
181 
182 
183     ACPI_FUNCTION_TRACE (AcpiGetIrqRoutingTable);
184 
185 
186     /* Validate parameters then dispatch to internal routine */
187 
188     Status = AcpiRsValidateParameters (DeviceHandle, RetBuffer, &Node);
189     if (ACPI_FAILURE (Status))
190     {
191         return_ACPI_STATUS (Status);
192     }
193 
194     Status = AcpiRsGetPrtMethodData (Node, RetBuffer);
195     return_ACPI_STATUS (Status);
196 }
197 
198 ACPI_EXPORT_SYMBOL (AcpiGetIrqRoutingTable)
199 
200 
201 /*******************************************************************************
202  *
203  * FUNCTION:    AcpiGetCurrentResources
204  *
205  * PARAMETERS:  DeviceHandle    - Handle to the device object for the
206  *                                device we are querying
207  *              RetBuffer       - Pointer to a buffer to receive the
208  *                                current resources for the device
209  *
210  * RETURN:      Status
211  *
212  * DESCRIPTION: This function is called to get the current resources for a
213  *              specific device. The caller must first acquire a handle for
214  *              the desired device. The resource data is placed in the buffer
215  *              pointed to by the RetBuffer variable parameter.
216  *
217  *              If the function fails an appropriate status will be returned
218  *              and the value of RetBuffer is undefined.
219  *
220  *              This function attempts to execute the _CRS method contained in
221  *              the object indicated by the passed DeviceHandle.
222  *
223  ******************************************************************************/
224 
225 ACPI_STATUS
226 AcpiGetCurrentResources (
227     ACPI_HANDLE             DeviceHandle,
228     ACPI_BUFFER             *RetBuffer)
229 {
230     ACPI_STATUS             Status;
231     ACPI_NAMESPACE_NODE     *Node;
232 
233 
234     ACPI_FUNCTION_TRACE (AcpiGetCurrentResources);
235 
236 
237     /* Validate parameters then dispatch to internal routine */
238 
239     Status = AcpiRsValidateParameters (DeviceHandle, RetBuffer, &Node);
240     if (ACPI_FAILURE (Status))
241     {
242         return_ACPI_STATUS (Status);
243     }
244 
245     Status = AcpiRsGetCrsMethodData (Node, RetBuffer);
246     return_ACPI_STATUS (Status);
247 }
248 
249 ACPI_EXPORT_SYMBOL (AcpiGetCurrentResources)
250 
251 
252 /*******************************************************************************
253  *
254  * FUNCTION:    AcpiGetPossibleResources
255  *
256  * PARAMETERS:  DeviceHandle    - Handle to the device object for the
257  *                                device we are querying
258  *              RetBuffer       - Pointer to a buffer to receive the
259  *                                resources for the device
260  *
261  * RETURN:      Status
262  *
263  * DESCRIPTION: This function is called to get a list of the possible resources
264  *              for a specific device. The caller must first acquire a handle
265  *              for the desired device. The resource data is placed in the
266  *              buffer pointed to by the RetBuffer variable.
267  *
268  *              If the function fails an appropriate status will be returned
269  *              and the value of RetBuffer is undefined.
270  *
271  ******************************************************************************/
272 
273 ACPI_STATUS
274 AcpiGetPossibleResources (
275     ACPI_HANDLE             DeviceHandle,
276     ACPI_BUFFER             *RetBuffer)
277 {
278     ACPI_STATUS             Status;
279     ACPI_NAMESPACE_NODE     *Node;
280 
281 
282     ACPI_FUNCTION_TRACE (AcpiGetPossibleResources);
283 
284 
285     /* Validate parameters then dispatch to internal routine */
286 
287     Status = AcpiRsValidateParameters (DeviceHandle, RetBuffer, &Node);
288     if (ACPI_FAILURE (Status))
289     {
290         return_ACPI_STATUS (Status);
291     }
292 
293     Status = AcpiRsGetPrsMethodData (Node, RetBuffer);
294     return_ACPI_STATUS (Status);
295 }
296 
297 ACPI_EXPORT_SYMBOL (AcpiGetPossibleResources)
298 
299 
300 /*******************************************************************************
301  *
302  * FUNCTION:    AcpiSetCurrentResources
303  *
304  * PARAMETERS:  DeviceHandle    - Handle to the device object for the
305  *                                device we are setting resources
306  *              InBuffer        - Pointer to a buffer containing the
307  *                                resources to be set for the device
308  *
309  * RETURN:      Status
310  *
311  * DESCRIPTION: This function is called to set the current resources for a
312  *              specific device. The caller must first acquire a handle for
313  *              the desired device. The resource data is passed to the routine
314  *              the buffer pointed to by the InBuffer variable.
315  *
316  ******************************************************************************/
317 
318 ACPI_STATUS
319 AcpiSetCurrentResources (
320     ACPI_HANDLE             DeviceHandle,
321     ACPI_BUFFER             *InBuffer)
322 {
323     ACPI_STATUS             Status;
324     ACPI_NAMESPACE_NODE     *Node;
325 
326 
327     ACPI_FUNCTION_TRACE (AcpiSetCurrentResources);
328 
329 
330     /* Validate the buffer, don't allow zero length */
331 
332     if ((!InBuffer) ||
333         (!InBuffer->Pointer) ||
334         (!InBuffer->Length))
335     {
336         return_ACPI_STATUS (AE_BAD_PARAMETER);
337     }
338 
339     /* Validate parameters then dispatch to internal routine */
340 
341     Status = AcpiRsValidateParameters (DeviceHandle, InBuffer, &Node);
342     if (ACPI_FAILURE (Status))
343     {
344         return_ACPI_STATUS (Status);
345     }
346 
347     Status = AcpiRsSetSrsMethodData (Node, InBuffer);
348     return_ACPI_STATUS (Status);
349 }
350 
351 ACPI_EXPORT_SYMBOL (AcpiSetCurrentResources)
352 
353 
354 /******************************************************************************
355  *
356  * FUNCTION:    AcpiResourceToAddress64
357  *
358  * PARAMETERS:  Resource        - Pointer to a resource
359  *              Out             - Pointer to the users's return buffer
360  *                                (a struct acpi_resource_address64)
361  *
362  * RETURN:      Status
363  *
364  * DESCRIPTION: If the resource is an address16, address32, or address64,
365  *              copy it to the address64 return buffer. This saves the
366  *              caller from having to duplicate code for different-sized
367  *              addresses.
368  *
369  ******************************************************************************/
370 
371 ACPI_STATUS
372 AcpiResourceToAddress64 (
373     ACPI_RESOURCE               *Resource,
374     ACPI_RESOURCE_ADDRESS64     *Out)
375 {
376     ACPI_RESOURCE_ADDRESS16     *Address16;
377     ACPI_RESOURCE_ADDRESS32     *Address32;
378 
379 
380     if (!Resource || !Out)
381     {
382         return (AE_BAD_PARAMETER);
383     }
384 
385     /* Convert 16 or 32 address descriptor to 64 */
386 
387     switch (Resource->Type)
388     {
389     case ACPI_RESOURCE_TYPE_ADDRESS16:
390 
391         Address16 = ACPI_CAST_PTR (ACPI_RESOURCE_ADDRESS16, &Resource->Data);
392         ACPI_COPY_ADDRESS (Out, Address16);
393         break;
394 
395     case ACPI_RESOURCE_TYPE_ADDRESS32:
396 
397         Address32 = ACPI_CAST_PTR (ACPI_RESOURCE_ADDRESS32, &Resource->Data);
398         ACPI_COPY_ADDRESS (Out, Address32);
399         break;
400 
401     case ACPI_RESOURCE_TYPE_ADDRESS64:
402 
403         /* Simple copy for 64 bit source */
404 
405         ACPI_MEMCPY (Out, &Resource->Data, sizeof (ACPI_RESOURCE_ADDRESS64));
406         break;
407 
408     default:
409         return (AE_BAD_PARAMETER);
410     }
411 
412     return (AE_OK);
413 }
414 
415 ACPI_EXPORT_SYMBOL (AcpiResourceToAddress64)
416 
417 
418 /*******************************************************************************
419  *
420  * FUNCTION:    AcpiGetVendorResource
421  *
422  * PARAMETERS:  DeviceHandle    - Handle for the parent device object
423  *              Name            - Method name for the parent resource
424  *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
425  *              Uuid            - Pointer to the UUID to be matched.
426  *                                includes both subtype and 16-byte UUID
427  *              RetBuffer       - Where the vendor resource is returned
428  *
429  * RETURN:      Status
430  *
431  * DESCRIPTION: Walk a resource template for the specified evice to find a
432  *              vendor-defined resource that matches the supplied UUID and
433  *              UUID subtype. Returns a ACPI_RESOURCE of type Vendor.
434  *
435  ******************************************************************************/
436 
437 ACPI_STATUS
438 AcpiGetVendorResource (
439     ACPI_HANDLE             DeviceHandle,
440     char                    *Name,
441     ACPI_VENDOR_UUID        *Uuid,
442     ACPI_BUFFER             *RetBuffer)
443 {
444     ACPI_VENDOR_WALK_INFO   Info;
445     ACPI_STATUS             Status;
446 
447 
448     /* Other parameters are validated by AcpiWalkResources */
449 
450     if (!Uuid || !RetBuffer)
451     {
452         return (AE_BAD_PARAMETER);
453     }
454 
455     Info.Uuid = Uuid;
456     Info.Buffer = RetBuffer;
457     Info.Status = AE_NOT_EXIST;
458 
459     /* Walk the _CRS or _PRS resource list for this device */
460 
461     Status = AcpiWalkResources (DeviceHandle, Name, AcpiRsMatchVendorResource,
462                 &Info);
463     if (ACPI_FAILURE (Status))
464     {
465         return (Status);
466     }
467 
468     return (Info.Status);
469 }
470 
471 ACPI_EXPORT_SYMBOL (AcpiGetVendorResource)
472 
473 
474 /*******************************************************************************
475  *
476  * FUNCTION:    AcpiRsMatchVendorResource
477  *
478  * PARAMETERS:  ACPI_WALK_RESOURCE_CALLBACK
479  *
480  * RETURN:      Status
481  *
482  * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID
483  *
484  ******************************************************************************/
485 
486 static ACPI_STATUS
487 AcpiRsMatchVendorResource (
488     ACPI_RESOURCE           *Resource,
489     void                    *Context)
490 {
491     ACPI_VENDOR_WALK_INFO       *Info = Context;
492     ACPI_RESOURCE_VENDOR_TYPED  *Vendor;
493     ACPI_BUFFER                 *Buffer;
494     ACPI_STATUS                 Status;
495 
496 
497     /* Ignore all descriptors except Vendor */
498 
499     if (Resource->Type != ACPI_RESOURCE_TYPE_VENDOR)
500     {
501         return (AE_OK);
502     }
503 
504     Vendor = &Resource->Data.VendorTyped;
505 
506     /*
507      * For a valid match, these conditions must hold:
508      *
509      * 1) Length of descriptor data must be at least as long as a UUID struct
510      * 2) The UUID subtypes must match
511      * 3) The UUID data must match
512      */
513     if ((Vendor->ByteLength < (ACPI_UUID_LENGTH + 1)) ||
514         (Vendor->UuidSubtype != Info->Uuid->Subtype)  ||
515         (ACPI_MEMCMP (Vendor->Uuid, Info->Uuid->Data, ACPI_UUID_LENGTH)))
516     {
517         return (AE_OK);
518     }
519 
520     /* Validate/Allocate/Clear caller buffer */
521 
522     Buffer = Info->Buffer;
523     Status = AcpiUtInitializeBuffer (Buffer, Resource->Length);
524     if (ACPI_FAILURE (Status))
525     {
526         return (Status);
527     }
528 
529     /* Found the correct resource, copy and return it */
530 
531     ACPI_MEMCPY (Buffer->Pointer, Resource, Resource->Length);
532     Buffer->Length = Resource->Length;
533 
534     /* Found the desired descriptor, terminate resource walk */
535 
536     Info->Status = AE_OK;
537     return (AE_CTRL_TERMINATE);
538 }
539 
540 
541 /*******************************************************************************
542  *
543  * FUNCTION:    AcpiWalkResources
544  *
545  * PARAMETERS:  DeviceHandle    - Handle to the device object for the
546  *                                device we are querying
547  *              Name            - Method name of the resources we want
548  *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
549  *              UserFunction    - Called for each resource
550  *              Context         - Passed to UserFunction
551  *
552  * RETURN:      Status
553  *
554  * DESCRIPTION: Retrieves the current or possible resource list for the
555  *              specified device. The UserFunction is called once for
556  *              each resource in the list.
557  *
558  ******************************************************************************/
559 
560 ACPI_STATUS
561 AcpiWalkResources (
562     ACPI_HANDLE                 DeviceHandle,
563     char                        *Name,
564     ACPI_WALK_RESOURCE_CALLBACK UserFunction,
565     void                        *Context)
566 {
567     ACPI_STATUS                 Status;
568     ACPI_BUFFER                 Buffer;
569     ACPI_RESOURCE               *Resource;
570     ACPI_RESOURCE               *ResourceEnd;
571 
572 
573     ACPI_FUNCTION_TRACE (AcpiWalkResources);
574 
575 
576     /* Parameter validation */
577 
578     if (!DeviceHandle || !UserFunction || !Name ||
579         (!ACPI_COMPARE_NAME (Name, METHOD_NAME__CRS) &&
580          !ACPI_COMPARE_NAME (Name, METHOD_NAME__PRS)))
581     {
582         return_ACPI_STATUS (AE_BAD_PARAMETER);
583     }
584 
585     /* Get the _CRS or _PRS resource list */
586 
587     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
588     Status = AcpiRsGetMethodData (DeviceHandle, Name, &Buffer);
589     if (ACPI_FAILURE (Status))
590     {
591         return_ACPI_STATUS (Status);
592     }
593 
594     /* Buffer now contains the resource list */
595 
596     Resource = ACPI_CAST_PTR (ACPI_RESOURCE, Buffer.Pointer);
597     ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Buffer.Pointer, Buffer.Length);
598 
599     /* Walk the resource list until the EndTag is found (or buffer end) */
600 
601     while (Resource < ResourceEnd)
602     {
603         /* Sanity check the resource */
604 
605         if (Resource->Type > ACPI_RESOURCE_TYPE_MAX)
606         {
607             Status = AE_AML_INVALID_RESOURCE_TYPE;
608             break;
609         }
610 
611         /* Invoke the user function, abort on any error returned */
612 
613         Status = UserFunction (Resource, Context);
614         if (ACPI_FAILURE (Status))
615         {
616             if (Status == AE_CTRL_TERMINATE)
617             {
618                 /* This is an OK termination by the user function */
619 
620                 Status = AE_OK;
621             }
622             break;
623         }
624 
625         /* EndTag indicates end-of-list */
626 
627         if (Resource->Type == ACPI_RESOURCE_TYPE_END_TAG)
628         {
629             break;
630         }
631 
632         /* Get the next resource descriptor */
633 
634         Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length);
635     }
636 
637     ACPI_FREE (Buffer.Pointer);
638     return_ACPI_STATUS (Status);
639 }
640 
641 ACPI_EXPORT_SYMBOL (AcpiWalkResources)
642