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); -}