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.
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.
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]
22 * Copyright (c) 2010, Intel Corporation.
23 * All rights reserved.
30 #include <config_admin.h>
33 #include <libsysevent.h>
34 #include <libdevinfo.h>
35 #include <libnvpair.h>
40 #include <sys/types.h>
42 #include <sys/sysevent/eventdefs.h>
43 #include <sys/sysevent/dr.h>
44 #include <sys/sbd_ioctl.h>
45 #include <sys/acpidev.h>
47 #define PMCONFIG_PATH "/usr/sbin/pmconfig"
49 #define CFGADM_CMD_ASSIGN "assign"
50 #define CFGADM_CMD_POWERON "poweron"
51 #define CFGADM_CMD_PASSTHRU "passthru"
53 #define STATUS_INPROGRESS 0
54 #define STATUS_SUCCESS 1
55 #define STATUS_FAILURE 2
58 static char *s_status_array
[] = {
59 ACPIDEV_CMD_OST_INPROGRESS
,
60 ACPIDEV_CMD_OST_SUCCESS
,
61 ACPIDEV_CMD_OST_FAILURE
,
65 extern void debug_print(int, const char *, ...);
69 confirm_no(void *appdata_ptr
, const char *message
)
76 message_output(void *appdata_ptr
, const char *message
)
78 debug_print(2, "cfgadm message: %s", message
);
83 plat_opt_str_alloc(int cmd
, char *acpi_event_type
, int status
)
88 if (cmd
== SBD_CMD_PASSTHRU
) {
89 len
= strlen(s_status_array
[status
]) +
90 strlen(ACPIDEV_EVENT_TYPE_ATTR_NAME
) +
91 strlen(acpi_event_type
) + 10;
92 if ((opt
= malloc(len
)) != NULL
) {
93 (void) snprintf(opt
, len
, "%s %s=%s",
94 s_status_array
[status
],
95 ACPIDEV_EVENT_TYPE_ATTR_NAME
,
97 debug_print(2, "plat_opt_str_alloc = '%s'", opt
);
100 len
= strlen("platform=''") +
101 strlen(s_status_array
[status
]) +
102 strlen(ACPIDEV_EVENT_TYPE_ATTR_NAME
) +
103 strlen(acpi_event_type
) + 10;
104 if ((opt
= malloc(len
)) != NULL
) {
105 (void) snprintf(opt
, len
, "platform='%s %s=%s'",
106 s_status_array
[status
],
107 ACPIDEV_EVENT_TYPE_ATTR_NAME
,
109 debug_print(2, "plat_opt_str_alloc = '%s'", opt
);
117 cfgadm_cmd_wrapper(int cmd
, int apid_num
, char **apids
,
118 char *acpi_event_type
, int status
,
119 struct cfga_confirm
*confirm
, struct cfga_msg
*message
)
125 assert(apid_num
== 1);
126 assert(apids
!= NULL
);
128 plat_opts
= plat_opt_str_alloc(cmd
, acpi_event_type
, status
);
129 if (plat_opts
== NULL
) {
131 "failed to generate platform option string for cfgadm");
136 case SBD_CMD_CONNECT
:
137 ret
= config_change_state(CFGA_CMD_CONNECT
, apid_num
, apids
,
138 plat_opts
, confirm
, message
, &estrp
, 0);
139 if (ret
!= CFGA_OK
) {
140 debug_print(0, "cfgadm('connect', '%s') failed, "
141 "ret = %d, errstr = '%s'", apids
[0], ret
, estrp
);
145 case SBD_CMD_CONFIGURE
:
146 ret
= config_change_state(CFGA_CMD_CONFIGURE
, apid_num
, apids
,
147 plat_opts
, confirm
, message
, &estrp
, 0);
148 if (ret
!= CFGA_OK
) {
149 debug_print(0, "cfgadm('configure', '%s') failed, "
150 "ret = %d, errstr = '%s'", apids
[0], ret
, estrp
);
155 ret
= config_private_func(CFGADM_CMD_ASSIGN
, apid_num
, apids
,
156 plat_opts
, confirm
, message
, &estrp
, 0);
157 if (ret
!= CFGA_OK
) {
158 debug_print(0, "cfgadm('assign', '%s') failed, "
159 "ret = %d, errstr = '%s'", apids
[0], ret
, estrp
);
163 case SBD_CMD_POWERON
:
164 ret
= config_private_func(CFGADM_CMD_POWERON
, apid_num
, apids
,
165 plat_opts
, confirm
, message
, &estrp
, 0);
166 if (ret
!= CFGA_OK
) {
167 debug_print(0, "cfgadm('poweron', '%s') failed, "
168 "ret = %d, errstr = '%s'", apids
[0], ret
, estrp
);
172 case SBD_CMD_PASSTHRU
:
173 ret
= config_private_func(CFGADM_CMD_PASSTHRU
, apid_num
, apids
,
174 plat_opts
, confirm
, message
, &estrp
, 0);
175 if (ret
!= CFGA_OK
) {
176 debug_print(0, "cfgadm('passthru', '%s') failed, "
177 "ret = %d, errstr = '%s'", apids
[0], ret
, estrp
);
182 debug_print(2, "unknown command (%d) to cfgadm_cmd_wrapper()");
189 return (ret
== CFGA_OK
? 0 : -1);
193 event_process(char *ap_id
, char *req
, char *acpi_event_type
)
196 struct cfga_msg message
;
197 struct cfga_confirm confirm
;
199 if (strcmp(req
, DR_REQ_INCOMING_RES
) != 0) {
201 "Event is not supported (ap_id = %s, req = %s)",
207 (void) memset(&confirm
, 0, sizeof (confirm
));
208 confirm
.confirm
= confirm_no
;
209 (void) memset(&message
, 0, sizeof (message
));
210 message
.message_routine
= message_output
;
212 if (cfgadm_cmd_wrapper(SBD_CMD_ASSIGN
, 1, apids
,
213 acpi_event_type
, STATUS_NOOP
, &confirm
, &message
) != 0) {
217 "board '%s' has been assigned successfully", ap_id
);
218 (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU
, 1, apids
,
219 acpi_event_type
, STATUS_INPROGRESS
, &confirm
, &message
);
221 if (cfgadm_cmd_wrapper(SBD_CMD_POWERON
, 1, apids
,
222 acpi_event_type
, STATUS_NOOP
, &confirm
, &message
) != 0) {
226 "board '%s' has been powered on successfully", ap_id
);
227 (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU
, 1, apids
,
228 acpi_event_type
, STATUS_INPROGRESS
, &confirm
, &message
);
230 if (cfgadm_cmd_wrapper(SBD_CMD_CONNECT
, 1, apids
,
231 acpi_event_type
, STATUS_INPROGRESS
, &confirm
, &message
) != 0) {
235 "board '%s' has been connected successfully", ap_id
);
236 (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU
, 1, apids
,
237 acpi_event_type
, STATUS_INPROGRESS
, &confirm
, &message
);
239 if (cfgadm_cmd_wrapper(SBD_CMD_CONFIGURE
, 1, apids
,
240 acpi_event_type
, STATUS_INPROGRESS
, &confirm
, &message
) != 0) {
244 "board '%s' has been configured successfully", ap_id
);
245 (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU
, 1, apids
,
246 acpi_event_type
, STATUS_SUCCESS
, &confirm
, &message
);
248 (void) system(PMCONFIG_PATH
);
250 "board '%s' has been added into system successfully", ap_id
);
255 (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU
, 1, apids
,
256 acpi_event_type
, STATUS_FAILURE
, &confirm
, &message
);
258 syslog(LOG_ERR
, "failed to add board '%s' into system", ap_id
);
264 notify_hotplug(sysevent_t
*ev
)
267 nvlist_t
*attr_list
= NULL
;
268 char *class, *subclass
;
269 char *ap_id
, *req
, *acpi_event_type
;
271 vendor
= sysevent_get_vendor_name(ev
);
272 debug_print(2, "message_vendor = '%s'", vendor
? vendor
: "unknown");
273 if (vendor
== NULL
|| strcmp(vendor
, SUNW_VENDOR
) != 0) {
275 "vendor id of message is not '%s'", SUNW_VENDOR
);
279 class = sysevent_get_class_name(ev
);
280 debug_print(2, "message_class = '%s'", class ? class : "unknown");
281 if (class == NULL
|| strcmp(class, EC_DR
) != 0) {
282 debug_print(2, "class of message is not '%s'", EC_DR
);
286 subclass
= sysevent_get_subclass_name(ev
);
288 "message_subclass = '%s'", subclass
? subclass
: "unknown");
289 if (subclass
== NULL
|| strcmp(subclass
, ESC_DR_REQ
) != 0) {
291 "subclass of message is not '%s'", ESC_DR_REQ
);
295 if (sysevent_get_attr_list(ev
, &attr_list
) != 0) {
297 "can't retrieve attribute list from DR message");
301 if (nvlist_lookup_string(attr_list
, DR_AP_ID
, &ap_id
) != 0) {
303 "can't retrieve '%s' property from attribute list",
307 debug_print(2, "%s = '%s'", DR_AP_ID
, ap_id
? ap_id
: "<null>");
308 if ((ap_id
== NULL
) || (strlen(ap_id
) == 0)) {
309 debug_print(2, "'%s' property in message is NULL", DR_AP_ID
);
313 if (nvlist_lookup_string(attr_list
, DR_REQ_TYPE
, &req
) != 0) {
315 "can't retrieve '%s' property from attribute list",
319 debug_print(2, "%s = '%s'", DR_REQ_TYPE
, req
? req
: "<null>");
320 if ((req
== NULL
) || (strlen(req
) == 0)) {
321 debug_print(2, "'%s' property in message is NULL", DR_REQ_TYPE
);
325 if (nvlist_lookup_string(attr_list
, ACPIDEV_EVENT_TYPE_ATTR_NAME
,
326 &acpi_event_type
) != 0) {
328 "can't retrieve '%s' property from attribute list",
329 ACPIDEV_EVENT_TYPE_ATTR_NAME
);
332 debug_print(2, "%s = '%s'", ACPIDEV_EVENT_TYPE_ATTR_NAME
,
333 acpi_event_type
? acpi_event_type
: "<null>");
334 if ((acpi_event_type
== NULL
) || (strlen(acpi_event_type
) == 0)) {
335 debug_print(2, "'%s' property in message is NULL",
336 ACPIDEV_EVENT_TYPE_ATTR_NAME
);
340 (void) event_process(ap_id
, req
, acpi_event_type
);
343 if (vendor
!= NULL
) {
347 nvlist_free(attr_list
);
349 /* No need to free class & subclass. */