Generic plug-and-play enumerator infrastructure. Query supplied
enumerators, crossreference returned identifiers with a text-format database and automatically load corresponding modules and dependancies.
This commit is contained in:
parent
cefd51ec44
commit
0e02313a88
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=38789
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile.inc,v 1.2 1998/08/31 21:10:42 msmith Exp $
|
||||
# $Id: Makefile.inc,v 1.3 1998/09/01 00:41:24 msmith Exp $
|
||||
|
||||
SRCS+= boot.c commands.c console.c devopen.c interp.c interp_backslash.c
|
||||
SRCS+= interp_parse.c load_aout.c ls.c misc.c module.c panic.c
|
||||
SRCS+= interp_parse.c load_aout.c ls.c misc.c module.c panic.c # pnp.c
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: bootstrap.h,v 1.2 1998/08/31 21:10:42 msmith Exp $
|
||||
* $Id: bootstrap.h,v 1.3 1998/09/03 02:10:07 msmith Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -86,6 +86,29 @@ struct console
|
||||
extern struct console *consoles[];
|
||||
extern void cons_probe(void);
|
||||
|
||||
/*
|
||||
* Plug-and-play enumerator/configurator interface.
|
||||
*/
|
||||
struct pnpinfo
|
||||
{
|
||||
char *pi_ident; /* ASCII identifier, actual format varies with bus/handler */
|
||||
int pi_revision; /* optional revision (or -1) if not supported */
|
||||
char *pi_module; /* module/args nominated to handle device */
|
||||
int pi_argc; /* module arguments */
|
||||
char **pi_argv;
|
||||
int pi_handler; /* handler which detected this device */
|
||||
struct pnpinfo *pi_next;
|
||||
}
|
||||
|
||||
struct pnphandler
|
||||
{
|
||||
char *pp_name; /* handler/bus name */
|
||||
struct pnpinfo *(pp_enumerate *)(int index); /* return a string identifying device (index) */
|
||||
};
|
||||
|
||||
extern struct pnphandler *pnphandlers[]; /* provided by MD code */
|
||||
|
||||
|
||||
/*
|
||||
* Module metadata header.
|
||||
*
|
||||
|
@ -11,7 +11,7 @@
|
||||
* Jordan K. Hubbard
|
||||
* 29 August 1998
|
||||
*
|
||||
* $Id: interp_parse.c,v 1.1 1998/09/01 00:41:24 msmith Exp $
|
||||
* $Id: interp_parse.c,v 1.2 1998/09/03 06:14:41 jkh Exp $
|
||||
*
|
||||
* The meat of the simple parser.
|
||||
*/
|
||||
@ -147,7 +147,7 @@ parse(int *argc, char ***argv, char *str)
|
||||
int len = strlen(val);
|
||||
|
||||
strncpy(buf + i, val, PARSE_BUFSIZE - (i + 1));
|
||||
i += min(len, sizeof(buf) - 1);
|
||||
i += min(len, PARSE_BUFSIZE - 1);
|
||||
}
|
||||
*q = tmp; /* restore value */
|
||||
p = q + (token ? 1 : 0);
|
||||
|
221
sys/boot/common/pnp.c
Normal file
221
sys/boot/common/pnp.c
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* mjs copyright
|
||||
*/
|
||||
/*
|
||||
* "Plug and Play" functionality.
|
||||
*
|
||||
* We use the PnP enumerators to obtain identifiers for installed hardware,
|
||||
* and the contents of a database to determine modules to be loaded to support
|
||||
* such hardware.
|
||||
*/
|
||||
|
||||
#include <stand.h>
|
||||
#include <bootstrap.h>
|
||||
|
||||
static struct pnpinfo *pnp_devices = NULL;
|
||||
|
||||
static void pnp_discard(void);
|
||||
|
||||
/*
|
||||
* Perform complete enumeration sweep, and load required module(s) if possible.
|
||||
*/
|
||||
|
||||
int
|
||||
pnp_autoload(void)
|
||||
{
|
||||
int hdlr, idx;
|
||||
|
||||
/* forget anything we think we knew */
|
||||
pnp_discard();
|
||||
|
||||
/* iterate over all of the handlers */
|
||||
for (hdlr = 0; pnphandlers[hdlr]->pp_name != NULL; i++) {
|
||||
printf("Probing bus '%s'...\n", pnphandlers[hdlr]->pp_name);
|
||||
idx = 0;
|
||||
while ((pi = pnphandlers[hdlr]->pp_enumerate(idx++)) != NULL) {
|
||||
printf(" %s\n", pi->pi_ident);
|
||||
pi->pi_handler = hdlr;
|
||||
pi->pi_next = pnp_devices;
|
||||
pnp_devices = pi;
|
||||
}
|
||||
}
|
||||
/* find anything? */
|
||||
if (pnp_devices != NULL) {
|
||||
/* XXX hardcoded paths! should use loaddev? */
|
||||
pnp_readconf("/boot/pnpdata.local");
|
||||
pnp_readconf("/boot/pnpdata");
|
||||
|
||||
pnp_reload();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to load outstanding modules (eg. after disk change)
|
||||
*/
|
||||
int
|
||||
pnp_reload(void)
|
||||
{
|
||||
struct pnpinfo *pi;
|
||||
char *modfname;
|
||||
|
||||
/* try to load any modules that have been nominated */
|
||||
for (pi = pnp_devices; pi != NULL; pi = pi->pi_next) {
|
||||
/* Already loaded? */
|
||||
if ((pi->pi_module != NULL) && (mod_findmodule(pi->pi_module, NULL) == NULL)) {
|
||||
modfname = malloc(strlen(pi->pi_module + 3));
|
||||
sprintf(modfname, "%s.ko", pi->pi_module); /* XXX implicit knowledge of KLD module filenames */
|
||||
if (mod_load(pi->pi_module, pi->pi_argc, pi->pi_argv))
|
||||
printf("Could not load module '%s' for device '%s'\n", modfname, pi->pi_ident);
|
||||
free(modfname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Throw away anything we think we know about PnP devices
|
||||
*/
|
||||
static void
|
||||
pnp_discard(void)
|
||||
{
|
||||
struct pnpinfo *pi;
|
||||
|
||||
while (pnp_devices != NULL) {
|
||||
pi = pnp_devices;
|
||||
pnp_devices = pnp_devices->pi_next;
|
||||
if (pi->pi_ident)
|
||||
free(pi->pi_ident);
|
||||
if (pi->pi_module)
|
||||
free(pi->pi_module);
|
||||
if (pi->pi_argv)
|
||||
free(pi->pi_argv);
|
||||
free(pi);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The PnP configuration database consists of a flat text file with
|
||||
* entries one per line. Valid lines are:
|
||||
*
|
||||
* # <text>
|
||||
*
|
||||
* This line is a comment, and ignored.
|
||||
*
|
||||
* [<name>]
|
||||
*
|
||||
* Entries following this line are for devices connected to the
|
||||
* bus <name>, At least one such entry must be encountered
|
||||
* before identifiers are recognised.
|
||||
*
|
||||
* ident=<identifier> rev=<revision> module=<module> args=<arguments>
|
||||
*
|
||||
* This line describes an identifier:module mapping. The 'ident'
|
||||
* and 'module' fields are required; the 'rev' field is currently
|
||||
* ignored (but should be used), and the 'args' field must come
|
||||
* last.
|
||||
*/
|
||||
static void
|
||||
pnp_readconf(char *path)
|
||||
{
|
||||
struct pnpinfo *pi;
|
||||
int fd, line;
|
||||
char lbuf[128], *currbus, *ident, *revision, *module, *args;
|
||||
char *cp, *ep, *tp, c;
|
||||
|
||||
/* try to open the file */
|
||||
if ((fd = open(path, O_RDONLY)) >= 0) {
|
||||
line = 0;
|
||||
currbus = NULL;
|
||||
|
||||
while (fgetstr(lbuf, sizeof(lbuf), fd) > 0) {
|
||||
line++;
|
||||
/* Find the first non-space character on the line */
|
||||
for (cp = lbuf; (*cp != 0) && !isspace(*cp); cp++)
|
||||
;
|
||||
|
||||
/* keep/discard? */
|
||||
if ((*cp == 0) || (*cp == '#'))
|
||||
continue;
|
||||
|
||||
/* bus declaration? */
|
||||
if (*cp == '[') {
|
||||
if (((ep = strchr(cp, ']')) == NULL) || ((ep - cp) < 2)) {
|
||||
printf("%s line %d: bad bus specification\n", path, line);
|
||||
} else {
|
||||
if (currbus != NULL)
|
||||
free(currbus);
|
||||
*ep = 0;
|
||||
currbus = strdup(cp + 1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* XXX should we complain? */
|
||||
if (currbus == NULL)
|
||||
continue;
|
||||
|
||||
/* mapping */
|
||||
for (ident = module = args = NULL; *cp != 0;) {
|
||||
|
||||
/* discard leading whitespace */
|
||||
if (isspace(*cp)) {
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* scan for terminator, separator */
|
||||
for (ep = cp; (*ep != 0) && (*ep != '=') && !isspace(ep); ep++)
|
||||
;
|
||||
|
||||
if (*ep == '=') {
|
||||
*ep = 0;
|
||||
for (tp = ep + 1; (*tp != 0) && !isspace(tp); tp++)
|
||||
;
|
||||
c = *tp;
|
||||
*tp = 0;
|
||||
if ((ident == NULL) && !strcmp(cp, "ident")) {
|
||||
ident = ep + 1;
|
||||
} else if ((revision == NULL) && !strcmp(cp, "revision")) {
|
||||
revision = ep + 1;
|
||||
} else if ((args == NULL) && !strcmp(cp, "args")) {
|
||||
*tp = c;
|
||||
while (*tp != 0) /* skip to end of string */
|
||||
tp++;
|
||||
args = ep + 1;
|
||||
} else {
|
||||
/* XXX complain? */
|
||||
}
|
||||
cp = tp;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* it's garbage or a keyword - ignore it for now */
|
||||
cp = ep;
|
||||
}
|
||||
|
||||
/* we must have at least ident and module set */
|
||||
if ((ident == NULL) || (module == NULL)) {
|
||||
printf("%s line %d: bad mapping\n", path, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop looking for module/bus that might match this
|
||||
* XXX no revision parse/test here yet.
|
||||
*/
|
||||
for (pi = pnp_modules; pi != NULL; pi = pi->pi_next) {
|
||||
if (!strcmp(pnphandlers[pi->pi_handler]->pp_name, currbus) &&
|
||||
!strcmp(pi->pi_indent, ident)) {
|
||||
if (args != NULL)
|
||||
if (parse(&pi->pi_argc, &pi->pi_argv, args)) {
|
||||
printf("%s line %d: bad arguments\n", path, line);
|
||||
break;
|
||||
}
|
||||
pi->pi_module = strdup(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user