2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A/* Portions Copyright 2005 Cyril Plisko */ 2N/A/* Limit size of sysinfo return */ 2N/A * Attachment point specifier types. 2N/A * Incomplete definition 2N/A * Structure that contains plugin library information. 2N/A * Library locator data struct - used to pass down through the device 2N/A * tree walking code. 2N/A * linked list of cfga_stat_data structs - used for 2N/A * linked list of arrays. Each array represents a bunch 2N/A * of list_data_t structures returned by a single call 2N/A * to a plugin's cfga_list_ext() routine. 2N/A * encapsulate config_list args to get them through the tree 2N/A const char *
opts;
/* Hardware specific options */ 2N/A int *
countp;
/* Total number of list and stat structures */ 2N/A * Internal operations for libcfgadm which are version dependant 2N/A * Lock to protect list of libraries 2N/A * Forward declarations 2N/A * Plugin library search path helpers 2N/A "Device library initialize failed",
2N/A "Memory allocation failed",
2N/A "Invalid argument(s)" 2N/A * Table of version dependant routines 2N/A * Public interfaces for libcfgadm, as documented in config_admin.3x 2N/A * config_change_state 2N/A * call cfga_state_change_func 2N/A * call it's cfga_stat 2N/A * call cfga_state_change_func 2N/A * operate on each ap_id 2N/A * Need to check condition before proceeding in 2N/A * the "configure direction" 2N/A * config_private_func 2N/A * operate on each ap_id 2N/A * operate on each ap_id 2N/A * V1 entry points don't support dynamic attachment points 2N/A * This is a V1 interface which can use only V1 plugins 2N/A * This is a V1 interface which can use only V1 plugins 2N/A * V1 interfaces don't support prefiltering, no class 2N/A * We support both V1 and V2 plugins through this entry 2N/A * discover and stat all attachment points 2N/A * Stat specified attachment points. With dynamic expansion 2N/A * more data may be returned than was specified by user. 2N/A * For the list command notify user if no attachment 2N/A * point is found in the system. 2N/A * If attachment points are being prefiltered, absence of data 2N/A * does not imply that config. admin. is not 2N/A * supported by the system. 2N/A * Prefiltering: requested class is absent 2N/A * No attachment points in system 2N/A * config_unload_libs 2N/A * Attempts to remove all libs on the plugin list. 2N/A /* destroy cache entries to remove refcnt agains plugins */ 2N/A * Extract static ap_ids 2N/A * Use the default comparator for static ap_ids 2N/A * static components match. They belong to 2N/A * the same static ap_id. Check if both are dynamic 2N/A * If not, static < dynamic. 2N/A * If both are static, then ap1 = ap2 2N/A * Both are dynamic and belong to same static ap_id. 2N/A * Use the plugin comparator 2N/A * operate on each ap_id 2N/A * Private support routines for the public interfaces 2N/A ep =
"Configuration operation succeeded";
2N/A ep =
"Configuration operation cancelled";
2N/A ep =
"Configuration operation invalid";
2N/A ep =
"Configuration administration not supported";
2N/A ep =
"Configuration operation not supported";
2N/A ep =
"Insufficient privileges";
2N/A ep =
"Component system is busy, try again";
2N/A ep =
"System is busy, try again";
2N/A ep =
"Insufficient condition";
2N/A ep =
"Hardware specific failure";
2N/A ep =
"Attachment point not found";
2N/A ep =
"No attachment point with specified attributes found";
2N/A * listopts is a string in the getsubopt(3C) style: 2N/A * name1=value1,name2=value2, 2N/A * NULL is a legal value for listopts 2N/A * Obtain the devlink from a /devices path 2N/A /* open devlink database */ 2N/A * mklog_common - make a logical name from the driver and instance 2N/A * mklog_common - make a logical name from the driver and instance 2N/A * resolve_lib_ref - relocate to use plugin lib 2N/A * Version symbol not defined, must be the first version 2N/A * Check if plugin version matches request. 2N/A * Record the plugin version and setup version dependant routines 2N/A /* resolve symbols common to all versions */ 2N/A /* Resolve version specific symbols */ 2N/A int *,
const char *,
char **))
sym;
2N/A * config_calloc_check - perform allocation, check result and 2N/A * config_get_lib - given an ap_id find the library name 2N/A * If successful, the plugin library is held. 2N/A * Separate into base and dynamic components 2N/A * No upper limit on version 2N/A * We need atleast version 2 of the plug-in library 2N/A * interface since the ap_id has a dynamic component. 2N/A * If the ap_id is a devlink in CFGA_DEV_DIR, follow link 2N/A * to get the physical ap_id. 2N/A * find and load the library 2N/A * The base component of the ap_id is used to locate the plug-in 2N/A * dev links created for now. 2N/A * physical ap_id: Use ap_base as root for tree walk 2N/A * A link based apid (logical) will resolve to a physical 2N/A * logical ap_id or ap_type: Use "/" as root for tree walk 2N/A * Note: an aptype cannot have a dynamic component 2N/A * variables used by assert() only which is disabled 2N/A * by defining NDEBUG (see top of this file) 2N/A * If a dynamic component was present, v1 plug-ins are not 2N/A * ap_physical is passed to plugins as their ap_id argument. 2N/A * Append dynamic component if any. 2N/A/* load_lib - load library for non-SHP attachment point node */ 2N/A/* load_lib_hp - load library for SHP attachment point node */ 2N/A * load_lib_impl - Given a library pathname, create a entry for it 2N/A * in the library list, * if one does not already exist, and read 2N/A * lock it to keep it there. 2N/A * lock the library list 2N/A * see if lib exist in list, if not, allocate a new one 2N/A /* fill in logical and physical name in libloc_p */ 2N/A /* allocate a new plugin_lib_t structure */ 2N/A * ensure that the lib is open and linked in 2N/A * link in new entry to the end of list 2N/A /* Initialize refcnt to 1 */ 2N/A * record libp and physical node name in the libloc struct 2N/A * find_lib - find library for non-SHP attachment point node 2N/A /* Make sure pathname and class is null if we fail */ 2N/A * Initialize possible library tags. 2N/A * Cycle through the array of names to find the library. 2N/A /* Attachment points may not have a class (i.e. are generic) */ 2N/A /* Record class name (if any) */ 2N/A * find_lib_hp - find library for SHP attachment point 2N/A /* Make sure pathname and class is null if we fail */ 2N/A * Initialize possible library tags. 2N/A * Only support PCI class for now, this will need to be 2N/A * changed as other plugins are migrated to SHP plugin. 2N/A * No type check for now as PCI is the only class SHP plugin 2N/A * supports. In the future we'll need to enable the type check 2N/A * and set class accordingly, when non PCI plugins are migrated 2N/A * to SHP. In that case we'll probably need to add an additional 2N/A * interface between libcfgadm and the plugins, and SHP plugin will 2N/A * implement this interface which will translate the bus specific 2N/A * strings to standard classes that libcfgadm can recognize, for 2N/A * all the buses it supports, e.g. for pci/pcie it will translate 2N/A * PCIE_NATIVE_HP_TYPE to string "pci". We'll also need to bump up 2N/A * SHP plugin version to 3 to use the new interface. 2N/A /* Record class name (if any) */ 2N/A * find_lib_impl - Given an attachment point node find it's library 2N/A * Initialize machine name and arch name 2N/A * Try path based upon platform name 2N/A /* file exists, is it a lib */ 2N/A * Try path based upon machine name 2N/A /* file exists, is it a lib */ 2N/A * Try path based upon arch name 2N/A /* file exists, is it a lib */ 2N/A * Try generic location 2N/A /* file exists, is it a lib */ 2N/A * find_ap_common - locate a particular attachment point 2N/A /* Remove devices prefix (if any) */ 2N/A /* Remove dynamic component if any */ 2N/A /* Remove minor name (if any) */ 2N/A * begin walk of device tree 2N/A * Since we create minor nodes & dev links for both all PCI/PCIE 2N/A * of the new framework, we should first match with hp nodes. If 2N/A * di_lookup_node() may fail, either because the 2N/A * ap_id does not exist, or because the ap_id refers 2N/A * to a legacy PCI slot, thus we'll not able to 2N/A * find node using DINFOHP, try to see if we can 2N/A * find one using DINFOCACHE. 2N/A * Failed to find a matching hp node, try minor node. 2N/A * di_lookup_node() may fail, because the 2N/A * ap_id does not exist. 2N/A * check_ap - called for each non-SHP attachment point found 2N/A * check_ap_hp - called for each SHP attachment point found 2N/A * check_ap_impl - called for each attachment point found 2N/A * This is used in cases where a particular attachment point 2N/A * or type of attachment point is specified via a logical name or ap_type. 2N/A * Not used for physical names or in the list case with no 2N/A * This routime handles only aptypes and driver based logical apids. 2N/A * If the base matches driver and instance try and find a lib for it, 2N/A * then load it. On any failure we continue the walk. 2N/A * driver based logical ap_ids are derived from driver name + instance. 2N/A * Ap_types are just partial driver names. 2N/A * save the correct type of error so user does not get confused 2N/A * check_ap_phys - called for each non-SHP attachment point found 2N/A * check_ap_phys_hp - called for each SHP attachment point found 2N/A * check_ap_phys_impl - called for each attachment point found 2N/A * This is used in cases where a particular attachment point 2N/A * is specified via a physical name. If the name matches then 2N/A * we try and find and load the library for it. 2N/A * See if library, as specified by the full pathname and controller 2N/A * instance number is already represented in the plugin library list. 2N/A * If the instance number is -1 it is ignored. 2N/A * Coalesce stat and list data into single array 2N/A * allocate the array 2N/A * copy all the stat elements (if any) into the array 2N/A * copy all the list elements (if any) into the array 2N/A * The caller of this routine may supply a buffer through 2N/A * ap_id_list for returning data. Otherwise, this routine allocates the 2N/A * allocate the array if caller does not supply one. 2N/A * copy the stat elements into the array 2N/A * Free buffer only if we allocated it. 2N/A * list_common - walk the device tree and stat all attachment points. 2N/A * May walk a subset of all attachment points in the device tree if 2N/A * a class is specified 2N/A /* No need to filter on class for now */ 2N/A * Walk all minor nodes 2N/A * If errstring is null it means user in not interested in getting 2N/A * error status. So we don't do all the work 2N/A * do_list_common - list non-SHP attachment point 2N/A * created for now, we need to specifically exclude these connectors 2N/A * during walking minor nodes. 2N/A * do_list_common_hp - list SHP attachment point 2N/A * do_list_common_impl - Routine to list attachment point as part of 2N/A * a config_list opertion. Used by both v1 and v2 interfaces. 2N/A * This is somewhat similar to config_get_lib() and its helper routines 2N/A * except that the ap_ids are always physical and don't have dynamic 2N/A * try and find a lib for this node 2N/A * Load all plugins. We will check compatibility later in this 2N/A * Note: For list type routines (list all attachment points in 2N/A * device tree) we don't pass errstring to the plugin, nor do we 2N/A * stop the walk if an error occurs in the plugin. 2N/A * If the underlying hotplug daemon is not enabled, 2N/A * the SHP attach points will not be shown, this 2N/A * could confuse the uesrs. We specifically pass the 2N/A * errstring to SHP plugin so that it can set the 2N/A * errstring accordingly in this case, giving users 2N/A * stat_common - stat a user specified set of attachment points. 2N/A * operate on each ap_id 2N/A * do pre-filtering if requested 2N/A * Unlike list type routines, while stat'ing specific 2N/A * attachment points we pass errstring to the plugins 2N/A * and halt if an error occurs in the plugin. 2N/A * Pass errstring as a separate argument. Some higher level routines need 2N/A * allocate stat data buffer and list element 2N/A * Set up the logical and physical id's. 2N/A * For v1 interfaces, the generic library (libcfgadm) creates the 2N/A * ap_ids. mklog() is assumed to have been called in 2N/A * the caller of this routine. 2N/A * allocate array list 2N/A * The listopts argument is currently unused. Use NULL 2N/A * Set up the logical and physical id's if necessary. 2N/A * For v2 interfaces, the generic library (libcfgadm) creates the 2N/A * ap_ids only if there are no dynamic attachment points and the 2N/A * plug-in does not create the name itself. mklog() is 2N/A * assumed to have been called in the caller of this routine. 2N/A /* Fill in the class information for all list elements */ 2N/A * Check if a plugin version is within requested limits. 2N/A * find_arg_type - determine if an argument is an ap_id or an ap_type. 2N/A * Extract the base component 2N/A /* Copy only the first "len" chars */ 2N/A * If it starts with a slash and is stat-able its a physical. 2N/A * Is this a symlink in CFGA_DEV_DIR ? 2N/A * Check for ":" which is always present in an ap_id 2N/A * but not in an ap_type. 2N/A * we need to check that the characters right before the : are digits 2N/A * since an ap_id is of the form <name><instance>:<specific ap name> 2N/A/* mask represents the flags accepted */ 2N/A * Returns the class or the empty string if attacment point has 2N/A if (c !=
'\0' && c !=
':') {
2N/A * Transform stat data to list data 2N/A * Default implementation of cfga_ap_id_cmp. Works for most cases 2N/A * except for long hex number sequences like world-wide-name. 2N/A * This function compares the ap's in a generic way. It does so by 2N/A * determining the place of difference between the 2 aps. If the first 2N/A * difference is a digit, it attempts to obtain the numbers and compare them 2N/A * Otherwise it just compares the aps as strings 2N/A * Search for first different char 2N/A * If one of the char is a digit, back up to where the 2N/A * number started, compare the number. 2N/A /* One of them isn't a number, compare the char */