1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * Telco-alarm library, which communicates through libpcp to set/get 27 * alarms. 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <sys/types.h> 33 #include <unistd.h> 34 #include <libpcp.h> 35 36 #include "tsalarm.h" 37 38 /* Message Types */ 39 #define TSALARM_CONTROL 15 40 #define TSALARM_CONTROL_R 16 41 42 #define TSALARM_CHANNEL_TIMEOUT 20 43 #define TSALARM_MAX_RETRIES 3 44 #define TSALARM_SERVICE_NAME "SUNW,sun4v-telco-alarm" 45 46 int 47 tsalarm_get(uint32_t alarm_type, uint32_t *alarm_state) 48 { 49 int chnl_fd; 50 tsalarm_req_t *req_ptr = NULL; 51 tsalarm_resp_t *resp_ptr = NULL; 52 pcp_msg_t send_msg; 53 pcp_msg_t recv_msg; 54 int rc = TSALARM_SUCCESS; 55 int retries; 56 57 /* initialize virtual channel */ 58 for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) { 59 if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) { 60 if (retries == TSALARM_MAX_RETRIES) { 61 rc = TSALARM_CHANNEL_INIT_FAILURE; 62 goto cleanup; 63 } 64 (void) sleep(TSALARM_CHANNEL_TIMEOUT); 65 } else 66 break; 67 } 68 69 /* create request message data */ 70 req_ptr = malloc(sizeof (tsalarm_req_t)); 71 if (req_ptr == NULL) { 72 rc = TSALARM_NULL_REQ_DATA; 73 goto cleanup; 74 } 75 req_ptr->alarm_action = TSALARM_STATUS; 76 req_ptr->alarm_id = alarm_type; 77 78 send_msg.msg_type = TSALARM_CONTROL; 79 send_msg.sub_type = NULL; 80 send_msg.msg_len = sizeof (tsalarm_req_t); 81 send_msg.msg_data = (uint8_t *)req_ptr; 82 83 /* 84 * Send the request and receive the response. 85 */ 86 if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg, 87 TSALARM_CHANNEL_TIMEOUT) < 0) { 88 /* we either timed out or erred; either way try again */ 89 (void) sleep(TSALARM_CHANNEL_TIMEOUT); 90 91 if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg, 92 TSALARM_CHANNEL_TIMEOUT) < 0) { 93 rc = TSALARM_COMM_FAILURE; 94 goto cleanup; 95 } 96 } 97 98 /* 99 * verify that the Alarm action has taken place 100 */ 101 if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL) 102 goto cleanup; 103 104 /* 105 * validate that this data was meant for us 106 */ 107 if (recv_msg.msg_type != TSALARM_CONTROL_R) { 108 rc = TSALARM_UNBOUND_PACKET_RECVD; 109 goto cleanup; 110 } 111 112 if (resp_ptr->status == TSALARM_ERROR) { 113 rc = TSALARM_GET_ERROR; 114 goto cleanup; 115 } 116 117 if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) { 118 rc = TSALARM_GET_ERROR; 119 goto cleanup; 120 } 121 122 *alarm_state = resp_ptr->alarm_state; 123 124 cleanup: 125 if (req_ptr != NULL) 126 free(req_ptr); 127 128 /* free recv_msg.msg_data through pointer to make sure it is valid */ 129 if (resp_ptr != NULL) 130 free(resp_ptr); 131 132 /* close virtual channel fd */ 133 (void) pcp_close(chnl_fd); 134 135 return (rc); 136 } 137 138 int 139 tsalarm_set(uint32_t alarm_type, uint32_t alarm_state) 140 { 141 int chnl_fd; 142 tsalarm_req_t *req_ptr = NULL; 143 tsalarm_resp_t *resp_ptr = NULL; 144 pcp_msg_t send_msg; 145 pcp_msg_t recv_msg; 146 int rc = TSALARM_SUCCESS; 147 int retries; 148 149 /* initialize virtual channel */ 150 for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) { 151 if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) { 152 if (retries == TSALARM_MAX_RETRIES) { 153 rc = TSALARM_CHANNEL_INIT_FAILURE; 154 goto cleanup; 155 } 156 (void) sleep(TSALARM_CHANNEL_TIMEOUT); 157 } else 158 break; 159 } 160 161 /* create request message data */ 162 req_ptr = malloc(sizeof (tsalarm_req_t)); 163 if (req_ptr == NULL) { 164 rc = TSALARM_NULL_REQ_DATA; 165 goto cleanup; 166 } 167 req_ptr->alarm_id = alarm_type; 168 if (alarm_state == TSALARM_STATE_ON) 169 req_ptr->alarm_action = TSALARM_ENABLE; 170 else if (alarm_state == TSALARM_STATE_OFF) 171 req_ptr->alarm_action = TSALARM_DISABLE; 172 173 send_msg.msg_type = TSALARM_CONTROL; 174 send_msg.sub_type = NULL; 175 send_msg.msg_len = sizeof (tsalarm_req_t); 176 send_msg.msg_data = (uint8_t *)req_ptr; 177 178 /* 179 * Send the request and receive the response. 180 */ 181 if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg, 182 TSALARM_CHANNEL_TIMEOUT) < 0) { 183 /* we either timed out or erred; either way try again */ 184 (void) sleep(TSALARM_CHANNEL_TIMEOUT); 185 186 if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg, 187 TSALARM_CHANNEL_TIMEOUT) < 0) { 188 rc = TSALARM_COMM_FAILURE; 189 goto cleanup; 190 } 191 } 192 193 /* 194 * verify that the Alarm action has taken place 195 */ 196 if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL) 197 goto cleanup; 198 199 /* 200 * validate that this data was meant for us 201 */ 202 if (recv_msg.msg_type != TSALARM_CONTROL_R) { 203 rc = TSALARM_UNBOUND_PACKET_RECVD; 204 goto cleanup; 205 } 206 207 if (resp_ptr->status == TSALARM_ERROR) { 208 rc = TSALARM_SET_ERROR; 209 goto cleanup; 210 } 211 212 /* 213 * ensure the Alarm action taken is the one requested 214 */ 215 if ((req_ptr->alarm_action == TSALARM_DISABLE) && 216 (resp_ptr->alarm_state != TSALARM_STATE_OFF)) { 217 rc = TSALARM_SET_ERROR; 218 goto cleanup; 219 } else if ((req_ptr->alarm_action == TSALARM_ENABLE) && 220 (resp_ptr->alarm_state != TSALARM_STATE_ON)) { 221 rc = TSALARM_SET_ERROR; 222 goto cleanup; 223 } else if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) { 224 rc = TSALARM_SET_ERROR; 225 goto cleanup; 226 } 227 228 cleanup: 229 if (req_ptr != NULL) 230 free(req_ptr); 231 232 /* free recv_msg.msg_data through pointer to make sure it is valid */ 233 if (resp_ptr != NULL) 234 free(resp_ptr); 235 236 /* close virtual channel fd */ 237 (void) pcp_close(chnl_fd); 238 239 return (rc); 240 } 241