xref: /freebsd/sys/kern/subr_hints.c (revision dc15eac046a11d0a831eedf97459900227c50fb8)
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>
32e3546a75SScott Long #include <sys/mutex.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) {
6432069af6SAlexander Leidinger 		hintp = NULL;
6532069af6SAlexander Leidinger 
669516fbd6SPeter Wemm 		switch (hintmode) {
676692ac66SPeter Wemm 		case 0:		/* loader hints in environment only */
689516fbd6SPeter Wemm 			break;
699516fbd6SPeter Wemm 		case 1:		/* static hints only */
709516fbd6SPeter Wemm 			hintp = static_hints;
71d786139cSMaxime Henrion 			checkmethod = 0;
729516fbd6SPeter Wemm 			break;
739516fbd6SPeter Wemm 		case 2:		/* fallback mode */
74d786139cSMaxime Henrion 			if (dynamic_kenv) {
75e3546a75SScott Long 				mtx_lock(&kenv_lock);
76d786139cSMaxime Henrion 				cp = kenvp[0];
77d786139cSMaxime Henrion 				for (i = 0; cp != NULL; cp = kenvp[++i]) {
78d786139cSMaxime Henrion 					if (!strncmp(cp, "hint.", 5)) {
79d786139cSMaxime Henrion 						use_kenv = 1;
80d786139cSMaxime Henrion 						checkmethod = 0;
81d786139cSMaxime Henrion 						break;
82d786139cSMaxime Henrion 					}
83d786139cSMaxime Henrion 				}
84e3546a75SScott Long 				mtx_unlock(&kenv_lock);
85d786139cSMaxime Henrion 			} else {
869516fbd6SPeter Wemm 				cp = kern_envp;
879516fbd6SPeter Wemm 				while (cp) {
889516fbd6SPeter Wemm 					if (strncmp(cp, "hint.", 5) == 0) {
899516fbd6SPeter Wemm 						cp = NULL;
909516fbd6SPeter Wemm 						hintp = kern_envp;
919516fbd6SPeter Wemm 						break;
929516fbd6SPeter Wemm 					}
939516fbd6SPeter Wemm 					while (*cp != '\0')
949516fbd6SPeter Wemm 						cp++;
959516fbd6SPeter Wemm 					cp++;
969516fbd6SPeter Wemm 					if (*cp == '\0') {
979516fbd6SPeter Wemm 						cp = NULL;
989516fbd6SPeter Wemm 						hintp = static_hints;
999516fbd6SPeter Wemm 						break;
1009516fbd6SPeter Wemm 					}
1019516fbd6SPeter Wemm 				}
102d786139cSMaxime Henrion 			}
1039516fbd6SPeter Wemm 			break;
1049516fbd6SPeter Wemm 		default:
1059516fbd6SPeter Wemm 			break;
1069516fbd6SPeter Wemm 		}
107d786139cSMaxime Henrion 		if (hintp == NULL) {
108d786139cSMaxime Henrion 			if (dynamic_kenv) {
109d786139cSMaxime Henrion 				use_kenv = 1;
110d786139cSMaxime Henrion 				checkmethod = 0;
111d786139cSMaxime Henrion 			} else
1129516fbd6SPeter Wemm 				hintp = kern_envp;
1139516fbd6SPeter Wemm 		}
114d786139cSMaxime Henrion 	}
1159516fbd6SPeter Wemm 
116d786139cSMaxime Henrion 	if (use_kenv) {
117e3546a75SScott Long 		mtx_lock(&kenv_lock);
118d786139cSMaxime Henrion 		i = 0;
119d786139cSMaxime Henrion 		cp = kenvp[0];
120d786139cSMaxime Henrion 		if (cp == NULL) {
121e3546a75SScott Long 			mtx_unlock(&kenv_lock);
122d786139cSMaxime Henrion 			return (ENOENT);
123d786139cSMaxime Henrion 		}
1246692ac66SPeter Wemm 	} else
1259516fbd6SPeter Wemm 		cp = hintp;
1262398f0cdSPeter Wemm 	while (cp) {
1272398f0cdSPeter Wemm 		hit = 1;
1282398f0cdSPeter Wemm 		(*line)++;
1292398f0cdSPeter Wemm 		if (strncmp(cp, "hint.", 5) != 0)
1302398f0cdSPeter Wemm 			hit = 0;
1312398f0cdSPeter Wemm 		else
1322398f0cdSPeter Wemm 			n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%128s",
1332398f0cdSPeter Wemm 			    r_name, &r_unit, r_resname, r_value);
1342398f0cdSPeter Wemm 		if (hit && n != 4) {
1352398f0cdSPeter Wemm 			printf("CONFIG: invalid hint '%s'\n", cp);
136*dc15eac0SEd Schouten 			p = strchr(cp, 'h');
1372398f0cdSPeter Wemm 			*p = 'H';
1382398f0cdSPeter Wemm 			hit = 0;
1392398f0cdSPeter Wemm 		}
1402398f0cdSPeter Wemm 		if (hit && startln && *startln >= 0 && *line < *startln)
1412398f0cdSPeter Wemm 			hit = 0;
1422398f0cdSPeter Wemm 		if (hit && name && strcmp(name, r_name) != 0)
1432398f0cdSPeter Wemm 			hit = 0;
1442398f0cdSPeter Wemm 		if (hit && unit && *unit != r_unit)
1452398f0cdSPeter Wemm 			hit = 0;
1462398f0cdSPeter Wemm 		if (hit && resname && strcmp(resname, r_resname) != 0)
1472398f0cdSPeter Wemm 			hit = 0;
1482398f0cdSPeter Wemm 		if (hit && value && strcmp(value, r_value) != 0)
1492398f0cdSPeter Wemm 			hit = 0;
1502398f0cdSPeter Wemm 		if (hit)
1512398f0cdSPeter Wemm 			break;
1524f033348SPeter Wemm 		if (use_kenv) {
153d786139cSMaxime Henrion 			cp = kenvp[++i];
1544f033348SPeter Wemm 			if (cp == NULL)
1554f033348SPeter Wemm 				break;
1564f033348SPeter Wemm 		} else {
1572398f0cdSPeter Wemm 			while (*cp != '\0')
1582398f0cdSPeter Wemm 				cp++;
1592398f0cdSPeter Wemm 			cp++;
1602398f0cdSPeter Wemm 			if (*cp == '\0') {
1612398f0cdSPeter Wemm 				cp = NULL;
1622398f0cdSPeter Wemm 				break;
1632398f0cdSPeter Wemm 			}
1642398f0cdSPeter Wemm 		}
1654f033348SPeter Wemm 	}
166d786139cSMaxime Henrion 	if (use_kenv)
167e3546a75SScott Long 		mtx_unlock(&kenv_lock);
1682398f0cdSPeter Wemm 	if (cp == NULL)
1692398f0cdSPeter Wemm 		return ENOENT;
1702398f0cdSPeter Wemm 
1712398f0cdSPeter Wemm 	s = cp;
1722398f0cdSPeter Wemm 	/* This is a bit of a hack, but at least is reentrant */
1732398f0cdSPeter Wemm 	/* Note that it returns some !unterminated! strings. */
174*dc15eac0SEd Schouten 	s = strchr(s, '.') + 1;		/* start of device */
1752398f0cdSPeter Wemm 	if (ret_name)
1762398f0cdSPeter Wemm 		*ret_name = s;
177*dc15eac0SEd Schouten 	s = strchr(s, '.') + 1;		/* start of unit */
17885c36f3dSJohn Baldwin 	if (ret_namelen && ret_name)
1792398f0cdSPeter Wemm 		*ret_namelen = s - *ret_name - 1; /* device length */
1802398f0cdSPeter Wemm 	if (ret_unit)
1812398f0cdSPeter Wemm 		*ret_unit = r_unit;
182*dc15eac0SEd Schouten 	s = strchr(s, '.') + 1;		/* start of resname */
1832398f0cdSPeter Wemm 	if (ret_resname)
1842398f0cdSPeter Wemm 		*ret_resname = s;
185*dc15eac0SEd Schouten 	s = strchr(s, '=') + 1;		/* start of value */
18685c36f3dSJohn Baldwin 	if (ret_resnamelen && ret_resname)
1872398f0cdSPeter Wemm 		*ret_resnamelen = s - *ret_resname - 1; /* value len */
1882398f0cdSPeter Wemm 	if (ret_value)
1892398f0cdSPeter Wemm 		*ret_value = s;
1902398f0cdSPeter Wemm 	if (startln)			/* line number for anchor */
1912398f0cdSPeter Wemm 		*startln = *line + 1;
1922398f0cdSPeter Wemm 	return 0;
1932398f0cdSPeter Wemm }
1942398f0cdSPeter Wemm 
1952398f0cdSPeter Wemm /*
1962398f0cdSPeter Wemm  * Search all the data sources for matches to our query.  We look for
1972398f0cdSPeter Wemm  * dynamic hints first as overrides for static or fallback hints.
1982398f0cdSPeter Wemm  */
1992398f0cdSPeter Wemm static int
2002398f0cdSPeter Wemm resource_find(int *line, int *startln,
2012398f0cdSPeter Wemm     const char *name, int *unit, const char *resname, const char *value,
2022398f0cdSPeter Wemm     const char **ret_name, int *ret_namelen, int *ret_unit,
2032398f0cdSPeter Wemm     const char **ret_resname, int *ret_resnamelen, const char **ret_value)
2042398f0cdSPeter Wemm {
2052398f0cdSPeter Wemm 	int i;
2062398f0cdSPeter Wemm 	int un;
2072398f0cdSPeter Wemm 
2082398f0cdSPeter Wemm 	*line = 0;
2092398f0cdSPeter Wemm 
2102398f0cdSPeter Wemm 	/* Search for exact unit matches first */
2119516fbd6SPeter Wemm 	i = res_find(line, startln, name, unit, resname, value,
2122398f0cdSPeter Wemm 	    ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
2132398f0cdSPeter Wemm 	    ret_value);
2142398f0cdSPeter Wemm 	if (i == 0)
2152398f0cdSPeter Wemm 		return 0;
2162398f0cdSPeter Wemm 	if (unit == NULL)
2172398f0cdSPeter Wemm 		return ENOENT;
2182398f0cdSPeter Wemm 	/* If we are still here, search for wildcard matches */
2192398f0cdSPeter Wemm 	un = -1;
2209516fbd6SPeter Wemm 	i = res_find(line, startln, name, &un, resname, value,
2212398f0cdSPeter Wemm 	    ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
2222398f0cdSPeter Wemm 	    ret_value);
2232398f0cdSPeter Wemm 	if (i == 0)
2242398f0cdSPeter Wemm 		return 0;
2252398f0cdSPeter Wemm 	return ENOENT;
2262398f0cdSPeter Wemm }
2272398f0cdSPeter Wemm 
2282398f0cdSPeter Wemm int
2292398f0cdSPeter Wemm resource_int_value(const char *name, int unit, const char *resname, int *result)
2302398f0cdSPeter Wemm {
2312398f0cdSPeter Wemm 	int error;
2322398f0cdSPeter Wemm 	const char *str;
2332398f0cdSPeter Wemm 	char *op;
2342398f0cdSPeter Wemm 	unsigned long val;
2352398f0cdSPeter Wemm 	int line;
2362398f0cdSPeter Wemm 
2372398f0cdSPeter Wemm 	line = 0;
2382398f0cdSPeter Wemm 	error = resource_find(&line, NULL, name, &unit, resname, NULL,
2392398f0cdSPeter Wemm 	    NULL, NULL, NULL, NULL, NULL, &str);
2402398f0cdSPeter Wemm 	if (error)
2412398f0cdSPeter Wemm 		return error;
2422398f0cdSPeter Wemm 	if (*str == '\0')
2432398f0cdSPeter Wemm 		return EFTYPE;
2442398f0cdSPeter Wemm 	val = strtoul(str, &op, 0);
2452398f0cdSPeter Wemm 	if (*op != '\0')
2462398f0cdSPeter Wemm 		return EFTYPE;
2472398f0cdSPeter Wemm 	*result = val;
2482398f0cdSPeter Wemm 	return 0;
2492398f0cdSPeter Wemm }
2502398f0cdSPeter Wemm 
2512398f0cdSPeter Wemm int
2522398f0cdSPeter Wemm resource_long_value(const char *name, int unit, const char *resname,
2532398f0cdSPeter Wemm     long *result)
2542398f0cdSPeter Wemm {
2552398f0cdSPeter Wemm 	int error;
2562398f0cdSPeter Wemm 	const char *str;
2572398f0cdSPeter Wemm 	char *op;
2582398f0cdSPeter Wemm 	unsigned long val;
2592398f0cdSPeter Wemm 	int line;
2602398f0cdSPeter Wemm 
2612398f0cdSPeter Wemm 	line = 0;
2622398f0cdSPeter Wemm 	error = resource_find(&line, NULL, name, &unit, resname, NULL,
2632398f0cdSPeter Wemm 	    NULL, NULL, NULL, NULL, NULL, &str);
2642398f0cdSPeter Wemm 	if (error)
2652398f0cdSPeter Wemm 		return error;
2662398f0cdSPeter Wemm 	if (*str == '\0')
2672398f0cdSPeter Wemm 		return EFTYPE;
2682398f0cdSPeter Wemm 	val = strtoul(str, &op, 0);
2692398f0cdSPeter Wemm 	if (*op != '\0')
2702398f0cdSPeter Wemm 		return EFTYPE;
2712398f0cdSPeter Wemm 	*result = val;
2722398f0cdSPeter Wemm 	return 0;
2732398f0cdSPeter Wemm }
2742398f0cdSPeter Wemm 
2752398f0cdSPeter Wemm int
2762398f0cdSPeter Wemm resource_string_value(const char *name, int unit, const char *resname,
2772398f0cdSPeter Wemm     const char **result)
2782398f0cdSPeter Wemm {
2792398f0cdSPeter Wemm 	int error;
2802398f0cdSPeter Wemm 	const char *str;
2812398f0cdSPeter Wemm 	int line;
2822398f0cdSPeter Wemm 
2832398f0cdSPeter Wemm 	line = 0;
2842398f0cdSPeter Wemm 	error = resource_find(&line, NULL, name, &unit, resname, NULL,
2852398f0cdSPeter Wemm 	    NULL, NULL, NULL, NULL, NULL, &str);
2862398f0cdSPeter Wemm 	if (error)
2872398f0cdSPeter Wemm 		return error;
2882398f0cdSPeter Wemm 	*result = str;
2892398f0cdSPeter Wemm 	return 0;
2902398f0cdSPeter Wemm }
2912398f0cdSPeter Wemm 
2922398f0cdSPeter Wemm /*
2932398f0cdSPeter Wemm  * This is a bit nasty, but allows us to not modify the env strings.
2942398f0cdSPeter Wemm  */
2952398f0cdSPeter Wemm static const char *
2962398f0cdSPeter Wemm resource_string_copy(const char *s, int len)
2972398f0cdSPeter Wemm {
2982398f0cdSPeter Wemm 	static char stringbuf[256];
2992398f0cdSPeter Wemm 	static int offset = 0;
3002398f0cdSPeter Wemm 	const char *ret;
3012398f0cdSPeter Wemm 
3022398f0cdSPeter Wemm 	if (len == 0)
3032398f0cdSPeter Wemm 		len = strlen(s);
3042398f0cdSPeter Wemm 	if (len > 255)
3052398f0cdSPeter Wemm 		return NULL;
3062398f0cdSPeter Wemm 	if ((offset + len + 1) > 255)
3072398f0cdSPeter Wemm 		offset = 0;
3082398f0cdSPeter Wemm 	bcopy(s, &stringbuf[offset], len);
3092398f0cdSPeter Wemm 	stringbuf[offset + len] = '\0';
3102398f0cdSPeter Wemm 	ret = &stringbuf[offset];
3112398f0cdSPeter Wemm 	offset += len + 1;
3122398f0cdSPeter Wemm 	return ret;
3132398f0cdSPeter Wemm }
3142398f0cdSPeter Wemm 
3152398f0cdSPeter Wemm /*
31674e62047SJohn-Mark Gurney  * err = resource_find_match(&anchor, &name, &unit, resname, value)
3172398f0cdSPeter Wemm  * Iteratively fetch a list of devices wired "at" something
3182398f0cdSPeter Wemm  * res and value are restrictions.  eg: "at", "scbus0".
3192398f0cdSPeter Wemm  * For practical purposes, res = required, value = optional.
3202398f0cdSPeter Wemm  * *name and *unit are set.
3212398f0cdSPeter Wemm  * set *anchor to zero before starting.
3222398f0cdSPeter Wemm  */
3232398f0cdSPeter Wemm int
3242398f0cdSPeter Wemm resource_find_match(int *anchor, const char **name, int *unit,
3252398f0cdSPeter Wemm     const char *resname, const char *value)
3262398f0cdSPeter Wemm {
3272398f0cdSPeter Wemm 	const char *found_name;
3282398f0cdSPeter Wemm 	int found_namelen;
3292398f0cdSPeter Wemm 	int found_unit;
3302398f0cdSPeter Wemm 	int ret;
3312398f0cdSPeter Wemm 	int newln;
3322398f0cdSPeter Wemm 
3332398f0cdSPeter Wemm 	newln = *anchor;
3342398f0cdSPeter Wemm 	ret = resource_find(anchor, &newln, NULL, NULL, resname, value,
3352398f0cdSPeter Wemm 	    &found_name, &found_namelen, &found_unit, NULL, NULL, NULL);
3362398f0cdSPeter Wemm 	if (ret == 0) {
3372398f0cdSPeter Wemm 		*name = resource_string_copy(found_name, found_namelen);
3382398f0cdSPeter Wemm 		*unit = found_unit;
3392398f0cdSPeter Wemm 	}
3402398f0cdSPeter Wemm 	*anchor = newln;
3412398f0cdSPeter Wemm 	return ret;
3422398f0cdSPeter Wemm }
3432398f0cdSPeter Wemm 
3442398f0cdSPeter Wemm 
3452398f0cdSPeter Wemm /*
3462398f0cdSPeter Wemm  * err = resource_find_dev(&anchor, name, &unit, res, value);
3472398f0cdSPeter Wemm  * Iterate through a list of devices, returning their unit numbers.
3482398f0cdSPeter Wemm  * res and value are optional restrictions.  eg: "at", "scbus0".
3492398f0cdSPeter Wemm  * *unit is set to the value.
3502398f0cdSPeter Wemm  * set *anchor to zero before starting.
3512398f0cdSPeter Wemm  */
3522398f0cdSPeter Wemm int
3532398f0cdSPeter Wemm resource_find_dev(int *anchor, const char *name, int *unit,
3542398f0cdSPeter Wemm     const char *resname, const char *value)
3552398f0cdSPeter Wemm {
3562398f0cdSPeter Wemm 	int found_unit;
3572398f0cdSPeter Wemm 	int newln;
3582398f0cdSPeter Wemm 	int ret;
3592398f0cdSPeter Wemm 
3602398f0cdSPeter Wemm 	newln = *anchor;
3612398f0cdSPeter Wemm 	ret = resource_find(anchor, &newln, name, NULL, resname, value,
3622398f0cdSPeter Wemm 	    NULL, NULL, &found_unit, NULL, NULL, NULL);
3632398f0cdSPeter Wemm 	if (ret == 0) {
3642398f0cdSPeter Wemm 		*unit = found_unit;
3652398f0cdSPeter Wemm 	}
3662398f0cdSPeter Wemm 	*anchor = newln;
3672398f0cdSPeter Wemm 	return ret;
3682398f0cdSPeter Wemm }
3696591b310SJohn Baldwin 
3706591b310SJohn Baldwin /*
3716591b310SJohn Baldwin  * Check to see if a device is disabled via a disabled hint.
3726591b310SJohn Baldwin  */
3736591b310SJohn Baldwin int
3746591b310SJohn Baldwin resource_disabled(const char *name, int unit)
3756591b310SJohn Baldwin {
3766591b310SJohn Baldwin 	int error, value;
3776591b310SJohn Baldwin 
3786591b310SJohn Baldwin 	error = resource_int_value(name, unit, "disabled", &value);
3796591b310SJohn Baldwin 	if (error)
3806591b310SJohn Baldwin 	       return (0);
3816591b310SJohn Baldwin 	return (value);
3826591b310SJohn Baldwin }
383