Add device_compatible_match(), a generalized routine for weighted

matching of device_compatible_entry data to a device's "compatible"
strings.
This commit is contained in:
thorpej 2018-06-18 15:36:54 +00:00
parent 8adf28c539
commit 3afafc8ac9
2 changed files with 71 additions and 3 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr_autoconf.c,v 1.257 2018/03/04 07:12:18 mlelstv Exp $ */
/* $NetBSD: subr_autoconf.c,v 1.258 2018/06/18 15:36:54 thorpej Exp $ */
/*
* Copyright (c) 1996, 2000 Christopher G. Demetriou
@ -77,7 +77,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.257 2018/03/04 07:12:18 mlelstv Exp $");
__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.258 2018/06/18 15:36:54 thorpej Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@ -2274,6 +2274,69 @@ device_find_by_driver_unit(const char *name, int unit)
return device_lookup(cd, unit);
}
/*
* device_compatible_entry_matches:
*
* Helper function to determine if a device_compatible_entry
* contains a match for the specified "compatible" string.
*/
static bool
device_compatible_entry_matches(const struct device_compatible_entry *dce,
const char *compatible)
{
const char **cpp = DEVICE_COMPAT_ENTRY_GET_STRINGS(dce);
if (cpp == NULL)
return false;
while (*cpp != NULL)
if (strcmp(*cpp, compatible) == 0)
return true;
return false;
}
/*
* device_compatible_match:
*
* Match a driver's "compatible" data against a device's
* "compatible" strings. If a match is found, we return
* the matching device_compatible_entry, along with a
* matching weight.
*/
const struct device_compatible_entry *
device_compatible_match(const char **device_compats, int ndevice_compats,
const struct device_compatible_entry *driver_compats,
int *match_weightp)
{
const struct device_compatible_entry *dce = NULL;
int i, match_weight;
if (ndevice_compats == 0 || device_compats == NULL ||
driver_compats == NULL)
return NULL;
/*
* We take the first match because we start with the most-specific
* device compatible string.
*/
for (i = 0, match_weight = ndevice_compats - 1;
i < ndevice_compats;
i++, match_weight--) {
for (dce = driver_compats;
DEVICE_COMPAT_ENTRY_IS_TERMINATOR(dce) == false; dce++) {
if (device_compatible_entry_matches(dce,
device_compats[i])) {
KASSERT(match_weight >= 0);
if (match_weightp)
*match_weightp = match_weight;
return dce;
}
}
}
return NULL;
}
/*
* Power management related functions.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: device.h,v 1.152 2018/06/17 15:06:27 thorpej Exp $ */
/* $NetBSD: device.h,v 1.153 2018/06/18 15:36:54 thorpej Exp $ */
/*
* Copyright (c) 1996, 2000 Christopher G. Demetriou
@ -552,6 +552,11 @@ bool device_is_a(device_t, const char *);
device_t device_find_by_xname(const char *);
device_t device_find_by_driver_unit(const char *, int);
const struct device_compatible_entry *
device_compatible_match(const char **, int,
const struct device_compatible_entry *,
int *);
bool device_pmf_is_registered(device_t);
bool device_pmf_driver_suspend(device_t, const pmf_qual_t *);