2N/A/*
2N/A * CDDL HEADER START
2N/A *
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 *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
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 *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A/*
2N/A * Telco-alarm library, which communicates through libpcp to set/get
2N/A * alarms.
2N/A */
2N/A
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <sys/types.h>
2N/A#include <unistd.h>
2N/A#include <libpcp.h>
2N/A
2N/A#include "tsalarm.h"
2N/A
2N/A/* Message Types */
2N/A#define TSALARM_CONTROL 15
2N/A#define TSALARM_CONTROL_R 16
2N/A
2N/A#define TSALARM_CHANNEL_TIMEOUT 20
2N/A#define TSALARM_MAX_RETRIES 3
2N/A#define TSALARM_SERVICE_NAME "SUNW,sun4v-telco-alarm"
2N/A
2N/Aint
2N/Atsalarm_get(uint32_t alarm_type, uint32_t *alarm_state)
2N/A{
2N/A int chnl_fd;
2N/A tsalarm_req_t *req_ptr = NULL;
2N/A tsalarm_resp_t *resp_ptr = NULL;
2N/A pcp_msg_t send_msg;
2N/A pcp_msg_t recv_msg;
2N/A int rc = TSALARM_SUCCESS;
2N/A int retries;
2N/A
2N/A /* initialize virtual channel */
2N/A for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) {
2N/A if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) {
2N/A if (retries == TSALARM_MAX_RETRIES) {
2N/A rc = TSALARM_CHANNEL_INIT_FAILURE;
2N/A goto cleanup;
2N/A }
2N/A (void) sleep(TSALARM_CHANNEL_TIMEOUT);
2N/A } else
2N/A break;
2N/A }
2N/A
2N/A /* create request message data */
2N/A req_ptr = malloc(sizeof (tsalarm_req_t));
2N/A if (req_ptr == NULL) {
2N/A rc = TSALARM_NULL_REQ_DATA;
2N/A goto cleanup;
2N/A }
2N/A req_ptr->alarm_action = TSALARM_STATUS;
2N/A req_ptr->alarm_id = alarm_type;
2N/A
2N/A send_msg.msg_type = TSALARM_CONTROL;
2N/A send_msg.sub_type = NULL;
2N/A send_msg.msg_len = sizeof (tsalarm_req_t);
2N/A send_msg.msg_data = (uint8_t *)req_ptr;
2N/A
2N/A /*
2N/A * Send the request and receive the response.
2N/A */
2N/A if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
2N/A TSALARM_CHANNEL_TIMEOUT) < 0) {
2N/A /* we either timed out or erred; either way try again */
2N/A (void) sleep(TSALARM_CHANNEL_TIMEOUT);
2N/A
2N/A if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
2N/A TSALARM_CHANNEL_TIMEOUT) < 0) {
2N/A rc = TSALARM_COMM_FAILURE;
2N/A goto cleanup;
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * verify that the Alarm action has taken place
2N/A */
2N/A if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL)
2N/A goto cleanup;
2N/A
2N/A /*
2N/A * validate that this data was meant for us
2N/A */
2N/A if (recv_msg.msg_type != TSALARM_CONTROL_R) {
2N/A rc = TSALARM_UNBOUND_PACKET_RECVD;
2N/A goto cleanup;
2N/A }
2N/A
2N/A if (resp_ptr->status == TSALARM_ERROR) {
2N/A rc = TSALARM_GET_ERROR;
2N/A goto cleanup;
2N/A }
2N/A
2N/A if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) {
2N/A rc = TSALARM_GET_ERROR;
2N/A goto cleanup;
2N/A }
2N/A
2N/A *alarm_state = resp_ptr->alarm_state;
2N/A
2N/Acleanup:
2N/A if (req_ptr != NULL)
2N/A free(req_ptr);
2N/A
2N/A /* free recv_msg.msg_data through pointer to make sure it is valid */
2N/A if (resp_ptr != NULL)
2N/A free(resp_ptr);
2N/A
2N/A /* close virtual channel fd */
2N/A (void) pcp_close(chnl_fd);
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/Aint
2N/Atsalarm_set(uint32_t alarm_type, uint32_t alarm_state)
2N/A{
2N/A int chnl_fd;
2N/A tsalarm_req_t *req_ptr = NULL;
2N/A tsalarm_resp_t *resp_ptr = NULL;
2N/A pcp_msg_t send_msg;
2N/A pcp_msg_t recv_msg;
2N/A int rc = TSALARM_SUCCESS;
2N/A int retries;
2N/A
2N/A /* initialize virtual channel */
2N/A for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) {
2N/A if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) {
2N/A if (retries == TSALARM_MAX_RETRIES) {
2N/A rc = TSALARM_CHANNEL_INIT_FAILURE;
2N/A goto cleanup;
2N/A }
2N/A (void) sleep(TSALARM_CHANNEL_TIMEOUT);
2N/A } else
2N/A break;
2N/A }
2N/A
2N/A /* create request message data */
2N/A req_ptr = malloc(sizeof (tsalarm_req_t));
2N/A if (req_ptr == NULL) {
2N/A rc = TSALARM_NULL_REQ_DATA;
2N/A goto cleanup;
2N/A }
2N/A req_ptr->alarm_id = alarm_type;
2N/A if (alarm_state == TSALARM_STATE_ON)
2N/A req_ptr->alarm_action = TSALARM_ENABLE;
2N/A else if (alarm_state == TSALARM_STATE_OFF)
2N/A req_ptr->alarm_action = TSALARM_DISABLE;
2N/A
2N/A send_msg.msg_type = TSALARM_CONTROL;
2N/A send_msg.sub_type = NULL;
2N/A send_msg.msg_len = sizeof (tsalarm_req_t);
2N/A send_msg.msg_data = (uint8_t *)req_ptr;
2N/A
2N/A /*
2N/A * Send the request and receive the response.
2N/A */
2N/A if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
2N/A TSALARM_CHANNEL_TIMEOUT) < 0) {
2N/A /* we either timed out or erred; either way try again */
2N/A (void) sleep(TSALARM_CHANNEL_TIMEOUT);
2N/A
2N/A if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
2N/A TSALARM_CHANNEL_TIMEOUT) < 0) {
2N/A rc = TSALARM_COMM_FAILURE;
2N/A goto cleanup;
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * verify that the Alarm action has taken place
2N/A */
2N/A if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL)
2N/A goto cleanup;
2N/A
2N/A /*
2N/A * validate that this data was meant for us
2N/A */
2N/A if (recv_msg.msg_type != TSALARM_CONTROL_R) {
2N/A rc = TSALARM_UNBOUND_PACKET_RECVD;
2N/A goto cleanup;
2N/A }
2N/A
2N/A if (resp_ptr->status == TSALARM_ERROR) {
2N/A rc = TSALARM_SET_ERROR;
2N/A goto cleanup;
2N/A }
2N/A
2N/A /*
2N/A * ensure the Alarm action taken is the one requested
2N/A */
2N/A if ((req_ptr->alarm_action == TSALARM_DISABLE) &&
2N/A (resp_ptr->alarm_state != TSALARM_STATE_OFF)) {
2N/A rc = TSALARM_SET_ERROR;
2N/A goto cleanup;
2N/A } else if ((req_ptr->alarm_action == TSALARM_ENABLE) &&
2N/A (resp_ptr->alarm_state != TSALARM_STATE_ON)) {
2N/A rc = TSALARM_SET_ERROR;
2N/A goto cleanup;
2N/A } else if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) {
2N/A rc = TSALARM_SET_ERROR;
2N/A goto cleanup;
2N/A }
2N/A
2N/Acleanup:
2N/A if (req_ptr != NULL)
2N/A free(req_ptr);
2N/A
2N/A /* free recv_msg.msg_data through pointer to make sure it is valid */
2N/A if (resp_ptr != NULL)
2N/A free(resp_ptr);
2N/A
2N/A /* close virtual channel fd */
2N/A (void) pcp_close(chnl_fd);
2N/A
2N/A return (rc);
2N/A}