git: b8ff248f6595 - main - stand/ofw: Subclass devnet to cope with ofw's unique needs
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 30 Nov 2022 22:31:30 UTC
The branch main has been updated by imp:
URL: https://cgit.FreeBSD.org/src/commit/?id=b8ff248f6595067ef9a31d5d4cec5fb9b9052fc3
commit b8ff248f6595067ef9a31d5d4cec5fb9b9052fc3
Author: Warner Losh <imp@FreeBSD.org>
AuthorDate: 2022-11-30 22:10:05 +0000
Commit: Warner Losh <imp@FreeBSD.org>
CommitDate: 2022-11-30 22:30:33 +0000
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
---
stand/libofw/libofw.h | 1 +
stand/libofw/ofw_net.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++
stand/powerpc/ofw/conf.c | 2 +-
3 files changed, 77 insertions(+), 1 deletion(-)
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
};