scf_notify.c revision c9181931796b5d4505a5230d4a399b406b0aabc4
/*
* 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
*/
/*
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <config_admin.h>
#include <strings.h>
#include <syslog.h>
#include <libsysevent.h>
#include <libdevinfo.h>
#include <libnvpair.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <stropts.h>
/* Macros */
/*
* Connection for SCF driver
*/
/* Check the availability of SCF driver */
static int scfdrv_enable = 0;
/* Device for SCF Driver */
#define SCFRETRY 10
#define SCFIOCWAIT 3
#define SCFDATA_DEV_INFO 32
#define SCFDATA_APID 1054
/*
* Data for XSCF
* Note the size of the ap_id must be SCFDATA_APID for proper data alignment
* for the ioctl. The SCF has a corresponding data structure which is matched
* here.
*/
typedef struct {
char ap_id[SCFDATA_APID];
char dev_name[SCFDATA_DEV_INFO];
char dev_model[SCFDATA_DEV_INFO];
/*
* Data for scf notification of state changes.
* pci_name is an ap_id phys path for the hot pluggable pci device.
* r_state is the recepticle state.
* o_state is the occupant state.
* cache_fmri_str is a string representation of an fmri in the rsrc cache.
* fmri_asru_str is the asru for an fmri which is found in the topology.
* found is a boolean indicating whether the device was found in the topology.
*/
typedef struct {
char pci_name[MAXPATHLEN];
} pci_notify_t;
/*
* Function Prototypes
*/
const char *pci_name);
/*
* Error report utility for libcfgadm functions
*/
void
const char *ap_id)
{
const char *ep;
ep = "configuration administration unknown error";
}
} else {
}
}
/*
* Get the slot status.
*/
void
{
int nlist; /* number of slot */
/*
* Get the attachment point information.
*/
goto out;
}
"ap_log_id = %.*s\n"
"ap_phys_id = %.*s\n"
"ap_r_state = %d\n"
"ap_o_state = %d\n"
"ap_cond = %d\n"
"ap_busy = %6d\n"
"ap_status_time = %s"
"ap_info = %.*s\n"
"ap_type = %.*s\n",
/* Copy the slot status. */
out:
if (stat) {
}
if (errstr) {
}
}
/*
* Get the pci_name
*/
static int
{
char *pci_name_ptr; /* pci node name pointer */
char *ap_lid_ptr; /* logical ap_id pointer */
int devices_len; /* "/device" length */
int pci_name_len; /* pci node name length */
int ap_lid_len; /* logical ap_id pointer */
/*
* Pick pci node name up from physical ap_id string.
*/
/* Check the length of physical ap_id string */
return (-1); /* changed */
}
/* Check the pci node name start, which is after "/devices". */
} else {
devices_len = 0;
}
/* Check the pci node name end, which is before ":". */
ap_lid_len = 0;
} else {
}
/*
* Get the head of pci node name string.
* Get the length of pci node name string.
*/
/* Copy the pci node name. */
return (0);
}
/*
* Get the property of name and model.
*/
static int
{
char *tmp; /* tmp */
/*
* Take the snap shot of device node configuration,
* to get the names of node and model.
*/
"Could not get dev info snapshot. errno=%d\n",
errno);
return (-1); /* changed */
}
/*
* The new child under pci node should be added. Then the
* device and model names should be passed, which is in the
* node with the minimum bus address.
*
* - Move to the child node level.
* - Search the node with the minimum bus addrress in the
* sibling list.
*/
goto out;
}
funcid = 0;
devid = 0;
"no bus addrress on device\n");
goto one_child;
}
}
}
break;
}
/*
* We do need to update the child node
* Case 1. devid > sdevid
* Case 2. devid == sdevid && funcid > sfuncid
*/
}
/*
* We do need to update the child node
* Case 1. devid >= sdevid
*/
funcid = 0;
}
} else {
break;
}
}
/*
* Get the name and model properties.
*/
}
}
}
out:
return (0); /* added */
}
void
{
int rc; /* return code */
/* For libsysevent */
/* For libcfgadm */
/* For libdevinfo */
/* Data for SCF */
/*
* Initialization
*/
/* Get the current time when event picked up. */
/*
* Check the vendor and publisher name of event.
*/
/* Check the vendor is "SUNW" */
/* Just return when not from SUNW */
goto out;
}
/* Enough to check "px" and "pcieb" at the beginning of string */
/* Just return when not px event */
goto out;
}
/*
* Get attribute values of attachment point.
*/
/* could not get attribute list */
goto out;
}
/* could not find the attribute from the list */
goto out;
}
goto out;
} else {
/*
* Get the slot status.
*/
}
/*
* Get the pci name which is needed for both the configure and
* unconfigure.
*/
if (rc != 0) {
goto out;
}
/*
* Event for configure case only,
* Get the name and model property
*/
if (o_state == CFGA_STAT_CONFIGURED) {
(char *)pci_notify_dev_info.pci_name);
if (rc != 0) {
goto out;
}
}
/*
* Copy the data for SCF.
* Initialize Data passed to SCF Driver.
*/
/*
* Set Data passed to SCF Driver.
*/
sizeof (scf_slotinfo_t));
if (!scfdrv_enable) {
scfdrv_enable = 1;
/*
* Pass data to SCF driver by ioctl.
*/
scfdrv_enable = 0;
goto out;
}
/* retry a few times for EBUSY and EIO */
(void) sleep(SCFIOCWAIT);
continue;
}
break;
}
scfdrv_enable = 0;
}
out:
}
}
if (ev_attr_list != NULL) {
}
}