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