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:
parent
1fcc50004c
commit
99e6980fcf
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 18, 2022
|
||||
.Dd September 29, 2022
|
||||
.Dt DEVICE_GET_PROPERTY 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -54,6 +54,9 @@ Currently the following types are supported:
|
||||
The underlying property is a string of bytes.
|
||||
.It Dv DEVICE_PROP_ANY
|
||||
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
|
||||
The underlying property is an array of unsigned 32 bit integers.
|
||||
The
|
||||
|
@ -1923,6 +1923,35 @@ acpi_find_dsd(struct acpi_device *ad)
|
||||
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
|
||||
acpi_bus_get_prop(device_t bus, device_t child, const char *propname,
|
||||
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_UINT64:
|
||||
break;
|
||||
case DEVICE_PROP_HANDLE:
|
||||
return (acpi_bus_get_prop_handle(obj, propvalue, size));
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
@ -1972,6 +2003,22 @@ acpi_bus_get_prop(device_t bus, device_t child, const char *propname,
|
||||
MIN(size, 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:
|
||||
return (0);
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ static ssize_t
|
||||
simplebus_get_property(device_t bus, device_t child, const char *propname,
|
||||
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;
|
||||
uint32_t *buffer;
|
||||
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_UINT32:
|
||||
case DEVICE_PROP_UINT64:
|
||||
case DEVICE_PROP_HANDLE:
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
node = ofw_bus_get_node(child);
|
||||
if (propvalue == NULL || size == 0)
|
||||
return (OF_getproplen(node, propname));
|
||||
|
||||
@ -404,6 +406,19 @@ simplebus_get_property(device_t bus, device_t child, const char *propname,
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -2226,6 +2226,7 @@ device_get_property(device_t dev, const char *prop, void *val, size_t sz,
|
||||
switch (type) {
|
||||
case DEVICE_PROP_ANY:
|
||||
case DEVICE_PROP_BUFFER:
|
||||
case DEVICE_PROP_HANDLE: /* Size checks done in implementation. */
|
||||
break;
|
||||
case DEVICE_PROP_UINT32:
|
||||
if (sz % 4 != 0)
|
||||
|
@ -72,6 +72,7 @@ typedef enum device_property_type {
|
||||
DEVICE_PROP_BUFFER = 1,
|
||||
DEVICE_PROP_UINT32 = 2,
|
||||
DEVICE_PROP_UINT64 = 3,
|
||||
DEVICE_PROP_HANDLE = 4,
|
||||
} device_property_type_t;
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user