pnp.c (38789) | pnp.c (39178) |
---|---|
1/* 2 * mjs copyright 3 */ 4/* 5 * "Plug and Play" functionality. 6 * 7 * We use the PnP enumerators to obtain identifiers for installed hardware, 8 * and the contents of a database to determine modules to be loaded to support 9 * such hardware. 10 */ 11 12#include <stand.h> | 1/* 2 * mjs copyright 3 */ 4/* 5 * "Plug and Play" functionality. 6 * 7 * We use the PnP enumerators to obtain identifiers for installed hardware, 8 * and the contents of a database to determine modules to be loaded to support 9 * such hardware. 10 */ 11 12#include <stand.h> |
13#include <string.h> |
|
13#include <bootstrap.h> 14 15static struct pnpinfo *pnp_devices = NULL; 16 | 14#include <bootstrap.h> 15 16static struct pnpinfo *pnp_devices = NULL; 17 |
17static void pnp_discard(void); | 18static void pnp_discard(struct pnpinfo **list); 19static int pnp_readconf(char *path); 20static int pnp_scankernel(void); |
18 19/* 20 * Perform complete enumeration sweep, and load required module(s) if possible. 21 */ 22 | 21 22/* 23 * Perform complete enumeration sweep, and load required module(s) if possible. 24 */ 25 |
26COMMAND_SET(pnpscan, "pnpscan", "scan for PnP devices", pnp_scan); 27 |
|
23int | 28int |
24pnp_autoload(void) | 29pnp_scan(int argc, char *argv[]) |
25{ | 30{ |
26 int hdlr, idx; | 31 int hdlr; |
27 28 /* forget anything we think we knew */ | 32 33 /* forget anything we think we knew */ |
29 pnp_discard(); | 34 pnp_discard(&pnp_devices); |
30 31 /* iterate over all of the handlers */ | 35 36 /* iterate over all of the handlers */ |
32 for (hdlr = 0; pnphandlers[hdlr]->pp_name != NULL; i++) { | 37 for (hdlr = 0; pnphandlers[hdlr] != NULL; hdlr++) { |
33 printf("Probing bus '%s'...\n", pnphandlers[hdlr]->pp_name); | 38 printf("Probing bus '%s'...\n", pnphandlers[hdlr]->pp_name); |
34 idx = 0; 35 while ((pi = pnphandlers[hdlr]->pp_enumerate(idx++)) != NULL) { 36 printf(" %s\n", pi->pi_ident); 37 pi->pi_handler = hdlr; 38 pi->pi_next = pnp_devices; 39 pnp_devices = pi; 40 } | 39 pnphandlers[hdlr]->pp_enumerate(&pnp_devices); |
41 } | 40 } |
42 /* find anything? */ 43 if (pnp_devices != NULL) { 44 /* XXX hardcoded paths! should use loaddev? */ 45 pnp_readconf("/boot/pnpdata.local"); 46 pnp_readconf("/boot/pnpdata"); 47 48 pnp_reload(); 49 } | 41 return(CMD_OK); |
50} 51 52/* 53 * Try to load outstanding modules (eg. after disk change) 54 */ 55int | 42} 43 44/* 45 * Try to load outstanding modules (eg. after disk change) 46 */ 47int |
56pnp_reload(void) | 48pnp_reload(char *fname) |
57{ 58 struct pnpinfo *pi; 59 char *modfname; 60 | 49{ 50 struct pnpinfo *pi; 51 char *modfname; 52 |
61 /* try to load any modules that have been nominated */ 62 for (pi = pnp_devices; pi != NULL; pi = pi->pi_next) { 63 /* Already loaded? */ 64 if ((pi->pi_module != NULL) && (mod_findmodule(pi->pi_module, NULL) == NULL)) { 65 modfname = malloc(strlen(pi->pi_module + 3)); 66 sprintf(modfname, "%s.ko", pi->pi_module); /* XXX implicit knowledge of KLD module filenames */ 67 if (mod_load(pi->pi_module, pi->pi_argc, pi->pi_argv)) 68 printf("Could not load module '%s' for device '%s'\n", modfname, pi->pi_ident); 69 free(modfname); | 53 /* find anything? */ 54 if (pnp_devices != NULL) { 55 56 /* check for kernel, assign modules handled by static drivers there */ 57 if (pnp_scankernel()) { 58 command_errmsg = "cannot load drivers until kernel loaded"; 59 return(CMD_ERROR); |
70 } | 60 } |
61 if (fname == NULL) { 62 /* default paths */ 63 pnp_readconf("/boot/pnpdata.local"); 64 pnp_readconf("/boot/pnpdata"); 65 } else { 66 if (pnp_readconf("fname")) { 67 sprintf(command_errbuf, "can't read PnP information from '%s'", fname); 68 return(CMD_ERROR); 69 } 70 } 71 72 /* try to load any modules that have been nominated */ 73 for (pi = pnp_devices; pi != NULL; pi = pi->pi_next) { 74 /* Already loaded? */ 75 if ((pi->pi_module != NULL) && (mod_findmodule(pi->pi_module, NULL) == NULL)) { 76 modfname = malloc(strlen(pi->pi_module + 3)); 77 sprintf(modfname, "%s.ko", pi->pi_module); /* XXX implicit knowledge of KLD module filenames */ 78 if (mod_load(pi->pi_module, pi->pi_argc, pi->pi_argv)) 79 printf("Could not load module '%s' for device '%s'\n", modfname, pi->pi_ident->id_ident); 80 free(modfname); 81 } 82 } |
|
71 } | 83 } |
84 return(CMD_OK); |
|
72} 73 | 85} 86 |
74 | |
75/* | 87/* |
76 * Throw away anything we think we know about PnP devices | 88 * Throw away anything we think we know about PnP devices on (list) |
77 */ 78static void | 89 */ 90static void |
79pnp_discard(void) | 91pnp_discard(struct pnpinfo **list) |
80{ 81 struct pnpinfo *pi; | 92{ 93 struct pnpinfo *pi; |
94 struct pnpident *id; |
|
82 | 95 |
83 while (pnp_devices != NULL) { 84 pi = pnp_devices; 85 pnp_devices = pnp_devices->pi_next; 86 if (pi->pi_ident) 87 free(pi->pi_ident); | 96 while (*list != NULL) { 97 pi = *list; 98 *list = (*list)->pi_next; 99 while (pi->pi_ident) { 100 id = pi->pi_ident; 101 pi->pi_ident = pi->pi_ident->id_next; 102 free(id); 103 } |
88 if (pi->pi_module) 89 free(pi->pi_module); 90 if (pi->pi_argv) 91 free(pi->pi_argv); 92 free(pi); 93 } 94} 95 --- 13 unchanged lines hidden (view full) --- 109 * 110 * ident=<identifier> rev=<revision> module=<module> args=<arguments> 111 * 112 * This line describes an identifier:module mapping. The 'ident' 113 * and 'module' fields are required; the 'rev' field is currently 114 * ignored (but should be used), and the 'args' field must come 115 * last. 116 */ | 104 if (pi->pi_module) 105 free(pi->pi_module); 106 if (pi->pi_argv) 107 free(pi->pi_argv); 108 free(pi); 109 } 110} 111 --- 13 unchanged lines hidden (view full) --- 125 * 126 * ident=<identifier> rev=<revision> module=<module> args=<arguments> 127 * 128 * This line describes an identifier:module mapping. The 'ident' 129 * and 'module' fields are required; the 'rev' field is currently 130 * ignored (but should be used), and the 'args' field must come 131 * last. 132 */ |
117static void | 133static int |
118pnp_readconf(char *path) 119{ 120 struct pnpinfo *pi; | 134pnp_readconf(char *path) 135{ 136 struct pnpinfo *pi; |
137 struct pnpident *id; |
|
121 int fd, line; 122 char lbuf[128], *currbus, *ident, *revision, *module, *args; 123 char *cp, *ep, *tp, c; 124 125 /* try to open the file */ 126 if ((fd = open(path, O_RDONLY)) >= 0) { 127 line = 0; 128 currbus = NULL; --- 21 unchanged lines hidden (view full) --- 150 continue; 151 } 152 153 /* XXX should we complain? */ 154 if (currbus == NULL) 155 continue; 156 157 /* mapping */ | 138 int fd, line; 139 char lbuf[128], *currbus, *ident, *revision, *module, *args; 140 char *cp, *ep, *tp, c; 141 142 /* try to open the file */ 143 if ((fd = open(path, O_RDONLY)) >= 0) { 144 line = 0; 145 currbus = NULL; --- 21 unchanged lines hidden (view full) --- 167 continue; 168 } 169 170 /* XXX should we complain? */ 171 if (currbus == NULL) 172 continue; 173 174 /* mapping */ |
158 for (ident = module = args = NULL; *cp != 0;) { | 175 for (ident = module = args = revision = NULL; *cp != 0;) { |
159 160 /* discard leading whitespace */ 161 if (isspace(*cp)) { 162 cp++; 163 continue; 164 } 165 166 /* scan for terminator, separator */ | 176 177 /* discard leading whitespace */ 178 if (isspace(*cp)) { 179 cp++; 180 continue; 181 } 182 183 /* scan for terminator, separator */ |
167 for (ep = cp; (*ep != 0) && (*ep != '=') && !isspace(ep); ep++) | 184 for (ep = cp; (*ep != 0) && (*ep != '=') && !isspace(*ep); ep++) |
168 ; 169 170 if (*ep == '=') { 171 *ep = 0; | 185 ; 186 187 if (*ep == '=') { 188 *ep = 0; |
172 for (tp = ep + 1; (*tp != 0) && !isspace(tp); tp++) | 189 for (tp = ep + 1; (*tp != 0) && !isspace(*tp); tp++) |
173 ; 174 c = *tp; 175 *tp = 0; 176 if ((ident == NULL) && !strcmp(cp, "ident")) { 177 ident = ep + 1; 178 } else if ((revision == NULL) && !strcmp(cp, "revision")) { 179 revision = ep + 1; 180 } else if ((args == NULL) && !strcmp(cp, "args")) { --- 14 unchanged lines hidden (view full) --- 195 196 /* we must have at least ident and module set */ 197 if ((ident == NULL) || (module == NULL)) { 198 printf("%s line %d: bad mapping\n", path, line); 199 continue; 200 } 201 202 /* | 190 ; 191 c = *tp; 192 *tp = 0; 193 if ((ident == NULL) && !strcmp(cp, "ident")) { 194 ident = ep + 1; 195 } else if ((revision == NULL) && !strcmp(cp, "revision")) { 196 revision = ep + 1; 197 } else if ((args == NULL) && !strcmp(cp, "args")) { --- 14 unchanged lines hidden (view full) --- 212 213 /* we must have at least ident and module set */ 214 if ((ident == NULL) || (module == NULL)) { 215 printf("%s line %d: bad mapping\n", path, line); 216 continue; 217 } 218 219 /* |
203 * Loop looking for module/bus that might match this | 220 * Loop looking for module/bus that might match this, but aren't already 221 * assigned. |
204 * XXX no revision parse/test here yet. 205 */ | 222 * XXX no revision parse/test here yet. 223 */ |
206 for (pi = pnp_modules; pi != NULL; pi = pi->pi_next) { 207 if (!strcmp(pnphandlers[pi->pi_handler]->pp_name, currbus) && 208 !strcmp(pi->pi_indent, ident)) { 209 if (args != NULL) 210 if (parse(&pi->pi_argc, &pi->pi_argv, args)) { 211 printf("%s line %d: bad arguments\n", path, line); | 224 for (pi = pnp_devices; pi != NULL; pi = pi->pi_next) { 225 226 /* no driver assigned, bus matches OK */ 227 if ((pi->pi_module == NULL) && 228 !strcmp(pi->pi_handler->pp_name, currbus)) { 229 230 /* scan idents, take first match */ 231 for (id = pi->pi_ident; id != NULL; id = id->id_next) 232 if (!strcmp(id->id_ident, ident)) |
212 break; | 233 break; |
213 } 214 pi->pi_module = strdup(module); | 234 235 /* find a match? */ 236 if (id != NULL) { 237 if (args != NULL) 238 if (parse(&pi->pi_argc, &pi->pi_argv, args)) { 239 printf("%s line %d: bad arguments\n", path, line); 240 continue; 241 } 242 pi->pi_module = strdup(module); 243 printf("use module '%s' for %s:%s\n", module, pi->pi_handler->pp_name, id->id_ident); 244 } |
215 } 216 } 217 } 218 close(fd); 219 } | 245 } 246 } 247 } 248 close(fd); 249 } |
250 return(CMD_OK); |
|
220} 221 | 251} 252 |
253static int 254pnp_scankernel(void) 255{ 256 return(CMD_OK); 257} 258 259/* 260 * Add a unique identifier to (pi) 261 */ 262void 263pnp_addident(struct pnpinfo *pi, char *ident) 264{ 265 struct pnpident *id, **idp; 266 267 if (pi->pi_ident == NULL) { 268 idp = &(pi->pi_ident); 269 } else { 270 for (id = pi->pi_ident; id->id_next != NULL; id = id->id_next) 271 if (!strcmp(id->id_ident, ident)) 272 return; /* already have this one */ 273 ; 274 idp = &(id->id_next); 275 } 276 *idp = malloc(sizeof(struct pnpident)); 277 (*idp)->id_next = NULL; 278 (*idp)->id_ident = strdup(ident); 279} 280 |
|