xref: /dragonfly/sys/dev/acpica/acpi_package.c (revision 417dc5a4)
15db2f26eSSascha Wildner /*-
25db2f26eSSascha Wildner  * Copyright (c) 2003 Nate Lawson
35db2f26eSSascha Wildner  * All rights reserved.
45db2f26eSSascha Wildner  *
55db2f26eSSascha Wildner  * Redistribution and use in source and binary forms, with or without
65db2f26eSSascha Wildner  * modification, are permitted provided that the following conditions
75db2f26eSSascha Wildner  * are met:
85db2f26eSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
95db2f26eSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
105db2f26eSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
115db2f26eSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
125db2f26eSSascha Wildner  *    documentation and/or other materials provided with the distribution.
135db2f26eSSascha Wildner  *
145db2f26eSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
155db2f26eSSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165db2f26eSSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
175db2f26eSSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
185db2f26eSSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
195db2f26eSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
205db2f26eSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
215db2f26eSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
225db2f26eSSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
235db2f26eSSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
245db2f26eSSascha Wildner  * SUCH DAMAGE.
255db2f26eSSascha Wildner  *
265db2f26eSSascha Wildner  * $FreeBSD: src/sys/dev/acpica/acpi_package.c,v 1.9.8.1 2009/04/15 03:14:26 kensmith Exp $
275db2f26eSSascha Wildner  */
285db2f26eSSascha Wildner 
295db2f26eSSascha Wildner #include <sys/param.h>
305db2f26eSSascha Wildner #include <sys/kernel.h>
315db2f26eSSascha Wildner #include <sys/bus.h>
325db2f26eSSascha Wildner #include <sys/sbuf.h>
335db2f26eSSascha Wildner 
345db2f26eSSascha Wildner #include <sys/rman.h>
355db2f26eSSascha Wildner 
365db2f26eSSascha Wildner #include "acpi.h"
375db2f26eSSascha Wildner #include <dev/acpica/acpivar.h>
385db2f26eSSascha Wildner 
395db2f26eSSascha Wildner /*
405db2f26eSSascha Wildner  * Package manipulation convenience functions
415db2f26eSSascha Wildner  */
425db2f26eSSascha Wildner 
435db2f26eSSascha Wildner int
acpi_PkgInt(ACPI_OBJECT * res,int idx,UINT64 * dst)44*417dc5a4SSascha Wildner acpi_PkgInt(ACPI_OBJECT *res, int idx, UINT64 *dst)
455db2f26eSSascha Wildner {
465db2f26eSSascha Wildner     ACPI_OBJECT		*obj;
475db2f26eSSascha Wildner 
485db2f26eSSascha Wildner     obj = &res->Package.Elements[idx];
495db2f26eSSascha Wildner     if (obj == NULL || obj->Type != ACPI_TYPE_INTEGER)
505db2f26eSSascha Wildner 	return (EINVAL);
515db2f26eSSascha Wildner     *dst = obj->Integer.Value;
525db2f26eSSascha Wildner 
535db2f26eSSascha Wildner     return (0);
545db2f26eSSascha Wildner }
555db2f26eSSascha Wildner 
565db2f26eSSascha Wildner int
acpi_PkgInt32(ACPI_OBJECT * res,int idx,uint32_t * dst)575db2f26eSSascha Wildner acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst)
585db2f26eSSascha Wildner {
59*417dc5a4SSascha Wildner     UINT64		tmp;
605db2f26eSSascha Wildner     int			error;
615db2f26eSSascha Wildner 
625db2f26eSSascha Wildner     error = acpi_PkgInt(res, idx, &tmp);
635db2f26eSSascha Wildner     if (error == 0)
645db2f26eSSascha Wildner 	*dst = (uint32_t)tmp;
655db2f26eSSascha Wildner 
665db2f26eSSascha Wildner     return (error);
675db2f26eSSascha Wildner }
685db2f26eSSascha Wildner 
695db2f26eSSascha Wildner int
acpi_PkgStr(ACPI_OBJECT * res,int idx,void * dst,size_t size)705db2f26eSSascha Wildner acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size)
715db2f26eSSascha Wildner {
725db2f26eSSascha Wildner     ACPI_OBJECT		*obj;
735db2f26eSSascha Wildner     void		*ptr;
745db2f26eSSascha Wildner     size_t		 length;
755db2f26eSSascha Wildner 
765db2f26eSSascha Wildner     obj = &res->Package.Elements[idx];
775db2f26eSSascha Wildner     if (obj == NULL)
785db2f26eSSascha Wildner 	return (EINVAL);
795db2f26eSSascha Wildner     bzero(dst, size);
805db2f26eSSascha Wildner 
815db2f26eSSascha Wildner     switch (obj->Type) {
825db2f26eSSascha Wildner     case ACPI_TYPE_STRING:
835db2f26eSSascha Wildner 	ptr = obj->String.Pointer;
845db2f26eSSascha Wildner 	length = obj->String.Length;
855db2f26eSSascha Wildner 	break;
865db2f26eSSascha Wildner     case ACPI_TYPE_BUFFER:
875db2f26eSSascha Wildner 	ptr = obj->Buffer.Pointer;
885db2f26eSSascha Wildner 	length = obj->Buffer.Length;
895db2f26eSSascha Wildner 	break;
905db2f26eSSascha Wildner     default:
915db2f26eSSascha Wildner 	return (EINVAL);
925db2f26eSSascha Wildner     }
935db2f26eSSascha Wildner 
945db2f26eSSascha Wildner     /* Make sure string will fit, including terminating NUL */
955db2f26eSSascha Wildner     if (++length > size)
965db2f26eSSascha Wildner 	return (E2BIG);
975db2f26eSSascha Wildner 
985db2f26eSSascha Wildner     strlcpy(dst, ptr, length);
995db2f26eSSascha Wildner     return (0);
1005db2f26eSSascha Wildner }
1015db2f26eSSascha Wildner 
1025db2f26eSSascha Wildner int
acpi_PkgGas(device_t dev,ACPI_OBJECT * res,int idx,int * type,int * rid,struct resource ** dst,u_int flags)1035db2f26eSSascha Wildner acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type, int *rid,
1045db2f26eSSascha Wildner     struct resource **dst, u_int flags)
1055db2f26eSSascha Wildner {
1065db2f26eSSascha Wildner     ACPI_GENERIC_ADDRESS gas;
1075db2f26eSSascha Wildner     ACPI_OBJECT *obj;
1085db2f26eSSascha Wildner 
1095db2f26eSSascha Wildner     obj = &res->Package.Elements[idx];
1105db2f26eSSascha Wildner     if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER ||
1115db2f26eSSascha Wildner 	obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3)
1125db2f26eSSascha Wildner 	return (EINVAL);
1135db2f26eSSascha Wildner 
1145db2f26eSSascha Wildner     memcpy(&gas, obj->Buffer.Pointer + 3, sizeof(gas));
1155db2f26eSSascha Wildner 
1165db2f26eSSascha Wildner     return (acpi_bus_alloc_gas(dev, type, rid, &gas, dst, flags));
1175db2f26eSSascha Wildner }
1185db2f26eSSascha Wildner 
1195db2f26eSSascha Wildner int
acpi_PkgRawGas(ACPI_OBJECT * res,int idx,ACPI_GENERIC_ADDRESS * gas)1205db2f26eSSascha Wildner acpi_PkgRawGas(ACPI_OBJECT *res, int idx, ACPI_GENERIC_ADDRESS *gas)
1215db2f26eSSascha Wildner {
1225db2f26eSSascha Wildner     ACPI_OBJECT         *obj;
1235db2f26eSSascha Wildner     obj = &res->Package.Elements[idx];
1245db2f26eSSascha Wildner     if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER ||
1255db2f26eSSascha Wildner         obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3)
1265db2f26eSSascha Wildner         return (EINVAL);
1275db2f26eSSascha Wildner     memcpy(gas, obj->Buffer.Pointer + 3, sizeof(*gas));
1285db2f26eSSascha Wildner     return (0);
1295db2f26eSSascha Wildner }
1305db2f26eSSascha Wildner 
1315db2f26eSSascha Wildner ACPI_HANDLE
acpi_GetReference(ACPI_HANDLE scope,ACPI_OBJECT * obj)1325db2f26eSSascha Wildner acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj)
1335db2f26eSSascha Wildner {
1345db2f26eSSascha Wildner     ACPI_HANDLE h;
1355db2f26eSSascha Wildner 
1365db2f26eSSascha Wildner     if (obj == NULL)
1375db2f26eSSascha Wildner 	return (NULL);
1385db2f26eSSascha Wildner 
1395db2f26eSSascha Wildner     switch (obj->Type) {
1405db2f26eSSascha Wildner     case ACPI_TYPE_LOCAL_REFERENCE:
1415db2f26eSSascha Wildner     case ACPI_TYPE_ANY:
1425db2f26eSSascha Wildner 	h = obj->Reference.Handle;
1435db2f26eSSascha Wildner 	break;
1445db2f26eSSascha Wildner     case ACPI_TYPE_STRING:
1455db2f26eSSascha Wildner 	/*
1465db2f26eSSascha Wildner 	 * The String object usually contains a fully-qualified path, so
1475db2f26eSSascha Wildner 	 * scope can be NULL.
1485db2f26eSSascha Wildner 	 *
1495db2f26eSSascha Wildner 	 * XXX This may not always be the case.
1505db2f26eSSascha Wildner 	 */
1515db2f26eSSascha Wildner 	if (ACPI_FAILURE(AcpiGetHandle(scope, obj->String.Pointer, &h)))
1525db2f26eSSascha Wildner 	    h = NULL;
1535db2f26eSSascha Wildner 	break;
1545db2f26eSSascha Wildner     default:
1555db2f26eSSascha Wildner 	h = NULL;
1565db2f26eSSascha Wildner 	break;
1575db2f26eSSascha Wildner     }
1585db2f26eSSascha Wildner 
1595db2f26eSSascha Wildner     return (h);
1605db2f26eSSascha Wildner }
161