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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Telco-alarm library, which communicates through libpcp to set/get 28 * alarms. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <sys/types.h> 36 #include <unistd.h> 37 #include <libpcp.h> 38 39 #include "tsalarm.h" 40 41 /* Message Types */ 42 #define TSALARM_CONTROL 15 43 #define TSALARM_CONTROL_R 16 44 45 #define TSALARM_CHANNEL_TIMEOUT 20 46 #define TSALARM_MAX_RETRIES 3 47 #define TSALARM_SERVICE_NAME "SUNW,sun4v-telco-alarm" 48 49 int 50 tsalarm_get(uint32_t alarm_type, uint32_t *alarm_state) 51 { 52 int chnl_fd; 53 tsalarm_req_t *req_ptr = NULL; 54 tsalarm_resp_t *resp_ptr = NULL; 55 pcp_msg_t send_msg; 56 pcp_msg_t recv_msg; 57 int rc = TSALARM_SUCCESS; 58 int retries; 59 60 /* initialize virtual channel */ 61 for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) { 62 if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) { 63 if (retries == TSALARM_MAX_RETRIES) { 64 rc = TSALARM_CHANNEL_INIT_FAILURE; 65 goto cleanup; 66 } 67 (void) sleep(TSALARM_CHANNEL_TIMEOUT); 68 } else 69 break; 70 } 71 72 /* create request message data */ 73 req_ptr = malloc(sizeof (tsalarm_req_t)); 74 if (req_ptr == NULL) { 75 rc = TSALARM_NULL_REQ_DATA; 76 goto cleanup; 77 } 78 req_ptr->alarm_action = TSALARM_STATUS; 79 req_ptr->alarm_id = alarm_type; 80 81 send_msg.msg_type = TSALARM_CONTROL; 82 send_msg.sub_type = NULL; 83 send_msg.msg_len = sizeof (tsalarm_req_t); 84 send_msg.msg_data = (uint8_t *)req_ptr; 85 86 /* 87 * Send the request and receive the response. 88 */ 89 if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg, 90 TSALARM_CHANNEL_TIMEOUT) < 0) { 91 /* we either timed out or erred; either way try again */ 92 (void) sleep(TSALARM_CHANNEL_TIMEOUT); 93 94 if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg, 95 TSALARM_CHANNEL_TIMEOUT) < 0) { 96 rc = TSALARM_COMM_FAILURE; 97 goto cleanup; 98 } 99 } 100 101 /* 102 * validate that this data was meant for us 103 */ 104 if (recv_msg.msg_type != TSALARM_CONTROL_R) { 105 rc = TSALARM_UNBOUND_PACKET_RECVD; 106 goto cleanup; 107 } 108 109 /* 110 * verify that the Alarm action has taken place 111 */ 112 if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL) 113 goto cleanup; 114 115 if (resp_ptr->status == TSALARM_ERROR) { 116 rc = TSALARM_GET_ERROR; 117 goto cleanup; 118 } 119 120 if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) { 121 rc = TSALARM_GET_ERROR; 122 goto cleanup; 123 } 124 125 *alarm_state = resp_ptr->alarm_state; 126 127 cleanup: 128 if (req_ptr != NULL) 129 free(req_ptr); 130 if (recv_msg.msg_data != NULL) 131 free(recv_msg.msg_data); 132 133 /* close virtual channel fd */ 134 (void) pcp_close(chnl_fd); 135 136 return (rc); 137 } 138 139 int 140 tsalarm_set(uint32_t alarm_type, uint32_t alarm_state) 141 { 142 int chnl_fd; 143 tsalarm_req_t *req_ptr = NULL; 144 tsalarm_resp_t *resp_ptr = NULL; 145 pcp_msg_t send_msg; 146 pcp_msg_t recv_msg; 147 int rc = TSALARM_SUCCESS; 148 int retries; 149 150 /* initialize virtual channel */ 151 for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) { 152 if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) { 153 if (retries == TSALARM_MAX_RETRIES) { 154 rc = TSALARM_CHANNEL_INIT_FAILURE; 155 goto cleanup; 156 } 157 (void) sleep(TSALARM_CHANNEL_TIMEOUT); 158 } else 159 break; 160 } 161 162 /* create request message data */ 163 req_ptr = malloc(sizeof (tsalarm_req_t)); 164 if (req_ptr == NULL) { 165 rc = TSALARM_NULL_REQ_DATA; 166 goto cleanup; 167 } 168 req_ptr->alarm_id = alarm_type; 169 if (alarm_state == TSALARM_STATE_ON) 170 req_ptr->alarm_action = TSALARM_ENABLE; 171 else if (alarm_state == TSALARM_STATE_OFF) 172 req_ptr->alarm_action = TSALARM_DISABLE; 173 174 send_msg.msg_type = TSALARM_CONTROL; 175 send_msg.sub_type = NULL; 176 send_msg.msg_len = sizeof (tsalarm_req_t); 177 send_msg.msg_data = (uint8_t *)req_ptr; 178 179 /* 180 * Send the request and receive the response. 181 */ 182 if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg, 183 TSALARM_CHANNEL_TIMEOUT) < 0) { 184 /* we either timed out or erred; either way try again */ 185 (void) sleep(TSALARM_CHANNEL_TIMEOUT); 186 187 if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg, 188 TSALARM_CHANNEL_TIMEOUT) < 0) { 189 rc = TSALARM_COMM_FAILURE; 190 goto cleanup; 191 } 192 } 193 194 /* 195 * validate that this data was meant for us 196 */ 197 if (recv_msg.msg_type != TSALARM_CONTROL_R) { 198 rc = TSALARM_UNBOUND_PACKET_RECVD; 199 goto cleanup; 200 } 201 202 /* 203 * verify that the Alarm action has taken place 204 */ 205 if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL) 206 goto cleanup; 207 208 if (resp_ptr->status == TSALARM_ERROR) { 209 rc = TSALARM_SET_ERROR; 210 goto cleanup; 211 } 212 213 /* 214 * ensure the Alarm action taken is the one requested 215 */ 216 if ((req_ptr->alarm_action == TSALARM_DISABLE) && 217 (resp_ptr->alarm_state != TSALARM_STATE_OFF)) { 218 rc = TSALARM_SET_ERROR; 219 goto cleanup; 220 } else if ((req_ptr->alarm_action == TSALARM_ENABLE) && 221 (resp_ptr->alarm_state != TSALARM_STATE_ON)) { 222 rc = TSALARM_SET_ERROR; 223 goto cleanup; 224 } else if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) { 225 rc = TSALARM_SET_ERROR; 226 goto cleanup; 227 } 228 229 cleanup: 230 if (req_ptr != NULL) 231 free(req_ptr); 232 if (recv_msg.msg_data != NULL) 233 free(recv_msg.msg_data); 234 235 /* close virtual channel fd */ 236 (void) pcp_close(chnl_fd); 237 238 return (rc); 239 } 240