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()");
187 if (plat_opts
!= NULL
)
190 return (ret
== CFGA_OK
? 0 : -1);
194 event_process(char *ap_id
, char *req
, char *acpi_event_type
)
197 struct cfga_msg message
;
198 struct cfga_confirm confirm
;
200 if (strcmp(req
, DR_REQ_INCOMING_RES
) != 0) {
202 "Event is not supported (ap_id = %s, req = %s)",
208 (void) memset(&confirm
, 0, sizeof (confirm
));
209 confirm
.confirm
= confirm_no
;
210 (void) memset(&message
, 0, sizeof (message
));
211 message
.message_routine
= message_output
;
213 if (cfgadm_cmd_wrapper(SBD_CMD_ASSIGN
, 1, apids
,
214 acpi_event_type
, STATUS_NOOP
, &confirm
, &message
) != 0) {
218 "board '%s' has been assigned successfully", ap_id
);
219 (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU
, 1, apids
,
220 acpi_event_type
, STATUS_INPROGRESS
, &confirm
, &message
);
222 if (cfgadm_cmd_wrapper(SBD_CMD_POWERON
, 1, apids
,
223 acpi_event_type
, STATUS_NOOP
, &confirm
, &message
) != 0) {
227 "board '%s' has been powered on successfully", ap_id
);
228 (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU
, 1, apids
,
229 acpi_event_type
, STATUS_INPROGRESS
, &confirm
, &message
);
231 if (cfgadm_cmd_wrapper(SBD_CMD_CONNECT
, 1, apids
,
232 acpi_event_type
, STATUS_INPROGRESS
, &confirm
, &message
) != 0) {
236 "board '%s' has been connected successfully", ap_id
);
237 (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU
, 1, apids
,
238 acpi_event_type
, STATUS_INPROGRESS
, &confirm
, &message
);
240 if (cfgadm_cmd_wrapper(SBD_CMD_CONFIGURE
, 1, apids
,
241 acpi_event_type
, STATUS_INPROGRESS
, &confirm
, &message
) != 0) {
245 "board '%s' has been configured successfully", ap_id
);
246 (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU
, 1, apids
,
247 acpi_event_type
, STATUS_SUCCESS
, &confirm
, &message
);
249 (void) system(PMCONFIG_PATH
);
251 "board '%s' has been added into system successfully", ap_id
);
256 (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU
, 1, apids
,
257 acpi_event_type
, STATUS_FAILURE
, &confirm
, &message
);
259 syslog(LOG_ERR
, "failed to add board '%s' into system", ap_id
);
265 notify_hotplug(sysevent_t
*ev
)
268 nvlist_t
*attr_list
= NULL
;
269 char *class, *subclass
;
270 char *ap_id
, *req
, *acpi_event_type
;
272 vendor
= sysevent_get_vendor_name(ev
);
273 debug_print(2, "message_vendor = '%s'", vendor
? vendor
: "unknown");
274 if (vendor
== NULL
|| strcmp(vendor
, SUNW_VENDOR
) != 0) {
276 "vendor id of message is not '%s'", SUNW_VENDOR
);
280 class = sysevent_get_class_name(ev
);
281 debug_print(2, "message_class = '%s'", class ? class : "unknown");
282 if (class == NULL
|| strcmp(class, EC_DR
) != 0) {
283 debug_print(2, "class of message is not '%s'", EC_DR
);
287 subclass
= sysevent_get_subclass_name(ev
);
289 "message_subclass = '%s'", subclass
? subclass
: "unknown");
290 if (subclass
== NULL
|| strcmp(subclass
, ESC_DR_REQ
) != 0) {
292 "subclass of message is not '%s'", ESC_DR_REQ
);
296 if (sysevent_get_attr_list(ev
, &attr_list
) != 0) {
298 "can't retrieve attribute list from DR message");
302 if (nvlist_lookup_string(attr_list
, DR_AP_ID
, &ap_id
) != 0) {
304 "can't retrieve '%s' property from attribute list",
308 debug_print(2, "%s = '%s'", DR_AP_ID
, ap_id
? ap_id
: "<null>");
309 if ((ap_id
== NULL
) || (strlen(ap_id
) == 0)) {
310 debug_print(2, "'%s' property in message is NULL", DR_AP_ID
);
314 if (nvlist_lookup_string(attr_list
, DR_REQ_TYPE
, &req
) != 0) {
316 "can't retrieve '%s' property from attribute list",
320 debug_print(2, "%s = '%s'", DR_REQ_TYPE
, req
? req
: "<null>");
321 if ((req
== NULL
) || (strlen(req
) == 0)) {
322 debug_print(2, "'%s' property in message is NULL", DR_REQ_TYPE
);
326 if (nvlist_lookup_string(attr_list
, ACPIDEV_EVENT_TYPE_ATTR_NAME
,
327 &acpi_event_type
) != 0) {
329 "can't retrieve '%s' property from attribute list",
330 ACPIDEV_EVENT_TYPE_ATTR_NAME
);
333 debug_print(2, "%s = '%s'", ACPIDEV_EVENT_TYPE_ATTR_NAME
,
334 acpi_event_type
? acpi_event_type
: "<null>");
335 if ((acpi_event_type
== NULL
) || (strlen(acpi_event_type
) == 0)) {
336 debug_print(2, "'%s' property in message is NULL",
337 ACPIDEV_EVENT_TYPE_ATTR_NAME
);
341 (void) event_process(ap_id
, req
, acpi_event_type
);
344 if (vendor
!= NULL
) {
348 if (attr_list
!= NULL
) {
349 nvlist_free(attr_list
);
352 /* No need to free class & subclass. */