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 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 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