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
This commit is contained in:
parent
ed3cc2f248
commit
b8ff248f65
@ -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 *);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ struct devsw *devsw[] = {
|
||||
&ofwdisk,
|
||||
#endif
|
||||
#if defined(LOADER_NET_SUPPORT)
|
||||
&netdev,
|
||||
&ofw_netdev,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user