This implements simple device probing.
I have discussed this with deraadt@ and then later with kettenis@
and mpi@ and we've decided that OpenFirmware emulation would be a
bit too much (at least for now).
This is a work in progress, it will improve a bit once we start
working on the Netfront network interface.
OK?
---
sys/dev/pv/xen.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
sys/dev/pv/xenvar.h | 6 +++++
2 files changed, 73 insertions(+)
diff --git sys/dev/pv/xen.c sys/dev/pv/xen.c
index c78cc75..8523e03 100644
--- sys/dev/pv/xen.c
+++ sys/dev/pv/xen.c
@@ -47,10 +47,11 @@ void xen_disable_emulated_devices(struct xen_softc
*);
int xen_match(struct device *, void *, void *);
void xen_attach(struct device *, struct device *, void *);
void xen_deferred(void *);
void xen_resume(struct device *);
int xen_activate(struct device *, int);
+int xen_probe_devices(struct xen_softc *);
int xs_attach(struct xen_softc *);
struct cfdriver xen_cd = {
NULL, "xen", DV_DULL
@@ -107,10 +108,12 @@ xen_attach(struct device *parent, struct device *self,
void *aux)
if (xs_attach(sc))
return;
xen_disable_emulated_devices(sc);
+ xen_probe_devices(sc);
+
mountroothook_establish(xen_deferred, sc);
}
void
xen_deferred(void *arg)
@@ -721,10 +724,74 @@ xen_intr_enable(void)
sc->sc_dev.dv_xname, xi->xi_port);
}
}
}
+static int
+xen_attach_print(void *aux, const char *name)
+{
+ struct xen_attach_args *xa = aux;
+
+ if (name)
+ printf("\"%s\" at %s: %s", xa->xa_name, name, xa->xa_node);
+
+ return (UNCONF);
+}
+
+int
+xen_probe_devices(struct xen_softc *sc)
+{
+ struct xen_attach_args xa;
+ struct xs_transaction xst;
+ struct iovec *iovp1, *iovp2;
+ int error = 0, iov1_cnt, iov2_cnt, i, j;
+ char path[64];
+
+ memset(&xst, 0, sizeof(xst));
+ xst.xst_id = 0;
+ xst.xst_sc = sc->sc_xs;
+ xst.xst_flags |= XST_POLL;
+
+ if ((error = xs_cmd(&xst, XS_DIRECTORY, "device", &iovp1,
+ &iov1_cnt)) != 0)
+ return (error);
+
+ for (i = 0; i < iov1_cnt; i++) {
+ /* Special handling */
+ if (!strcmp("suspend", (char *)iovp1[i].iov_base)) {
+ xa.xa_parent = sc;
+ strlcpy(xa.xa_name, (char *)iovp1[i].iov_base,
+ sizeof(xa.xa_name));
+ snprintf(xa.xa_node, sizeof(xa.xa_node), "device/%s",
+ (char *)iovp1[i].iov_base);
+ config_found((struct device *)sc, &xa,
+ xen_attach_print);
+ continue;
+ }
+ snprintf(path, sizeof(path), "device/%s",
+ (char *)iovp1[i].iov_base);
+ if ((error = xs_cmd(&xst, XS_DIRECTORY, path, &iovp2,
+ &iov2_cnt)) != 0) {
+ xs_resfree(&xst, iovp1, iov1_cnt);
+ return (error);
+ }
+ for (j = 0; j < iov2_cnt; j++) {
+ xa.xa_parent = sc;
+ strlcpy(xa.xa_name, (char *)iovp1[i].iov_base,
+ sizeof(xa.xa_name));
+ snprintf(xa.xa_node, sizeof(xa.xa_node), "device/%s/%s",
+ (char *)iovp1[i].iov_base,
+ (char *)iovp2[j].iov_base);
+ config_found((struct device *)sc, &xa,
+ xen_attach_print);
+ }
+ xs_resfree(&xst, iovp2, iov2_cnt);
+ }
+
+ return (error);
+}
+
#include <machine/pio.h>
#define XMI_PORT 0x10
#define XMI_MAGIC 0x49d2
#define XMI_UNPLUG_IDE 0x01
diff --git sys/dev/pv/xenvar.h sys/dev/pv/xenvar.h
index 9d73921..0e62dd9 100644
--- sys/dev/pv/xenvar.h
+++ sys/dev/pv/xenvar.h
@@ -55,10 +55,16 @@ struct xen_softc {
struct xs_softc *sc_xs; /* xenstore softc */
};
extern struct xen_softc *xen_sc;
+struct xen_attach_args {
+ void *xa_parent;
+ char xa_name[16];
+ char xa_node[64];
+};
+
/*
* Hypercalls
*/
#define memory_op 12
#define xen_version 17
--
2.6.3