new ofw_search_compatible()

Warner Losh imp at bsdimp.com
Wed Oct 23 14:45:31 UTC 2013


I like this...

For PC Card I took a slightly different tact where I passed in the size of the element and returned a pointer to the element. Each element started with a struct that described what to match. Worked well there, but most of the time all that was looked up was a simple int. A more general solution, but maybe not worth the extra hair, unless you combine it with a probe routine that is 100% driven from tables (which the pc card client drivers were).

The only other nit in the interface is that it requires a NULL terminator. I'd prefer a count of elements, but I could go either way.

Warner

On Oct 23, 2013, at 8:39 AM, Ian Lepore wrote:

> While creating drivers that work for a variety of SoCs, I increasingly
> find myself coding sequences such as:
> 
> 	if (ofw_bus_is_compatible(dev, "fsl,imx51-fec"))
> 		sc->fectype = FECTYPE_IMX51;
> 	else if (ofw_bus_is_compatible(dev, "fsl,imx53-fec"))
> 		sc->fectype = FECTYPE_IMX53;
> 	else if (ofw_bus_is_compatible(dev, "fsl,imx6q-fec"))
> 		sc->fectype = FECTYPE_IMX6;
> 	else
> 		sc->fectype = FECTYPE_GENERIC;
> 
> That's a short list as an example, eventually that driver may support a
> dozen SoCs.  I'd like to add a helper routine that turns this into a
> table lookup, patch attached.  Any objections?  It turns sequences such
> as the above into:
> 
> static struct ofw_compat_data compat_data[] = {
> 	{"fsl,imx51-fec", FECTYPE_IMX51},
> 	{"fsl,imx53-fec", FECTYPE_IMX53},
> 	{"fsl,imx6q-fec", FECTYPE_IMX6},
> 	{NULL,		  FECTYPE_NONE},
> };
> /* ... */
> sc->fectype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
> 
> The search routine by design can't return NULL unless you pass it a NULL
> table pointer.  That lets you provide whatever "not found" value in the
> table-end sentry that works best for the way your code is structured.
> 
> -- Ian
> 
> Index: sys/dev/ofw/ofw_bus_subr.h
> ===================================================================
> --- sys/dev/ofw/ofw_bus_subr.h	(revision 256962)
> +++ sys/dev/ofw/ofw_bus_subr.h	(working copy)
> @@ -47,6 +47,11 @@ struct ofw_bus_iinfo {
> 	pcell_t			opi_addrc;
> };
> 
> +struct ofw_compat_data {
> +	const char	*ocd_str;
> +	uintptr_t	 ocd_data;
> +};
> +
> /* Generic implementation of ofw_bus_if.m methods and helper routines */
> int	ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *, phandle_t);
> void	ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *);
> @@ -74,6 +79,10 @@ void	ofw_bus_find_iparent(phandle_t);
> int ofw_bus_is_compatible(device_t, const char *);
> int ofw_bus_is_compatible_strict(device_t, const char *);
> 
> +/* Helper routine to search a list of compat props. */
> +const struct ofw_compat_data *
> +    ofw_bus_search_compatible(device_t, const struct ofw_compat_data *);
> +
> /* Helper routine for checking existence of a prop */
> int ofw_bus_has_prop(device_t, const char *);
> Index: sys/dev/ofw/ofw_bus_subr.c
> ===================================================================
> --- sys/dev/ofw/ofw_bus_subr.c	(revision 256962)
> +++ sys/dev/ofw/ofw_bus_subr.c	(working copy)
> @@ -197,6 +197,21 @@ ofw_bus_is_compatible_strict(device_t dev, const c
> 	return (0);
> }
> 
> +const struct ofw_compat_data *
> +ofw_bus_search_compatible(device_t dev, const struct ofw_compat_data *compat)
> +{
> +
> +	if (compat == NULL)
> +		return NULL;
> +
> +	for (; compat->ocd_str != NULL; ++compat) {
> +		if (ofw_bus_is_compatible(dev, compat->ocd_str))
> +			break;
> +	}
> +
> +	return (compat);
> +}
> +
> int
> ofw_bus_has_prop(device_t dev, const char *propname)
> {
> 
> _______________________________________________
> freebsd-embedded at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-embedded
> To unsubscribe, send any mail to "freebsd-embedded-unsubscribe at freebsd.org"



More information about the freebsd-embedded mailing list