14975Swillard /*
24975Swillard * CDDL HEADER START
34975Swillard *
44975Swillard * The contents of this file are subject to the terms of the
54975Swillard * Common Development and Distribution License (the "License").
64975Swillard * You may not use this file except in compliance with the License.
74975Swillard *
84975Swillard * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94975Swillard * or http://www.opensolaris.org/os/licensing.
104975Swillard * See the License for the specific language governing permissions
114975Swillard * and limitations under the License.
124975Swillard *
134975Swillard * When distributing Covered Code, include this CDDL HEADER in each
144975Swillard * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154975Swillard * If applicable, add the following below this CDDL HEADER, with the
164975Swillard * fields enclosed by brackets "[]" replaced with your own identifying
174975Swillard * information: Portions Copyright [yyyy] [name of copyright owner]
184975Swillard *
194975Swillard * CDDL HEADER END
204975Swillard */
214975Swillard /*
22*12241Scarl.chesbrough@sun.com * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
234975Swillard */
244975Swillard
254975Swillard /*
264975Swillard * Telco-alarm library, which communicates through libpcp to set/get
274975Swillard * alarms.
284975Swillard */
294975Swillard
304975Swillard #include <stdio.h>
314975Swillard #include <stdlib.h>
324975Swillard #include <sys/types.h>
334975Swillard #include <unistd.h>
344975Swillard #include <libpcp.h>
354975Swillard
364975Swillard #include "tsalarm.h"
374975Swillard
384975Swillard /* Message Types */
394975Swillard #define TSALARM_CONTROL 15
404975Swillard #define TSALARM_CONTROL_R 16
414975Swillard
424975Swillard #define TSALARM_CHANNEL_TIMEOUT 20
434975Swillard #define TSALARM_MAX_RETRIES 3
444975Swillard #define TSALARM_SERVICE_NAME "SUNW,sun4v-telco-alarm"
454975Swillard
464975Swillard int
tsalarm_get(uint32_t alarm_type,uint32_t * alarm_state)474975Swillard tsalarm_get(uint32_t alarm_type, uint32_t *alarm_state)
484975Swillard {
494975Swillard int chnl_fd;
504975Swillard tsalarm_req_t *req_ptr = NULL;
514975Swillard tsalarm_resp_t *resp_ptr = NULL;
524975Swillard pcp_msg_t send_msg;
534975Swillard pcp_msg_t recv_msg;
544975Swillard int rc = TSALARM_SUCCESS;
554975Swillard int retries;
564975Swillard
574975Swillard /* initialize virtual channel */
584975Swillard for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) {
594975Swillard if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) {
604975Swillard if (retries == TSALARM_MAX_RETRIES) {
614975Swillard rc = TSALARM_CHANNEL_INIT_FAILURE;
624975Swillard goto cleanup;
634975Swillard }
644975Swillard (void) sleep(TSALARM_CHANNEL_TIMEOUT);
654975Swillard } else
664975Swillard break;
674975Swillard }
684975Swillard
694975Swillard /* create request message data */
704975Swillard req_ptr = malloc(sizeof (tsalarm_req_t));
714975Swillard if (req_ptr == NULL) {
724975Swillard rc = TSALARM_NULL_REQ_DATA;
734975Swillard goto cleanup;
744975Swillard }
754975Swillard req_ptr->alarm_action = TSALARM_STATUS;
764975Swillard req_ptr->alarm_id = alarm_type;
774975Swillard
784975Swillard send_msg.msg_type = TSALARM_CONTROL;
794975Swillard send_msg.sub_type = NULL;
804975Swillard send_msg.msg_len = sizeof (tsalarm_req_t);
814975Swillard send_msg.msg_data = (uint8_t *)req_ptr;
824975Swillard
834975Swillard /*
844975Swillard * Send the request and receive the response.
854975Swillard */
864975Swillard if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
874975Swillard TSALARM_CHANNEL_TIMEOUT) < 0) {
884975Swillard /* we either timed out or erred; either way try again */
894975Swillard (void) sleep(TSALARM_CHANNEL_TIMEOUT);
904975Swillard
914975Swillard if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
924975Swillard TSALARM_CHANNEL_TIMEOUT) < 0) {
934975Swillard rc = TSALARM_COMM_FAILURE;
944975Swillard goto cleanup;
954975Swillard }
964975Swillard }
974975Swillard
984975Swillard /*
99*12241Scarl.chesbrough@sun.com * verify that the Alarm action has taken place
100*12241Scarl.chesbrough@sun.com */
101*12241Scarl.chesbrough@sun.com if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL)
102*12241Scarl.chesbrough@sun.com goto cleanup;
103*12241Scarl.chesbrough@sun.com
104*12241Scarl.chesbrough@sun.com /*
1054975Swillard * validate that this data was meant for us
1064975Swillard */
1074975Swillard if (recv_msg.msg_type != TSALARM_CONTROL_R) {
1084975Swillard rc = TSALARM_UNBOUND_PACKET_RECVD;
1094975Swillard goto cleanup;
1104975Swillard }
1114975Swillard
1124975Swillard if (resp_ptr->status == TSALARM_ERROR) {
1134975Swillard rc = TSALARM_GET_ERROR;
1144975Swillard goto cleanup;
1154975Swillard }
1164975Swillard
1174975Swillard if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) {
1184975Swillard rc = TSALARM_GET_ERROR;
1194975Swillard goto cleanup;
1204975Swillard }
1214975Swillard
1224975Swillard *alarm_state = resp_ptr->alarm_state;
1234975Swillard
1244975Swillard cleanup:
1254975Swillard if (req_ptr != NULL)
1264975Swillard free(req_ptr);
127*12241Scarl.chesbrough@sun.com
128*12241Scarl.chesbrough@sun.com /* free recv_msg.msg_data through pointer to make sure it is valid */
129*12241Scarl.chesbrough@sun.com if (resp_ptr != NULL)
130*12241Scarl.chesbrough@sun.com free(resp_ptr);
1314975Swillard
1324975Swillard /* close virtual channel fd */
1334975Swillard (void) pcp_close(chnl_fd);
1344975Swillard
1354975Swillard return (rc);
1364975Swillard }
1374975Swillard
1384975Swillard int
tsalarm_set(uint32_t alarm_type,uint32_t alarm_state)1394975Swillard tsalarm_set(uint32_t alarm_type, uint32_t alarm_state)
1404975Swillard {
1414975Swillard int chnl_fd;
1424975Swillard tsalarm_req_t *req_ptr = NULL;
1434975Swillard tsalarm_resp_t *resp_ptr = NULL;
1444975Swillard pcp_msg_t send_msg;
1454975Swillard pcp_msg_t recv_msg;
1464975Swillard int rc = TSALARM_SUCCESS;
1474975Swillard int retries;
1484975Swillard
1494975Swillard /* initialize virtual channel */
1504975Swillard for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) {
1514975Swillard if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) {
1524975Swillard if (retries == TSALARM_MAX_RETRIES) {
1534975Swillard rc = TSALARM_CHANNEL_INIT_FAILURE;
1544975Swillard goto cleanup;
1554975Swillard }
1564975Swillard (void) sleep(TSALARM_CHANNEL_TIMEOUT);
1574975Swillard } else
1584975Swillard break;
1594975Swillard }
1604975Swillard
1614975Swillard /* create request message data */
1624975Swillard req_ptr = malloc(sizeof (tsalarm_req_t));
1634975Swillard if (req_ptr == NULL) {
1644975Swillard rc = TSALARM_NULL_REQ_DATA;
1654975Swillard goto cleanup;
1664975Swillard }
1674975Swillard req_ptr->alarm_id = alarm_type;
1684975Swillard if (alarm_state == TSALARM_STATE_ON)
1694975Swillard req_ptr->alarm_action = TSALARM_ENABLE;
1704975Swillard else if (alarm_state == TSALARM_STATE_OFF)
1714975Swillard req_ptr->alarm_action = TSALARM_DISABLE;
1724975Swillard
1734975Swillard send_msg.msg_type = TSALARM_CONTROL;
1744975Swillard send_msg.sub_type = NULL;
1754975Swillard send_msg.msg_len = sizeof (tsalarm_req_t);
1764975Swillard send_msg.msg_data = (uint8_t *)req_ptr;
1774975Swillard
1784975Swillard /*
1794975Swillard * Send the request and receive the response.
1804975Swillard */
1814975Swillard if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
1824975Swillard TSALARM_CHANNEL_TIMEOUT) < 0) {
1834975Swillard /* we either timed out or erred; either way try again */
1844975Swillard (void) sleep(TSALARM_CHANNEL_TIMEOUT);
1854975Swillard
1864975Swillard if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
1874975Swillard TSALARM_CHANNEL_TIMEOUT) < 0) {
1884975Swillard rc = TSALARM_COMM_FAILURE;
1894975Swillard goto cleanup;
1904975Swillard }
1914975Swillard }
1924975Swillard
1934975Swillard /*
194*12241Scarl.chesbrough@sun.com * verify that the Alarm action has taken place
195*12241Scarl.chesbrough@sun.com */
196*12241Scarl.chesbrough@sun.com if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL)
197*12241Scarl.chesbrough@sun.com goto cleanup;
198*12241Scarl.chesbrough@sun.com
199*12241Scarl.chesbrough@sun.com /*
2004975Swillard * validate that this data was meant for us
2014975Swillard */
2024975Swillard if (recv_msg.msg_type != TSALARM_CONTROL_R) {
2034975Swillard rc = TSALARM_UNBOUND_PACKET_RECVD;
2044975Swillard goto cleanup;
2054975Swillard }
2064975Swillard
2074975Swillard if (resp_ptr->status == TSALARM_ERROR) {
2084975Swillard rc = TSALARM_SET_ERROR;
2094975Swillard goto cleanup;
2104975Swillard }
2114975Swillard
2124975Swillard /*
2134975Swillard * ensure the Alarm action taken is the one requested
2144975Swillard */
2154975Swillard if ((req_ptr->alarm_action == TSALARM_DISABLE) &&
2164975Swillard (resp_ptr->alarm_state != TSALARM_STATE_OFF)) {
2174975Swillard rc = TSALARM_SET_ERROR;
2184975Swillard goto cleanup;
2194975Swillard } else if ((req_ptr->alarm_action == TSALARM_ENABLE) &&
2204975Swillard (resp_ptr->alarm_state != TSALARM_STATE_ON)) {
2214975Swillard rc = TSALARM_SET_ERROR;
2224975Swillard goto cleanup;
2234975Swillard } else if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) {
2244975Swillard rc = TSALARM_SET_ERROR;
2254975Swillard goto cleanup;
2264975Swillard }
2274975Swillard
2284975Swillard cleanup:
2294975Swillard if (req_ptr != NULL)
2304975Swillard free(req_ptr);
231*12241Scarl.chesbrough@sun.com
232*12241Scarl.chesbrough@sun.com /* free recv_msg.msg_data through pointer to make sure it is valid */
233*12241Scarl.chesbrough@sun.com if (resp_ptr != NULL)
234*12241Scarl.chesbrough@sun.com free(resp_ptr);
2354975Swillard
2364975Swillard /* close virtual channel fd */
2374975Swillard (void) pcp_close(chnl_fd);
2384975Swillard
2394975Swillard return (rc);
2404975Swillard }
241