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 * $FreeBSD$ 272398f0cdSPeter Wemm */ 282398f0cdSPeter Wemm 292398f0cdSPeter Wemm #include <sys/param.h> 302398f0cdSPeter Wemm #include <sys/systm.h> 312398f0cdSPeter Wemm #include <sys/bus.h> 322398f0cdSPeter Wemm 332398f0cdSPeter Wemm /* 342398f0cdSPeter Wemm * Access functions for device resources. 352398f0cdSPeter Wemm */ 362398f0cdSPeter Wemm 372398f0cdSPeter Wemm extern char static_hints[]; /* by config for now */ 382398f0cdSPeter Wemm 392398f0cdSPeter Wemm /* 402398f0cdSPeter Wemm * Evil wildcarding resource string lookup. 412398f0cdSPeter Wemm * This walks the supplied env string table and returns a match. 422398f0cdSPeter Wemm * The start point can be remembered for incremental searches. 432398f0cdSPeter Wemm */ 442398f0cdSPeter Wemm static int 452398f0cdSPeter Wemm res_find(const char *cp, int *line, int *startln, 462398f0cdSPeter Wemm const char *name, int *unit, const char *resname, const char *value, 472398f0cdSPeter Wemm const char **ret_name, int *ret_namelen, int *ret_unit, 482398f0cdSPeter Wemm const char **ret_resname, int *ret_resnamelen, const char **ret_value) 492398f0cdSPeter Wemm { 502398f0cdSPeter Wemm int n = 0, hit; 512398f0cdSPeter Wemm char r_name[32]; 522398f0cdSPeter Wemm int r_unit; 532398f0cdSPeter Wemm char r_resname[32]; 542398f0cdSPeter Wemm char r_value[128]; 552398f0cdSPeter Wemm const char *s; 562398f0cdSPeter Wemm char *p; 572398f0cdSPeter Wemm 582398f0cdSPeter Wemm while (cp) { 592398f0cdSPeter Wemm hit = 1; 602398f0cdSPeter Wemm (*line)++; 612398f0cdSPeter Wemm if (strncmp(cp, "hint.", 5) != 0) 622398f0cdSPeter Wemm hit = 0; 632398f0cdSPeter Wemm else 642398f0cdSPeter Wemm n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%128s", 652398f0cdSPeter Wemm r_name, &r_unit, r_resname, r_value); 662398f0cdSPeter Wemm if (hit && n != 4) { 672398f0cdSPeter Wemm printf("CONFIG: invalid hint '%s'\n", cp); 682398f0cdSPeter Wemm /* XXX: abuse bogus index() declaration */ 692398f0cdSPeter Wemm p = index(cp, 'h'); 702398f0cdSPeter Wemm *p = 'H'; 712398f0cdSPeter Wemm hit = 0; 722398f0cdSPeter Wemm } 732398f0cdSPeter Wemm if (hit && startln && *startln >= 0 && *line < *startln) 742398f0cdSPeter Wemm hit = 0; 752398f0cdSPeter Wemm if (hit && name && strcmp(name, r_name) != 0) 762398f0cdSPeter Wemm hit = 0; 772398f0cdSPeter Wemm if (hit && unit && *unit != r_unit) 782398f0cdSPeter Wemm hit = 0; 792398f0cdSPeter Wemm if (hit && resname && strcmp(resname, r_resname) != 0) 802398f0cdSPeter Wemm hit = 0; 812398f0cdSPeter Wemm if (hit && value && strcmp(value, r_value) != 0) 822398f0cdSPeter Wemm hit = 0; 832398f0cdSPeter Wemm if (hit) 842398f0cdSPeter Wemm break; 852398f0cdSPeter Wemm while (*cp != '\0') 862398f0cdSPeter Wemm cp++; 872398f0cdSPeter Wemm cp++; 882398f0cdSPeter Wemm if (*cp == '\0') { 892398f0cdSPeter Wemm cp = NULL; 902398f0cdSPeter Wemm break; 912398f0cdSPeter Wemm } 922398f0cdSPeter Wemm } 932398f0cdSPeter Wemm if (cp == NULL) 942398f0cdSPeter Wemm return ENOENT; 952398f0cdSPeter Wemm 962398f0cdSPeter Wemm s = cp; 972398f0cdSPeter Wemm /* This is a bit of a hack, but at least is reentrant */ 982398f0cdSPeter Wemm /* Note that it returns some !unterminated! strings. */ 992398f0cdSPeter Wemm s = index(s, '.') + 1; /* start of device */ 1002398f0cdSPeter Wemm if (ret_name) 1012398f0cdSPeter Wemm *ret_name = s; 1022398f0cdSPeter Wemm s = index(s, '.') + 1; /* start of unit */ 1032398f0cdSPeter Wemm if (ret_namelen) 1042398f0cdSPeter Wemm *ret_namelen = s - *ret_name - 1; /* device length */ 1052398f0cdSPeter Wemm if (ret_unit) 1062398f0cdSPeter Wemm *ret_unit = r_unit; 1072398f0cdSPeter Wemm s = index(s, '.') + 1; /* start of resname */ 1082398f0cdSPeter Wemm if (ret_resname) 1092398f0cdSPeter Wemm *ret_resname = s; 1102398f0cdSPeter Wemm s = index(s, '=') + 1; /* start of value */ 1112398f0cdSPeter Wemm if (ret_resnamelen) 1122398f0cdSPeter Wemm *ret_resnamelen = s - *ret_resname - 1; /* value len */ 1132398f0cdSPeter Wemm if (ret_value) 1142398f0cdSPeter Wemm *ret_value = s; 1152398f0cdSPeter Wemm if (startln) /* line number for anchor */ 1162398f0cdSPeter Wemm *startln = *line + 1; 1172398f0cdSPeter Wemm return 0; 1182398f0cdSPeter Wemm } 1192398f0cdSPeter Wemm 1202398f0cdSPeter Wemm /* 1212398f0cdSPeter Wemm * Search all the data sources for matches to our query. We look for 1222398f0cdSPeter Wemm * dynamic hints first as overrides for static or fallback hints. 1232398f0cdSPeter Wemm */ 1242398f0cdSPeter Wemm static int 1252398f0cdSPeter Wemm resource_find(int *line, int *startln, 1262398f0cdSPeter Wemm const char *name, int *unit, const char *resname, const char *value, 1272398f0cdSPeter Wemm const char **ret_name, int *ret_namelen, int *ret_unit, 1282398f0cdSPeter Wemm const char **ret_resname, int *ret_resnamelen, const char **ret_value) 1292398f0cdSPeter Wemm { 1302398f0cdSPeter Wemm int i; 1312398f0cdSPeter Wemm int un; 1322398f0cdSPeter Wemm 1332398f0cdSPeter Wemm *line = 0; 1342398f0cdSPeter Wemm 1352398f0cdSPeter Wemm /* Search for exact unit matches first */ 1362398f0cdSPeter Wemm i = res_find(kern_envp, line, startln, name, unit, resname, value, 1372398f0cdSPeter Wemm ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen, 1382398f0cdSPeter Wemm ret_value); 1392398f0cdSPeter Wemm if (i == 0) 1402398f0cdSPeter Wemm return 0; 1412398f0cdSPeter Wemm i = res_find(static_hints, line, startln, name, unit, resname, value, 1422398f0cdSPeter Wemm ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen, 1432398f0cdSPeter Wemm ret_value); 1442398f0cdSPeter Wemm if (i == 0) 1452398f0cdSPeter Wemm return 0; 1462398f0cdSPeter Wemm if (unit == NULL) 1472398f0cdSPeter Wemm return ENOENT; 1482398f0cdSPeter Wemm /* If we are still here, search for wildcard matches */ 1492398f0cdSPeter Wemm un = -1; 1502398f0cdSPeter Wemm i = res_find(kern_envp, line, startln, name, &un, resname, value, 1512398f0cdSPeter Wemm ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen, 1522398f0cdSPeter Wemm ret_value); 1532398f0cdSPeter Wemm if (i == 0) 1542398f0cdSPeter Wemm return 0; 1552398f0cdSPeter Wemm un = -1; 1562398f0cdSPeter Wemm i = res_find(static_hints, line, startln, name, &un, resname, value, 1572398f0cdSPeter Wemm ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen, 1582398f0cdSPeter Wemm ret_value); 1592398f0cdSPeter Wemm if (i == 0) 1602398f0cdSPeter Wemm return 0; 1612398f0cdSPeter Wemm return ENOENT; 1622398f0cdSPeter Wemm } 1632398f0cdSPeter Wemm 1642398f0cdSPeter Wemm int 1652398f0cdSPeter Wemm resource_int_value(const char *name, int unit, const char *resname, int *result) 1662398f0cdSPeter Wemm { 1672398f0cdSPeter Wemm int error; 1682398f0cdSPeter Wemm const char *str; 1692398f0cdSPeter Wemm char *op; 1702398f0cdSPeter Wemm unsigned long val; 1712398f0cdSPeter Wemm int line; 1722398f0cdSPeter Wemm 1732398f0cdSPeter Wemm line = 0; 1742398f0cdSPeter Wemm error = resource_find(&line, NULL, name, &unit, resname, NULL, 1752398f0cdSPeter Wemm NULL, NULL, NULL, NULL, NULL, &str); 1762398f0cdSPeter Wemm if (error) 1772398f0cdSPeter Wemm return error; 1782398f0cdSPeter Wemm if (*str == '\0') 1792398f0cdSPeter Wemm return EFTYPE; 1802398f0cdSPeter Wemm val = strtoul(str, &op, 0); 1812398f0cdSPeter Wemm if (*op != '\0') 1822398f0cdSPeter Wemm return EFTYPE; 1832398f0cdSPeter Wemm *result = val; 1842398f0cdSPeter Wemm return 0; 1852398f0cdSPeter Wemm } 1862398f0cdSPeter Wemm 1872398f0cdSPeter Wemm int 1882398f0cdSPeter Wemm resource_long_value(const char *name, int unit, const char *resname, 1892398f0cdSPeter Wemm long *result) 1902398f0cdSPeter Wemm { 1912398f0cdSPeter Wemm int error; 1922398f0cdSPeter Wemm const char *str; 1932398f0cdSPeter Wemm char *op; 1942398f0cdSPeter Wemm unsigned long val; 1952398f0cdSPeter Wemm int line; 1962398f0cdSPeter Wemm 1972398f0cdSPeter Wemm line = 0; 1982398f0cdSPeter Wemm error = resource_find(&line, NULL, name, &unit, resname, NULL, 1992398f0cdSPeter Wemm NULL, NULL, NULL, NULL, NULL, &str); 2002398f0cdSPeter Wemm if (error) 2012398f0cdSPeter Wemm return error; 2022398f0cdSPeter Wemm if (*str == '\0') 2032398f0cdSPeter Wemm return EFTYPE; 2042398f0cdSPeter Wemm val = strtoul(str, &op, 0); 2052398f0cdSPeter Wemm if (*op != '\0') 2062398f0cdSPeter Wemm return EFTYPE; 2072398f0cdSPeter Wemm *result = val; 2082398f0cdSPeter Wemm return 0; 2092398f0cdSPeter Wemm } 2102398f0cdSPeter Wemm 2112398f0cdSPeter Wemm int 2122398f0cdSPeter Wemm resource_string_value(const char *name, int unit, const char *resname, 2132398f0cdSPeter Wemm const char **result) 2142398f0cdSPeter Wemm { 2152398f0cdSPeter Wemm int error; 2162398f0cdSPeter Wemm const char *str; 2172398f0cdSPeter Wemm int line; 2182398f0cdSPeter Wemm 2192398f0cdSPeter Wemm line = 0; 2202398f0cdSPeter Wemm error = resource_find(&line, NULL, name, &unit, resname, NULL, 2212398f0cdSPeter Wemm NULL, NULL, NULL, NULL, NULL, &str); 2222398f0cdSPeter Wemm if (error) 2232398f0cdSPeter Wemm return error; 2242398f0cdSPeter Wemm *result = str; 2252398f0cdSPeter Wemm return 0; 2262398f0cdSPeter Wemm } 2272398f0cdSPeter Wemm 2282398f0cdSPeter Wemm /* 2292398f0cdSPeter Wemm * This is a bit nasty, but allows us to not modify the env strings. 2302398f0cdSPeter Wemm */ 2312398f0cdSPeter Wemm static const char * 2322398f0cdSPeter Wemm resource_string_copy(const char *s, int len) 2332398f0cdSPeter Wemm { 2342398f0cdSPeter Wemm static char stringbuf[256]; 2352398f0cdSPeter Wemm static int offset = 0; 2362398f0cdSPeter Wemm const char *ret; 2372398f0cdSPeter Wemm 2382398f0cdSPeter Wemm if (len == 0) 2392398f0cdSPeter Wemm len = strlen(s); 2402398f0cdSPeter Wemm if (len > 255) 2412398f0cdSPeter Wemm return NULL; 2422398f0cdSPeter Wemm if ((offset + len + 1) > 255) 2432398f0cdSPeter Wemm offset = 0; 2442398f0cdSPeter Wemm bcopy(s, &stringbuf[offset], len); 2452398f0cdSPeter Wemm stringbuf[offset + len] = '\0'; 2462398f0cdSPeter Wemm ret = &stringbuf[offset]; 2472398f0cdSPeter Wemm offset += len + 1; 2482398f0cdSPeter Wemm return ret; 2492398f0cdSPeter Wemm } 2502398f0cdSPeter Wemm 2512398f0cdSPeter Wemm /* 2522398f0cdSPeter Wemm * err = resource_find_at(&anchor, &name, &unit, resname, value) 2532398f0cdSPeter Wemm * Iteratively fetch a list of devices wired "at" something 2542398f0cdSPeter Wemm * res and value are restrictions. eg: "at", "scbus0". 2552398f0cdSPeter Wemm * For practical purposes, res = required, value = optional. 2562398f0cdSPeter Wemm * *name and *unit are set. 2572398f0cdSPeter Wemm * set *anchor to zero before starting. 2582398f0cdSPeter Wemm */ 2592398f0cdSPeter Wemm int 2602398f0cdSPeter Wemm resource_find_match(int *anchor, const char **name, int *unit, 2612398f0cdSPeter Wemm const char *resname, const char *value) 2622398f0cdSPeter Wemm { 2632398f0cdSPeter Wemm const char *found_name; 2642398f0cdSPeter Wemm int found_namelen; 2652398f0cdSPeter Wemm int found_unit; 2662398f0cdSPeter Wemm int ret; 2672398f0cdSPeter Wemm int newln; 2682398f0cdSPeter Wemm 2692398f0cdSPeter Wemm newln = *anchor; 2702398f0cdSPeter Wemm ret = resource_find(anchor, &newln, NULL, NULL, resname, value, 2712398f0cdSPeter Wemm &found_name, &found_namelen, &found_unit, NULL, NULL, NULL); 2722398f0cdSPeter Wemm if (ret == 0) { 2732398f0cdSPeter Wemm *name = resource_string_copy(found_name, found_namelen); 2742398f0cdSPeter Wemm *unit = found_unit; 2752398f0cdSPeter Wemm } 2762398f0cdSPeter Wemm *anchor = newln; 2772398f0cdSPeter Wemm return ret; 2782398f0cdSPeter Wemm } 2792398f0cdSPeter Wemm 2802398f0cdSPeter Wemm 2812398f0cdSPeter Wemm /* 2822398f0cdSPeter Wemm * err = resource_find_dev(&anchor, name, &unit, res, value); 2832398f0cdSPeter Wemm * Iterate through a list of devices, returning their unit numbers. 2842398f0cdSPeter Wemm * res and value are optional restrictions. eg: "at", "scbus0". 2852398f0cdSPeter Wemm * *unit is set to the value. 2862398f0cdSPeter Wemm * set *anchor to zero before starting. 2872398f0cdSPeter Wemm */ 2882398f0cdSPeter Wemm int 2892398f0cdSPeter Wemm resource_find_dev(int *anchor, const char *name, int *unit, 2902398f0cdSPeter Wemm const char *resname, const char *value) 2912398f0cdSPeter Wemm { 2922398f0cdSPeter Wemm int found_unit; 2932398f0cdSPeter Wemm int newln; 2942398f0cdSPeter Wemm int ret; 2952398f0cdSPeter Wemm 2962398f0cdSPeter Wemm newln = *anchor; 2972398f0cdSPeter Wemm ret = resource_find(anchor, &newln, name, NULL, resname, value, 2982398f0cdSPeter Wemm NULL, NULL, &found_unit, NULL, NULL, NULL); 2992398f0cdSPeter Wemm if (ret == 0) { 3002398f0cdSPeter Wemm *unit = found_unit; 3012398f0cdSPeter Wemm } 3022398f0cdSPeter Wemm *anchor = newln; 3032398f0cdSPeter Wemm return ret; 3042398f0cdSPeter Wemm } 305