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