aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/man/man9/BUS_GET_PROPERTY.965
-rw-r--r--share/man/man9/Makefile2
-rw-r--r--share/man/man9/device_get_property.967
-rw-r--r--sys/dev/acpica/acpi.c37
-rw-r--r--sys/dev/fdt/simplebus.c16
-rw-r--r--sys/kern/bus_if.m31
-rw-r--r--sys/kern/subr_bus.c14
-rw-r--r--sys/sys/bus.h2
8 files changed, 234 insertions, 0 deletions
diff --git a/share/man/man9/BUS_GET_PROPERTY.9 b/share/man/man9/BUS_GET_PROPERTY.9
new file mode 100644
index 000000000000..89edbd95b68c
--- /dev/null
+++ b/share/man/man9/BUS_GET_PROPERTY.9
@@ -0,0 +1,65 @@
+.\" -
+.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+.\"
+.\" Copyright (c) 2021 Semihalf
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 19, 2021
+.Dt BUS_GET_PROPERTY 9
+.Os
+.Sh NAME
+.Nm BUS_GET_PROPERTY
+.Nd get child's specific property
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/bus.h
+.Ft ssize_t
+.Fn BUS_GET_PROPERTY "device_t dev" "device_t child" "const char *propname" \
+ "void *propvalue" "size_t size"
+.Sh DESCRIPTION
+The
+.Fn BUS_GET_PROPERTY
+method
+is called from driver code which wants to access child's specific data stored
+on the bus.
+Property consits of its name and value.
+Implementation shall copy to
+.Fa propvalue
+at most
+.Fa size
+bytes.
+.Sh NOTES
+If
+.Fa propvalue
+is NULL or
+.Fa size
+is zero, then implementation shall only return size of the property.
+.Sh RETURN VALUES
+Property's size if successful, otherwise -1.
+.Sh SEE ALSO
+.Xr device 9 ,
+.Xr device_get_property 9
+.Sh AUTHORS
+This manual page was written by
+.An Bartlomiej Grzesik .
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index 4764db983f8a..30632e0a6cb6 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -47,6 +47,7 @@ MAN= accept_filter.9 \
bus_generic_read_ivar.9 \
bus_generic_shutdown.9 \
BUS_GET_CPUS.9 \
+ BUS_GET_PROPERTY.9 \
bus_get_resource.9 \
bus_map_resource.9 \
BUS_NEW_PASS.9 \
@@ -108,6 +109,7 @@ MAN= accept_filter.9 \
device_get_ivars.9 \
device_get_name.9 \
device_get_parent.9 \
+ device_get_property.9 \
device_get_softc.9 \
device_get_state.9 \
device_get_sysctl.9 \
diff --git a/share/man/man9/device_get_property.9 b/share/man/man9/device_get_property.9
new file mode 100644
index 000000000000..1d9bd5058b1a
--- /dev/null
+++ b/share/man/man9/device_get_property.9
@@ -0,0 +1,67 @@
+.\" -
+.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+.\"
+.\" Copyright (c) 2021 Semihalf
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 19, 2021
+.Dt DEVICE_GET_PROPERTY 9
+.Os
+.Sh NAME
+.Nm device_get_property ,
+.Nm device_has_property
+.Nd access device specific data
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/bus.h
+.Ft ssize_t
+.Fn device_get_property "device_t dev" "const char *prop" "void *val" "size_t sz"
+.Ft bool
+.Fn device_has_property "device_t dev" "const char *prop"
+.Sh DESCRIPTION
+Access device specific data provided by the parent bus.
+Drivers can use these properties to obtain device capabilities and set
+necessary quirks.
+.Sh NOTES
+You can pass NULL as pointer to property's value when calling
+.Fn device_get_property
+to obtain its size.
+.Pp
+Currently this interface is implemented by
+.Xr simplebus 4
+and
+.Xr acpi 4 .
+.Sh RETURN VALUES
+.Fn device_get_property
+if successful returns property's size, otherwise returns -1.
+.Pp
+.Fn device_has_property
+returns true if given property was found.
+.Sh SEE ALSO
+.Xr acpi 4 ,
+.Xr simplebus 4 ,
+.Xr device 9
+.Sh AUTHORS
+This manual page was written by
+.An Bartlomiej Grzesik .
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 40b928f9cdd6..5d2b895bbe88 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -144,6 +144,8 @@ static void acpi_delete_resource(device_t bus, device_t child, int type,
int rid);
static uint32_t acpi_isa_get_logicalid(device_t dev);
static int acpi_isa_get_compatid(device_t dev, uint32_t *cids, int count);
+static ssize_t acpi_bus_get_prop(device_t bus, device_t child, const char *propname,
+ void *propvalue, size_t size);
static int acpi_device_id_probe(device_t bus, device_t dev, char **ids, char **match);
static ACPI_STATUS acpi_device_eval_obj(device_t bus, device_t dev,
ACPI_STRING pathname, ACPI_OBJECT_LIST *parameters,
@@ -223,6 +225,7 @@ static device_method_t acpi_methods[] = {
DEVMETHOD(bus_hint_device_unit, acpi_hint_device_unit),
DEVMETHOD(bus_get_cpus, acpi_get_cpus),
DEVMETHOD(bus_get_domain, acpi_get_domain),
+ DEVMETHOD(bus_get_property, acpi_bus_get_prop),
/* ACPI bus */
DEVMETHOD(acpi_id_probe, acpi_device_id_probe),
@@ -1817,6 +1820,40 @@ acpi_find_dsd(device_t bus, device_t dev)
return (AE_NOT_FOUND);
}
+static ssize_t
+acpi_bus_get_prop(device_t bus, device_t child, const char *propname,
+ void *propvalue, size_t size)
+{
+ ACPI_STATUS status;
+ const ACPI_OBJECT *obj;
+
+ status = acpi_device_get_prop(bus, child, __DECONST(char *, propname),
+ &obj);
+ if (ACPI_FAILURE(status))
+ return (-1);
+
+ switch (obj->Type) {
+ case ACPI_TYPE_INTEGER:
+ if (propvalue != NULL && size >= sizeof(uint64_t))
+ *((uint64_t *) propvalue) = obj->Integer.Value;
+ return (sizeof(uint64_t));
+
+ case ACPI_TYPE_STRING:
+ if (propvalue != NULL && size > 0)
+ memcpy(propvalue, obj->String.Pointer,
+ MIN(size, obj->String.Length));
+ return (obj->String.Length);
+
+ case ACPI_TYPE_BUFFER:
+ if (propvalue != NULL && size > 0)
+ memcpy(propvalue, obj->Buffer.Pointer,
+ MIN(size, obj->Buffer.Length));
+ return (obj->Buffer.Length);
+ }
+
+ return (-1);
+}
+
int
acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate)
{
diff --git a/sys/dev/fdt/simplebus.c b/sys/dev/fdt/simplebus.c
index 76814ed40b04..4d58f9b3ea69 100644
--- a/sys/dev/fdt/simplebus.c
+++ b/sys/dev/fdt/simplebus.c
@@ -54,6 +54,9 @@ static device_t simplebus_add_child(device_t dev, u_int order,
const char *name, int unit);
static struct resource_list *simplebus_get_resource_list(device_t bus,
device_t child);
+
+static ssize_t simplebus_get_property(device_t bus, device_t child,
+ const char *propname, void *propvalue, size_t size);
/*
* ofw_bus interface
*/
@@ -89,6 +92,7 @@ static device_method_t simplebus_methods[] = {
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_child_pnpinfo, ofw_bus_gen_child_pnpinfo),
DEVMETHOD(bus_get_resource_list, simplebus_get_resource_list),
+ DEVMETHOD(bus_get_property, simplebus_get_property),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, simplebus_get_devinfo),
@@ -350,6 +354,18 @@ simplebus_get_resource_list(device_t bus __unused, device_t child)
return (&ndi->rl);
}
+static ssize_t
+simplebus_get_property(device_t bus, device_t child, const char *propname,
+ void *propvalue, size_t size)
+{
+ phandle_t node = ofw_bus_get_node(child);
+
+ if (propvalue == NULL || size == 0)
+ return (OF_getproplen(node, propname));
+
+ return (OF_getencprop(node, propname, propvalue, size));
+}
+
static struct resource *
simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m
index 71d83954ef4d..0bd7056019ab 100644
--- a/sys/kern/bus_if.m
+++ b/sys/kern/bus_if.m
@@ -88,6 +88,13 @@ CODE {
*newstart = start;
return (0);
}
+
+ static ssize_t
+ null_get_property(device_t dev, device_t child, const char *propname,
+ void *propvalue, size_t size)
+ {
+ return (-1);
+ }
};
/**
@@ -924,3 +931,27 @@ METHOD int reset_child {
device_t _child;
int _flags;
};
+
+/**
+ * @brief Gets child's specific property
+ *
+ * The bus_get_property can be used to access device
+ * specific properties stored on the bus. If _propvalue
+ * is NULL or _size is 0, then method only returns size
+ * of the property.
+ *
+ * @param _dev the bus device
+ * @param _child the child device
+ * @param _propname property name
+ * @param _propvalue property value destination
+ * @param _size property value size
+ *
+ * @returns size of property if successful otherwise -1
+ */
+METHOD ssize_t get_property {
+ device_t _dev;
+ device_t _child;
+ const char *_propname;
+ void *_propvalue;
+ size_t _size;
+} DEFAULT null_get_property;
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 77b4c4c66c4b..1f580f455dc0 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -2708,6 +2708,20 @@ device_verbose(device_t dev)
dev->flags &= ~DF_QUIET;
}
+ssize_t
+device_get_property(device_t dev, const char *prop, void *val, size_t sz)
+{
+ device_t bus = device_get_parent(dev);
+
+ return (BUS_GET_PROPERTY(bus, dev, prop, val, sz));
+}
+
+bool
+device_has_property(device_t dev, const char *prop)
+{
+ return (device_get_property(dev, prop, NULL, 0) >= 0);
+}
+
/**
* @brief Return non-zero if the DF_QUIET_CHIDLREN flag is set on the device
*/
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index c9ac84020ba5..ff86cbcf457f 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -631,6 +631,8 @@ int device_set_unit(device_t dev, int unit); /* XXX DONT USE XXX */
int device_shutdown(device_t dev);
void device_unbusy(device_t dev);
void device_verbose(device_t dev);
+ssize_t device_get_property(device_t dev, const char *prop, void *val, size_t sz);
+bool device_has_property(device_t dev, const char *prop);
/*
* Access functions for devclass.