Home | History | Annotate | Line # | Download | only in ofw
ofw_network_subr.c revision 1.2
      1 /*	$NetBSD: ofw_network_subr.c,v 1.2 2001/11/13 07:26:28 lukem Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *	This product includes software developed by the NetBSD
     22  *	Foundation, Inc. and its contributors.
     23  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  *    contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  * POSSIBILITY OF SUCH DAMAGE.
     38  */
     39 
     40 #include <sys/cdefs.h>
     41 __KERNEL_RCSID(0, "$NetBSD: ofw_network_subr.c,v 1.2 2001/11/13 07:26:28 lukem Exp $");
     42 
     43 #include <sys/param.h>
     44 #include <sys/systm.h>
     45 #include <sys/malloc.h>
     46 #include <sys/socket.h>
     47 
     48 #include <net/if.h>
     49 #include <net/if_media.h>
     50 
     51 #include <dev/ofw/openfirm.h>
     52 
     53 #define	OFW_MAX_STACK_BUF_SIZE	256
     54 #define	OFW_PATH_BUF_SIZE	512
     55 
     56 struct table_entry {
     57 	const char *t_string;
     58 	int t_value;
     59 };
     60 
     61 int	of_network_parse_network_type __P((const char *));
     62 
     63 /*
     64  * int of_network_decode_media(phandle, nmediap, defmediap)
     65  *
     66  * This routine decodes the OFW properties `supported-network-types'
     67  * and `chosen-network-type'.
     68  *
     69  * Arguments:
     70  *	phandle		OFW phandle of device whos network media properties
     71  *			are to be decoded.
     72  *	nmediap		Pointer to an integer which will be initialized
     73  *			with the number of returned media words.
     74  *	defmediap	Pointer to an integer which will be initialized
     75  *			with the default network media.
     76  *
     77  * Return Values:
     78  *	An array of integers, allocated with malloc(), containing the
     79  *	decoded media values.  The number of elements in the array will
     80  *	be stored in the location pointed to by the `nmediap' argument.
     81  *	The default media will be stored in the location pointed to by
     82  *	the `defmediap' argument.
     83  *
     84  * Side Effects:
     85  *	None.
     86  */
     87 int *
     88 of_network_decode_media(phandle, nmediap, defmediap)
     89 	int phandle, *nmediap, *defmediap;
     90 {
     91 	int i, len, count, med, *rv = NULL;
     92 	char *buf = NULL, *cp, *ncp;
     93 
     94 	len = OF_getproplen(phandle, "supported-network-types");
     95 	if (len <= 0)
     96 		return (NULL);
     97 
     98 	buf = malloc(len, M_TEMP, M_WAITOK);
     99 
    100 	/* `supported-network-types' should not change. */
    101 	if (OF_getprop(phandle, "supported-network-types", buf, len) != len)
    102 		goto bad;
    103 
    104 	/*
    105 	 * Count the number of entries in the array.  This is kind of tricky,
    106 	 * because they're variable-length strings, yuck.
    107 	 */
    108 	for (count = 0, cp = buf; cp <= (buf + len); cp++) {
    109 		/*
    110 		 * If we encounter nul, that marks the end of a string,
    111 		 * and thus one complete media description.
    112 		 */
    113 		if (*cp == '\0')
    114 			count++;
    115 	}
    116 
    117 	/* Sanity. */
    118 	if (count == 0)
    119 		goto bad;
    120 
    121 	/* Allocate the return value array. */
    122 	rv = malloc(count * sizeof(int), M_DEVBUF, M_WAITOK);
    123 
    124 	/*
    125 	 * Parse each media string.  If we get -1 back from the parser,
    126 	 * back off the count by one, to skip the bad entry.
    127 	 */
    128 	for (i = 0, cp = buf; cp <= (buf + len) && i < count; ) {
    129 		/*
    130 		 * Find the next string now, as we may chop
    131 		 * the current one up in the parser.
    132 		 */
    133 		for (ncp = cp; *ncp != '\0'; ncp++)
    134 			/* ...skip to the nul... */ ;
    135 		ncp++;	/* ...and now past it. */
    136 
    137 		med = of_network_parse_network_type(cp);
    138 		if (med == -1)
    139 			count--;
    140 		else {
    141 			rv[i] = med;
    142 			i++;
    143 		}
    144 		cp = ncp;
    145 	}
    146 
    147 	/* Sanity... */
    148 	if (count == 0)
    149 		goto bad;
    150 
    151 	/*
    152 	 * We now have the `supported-media-types' property decoded.
    153 	 * Next step is to decode the `chosen-media-type' property,
    154 	 * if it exists.
    155 	 */
    156 	free(buf, M_TEMP);
    157 	buf = NULL;
    158 	len = OF_getproplen(phandle, "chosen-network-type");
    159 	if (len <= 0) {
    160 		/* Property does not exist. */
    161 		*defmediap = -1;
    162 		goto done;
    163 	}
    164 
    165 	buf = malloc(len, M_TEMP, M_WAITOK);
    166 	if (OF_getprop(phandle, "chosen-network-type", buf, len) != len) {
    167 		/* Something went wrong... */
    168 		*defmediap = -1;
    169 		goto done;
    170 	}
    171 
    172 	*defmediap = of_network_parse_network_type(buf);
    173 
    174  done:
    175 	if (buf != NULL)
    176 		free(buf, M_TEMP);
    177 	*nmediap = count;
    178 	return (rv);
    179 
    180  bad:
    181 	if (rv != NULL)
    182 		free(rv, M_DEVBUF);
    183 	if (buf != NULL)
    184 		free(buf, M_TEMP);
    185 	return (NULL);
    186 }
    187 
    188 int
    189 of_network_parse_network_type(cp)
    190 	const char *cp;
    191 {
    192 	/*
    193 	 * We could tokenize this, but that would be a pain in
    194 	 * the neck given how the media are described.  If this
    195 	 * table grows any larger, we may want to consider doing
    196 	 * that.
    197 	 *
    198 	 * Oh yes, we also only support combinations that actually
    199 	 * make sense.
    200 	 */
    201 	static const struct table_entry mediatab[] = {
    202 		{ "ethernet,10,rj45,half",
    203 		  IFM_ETHER|IFM_10_T },
    204 		{ "ethernet,10,rj45,full",
    205 		  IFM_ETHER|IFM_10_T|IFM_FDX },
    206 		{ "ethernet,10,aui,half",
    207 		  IFM_ETHER|IFM_10_5, },
    208 		{ "ethernet,10,bnc,half",
    209 		  IFM_ETHER|IFM_10_2, },
    210 		{ "ethernet,100,rj45,half",
    211 		  IFM_ETHER|IFM_100_TX },
    212 		{ "ethernet,100,rj45,full",
    213 		  IFM_ETHER|IFM_100_TX|IFM_FDX },
    214 		{ NULL, -1 },
    215 	};
    216 	int i;
    217 
    218 	for (i = 0; mediatab[i].t_string != NULL; i++) {
    219 		if (strcmp(cp, mediatab[i].t_string) == 0)
    220 			return (mediatab[i].t_value);
    221 	}
    222 
    223 	/* Not found. */
    224 	return (-1);
    225 }
    226