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