1 /*************************************************************************
2  * Description
3  *	HBAAPILIB-sun.c - Implements the Sun Extention for Target mode
4  *		FCHBA discovery
5  *
6  * License:
7  *	The contents of this file are subject to the SNIA Public License
8  *	Version 1.0 (the "License"); you may not use this file except in
9  *	compliance with the License. You may obtain a copy of the License at
10  *
11  *	/http://www.snia.org/English/Resources/Code/OpenSource.html
12  *
13  *	Software distributed under the License is distributed on an "AS IS"
14  *	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
15  *	the License for the specific language governing rights and limitations
16  *	under the License.
17  *
18  *************************************************************************
19  */
20 
21 #ifdef WIN32
22 #include <windows.h>
23 #include <string.h>
24 /*
25  * Next define forces entry points in the dll to be exported
26  * See hbaapi.h to see what it does.
27  */
28 #define HBAAPI_EXPORTS
29 #else
30 #include <dlfcn.h>
31 #include <strings.h>
32 #endif
33 #include <stdio.h>
34 #include <time.h>
35 #include <dlfcn.h>
36 #include "hbaapi.h"
37 #include "hbaapi-sun.h"
38 #include "vendorhbaapi.h"
39 #include <stdlib.h>
40 #ifdef USESYSLOG
41 #include <syslog.h>
42 #endif
43 
44 
45 /*
46  * LIBRARY_NUM is a shortcut to figure out which library we need to call.
47  *  The top 16 bits of handle are the library index
48  */
49 #define LIBRARY_NUM(handle)	((handle)>>16)
50 
51 /*
52  * VENDOR_HANDLE turns a global library handle into a vendor specific handle,
53  * with all upper 16 bits set to 0
54  */
55 #define VENDOR_HANDLE(handle)	((handle)&0xFFFF)
56 
57 #define HBA_HANDLE_FROM_LOCAL(library, vendor) \
58 				(((library)<<16) | ((vendor)&0x0000FFFF))
59 
60 extern int _hbaapi_debuglevel;
61 #define DEBUG(L, STR, A1, A2, A3)
62 
63 #if defined(USESYSLOG) && defined(USELOGFILE)
64 extern FILE *_hbaapi_debug_fd;
65 extern int _hbaapi_sysloginit;
66 #undef DEBUG
67 #ifdef WIN32
68 #define DEBUG(L, STR, A1, A2, A3)\
69     if ((L) <= _hbaapi_debuglevel) {\
70 	if(_hbaapi_sysloginit == 0) {\
71 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
72 	    _hbaapi_sysloginit = 1;\
73 	}\
74 	syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
75 	if(_hbaapi_debug_fd == NULL) {\
76 	    char _logFile[MAX_PATH]; \
77 	    GetTempPath(MAX_PATH, _logFile); \
78 	    strcat(_logFile, "HBAAPI.log"); \
79 	    _hbaapi_debug_fd = fopen(_logFile, "a");\
80 	}\
81         if(_hbaapi_debug_fd != NULL) {\
82 	    fprintf(_hbaapi_debug_fd, (STR ## "\n"), (A1), (A2), (A3));\
83 	}\
84     }
85 #else /* WIN32*/
86 #define DEBUG(L, STR, A1, A2, A3)\
87     if ((L) <= _hbaapi_debuglevel) {\
88 	if(_hbaapi_sysloginit == 0) {\
89 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
90 	    _hbaapi_sysloginit = 1;\
91 	}\
92 	syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
93 	if(_hbaapi_debug_fd == NULL) {\
94 	    _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
95 	}\
96         if(_hbaapi_debug_fd != NULL) {\
97 	    fprintf(_hbaapi_debug_fd, (STR ## "\n"), (A1), (A2), (A3));\
98 	}\
99     }
100 #endif /* WIN32*/
101 
102 #else /* Not both USESYSLOG and USELOGFILE */
103 #if defined(USESYSLOG)
104 int _hbaapi_sysloginit = 0;
105 #undef DEBUG
106 #define DEBUG(L, STR, A1, A2, A3) \
107     if ((L) <= _hbaapi_debuglevel) {\
108 	if(_hbaapi_sysloginit == 0) {\
109 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
110 	    _hbaapi_sysloginit = 1;\
111 	}\
112 	syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
113     }
114 #endif /* USESYSLOG */
115 #if defined(USELOGFILE)
116 FILE *_hbaapi_debug_fd = NULL;
117 #undef DEBUG
118 #ifdef WIN32
119 #define DEBUG(L, STR, A1, A2, A3) \
120     if((L) <= _hbaapi_debuglevel) {\
121 	if(_hbaapi_debug_fd == NULL) {\
122 	    char _logFile[MAX_PATH]; \
123 	    GetTempPath(MAX_PATH, _logFile); \
124 	    strcat(_logFile, "HBAAPI.log"); \
125 	    _hbaapi_debug_fd = fopen(_logFile, "a");\
126         }\
127     }
128 #else /* WIN32 */
129 #define DEBUG(L, STR, A1, A2, A3) \
130     if((L) <= _hbaapi_debuglevel) {\
131 	if(_hbaapi_debug_fd == NULL) {\
132 	    _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
133 	}\
134 	if(_hbaapi_debug_fd != NULL) { \
135 	    fprintf(_hbaapi_debug_fd, (STR) ## "\n", (A1), (A2), (A3));\
136 	}\
137     }
138 #endif /* WIN32 */
139 #endif /* USELOGFILE */
140 #endif /* Not both USELOGFILE and USESYSLOG */
141 
142 #ifdef POSIX_THREADS
143 #include <pthread.h>
144 /*
145  * When multiple mutex's are grabed, they must be always be grabbed in
146  * the same order, or deadlock can result.  There are three levels
147  * of mutex's involved in this API.  If LL_mutex is grabbed, always grap
148  * it first.  If AL_mutex is grabbed, it may not be grabbed before
149  * LL_mutex.  If grabbed in a multi grab sequence, the mutex's protecting
150  * the callback lists must always be grabbed last and release before calling
151  * a vendor specific library function that might invoke a callback function
152  * on the same thread.
153  */
154 #define GRAB_MUTEX(M)			grab_mutex(M)
155 #define RELEASE_MUTEX(M)		release_mutex(M)
156 #define RELEASE_MUTEX_RETURN(M,RET)	release_mutex(M); return(RET)
157 #elif defined (WIN32)
158 #define GRAB_MUTEX(m)			EnterCriticalSection(m)
159 #define RELEASE_MUTEX(m)		LeaveCriticalSection(m)
160 #define RELEASE_MUTEX_RETURN(m, RET)	LeaveCriticalSection(m); return(RET)
161 #else
162 #define GRAB_MUTEX(M)
163 #define RELEASE_MUTEX(M)
164 #define RELEASE_MUTEX_RETURN(M,RET)	return(RET)
165 #endif
166 
167 /*
168  * HBA_LIBRARY_STATUS and HBA_LIBRARY_INFO are redefined here.
169  * Avoid any change in the common code.
170  */
171 typedef enum {
172     HBA_LIBRARY_UNKNOWN,
173     HBA_LIBRARY_LOADED,
174     HBA_LIBRARY_NOT_LOADED
175 } HBA_LIBRARY_STATUS;
176 
177 typedef struct hba_library_info {
178     struct hba_library_info
179 			*next;
180 #ifdef WIN32
181     HINSTANCE		hLibrary;		/* Handle to a loaded DLL */
182 #else
183     char		*LibraryName;
184     void*		hLibrary;		/* Handle to a loaded DLL */
185 #endif
186     char		*LibraryPath;
187     HBA_ENTRYPOINTSV2	functionTable;		/* Function pointers */
188     HBA_LIBRARY_STATUS	status;			/* info on this library */
189     HBA_UINT32		index;
190 } HBA_LIBRARY_INFO, *PHBA_LIBRARY_INFO;
191 
192 #define ARE_WE_INITED() \
193 	if (_hbaapi_librarylist == NULL) { \
194 		return(HBA_STATUS_ERROR); \
195 	}
196 
197 extern HBA_LIBRARY_INFO *_hbaapi_librarylist;
198 extern HBA_UINT32 _hbaapi_total_library_count;
199 #ifdef POSIX_THREADS
200 extern pthread_mutex_t _hbaapi_LL_mutex;
201 #elif defined(WIN32)
202 extern CRITICAL_SECTION _hbaapi_LL_mutex;
203 #endif
204 
205 /*
206  * Function type def fop Sun extentions.
207  */
208 typedef HBA_UINT32	(* Sun_HBAGetNumberOfTgtAdaptersFunc)();
209 typedef HBA_STATUS	(* Sun_HBAGetTgtAdapterNameFunc)(HBA_UINT32, char *);
210 typedef HBA_HANDLE	(* Sun_HBAOpenTgtAdapterFunc)(char *);
211 typedef HBA_STATUS	(* Sun_HBAOpenTgtAdapterByWWNFunc)
212 			    (HBA_HANDLE *, HBA_WWN);
213 typedef	HBA_STATUS	(* Sun_HBANPIVGetAdapterAttributesFunc)
214 			    (HBA_HANDLE, HBA_ADAPTERATTRIBUTES *);
215 typedef	HBA_STATUS	(* Sun_HBAGetNPIVPortInfoFunc)
216 			    (HBA_HANDLE, HBA_UINT32, HBA_UINT32, HBA_NPIVATTRIBUTES *);
217 typedef HBA_STATUS	(* Sun_HBADeleteNPIVPortFunc)
218 			    (HBA_HANDLE, HBA_UINT32, HBA_WWN);
219 typedef HBA_STATUS	(* Sun_HBACreateNPIVPortFunc)
220 			    (HBA_HANDLE, HBA_UINT32, HBA_WWN, HBA_WWN, HBA_UINT32 *);
221 typedef	HBA_STATUS	(* Sun_HBAAdapterReturnWWNFunc)
222 			    (HBA_HANDLE, HBA_UINT32, HBA_WWN *, HBA_WWN *);
223 typedef	HBA_STATUS	(* Sun_HBAAdapterCreateWWNFunc)
224 			    (HBA_HANDLE, HBA_UINT32, HBA_WWN *, HBA_WWN *, HBA_WWN *,
225 			    HBA_INT32);
226 typedef	HBA_STATUS	(* Sun_HBAGetPortNPIVAttributesFunc)
227 			    (HBA_HANDLE, HBA_UINT32, HBA_PORTNPIVATTRIBUTES *);
228 typedef	HBA_STATUS	(* Sun_HBARegisterForAdapterDeviceEventsFunc)
229 			    (void (*)(void *, HBA_WWN, HBA_UINT32, HBA_UINT32),
230 			    void *, HBA_HANDLE, HBA_WWN, HBA_CALLBACKHANDLE *);
231 
232 /*
233  * Individual adapter (hba) information
234  * Same as hbaadapter with different structure name.
235  */
236 typedef struct hba_tgtadapter_info {
237     struct hba_tgtadapter_info
238 			*next;
239     HBA_STATUS		GNstatus; /* status from GetTgtAdapterNameFunc */
240     char		*name;
241     HBA_WWN		nodeWWN;
242     HBA_LIBRARY_INFO	*library;
243     HBA_UINT32		index;
244 } HBA_TGTADAPTER_INFO;
245 
246 /*
247  * Make the list as an array with max size 16
248  */
249 HBA_TGTADAPTER_INFO *_hbaapi_tgtadapterlist;
250 HBA_UINT32 _hbaapi_total_tgtadapter_count = 0;
251 #ifdef POSIX_THREADS
252 pthread_mutex_t _hbaapi_tgtAL_mutex = PTHREAD_MUTEX_INITIALIZER;
253 #elif defined(WIN32)
254 CRITICAL_SECTION _hbaapi_tgtAL_mutex;
255 #endif
256 
257 /*
258  * Common library internal. Mutex handling
259  */
260 #ifdef POSIX_THREADS
261 static void
262 grab_mutex(pthread_mutex_t *mp) {
263     int ret;
264     if((ret = pthread_mutex_lock(mp)) != 0) {
265 	perror("pthread_mutex_lock - HBAAPI:");
266 	DEBUG(0, "pthread_mutex_lock returned %d", ret, 0, 0);
267     }
268 }
269 
270 static void
271 release_mutex(pthread_mutex_t *mp) {
272     int ret;
273     if((ret = pthread_mutex_unlock(mp)) != 0) {
274 	perror("pthread_mutex_unlock - HBAAPI:");
275 	DEBUG(0, "pthread_mutex_unlock returned %d", ret, 0, 0);
276     }
277 }
278 #endif
279 
280 /*
281  * The API used to use fixed size tables as its primary data structure.
282  * Indexing from 1 to N identified each adapters.  Now the adapters are
283  * on a linked list.  There is a unique "index" foreach each adapter.
284  * Adapters always keep their index, even if they are removed from the
285  * hardware.  The only time the indexing is reset is on HBA_FreeLibrary
286  */
287 HBA_UINT32
288 Sun_HBA_GetNumberOfTgtAdapters()
289 {
290     int j=0;
291     HBA_LIBRARY_INFO	*lib_infop;
292     Sun_HBAGetNumberOfTgtAdaptersFunc
293 			GetNumberOfTgtAdaptersFunc = NULL;
294     Sun_HBAGetTgtAdapterNameFunc
295 			GetTgtAdapterNameFunc = NULL;
296     HBA_BOOLEAN		found_name;
297     HBA_TGTADAPTER_INFO	*adapt_infop;
298     HBA_STATUS		status;
299 
300     char adaptername[256];
301     int num_adapters; /* local */
302 
303     if(_hbaapi_librarylist == NULL) {
304 	return (0);
305     }
306     GRAB_MUTEX(&_hbaapi_LL_mutex); /* pay attention to order */
307     GRAB_MUTEX(&_hbaapi_tgtAL_mutex);
308 
309     for (lib_infop = _hbaapi_librarylist;
310 	 lib_infop != NULL;
311 	 lib_infop = lib_infop->next) {
312 
313 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
314 	    continue;
315 	}
316 
317 	if (lib_infop->hLibrary != NULL) {
318             GetNumberOfTgtAdaptersFunc = (Sun_HBAGetNumberOfTgtAdaptersFunc)
319 		dlsym(lib_infop->hLibrary, "Sun_fcGetNumberOfTgtAdapters");
320             GetTgtAdapterNameFunc = (Sun_HBAGetTgtAdapterNameFunc)
321 		dlsym(lib_infop->hLibrary, "Sun_fcGetTgtAdapterName");
322 	    if (GetNumberOfTgtAdaptersFunc == NULL ||
323 		GetTgtAdapterNameFunc == NULL)	{
324 		GetNumberOfTgtAdaptersFunc = GetTgtAdapterNameFunc = NULL;
325                 continue;
326             }
327 	} else {
328 	    continue;
329 	}
330 
331 	num_adapters = ((GetNumberOfTgtAdaptersFunc)());
332 #ifndef WIN32
333 	DEBUG(1, "HBAAPI: number of target mode adapters for %s = %d\n",
334 	      lib_infop->LibraryName, num_adapters, 0);
335 #else
336 	DEBUG(1, "HBAAPI: number of target mode_adapters for %s = %d\n",
337 	      lib_infop->LibraryPath, num_adapters, 0);
338 #endif
339 
340 	for (j = 0; j < num_adapters; j++) {
341 	    found_name = 0;
342 	    status = (GetTgtAdapterNameFunc)(j, (char *)&adaptername);
343 	    if(status == HBA_STATUS_OK) {
344 		for(adapt_infop = _hbaapi_tgtadapterlist;
345 		    adapt_infop != NULL;
346 		    adapt_infop = adapt_infop->next) {
347 		    /*
348 		     * check for duplicates, really, this may just be a second
349 		     * call to this function
350 		     * ??? how do we know when a name becomes stale?
351 		     */
352 		    if(strcmp(adaptername, adapt_infop->name) == 0) {
353 			/* already got this one */
354 			found_name++;
355 			break;
356 		    }
357 		}
358 		if(found_name != 0) {
359 		    continue;
360 		}
361 	    }
362 
363 	    adapt_infop = (HBA_TGTADAPTER_INFO *)
364 		calloc(1, sizeof(HBA_TGTADAPTER_INFO));
365 	    if(adapt_infop == NULL) {
366 #ifndef WIN32
367 		fprintf(stderr,
368 			"HBA_GetNumberOfAdapters: calloc failed on sizeof:%d\n",
369 			sizeof(HBA_TGTADAPTER_INFO));
370 #endif
371 		RELEASE_MUTEX(&_hbaapi_tgtAL_mutex);
372 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
373 				     _hbaapi_total_tgtadapter_count);
374 	    }
375 	    if((adapt_infop->GNstatus = status) == HBA_STATUS_OK) {
376 		adapt_infop->name = strdup(adaptername);
377 	    } else {
378 		char dummyname[512];
379 		sprintf(dummyname, "NULLADAPTER-%s-%03d",
380 			lib_infop->LibraryPath, _hbaapi_total_tgtadapter_count);
381 		dummyname[255] = '\0';
382 		adapt_infop->name = strdup(dummyname);
383 	    }
384 	    adapt_infop->library = lib_infop;
385 	    adapt_infop->next = _hbaapi_tgtadapterlist;
386 	    adapt_infop->index = _hbaapi_total_tgtadapter_count;
387 	    _hbaapi_tgtadapterlist = adapt_infop;
388 	    _hbaapi_total_tgtadapter_count++;
389 	}
390 	GetNumberOfTgtAdaptersFunc = GetTgtAdapterNameFunc = NULL;
391     }
392     RELEASE_MUTEX(&_hbaapi_tgtAL_mutex);
393     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, _hbaapi_total_tgtadapter_count);
394 }
395 
396 HBA_STATUS
397 Sun_HBA_GetTgtAdapterName(
398     HBA_UINT32 adapterindex,
399     char *adaptername)
400 {
401     HBA_TGTADAPTER_INFO	*adapt_infop;
402     HBA_STATUS		ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
403 
404     if (adaptername == NULL) {
405 	    return(HBA_STATUS_ERROR_ARG);
406     }
407     /*
408      * The adapter index is from old code, but we have
409      * to support it.  Go down the list looking for
410      * the adapter
411      */
412     ARE_WE_INITED();
413     GRAB_MUTEX(&_hbaapi_tgtAL_mutex);
414     *adaptername = '\0';
415     for(adapt_infop = _hbaapi_tgtadapterlist;
416 	adapt_infop != NULL;
417 	adapt_infop = adapt_infop->next) {
418 
419 	if(adapt_infop->index == adapterindex) {
420 	    if(adapt_infop->name != NULL &&
421 	       adapt_infop->GNstatus == HBA_STATUS_OK) {
422 		strcpy(adaptername, adapt_infop->name);
423 	    } else {
424 		*adaptername = '\0';
425 	    }
426 	    ret = adapt_infop->GNstatus;
427 	    break;
428 	}
429     }
430     DEBUG(2, "GetAdapterName for index:%d ->%s", adapterindex, adaptername, 0);
431     RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, ret);
432 }
433 
434 HBA_HANDLE
435 Sun_HBA_OpenTgtAdapter(char* adaptername)
436 {
437     HBA_HANDLE		handle;
438     Sun_HBAOpenTgtAdapterFunc	OpenTgtAdapterFunc;
439     HBA_TGTADAPTER_INFO	*adapt_infop;
440     HBA_LIBRARY_INFO	*lib_infop;
441 
442     DEBUG(2, "OpenAdapter: %s", adaptername, 0, 0);
443 
444     if(_hbaapi_librarylist == NULL) {
445 	return(HBA_HANDLE_INVALID);
446     }
447     if (adaptername == NULL) {
448 	return(HBA_STATUS_ERROR_ARG);
449     }
450     handle = HBA_HANDLE_INVALID;
451     GRAB_MUTEX(&_hbaapi_AL_mutex);
452     for(adapt_infop = _hbaapi_tgtadapterlist;
453 	adapt_infop != NULL;
454 	adapt_infop = adapt_infop->next) {
455 	if (strcmp(adaptername, adapt_infop->name) != 0) {
456 	    continue;
457 	}
458 	lib_infop = adapt_infop->library;
459         OpenTgtAdapterFunc = (Sun_HBAOpenTgtAdapterFunc)
460 		dlsym(lib_infop->hLibrary, "Sun_fcOpenTgtAdapter");
461 	if (OpenTgtAdapterFunc != NULL) {
462 	    /* retrieve the vendor handle */
463 	    handle = (OpenTgtAdapterFunc)(adaptername);
464 	    if(handle != 0) {
465 		/* or this with the library index to get the common handle */
466 		handle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
467 	    }
468 	}
469 	break;
470     }
471     RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, handle);
472 }
473 
474 /*
475  * This function ignores the list of known adapters and instead tries
476  * each vendors open function to see if one of them
477  * can open an adapter when referenced with a particular WWN
478  */
479 HBA_STATUS
480 Sun_HBA_OpenTgtAdapterByWWN(HBA_HANDLE *phandle, HBA_WWN nodeWWN)
481 {
482     HBA_HANDLE		handle;
483     HBA_LIBRARY_INFO	*lib_infop;
484     Sun_HBAGetNumberOfTgtAdaptersFunc
485 			GetNumberOfTgtAdaptersFunc;
486     Sun_HBAOpenTgtAdapterByWWNFunc
487 			OpenTgtAdapterByWWNFunc;
488     HBA_STATUS		status;
489 
490     DEBUG(2, "OpenAdapterByWWN: %s", WWN2STR1(&nodeWWN), 0, 0);
491 
492     if (phandle == NULL) {
493 	    return(HBA_STATUS_ERROR_ARG);
494     }
495 
496     ARE_WE_INITED();
497 
498     *phandle = HBA_HANDLE_INVALID;
499 
500     GRAB_MUTEX(&_hbaapi_LL_mutex);
501     for (lib_infop = _hbaapi_librarylist;
502 	 lib_infop != NULL;
503 	 lib_infop = lib_infop->next) {
504 
505 	status = HBA_STATUS_ERROR_ILLEGAL_WWN;
506 
507 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
508 	    continue;
509 	}
510 
511         GetNumberOfTgtAdaptersFunc = (Sun_HBAGetNumberOfTgtAdaptersFunc)
512 		dlsym(lib_infop->hLibrary, "Sun_fcGetNumberOfTgtAdapters");
513         OpenTgtAdapterByWWNFunc = (Sun_HBAOpenTgtAdapterByWWNFunc)
514 		dlsym(lib_infop->hLibrary, "Sun_fcOpenTgtAdapterByWWN");
515 	if (GetNumberOfTgtAdaptersFunc == NULL ||
516 		OpenTgtAdapterByWWNFunc == NULL) {
517 		GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
518                 continue;
519         }
520 
521 	(void) ((GetNumberOfTgtAdaptersFunc)());
522 
523 	if((status = (OpenTgtAdapterByWWNFunc)(&handle, nodeWWN))
524 	    != HBA_STATUS_OK) {
525 	    GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
526 	    continue;
527 	}
528 	/* OK, make a vendor non-specific handle */
529 	*phandle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
530 	status = HBA_STATUS_OK;
531 	break;
532 
533 	GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
534     }
535     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
536 }
537 
538 static HBA_STATUS
539 HBA_NPIV_CheckLibrary(HBA_HANDLE handle,
540 			HBA_LIBRARY_INFO **lib_infopp,
541 			HBA_HANDLE *vendorhandle) {
542 	HBA_UINT32		libraryIndex;
543 	HBA_LIBRARY_INFO	*lib_infop;
544 
545 	if (vendorhandle == NULL) {
546 		return(HBA_STATUS_ERROR_ARG);
547 	}
548 	if(_hbaapi_librarylist == NULL) {
549 		return(HBA_STATUS_ERROR);
550 	}
551 	libraryIndex = LIBRARY_NUM(handle);
552 
553 	GRAB_MUTEX(&_hbaapi_LL_mutex);
554 	for(lib_infop = _hbaapi_librarylist;
555 	    lib_infop != NULL;
556 	    lib_infop = lib_infop->next) {
557 		if(lib_infop->index == libraryIndex) {
558 			if(lib_infop->status != HBA_LIBRARY_LOADED) {
559 				return HBA_STATUS_ERROR;
560 			}
561 			*lib_infopp = lib_infop;
562 			*vendorhandle = VENDOR_HANDLE(handle);
563 			/* caller will release the mutex */
564 			return HBA_STATUS_OK;
565 		}
566 	}
567 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INVALID_HANDLE);
568 }
569 #define	NPIVCHECKLIBRARY() \
570 	status = HBA_NPIV_CheckLibrary(handle, &lib_infop, &vendorHandle); \
571 	if(status != HBA_STATUS_OK) { \
572 		return(status); \
573 	}
574 
575 HBA_STATUS
576 Sun_HBA_NPIVGetAdapterAttributes (
577     HBA_HANDLE		handle,
578     HBA_ADAPTERATTRIBUTES
579 			*hbaattributes)
580 {
581 	HBA_STATUS		status;
582 	HBA_LIBRARY_INFO	*lib_infop;
583 	HBA_HANDLE		vendorHandle;
584 	Sun_HBANPIVGetAdapterAttributesFunc	NPIVGetAdapterAttributesFunc;
585 
586 	DEBUG(2, "HBA_NPIVGetAdapterAttributes", 0, 0, 0);
587 
588 	NPIVCHECKLIBRARY();
589 	NPIVGetAdapterAttributesFunc = (Sun_HBANPIVGetAdapterAttributesFunc)
590 	    dlsym(lib_infop->hLibrary, "Sun_fcNPIVGetAdapterAttributes");
591 	if (NPIVGetAdapterAttributesFunc != NULL) {
592 		status = ((NPIVGetAdapterAttributesFunc)(vendorHandle,
593 			hbaattributes));
594 	} else {
595 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
596 	}
597 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
598 }
599 
600 HBA_STATUS
601 Sun_HBA_GetNPIVPortInfo (
602     HBA_HANDLE		handle,
603     HBA_UINT32		portindex,
604     HBA_UINT32		vportindex,
605     HBA_NPIVATTRIBUTES	*attributes)
606 {
607 	HBA_STATUS		status;
608 	HBA_LIBRARY_INFO	*lib_infop;
609 	HBA_HANDLE		vendorHandle;
610 	Sun_HBAGetNPIVPortInfoFunc	GetNPIVPortInfoFunc;
611 
612 	NPIVCHECKLIBRARY();
613 	GetNPIVPortInfoFunc = (Sun_HBAGetNPIVPortInfoFunc)
614 		dlsym(lib_infop->hLibrary, "Sun_fcGetNPIVPortInfo");
615 	if (GetNPIVPortInfoFunc != NULL) {
616 		status = ((GetNPIVPortInfoFunc)(vendorHandle, portindex,
617 			vportindex, attributes));
618 	} else {
619 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
620 	}
621 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
622 }
623 
624 HBA_STATUS
625 Sun_HBA_DeleteNPIVPort (
626     HBA_HANDLE		handle,
627     HBA_UINT32		portindex,
628     HBA_WWN		vportWWN)
629 {
630 	HBA_STATUS		status;
631 	HBA_LIBRARY_INFO	*lib_infop;
632 	HBA_HANDLE		vendorHandle;
633 	Sun_HBADeleteNPIVPortFunc	DeleteNPIVPortFunc;
634 
635 	NPIVCHECKLIBRARY();
636 	DeleteNPIVPortFunc = (Sun_HBADeleteNPIVPortFunc)
637 		dlsym(lib_infop->hLibrary, "Sun_fcDeleteNPIVPort");
638 	if (DeleteNPIVPortFunc != NULL) {
639 		status = ((DeleteNPIVPortFunc)(vendorHandle,
640 		    portindex, vportWWN));
641 	} else {
642 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
643 	}
644 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
645 }
646 
647 HBA_STATUS
648 Sun_HBA_CreateNPIVPort (
649     HBA_HANDLE		handle,
650     HBA_UINT32		portindex,
651     HBA_WWN		vnodeWWN,
652     HBA_WWN		vportWWN,
653     HBA_UINT32		*vportindex)
654 {
655 	HBA_STATUS		status;
656 	HBA_LIBRARY_INFO	*lib_infop;
657 	HBA_HANDLE		vendorHandle;
658 	Sun_HBACreateNPIVPortFunc	CreateNPIVPortFunc;
659 
660 	NPIVCHECKLIBRARY();
661 	CreateNPIVPortFunc = (Sun_HBACreateNPIVPortFunc)
662 		dlsym(lib_infop->hLibrary, "Sun_fcCreateNPIVPort");
663 	if (CreateNPIVPortFunc != NULL) {
664 		status = ((CreateNPIVPortFunc)(vendorHandle,
665 		    portindex, vnodeWWN, vportWWN, vportindex));
666 	} else {
667 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
668 	}
669 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
670 }
671 
672 HBA_STATUS
673 Sun_HBA_GetPortNPIVAttributes (
674     HBA_HANDLE		handle,
675     HBA_UINT32		portindex,
676     HBA_PORTNPIVATTRIBUTES	*portnpivattributes)
677 {
678 	HBA_STATUS		status;
679 	HBA_LIBRARY_INFO	*lib_infop;
680 	HBA_HANDLE		vendorHandle;
681 	Sun_HBAGetPortNPIVAttributesFunc	GetPortNPIVAttributesFunc;
682 
683 	NPIVCHECKLIBRARY();
684 	GetPortNPIVAttributesFunc = (Sun_HBAGetPortNPIVAttributesFunc)
685 		dlsym(lib_infop->hLibrary, "Sun_fcGetPortNPIVAttributes");
686 	if (GetPortNPIVAttributesFunc != NULL) {
687 		status = ((GetPortNPIVAttributesFunc)(
688 		    vendorHandle, portindex, portnpivattributes));
689 	} else {
690 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
691 	}
692 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
693 }
694 
695 HBA_STATUS
696 Sun_HBA_AdapterCreateWWN (
697     HBA_HANDLE		handle,
698     HBA_UINT32		portindex,
699     HBA_WWN		*nwwn,
700     HBA_WWN		*pwwn,
701     HBA_WWN		*OUI,
702     HBA_INT32		method)
703 {
704 	HBA_STATUS		status;
705 	HBA_LIBRARY_INFO	*lib_infop;
706 	HBA_HANDLE		vendorHandle;
707 	Sun_HBAAdapterCreateWWNFunc	AdapterCreateWWNFunc;
708 
709 	NPIVCHECKLIBRARY();
710 	AdapterCreateWWNFunc = (Sun_HBAAdapterCreateWWNFunc)
711 		dlsym(lib_infop->hLibrary, "Sun_fcAdapterCreateWWN");
712 	if (AdapterCreateWWNFunc != NULL) {
713 		status = ((AdapterCreateWWNFunc)(vendorHandle,
714 		    portindex, nwwn, pwwn, OUI, method));
715 	} else {
716 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
717 	}
718 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
719 }
720 
721 HBA_STATUS
722 Sun_HBA_AdapterReturnWWN (
723     HBA_HANDLE		handle,
724     HBA_UINT32		portindex,
725     HBA_WWN		*nwwn,
726     HBA_WWN		*pwwn)
727 {
728 	HBA_STATUS		status;
729 	HBA_LIBRARY_INFO	*lib_infop;
730 	HBA_HANDLE		vendorHandle;
731 	Sun_HBAAdapterReturnWWNFunc	AdapterReturnWWNFunc;
732 
733 	NPIVCHECKLIBRARY();
734 	AdapterReturnWWNFunc = (Sun_HBAAdapterReturnWWNFunc)
735 		dlsym(lib_infop->hLibrary, "Sun_fcAdapterReturnWWN");
736 	if (AdapterReturnWWNFunc != NULL) {
737 		status = ((AdapterReturnWWNFunc)(vendorHandle,
738 		    portindex, nwwn, pwwn));
739 	} else {
740 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
741 	}
742 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
743 }
744 
745 typedef struct hba_npivadaptercallback_elem {
746     struct hba_npivadaptercallback_elem
747 			*next;
748     HBA_LIBRARY_INFO	*lib_info;
749     void		*userdata;
750     HBA_CALLBACKHANDLE	vendorcbhandle;
751     void		(*callback)();
752 } HBA_NPIVADAPTERCALLBACK_ELEM;
753 extern HBA_NPIVADAPTERCALLBACK_ELEM *_hbaapi_adapterdeviceevents_callback_list;
754 
755 /* Adapter Device Events ********************************************************/
756 static void
757 adapterdeviceevents_callback (void *data,
758     HBA_WWN	PortWWN,
759     HBA_UINT32	eventType,
760     HBA_UINT32	fabricPortID)
761 {
762 	HBA_NPIVADAPTERCALLBACK_ELEM	*acbp;
763 
764 	DEBUG(3, "AdapterDeviceEvent, port:%s, eventType:%d fabricPortID:0X%06x",
765 	    WWN2STR1(&PortWWN), eventType, fabricPortID);
766 
767 	GRAB_MUTEX(&_hbaapi_APE_mutex);
768 
769 	for(acbp = _hbaapi_adapterdeviceevents_callback_list;
770 	    acbp != NULL;
771 	    acbp = acbp->next) {
772 		if(data == (void *)acbp) {
773 			(*acbp->callback)(acbp->userdata, PortWWN, eventType, fabricPortID);
774 			break;
775 		}
776 	}
777 	RELEASE_MUTEX(&_hbaapi_APE_mutex);
778 }
779 
780 HBA_STATUS
781 Sun_HBA_RegisterForAdapterDeviceEvents (
782     void	(*callback) (
783 	void		*data,
784 	HBA_WWN		PortWWN,
785 	HBA_UINT32	eventType,
786 	HBA_UINT32	fabricPortID
787 	),
788     void		*userData,
789     HBA_HANDLE		handle,
790     HBA_WWN		PortWWN,
791     HBA_CALLBACKHANDLE	*callbackHandle)
792 {
793 	HBA_NPIVADAPTERCALLBACK_ELEM	*acbp;
794 	HBA_STATUS			status;
795 	HBA_LIBRARY_INFO		*lib_infop;
796 	HBA_HANDLE			vendorHandle;
797 	Sun_HBARegisterForAdapterDeviceEventsFunc
798 					registeredfunc;
799 
800 	if (callbackHandle == NULL) {
801 		return(HBA_STATUS_ERROR_ARG);
802 	}
803 
804         NPIVCHECKLIBRARY();
805 	registeredfunc = (Sun_HBARegisterForAdapterDeviceEventsFunc)
806                 dlsym(lib_infop->hLibrary,
807 		    "Sun_fcRegisterForAdapterDeviceEvents");
808 	if (registeredfunc == NULL) {
809 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
810 	}
811 
812 	acbp = (HBA_NPIVADAPTERCALLBACK_ELEM *)
813 		calloc(1, sizeof(HBA_NPIVADAPTERCALLBACK_ELEM));
814 
815 	if(acbp == NULL) {
816 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
817 	}
818 
819 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
820 	acbp->callback = callback;
821 	acbp->userdata = userData;
822 	acbp->lib_info = lib_infop;
823 
824 	status = (registeredfunc)(adapterdeviceevents_callback,
825 		(void *)acbp,
826 		vendorHandle,
827 		PortWWN,
828 		&acbp->vendorcbhandle);
829 	if(status != HBA_STATUS_OK) {
830 		free(acbp);
831 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
832 	}
833 
834 	GRAB_MUTEX(&_hbaapi_APE_mutex);
835 	acbp->next = _hbaapi_adapterdeviceevents_callback_list;
836 	_hbaapi_adapterdeviceevents_callback_list = acbp;
837 	RELEASE_MUTEX(&_hbaapi_APE_mutex);
838 
839 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
840 }
841