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
tsalarm_get(uint32_t alarm_type,uint32_t * alarm_state)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
tsalarm_set(uint32_t alarm_type,uint32_t alarm_state)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