xref: /titanic_50/usr/src/lib/libtsalarm/common/tsalarm.c (revision dc5982c9e1ebe3315aac975f1c4f1ad46c83c2d2)
14a6822d0Swillard /*
24a6822d0Swillard  * CDDL HEADER START
34a6822d0Swillard  *
44a6822d0Swillard  * The contents of this file are subject to the terms of the
54a6822d0Swillard  * Common Development and Distribution License (the "License").
64a6822d0Swillard  * You may not use this file except in compliance with the License.
74a6822d0Swillard  *
84a6822d0Swillard  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94a6822d0Swillard  * or http://www.opensolaris.org/os/licensing.
104a6822d0Swillard  * See the License for the specific language governing permissions
114a6822d0Swillard  * and limitations under the License.
124a6822d0Swillard  *
134a6822d0Swillard  * When distributing Covered Code, include this CDDL HEADER in each
144a6822d0Swillard  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154a6822d0Swillard  * If applicable, add the following below this CDDL HEADER, with the
164a6822d0Swillard  * fields enclosed by brackets "[]" replaced with your own identifying
174a6822d0Swillard  * information: Portions Copyright [yyyy] [name of copyright owner]
184a6822d0Swillard  *
194a6822d0Swillard  * CDDL HEADER END
204a6822d0Swillard  */
214a6822d0Swillard /*
22*dc5982c9SCarl Chesbrough  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
234a6822d0Swillard  */
244a6822d0Swillard 
254a6822d0Swillard /*
264a6822d0Swillard  * Telco-alarm library, which communicates through libpcp to set/get
274a6822d0Swillard  * alarms.
284a6822d0Swillard  */
294a6822d0Swillard 
304a6822d0Swillard #include <stdio.h>
314a6822d0Swillard #include <stdlib.h>
324a6822d0Swillard #include <sys/types.h>
334a6822d0Swillard #include <unistd.h>
344a6822d0Swillard #include <libpcp.h>
354a6822d0Swillard 
364a6822d0Swillard #include "tsalarm.h"
374a6822d0Swillard 
384a6822d0Swillard /* Message Types */
394a6822d0Swillard #define	TSALARM_CONTROL		15
404a6822d0Swillard #define	TSALARM_CONTROL_R	16
414a6822d0Swillard 
424a6822d0Swillard #define	TSALARM_CHANNEL_TIMEOUT	20
434a6822d0Swillard #define	TSALARM_MAX_RETRIES	3
444a6822d0Swillard #define	TSALARM_SERVICE_NAME	"SUNW,sun4v-telco-alarm"
454a6822d0Swillard 
464a6822d0Swillard int
tsalarm_get(uint32_t alarm_type,uint32_t * alarm_state)474a6822d0Swillard tsalarm_get(uint32_t alarm_type, uint32_t *alarm_state)
484a6822d0Swillard {
494a6822d0Swillard 	int		chnl_fd;
504a6822d0Swillard 	tsalarm_req_t	*req_ptr = NULL;
514a6822d0Swillard 	tsalarm_resp_t	*resp_ptr = NULL;
524a6822d0Swillard 	pcp_msg_t	send_msg;
534a6822d0Swillard 	pcp_msg_t	recv_msg;
544a6822d0Swillard 	int		rc = TSALARM_SUCCESS;
554a6822d0Swillard 	int		retries;
564a6822d0Swillard 
574a6822d0Swillard 	/* initialize virtual channel */
584a6822d0Swillard 	for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) {
594a6822d0Swillard 		if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) {
604a6822d0Swillard 			if (retries == TSALARM_MAX_RETRIES) {
614a6822d0Swillard 				rc = TSALARM_CHANNEL_INIT_FAILURE;
624a6822d0Swillard 				goto cleanup;
634a6822d0Swillard 			}
644a6822d0Swillard 			(void) sleep(TSALARM_CHANNEL_TIMEOUT);
654a6822d0Swillard 		} else
664a6822d0Swillard 			break;
674a6822d0Swillard 	}
684a6822d0Swillard 
694a6822d0Swillard 	/* create request message data */
704a6822d0Swillard 	req_ptr = malloc(sizeof (tsalarm_req_t));
714a6822d0Swillard 	if (req_ptr == NULL) {
724a6822d0Swillard 		rc = TSALARM_NULL_REQ_DATA;
734a6822d0Swillard 		goto cleanup;
744a6822d0Swillard 	}
754a6822d0Swillard 	req_ptr->alarm_action = TSALARM_STATUS;
764a6822d0Swillard 	req_ptr->alarm_id = alarm_type;
774a6822d0Swillard 
784a6822d0Swillard 	send_msg.msg_type = TSALARM_CONTROL;
794a6822d0Swillard 	send_msg.sub_type = NULL;
804a6822d0Swillard 	send_msg.msg_len = sizeof (tsalarm_req_t);
814a6822d0Swillard 	send_msg.msg_data = (uint8_t *)req_ptr;
824a6822d0Swillard 
834a6822d0Swillard 	/*
844a6822d0Swillard 	 * Send the request and receive the response.
854a6822d0Swillard 	 */
864a6822d0Swillard 	if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
874a6822d0Swillard 	    TSALARM_CHANNEL_TIMEOUT) < 0) {
884a6822d0Swillard 		/* we either timed out or erred; either way try again */
894a6822d0Swillard 		(void) sleep(TSALARM_CHANNEL_TIMEOUT);
904a6822d0Swillard 
914a6822d0Swillard 		if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
924a6822d0Swillard 		    TSALARM_CHANNEL_TIMEOUT) < 0) {
934a6822d0Swillard 			rc = TSALARM_COMM_FAILURE;
944a6822d0Swillard 			goto cleanup;
954a6822d0Swillard 		}
964a6822d0Swillard 	}
974a6822d0Swillard 
984a6822d0Swillard 	/*
99*dc5982c9SCarl Chesbrough 	 * verify that the Alarm action has taken place
100*dc5982c9SCarl Chesbrough 	 */
101*dc5982c9SCarl Chesbrough 	if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL)
102*dc5982c9SCarl Chesbrough 		goto cleanup;
103*dc5982c9SCarl Chesbrough 
104*dc5982c9SCarl Chesbrough 	/*
1054a6822d0Swillard 	 * validate that this data was meant for us
1064a6822d0Swillard 	 */
1074a6822d0Swillard 	if (recv_msg.msg_type != TSALARM_CONTROL_R) {
1084a6822d0Swillard 		rc = TSALARM_UNBOUND_PACKET_RECVD;
1094a6822d0Swillard 		goto cleanup;
1104a6822d0Swillard 	}
1114a6822d0Swillard 
1124a6822d0Swillard 	if (resp_ptr->status == TSALARM_ERROR) {
1134a6822d0Swillard 		rc = TSALARM_GET_ERROR;
1144a6822d0Swillard 		goto cleanup;
1154a6822d0Swillard 	}
1164a6822d0Swillard 
1174a6822d0Swillard 	if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) {
1184a6822d0Swillard 		rc = TSALARM_GET_ERROR;
1194a6822d0Swillard 		goto cleanup;
1204a6822d0Swillard 	}
1214a6822d0Swillard 
1224a6822d0Swillard 	*alarm_state = resp_ptr->alarm_state;
1234a6822d0Swillard 
1244a6822d0Swillard cleanup:
1254a6822d0Swillard 	if (req_ptr != NULL)
1264a6822d0Swillard 		free(req_ptr);
127*dc5982c9SCarl Chesbrough 
128*dc5982c9SCarl Chesbrough 	/* free recv_msg.msg_data through pointer to make sure it is valid */
129*dc5982c9SCarl Chesbrough 	if (resp_ptr != NULL)
130*dc5982c9SCarl Chesbrough 		free(resp_ptr);
1314a6822d0Swillard 
1324a6822d0Swillard 	/* close virtual channel fd */
1334a6822d0Swillard 	(void) pcp_close(chnl_fd);
1344a6822d0Swillard 
1354a6822d0Swillard 	return (rc);
1364a6822d0Swillard }
1374a6822d0Swillard 
1384a6822d0Swillard int
tsalarm_set(uint32_t alarm_type,uint32_t alarm_state)1394a6822d0Swillard tsalarm_set(uint32_t alarm_type, uint32_t alarm_state)
1404a6822d0Swillard {
1414a6822d0Swillard 	int		chnl_fd;
1424a6822d0Swillard 	tsalarm_req_t   *req_ptr = NULL;
1434a6822d0Swillard 	tsalarm_resp_t  *resp_ptr = NULL;
1444a6822d0Swillard 	pcp_msg_t	send_msg;
1454a6822d0Swillard 	pcp_msg_t	recv_msg;
1464a6822d0Swillard 	int		rc = TSALARM_SUCCESS;
1474a6822d0Swillard 	int		retries;
1484a6822d0Swillard 
1494a6822d0Swillard 	/* initialize virtual channel */
1504a6822d0Swillard 	for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) {
1514a6822d0Swillard 		if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) {
1524a6822d0Swillard 			if (retries == TSALARM_MAX_RETRIES) {
1534a6822d0Swillard 				rc = TSALARM_CHANNEL_INIT_FAILURE;
1544a6822d0Swillard 				goto cleanup;
1554a6822d0Swillard 			}
1564a6822d0Swillard 			(void) sleep(TSALARM_CHANNEL_TIMEOUT);
1574a6822d0Swillard 		} else
1584a6822d0Swillard 			break;
1594a6822d0Swillard 	}
1604a6822d0Swillard 
1614a6822d0Swillard 	/* create request message data */
1624a6822d0Swillard 	req_ptr = malloc(sizeof (tsalarm_req_t));
1634a6822d0Swillard 	if (req_ptr == NULL) {
1644a6822d0Swillard 		rc = TSALARM_NULL_REQ_DATA;
1654a6822d0Swillard 		goto cleanup;
1664a6822d0Swillard 	}
1674a6822d0Swillard 	req_ptr->alarm_id = alarm_type;
1684a6822d0Swillard 	if (alarm_state == TSALARM_STATE_ON)
1694a6822d0Swillard 		req_ptr->alarm_action = TSALARM_ENABLE;
1704a6822d0Swillard 	else if (alarm_state == TSALARM_STATE_OFF)
1714a6822d0Swillard 		req_ptr->alarm_action = TSALARM_DISABLE;
1724a6822d0Swillard 
1734a6822d0Swillard 	send_msg.msg_type = TSALARM_CONTROL;
1744a6822d0Swillard 	send_msg.sub_type = NULL;
1754a6822d0Swillard 	send_msg.msg_len = sizeof (tsalarm_req_t);
1764a6822d0Swillard 	send_msg.msg_data = (uint8_t *)req_ptr;
1774a6822d0Swillard 
1784a6822d0Swillard 	/*
1794a6822d0Swillard 	 * Send the request and receive the response.
1804a6822d0Swillard 	 */
1814a6822d0Swillard 	if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
1824a6822d0Swillard 	    TSALARM_CHANNEL_TIMEOUT) < 0) {
1834a6822d0Swillard 		/* we either timed out or erred; either way try again */
1844a6822d0Swillard 		(void) sleep(TSALARM_CHANNEL_TIMEOUT);
1854a6822d0Swillard 
1864a6822d0Swillard 		if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
1874a6822d0Swillard 		    TSALARM_CHANNEL_TIMEOUT) < 0) {
1884a6822d0Swillard 			rc = TSALARM_COMM_FAILURE;
1894a6822d0Swillard 			goto cleanup;
1904a6822d0Swillard 		}
1914a6822d0Swillard 	}
1924a6822d0Swillard 
1934a6822d0Swillard 	/*
194*dc5982c9SCarl Chesbrough 	 * verify that the Alarm action has taken place
195*dc5982c9SCarl Chesbrough 	 */
196*dc5982c9SCarl Chesbrough 	if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL)
197*dc5982c9SCarl Chesbrough 		goto cleanup;
198*dc5982c9SCarl Chesbrough 
199*dc5982c9SCarl Chesbrough 	/*
2004a6822d0Swillard 	 * validate that this data was meant for us
2014a6822d0Swillard 	 */
2024a6822d0Swillard 	if (recv_msg.msg_type != TSALARM_CONTROL_R) {
2034a6822d0Swillard 		rc = TSALARM_UNBOUND_PACKET_RECVD;
2044a6822d0Swillard 		goto cleanup;
2054a6822d0Swillard 	}
2064a6822d0Swillard 
2074a6822d0Swillard 	if (resp_ptr->status == TSALARM_ERROR) {
2084a6822d0Swillard 		rc = TSALARM_SET_ERROR;
2094a6822d0Swillard 		goto cleanup;
2104a6822d0Swillard 	}
2114a6822d0Swillard 
2124a6822d0Swillard 	/*
2134a6822d0Swillard 	 * ensure the Alarm action taken is the one requested
2144a6822d0Swillard 	 */
2154a6822d0Swillard 	if ((req_ptr->alarm_action == TSALARM_DISABLE) &&
2164a6822d0Swillard 	    (resp_ptr->alarm_state != TSALARM_STATE_OFF)) {
2174a6822d0Swillard 		rc = TSALARM_SET_ERROR;
2184a6822d0Swillard 		goto cleanup;
2194a6822d0Swillard 	} else if ((req_ptr->alarm_action == TSALARM_ENABLE) &&
2204a6822d0Swillard 	    (resp_ptr->alarm_state != TSALARM_STATE_ON)) {
2214a6822d0Swillard 		rc = TSALARM_SET_ERROR;
2224a6822d0Swillard 		goto cleanup;
2234a6822d0Swillard 	} else if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) {
2244a6822d0Swillard 		rc = TSALARM_SET_ERROR;
2254a6822d0Swillard 		goto cleanup;
2264a6822d0Swillard 	}
2274a6822d0Swillard 
2284a6822d0Swillard cleanup:
2294a6822d0Swillard 	if (req_ptr != NULL)
2304a6822d0Swillard 		free(req_ptr);
231*dc5982c9SCarl Chesbrough 
232*dc5982c9SCarl Chesbrough 	/* free recv_msg.msg_data through pointer to make sure it is valid */
233*dc5982c9SCarl Chesbrough 	if (resp_ptr != NULL)
234*dc5982c9SCarl Chesbrough 		free(resp_ptr);
2354a6822d0Swillard 
2364a6822d0Swillard 	/* close virtual channel fd */
2374a6822d0Swillard 	(void) pcp_close(chnl_fd);
2384a6822d0Swillard 
2394a6822d0Swillard 	return (rc);
2404a6822d0Swillard }
241