Deleted Added
full compact
subr_bus.c (70804) subr_bus.c (78135)
1/*-
2 * Copyright (c) 1997,1998 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 1997,1998 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/kern/subr_bus.c 70804 2001-01-08 22:16:26Z n_hibma $
26 * $FreeBSD: head/sys/kern/subr_bus.c 78135 2001-06-12 09:40:04Z peter $
27 */
28
29#include "opt_bus.h"
30
31#include <sys/param.h>
32#include <sys/queue.h>
33#include <sys/malloc.h>
34#include <sys/kernel.h>

--- 51 unchanged lines hidden (view full) ---

86#define print_driver(d,i) /* nop */
87#define print_driver_list(d,i) /* nop */
88#define print_devclass_short(d,i) /* nop */
89#define print_devclass(d,i) /* nop */
90#define print_devclass_list_short() /* nop */
91#define print_devclass_list() /* nop */
92#endif
93
27 */
28
29#include "opt_bus.h"
30
31#include <sys/param.h>
32#include <sys/queue.h>
33#include <sys/malloc.h>
34#include <sys/kernel.h>

--- 51 unchanged lines hidden (view full) ---

86#define print_driver(d,i) /* nop */
87#define print_driver_list(d,i) /* nop */
88#define print_devclass_short(d,i) /* nop */
89#define print_devclass(d,i) /* nop */
90#define print_devclass_list_short() /* nop */
91#define print_devclass_list() /* nop */
92#endif
93
94extern char static_hints[];
95extern int hintmode;
96static int hints_loaded = 0;
94extern char static_hints[]; /* by config for now */
97
98TAILQ_HEAD(,device) bus_data_devices;
99static int bus_data_generation = 1;
100
101kobj_method_t null_methods[] = {
102 { 0, 0 }
103};
104

--- 998 unchanged lines hidden (view full) ---

