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