Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Dec 2015 08:17:50 +0000 (UTC)
From:      Michal Meloun <mmel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r292156 - head/sys/dev/ofw
Message-ID:  <201512130817.tBD8HoRS053771@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mmel
Date: Sun Dec 13 08:17:49 2015
New Revision: 292156
URL: https://svnweb.freebsd.org/changeset/base/292156

Log:
  OFW: Add helper functions for parsing xref based lists.
  By using this functions, we can parse a list of tuples, each of them holds
  xref and variable number of values.
  This kind of list is used in DT for clocks, gpios, resets ...
  
  Discussed with:	ian, nwhitehorn
  Approved by:	kib (mentor)
  Differential Revision: https://reviews.freebsd.org/D4316

Modified:
  head/sys/dev/ofw/ofw_bus_subr.c
  head/sys/dev/ofw/ofw_bus_subr.h

Modified: head/sys/dev/ofw/ofw_bus_subr.c
==============================================================================
--- head/sys/dev/ofw/ofw_bus_subr.c	Sun Dec 13 07:39:49 2015	(r292155)
+++ head/sys/dev/ofw/ofw_bus_subr.c	Sun Dec 13 08:17:49 2015	(r292156)
@@ -607,3 +607,134 @@ ofw_bus_find_child_device_by_phandle(dev
 
 	return (retval);
 }
+
+/*
+ * Parse property that contain list of xrefs and values
+ * (like standard "clocks" and "resets" properties)
+ * Input arguments:
+ *  node - consumers device node
+ *  list_name  - name of parsed list - "clocks"
+ *  cells_name - name of size property - "#clock-cells"
+ * Output arguments:
+ *  producer - handle of producer
+ *  ncells   - number of cells in result
+ *  cells    - array of decoded cells
+ */
+int
+ofw_bus_parse_xref_list_alloc(phandle_t node, const char *list_name,
+    const char *cells_name, int idx, phandle_t *producer, int *ncells,
+    pcell_t **cells)
+{
+	phandle_t pnode;
+	phandle_t *elems;
+	uint32_t  pcells;
+	int rv, i, j, nelems, cnt;
+
+	elems = NULL;
+	nelems = OF_getencprop_alloc(node, list_name,  sizeof(*elems),
+	    (void **)&elems);
+	if (nelems <= 0)
+		return (ENOENT);
+	rv = ENOENT;
+	for (i = 0, cnt = 0; i < nelems; i += pcells, cnt++) {
+		pnode = elems[i++];
+		if (OF_getencprop(OF_node_from_xref(pnode),
+		    cells_name, &pcells, sizeof(pcells)) == -1) {
+			printf("Missing %s property\n", cells_name);
+			rv = ENOENT;
+			break;
+		}
+
+		if ((i + pcells) > nelems) {
+			printf("Invalid %s property value <%d>\n", cells_name,
+			    pcells);
+			rv = ERANGE;
+			break;
+		}
+		if (cnt == idx) {
+			*cells= malloc(pcells * sizeof(**cells), M_OFWPROP,
+			    M_WAITOK);
+			*producer = pnode;
+			*ncells = pcells;
+			for (j = 0; j < pcells; j++)
+				(*cells)[j] = elems[i + j];
+			rv = 0;
+			break;
+		}
+	}
+	if (elems != NULL)
+		free(elems, M_OFWPROP);
+	return (rv);
+}
+
+/*
+ * Find index of string in string list property (case sensitive).
+ */
+int
+ofw_bus_find_string_index(phandle_t node, const char *list_name,
+    const char *name, int *idx)
+{
+	char *elems;
+	int rv, i, cnt, nelems;
+
+	elems = NULL;
+	nelems = OF_getprop_alloc(node, list_name, 1, (void **)&elems);
+	if (nelems <= 0)
+		return (ENOENT);
+
+	rv = ENOENT;
+	for (i = 0, cnt = 0; i < nelems; cnt++) {
+		if (strcmp(elems + i, name) == 0) {
+			*idx = cnt;
+			rv = 0;
+			break;
+		}
+		i += strlen(elems + i) + 1;
+	}
+
+	if (elems != NULL)
+		free(elems, M_OFWPROP);
+	return (rv);
+}
+
+/*
+ * Create zero terminated array of strings from string list property.
+ */
+int
+ofw_bus_string_list_to_array(phandle_t node, const char *list_name,
+   const char ***array)
+{
+	char *elems, *tptr;
+	int i, cnt, nelems, len;
+
+	elems = NULL;
+	nelems = OF_getprop_alloc(node, list_name, 1, (void **)&elems);
+	if (nelems <= 0)
+		return (nelems);
+
+	/* Count number of strings. */
+	for (i = 0, cnt = 0; i < nelems; cnt++)
+		i += strlen(elems + i) + 1;
+
+	/* Allocate space for arrays and all strings. */
+	*array = malloc((cnt + 1) * sizeof(char *) + nelems, M_OFWPROP,
+	    M_WAITOK);
+
+	/* Get address of first string. */
+	tptr = (char *)(*array + cnt);
+
+	/* Copy strings. */
+	memcpy(tptr, elems, nelems);
+	free(elems, M_OFWPROP);
+
+	/* Fill string pointers. */
+	for (i = 0, cnt = 0; i < nelems; cnt++) {
+		len = strlen(tptr + i) + 1;
+		*array[cnt] = tptr;
+		i += len;
+		tptr += len;
+	}
+	*array[cnt] = 0;
+
+	return (cnt);
+}

Modified: head/sys/dev/ofw/ofw_bus_subr.h
==============================================================================
--- head/sys/dev/ofw/ofw_bus_subr.h	Sun Dec 13 07:39:49 2015	(r292155)
+++ head/sys/dev/ofw/ofw_bus_subr.h	Sun Dec 13 08:17:49 2015	(r292156)
@@ -110,4 +110,13 @@ phandle_t ofw_bus_find_child(phandle_t, 
 /* Helper routine to find a device_t child matchig a given phandle_t */
 device_t ofw_bus_find_child_device_by_phandle(device_t bus, phandle_t node);
 
+/* Helper routines for parsing lists  */
+int ofw_bus_parse_xref_list_alloc(phandle_t node, const char *list_name,
+    const char *cells_name, int idx, phandle_t *producer, int *ncells,
+    pcell_t **cells);
+int ofw_bus_find_string_index(phandle_t node, const char *list_name,
+    const char *name, int *idx);
+int ofw_bus_string_list_to_array(phandle_t node, const char *list_name,
+    const char ***array);
+
 #endif /* !_DEV_OFW_OFW_BUS_SUBR_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201512130817.tBD8HoRS053771>