aboutsummaryrefslogtreecommitdiff
path: root/stand
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2022-11-30 22:10:05 +0000
committerWarner Losh <imp@FreeBSD.org>2022-11-30 22:30:33 +0000
commitb8ff248f6595067ef9a31d5d4cec5fb9b9052fc3 (patch)
treefd49686f811c1f66eb78a2dde53fd9b5aae5f12d /stand
parented3cc2f24829e6c5827f142cfcd9729331a1106c (diff)
downloadsrc-b8ff248f6595067ef9a31d5d4cec5fb9b9052fc3.tar.gz
src-b8ff248f6595067ef9a31d5d4cec5fb9b9052fc3.zip
stand/ofw: Subclass devnet to cope with ofw's unique needs
We need to match devices in a slightly special way: We have to look up the path and see if the device is a 'network' device in order to use it. Sponsored by: Netflix Tested by: grehan@ (with tweaks to my original patch) Differential Revision: https://reviews.freebsd.org/D37557
Diffstat (limited to 'stand')
-rw-r--r--stand/libofw/libofw.h1
-rw-r--r--stand/libofw/ofw_net.c75
-rw-r--r--stand/powerpc/ofw/conf.c2
3 files changed, 77 insertions, 1 deletions
diff --git a/stand/libofw/libofw.h b/stand/libofw/libofw.h
index 0494a78135e7..ce7e6e986029 100644
--- a/stand/libofw/libofw.h
+++ b/stand/libofw/libofw.h
@@ -48,6 +48,7 @@ extern int ofw_getdev(void **vdev, const char *devspec, const char **path);
extern ev_sethook_t ofw_setcurrdev;
extern struct devsw ofwdisk;
+extern struct devsw ofw_netdev;
extern struct netif_driver ofwnet;
int ofwn_getunit(const char *);
diff --git a/stand/libofw/ofw_net.c b/stand/libofw/ofw_net.c
index fa4a3abd88e8..59b9f8de7efb 100644
--- a/stand/libofw/ofw_net.c
+++ b/stand/libofw/ofw_net.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <net.h>
#include <netif.h>
+#include "libofw.h"
#include "openfirm.h"
static int ofwn_probe(struct netif *, void *);
@@ -267,3 +268,77 @@ ofwn_getunit(const char *path)
return -1;
}
#endif
+
+/*
+ * To properly match network devices, we have to subclass the netdev device.
+ * It has a different devdesc than a normal network device (which is fine:
+ * it's a struct superset) and different matching criteria (since it has to
+ * look at the path, find a handle and see if that handle is a network node
+ * or not).
+ */
+
+static int ofwnd_init(void);
+static int ofwnd_parsedev(struct devdesc **, const char *, const char **);
+static bool ofwnd_match(struct devsw *, const char *);
+static char *ofwnd_fmtdev(struct devdesc *);
+
+struct devsw ofw_netdev = {
+ .dv_name = "network",
+ .dv_type = DEVT_NET,
+ .dv_init = ofwnd_init,
+ .dv_match = ofwnd_match,
+ .dv_fmtdev = ofwnd_fmtdev,
+ .dv_parsedev = ofwnd_parsedev,
+};
+
+static int ofwnd_init(void)
+{
+ netdev.dv_init();
+ ofw_netdev.dv_strategy = netdev.dv_strategy;
+ ofw_netdev.dv_open = netdev.dv_open;
+ ofw_netdev.dv_close = netdev.dv_close;
+ ofw_netdev.dv_ioctl = netdev.dv_ioctl;
+ ofw_netdev.dv_print = netdev.dv_print;
+ ofw_netdev.dv_fmtdev = netdev.dv_fmtdev;
+ /* parsedev is unique to ofwnd */
+ /* match is unique to ofwnd */
+ return (0);
+}
+
+static int
+ofwnd_parsedev(struct devdesc **dev, const char *devspec, const char **path)
+{
+ const char *rem_path;
+ struct ofw_devdesc *idev;
+
+ if (ofw_path_to_handle(devspec, ofw_netdev.dv_name, &rem_path) == -1)
+ return (ENOENT);
+ idev = malloc(sizeof(struct ofw_devdesc));
+ if (idev == NULL) {
+ printf("ofw_parsedev: malloc failed\n");
+ return ENOMEM;
+ };
+ strlcpy(idev->d_path, devspec, min(rem_path - devspec + 1,
+ sizeof(idev->d_path)));
+ if (dev != NULL)
+ *dev = &idev->dd;
+ if (path != NULL)
+ *path = rem_path;
+ return 0;
+}
+
+static bool
+ofwnd_match(struct devsw *devsw, const char *devspec)
+{
+ const char *path;
+
+ return (ofw_path_to_handle(devspec, devsw->dv_name, &path) != -1);
+}
+
+static char *
+ofwnd_fmtdev(struct devdesc *idev)
+{
+ struct ofw_devdesc *dev = (struct ofw_devdesc *)idev;
+
+ return (dev->d_path);
+}
diff --git a/stand/powerpc/ofw/conf.c b/stand/powerpc/ofw/conf.c
index a472faeed97b..c2b28f4fe0f0 100644
--- a/stand/powerpc/ofw/conf.c
+++ b/stand/powerpc/ofw/conf.c
@@ -54,7 +54,7 @@ struct devsw *devsw[] = {
&ofwdisk,
#endif
#if defined(LOADER_NET_SUPPORT)
- &netdev,
+ &ofw_netdev,
#endif
NULL
};