1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-11 09:50:12 +00:00

device: add device_get_property and device_has_property

Generialize bus specific property accessors. Those functions allow driver code
to access device specific information.

Currently there is only support for FDT and ACPI buses.

Reviewed by: manu, mw
Sponsored by: Semihalf
Differential revision: https://reviews.freebsd.org/D31597
This commit is contained in:
Bartlomiej Grzesik 2021-07-30 10:57:06 +02:00 committed by Marcin Wojtas
parent b91fc6c43a
commit 3f9a00e3b5
8 changed files with 234 additions and 0 deletions

View File

@ -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 .

View File

@ -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 \

View File

@ -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 .

View File

@ -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)
{

View File

@ -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)

View File

@ -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;

View File

@ -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
*/

View File

@ -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.