Module Name: src
Committed By: thorpej
Date: Sun Jan 24 20:09:03 UTC 2021
Modified Files:
src/sys/dev/ofw: ofw_network_subr.c
Log Message:
Rewrite of_network_decode_media() to use strlist_next() and
device_compatible_lookup().
To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/ofw/ofw_network_subr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ofw/ofw_network_subr.c
diff -u src/sys/dev/ofw/ofw_network_subr.c:1.8 src/sys/dev/ofw/ofw_network_subr.c:1.9
--- src/sys/dev/ofw/ofw_network_subr.c:1.8 Wed May 29 06:21:57 2019
+++ src/sys/dev/ofw/ofw_network_subr.c Sun Jan 24 20:09:03 2021
@@ -1,7 +1,7 @@
-/* $NetBSD: ofw_network_subr.c,v 1.8 2019/05/29 06:21:57 msaitoh Exp $ */
+/* $NetBSD: ofw_network_subr.c,v 1.9 2021/01/24 20:09:03 thorpej Exp $ */
/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 2021 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -31,27 +31,40 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ofw_network_subr.c,v 1.8 2019/05/29 06:21:57 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ofw_network_subr.c,v 1.9 2021/01/24 20:09:03 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/socket.h>
+#include <sys/device.h>
#include <net/if.h>
#include <net/if_media.h>
#include <dev/ofw/openfirm.h>
-#define OFW_MAX_STACK_BUF_SIZE 256
-#define OFW_PATH_BUF_SIZE 512
+static const struct device_compatible_entry media_compat[] = {
+ { .compat = "ethernet,10,rj45,half",
+ .value = IFM_ETHER | IFM_10_T },
-struct table_entry {
- const char *t_string;
- int t_value;
-};
+ { .compat = "ethernet,10,rj45,full",
+ .value = IFM_ETHER | IFM_10_T | IFM_FDX },
+
+ { .compat = "ethernet,10,aui,half",
+ .value = IFM_ETHER | IFM_10_5 },
+
+ { .compat = "ethernet,10,bnc,half",
+ .value = IFM_ETHER | IFM_10_2 },
-int of_network_parse_network_type(const char *);
+ { .compat = "ethernet,100,rj45,half",
+ .value = IFM_ETHER | IFM_100_TX },
+
+ { .compat = "ethernet,100,rj45,full",
+ .value = IFM_ETHER | IFM_100_TX | IFM_FDX },
+
+ { 0 }
+};
/*
* int of_network_decode_media(phandle, nmediap, defmediap)
@@ -80,73 +93,52 @@ int of_network_parse_network_type(const
int *
of_network_decode_media(int phandle, int *nmediap, int *defmediap)
{
- int i, len, count, med, *rv = NULL;
- char *buf = NULL, *cp, *ncp;
+ const struct device_compatible_entry *dce;
+ int nmedia, len, *rv = NULL;
+ char *sl = NULL;
+ const char *cp;
+ size_t cursor;
+ unsigned int count;
len = OF_getproplen(phandle, "supported-network-types");
if (len <= 0)
return (NULL);
- buf = malloc(len, M_TEMP, M_WAITOK);
+ sl = malloc(len, M_TEMP, M_WAITOK);
/* `supported-network-types' should not change. */
- if (OF_getprop(phandle, "supported-network-types", buf, len) != len)
+ if (OF_getprop(phandle, "supported-network-types", sl, len) != len)
goto bad;
- /*
- * Count the number of entries in the array. This is kind of tricky,
- * because they're variable-length strings, yuck.
- */
- for (count = 0, cp = buf; cp <= (buf + len); cp++) {
- /*
- * If we encounter nul, that marks the end of a string,
- * and thus one complete media description.
- */
- if (*cp == '\0')
- count++;
- }
+ count = strlist_count(sl, len);
- /* Sanity. */
if (count == 0)
goto bad;
/* Allocate the return value array. */
rv = malloc(count * sizeof(int), M_DEVBUF, M_WAITOK);
- /*
- * Parse each media string. If we get -1 back from the parser,
- * back off the count by one, to skip the bad entry.
- */
- for (i = 0, cp = buf; cp <= (buf + len) && i < count; ) {
- /*
- * Find the next string now, as we may chop
- * the current one up in the parser.
- */
- for (ncp = cp; *ncp != '\0'; ncp++)
- /* ...skip to the nul... */ ;
- ncp++; /* ...and now past it. */
-
- med = of_network_parse_network_type(cp);
- if (med == -1)
- count--;
- else {
- rv[i] = med;
- i++;
+ /* Parse each media string. */
+ for (nmedia = 0, cursor = 0;
+ (cp = strlist_next(sl, len, &cursor)) != NULL; ) {
+ dce = device_compatible_lookup(&cp, 1, media_compat);
+ if (dce != NULL) {
+ rv[nmedia++] = (int)dce->value;
}
- cp = ncp;
}
-
/* Sanity... */
- if (count == 0)
+ if (nmedia == 0)
goto bad;
+ free(sl, M_TEMP);
+ sl = NULL;
+
/*
* We now have the `supported-media-types' property decoded.
* Next step is to decode the `chosen-media-type' property,
* if it exists.
*/
- free(buf, M_TEMP);
- buf = NULL;
+ *defmediap = -1;
len = OF_getproplen(phandle, "chosen-network-type");
if (len <= 0) {
/* Property does not exist. */
@@ -154,63 +146,28 @@ of_network_decode_media(int phandle, int
goto done;
}
- buf = malloc(len, M_TEMP, M_WAITOK);
- if (OF_getprop(phandle, "chosen-network-type", buf, len) != len) {
+ sl = malloc(len, M_TEMP, M_WAITOK);
+ if (OF_getprop(phandle, "chosen-network-type", sl, len) != len) {
/* Something went wrong... */
- *defmediap = -1;
goto done;
}
- *defmediap = of_network_parse_network_type(buf);
+ cp = sl;
+ dce = device_compatible_lookup(&cp, 1, media_compat);
+ if (dce != NULL) {
+ *defmediap = (int)dce->value;
+ }
done:
- if (buf != NULL)
- free(buf, M_TEMP);
- *nmediap = count;
+ if (sl != NULL)
+ free(sl, M_TEMP);
+ *nmediap = nmedia;
return (rv);
bad:
if (rv != NULL)
free(rv, M_DEVBUF);
- if (buf != NULL)
- free(buf, M_TEMP);
+ if (sl != NULL)
+ free(sl, M_TEMP);
return (NULL);
}
-
-int
-of_network_parse_network_type(const char *cp)
-{
- /*
- * We could tokenize this, but that would be a pain in
- * the neck given how the media are described. If this
- * table grows any larger, we may want to consider doing
- * that.
- *
- * Oh yes, we also only support combinations that actually
- * make sense.
- */
- static const struct table_entry mediatab[] = {
- { "ethernet,10,rj45,half",
- IFM_ETHER | IFM_10_T },
- { "ethernet,10,rj45,full",
- IFM_ETHER | IFM_10_T | IFM_FDX },
- { "ethernet,10,aui,half",
- IFM_ETHER | IFM_10_5, },
- { "ethernet,10,bnc,half",
- IFM_ETHER | IFM_10_2, },
- { "ethernet,100,rj45,half",
- IFM_ETHER | IFM_100_TX },
- { "ethernet,100,rj45,full",
- IFM_ETHER | IFM_100_TX | IFM_FDX },
- { NULL, -1 },
- };
- int i;
-
- for (i = 0; mediatab[i].t_string != NULL; i++) {
- if (strcmp(cp, mediatab[i].t_string) == 0)
- return (mediatab[i].t_value);
- }
-
- /* Not found. */
- return (-1);
-}