1103 return (err);
1104
1105 bus_data_generation_update();
1106 return (0);
1107}
1108
1109/*======================================*/
1110/*
95
96TAILQ_HEAD(,device) bus_data_devices;
97static int bus_data_generation = 1;
98
99kobj_method_t null_methods[] = {
100 { 0, 0 }
101};
102

--- 998 unchanged lines hidden (view full) ---

1101 return (err);
1102
1103 bus_data_generation_update();
1104 return (0);
1105}
1106
1107/*======================================*/
1108/*
1111 * Access functions for device resources.
1112 */
1113
1114/* Runtime version */
1115static struct config_device *devtab;
1116static int devtab_count = 0;
1117
1118static int
1119resource_new_name(const char *name, int unit)
1120{
1121 struct config_device *new;
1122
1123 new = malloc((devtab_count + 1) * sizeof(*new), M_TEMP, M_NOWAIT);
1124 if (new == NULL)
1125 return (-1);
1126 if (devtab && devtab_count > 0)
1127 bcopy(devtab, new, devtab_count * sizeof(*new));
1128 bzero(&new[devtab_count], sizeof(*new));
1129 new[devtab_count].name = malloc(strlen(name) + 1, M_TEMP, M_NOWAIT);
1130 if (new[devtab_count].name == NULL) {
1131 free(new, M_TEMP);
1132 return (-1);
1133 }
1134 strcpy(new[devtab_count].name, name);
1135 new[devtab_count].unit = unit;
1136 new[devtab_count].resource_count = 0;
1137 new[devtab_count].resources = NULL;
1138 devtab = new;
1139 return (devtab_count++);
1140}
1141
1142static int
1143resource_new_resname(int j, const char *resname, resource_type type)
1144{
1145 struct config_resource *new;
1146 int i;
1147
1148 i = devtab[j].resource_count;
1149 new = malloc((i + 1) * sizeof(*new), M_TEMP, M_NOWAIT);
1150 if (new == NULL)
1151 return (-1);
1152 if (devtab[j].resources && i > 0)
1153 bcopy(devtab[j].resources, new, i * sizeof(*new));
1154 bzero(&new[i], sizeof(*new));
1155 new[i].name = malloc(strlen(resname) + 1, M_TEMP, M_NOWAIT);
1156 if (new[i].name == NULL) {
1157 free(new, M_TEMP);
1158 return (-1);
1159 }
1160 strcpy(new[i].name, resname);
1161 new[i].type = type;
1162 if (devtab[j].resources)
1163 free(devtab[j].resources, M_TEMP);
1164 devtab[j].resources = new;
1165 devtab[j].resource_count = i + 1;
1166 return (i);
1167}
1168
1169static int
1170resource_match_string(int i, const char *resname, const char *value)
1171{
1172 int j;
1173 struct config_resource *res;
1174
1175 for (j = 0, res = devtab[i].resources;
1176 j < devtab[i].resource_count; j++, res++)
1177 if (!strcmp(res->name, resname)
1178 && res->type == RES_STRING
1179 && !strcmp(res->u.stringval, value))
1180 return (j);
1181 return (-1);
1182}
1183
1184static int
1185resource_find_hard(char *cp, const char *name, int unit,
1186 const char *resname, struct config_resource **result)
1187{
1188 char match[256];
1189 int matchlen;
1190 char *op;
1191 long val;
1192
1193 snprintf(match, sizeof(match), "hint.%s.%d.%s=", name, unit, resname);
1194 matchlen = strlen(match);
1195 while (cp) {
1196 if (strncmp(match, cp, matchlen) == 0)
1197 break;
1198 while (*cp != '\0')
1199 cp++;
1200 cp++;
1201 if (*cp == '\0') {
1202 cp = NULL;
1203 break;
1204 }
1205 }
1206 if (cp)
1207 cp += matchlen; /* skip over name and '=' */
1208 else
1209 return (ENOENT);
1210 val = strtoul(cp, &op, 0);
1211 if (*cp != '\0' && *op == '\0') {
1212 (*result)->type = RES_INT;
1213 (*result)->u.intval = val;
1214 } else {
1215 (*result)->type = RES_STRING;
1216 (*result)->u.stringval = cp;
1217 }
1218 return (0);
1219}
1220
1221static int
1222resource_find(const char *name, int unit, const char *resname,
1223 struct config_resource **result)
1224{
1225 int i, j;
1226 struct config_resource *res;
1227
1228 if (!hints_loaded) {
1229 /* First specific, then generic. Dynamic over static. */
1230 i = resource_find_hard(kern_envp, name, unit, resname, result);
1231 if (i == 0)
1232 return (0);
1233 i = resource_find_hard(static_hints, name, unit, resname,
1234 result);
1235 if (i == 0)
1236 return (0);
1237 i = resource_find_hard(kern_envp, name, -1, resname, result);
1238 if (i == 0)
1239 return (0);
1240 i = resource_find_hard(static_hints, name, -1, resname, result);
1241 return (i);
1242 }
1243
1244 /*
1245 * First check specific instances, then generic.
1246 */
1247 for (i = 0; i < devtab_count; i++) {
1248 if (devtab[i].unit < 0)
1249 continue;
1250 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
1251 res = devtab[i].resources;
1252 for (j = 0; j < devtab[i].resource_count; j++, res++)
1253 if (!strcmp(res->name, resname)) {
1254 *result = res;
1255 return (0);
1256 }
1257 }
1258 }
1259 for (i = 0; i < devtab_count; i++) {
1260 if (devtab[i].unit >= 0)
1261 continue;
1262 if (!strcmp(devtab[i].name, name)) {
1263 res = devtab[i].resources;
1264 for (j = 0; j < devtab[i].resource_count; j++, res++)
1265 if (!strcmp(res->name, resname)) {
1266 *result = res;
1267 return (0);
1268 }
1269 }
1270 }
1271 return (ENOENT);
1272}
1273
1274int
1275resource_int_value(const char *name, int unit, const char *resname, int *result)
1276{
1277 struct config_resource tmpres;
1278 struct config_resource *res;
1279 int error;
1280
1281 res = &tmpres;
1282 if ((error = resource_find(name, unit, resname, &res)) != 0)
1283 return (error);
1284 if (res->type != RES_INT)
1285 return (EFTYPE);
1286 *result = res->u.intval;
1287 return (0);
1288}
1289
1290int
1291resource_long_value(const char *name, int unit, const char *resname,
1292 long *result)
1293{
1294 struct config_resource tmpres;
1295 struct config_resource *res;
1296 int error;
1297
1298 res = &tmpres;
1299 if ((error = resource_find(name, unit, resname, &res)) != 0)
1300 return (error);
1301 if (res->type != RES_LONG)
1302 return (EFTYPE);
1303 *result = res->u.longval;
1304 return (0);
1305}
1306
1307int
1308resource_string_value(const char *name, int unit, const char *resname,
1309 char **result)
1310{
1311 struct config_resource tmpres;
1312 struct config_resource *res;
1313 int error;
1314
1315 res = &tmpres;
1316 if ((error = resource_find(name, unit, resname, &res)) != 0)
1317 return (error);
1318 if (res->type != RES_STRING)
1319 return (EFTYPE);
1320 *result = res->u.stringval;
1321 return (0);
1322}
1323
1324int
1325resource_query_string(int i, const char *resname, const char *value)
1326{
1327 if (i < 0)
1328 i = 0;
1329 else
1330 i = i + 1;
1331 for (; i < devtab_count; i++)
1332 if (resource_match_string(i, resname, value) >= 0)
1333 return (i);
1334 return (-1);
1335}
1336
1337int
1338resource_locate(int i, const char *resname)
1339{
1340 if (i < 0)
1341 i = 0;
1342 else
1343 i = i + 1;
1344 for (; i < devtab_count; i++)
1345 if (!strcmp(devtab[i].name, resname))
1346 return (i);
1347 return (-1);
1348}
1349
1350int
1351resource_count(void)
1352{
1353 return (devtab_count);
1354}
1355
1356char *
1357resource_query_name(int i)
1358{
1359 return (devtab[i].name);
1360}
1361
1362int
1363resource_query_unit(int i)
1364{
1365 return (devtab[i].unit);
1366}
1367
1368static int
1369resource_create(const char *name, int unit, const char *resname,
1370 resource_type type, struct config_resource **result)
1371{
1372 int i, j;
1373 struct config_resource *res = NULL;
1374
1375 for (i = 0; i < devtab_count; i++) {
1376 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
1377 res = devtab[i].resources;
1378 break;
1379 }
1380 }
1381 if (res == NULL) {
1382 i = resource_new_name(name, unit);
1383 if (i < 0)
1384 return (ENOMEM);
1385 res = devtab[i].resources;
1386 }
1387 for (j = 0; j < devtab[i].resource_count; j++, res++) {
1388 if (!strcmp(res->name, resname)) {
1389 *result = res;
1390 return (0);
1391 }
1392 }
1393 j = resource_new_resname(i, resname, type);
1394 if (j < 0)
1395 return (ENOMEM);
1396 res = &devtab[i].resources[j];
1397 *result = res;
1398 return (0);
1399}
1400
1401int
1402resource_set_int(const char *name, int unit, const char *resname, int value)
1403{
1404 int error;
1405 struct config_resource *res;
1406
1407 error = resource_create(name, unit, resname, RES_INT, &res);
1408 if (error)
1409 return (error);
1410 if (res->type != RES_INT)
1411 return (EFTYPE);
1412 res->u.intval = value;
1413 return (0);
1414}
1415
1416int
1417resource_set_long(const char *name, int unit, const char *resname, long value)
1418{
1419 int error;
1420 struct config_resource *res;
1421
1422 error = resource_create(name, unit, resname, RES_LONG, &res);
1423 if (error)
1424 return (error);
1425 if (res->type != RES_LONG)
1426 return (EFTYPE);
1427 res->u.longval = value;
1428 return (0);
1429}
1430
1431int
1432resource_set_string(const char *name, int unit, const char *resname,
1433 const char *value)
1434{
1435 int error;
1436 struct config_resource *res;
1437
1438 error = resource_create(name, unit, resname, RES_STRING, &res);
1439 if (error)
1440 return (error);
1441 if (res->type != RES_STRING)
1442 return (EFTYPE);
1443 if (res->u.stringval)
1444 free(res->u.stringval, M_TEMP);
1445 res->u.stringval = malloc(strlen(value) + 1, M_TEMP, M_NOWAIT);
1446 if (res->u.stringval == NULL)
1447 return (ENOMEM);
1448 strcpy(res->u.stringval, value);
1449 return (0);
1450}
1451
1452/*
1453 * We use the identify routine to get the hints for all the other devices.
1454 * Strings that are all digits or begin with 0x are integers.
1455 *
1456 * hint.aha.0.bus_speedup=1
1457 * hint.aha.1.irq=10
1458 * hint.wl.0.netid=PLUG
1459 * hint.wl.1.netid=XYZZY
1460 */
1461static void
1462hint_load(char *cp)
1463{
1464 char *ep, *op, *walker;
1465 int len;
1466 int val;
1467 char name[20];
1468 int unit;
1469 char resname[255];
1470
1471 for (ep = cp; *ep != '=' && *ep != '\0'; ep++)
1472 continue;
1473 len = ep - cp;
1474 if (*ep == '=')
1475 ep++;
1476 walker = cp;
1477 walker += 5;
1478 op = walker;
1479 while (*walker && *walker != '.')
1480 walker++;
1481 if (*walker != '.')
1482 return;
1483 if (walker - op > sizeof(name))
1484 return;
1485 strncpy(name, op, walker - op);
1486 name[walker - op] = '\0';
1487 walker++;
1488 op = walker;
1489 while (*walker && *walker != '.')
1490 walker++;
1491 if (*walker != '.')
1492 return;
1493 unit = strtoul(op, &walker, 0);
1494 if (*walker != '.')
1495 return;
1496 walker++;
1497 op = walker;
1498 while (*walker && *walker != '=')
1499 walker++;
1500 if (*walker != '=')
1501 return;
1502 if (walker - op > sizeof(resname))
1503 return;
1504 strncpy(resname, op, walker - op);
1505 resname[walker - op] = '\0';
1506 walker++;
1507 if (walker != ep)
1508 return;
1509 if (bootverbose)
1510 printf("Setting %s %d %s to ", name, unit, resname);
1511 val = strtoul(ep, &op, 0);
1512 if (*ep != '\0' && *op == '\0') {
1513 resource_set_int(name, unit, resname, val);
1514 if (bootverbose)
1515 printf("%d (int)\n", val);
1516 } else {
1517 resource_set_string(name, unit, resname, ep);
1518 if (bootverbose)
1519 printf("%s (string)\n", ep);
1520 }
1521}
1522
1523
1524static void
1525hints_load(void *dummy __unused)
1526{
1527 char *cp;
1528
1529 if (hintmode == 2) { /* default hints only */
1530 cp = kern_envp;
1531 while (cp) {
1532 if (strncmp(cp, "hint.", 5) == 0) {
1533 /* ok, we found a hint, ignore these defaults */
1534 hintmode = 0;
1535 break;
1536 }
1537 while (*cp != '\0')
1538 cp++;
1539 cp++;
1540 if (*cp == '\0')
1541 break;
1542 }
1543 }
1544 if (hintmode != 0) {
1545 cp = static_hints;
1546 while (cp) {
1547 if (strncmp(cp, "hint.", 5) == 0)
1548 hint_load(cp);
1549 while (*cp != '\0')
1550 cp++;
1551 cp++;
1552 if (*cp == '\0')
1553 break;
1554 }
1555 }
1556 cp = kern_envp;
1557 while (cp) {
1558 if (strncmp(cp, "hint.", 5) == 0)
1559 hint_load(cp);
1560 while (*cp != '\0')
1561 cp++;
1562 cp++;
1563 if (*cp == '\0')
1564 break;
1565 }
1566 hints_loaded++;
1567}
1568SYSINIT(cfghints, SI_SUB_KMEM, SI_ORDER_ANY + 60, hints_load, 0)
1569
1570/*======================================*/
1571/*
1572 * Some useful method implementations to make life easier for bus drivers.
1573 */
1574
1109 * Some useful method implementations to make life easier for bus drivers.
1110 */
1111
1575 void
1112void
1576resource_list_init(struct resource_list *rl)
1577{
1578 SLIST_INIT(rl);
1579}
1580
1581void
1582resource_list_free(struct resource_list *rl)
1583{

--- 1002 unchanged lines hidden (view full) ---

2586 return (0);
2587}
2588
2589void
2590bus_data_generation_update(void)
2591{
2592 bus_data_generation++;
2593}
1113resource_list_init(struct resource_list *rl)
1114{
1115 SLIST_INIT(rl);
1116}
1117
1118void
1119resource_list_free(struct resource_list *rl)
1120{

--- 1002 unchanged lines hidden (view full) ---

2123 return (0);
2124}
2125
2126void
2127bus_data_generation_update(void)
2128{
2129 bus_data_generation++;
2130}
2131
2132/*======================================*/
2133/*
2134 * Access functions for device resources.
2135 */
2136
2137/*
2138 * Evil wildcarding resource string lookup.
2139 * This walks the supplied env string table and returns a match.
2140 * The start point can be remembered for incremental searches.
2141 */
2142static int
2143res_find(const char *cp, int *line, int *startln,
2144 const char *name, int *unit, const char *resname, const char *value,
2145 const char **ret_name, int *ret_namelen, int *ret_unit,
2146 const char **ret_resname, int *ret_resnamelen, const char **ret_value)
2147{
2148 int n = 0, hit;
2149 char r_name[32];
2150 int r_unit;
2151 char r_resname[32];
2152 char r_value[128];
2153 const char *s;
2154 char *p;
2155
2156 while (cp) {
2157 hit = 1;
2158 (*line)++;
2159 if (strncmp(cp, "hint.", 5) != 0)
2160 hit = 0;
2161 else
2162 n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%128s",
2163 r_name, &r_unit, r_resname, r_value);
2164 if (hit && n != 4) {
2165 printf("CONFIG: invalid hint '%s'\n", cp);
2166 /* XXX: abuse bogus index() declaration */
2167 p = index(cp, 'h');
2168 *p = 'H';
2169 hit = 0;
2170 }
2171 if (hit && startln && *startln >= 0 && *line < *startln)
2172 hit = 0;
2173 if (hit && name && strcmp(name, r_name) != 0)
2174 hit = 0;
2175 if (hit && unit && *unit != r_unit)
2176 hit = 0;
2177 if (hit && resname && strcmp(resname, r_resname) != 0)
2178 hit = 0;
2179 if (hit && value && strcmp(value, r_value) != 0)
2180 hit = 0;
2181 if (hit)
2182 break;
2183 while (*cp != '\0')
2184 cp++;
2185 cp++;
2186 if (*cp == '\0') {
2187 cp = NULL;
2188 break;
2189 }
2190 }
2191 if (cp == NULL)
2192 return ENOENT;
2193
2194 s = cp;
2195 /* This is a bit of a hack, but at least is reentrant */
2196 /* Note that it returns some !unterminated! strings. */
2197 s = index(s, '.') + 1; /* start of device */
2198 if (ret_name)
2199 *ret_name = s;
2200 s = index(s, '.') + 1; /* start of unit */
2201 if (ret_namelen)
2202 *ret_namelen = s - *ret_name - 1; /* device length */
2203 if (ret_unit)
2204 *ret_unit = r_unit;
2205 s = index(s, '.') + 1; /* start of resname */
2206 if (ret_resname)
2207 *ret_resname = s;
2208 s = index(s, '=') + 1; /* start of value */
2209 if (ret_resnamelen)
2210 *ret_resnamelen = s - *ret_resname - 1; /* value len */
2211 if (ret_value)
2212 *ret_value = s;
2213 if (startln) /* line number for anchor */
2214 *startln = *line + 1;
2215 return 0;
2216}
2217
2218/*
2219 * Search all the data sources for matches to our query. We look for
2220 * dynamic hints first as overrides for static or fallback hints.
2221 */
2222static int
2223resource_find(int *line, int *startln,
2224 const char *name, int *unit, const char *resname, const char *value,
2225 const char **ret_name, int *ret_namelen, int *ret_unit,
2226 const char **ret_resname, int *ret_resnamelen, const char **ret_value)
2227{
2228 int i;
2229 int un;
2230
2231 *line = 0;
2232
2233 /* Search for exact unit matches first */
2234 i = res_find(kern_envp, line, startln, name, unit, resname, value,
2235 ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
2236 ret_value);
2237 if (i == 0)
2238 return 0;
2239 i = res_find(static_hints, line, startln, name, unit, resname, value,
2240 ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
2241 ret_value);
2242 if (i == 0)
2243 return 0;
2244 if (unit == NULL)
2245 return ENOENT;
2246 /* If we are still here, search for wildcard matches */
2247 un = -1;
2248 i = res_find(kern_envp, line, startln, name, &un, resname, value,
2249 ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
2250 ret_value);
2251 if (i == 0)
2252 return 0;
2253 un = -1;
2254 i = res_find(static_hints, line, startln, name, &un, resname, value,
2255 ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
2256 ret_value);
2257 if (i == 0)
2258 return 0;
2259 return ENOENT;
2260}
2261
2262int
2263resource_int_value(const char *name, int unit, const char *resname, int *result)
2264{
2265 int error;
2266 const char *str;
2267 char *op;
2268 unsigned long val;
2269 int line;
2270
2271 line = 0;
2272 error = resource_find(&line, NULL, name, &unit, resname, NULL,
2273 NULL, NULL, NULL, NULL, NULL, &str);
2274 if (error)
2275 return error;
2276 if (*str == '\0')
2277 return EFTYPE;
2278 val = strtoul(str, &op, 0);
2279 if (*op != '\0')
2280 return EFTYPE;
2281 *result = val;
2282 return 0;
2283}
2284
2285int
2286resource_long_value(const char *name, int unit, const char *resname,
2287 long *result)
2288{
2289 int error;
2290 const char *str;
2291 char *op;
2292 unsigned long val;
2293 int line;
2294
2295 line = 0;
2296 error = resource_find(&line, NULL, name, &unit, resname, NULL,
2297 NULL, NULL, NULL, NULL, NULL, &str);
2298 if (error)
2299 return error;
2300 if (*str == '\0')
2301 return EFTYPE;
2302 val = strtoul(str, &op, 0);
2303 if (*op != '\0')
2304 return EFTYPE;
2305 *result = val;
2306 return 0;
2307}
2308
2309int
2310resource_string_value(const char *name, int unit, const char *resname,
2311 const char **result)
2312{
2313 int error;
2314 const char *str;
2315 int line;
2316
2317 line = 0;
2318 error = resource_find(&line, NULL, name, &unit, resname, NULL,
2319 NULL, NULL, NULL, NULL, NULL, &str);
2320 if (error)
2321 return error;
2322 *result = str;
2323 return 0;
2324}
2325
2326/*
2327 * This is a bit nasty, but allows us to not modify the env strings.
2328 */
2329static const char *
2330resource_string_copy(const char *s, int len)
2331{
2332 static char stringbuf[256];
2333 static int offset = 0;
2334 const char *ret;
2335
2336 if (len == 0)
2337 len = strlen(s);
2338 if (len > 255)
2339 return NULL;
2340 if ((offset + len + 1) > 255)
2341 offset = 0;
2342 bcopy(s, &stringbuf[offset], len);
2343 stringbuf[offset + len] = '\0';
2344 ret = &stringbuf[offset];
2345 offset += len + 1;
2346 return ret;
2347}
2348
2349/*
2350 * err = resource_find_at(&anchor, &name, &unit, resname, value)
2351 * Iteratively fetch a list of devices wired "at" something
2352 * res and value are restrictions. eg: "at", "scbus0".
2353 * For practical purposes, res = required, value = optional.
2354 * *name and *unit are set.
2355 * set *anchor to zero before starting.
2356 */
2357int
2358resource_find_match(int *anchor, const char **name, int *unit,
2359 const char *resname, const char *value)
2360{
2361 const char *found_name;
2362 int found_namelen;
2363 int found_unit;
2364 int ret;
2365 int newln;
2366
2367 newln = *anchor;
2368 ret = resource_find(anchor, &newln, NULL, NULL, resname, value,
2369 &found_name, &found_namelen, &found_unit, NULL, NULL, NULL);
2370 if (ret == 0) {
2371 *name = resource_string_copy(found_name, found_namelen);
2372 *unit = found_unit;
2373 }
2374 *anchor = newln;
2375 return ret;
2376}
2377
2378
2379/*
2380 * err = resource_find_dev(&anchor, name, &unit, res, value);
2381 * Iterate through a list of devices, returning their unit numbers.
2382 * res and value are optional restrictions. eg: "at", "scbus0".
2383 * *unit is set to the value.
2384 * set *anchor to zero before starting.
2385 */
2386int
2387resource_find_dev(int *anchor, const char *name, int *unit,
2388 const char *resname, const char *value)
2389{
2390 int found_unit;
2391 int newln;
2392 int ret;
2393
2394 newln = *anchor;
2395 ret = resource_find(anchor, &newln, name, NULL, resname, value,
2396 NULL, NULL, &found_unit, NULL, NULL, NULL);
2397 if (ret == 0) {
2398 *unit = found_unit;
2399 }
2400 *anchor = newln;
2401 return ret;
2402}