picldr.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* 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
* 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
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/systeminfo.h>
#include <pthread.h>
#include <syslog.h>
#include <picl.h>
#include <picltree.h>
#include <picldefs.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <unistd.h>
#include <stropts.h>
#include <assert.h>
#include <libnvpair.h>
#include <libintl.h>
#include <poll.h>
#include <smclib.h>
#include "piclenvmond.h"
#include "picldr.h"
/* external functions */
extern picl_errno_t env_platmod_init();
extern void env_platmod_handle_event(const char *, const void *, size_t);
extern picl_errno_t env_platmod_create_sensors();
extern picl_errno_t env_platmod_setup_hotswap();
extern picl_errno_t env_platmod_sp_monitor();
extern picl_errno_t env_platmod_handle_latch_open();
extern void env_platmod_handle_sensor_event(void *);
extern int process_platmod_sp_state_change_notif(void *);
extern int process_platmod_change_cpu_node_state(void *);
extern int process_platmod_change_cpci_state(void *);
extern int process_platmod_async_msg_notif(void *);
extern void process_platmod_sp_heartbeat(uint8_t);
extern picl_errno_t env_platmod_create_hotswap_prop();
int (*writefn)(ptree_warg_t *, const void *),
/* external variables */
extern int env_debug;
static char chassisconf_name[SYS_NMLN];
static picl_nodehdl_t frutreeh = 0;
static pthread_t polling_threadID;
/* globals */
uint8_t cpu_geo_addr = 0;
/*
* envmond policy structure
*/
typedef struct _policy {
char *pname;
char *argp;
} env_policy_t;
/*
* read_policy_configuration - extract info. from the envmond.conf
*/
static int
{
char buf[RECORD_MAXSIZE];
return (-1);
}
continue;
}
continue;
}
goto errors;
}
} else {
goto errors;
}
}
if (lasts) {
goto errors;
}
} else {
}
}
return (0);
while (*policypp) {
}
return (-1);
}
/*
* supports environmental policies
*/
static void
{
char conffile[MAXPATHLEN];
if (parse_config_file == B_FALSE) {
return;
}
sys_name);
return;
}
return;
}
while (policyp) {
"%d seconds", alarm_check_interval);
}
}
}
/*
* detects the presence of RTM for CPU board
*/
static boolean_t
{
/* initialize the request packet */
DEFAULT_SEQN, size);
/* make a call to smc library to send cmd */
POLL_TIMEOUT) != SMC_SUCCESS) {
return (B_FALSE);
}
return (B_TRUE);
}
/*
* this routine does the following:
* 1. initializes the CPU geo-addr
* 2. gets the system name
* 3. create the chassis type property
* 4. creates the conf_file property
*/
static picl_errno_t
{
int rc = 0;
char conf_name[PICL_PROPNAMELEN_MAX];
/* get the geo_addr */
/* initialize the request packet */
DEFAULT_SEQN, size);
/* make a call to smc library to send cmd */
POLL_TIMEOUT) != SMC_SUCCESS) {
return (PICL_FAILURE);
}
/* get the system name */
return (PICL_FAILURE);
}
sizeof (chassisconf_name));
/* initialize the node handles */
return (rc);
}
PICL_SUCCESS) {
return (rc);
}
&chassis_nodehdl)) != PICL_SUCCESS) {
return (rc);
}
/* create the chassis type property */
chassisconf_name)) != PICL_SUCCESS) {
return (rc);
}
/*
* create dummy prop to inform frutree plugin abt conf file
* (rtm based or w/o rtm)
* frutree plugin removes this prop after reading the value
*/
if (is_rtm_present() == B_TRUE) {
"%s.RTM.conf", chassisconf_name);
} else {
"%s.conf", chassisconf_name);
}
conf_name)) != PICL_SUCCESS) {
return (rc);
}
return (PICL_SUCCESS);
}
/*
* initialization
*/
env_init()
{
return (rc);
}
/* parse the configuration file */
/*
* do any platform specific intialization if required
* IMPORTANT: must post dr_incoming resource event on
* chassis after doing all the reqd checks
*/
rc = env_platmod_init();
return (rc);
}
/*
* sets smc global enables
*/
static int
{
/* initialize the request packet */
DEFAULT_SEQN, size);
/* make a call to smc library to send cmd */
POLL_TIMEOUT) != SMC_SUCCESS) {
return (-1);
}
if (ipmi_enable) {
} else {
}
DEFAULT_SEQN, size);
/* make a call to smc library to send cmd */
POLL_TIMEOUT) != SMC_SUCCESS) {
return (-1);
}
return (0);
}
/*
* wrapper smc drv open
*/
int
env_open_smc(void)
{
int fd;
return (-1);
}
return (fd);
}
static picl_smc_event_t
{
switch (event_data) {
case SMC_LOCAL_EVENT_BRIDGE_IN_RESET : /*FALLTHRU*/
if ((rc = env_platmod_handle_bus_if_change(
event_data)) != PICL_SUCCESS) {
" in handling bus interface change "
"event, error = %d"), rc);
}
break;
if ((rc = env_platmod_handle_latch_open()) !=
PICL_SUCCESS) {
" in handling latch open event, "
"error = %d"), rc);
}
break;
default:
break;
}
return (event);
}
static void
{
int rc = SMC_SUCCESS;
switch (event) {
/*
* This message comes to CPU when the service processor is going offline
* or online.
*/
SMC_SUCCESS) {
"service processor change of state event, "
"error = %d"), rc);
}
break;
/*
* This message comes to CPU when service processor
* requests the CPU to go online or offline (shutdown).
*/
SMC_SUCCESS) {
"cpu change of state event, error = %d"), rc);
}
break;
/*
* This message comes to CPU(Satellite) when the
* other node (Host) is going online or offline.
*/
SMC_SUCCESS) {
"cpci change state event, error = %d"), rc);
}
break;
/*
* This message comes from service processor to inform
* change in states for other nodes
*/
SMC_SUCCESS) {
"async event notification, error = %d"), rc);
}
break;
case MSG_GET_CPU_NODE_STATE:
/* respond to the service processor heartbeat */
break;
default:
break;
}
}
/*ARGSUSED*/
static picl_smc_event_t
{
return (NO_EVENT);
}
return (NO_EVENT);
}
} else { /* it must be an IPMI event */
case 0x3:
case 0x4:
" Sensor Event Received\n"));
/* sensor event */
case TEMPERATURE_SENSOR_TYPE:
break;
default:
break;
}
default:
break;
}
}
return (event);
}
/*
* polls SMC driver for SMC events
*/
/*ARGSUSED*/
static void *
env_polling_thread(void *args)
{
int poll_rc;
void *datap;
int smcfd;
smcfd = env_open_smc();
if (smcfd == -1) {
"Open of SMC drv failed"));
return (NULL);
}
"Sensor events failed"));
return (NULL);
}
/* request for async messages */
"Async messages failed"));
return (NULL);
}
/* Now wait for SMC events to come */
for (;;) {
if (poll_rc < 0) {
"processing halted"));
break;
}
"wrong event data posted from SMC"));
}
}
return (NULL);
}
/*
* (to be)Called during chassis configuration. It does the following tasks.
* Set global enables on SMC
* Register for local(SMC) events and remote(IPMI) messages (State Change msgs)
* creates sensor nodes
* Initialize hotswap
* Initiallize the interaction with service processor
*/
static picl_errno_t
env_start_services(void)
{
int rc;
}
/* set the SMC global enables */
"Globals failed"));
return (PICL_FAILURE);
}
/* start a worker thread to poll for SMC events */
if (create_polling_thr) {
if (rc != 0) {
"creating polling thread"));
return (PICL_FAILURE);
}
}
/* create the sensor nodes */
" nodes, error = %d"), rc);
}
/* intialize the hotswap framework */
"initialization, error = %d"), rc);
}
"hotswap prop, error = %d"), rc);
}
/* intialize interaction with service processor */
" service processor, error = %d"), rc);
}
return (PICL_SUCCESS);
}
static picl_errno_t
{
char *cpu_name = PICL_NODE_CPU;
char *rtm_name = PICL_NODE_RTM;
return (PICL_SUCCESS);
}
/* initialize cpu loc node handle */
if (cpu_lnodehdl == 0) {
&cpu_lnodehdl)) != PICL_SUCCESS) {
" to get CPU nodehdl, error = %d"), rc);
return (rc);
}
}
/* create geo-addr prop under CPU location */
&proph) == PICL_PROPNOTFOUND) {
PICL_READ, sizeof (cpu_geo_addr),
(void *)&cpu_geo_addr)) != PICL_SUCCESS) {
return (rc);
}
}
PICL_READ, sizeof (status_time),
}
/* create geo address property for RTM node (if present) */
(void) ptree_find_node(chassis_nodehdl,
if (rtm_lnodehdl == 0) { /* RTM not present */
return (PICL_SUCCESS);
}
&proph) == PICL_PROPNOTFOUND) {
&cpu_geo_addr)) != PICL_SUCCESS) {
"to create CPU geo-addr, error = %d"), rc);
return (rc);
}
}
&status_time);
}
/* start all the environment monitoring services */
return (rc);
}
return (PICL_SUCCESS);
}
/*
* routine to handle all the picl state and condition change events
*/
void
{
picl_nodehdl_t nodeh = 0;
char *value;
char result[PICL_PROPNAMELEN_MAX];
if (!ename) {
return;
}
} else {
return;
}
/* unpack the nvlist and get the information */
return;
}
return;
}
PICLEVENTARG_CONDITION, &value) != 0) {
return;
}
if (env_debug & PICLEVENTS) {
" %s", PICL_PROP_NAME);
return;
}
}
if (chassis_nodehdl == 0 && state_event) {
return;
}
}
}
}
/* do any platform specific handling that is reqd */
}