xref: /titanic_44/usr/src/lib/libtsalarm/common/tsalarm.c (revision 4a6822d07d6d3f9ffe6907ef5f10d11dcadd75c6)
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