aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/proto
diff options
context:
space:
mode:
authorMarcel Moolenaar <marcel@FreeBSD.org>2015-07-19 23:37:45 +0000
committerMarcel Moolenaar <marcel@FreeBSD.org>2015-07-19 23:37:45 +0000
commitbe00e098188c0dec135fb449334593731abc0033 (patch)
treee753a32b4e0c39d0491cf9ea039c96301f3361f6 /sys/dev/proto
parent97cc6870f68b3bc545dfb78512cc0e771a93fd70 (diff)
downloadsrc-be00e098188c0dec135fb449334593731abc0033.tar.gz
src-be00e098188c0dec135fb449334593731abc0033.zip
Check the hw.proto.attach environment variable for devices that
proto(4) should attach to instead of the normal driver. Document the variable.
Notes
Notes: svn path=/head/; revision=285707
Diffstat (limited to 'sys/dev/proto')
-rw-r--r--sys/dev/proto/proto.h3
-rw-r--r--sys/dev/proto/proto_bus_isa.c7
-rw-r--r--sys/dev/proto/proto_bus_pci.c9
-rw-r--r--sys/dev/proto/proto_core.c58
4 files changed, 70 insertions, 7 deletions
diff --git a/sys/dev/proto/proto.h b/sys/dev/proto/proto.h
index 690d71fff85a..cf89512f6ea7 100644
--- a/sys/dev/proto/proto.h
+++ b/sys/dev/proto/proto.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2014 Marcel Moolenaar
+ * Copyright (c) 2014, 2015 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,6 +61,7 @@ extern char proto_driver_name[];
int proto_add_resource(struct proto_softc *, int, int, struct resource *);
+int proto_probe(device_t dev, const char *prefix, char ***devnamesp);
int proto_attach(device_t dev);
int proto_detach(device_t dev);
diff --git a/sys/dev/proto/proto_bus_isa.c b/sys/dev/proto/proto_bus_isa.c
index 0bbd469c8636..e7438bf1b4d5 100644
--- a/sys/dev/proto/proto_bus_isa.c
+++ b/sys/dev/proto/proto_bus_isa.c
@@ -59,6 +59,9 @@ static driver_t proto_isa_driver = {
sizeof(struct proto_softc),
};
+static char proto_isa_prefix[] = "isa";
+static char **proto_isa_devnames;
+
static int
proto_isa_probe(device_t dev)
{
@@ -77,12 +80,12 @@ proto_isa_probe(device_t dev)
return (ENODEV);
sb = sbuf_new_auto();
- sbuf_printf(sb, "isa:%#lx", rman_get_start(res));
+ sbuf_printf(sb, "%s:%#lx", proto_isa_prefix, rman_get_start(res));
sbuf_finish(sb);
device_set_desc_copy(dev, sbuf_data(sb));
sbuf_delete(sb);
bus_release_resource(dev, type, rid, res);
- return (BUS_PROBE_HOOVER);
+ return (proto_probe(dev, proto_isa_prefix, &proto_isa_devnames));
}
static int
diff --git a/sys/dev/proto/proto_bus_pci.c b/sys/dev/proto/proto_bus_pci.c
index 2d47fe6923b7..38155ce7c624 100644
--- a/sys/dev/proto/proto_bus_pci.c
+++ b/sys/dev/proto/proto_bus_pci.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2014 Marcel Moolenaar
+ * Copyright (c) 2014, 2015 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,6 +59,9 @@ static driver_t proto_pci_driver = {
sizeof(struct proto_softc),
};
+static char proto_pci_prefix[] = "pci";
+static char **proto_pci_devnames;
+
static int
proto_pci_probe(device_t dev)
{
@@ -68,12 +71,12 @@ proto_pci_probe(device_t dev)
return (ENXIO);
sb = sbuf_new_auto();
- sbuf_printf(sb, "pci%d:%d:%d:%d", pci_get_domain(dev),
+ sbuf_printf(sb, "%s%d:%d:%d:%d", proto_pci_prefix, pci_get_domain(dev),
pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
sbuf_finish(sb);
device_set_desc_copy(dev, sbuf_data(sb));
sbuf_delete(sb);
- return (BUS_PROBE_HOOVER);
+ return (proto_probe(dev, proto_pci_prefix, &proto_pci_devnames));
}
static int
diff --git a/sys/dev/proto/proto_core.c b/sys/dev/proto/proto_core.c
index 420df2bd9612..817f58e5aff2 100644
--- a/sys/dev/proto/proto_core.c
+++ b/sys/dev/proto/proto_core.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2014 Marcel Moolenaar
+ * Copyright (c) 2014, 2015 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -120,6 +120,62 @@ proto_intr(void *arg)
#endif
int
+proto_probe(device_t dev, const char *prefix, char ***devnamesp)
+{
+ char **devnames = *devnamesp;
+ const char *dn, *ep, *ev;
+ size_t pfxlen;
+ int idx, names;
+
+ if (devnames == NULL) {
+ pfxlen = strlen(prefix);
+ names = 1; /* NULL pointer */
+ ev = kern_getenv("hw.proto.attach");
+ if (ev != NULL) {
+ dn = ev;
+ while (*dn != '\0') {
+ ep = dn;
+ while (*ep != ',' && *ep != '\0')
+ ep++;
+ if ((ep - dn) > pfxlen &&
+ strncmp(dn, prefix, pfxlen) == 0)
+ names++;
+ dn = (*ep == ',') ? ep + 1 : ep;
+ }
+ }
+ devnames = malloc(names * sizeof(caddr_t), M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ *devnamesp = devnames;
+ if (ev != NULL) {
+ dn = ev;
+ idx = 0;
+ while (*dn != '\0') {
+ ep = dn;
+ while (*ep != ',' && *ep != '\0')
+ ep++;
+ if ((ep - dn) > pfxlen &&
+ strncmp(dn, prefix, pfxlen) == 0) {
+ devnames[idx] = malloc(ep - dn + 1,
+ M_DEVBUF, M_WAITOK | M_ZERO);
+ memcpy(devnames[idx], dn, ep - dn);
+ idx++;
+ }
+ dn = (*ep == ',') ? ep + 1 : ep;
+ }
+ freeenv(__DECONST(char *, ev));
+ }
+ }
+
+ dn = device_get_desc(dev);
+ while (*devnames != NULL) {
+ if (strcmp(dn, *devnames) == 0)
+ return (BUS_PROBE_SPECIFIC);
+ devnames++;
+ }
+ return (BUS_PROBE_HOOVER);
+}
+
+int
proto_attach(device_t dev)
{
struct proto_softc *sc;