/*
* 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
* 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
*/
/*
*/
/*
* Topology Plugin Modules
*
* Topology plugin modules are shared libraries that are dlopen'd and
* used to enumerate resources in the system and export per-node method
* operations.
*
* They are loaded by our builtin scheme-specific plugins, other modules or
* by processing a topo map XML file to enumerate and create nodes for
* resources that are present in the system. They may also export a set of
* topology node specific methods that can be invoked directly via
* topo_method_invoke() or indirectly via the
* topo_prop_get* family of functions to access dynamic property data.
*
* Module Plugin API
*
* Enumerators must provide entry points for initialization and clean-up
* (_topo_init() and _topo_fini()). In their _topo_init() function, an
* enumerator should register (topo_mod_register()) its enumeration callback
* and allocate resources required for a subsequent call to the callback.
* Optionally, methods may also be registered with topo_method_register().
*
* In its enumeration callback routine, the module should search for resources
* within its realm of responsibility and create any node ranges,
* topo_node_range_create() and nodes, topo_node_bind(). The Enumerator
* module is handed a node to which it may begin attaching additional
* topology nodes. The enumerator may only access those nodes within its
* current scope of operation: the node passed into its enumeration op and
* any nodes it creates during enumeration. If the enumerator requires walker-
* style access to these nodes, it must use
* topo_mod_walk_init()/topo_walk_step()/topo_walk_fini().
*
* If additional helper modules need to be loaded to complete the enumeration
* the module may do so by calling topo_mod_load(). Enumeration may then
* continue with the module handing off enumeration to its helper module
* by calling topo_mod_enumerate(). Similarly, a module may call
* topo_mod_enummap() to kick-off enumeration according to a given XML
* topology map file. A module *may* not cause re-entrance to itself
* via either of these interfaces. If re-entry is detected an error
* will be returned (ETOPO_ENUM_RECURS).
*
* If the module registers a release callback, it will be called on a node
* by node basis during topo_snap_rele(). Any private node data may be
* deallocated or methods unregistered at that time. Global module data
* should be cleaned up before or at the time that the module _topo_fini
* entry point is called.
*
* Module entry points and method invocations are guaranteed to be
* single-threaded for a given snapshot handle. Applications may have
* more than one topology snapshot open at a time. This means that the
* module operations and methods may be called for different module handles
* (topo_mod_t) asynchronously. The enumerator should not use static or
* global data structures that may become inconsistent in this situation.
* Method operations may be re-entrant if the module invokes one of its own
* methods directly or via dynamic property access. Caution should be
* exercised with method operations to insure that data remains consistent
* within the module and that deadlocks can not occur.
*/
#include <pthread.h>
#include <assert.h>
#include <errno.h>
#include <dirent.h>
#include <limits.h>
#include <alloca.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <topo_alloc.h>
#include <topo_error.h>
#include <topo_file.h>
#include <topo_fmri.h>
#include <topo_module.h>
#include <topo_method.h>
#include <topo_string.h>
#include <topo_subr.h>
#include <topo_tree.h>
{
char *path;
/*
* Already loaded, topo_mod_lookup will bump the ref count
*/
return (NULL);
}
return (mod);
}
return (NULL);
== NULL) { /* returned with mod held */
return (NULL);
}
return (mod);
}
void
{
}
static int
{
"module registration failed for %s: %s\n",
}
int
{
if (version != TOPO_VERSION)
== NULL)
sizeof (topo_modops_t))) == NULL)
return (0);
}
void
{
return;
return;
sizeof (topo_modops_t));
}
int
{
int err = 0;
if (err != 0) {
"%s: enumeration failed: module=%s, node=%s, instance=%d\n",
node->tn_instance);
return (-1);
}
return (0);
}
int
const char *scheme)
{
B_FALSE));
}
static nvlist_t *
{
return (NULL);
}
nvlist_t *
{
int err;
if (version != FM_HC_SCHEME_VERSION)
/*
* Do we have any args to pass?
*/
}
}
pfmri) != 0) {
}
}
/*
* Add optional payload
*/
lpart);
} else {
"");
}
}
lrev);
} else {
"");
}
}
lserial);
} else {
"");
}
}
if (hc_specific != NULL)
}
return (nfp);
}
nvlist_t *
const char *devid)
{
int err;
if (version != FM_DEV_SCHEME_VERSION)
}
}
return (nfp);
}
nvlist_t *
const char *serial)
{
int err;
if (version != FM_CPU_SCHEME_VERSION)
}
/*
* Add optional payload
*/
}
return (nfp);
}
nvlist_t *
{
int err;
if (version != FM_MOD_SCHEME_VERSION)
}
}
return (nfp);
}
nvlist_t *
{
int err;
if (version != FM_SW_SCHEME_VERSION)
err = 0;
if (obj_pkg)
if (site_line != -1)
if (ctxt_pid != -1)
if (ctxt_ctid != -1)
if (err) {
}
}
return (nfp);
}
int
{
int err;
}
return (0);
}
int
{
int err;
char *sp;
}
return (0);
}
void *
{
}
void
{
}
void
{
}
{
int err;
char *errmsg;
"ipmi_open() failed: %s (ipmi errno=%d)", errmsg,
err);
}
}
}
void
{
}
{
}
{
}
{
}
{
}
{
}
void
{
}
/*PRINTFLIKE2*/
void
{
return;
}
/*
* Get chassis manufacturer, name, part number, and serial number.
*/
static char *
{
return (NULL);
}
static char *
{
return (NULL);
}
static char *
{
return (NULL);
}
static char *
{
return (NULL);
}
static char *
{
return (NULL);
}
/*
* Generate client occupant path from the iport di_node, target port and
* lun properties.
*
* The caller is responsible for freeing the returned string.
*/
char *
int lun)
{
if (devtree == DI_NODE_NIL) {
goto out;
}
/* HBA iport node */
goto out;
}
if (iport == DI_NODE_NIL) {
goto out;
}
/* find matching client node */
/* do we have a client? */
if (client == DI_NODE_NIL) {
continue;
}
/* path addr */
"%s: no memory for path address\n", __func__);
goto out;
}
/* leading 'w' is not always consistent */
"w%s", path_addr);
}
target_port, lun);
} else {
/* pa_got_w && !tgt_got_w */
target_port, lun);
}
/* check for a match */
/* found our node */
if (client_devfs_path != NULL) {
/* oc_path is the client devfs path */
break;
}
}
}
if (client_devfs_path != NULL)
out:
if (new_path_addr != NULL)
return (NULL);
}
/*
* Look for CRO alias.
*
* Caller is responsible for freeing string.
*/
static void
{
di_cro_rec_t r;
static const char *query_fmt =
return;
/* init cro handle */
/* construct /devices path */
if (devices_path == NULL) {
goto out;
}
/* find the di_cro record associated with this path */
"%s: No memory for query. devices_path: %s\n", __func__,
goto out;
}
"%s: ra NULL\n", __func__);
goto out;
}
if (r == NULL) {
"%s: r NULL\n", __func__);
goto out;
}
/* return the alias-id */
out:
/* cleanup */
if (devices_path != NULL)
}
int
{
int err;
/* get chassis alias */
if (chassis_alias == NULL) {
"%s: no chassis alias\n", __func__);
return (-1);
}
/* add chassis alias to node and parent (chassis) */
/* some bay nodes hide under an hba node */
/* find it's "chassis" parent */
do {
}
goto skip;
}
/* already set? */
goto skip;
/* add chassis-alias to authority pgroup */
(const char *)chassis_alias, &err) != 0)
"%s: failed to add %s to %s : %s\n",
else
"%s: added %s to %s\n",
skip:
}
return (0);
}
void
{
}
void
{
}
/*
* This routine is always called from hc scheme enumerators so only the
* chassis authority is returned.
*/
nvlist_t *
{
return (NULL);
}
/* chassis */
"%s: chassis manufacturer(%s) name(%s) part(%s) "
"serial(%s) alias(%s) \n", __func__,
mfg);
}
name);
}
part);
}
serial);
}
alias);
}
if (serr != 0) {
return (NULL);
}
return (auth);
}
{
return (NULL);
return (wp);
}