dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / mpapi / libmpscsi_vhci / common / mp_utils.c
blobe640e66391fdae74e04c998e9247cc9bbf837003
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include "mp_utils.h"
26 #include <sys/sunddi.h>
28 #ifndef OIDLIST
29 #define OIDLIST "oid"
30 #endif
33 /* Remove these 5 when this source can compile with sunddi.h */
34 #ifndef EC_DDI
35 #define EC_DDI "EC_ddi"
36 #endif
38 #ifndef ESC_DDI_INITIATOR_REGISTER
39 #define ESC_DDI_INITIATOR_REGISTER "ESC_ddi_initiator_register"
40 #endif
42 #ifndef ESC_DDI_INITIATOR_UNREGISTER
43 #define ESC_DDI_INITIATOR_UNREGISTER "ESC_ddi_initiator_unregister"
44 #endif
46 #ifndef DDI_DRIVER_MAJOR
47 #define DDI_DRIVER_MAJOR "ddi.major"
48 #endif
50 #ifndef DDI_INSTANCE
51 #define DDI_INSTANCE "ddi.instance"
52 #endif
55 #define VISA_CHANGE 1
56 #define PROP_CHANGE 2
60 MP_STATUS
61 getStatus4ErrorCode(int driverError)
63 MP_STATUS mpStatus = MP_STATUS_FAILED;
65 log(LOG_INFO, "getStatus4ErrorCode()", "- enter");
67 switch (driverError) {
69 case MP_DRVR_INVALID_ID:
70 log(LOG_INFO, "getStatus4ErrorCode()",
71 " received mp_errno=MP_DRVR_INVALID_ID"
72 " from driver call.");
73 log(LOG_INFO, "getStatus4ErrorCode()",
74 " returning MP_STATUS_OBJECT_NOT_FOUND"
75 " to caller.");
76 mpStatus = MP_STATUS_OBJECT_NOT_FOUND;
77 break;
80 case MP_DRVR_ID_OBSOLETE:
81 log(LOG_INFO, "getStatus4ErrorCode()",
82 " received mp_errno=MP_DRVR_ID_OBSOLETE"
83 " from driver call.");
84 log(LOG_INFO, "getStatus4ErrorCode()",
85 " returning MP_STATUS_OBJECT_NOT_FOUND"
86 " to caller.");
87 mpStatus = MP_STATUS_OBJECT_NOT_FOUND;
88 break;
91 case MP_DRVR_ACCESS_SYMMETRIC:
92 log(LOG_INFO, "getStatus4ErrorCode()",
93 " received mp_errno=MP_DRVR_ACCESS_SYMMETRIC"
94 " from driver call.");
95 log(LOG_INFO, "getStatus4ErrorCode()",
96 " returning MP_STATUS_INVALID_PARAMETER"
97 " to caller.");
98 mpStatus = MP_STATUS_INVALID_PARAMETER;
99 break;
102 case MP_DRVR_PATH_UNAVAILABLE:
103 log(LOG_INFO, "getStatus4ErrorCode()",
104 " received mp_errno=MP_DRVR_PATH_UNAVAILABLE"
105 " from driver call.");
106 log(LOG_INFO, "getStatus4ErrorCode()",
107 " returning MP_STATUS_PATH_NONOPERATIONAL"
108 " to caller.");
109 mpStatus = MP_STATUS_PATH_NONOPERATIONAL;
110 break;
113 case MP_DRVR_IDS_NOT_ASSOCIATED:
114 log(LOG_INFO, "getStatus4ErrorCode()",
115 " received mp_errno=MP_DRVR_IDS_NOT_ASSOCIATED"
116 " from driver call.");
117 log(LOG_INFO, "getStatus4ErrorCode()",
118 " returning MP_STATUS_INVALID_PARAMETER"
119 " to caller.");
120 mpStatus = MP_STATUS_INVALID_PARAMETER;
121 break;
124 case MP_DRVR_ILLEGAL_ACCESS_STATE_REQUEST:
125 log(LOG_INFO, "getStatus4ErrorCode()",
126 " received mp_errno="
127 "MP_DRVR_ILLEGAL_ACCESS_STATE_REQUEST"
128 " from driver call.");
129 log(LOG_INFO, "getStatus4ErrorCode()",
130 " returning MP_STATUS_INVALID_PARAMETER"
131 " to caller.");
132 mpStatus = MP_STATUS_ACCESS_STATE_INVALID;
133 break;
136 default:
137 log(LOG_INFO, "getStatus4ErrorCode()",
138 " - received (unsupported) mp_errno=%d from"
139 " driver call.", driverError);
140 log(LOG_INFO, "getStatus4ErrorCode()",
141 " - returning MP_STATUS_FAILED to caller.");
142 mpStatus = MP_STATUS_FAILED;
145 log(LOG_INFO, "getStatus4ErrorCode()", "- exit");
147 return (mpStatus);
152 MP_OID_LIST
153 *createOidList(int size) {
155 MP_OID_LIST *pOidList = NULL;
158 log(LOG_INFO, "createOidList()", "- enter");
161 if (size < 1) {
163 log(LOG_INFO, "createOidList()",
164 "requested size is less than 1");
165 log(LOG_INFO, "createOidList()",
166 " - error exit");
167 return (NULL);
169 } else {
171 pOidList = (MP_OID_LIST*)calloc(1,
172 sizeof (MP_OID_LIST) +
173 ((size - 1) *
174 sizeof (MP_OID)));
176 if (NULL == pOidList) {
177 log(LOG_INFO, "createOidList()",
178 "no memory for pOidList");
179 log(LOG_INFO, "createOidList()",
180 " - error exit");
181 return (NULL);
184 log(LOG_INFO,
185 "createOidList()",
186 "- exit(%d)",
187 size);
189 return (pOidList);
193 /* Calls the client callback function, if one is registered */
194 static void
195 notifyClient(sysevent_t *ev)
197 nvlist_t *attr_list = NULL;
199 uint64_t *val = NULL;
200 int32_t *instance = NULL;
201 int32_t *major = NULL;
203 int valAllocated = 0;
205 uint_t nelem = 0;
207 int i = 0;
208 int eventType = 0;
209 int index = -1;
211 void *pCallerData = NULL;
213 char subClassName[256];
215 MP_BOOL becomingVisible = MP_FALSE;
217 MP_OID_LIST *oidList = NULL;
220 log(LOG_INFO, "notifyClient()", "- enter");
223 (void) strncpy(subClassName, sysevent_get_subclass_name(ev), 256);
225 if (strstr(subClassName, "change")) {
227 eventType = PROP_CHANGE;
229 log(LOG_INFO, "notifyClient()", "- got a change event");
230 log(LOG_INFO, "notifyClient()", ": [%s]",
231 subClassName);
233 if (strncmp(subClassName, ESC_SUN_MP_PLUGIN_CHANGE, 255)
234 == 0) {
236 index = MP_OBJECT_TYPE_PLUGIN;
238 } else if (strncmp(subClassName, ESC_SUN_MP_LU_CHANGE, 255)
239 == 0) {
241 index = MP_OBJECT_TYPE_MULTIPATH_LU;
243 } else if (strncmp(subClassName, ESC_SUN_MP_PATH_CHANGE, 255)
244 == 0) {
246 index = MP_OBJECT_TYPE_PATH_LU;
248 } else if (strncmp(subClassName, ESC_SUN_MP_INIT_PORT_CHANGE,
249 255) == 0) {
251 index = MP_OBJECT_TYPE_INITIATOR_PORT;
253 } else if (strncmp(subClassName, ESC_SUN_MP_TPG_CHANGE, 255)
254 == 0) {
256 index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
258 } else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_CHANGE,
259 255) == 0) {
261 index = MP_OBJECT_TYPE_TARGET_PORT;
263 } else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_CHANGE,
264 255) == 0) {
266 index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
269 } else if ((strstr(subClassName, "add")) ||
270 (strstr(subClassName, "initiator_register"))) {
272 eventType = VISA_CHANGE;
273 becomingVisible = MP_TRUE;
275 log(LOG_INFO, "notifyClient()", "- got a visibility"
276 " add event");
277 log(LOG_INFO, "notifyClient()", ": [%s]",
278 subClassName);
280 if (strncmp(subClassName, ESC_SUN_MP_LU_ADD, 255) == 0) {
282 index = MP_OBJECT_TYPE_MULTIPATH_LU;
284 } else if (strncmp(subClassName, ESC_SUN_MP_PATH_ADD, 255)
285 == 0) {
287 index = MP_OBJECT_TYPE_PATH_LU;
289 } else if (strncmp(subClassName, ESC_DDI_INITIATOR_REGISTER,
290 244) == 0) {
292 index = MP_OBJECT_TYPE_INITIATOR_PORT;
294 } else if (strncmp(subClassName, ESC_SUN_MP_TPG_ADD,
295 255) == 0) {
297 index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
299 } else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_ADD,
300 255) == 0) {
302 index = MP_OBJECT_TYPE_TARGET_PORT;
304 } else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_ADD, 255)
305 == 0) {
307 index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
311 } else if ((strstr(subClassName, "remove")) ||
312 (strstr(subClassName, "initiator_unregister"))) {
314 eventType = VISA_CHANGE;
315 becomingVisible = MP_FALSE;
317 log(LOG_INFO, "notifyClient()", "- got a visibility"
318 " remove event");
319 log(LOG_INFO, "notifyClient()", ": [%s]",
320 subClassName);
322 if (strncmp(subClassName, ESC_SUN_MP_LU_REMOVE, 255) == 0) {
324 index = MP_OBJECT_TYPE_MULTIPATH_LU;
326 } else if (strncmp(subClassName, ESC_SUN_MP_PATH_REMOVE, 255)
327 == 0) {
329 index = MP_OBJECT_TYPE_PATH_LU;
331 } else if (strncmp(subClassName, ESC_DDI_INITIATOR_UNREGISTER,
332 255) == 0) {
334 index = MP_OBJECT_TYPE_INITIATOR_PORT;
336 } else if (strncmp(subClassName, ESC_SUN_MP_TPG_REMOVE, 255)
337 == 0) {
339 index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
341 } else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_REMOVE,
342 255) == 0) {
344 index = MP_OBJECT_TYPE_TARGET_PORT;
346 } else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_REMOVE,
347 255) == 0) {
349 index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
353 } else {
354 log(LOG_INFO, "notifyClient()", "- got an unsupported event");
355 return;
358 if (index < 0) {
360 log(LOG_INFO, "notifyClient()", "- index is less than zero");
361 return;
364 if (eventType == VISA_CHANGE) {
366 (void) pthread_mutex_lock(&g_visa_mutex);
368 if (NULL == g_Visibility_Callback_List[index].pClientFn) {
370 log(LOG_INFO, "notifyClient()",
371 "- no visibility change callback to notify");
373 (void) pthread_mutex_unlock(&g_visa_mutex);
375 return;
378 (void) pthread_mutex_unlock(&g_visa_mutex);
381 if (eventType == PROP_CHANGE) {
383 (void) pthread_mutex_lock(&g_prop_mutex);
385 if (NULL == g_Property_Callback_List[index].pClientFn) {
387 log(LOG_INFO, "notifyClient()",
388 "- no property change callback to notify");
390 (void) pthread_mutex_unlock(&g_prop_mutex);
392 return;
395 (void) pthread_mutex_unlock(&g_prop_mutex);
398 (void) sysevent_get_attr_list(ev, &attr_list);
399 if (NULL != attr_list) {
401 if ((VISA_CHANGE == eventType) &&
402 (MP_OBJECT_TYPE_PLUGIN == index)) {
404 val = (uint64_t *)malloc(sizeof (uint64_t));
405 valAllocated = 1;
408 * We have no well-defined way to determine our OSN.
409 * Currently the common library uses 0 as OSN for every
410 * plugin, so just use 0. If the OSN assigned by the
411 * common library changed, this code would have to be
412 * updated.
414 *val = 0;
415 nelem = 1;
417 } else if ((VISA_CHANGE == eventType) &&
418 (MP_OBJECT_TYPE_INITIATOR_PORT == index)) {
420 (void) nvlist_lookup_int32_array(attr_list,
421 DDI_INSTANCE, &instance, &nelem);
423 log(LOG_INFO, "notifyClient()",
424 "- event (PHCI_INSTANCE) has [%d] elements",
425 nelem);
427 (void) nvlist_lookup_int32_array(attr_list,
428 DDI_DRIVER_MAJOR, &major, &nelem);
430 log(LOG_INFO, "notifyClient()",
431 "- event (PHCI_DRIVER_MAJOR) has [%d] elements",
432 nelem);
434 if ((NULL != instance) & (NULL != major)) {
436 val = (uint64_t *)malloc(sizeof (uint64_t));
438 valAllocated = 1;
440 *val = 0;
441 *val = MP_STORE_INST_TO_ID(*instance, *val);
442 *val = MP_STORE_MAJOR_TO_ID(*major, *val);
444 nelem = 1;
446 } else {
448 nelem = 0;
451 } else {
453 (void) nvlist_lookup_uint64_array(attr_list, OIDLIST,
454 &val, &nelem);
456 log(LOG_INFO, "notifyClient()",
457 "- event has [%d] elements",
458 nelem);
461 if (nelem > 0) {
463 for (i = 0; i < nelem; i++) {
465 log(LOG_INFO, "notifyClient()",
466 "- event [%d] = %llx",
467 i, val[i]);
470 oidList = createOidList(nelem);
471 if (NULL == oidList) {
473 log(LOG_INFO, "notifyClient()",
474 "- unable to create MP_OID_LIST");
476 log(LOG_INFO, "notifyClient()",
477 "- error exit");
479 nvlist_free(attr_list);
481 return;
484 oidList->oidCount = nelem;
486 for (i = 0; i < nelem; i++) {
488 oidList->oids[i].objectType = index;
489 oidList->oids[i].ownerId = g_pluginOwnerID;
490 oidList->oids[i].objectSequenceNumber = val[i];
493 if (valAllocated) {
495 free(val);
498 for (i = 0; i < oidList->oidCount; i++) {
500 log(LOG_INFO, "notifyClient()",
501 "oidList->oids[%d].objectType"
502 " = %d",
503 i, oidList->oids[i].objectType);
504 log(LOG_INFO, "notifyClient()",
505 "oidList->oids[%d].ownerId"
506 " = %d",
507 i, oidList->oids[i].ownerId);
508 log(LOG_INFO, "notifyClient()",
509 "oidList->oids[%d].objectSequenceNumber"
510 " = %llx",
511 i, oidList->oids[i].objectSequenceNumber);
514 if (eventType == PROP_CHANGE) {
516 (void) pthread_mutex_lock(&g_prop_mutex);
518 pCallerData = g_Property_Callback_List[index].
519 pCallerData;
521 (g_Property_Callback_List[index].pClientFn)
522 (oidList, pCallerData);
524 (void) pthread_mutex_unlock(&g_prop_mutex);
526 } else if (eventType == VISA_CHANGE) {
528 (void) pthread_mutex_lock(&g_visa_mutex);
530 pCallerData = g_Visibility_Callback_List[index].
531 pCallerData;
533 (g_Visibility_Callback_List[index].pClientFn)
534 (becomingVisible, oidList, pCallerData);
536 (void) pthread_mutex_unlock(&g_visa_mutex);
541 nvlist_free(attr_list);
545 log(LOG_INFO, "notifyClient()", "- exit");
548 /* Event handler called by system */
549 static void
550 sysevent_handler(sysevent_t *ev)
552 log(LOG_INFO, "sysevent_handler()", "- enter");
554 /* Is the event one of ours? */
555 if ((strncmp(EC_SUN_MP, sysevent_get_class_name(ev), 9) != 0) &&
556 (strncmp(EC_DDI, sysevent_get_class_name(ev), 6) != 0)) {
558 return;
561 /* Notify client if it cares */
562 notifyClient(ev);
565 log(LOG_INFO, "sysevent_handler()", "- exit");
568 /* Registers the plugin to the sysevent framework */
569 MP_STATUS
570 init_sysevents(void) {
572 const char *subclass_list[] = {
574 ESC_SUN_MP_PLUGIN_CHANGE,
576 ESC_SUN_MP_LU_CHANGE,
577 ESC_SUN_MP_LU_ADD,
578 ESC_SUN_MP_LU_REMOVE,
580 ESC_SUN_MP_PATH_CHANGE,
581 ESC_SUN_MP_PATH_ADD,
582 ESC_SUN_MP_PATH_REMOVE,
584 ESC_SUN_MP_INIT_PORT_CHANGE,
586 ESC_SUN_MP_TPG_CHANGE,
587 ESC_SUN_MP_TPG_ADD,
588 ESC_SUN_MP_TPG_REMOVE,
590 ESC_SUN_MP_TARGET_PORT_CHANGE,
591 ESC_SUN_MP_TARGET_PORT_ADD,
592 ESC_SUN_MP_TARGET_PORT_REMOVE,
594 ESC_SUN_MP_DEV_PROD_CHANGE,
595 ESC_SUN_MP_DEV_PROD_ADD,
596 ESC_SUN_MP_DEV_PROD_REMOVE
600 const char *init_port_subclass_list[] = {
602 ESC_DDI_INITIATOR_REGISTER,
603 ESC_DDI_INITIATOR_UNREGISTER
608 log(LOG_INFO, "init_sysevents()", "- enter");
611 g_SysEventHandle = sysevent_bind_handle(sysevent_handler);
612 if (g_SysEventHandle == NULL) {
614 log(LOG_INFO, "init_sysevents()",
615 "- sysevent_bind_handle() failed");
617 log(LOG_INFO, "init_sysevents()", "- error exit");
619 return (MP_STATUS_FAILED);
622 if (sysevent_subscribe_event(g_SysEventHandle, EC_SUN_MP,
623 subclass_list, sizeof (subclass_list) / sizeof (subclass_list[0]))
624 != 0) {
627 log(LOG_INFO, "init_sysevents()",
628 "- sysevent_subscribe_event() failed for subclass_list");
630 log(LOG_INFO, "init_sysevents()", "- error exit");
632 sysevent_unbind_handle(g_SysEventHandle);
634 return (MP_STATUS_FAILED);
637 if (sysevent_subscribe_event(g_SysEventHandle, EC_DDI,
638 init_port_subclass_list, sizeof (init_port_subclass_list) /
639 sizeof (init_port_subclass_list[0])) != 0) {
642 log(LOG_INFO, "init_sysevents()",
643 "- sysevent_subscribe_event() failed "
644 "for init_port_subclass_list");
646 log(LOG_INFO, "init_sysevents()", "- error exit");
648 sysevent_unbind_handle(g_SysEventHandle);
650 return (MP_STATUS_FAILED);
654 log(LOG_INFO, "init_sysevents()", "- exit");
656 return (MP_STATUS_SUCCESS);