diff options
author | kmacy <kmacy@FreeBSD.org> | 2006-10-05 06:14:28 +0000 |
---|---|---|
committer | kmacy <kmacy@FreeBSD.org> | 2006-10-05 06:14:28 +0000 |
commit | 254e1d0b6bedb639a972924d808f2f973fdee694 (patch) | |
tree | 2ce4fd76148db8274ba002abbc89af40cb4a4a1f /sys/sun4v/mdesc | |
parent | cb2fdfacbdacc1a7c8bf85059a5fa7ba965a6f28 (diff) | |
download | FreeBSD-src-254e1d0b6bedb639a972924d808f2f973fdee694.zip FreeBSD-src-254e1d0b6bedb639a972924d808f2f973fdee694.tar.gz |
placate Grim Reaper with sun4v support
Diffstat (limited to 'sys/sun4v/mdesc')
-rw-r--r-- | sys/sun4v/mdesc/mdesc_bus_if.m | 127 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_bus_subr.c | 133 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_diff.c | 603 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_findname.c | 67 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_findnodeprop.c | 76 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_fini.c | 48 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_getbinsize.c | 46 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_getgen.c | 46 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_getpropdata.c | 65 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_getpropstr.c | 62 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_getpropval.c | 68 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_init.c | 303 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_init_intern.c | 178 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_nodecount.c | 44 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_rootnode.c | 44 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_scandag.c | 191 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_subr.c | 76 | ||||
-rw-r--r-- | sys/sun4v/mdesc/mdesc_vdevfindval.c | 98 |
18 files changed, 2275 insertions, 0 deletions
diff --git a/sys/sun4v/mdesc/mdesc_bus_if.m b/sys/sun4v/mdesc/mdesc_bus_if.m new file mode 100644 index 0000000..9f5df3d --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_bus_if.m @@ -0,0 +1,127 @@ +#- +# Copyright (c) 2001, 2003 by Thomas Moestl <tmm@FreeBSD.org> +# Copyright (c) 2004, 2005 by Marius Strobl <marius@FreeBSD.org> +# Copyright (c) 2006 by Kip Macy <kmacy@FreeBSD.org> +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# $FreeBSD$ + +# Interface for retrieving the package handle and a subset, namely +# 'compatible', 'device_type', 'model' and 'name', of the standard +# properties of a device on an Open Firmware assisted bus for use +# in device drivers. The rest of the standard properties, 'address', +# 'interrupts', 'reg' and 'status', are not covered by this interface +# as they are expected to be only of interest in the respective bus +# driver. + +#include <sys/bus.h> + +#include <machine/cddl/mdesc.h> + +INTERFACE mdesc_bus; + +HEADER { + struct mdesc_bus_devinfo { + char *mbd_compat; + char *mbd_name; + char *mbd_type; + uint64_t mbd_handle; + }; +}; + +CODE { + static mdesc_bus_get_devinfo_t mdesc_bus_default_get_devinfo; + static mdesc_bus_get_compat_t mdesc_bus_default_get_compat; + static mdesc_bus_get_name_t mdesc_bus_default_get_name; + static mdesc_bus_get_type_t mdesc_bus_default_get_type; + + static const struct mdesc_bus_devinfo * + mdesc_bus_default_get_devinfo(device_t bus, device_t dev) + { + + return (NULL); + } + + static const char * + mdesc_bus_default_get_compat(device_t bus, device_t dev) + { + + return (NULL); + } + + static const char * + mdesc_bus_default_get_name(device_t bus, device_t dev) + { + + return (NULL); + } + + static const char * + mdesc_bus_default_get_type(device_t bus, device_t dev) + { + + return (NULL); + } + + static uint64_t + mdesc_bus_default_get_handle(device_t bus, device_t dev) + { + + return (0); + } +}; + +# Get the mdesc_bus_devinfo struct for the device dev on the bus. Used for bus +# drivers which use the generic methods in mdesc_bus_subr.c to implement the +# reset of this interface. The default method will return NULL, which means +# there is no such struct associated with the device. +METHOD const struct mdesc_bus_devinfo * get_devinfo { + device_t bus; + device_t dev; +} DEFAULT mdesc_bus_default_get_devinfo; + +# Get the alternate firmware name for the device dev on the bus. The default +# method will return NULL, which means the device doesn't have such a property. +METHOD const char * get_compat { + device_t bus; + device_t dev; +} DEFAULT mdesc_bus_default_get_compat; + +# Get the firmware name for the device dev on the bus. The default method will +# return NULL, which means the device doesn't have such a property. +METHOD const char * get_name { + device_t bus; + device_t dev; +} DEFAULT mdesc_bus_default_get_name; + +# Get the firmware device type for the device dev on the bus. The default +# method will return NULL, which means the device doesn't have such a property. +METHOD const char * get_type { + device_t bus; + device_t dev; +} DEFAULT mdesc_bus_default_get_type; + +METHOD uint64_t get_handle { + device_t bus; + device_t dev; +} DEFAULT mdesc_bus_default_get_handle; diff --git a/sys/sun4v/mdesc/mdesc_bus_subr.c b/sys/sun4v/mdesc/mdesc_bus_subr.c new file mode 100644 index 0000000..0399168 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_bus_subr.c @@ -0,0 +1,133 @@ +/*- + * Copyright (c) 2006 Kip Macy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/errno.h> +#include <sys/malloc.h> + +#include <machine/mdesc_bus_subr.h> +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + +#include "mdesc_bus_if.h" + +MALLOC_DEFINE(M_MDPROP, "mdesc", "machine description"); + +int +mdesc_bus_gen_setup_devinfo(struct mdesc_bus_devinfo *mbd, mde_cookie_t node) +{ + md_t *mdp; + + if (mbd == NULL) + return (ENOMEM); + + mdp = md_get(); + + /* The 'name' property is considered mandatory. */ + if ((md_get_prop_alloc(mdp, node, "name", MDET_PROP_STR, (uint8_t **)&mbd->mbd_name)) == -1) + return (EINVAL); + md_get_prop_alloc(mdp, node, "compatible", MDET_PROP_DAT, (uint8_t **)&mbd->mbd_compat); + md_get_prop_alloc(mdp, node, "device-type", MDET_PROP_STR, (uint8_t **)&mbd->mbd_type); + md_get_prop_val(mdp, node, "cfg-handle", &mbd->mbd_handle); + + md_put(mdp); + return (0); +} + +void +mdesc_bus_gen_destroy_devinfo(struct mdesc_bus_devinfo *mbd) +{ + + if (mbd == NULL) + return; + if (mbd->mbd_compat != NULL) + free(mbd->mbd_compat, M_MDPROP); + if (mbd->mbd_name != NULL) + free(mbd->mbd_name, M_MDPROP); + if (mbd->mbd_type != NULL) + free(mbd->mbd_type, M_MDPROP); +} + +const char * +mdesc_bus_gen_get_compat(device_t bus, device_t dev) +{ + const struct mdesc_bus_devinfo *mbd; + + mbd = MDESC_BUS_GET_DEVINFO(bus, dev); + if (mbd == NULL) + return (NULL); + return (mbd->mbd_compat); +} + +const char * +mdesc_bus_gen_get_name(device_t bus, device_t dev) +{ + const struct mdesc_bus_devinfo *mbd; + + mbd = MDESC_BUS_GET_DEVINFO(bus, dev); + if (mbd == NULL) + return (NULL); + return (mbd->mbd_name); +} + +const char * +mdesc_bus_gen_get_type(device_t bus, device_t dev) +{ + const struct mdesc_bus_devinfo *mbd; + + mbd = MDESC_BUS_GET_DEVINFO(bus, dev); + if (mbd == NULL) + return (NULL); + return (mbd->mbd_type); +} + +uint64_t +mdesc_bus_gen_get_handle(device_t bus, device_t dev) +{ + const struct mdesc_bus_devinfo *mbd; + + mbd = MDESC_BUS_GET_DEVINFO(bus, dev); + if (mbd == NULL) + return (0); + return (mbd->mbd_handle); +} + + + + + + + + + diff --git a/sys/sun4v/mdesc/mdesc_diff.c b/sys/sun4v/mdesc/mdesc_diff.c new file mode 100644 index 0000000..115016e --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_diff.c @@ -0,0 +1,603 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "@(#)mdesc_diff.c 1.1 06/05/16 SMI" + +#include <sys/types.h> +#ifdef _KERNEL +#include <sys/systm.h> +#else /* _KERNEL */ +#include <string.h> +#include <strings.h> +#endif /* _KERNEL */ +#include <sys/note.h> +#include <sys/mdesc.h> +#include <sys/mdesc_impl.h> + +#define MDD_FREE_CHECK(mdp, ptr, sz) \ + do { \ + if (ptr) mdp->freep(ptr, sz); \ + _NOTE(CONSTCOND) } while (0) + +#define MD_DIFF_MAGIC 0x4D445F4449464621ull /* 'MD_DIFF!' */ +#define MD_DIFF_NOMATCH (-1) +#define MD_DIFF_MATCH (1) + +typedef struct { + mde_cookie_t *mdep; + uint_t nelem; +} md_diff_t; + +typedef struct { + uint64_t mdd_magic; + md_diff_t added; + md_diff_t removed; + md_diff_t match1; + md_diff_t match2; + void *(*allocp)(size_t); + void (*freep)(void *, size_t); +} md_diff_impl_t; + +/* + * Internal utility functions + */ +static int mdd_scan_for_nodes(md_t *mdp, mde_cookie_t start, + char *compnodep, int *countp, mde_cookie_t **nodespp); + +static boolean_t mdd_any_dup_nodes(md_impl_t *mdp, md_prop_match_t *pmp, + int count, mde_cookie_t *nodesp); + +static int mdd_node_list_match(md_impl_t *md1, md_impl_t *md2, + md_element_t *match_nodep, mde_cookie_t *match_listp, + uint8_t *match_seenp, int start, int end, md_prop_match_t *match_elemsp); + +static int mdd_node_compare(md_impl_t *mdap, md_impl_t *mdbp, + md_element_t *nodeap, md_element_t *nodebp, md_prop_match_t *match_elemsp); + +/* + * Given two DAGs and information about how to uniquely identify + * the nodes of interest, determine which nodes have been added + * to the second MD, removed from the first MD, or exist in both + * MDs. This information is recorded and can be accessed using the + * opaque cookie returned to the caller. + */ +md_diff_cookie_t +md_diff_init(md_t *md1p, mde_cookie_t start1, md_t *md2p, mde_cookie_t start2, + char *compnodep, md_prop_match_t *match_fieldsp) +{ + int idx; + md_impl_t *md1 = (md_impl_t *)md1p; + md_impl_t *md2 = (md_impl_t *)md2p; + mde_cookie_t *md1nodesp = NULL; + mde_cookie_t *md2nodesp = NULL; + int md1count = 0; + int md2count = 0; + uint8_t *seenp = NULL; + + /* variables used to gather results */ + md_diff_impl_t *diff_res; + mde_cookie_t *mde_add_scr; + mde_cookie_t *mde_rem_scr; + mde_cookie_t *mde_match1_scr; + mde_cookie_t *mde_match2_scr; + int nadd = 0; + int nrem = 0; + int nmatch = 0; + + /* sanity check params */ + if ((md1p == NULL) || (md2p == NULL)) + return (MD_INVAL_DIFF_COOKIE); + + if ((start1 == MDE_INVAL_ELEM_COOKIE) || + (start2 == MDE_INVAL_ELEM_COOKIE)) + return (MD_INVAL_DIFF_COOKIE); + + if ((compnodep == NULL) || (match_fieldsp == NULL)) + return (MD_INVAL_DIFF_COOKIE); + + /* + * Prepare an array of the matching nodes from the first MD. + */ + if (mdd_scan_for_nodes(md1p, + start1, compnodep, &md1count, &md1nodesp) == -1) + return (MD_INVAL_DIFF_COOKIE); + + /* sanity check that all nodes are unique */ + if (md1nodesp && + mdd_any_dup_nodes(md1, match_fieldsp, md1count, md1nodesp)) { + MDD_FREE_CHECK(md1, md1nodesp, sizeof (mde_cookie_t) * + md1count); + return (MD_INVAL_DIFF_COOKIE); + } + + + /* + * Prepare an array of the matching nodes from the second MD. + */ + if (mdd_scan_for_nodes(md2p, + start2, compnodep, &md2count, &md2nodesp) == -1) + return (MD_INVAL_DIFF_COOKIE); + + /* sanity check that all nodes are unique */ + if (md2nodesp && + mdd_any_dup_nodes(md2, match_fieldsp, md2count, md2nodesp)) { + MDD_FREE_CHECK(md1, md1nodesp, sizeof (mde_cookie_t) * + md1count); + MDD_FREE_CHECK(md2, md2nodesp, sizeof (mde_cookie_t) * + md2count); + return (MD_INVAL_DIFF_COOKIE); + } + + /* setup our result structure */ + diff_res = md1->allocp(sizeof (md_diff_impl_t)); + bzero(diff_res, sizeof (md_diff_impl_t)); + diff_res->allocp = md1->allocp; + diff_res->freep = md1->freep; + diff_res->mdd_magic = MD_DIFF_MAGIC; + + /* + * Special cases for empty lists + */ + if ((md1count == 0) && (md2count != 0)) { + /* all the nodes found were added */ + diff_res->added.mdep = md2nodesp; + diff_res->added.nelem = md2count; + return ((mde_cookie_t)diff_res); + } + + if ((md1count != 0) && (md2count == 0)) { + /* all the nodes found were removed */ + diff_res->removed.mdep = md1nodesp; + diff_res->removed.nelem = md1count; + return ((mde_cookie_t)diff_res); + } + + if ((md1count == 0) && (md2count == 0)) + /* no nodes found */ + return ((mde_cookie_t)diff_res); + + /* + * Both lists have some elements. Allocate some scratch + * buffers to sort them into our three categories, added, + * removed, and matched pairs. + */ + mde_add_scr = diff_res->allocp(sizeof (mde_cookie_t) * md2count); + mde_rem_scr = diff_res->allocp(sizeof (mde_cookie_t) * md1count); + mde_match1_scr = diff_res->allocp(sizeof (mde_cookie_t) * md1count); + mde_match2_scr = diff_res->allocp(sizeof (mde_cookie_t) * md2count); + + /* array of seen flags only needed for md2 */ + seenp = (uint8_t *)diff_res->allocp(sizeof (uint8_t) * md2count); + bzero(seenp, sizeof (uint8_t) * md2count); + + /* + * Make a pass through the md1 node array. Make note of + * any nodes not in the md2 array, indicating that they + * have been removed. Also keep track of the nodes that + * are present in both arrays for the matched pair results. + */ + for (idx = 0; idx < md1count; idx++) { + + md_element_t *elem = &(md1->mdep[md1nodesp[idx]]); + + int match = mdd_node_list_match(md1, md2, elem, md2nodesp, + seenp, 0, md2count - 1, match_fieldsp); + + if (match == MD_DIFF_NOMATCH) + /* record deleted node */ + mde_rem_scr[nrem++] = md1nodesp[idx]; + else { + /* record matched node pair */ + mde_match1_scr[nmatch] = md1nodesp[idx]; + mde_match2_scr[nmatch] = md2nodesp[match]; + nmatch++; + + /* mark that this match has been recorded */ + seenp[match] = 1; + } + } + + /* + * Make a pass through the md2 array. Any nodes that have + * not been marked as seen have been added. + */ + for (idx = 0; idx < md2count; idx++) { + if (!seenp[idx]) + /* record added node */ + mde_add_scr[nadd++] = md2nodesp[idx]; + } + + /* fill in the added node list */ + if (nadd) { + int addsz = sizeof (mde_cookie_t) * nadd; + diff_res->added.mdep = (mde_cookie_t *)diff_res->allocp(addsz); + + bcopy(mde_add_scr, diff_res->added.mdep, addsz); + + diff_res->added.nelem = nadd; + } + + /* fill in the removed node list */ + if (nrem) { + int remsz = sizeof (mde_cookie_t) * nrem; + diff_res->removed.mdep = + (mde_cookie_t *)diff_res->allocp(remsz); + + bcopy(mde_rem_scr, diff_res->removed.mdep, remsz); + diff_res->removed.nelem = nrem; + } + + /* fill in the matching node lists */ + if (nmatch) { + int matchsz = sizeof (mde_cookie_t) * nmatch; + diff_res->match1.mdep = + (mde_cookie_t *)diff_res->allocp(matchsz); + diff_res->match2.mdep = + (mde_cookie_t *)diff_res->allocp(matchsz); + + bcopy(mde_match1_scr, diff_res->match1.mdep, matchsz); + bcopy(mde_match2_scr, diff_res->match2.mdep, matchsz); + diff_res->match1.nelem = nmatch; + diff_res->match2.nelem = nmatch; + } + + /* clean up */ + md1->freep(md1nodesp, sizeof (mde_cookie_t) * md1count); + md2->freep(md2nodesp, sizeof (mde_cookie_t) * md2count); + + diff_res->freep(mde_add_scr, sizeof (mde_cookie_t) * md2count); + diff_res->freep(mde_rem_scr, sizeof (mde_cookie_t) * md1count); + diff_res->freep(mde_match1_scr, sizeof (mde_cookie_t) * md1count); + diff_res->freep(mde_match2_scr, sizeof (mde_cookie_t) * md2count); + + diff_res->freep(seenp, sizeof (uint8_t) * md2count); + + return ((md_diff_cookie_t)diff_res); +} + +/* + * Returns an array of the nodes added to the second MD in a + * previous md_diff_init() call. Returns the number of elements + * in the returned array. If the value is zero, the pointer + * passed back will be NULL. + */ +int +md_diff_added(md_diff_cookie_t mdd, mde_cookie_t **mde_addedp) +{ + md_diff_impl_t *mddp = (md_diff_impl_t *)mdd; + + if ((mddp == NULL) || (mddp->mdd_magic != MD_DIFF_MAGIC)) + return (-1); + + *mde_addedp = mddp->added.mdep; + + return (mddp->added.nelem); +} + +/* + * Returns an array of the nodes removed from the first MD in a + * previous md_diff_init() call. Returns the number of elements + * in the returned array. If the value is zero, the pointer + * passed back will be NULL. + */ +int +md_diff_removed(md_diff_cookie_t mdd, mde_cookie_t **mde_removedp) +{ + md_diff_impl_t *mddp = (md_diff_impl_t *)mdd; + + if ((mddp == NULL) || (mddp->mdd_magic != MD_DIFF_MAGIC)) + return (-1); + + *mde_removedp = mddp->removed.mdep; + + return (mddp->removed.nelem); +} + +/* + * Returns a pair of parallel arrays that contain nodes that were + * considered matching based on the match criteria passed in to + * a previous md_diff_init() call. Returns the number of elements + * in the arrays. If the value is zero, both pointers passed back + * will be NULL. + */ +int +md_diff_matched(md_diff_cookie_t mdd, mde_cookie_t **mde_match1p, + mde_cookie_t **mde_match2p) +{ + md_diff_impl_t *mddp = (md_diff_impl_t *)mdd; + + if ((mddp == NULL) || (mddp->mdd_magic != MD_DIFF_MAGIC)) + return (-1); + + *mde_match1p = mddp->match1.mdep; + *mde_match2p = mddp->match2.mdep; + + return (mddp->match1.nelem); +} + +/* + * Deallocate any storage used to store results of a previous + * md_diff_init() call. Returns 0 on success and -1 on failure. + */ +int +md_diff_fini(md_diff_cookie_t mdd) +{ + md_diff_impl_t *mddp = (md_diff_impl_t *)mdd; + + if ((mddp == NULL) || (mddp->mdd_magic != MD_DIFF_MAGIC)) + return (-1); + + mddp->mdd_magic = 0; + + MDD_FREE_CHECK(mddp, mddp->added.mdep, mddp->added.nelem * + sizeof (mde_cookie_t)); + + MDD_FREE_CHECK(mddp, mddp->removed.mdep, mddp->removed.nelem * + sizeof (mde_cookie_t)); + + MDD_FREE_CHECK(mddp, mddp->match1.mdep, mddp->match1.nelem * + sizeof (mde_cookie_t)); + + MDD_FREE_CHECK(mddp, mddp->match2.mdep, mddp->match2.nelem * + sizeof (mde_cookie_t)); + + mddp->freep(mddp, sizeof (md_diff_impl_t)); + + return (0); +} + +/* + * Walk the "fwd" DAG in an MD and return an array of nodes that are + * of the specified type. The start param is used to start the walk + * from an arbitrary location in the DAG. Returns an array of nodes + * as well as a count of the number of nodes in the array. If the + * count is zero, the node pointer will be passed back as NULL. + * + * Returns: 0 success; -1 failure + */ +static int +mdd_scan_for_nodes(md_t *mdp, + mde_cookie_t start, char *compnodep, int *countp, mde_cookie_t **nodespp) +{ + mde_str_cookie_t cname; + mde_str_cookie_t aname; + md_impl_t *mdip = (md_impl_t *)mdp; + + if (mdip == NULL) + return (-1); + + cname = md_find_name(mdp, compnodep); + aname = md_find_name(mdp, "fwd"); + + /* get the number of nodes of interest in the DAG */ + *countp = md_scan_dag(mdp, start, cname, aname, NULL); + if (*countp == 0) { + *nodespp = NULL; + return (0); + } + + /* allocate the storage */ + *nodespp = mdip->allocp(sizeof (mde_cookie_t) * (*countp)); + + /* populate our array with the matching nodes */ + (void) md_scan_dag(mdp, start, cname, aname, *nodespp); + + return (0); +} + +/* + * Walk an array of nodes and check if there are any duplicate + * nodes. A duplicate is determined based on the specified match + * criteria. Returns B_TRUE if there are any duplicates and B_FALSE + * otherwise. + */ +static boolean_t +mdd_any_dup_nodes(md_impl_t *mdp, md_prop_match_t *pmp, int count, + mde_cookie_t *nodesp) +{ + int idx; + int match; + md_element_t *elem; + + ASSERT(count > 0 || nodesp == NULL); + + for (idx = 0; idx < count; idx++) { + elem = &(mdp->mdep[nodesp[idx]]); + + match = mdd_node_list_match(mdp, mdp, elem, nodesp, NULL, + idx + 1, count - 1, pmp); + + if (match != MD_DIFF_NOMATCH) + return (B_TRUE); + } + + return (B_FALSE); +} + +/* + * Given a node and a array of nodes, compare the node to all elements + * in the specified start-end range of the array. If the node matches + * one of the nodes in the array, return the index of that node. Otherwise + * return MD_DIFF_NOMATCH. + * + * The optional seen array parameter can be used to optimize repeated + * calls to this function. If the seen array indicates that an element + * has already been matched, the full comparison is not necessary. + */ +static int +mdd_node_list_match(md_impl_t *md1, md_impl_t *md2, md_element_t *match_nodep, + mde_cookie_t *match_listp, uint8_t *match_seenp, int start, int end, + md_prop_match_t *match_elemsp) +{ + int match; + int idx; + md_element_t *elem; + + for (idx = start; idx <= end; idx++) { + + if ((match_seenp != NULL) && (match_seenp[idx])) + continue; + + elem = &(md2->mdep[match_listp[idx]]); + + match = mdd_node_compare(md1, md2, match_nodep, elem, + match_elemsp); + if (match == MD_DIFF_MATCH) + return (idx); + } + + return (MD_DIFF_NOMATCH); +} + +/* + * Given two nodes and a list of properties, compare the nodes. + * A match is concluded if both nodes have all of the specified + * properties and all the values of those properties are the + * same. Returns MD_DIFF_NOMATCH if the nodes do not match and + * MD_DIFF_MATCH otherwise. + */ +static int +mdd_node_compare(md_impl_t *mdap, md_impl_t *mdbp, md_element_t *nodeap, + md_element_t *nodebp, md_prop_match_t *match_elemsp) +{ + md_element_t *ap; + md_element_t *bp; + boolean_t nodea_interest; + boolean_t nodeb_interest; + int idx; + + /* make sure we are starting at the beginning of the nodes */ + if ((MDE_TAG(nodeap) != MDET_NODE) || (MDE_TAG(nodebp) != MDET_NODE)) + return (MD_DIFF_NOMATCH); + + for (idx = 0; match_elemsp[idx].type != MDET_LIST_END; idx++) { + + int type; + + nodea_interest = B_FALSE; + nodeb_interest = B_FALSE; + + type = match_elemsp[idx].type; + + /* + * Check node A for the property of interest + */ + for (ap = nodeap; MDE_TAG(ap) != MDET_NODE_END; ap++) { + char *elemname; + + if (MDE_TAG(ap) != type) + continue; + + elemname = mdap->namep + MDE_NAME(ap); + + if (strcmp(elemname, match_elemsp[idx].namep) == 0) { + /* found the property of interest */ + nodea_interest = B_TRUE; + break; + } + } + + /* node A is not of interest */ + if (!nodea_interest) + return (MD_DIFF_NOMATCH); + + /* + * Check node B for the property of interest + */ + for (bp = nodebp; MDE_TAG(bp) != MDET_NODE_END; bp++) { + char *elemname; + + if (MDE_TAG(bp) != type) + continue; + + elemname = mdbp->namep + MDE_NAME(bp); + + if (strcmp(elemname, match_elemsp[idx].namep) == 0) { + nodeb_interest = B_TRUE; + break; + } + } + + /* node B is not of interest */ + if (!nodeb_interest) + return (MD_DIFF_NOMATCH); + + /* + * Both nodes have the property of interest. The + * nodes are not a match unless the value of that + * property match + */ + switch (type) { + case MDET_PROP_VAL: + if (MDE_PROP_VALUE(ap) != MDE_PROP_VALUE(bp)) + return (MD_DIFF_NOMATCH); + break; + + case MDET_PROP_STR: { + char *stra = (char *)(mdap->datap + + MDE_PROP_DATA_OFFSET(ap)); + char *strb = (char *)(mdbp->datap + + MDE_PROP_DATA_OFFSET(bp)); + + if (strcmp(stra, strb) != 0) + return (MD_DIFF_NOMATCH); + break; + } + + case MDET_PROP_DAT: { + + caddr_t dataa; + caddr_t datab; + + if (MDE_PROP_DATA_LEN(ap) != MDE_PROP_DATA_LEN(bp)) + return (MD_DIFF_NOMATCH); + + dataa = (caddr_t)(mdap->datap + + MDE_PROP_DATA_OFFSET(ap)); + datab = (caddr_t)(mdbp->datap + + MDE_PROP_DATA_OFFSET(bp)); + + if (memcmp(dataa, datab, MDE_PROP_DATA_LEN(ap)) != 0) + return (MD_DIFF_NOMATCH); + + break; + } + + default: + /* unsupported prop type */ + return (MD_DIFF_NOMATCH); + } + } + + /* + * All the specified properties exist in both + * nodes and have the same value. The two nodes + * match. + */ + + return (MD_DIFF_MATCH); +} diff --git a/sys/sun4v/mdesc/mdesc_findname.c b/sys/sun4v/mdesc/mdesc_findname.c new file mode 100644 index 0000000..c961619 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_findname.c @@ -0,0 +1,67 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + + +#include <sys/types.h> + +#ifdef _KERNEL +#include <sys/systm.h> +#else +#include <strings.h> +#endif + +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + +mde_str_cookie_t +md_find_name(md_t *ptr, char *namep) +{ + int idx, len; + md_impl_t *mdp; + + mdp = (md_impl_t *)ptr; + + /* + * At some point init should build a local hash table to + * speed these name searches ... for now use brute force + * because the machien descriptions are so small anyway. + */ + + for (idx = 0; idx < mdp->name_blk_size; idx += len) { + char *p; + + p = &(mdp->namep[idx]); + + len = strlen(p)+1; + + if (strcmp(p, namep) == 0) + return ((mde_str_cookie_t)idx); + } + + return (MDE_INVAL_STR_COOKIE); +} diff --git a/sys/sun4v/mdesc/mdesc_findnodeprop.c b/sys/sun4v/mdesc/mdesc_findnodeprop.c new file mode 100644 index 0000000..558b976 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_findnodeprop.c @@ -0,0 +1,76 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#include <sys/types.h> +#include <sys/param.h> +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + +mde_cookie_t +md_find_node_prop(md_impl_t *mdp, + mde_cookie_t node, + mde_str_cookie_t prop_name, + int tag_type) +{ + md_element_t *mdep; + int idx; + + if (node == MDE_INVAL_ELEM_COOKIE || + prop_name == MDE_INVAL_STR_COOKIE) { + return (MDE_INVAL_ELEM_COOKIE); + } + + idx = (int)node; + mdep = &(mdp->mdep[idx]); + + /* Skip over any empty elements */ + while (MDE_TAG(mdep) == MDET_NULL) { + idx++; + mdep++; + } + + /* see if cookie is infact a node */ + if (MDE_TAG(mdep) != MDET_NODE) { + return (MDE_INVAL_ELEM_COOKIE); + } + + /* + * Simply walk the elements in the node + * looking for a property with a matching name. + */ + + for (idx++, mdep++; MDE_TAG(mdep) != MDET_NODE_END; idx++, mdep++) { + if (MDE_TAG(mdep) == tag_type) { + if (MDE_NAME(mdep) == prop_name) { + return ((mde_cookie_t)idx); + } + } + } + + return (MDE_INVAL_ELEM_COOKIE); /* no such property name */ +} diff --git a/sys/sun4v/mdesc/mdesc_fini.c b/sys/sun4v/mdesc/mdesc_fini.c new file mode 100644 index 0000000..ff32ce8 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_fini.c @@ -0,0 +1,48 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "@(#)mdesc_fini.c 1.4 06/05/16 SMI" + +#include <sys/types.h> +#include <sys/mdesc.h> +#include <sys/mdesc_impl.h> + +/* + * Cleanup the internal MD structure. Does not + * deallocate the buffer holding the MD. + */ +int +md_fini(md_t *ptr) +{ + md_impl_t *mdp; + + mdp = (md_impl_t *)ptr; + + mdp->freep(mdp, sizeof (md_impl_t)); + + return (0); +} diff --git a/sys/sun4v/mdesc/mdesc_getbinsize.c b/sys/sun4v/mdesc/mdesc_getbinsize.c new file mode 100644 index 0000000..c3e2386 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_getbinsize.c @@ -0,0 +1,46 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "@(#)mdesc_getbinsize.c 1.1 06/05/16 SMI" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/mdesc.h> +#include <sys/mdesc_impl.h> + +size_t +md_get_bin_size(md_t *ptr) +{ + md_impl_t *mdp; + + mdp = (md_impl_t *)ptr; + + if (mdp == NULL) + return (0); + + return (mdp->size); +} diff --git a/sys/sun4v/mdesc/mdesc_getgen.c b/sys/sun4v/mdesc/mdesc_getgen.c new file mode 100644 index 0000000..7d1ad51 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_getgen.c @@ -0,0 +1,46 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "@(#)mdesc_getgen.c 1.1 06/05/16 SMI" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/mdesc.h> +#include <sys/mdesc_impl.h> + +uint64_t +md_get_gen(md_t *ptr) +{ + md_impl_t *mdp; + + mdp = (md_impl_t *)ptr; + + if (mdp == NULL) + return (MDESC_INVAL_GEN); + + return (mdp->gen); +} diff --git a/sys/sun4v/mdesc/mdesc_getpropdata.c b/sys/sun4v/mdesc/mdesc_getpropdata.c new file mode 100644 index 0000000..199a436 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_getpropdata.c @@ -0,0 +1,65 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "@(#)mdesc_getpropdata.c 1.2 05/06/08 SMI" + +#include <sys/types.h> +#include <sys/mdesc.h> +#include <sys/mdesc_impl.h> + +int +md_get_prop_data(md_t *ptr, mde_cookie_t node, char *namep, + uint8_t **datap, int *lenp) +{ + mde_str_cookie_t prop_name; + md_impl_t *mdp; + mde_cookie_t elem; + + mdp = (md_impl_t *)ptr; + + if (node == MDE_INVAL_ELEM_COOKIE) { + return (-1); + } + + prop_name = md_find_name(ptr, namep); + if (prop_name == MDE_INVAL_STR_COOKIE) { + return (-1); + } + + elem = md_find_node_prop(mdp, node, prop_name, MDET_PROP_DAT); + + if (elem != MDE_INVAL_ELEM_COOKIE) { + md_element_t *mdep; + mdep = &(mdp->mdep[(int)elem]); + + *lenp = (int)MDE_PROP_DATA_LEN(mdep); + *datap = mdp->datap+(int)MDE_PROP_DATA_OFFSET(mdep); + return (0); + } + + return (-1); /* no such property name */ +} diff --git a/sys/sun4v/mdesc/mdesc_getpropstr.c b/sys/sun4v/mdesc/mdesc_getpropstr.c new file mode 100644 index 0000000..61f9c30 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_getpropstr.c @@ -0,0 +1,62 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <sys/types.h> +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + +int +md_get_prop_str(md_t *ptr, mde_cookie_t node, char *namep, char **strp) +{ + mde_str_cookie_t prop_name; + md_impl_t *mdp; + mde_cookie_t elem; + + mdp = (md_impl_t *)ptr; + + if (node == MDE_INVAL_ELEM_COOKIE) { + return (-1); + } + + prop_name = md_find_name(ptr, namep); + if (prop_name == MDE_INVAL_STR_COOKIE) { + return (-1); + } + + elem = md_find_node_prop(mdp, node, prop_name, MDET_PROP_STR); + + if (elem != MDE_INVAL_ELEM_COOKIE) { + md_element_t *mdep; + mdep = &(mdp->mdep[(int)elem]); + + *strp = (char *)(mdp->datap+ + MDE_PROP_DATA_OFFSET(mdep)); + return (0); + } + + return (-1); /* no such property name */ +} diff --git a/sys/sun4v/mdesc/mdesc_getpropval.c b/sys/sun4v/mdesc/mdesc_getpropval.c new file mode 100644 index 0000000..3a17d5c --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_getpropval.c @@ -0,0 +1,68 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#include <sys/types.h> +#ifdef _KERNEL +#include <sys/systm.h> +#else +#include <strings.h> +#endif + +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + +int +md_get_prop_val(md_t *ptr, mde_cookie_t node, char *namep, uint64_t *valp) +{ + mde_str_cookie_t prop_name; + md_impl_t *mdp; + mde_cookie_t elem; + + mdp = (md_impl_t *)ptr; + + if (node == MDE_INVAL_ELEM_COOKIE) { + return (-1); + } + + prop_name = md_find_name(ptr, namep); + if (prop_name == MDE_INVAL_STR_COOKIE) { + return (-1); + } + + elem = md_find_node_prop(mdp, node, prop_name, MDET_PROP_VAL); + + if (elem != MDE_INVAL_ELEM_COOKIE) { + md_element_t *mdep; + mdep = &(mdp->mdep[(int)elem]); + + *valp = MDE_PROP_VALUE(mdep); + return (0); + } + + return (-1); /* no such property name */ +} diff --git a/sys/sun4v/mdesc/mdesc_init.c b/sys/sun4v/mdesc/mdesc_init.c new file mode 100644 index 0000000..4625cd6 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_init.c @@ -0,0 +1,303 @@ +/*- + * Copyright (c) 2006 Kip Macy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/hypervisor_api.h> +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + + +static void mdesc_postvm_init(void *); +/* + * It doesn't really matter when this happens right now + * it just needs to happen before device initialization + * and after VM initialization. Later on we will end up + * doing this statically from pmap_bootstrap so that we + * can kill off all calls to OBP. OBP removal is not in + * the critical path for sun4v at this time. + */ +SYSINIT(mdesc_init, SI_SUB_CPU, SI_ORDER_FIRST, mdesc_postvm_init, NULL); + + +#define UNIMPLEMENTED panic("%s not implemented.", __FUNCTION__) + +typedef struct mdesc_memops_ { + void *(*mm_buf_alloc)(size_t size, size_t align); + void (*mm_buf_free)(void *, size_t size); + void *(*mm_meta_alloc)(size_t size); + void (*mm_meta_free)(void *, size_t size); +} mdesc_memops_t; + +typedef struct mdesc_ { + uint64_t md_gen; /* md-generation# */ + struct mtx md_lock; + void *md_addr; /* address of raw MD */ + uint64_t md_size; /* size of raw MD */ + uint64_t md_buf_size; /* size of buffer allocated for MD */ + int md_refcount; /* reference count */ + mdesc_memops_t *md_memops; /* Memory operations for this MD */ +} mdesc_t; + + + +static mdesc_t *curr_mdesc = NULL; +static struct mtx curr_mdesc_lock; +static mdesc_memops_t *mdesc_memops; + +static void *mdesc_boot_buf_alloc(size_t size, size_t align); +static void mdesc_boot_buf_free(void *buf, size_t align); +static void *mdesc_boot_meta_alloc(size_t size); +static void mdesc_boot_meta_free(void *buf, size_t size); + +static void *mdesc_buf_alloc(size_t size, size_t align); +static void mdesc_buf_free(void *buf, size_t align); +static void *mdesc_meta_alloc(size_t size); +static void mdesc_meta_free(void *buf, size_t size); + +static mdesc_memops_t mdesc_boot_memops = { + mdesc_boot_buf_alloc, + mdesc_boot_buf_free, + mdesc_boot_meta_alloc, + mdesc_boot_meta_free, +}; + +static mdesc_memops_t mdesc_generic_memops = { + mdesc_buf_alloc, + mdesc_buf_free, + mdesc_meta_alloc, + mdesc_meta_free, +}; + +static void * +mdesc_boot_buf_alloc(size_t size, size_t align) +{ + UNIMPLEMENTED; +} + +static void +mdesc_boot_buf_free(void *buf, size_t align) +{ + UNIMPLEMENTED; +} + +static void * +mdesc_boot_meta_alloc(size_t size) +{ + UNIMPLEMENTED; +} + +static void +mdesc_boot_meta_free(void *buf, size_t size) +{ + UNIMPLEMENTED; +} + +static void * +mdesc_buf_alloc(size_t size, size_t align) +{ + return contigmalloc(size, M_MDPROP, M_WAITOK, phys_avail[0], + phys_avail[1], align, (1UL<<34)); +} + +static void +mdesc_buf_free(void *buf, size_t align) +{ + contigfree(buf, PAGE_SIZE /*fix me*/, M_MDPROP); +} + +static void * +mdesc_meta_alloc(size_t size) +{ + return malloc(size, M_MDPROP, M_WAITOK); +} + +static void +mdesc_meta_free(void *buf, size_t size) +{ + free(buf, M_MDPROP); +} + +void +mdesc_init(void) +{ + + mtx_init(&curr_mdesc_lock, "current machine description lock", NULL, MTX_DEF); + mdesc_memops = &mdesc_boot_memops; +} + +static void +mdesc_postvm_init(void *unused) +{ + mdesc_memops = &mdesc_generic_memops; +} + +static mdesc_t * +mdesc_alloc(void) +{ + mdesc_t *mdp; + + mdp = (mdesc_t *)(mdesc_memops->mm_meta_alloc)(sizeof(mdesc_t)); + if (mdp != NULL) { + bzero(mdp, sizeof(*mdp)); + mdp->md_memops = mdesc_memops; + mtx_init(&mdp->md_lock, "machine descriptor lock", NULL, MTX_DEF); + } + + return (mdp); +} + +int +mdesc_update(void) +{ + uint64_t rv; + uint64_t mdesc_size, mdesc_buf_size = 0; + void *buf = NULL; +#ifdef notyet + uint64_t gen; +#endif + do { + if (buf != NULL) + (mdesc_memops->mm_buf_free)(buf, mdesc_buf_size); + + mdesc_size = 0LL; + hv_mach_desc((uint64_t)0, &mdesc_size); + + mdesc_size = mdesc_buf_size = round_page(mdesc_size); + + if ((buf = (*mdesc_memops->mm_buf_alloc)(mdesc_buf_size, PAGE_SIZE)) == NULL) { + rv = -1; + goto done; + } + + rv = hv_mach_desc(vtophys(buf), &mdesc_size); + + if (rv != H_EOK && rv != H_EINVAL) { + rv = -1; + goto done; + } + } while (mdesc_size > mdesc_buf_size); + + KASSERT(rv == H_EOK, ("unexpected return from hv_mach_desc")); + + /* XXX we ignore the generation count... not all versions may + * support it + */ + + if (curr_mdesc->md_refcount == 0) { + (*mdesc_memops->mm_buf_free) (curr_mdesc->md_addr, curr_mdesc->md_size); + } else { + panic("out of date machine description list not implemented"); + } + + mtx_lock(&curr_mdesc_lock); +#ifdef notyet + curr_mdesc->md_gen = gen; +#endif + curr_mdesc->md_addr = buf; + curr_mdesc->md_size = mdesc_size; + curr_mdesc->md_buf_size = mdesc_buf_size; + mtx_unlock(&curr_mdesc_lock); + + return (rv); + + done: + if (buf != NULL) + (*mdesc_memops->mm_buf_free)(buf, mdesc_buf_size); + return (rv); +} + +md_t * +md_get(void) +{ + md_t *mdp; + + + /* + * XXX This should actually happen in init + */ + if (curr_mdesc == NULL) { + if ((curr_mdesc = mdesc_alloc()) == NULL) + panic("machine description allocation failed"); + if (mdesc_update()) + panic("machine description update failed"); + } + + mtx_lock(&curr_mdesc_lock); + curr_mdesc->md_refcount++; + mdp = md_init_intern(curr_mdesc->md_addr, + curr_mdesc->md_memops->mm_meta_alloc, + curr_mdesc->md_memops->mm_meta_free); + mtx_unlock(&curr_mdesc_lock); + + return (mdp); +} + +void +md_put(md_t *ptr) +{ + md_impl_t *mdp; + + mdp = (md_impl_t *)ptr; + +#ifdef notyet + mtx_lock(&curr_mdesc_lock) + + /* XXX check against generation */ + if (curr_mdesc->md_gen == mdp->md_gen) { + curr_mdesc->md_refcount--; + mtx_unlock(&curr_mdesc_lock) + goto done; + } + mtx_unlock(&curr_mdesc_lock); + /* + * MD is on the out of date list + */ + + done: +#endif + /* + * We don't keep an out of date list currently + */ + mtx_lock(&curr_mdesc_lock); + curr_mdesc->md_refcount--; + mtx_unlock(&curr_mdesc_lock); + mdp->freep(mdp, sizeof(md_impl_t)); +} + + diff --git a/sys/sun4v/mdesc/mdesc_init_intern.c b/sys/sun4v/mdesc/mdesc_init_intern.c new file mode 100644 index 0000000..dd5973e --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_init_intern.c @@ -0,0 +1,178 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + +md_t * +md_init_intern(uint64_t *ptr, void *(*allocp)(size_t), + void (*freep)(void *, size_t)) +{ + md_impl_t *mdp; + int idx; + int count; + int done; + uint64_t gen; + mde_str_cookie_t root_name; + + /* + * Very basic checkup for alignment to avoid + * bus error issues. + */ + if ((((uintptr_t)ptr) & 7) != 0) + return (NULL); + + mdp = (md_impl_t *)allocp(sizeof (md_impl_t)); + + if (mdp == NULL) + return (NULL); + + mdp->allocp = allocp; + mdp->freep = freep; + + mdp->caddr = (char *)ptr; + + /* + * setup internal structures + */ + + mdp->headerp = (md_header_t *)mdp->caddr; + + if (mdtoh32(mdp->headerp->transport_version) != MD_TRANSPORT_VERSION) { + goto cleanup_nohash; + } + + mdp->node_blk_size = mdtoh32(mdp->headerp->node_blk_sz); + mdp->name_blk_size = mdtoh32(mdp->headerp->name_blk_sz); + mdp->data_blk_size = mdtoh32(mdp->headerp->data_blk_sz); + + mdp->size = MD_HEADER_SIZE + mdp->node_blk_size + + mdp->name_blk_size + mdp->data_blk_size; + + mdp->mdep = (md_element_t *)(mdp->caddr + MD_HEADER_SIZE); + mdp->namep = (char *)(mdp->caddr + MD_HEADER_SIZE + mdp->node_blk_size); + mdp->datap = (uint8_t *)(mdp->caddr + MD_HEADER_SIZE + + mdp->name_blk_size + mdp->node_blk_size); + + mdp->root_node = MDE_INVAL_ELEM_COOKIE; + + + /* + * Should do a lot more sanity checking here. + */ + + /* + * Should initialize a name hash here if we intend to use one + */ + + /* + * Setup to find the root node + */ + root_name = md_find_name((md_t *)mdp, "root"); + if (root_name == MDE_INVAL_STR_COOKIE) { + goto cleanup; + } + + /* + * One more property we need is the count of nodes in the + * DAG, not just the number of elements. + * + * We try and pickup the root node along the way here. + */ + + for (done = 0, idx = 0, count = 0; !done; ) { + md_element_t *np; + + np = &(mdp->mdep[idx]); + + switch (MDE_TAG(np)) { + case MDET_LIST_END: + done = 1; + break; + + case MDET_NODE: + if (root_name == MDE_NAME(np)) { + if (mdp->root_node != MDE_INVAL_ELEM_COOKIE) { + /* Gah .. more than one root */ + goto cleanup; + } + mdp->root_node = (mde_cookie_t)idx; + } + idx = MDE_PROP_INDEX(np); + count++; + break; + + default: + idx++; /* ignore */ + } + } + + /* + * Ensure there is a root node + */ + if (mdp->root_node == MDE_INVAL_ELEM_COOKIE) { + goto cleanup; + } + + /* + * Register the counts + */ + + mdp->element_count = idx + 1; /* include LIST_END */ + mdp->node_count = count; + + /* + * Final sanity check that everything adds up + */ + if (mdp->element_count != (mdp->node_blk_size / MD_ELEMENT_SIZE)) + goto cleanup; + + mdp->md_magic = LIBMD_MAGIC; + + /* + * Setup MD generation + */ + if (md_get_prop_val((md_t *)mdp, mdp->root_node, + "md-generation#", &gen) != 0) + mdp->gen = MDESC_INVAL_GEN; + else + mdp->gen = gen; + + return ((md_t *)mdp); + +cleanup: + /* + * Clean up here - including a name hash if + * we build one. + */ + +cleanup_nohash: + mdp->freep(mdp, sizeof (md_impl_t)); + return (NULL); +} diff --git a/sys/sun4v/mdesc/mdesc_nodecount.c b/sys/sun4v/mdesc/mdesc_nodecount.c new file mode 100644 index 0000000..1c0376d --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_nodecount.c @@ -0,0 +1,44 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#include <sys/types.h> +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + +int +md_node_count(md_t *ptr) +{ + md_impl_t *mdp; + + mdp = (md_impl_t *)ptr; + + if (mdp->md_magic != LIBMD_MAGIC) + return (-1); + + return (mdp->node_count); +} diff --git a/sys/sun4v/mdesc/mdesc_rootnode.c b/sys/sun4v/mdesc/mdesc_rootnode.c new file mode 100644 index 0000000..2e4437a --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_rootnode.c @@ -0,0 +1,44 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#include <sys/types.h> +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + +mde_cookie_t +md_root_node(md_t *ptr) +{ + md_impl_t *mdp; + + mdp = (md_impl_t *)ptr; + + if (mdp->md_magic != LIBMD_MAGIC) + return (MDE_INVAL_ELEM_COOKIE); + + return (mdp->root_node); +} diff --git a/sys/sun4v/mdesc/mdesc_scandag.c b/sys/sun4v/mdesc/mdesc_scandag.c new file mode 100644 index 0000000..4d7716a --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_scandag.c @@ -0,0 +1,191 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * $FreeBSD$ + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <sys/types.h> +#include <sys/param.h> +#ifdef _KERNEL +#include <sys/systm.h> +#else +#include <string.h> +#include <strings.h> +#endif + +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + +static int +mdl_scan_dag(md_impl_t *mdp, + int nodeidx, + mde_str_cookie_t node_cookie, + mde_str_cookie_t arc_cookie, + uint8_t *dseenp, + int *idxp, + mde_cookie_t *stashp, + int level); + + +int +md_scan_dag(md_t *ptr, + mde_cookie_t startnode, + mde_str_cookie_t node_name_cookie, + mde_str_cookie_t arc_name_cookie, + mde_cookie_t *stashp) +{ + int res; + int idx; + uint8_t *seenp; + md_impl_t *mdp; + int start; + + mdp = (md_impl_t *)ptr; + + /* + * Possible the caller was lazy and didn't check the + * validitiy of either the node name or the arc name + * on calling ... in which case fail to find any + * nodes. + * This is distinct, from a fail (-1) since we return + * that nothing was found. + */ + + if (node_name_cookie == MDE_INVAL_STR_COOKIE || + arc_name_cookie == MDE_INVAL_STR_COOKIE) return 0; + + /* + * if we want to start at the top, start at index 0 + */ + + start = (int)startnode; + if (start == MDE_INVAL_ELEM_COOKIE) start = 0; + + /* + * Scan from the start point until the first node. + */ + while (MDE_TAG(&mdp->mdep[start]) == MDET_NULL) start++; + + /* + * This was a bogus start point if no node found + */ + if (MDE_TAG(&mdp->mdep[start]) != MDET_NODE) { + return (-1); /* illegal start node specified */ + } + + /* + * Allocate a recursion mask on the local stack fail + * if we can't allocate the recursion detection. + */ + seenp = (uint8_t *)mdp->allocp(mdp->element_count); + if (seenp == NULL) + return (-1); + (void) memset(seenp, 0, mdp->element_count); + + /* + * Now build the list of requested nodes. + */ + idx = 0; + res = mdl_scan_dag(mdp, start, + node_name_cookie, arc_name_cookie, + seenp, &idx, stashp, 0); + + mdp->freep(seenp, mdp->element_count); + + return (res >= 0 ? idx : res); +} + + + + + +static int +mdl_scan_dag(md_impl_t *mdp, + int nodeidx, + mde_str_cookie_t node_name_cookie, + mde_str_cookie_t arc_name_cookie, + uint8_t *seenp, + int *idxp, + mde_cookie_t *stashp, + int level) +{ + md_element_t *mdep; + + mdep = &(mdp->mdep[nodeidx]); + + /* see if cookie is infact a node */ + if (MDE_TAG(mdep) != MDET_NODE) + return (-1); + + /* have we been here before ? */ + if (seenp[nodeidx]) + return (0); + seenp[nodeidx] = 1; + + /* is this node of the type we seek ? */ + +#ifdef DEBUG_LIBMDESC + { + int x; + for (x = 0; x < level; x++) + printf("-"); + printf("%d (%s)\n", nodeidx, (char *)(mdp->datap + MDE_NAME(mdep))); + } +#endif + + if (MDE_NAME(mdep) == node_name_cookie) { + /* record the node in the list and keep searching */ + if (stashp != NULL) { + stashp[*idxp] = (mde_cookie_t)nodeidx; + } + (*idxp)++; +#ifdef DEBUG_LIBMDESC + printf("\t* %d\n", *idxp); +#endif + } + + /* + * Simply walk the elements in the node. + * if we find a matching arc, then recursively call + * the subordinate looking for a match + */ + + for (mdep++; MDE_TAG(mdep) != MDET_NODE_END; mdep++) { + if (MDE_TAG(mdep) == MDET_PROP_ARC && + MDE_NAME(mdep) == arc_name_cookie) { + int res; + + res = mdl_scan_dag(mdp, + (int)mdep->d.prop_idx, + node_name_cookie, + arc_name_cookie, + seenp, idxp, stashp, level+1); + + if (res == -1) + return (res); + } + } + + return (0); +} diff --git a/sys/sun4v/mdesc/mdesc_subr.c b/sys/sun4v/mdesc/mdesc_subr.c new file mode 100644 index 0000000..4840708 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_subr.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2006 Kip Macy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/malloc.h> + + +#include <machine/cddl/mdesc.h> +#include <machine/cddl/mdesc_impl.h> + + +int +md_get_prop_alloc(md_t *ptr, mde_cookie_t node, char *namep, int tag_type, + uint8_t **datap) +{ + mde_str_cookie_t prop_name; + md_impl_t *mdp; + mde_cookie_t elem; + int len; + + mdp = (md_impl_t *)ptr; + + if (node == MDE_INVAL_ELEM_COOKIE) { + return (-1); + } + + prop_name = md_find_name(ptr, namep); + if (prop_name == MDE_INVAL_STR_COOKIE) { + return (-1); + } + + elem = md_find_node_prop(mdp, node, prop_name, tag_type); + + if (elem != MDE_INVAL_ELEM_COOKIE) { + md_element_t *mdep; + mdep = &(mdp->mdep[(int)elem]); + + len = (int)MDE_PROP_DATA_LEN(mdep); + KASSERT(len > 0, ("invalid length")); + *datap = malloc(len, M_MDPROP, M_WAITOK); + bcopy(mdp->datap + (int)MDE_PROP_DATA_OFFSET(mdep), *datap, len); + return (0); + } + + return (-1); /* no such property name */ +} + + diff --git a/sys/sun4v/mdesc/mdesc_vdevfindval.c b/sys/sun4v/mdesc/mdesc_vdevfindval.c new file mode 100644 index 0000000..8216996 --- /dev/null +++ b/sys/sun4v/mdesc/mdesc_vdevfindval.c @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2006 Kip Macy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/endian.h> +#include <sys/systm.h> +#include <sys/sockio.h> +#include <sys/mbuf.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/socket.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/taskqueue.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> +#include <sys/rman.h> + +#include <sys/types.h> +#include <sys/param.h> +#include <machine/mdesc_bus.h> +#include <machine/cddl/mdesc.h> + + +int +md_vdev_find_val(device_t dev, char *namep, uint64_t *valp) +{ + uint64_t cfg_handle; + mde_cookie_t rootnode, node, *listp = NULL; + int i, listsz, num_nodes, num_devices, error; + md_t *mdp; + + cfg_handle = mdesc_bus_get_handle(dev); + + if ((mdp = md_get()) == NULL) + return (ENXIO); + + num_nodes = md_node_count(mdp); + listsz = num_nodes * sizeof(mde_cookie_t); + listp = (mde_cookie_t *)malloc(listsz, M_DEVBUF, M_WAITOK); + rootnode = md_root_node(mdp); + node = error = 0; + + num_devices = md_scan_dag(mdp, rootnode, + md_find_name(mdp, "virtual-device"), + md_find_name(mdp, "fwd"), listp); + + if (num_devices == 0) { + error = ENOENT; + goto done; + } + + for (i = 0; i < num_devices; i++) { + uint64_t thandle; + + node = listp[i]; + md_get_prop_val(mdp, node, "cfg-handle", &thandle); + if (thandle == cfg_handle) + break; + } + + md_get_prop_val(mdp, node, namep, valp); +done: + md_put(mdp); + + return (error); +} + |