aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Smith <msmith@FreeBSD.org>1998-09-04 02:43:26 +0000
committerMike Smith <msmith@FreeBSD.org>1998-09-04 02:43:26 +0000
commit0e02313a883de4755ade7c1872996354d0135762 (patch)
tree95918dc8bd8e43899ecdbd96f80e58c618ff19a0
parentcefd51ec44292b8783adfd5cb1c5994e40c55595 (diff)
downloadsrc-0e02313a883de4755ade7c1872996354d0135762.tar.gz
src-0e02313a883de4755ade7c1872996354d0135762.zip
Generic plug-and-play enumerator infrastructure. Query supplied
enumerators, crossreference returned identifiers with a text-format database and automatically load corresponding modules and dependancies.
Notes
Notes: svn path=/head/; revision=38789
-rw-r--r--sys/boot/common/Makefile.inc4
-rw-r--r--sys/boot/common/bootstrap.h25
-rw-r--r--sys/boot/common/interp_parse.c4
-rw-r--r--sys/boot/common/pnp.c221
4 files changed, 249 insertions, 5 deletions
diff --git a/sys/boot/common/Makefile.inc b/sys/boot/common/Makefile.inc
index ea7679d04ca9..8826353c715a 100644
--- a/sys/boot/common/Makefile.inc
+++ b/sys/boot/common/Makefile.inc
@@ -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
diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h
index 770ecfd3b609..0d7950cd03f9 100644
--- a/sys/boot/common/bootstrap.h
+++ b/sys/boot/common/bootstrap.h
@@ -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>
@@ -87,6 +87,29 @@ 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.
*
* Metadata are allocated on our heap, and copied into kernel space
diff --git a/sys/boot/common/interp_parse.c b/sys/boot/common/interp_parse.c
index 57aa68151a63..a985bc568ca1 100644
--- a/sys/boot/common/interp_parse.c
+++ b/sys/boot/common/interp_parse.c
@@ -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);
diff --git a/sys/boot/common/pnp.c b/sys/boot/common/pnp.c
new file mode 100644
index 000000000000..d0b606108d50
--- /dev/null
+++ b/sys/boot/common/pnp.c
@@ -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);
+ }
+}
+