device_get_property: add a HANDLE case

This will resolve a reference and return the appropriate handle, a node
on the simplebus or an ACPI_HANDLE for ACPI.  For now we do not try to
further abstract the return type.

MFC after:	2 weeks
Reviewed by:	mw
Differential Revision: https://reviews.freebsd.org/D36793
This commit is contained in:
Bjoern A. Zeeb 2022-09-29 12:41:58 +00:00
parent 1fcc50004c
commit 99e6980fcf
5 changed files with 70 additions and 3 deletions

View File

@ -25,7 +25,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd February 18, 2022 .Dd September 29, 2022
.Dt DEVICE_GET_PROPERTY 9 .Dt DEVICE_GET_PROPERTY 9
.Os .Os
.Sh NAME .Sh NAME
@ -54,6 +54,9 @@ Currently the following types are supported:
The underlying property is a string of bytes. The underlying property is a string of bytes.
.It Dv DEVICE_PROP_ANY .It Dv DEVICE_PROP_ANY
Wildcard property type. Wildcard property type.
.It Dv DEVICE_PROP_HANDLE
Following a reference the underlying property is a handle of the
respective bus.
.It Dv DEVICE_PROP_UINT32 .It Dv DEVICE_PROP_UINT32
The underlying property is an array of unsigned 32 bit integers. The underlying property is an array of unsigned 32 bit integers.
The The

View File

@ -1923,6 +1923,35 @@ acpi_find_dsd(struct acpi_device *ad)
return (AE_NOT_FOUND); return (AE_NOT_FOUND);
} }
static ssize_t
acpi_bus_get_prop_handle(const ACPI_OBJECT *hobj, void *propvalue, size_t size)
{
ACPI_OBJECT *pobj;
ACPI_HANDLE h;
if (hobj->Type != ACPI_TYPE_PACKAGE)
goto err;
if (hobj->Package.Count != 1)
goto err;
pobj = &hobj->Package.Elements[0];
if (pobj == NULL)
goto err;
if (pobj->Type != ACPI_TYPE_LOCAL_REFERENCE)
goto err;
h = acpi_GetReference(NULL, pobj);
if (h == NULL)
goto err;
if (propvalue != NULL && size >= sizeof(ACPI_HANDLE))
*(ACPI_HANDLE *)propvalue = h;
return (sizeof(ACPI_HANDLE));
err:
return (-1);
}
static ssize_t static ssize_t
acpi_bus_get_prop(device_t bus, device_t child, const char *propname, acpi_bus_get_prop(device_t bus, device_t child, const char *propname,
void *propvalue, size_t size, device_property_type_t type) void *propvalue, size_t size, device_property_type_t type)
@ -1941,6 +1970,8 @@ acpi_bus_get_prop(device_t bus, device_t child, const char *propname,
case DEVICE_PROP_UINT32: case DEVICE_PROP_UINT32:
case DEVICE_PROP_UINT64: case DEVICE_PROP_UINT64:
break; break;
case DEVICE_PROP_HANDLE:
return (acpi_bus_get_prop_handle(obj, propvalue, size));
default: default:
return (-1); return (-1);
} }
@ -1972,6 +2003,22 @@ acpi_bus_get_prop(device_t bus, device_t child, const char *propname,
MIN(size, obj->Buffer.Length)); MIN(size, obj->Buffer.Length));
return (obj->Buffer.Length); return (obj->Buffer.Length);
case ACPI_TYPE_PACKAGE:
if (propvalue != NULL && size >= sizeof(ACPI_OBJECT *)) {
*((ACPI_OBJECT **) propvalue) =
__DECONST(ACPI_OBJECT *, obj);
}
return (sizeof(ACPI_OBJECT *));
case ACPI_TYPE_LOCAL_REFERENCE:
if (propvalue != NULL && size >= sizeof(ACPI_HANDLE)) {
ACPI_HANDLE h;
h = acpi_GetReference(NULL,
__DECONST(ACPI_OBJECT *, obj));
memcpy(propvalue, h, sizeof(ACPI_HANDLE));
}
return (sizeof(ACPI_HANDLE));
default: default:
return (0); return (0);
} }

View File

@ -357,7 +357,7 @@ static ssize_t
simplebus_get_property(device_t bus, device_t child, const char *propname, simplebus_get_property(device_t bus, device_t child, const char *propname,
void *propvalue, size_t size, device_property_type_t type) void *propvalue, size_t size, device_property_type_t type)
{ {
phandle_t node = ofw_bus_get_node(child); phandle_t node, xref;
ssize_t ret, i; ssize_t ret, i;
uint32_t *buffer; uint32_t *buffer;
uint64_t val; uint64_t val;
@ -367,11 +367,13 @@ simplebus_get_property(device_t bus, device_t child, const char *propname,
case DEVICE_PROP_BUFFER: case DEVICE_PROP_BUFFER:
case DEVICE_PROP_UINT32: case DEVICE_PROP_UINT32:
case DEVICE_PROP_UINT64: case DEVICE_PROP_UINT64:
case DEVICE_PROP_HANDLE:
break; break;
default: default:
return (-1); return (-1);
} }
node = ofw_bus_get_node(child);
if (propvalue == NULL || size == 0) if (propvalue == NULL || size == 0)
return (OF_getproplen(node, propname)); return (OF_getproplen(node, propname));
@ -402,7 +404,20 @@ simplebus_get_property(device_t bus, device_t child, const char *propname,
((uint64_t *)buffer)[i / 2] = val; ((uint64_t *)buffer)[i / 2] = val;
} }
return (ret); return (ret);
} }
if (type == DEVICE_PROP_HANDLE) {
if (size < sizeof(node))
return (-1);
ret = OF_getencprop(node, propname, &xref, sizeof(xref));
if (ret <= 0)
return (ret);
node = OF_node_from_xref(xref);
if (propvalue != NULL)
*(uint32_t *)propvalue = node;
return (ret);
}
return (OF_getprop(node, propname, propvalue, size)); return (OF_getprop(node, propname, propvalue, size));
} }

View File

@ -2226,6 +2226,7 @@ device_get_property(device_t dev, const char *prop, void *val, size_t sz,
switch (type) { switch (type) {
case DEVICE_PROP_ANY: case DEVICE_PROP_ANY:
case DEVICE_PROP_BUFFER: case DEVICE_PROP_BUFFER:
case DEVICE_PROP_HANDLE: /* Size checks done in implementation. */
break; break;
case DEVICE_PROP_UINT32: case DEVICE_PROP_UINT32:
if (sz % 4 != 0) if (sz % 4 != 0)

View File

@ -72,6 +72,7 @@ typedef enum device_property_type {
DEVICE_PROP_BUFFER = 1, DEVICE_PROP_BUFFER = 1,
DEVICE_PROP_UINT32 = 2, DEVICE_PROP_UINT32 = 2,
DEVICE_PROP_UINT64 = 3, DEVICE_PROP_UINT64 = 3,
DEVICE_PROP_HANDLE = 4,
} device_property_type_t; } device_property_type_t;
/** /**