xref: /freebsd/sys/kern/subr_hints.c (revision 74e620476c8140d8fef018875de23ec6c8f1038f)
12398f0cdSPeter Wemm /*-
22398f0cdSPeter Wemm  * Copyright (c) 2000,2001 Peter Wemm <peter@FreeBSD.org>
32398f0cdSPeter Wemm  * All rights reserved.
42398f0cdSPeter Wemm  *
52398f0cdSPeter Wemm  * Redistribution and use in source and binary forms, with or without
62398f0cdSPeter Wemm  * modification, are permitted provided that the following conditions
72398f0cdSPeter Wemm  * are met:
82398f0cdSPeter Wemm  * 1. Redistributions of source code must retain the above copyright
92398f0cdSPeter Wemm  *    notice, this list of conditions and the following disclaimer.
102398f0cdSPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
112398f0cdSPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
122398f0cdSPeter Wemm  *    documentation and/or other materials provided with the distribution.
132398f0cdSPeter Wemm  *
142398f0cdSPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
152398f0cdSPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162398f0cdSPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
172398f0cdSPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
182398f0cdSPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
192398f0cdSPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
202398f0cdSPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212398f0cdSPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222398f0cdSPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232398f0cdSPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242398f0cdSPeter Wemm  * SUCH DAMAGE.
252398f0cdSPeter Wemm  */
262398f0cdSPeter Wemm 
27677b542eSDavid E. O'Brien #include <sys/cdefs.h>
28677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
29677b542eSDavid E. O'Brien 
302398f0cdSPeter Wemm #include <sys/param.h>
31d786139cSMaxime Henrion #include <sys/lock.h>
32d786139cSMaxime Henrion #include <sys/sx.h>
332398f0cdSPeter Wemm #include <sys/systm.h>
342398f0cdSPeter Wemm #include <sys/bus.h>
352398f0cdSPeter Wemm 
362398f0cdSPeter Wemm /*
372398f0cdSPeter Wemm  * Access functions for device resources.
382398f0cdSPeter Wemm  */
392398f0cdSPeter Wemm 
40d786139cSMaxime Henrion static int checkmethod = 1;
414f033348SPeter Wemm static int use_kenv;
429516fbd6SPeter Wemm static char *hintp;
432398f0cdSPeter Wemm 
442398f0cdSPeter Wemm /*
452398f0cdSPeter Wemm  * Evil wildcarding resource string lookup.
462398f0cdSPeter Wemm  * This walks the supplied env string table and returns a match.
472398f0cdSPeter Wemm  * The start point can be remembered for incremental searches.
482398f0cdSPeter Wemm  */
492398f0cdSPeter Wemm static int
509516fbd6SPeter Wemm res_find(int *line, int *startln,
512398f0cdSPeter Wemm     const char *name, int *unit, const char *resname, const char *value,
522398f0cdSPeter Wemm     const char **ret_name, int *ret_namelen, int *ret_unit,
532398f0cdSPeter Wemm     const char **ret_resname, int *ret_resnamelen, const char **ret_value)
542398f0cdSPeter Wemm {
554f033348SPeter Wemm 	int n = 0, hit, i = 0;
562398f0cdSPeter Wemm 	char r_name[32];
572398f0cdSPeter Wemm 	int r_unit;
582398f0cdSPeter Wemm 	char r_resname[32];
592398f0cdSPeter Wemm 	char r_value[128];
609516fbd6SPeter Wemm 	const char *s, *cp;
612398f0cdSPeter Wemm 	char *p;
622398f0cdSPeter Wemm 
63d786139cSMaxime Henrion 	if (checkmethod) {
649516fbd6SPeter Wemm 		switch (hintmode) {
656692ac66SPeter Wemm 		case 0:		/* loader hints in environment only */
669516fbd6SPeter Wemm 			break;
679516fbd6SPeter Wemm 		case 1:		/* static hints only */
689516fbd6SPeter Wemm 			hintp = static_hints;
69d786139cSMaxime Henrion 			checkmethod = 0;
709516fbd6SPeter Wemm 			break;
719516fbd6SPeter Wemm 		case 2:		/* fallback mode */
72d786139cSMaxime Henrion 			if (dynamic_kenv) {
73d786139cSMaxime Henrion 				sx_slock(&kenv_lock);
74d786139cSMaxime Henrion 				cp = kenvp[0];
75d786139cSMaxime Henrion 				for (i = 0; cp != NULL; cp = kenvp[++i]) {
76d786139cSMaxime Henrion 					if (!strncmp(cp, "hint.", 5)) {
77d786139cSMaxime Henrion 						use_kenv = 1;
78d786139cSMaxime Henrion 						checkmethod = 0;
79d786139cSMaxime Henrion 						break;
80d786139cSMaxime Henrion 					}
81d786139cSMaxime Henrion 				}
82d786139cSMaxime Henrion 				sx_sunlock(&kenv_lock);
83d786139cSMaxime Henrion 			} else {
849516fbd6SPeter Wemm 				cp = kern_envp;
859516fbd6SPeter Wemm 				while (cp) {
869516fbd6SPeter Wemm 					if (strncmp(cp, "hint.", 5) == 0) {
879516fbd6SPeter Wemm 						cp = NULL;
889516fbd6SPeter Wemm 						hintp = kern_envp;
899516fbd6SPeter Wemm 						break;
909516fbd6SPeter Wemm 					}
919516fbd6SPeter Wemm 					while (*cp != '\0')
929516fbd6SPeter Wemm 						cp++;
939516fbd6SPeter Wemm 					cp++;
949516fbd6SPeter Wemm 					if (*cp == '\0') {
959516fbd6SPeter Wemm 						cp = NULL;
969516fbd6SPeter Wemm 						hintp = static_hints;
979516fbd6SPeter Wemm 						break;
989516fbd6SPeter Wemm 					}
999516fbd6SPeter Wemm 				}
100d786139cSMaxime Henrion 			}
1019516fbd6SPeter Wemm 			break;
1029516fbd6SPeter Wemm 		default:
1039516fbd6SPeter Wemm 			break;
1049516fbd6SPeter Wemm 		}
105d786139cSMaxime Henrion 		if (hintp == NULL) {
106d786139cSMaxime Henrion 			if (dynamic_kenv) {
107d786139cSMaxime Henrion 				use_kenv = 1;
108d786139cSMaxime Henrion 				checkmethod = 0;
109d786139cSMaxime Henrion 			} else
1109516fbd6SPeter Wemm 				hintp = kern_envp;
1119516fbd6SPeter Wemm 		}
112d786139cSMaxime Henrion 	}
1139516fbd6SPeter Wemm 
114d786139cSMaxime Henrion 	if (use_kenv) {
115d786139cSMaxime Henrion 		sx_slock(&kenv_lock);
116d786139cSMaxime Henrion 		i = 0;
117d786139cSMaxime Henrion 		cp = kenvp[0];
118d786139cSMaxime Henrion 		if (cp == NULL) {
119d786139cSMaxime Henrion 			sx_sunlock(&kenv_lock);
120d786139cSMaxime Henrion 			return (ENOENT);
121d786139cSMaxime Henrion 		}
1226692ac66SPeter Wemm 	} else
1239516fbd6SPeter Wemm 		cp = hintp;
1242398f0cdSPeter Wemm 	while (cp) {
1252398f0cdSPeter Wemm 		hit = 1;
1262398f0cdSPeter Wemm 		(*line)++;
1272398f0cdSPeter Wemm 		if (strncmp(cp, "hint.", 5) != 0)
1282398f0cdSPeter Wemm 			hit = 0;
1292398f0cdSPeter Wemm 		else
1302398f0cdSPeter Wemm 			n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%128s",
1312398f0cdSPeter Wemm 			    r_name, &r_unit, r_resname, r_value);
1322398f0cdSPeter Wemm 		if (hit && n != 4) {
1332398f0cdSPeter Wemm 			printf("CONFIG: invalid hint '%s'\n", cp);
1342398f0cdSPeter Wemm 			/* XXX: abuse bogus index() declaration */
1352398f0cdSPeter Wemm 			p = index(cp, 'h');
1362398f0cdSPeter Wemm 			*p = 'H';
1372398f0cdSPeter Wemm 			hit = 0;
1382398f0cdSPeter Wemm 		}
1392398f0cdSPeter Wemm 		if (hit && startln && *startln >= 0 && *line < *startln)
1402398f0cdSPeter Wemm 			hit = 0;
1412398f0cdSPeter Wemm 		if (hit && name && strcmp(name, r_name) != 0)
1422398f0cdSPeter Wemm 			hit = 0;
1432398f0cdSPeter Wemm 		if (hit && unit && *unit != r_unit)
1442398f0cdSPeter Wemm 			hit = 0;
1452398f0cdSPeter Wemm 		if (hit && resname && strcmp(resname, r_resname) != 0)
1462398f0cdSPeter Wemm 			hit = 0;
1472398f0cdSPeter Wemm 		if (hit && value && strcmp(value, r_value) != 0)
1482398f0cdSPeter Wemm 			hit = 0;
1492398f0cdSPeter Wemm 		if (hit)
1502398f0cdSPeter Wemm 			break;
1514f033348SPeter Wemm 		if (use_kenv) {
152d786139cSMaxime Henrion 			cp = kenvp[++i];
1534f033348SPeter Wemm 			if (cp == NULL)
1544f033348SPeter Wemm 				break;
1554f033348SPeter Wemm 		} else {
1562398f0cdSPeter Wemm 			while (*cp != '\0')
1572398f0cdSPeter Wemm 				cp++;
1582398f0cdSPeter Wemm 			cp++;
1592398f0cdSPeter Wemm 			if (*cp == '\0') {
1602398f0cdSPeter Wemm 				cp = NULL;
1612398f0cdSPeter Wemm 				break;
1622398f0cdSPeter Wemm 			}
1632398f0cdSPeter Wemm 		}
1644f033348SPeter Wemm 	}
165d786139cSMaxime Henrion 	if (use_kenv)
166d786139cSMaxime Henrion 		sx_sunlock(&kenv_lock);
1672398f0cdSPeter Wemm 	if (cp == NULL)
1682398f0cdSPeter Wemm 		return ENOENT;
1692398f0cdSPeter Wemm 
1702398f0cdSPeter Wemm 	s = cp;
1712398f0cdSPeter Wemm 	/* This is a bit of a hack, but at least is reentrant */
1722398f0cdSPeter Wemm 	/* Note that it returns some !unterminated! strings. */
1732398f0cdSPeter Wemm 	s = index(s, '.') + 1;		/* start of device */
1742398f0cdSPeter Wemm 	if (ret_name)
1752398f0cdSPeter Wemm 		*ret_name = s;
1762398f0cdSPeter Wemm 	s = index(s, '.') + 1;		/* start of unit */
1772398f0cdSPeter Wemm 	if (ret_namelen)
1782398f0cdSPeter Wemm 		*ret_namelen = s - *ret_name - 1; /* device length */
1792398f0cdSPeter Wemm 	if (ret_unit)
1802398f0cdSPeter Wemm 		*ret_unit = r_unit;
1812398f0cdSPeter Wemm 	s = index(s, '.') + 1;		/* start of resname */
1822398f0cdSPeter Wemm 	if (ret_resname)
1832398f0cdSPeter Wemm 		*ret_resname = s;
1842398f0cdSPeter Wemm 	s = index(s, '=') + 1;		/* start of value */
1852398f0cdSPeter Wemm 	if (ret_resnamelen)
1862398f0cdSPeter Wemm 		*ret_resnamelen = s - *ret_resname - 1; /* value len */
1872398f0cdSPeter Wemm 	if (ret_value)
1882398f0cdSPeter Wemm 		*ret_value = s;
1892398f0cdSPeter Wemm 	if (startln)			/* line number for anchor */
1902398f0cdSPeter Wemm 		*startln = *line + 1;
1912398f0cdSPeter Wemm 	return 0;
1922398f0cdSPeter Wemm }
1932398f0cdSPeter Wemm 
1942398f0cdSPeter Wemm /*
1952398f0cdSPeter Wemm  * Search all the data sources for matches to our query.  We look for
1962398f0cdSPeter Wemm  * dynamic hints first as overrides for static or fallback hints.
1972398f0cdSPeter Wemm  */
1982398f0cdSPeter Wemm static int
1992398f0cdSPeter Wemm resource_find(int *line, int *startln,
2002398f0cdSPeter Wemm     const char *name, int *unit, const char *resname, const char *value,
2012398f0cdSPeter Wemm     const char **ret_name, int *ret_namelen, int *ret_unit,
2022398f0cdSPeter Wemm     const char **ret_resname, int *ret_resnamelen, const char **ret_value)
2032398f0cdSPeter Wemm {
2042398f0cdSPeter Wemm 	int i;
2052398f0cdSPeter Wemm 	int un;
2062398f0cdSPeter Wemm 
2072398f0cdSPeter Wemm 	*line = 0;
2082398f0cdSPeter Wemm 
2092398f0cdSPeter Wemm 	/* Search for exact unit matches first */
2109516fbd6SPeter Wemm 	i = res_find(line, startln, name, unit, resname, value,
2112398f0cdSPeter Wemm 	    ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
2122398f0cdSPeter Wemm 	    ret_value);
2132398f0cdSPeter Wemm 	if (i == 0)
2142398f0cdSPeter Wemm 		return 0;
2152398f0cdSPeter Wemm 	if (unit == NULL)
2162398f0cdSPeter Wemm 		return ENOENT;
2172398f0cdSPeter Wemm 	/* If we are still here, search for wildcard matches */
2182398f0cdSPeter Wemm 	un = -1;
2199516fbd6SPeter Wemm 	i = res_find(line, startln, name, &un, resname, value,
2202398f0cdSPeter Wemm 	    ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
2212398f0cdSPeter Wemm 	    ret_value);
2222398f0cdSPeter Wemm 	if (i == 0)
2232398f0cdSPeter Wemm 		return 0;
2242398f0cdSPeter Wemm 	return ENOENT;
2252398f0cdSPeter Wemm }
2262398f0cdSPeter Wemm 
2272398f0cdSPeter Wemm int
2282398f0cdSPeter Wemm resource_int_value(const char *name, int unit, const char *resname, int *result)
2292398f0cdSPeter Wemm {
2302398f0cdSPeter Wemm 	int error;
2312398f0cdSPeter Wemm 	const char *str;
2322398f0cdSPeter Wemm 	char *op;
2332398f0cdSPeter Wemm 	unsigned long val;
2342398f0cdSPeter Wemm 	int line;
2352398f0cdSPeter Wemm 
2362398f0cdSPeter Wemm 	line = 0;
2372398f0cdSPeter Wemm 	error = resource_find(&line, NULL, name, &unit, resname, NULL,
2382398f0cdSPeter Wemm 	    NULL, NULL, NULL, NULL, NULL, &str);
2392398f0cdSPeter Wemm 	if (error)
2402398f0cdSPeter Wemm 		return error;
2412398f0cdSPeter Wemm 	if (*str == '\0')
2422398f0cdSPeter Wemm 		return EFTYPE;
2432398f0cdSPeter Wemm 	val = strtoul(str, &op, 0);
2442398f0cdSPeter Wemm 	if (*op != '\0')
2452398f0cdSPeter Wemm 		return EFTYPE;
2462398f0cdSPeter Wemm 	*result = val;
2472398f0cdSPeter Wemm 	return 0;
2482398f0cdSPeter Wemm }
2492398f0cdSPeter Wemm 
2502398f0cdSPeter Wemm int
2512398f0cdSPeter Wemm resource_long_value(const char *name, int unit, const char *resname,
2522398f0cdSPeter Wemm     long *result)
2532398f0cdSPeter Wemm {
2542398f0cdSPeter Wemm 	int error;
2552398f0cdSPeter Wemm 	const char *str;
2562398f0cdSPeter Wemm 	char *op;
2572398f0cdSPeter Wemm 	unsigned long val;
2582398f0cdSPeter Wemm 	int line;
2592398f0cdSPeter Wemm 
2602398f0cdSPeter Wemm 	line = 0;
2612398f0cdSPeter Wemm 	error = resource_find(&line, NULL, name, &unit, resname, NULL,
2622398f0cdSPeter Wemm 	    NULL, NULL, NULL, NULL, NULL, &str);
2632398f0cdSPeter Wemm 	if (error)
2642398f0cdSPeter Wemm 		return error;
2652398f0cdSPeter Wemm 	if (*str == '\0')
2662398f0cdSPeter Wemm 		return EFTYPE;
2672398f0cdSPeter Wemm 	val = strtoul(str, &op, 0);
2682398f0cdSPeter Wemm 	if (*op != '\0')
2692398f0cdSPeter Wemm 		return EFTYPE;
2702398f0cdSPeter Wemm 	*result = val;
2712398f0cdSPeter Wemm 	return 0;
2722398f0cdSPeter Wemm }
2732398f0cdSPeter Wemm 
2742398f0cdSPeter Wemm int
2752398f0cdSPeter Wemm resource_string_value(const char *name, int unit, const char *resname,
2762398f0cdSPeter Wemm     const char **result)
2772398f0cdSPeter Wemm {
2782398f0cdSPeter Wemm 	int error;
2792398f0cdSPeter Wemm 	const char *str;
2802398f0cdSPeter Wemm 	int line;
2812398f0cdSPeter Wemm 
2822398f0cdSPeter Wemm 	line = 0;
2832398f0cdSPeter Wemm 	error = resource_find(&line, NULL, name, &unit, resname, NULL,
2842398f0cdSPeter Wemm 	    NULL, NULL, NULL, NULL, NULL, &str);
2852398f0cdSPeter Wemm 	if (error)
2862398f0cdSPeter Wemm 		return error;
2872398f0cdSPeter Wemm 	*result = str;
2882398f0cdSPeter Wemm 	return 0;
2892398f0cdSPeter Wemm }
2902398f0cdSPeter Wemm 
2912398f0cdSPeter Wemm /*
2922398f0cdSPeter Wemm  * This is a bit nasty, but allows us to not modify the env strings.
2932398f0cdSPeter Wemm  */
2942398f0cdSPeter Wemm static const char *
2952398f0cdSPeter Wemm resource_string_copy(const char *s, int len)
2962398f0cdSPeter Wemm {
2972398f0cdSPeter Wemm 	static char stringbuf[256];
2982398f0cdSPeter Wemm 	static int offset = 0;
2992398f0cdSPeter Wemm 	const char *ret;
3002398f0cdSPeter Wemm 
3012398f0cdSPeter Wemm 	if (len == 0)
3022398f0cdSPeter Wemm 		len = strlen(s);
3032398f0cdSPeter Wemm 	if (len > 255)
3042398f0cdSPeter Wemm 		return NULL;
3052398f0cdSPeter Wemm 	if ((offset + len + 1) > 255)
3062398f0cdSPeter Wemm 		offset = 0;
3072398f0cdSPeter Wemm 	bcopy(s, &stringbuf[offset], len);
3082398f0cdSPeter Wemm 	stringbuf[offset + len] = '\0';
3092398f0cdSPeter Wemm 	ret = &stringbuf[offset];
3102398f0cdSPeter Wemm 	offset += len + 1;
3112398f0cdSPeter Wemm 	return ret;
3122398f0cdSPeter Wemm }
3132398f0cdSPeter Wemm 
3142398f0cdSPeter Wemm /*
31574e62047SJohn-Mark Gurney  * err = resource_find_match(&anchor, &name, &unit, resname, value)
3162398f0cdSPeter Wemm  * Iteratively fetch a list of devices wired "at" something
3172398f0cdSPeter Wemm  * res and value are restrictions.  eg: "at", "scbus0".
3182398f0cdSPeter Wemm  * For practical purposes, res = required, value = optional.
3192398f0cdSPeter Wemm  * *name and *unit are set.
3202398f0cdSPeter Wemm  * set *anchor to zero before starting.
3212398f0cdSPeter Wemm  */
3222398f0cdSPeter Wemm int
3232398f0cdSPeter Wemm resource_find_match(int *anchor, const char **name, int *unit,
3242398f0cdSPeter Wemm     const char *resname, const char *value)
3252398f0cdSPeter Wemm {
3262398f0cdSPeter Wemm 	const char *found_name;
3272398f0cdSPeter Wemm 	int found_namelen;
3282398f0cdSPeter Wemm 	int found_unit;
3292398f0cdSPeter Wemm 	int ret;
3302398f0cdSPeter Wemm 	int newln;
3312398f0cdSPeter Wemm 
3322398f0cdSPeter Wemm 	newln = *anchor;
3332398f0cdSPeter Wemm 	ret = resource_find(anchor, &newln, NULL, NULL, resname, value,
3342398f0cdSPeter Wemm 	    &found_name, &found_namelen, &found_unit, NULL, NULL, NULL);
3352398f0cdSPeter Wemm 	if (ret == 0) {
3362398f0cdSPeter Wemm 		*name = resource_string_copy(found_name, found_namelen);
3372398f0cdSPeter Wemm 		*unit = found_unit;
3382398f0cdSPeter Wemm 	}
3392398f0cdSPeter Wemm 	*anchor = newln;
3402398f0cdSPeter Wemm 	return ret;
3412398f0cdSPeter Wemm }
3422398f0cdSPeter Wemm 
3432398f0cdSPeter Wemm 
3442398f0cdSPeter Wemm /*
3452398f0cdSPeter Wemm  * err = resource_find_dev(&anchor, name, &unit, res, value);
3462398f0cdSPeter Wemm  * Iterate through a list of devices, returning their unit numbers.
3472398f0cdSPeter Wemm  * res and value are optional restrictions.  eg: "at", "scbus0".
3482398f0cdSPeter Wemm  * *unit is set to the value.
3492398f0cdSPeter Wemm  * set *anchor to zero before starting.
3502398f0cdSPeter Wemm  */
3512398f0cdSPeter Wemm int
3522398f0cdSPeter Wemm resource_find_dev(int *anchor, const char *name, int *unit,
3532398f0cdSPeter Wemm     const char *resname, const char *value)
3542398f0cdSPeter Wemm {
3552398f0cdSPeter Wemm 	int found_unit;
3562398f0cdSPeter Wemm 	int newln;
3572398f0cdSPeter Wemm 	int ret;
3582398f0cdSPeter Wemm 
3592398f0cdSPeter Wemm 	newln = *anchor;
3602398f0cdSPeter Wemm 	ret = resource_find(anchor, &newln, name, NULL, resname, value,
3612398f0cdSPeter Wemm 	    NULL, NULL, &found_unit, NULL, NULL, NULL);
3622398f0cdSPeter Wemm 	if (ret == 0) {
3632398f0cdSPeter Wemm 		*unit = found_unit;
3642398f0cdSPeter Wemm 	}
3652398f0cdSPeter Wemm 	*anchor = newln;
3662398f0cdSPeter Wemm 	return ret;
3672398f0cdSPeter Wemm }
3686591b310SJohn Baldwin 
3696591b310SJohn Baldwin /*
3706591b310SJohn Baldwin  * Check to see if a device is disabled via a disabled hint.
3716591b310SJohn Baldwin  */
3726591b310SJohn Baldwin int
3736591b310SJohn Baldwin resource_disabled(const char *name, int unit)
3746591b310SJohn Baldwin {
3756591b310SJohn Baldwin 	int error, value;
3766591b310SJohn Baldwin 
3776591b310SJohn Baldwin 	error = resource_int_value(name, unit, "disabled", &value);
3786591b310SJohn Baldwin 	if (error)
3796591b310SJohn Baldwin 	       return (0);
3806591b310SJohn Baldwin 	return (value);
3816591b310SJohn Baldwin }
382