1 /*
   2  * CDDL HEADER START
   3  *
   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.
   7  *
   8  * You can obtain a copy of the license at
   9  * http://www.opensource.org/licenses/cddl1.txt.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  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]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2004-2012 Emulex. All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #define DEF_EVENT_STRUCT  /* Needed for emlxs_events.h in emlxs_event.h */
  28 #include <emlxs.h>
  29 
  30 
  31 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
  32 EMLXS_MSG_DEF(EMLXS_EVENT_C);
  33 
  34 
  35 static uint32_t emlxs_event_check(emlxs_port_t *port, emlxs_event_t *evt);
  36 static void emlxs_event_destroy(emlxs_hba_t *hba, emlxs_event_entry_t *entry);
  37 
  38 extern void
  39 emlxs_null_func() {}
  40 
  41 
  42 static uint32_t
  43 emlxs_event_check(emlxs_port_t *port, emlxs_event_t *evt)
  44 {
  45         emlxs_hba_t *hba = HBA;
  46 
  47         /* Check if the event is being requested */
  48         if ((hba->event_mask & evt->mask)) {
  49                 return (1);
  50         }
  51 
  52 #ifdef SAN_DIAG_SUPPORT
  53         if ((port->sd_event_mask & evt->mask)) {
  54                 return (1);
  55         }
  56 #endif /* SAN_DIAG_SUPPORT */
  57 
  58         return (0);
  59 
  60 } /* emlxs_event_check() */
  61 
  62 
  63 extern uint32_t
  64 emlxs_event_queue_create(emlxs_hba_t *hba)
  65 {
  66         emlxs_event_queue_t *eventq = &EVENTQ;
  67         ddi_iblock_cookie_t iblock;
  68 
  69         /* Clear the queue */
  70         bzero(eventq, sizeof (emlxs_event_queue_t));
  71 
  72         cv_init(&eventq->lock_cv, NULL, CV_DRIVER, NULL);
  73 
  74         if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
  75                 /* Get the current interrupt block cookie */
  76                 (void) ddi_get_iblock_cookie(hba->dip, (uint_t)EMLXS_INUMBER,
  77                     &iblock);
  78 
  79                 /* Create the mutex lock */
  80                 mutex_init(&eventq->lock, NULL, MUTEX_DRIVER, (void *)iblock);
  81         }
  82 #ifdef  MSI_SUPPORT
  83         else {
  84                 /* Create event mutex lock */
  85                 mutex_init(&eventq->lock, NULL, MUTEX_DRIVER,
  86                     DDI_INTR_PRI(hba->intr_arg));
  87         }
  88 #endif
  89 
  90         return (1);
  91 
  92 } /* emlxs_event_queue_create() */
  93 
  94 
  95 extern void
  96 emlxs_event_queue_destroy(emlxs_hba_t *hba)
  97 {
  98         emlxs_port_t *vport;
  99         emlxs_event_queue_t *eventq = &EVENTQ;
 100         uint32_t i;
 101         uint32_t wakeup = 0;
 102 
 103         mutex_enter(&eventq->lock);
 104 
 105         /* Clear all event masks and broadcast a wakeup */
 106         /* to clear any sleeping threads */
 107         if (hba->event_mask) {
 108                 hba->event_mask = 0;
 109                 hba->event_timer = 0;
 110                 wakeup = 1;
 111         }
 112 
 113         for (i = 0; i < MAX_VPORTS; i++) {
 114                 vport = &VPORT(i);
 115 
 116                 if (vport->sd_event_mask) {
 117                         vport->sd_event_mask = 0;
 118                         wakeup = 1;
 119                 }
 120         }
 121 
 122         if (wakeup) {
 123                 cv_broadcast(&eventq->lock_cv);
 124 
 125                 mutex_exit(&eventq->lock);
 126                 BUSYWAIT_MS(10);
 127                 mutex_enter(&eventq->lock);
 128         }
 129 
 130         /* Destroy the remaining events */
 131         while (eventq->first) {
 132                 emlxs_event_destroy(hba, eventq->first);
 133         }
 134 
 135         mutex_exit(&eventq->lock);
 136 
 137         /* Destroy the queue lock */
 138         mutex_destroy(&eventq->lock);
 139         cv_destroy(&eventq->lock_cv);
 140 
 141         /* Clear the queue */
 142         bzero(eventq, sizeof (emlxs_event_queue_t));
 143 
 144         return;
 145 
 146 } /* emlxs_event_queue_destroy() */
 147 
 148 
 149 /* Event queue lock must be held */
 150 static void
 151 emlxs_event_destroy(emlxs_hba_t *hba, emlxs_event_entry_t *entry)
 152 {
 153         emlxs_event_queue_t *eventq = &EVENTQ;
 154         emlxs_port_t *port;
 155         uint32_t missed = 0;
 156 
 157         port = (emlxs_port_t *)entry->port;
 158 
 159         eventq->count--;
 160         if (eventq->count == 0) {
 161                 eventq->first = NULL;
 162                 eventq->last = NULL;
 163         } else {
 164                 if (entry->prev) {
 165                         entry->prev->next = entry->next;
 166                 }
 167                 if (entry->next) {
 168                         entry->next->prev = entry->prev;
 169                 }
 170                 if (eventq->first == entry) {
 171                         eventq->first = entry->next;
 172                 }
 173                 if (eventq->last == entry) {
 174                         eventq->last = entry->prev;
 175                 }
 176         }
 177 
 178         entry->prev = NULL;
 179         entry->next = NULL;
 180 
 181         if ((entry->evt->mask == EVT_LINK) ||
 182             (entry->evt->mask == EVT_RSCN)) {
 183                 if (!(entry->flag & EMLXS_DFC_EVENT_DONE)) {
 184                         hba->hba_event.missed++;
 185                         missed = 1;
 186                 }
 187         }
 188 
 189         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_dequeued_msg,
 190             "%s[%d]: flag=%x missed=%d cnt=%d",
 191             entry->evt->label, entry->id, entry->flag, missed, eventq->count);
 192 
 193         /* Call notification handler */
 194         if (entry->evt->destroy != emlxs_null_func) {
 195                 entry->evt->destroy(entry);
 196         }
 197 
 198         /* Free context buffer */
 199         if (entry->bp && entry->size) {
 200                 kmem_free(entry->bp, entry->size);
 201         }
 202 
 203         /* Free entry buffer */
 204         kmem_free(entry, sizeof (emlxs_event_entry_t));
 205 
 206         return;
 207 
 208 } /* emlxs_event_destroy() */
 209 
 210 
 211 extern void
 212 emlxs_event(emlxs_port_t *port, emlxs_event_t *evt, void *bp, uint32_t size)
 213 {
 214         emlxs_hba_t *hba = HBA;
 215         emlxs_event_queue_t *eventq = &EVENTQ;
 216         emlxs_event_entry_t *entry;
 217         uint32_t i;
 218         uint32_t mask;
 219 
 220         if (emlxs_event_check(port, evt) == 0) {
 221                 goto failed;
 222         }
 223 
 224         /* Create event entry */
 225         if (!(entry = (emlxs_event_entry_t *)kmem_alloc(
 226             sizeof (emlxs_event_entry_t), KM_NOSLEEP))) {
 227                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 228                     "%s: Unable to allocate event entry.", evt->label);
 229 
 230                 goto failed;
 231         }
 232 
 233         /* Initialize */
 234         bzero(entry, sizeof (emlxs_event_entry_t));
 235 
 236         entry->evt = evt;
 237         entry->port = (void *)port;
 238         entry->bp = bp;
 239         entry->size = size;
 240 
 241         mutex_enter(&eventq->lock);
 242 
 243         /* Set the event timer */
 244         entry->timestamp = hba->timer_tics;
 245         if (evt->timeout) {
 246                 entry->timer = entry->timestamp + evt->timeout;
 247         }
 248 
 249         /* Eventq id starts with 1 */
 250         if (eventq->next_id == 0) {
 251                 eventq->next_id = 1;
 252         }
 253 
 254         /* Set the event id */
 255         entry->id = eventq->next_id++;
 256 
 257         /* Set last event table */
 258         mask = evt->mask;
 259         for (i = 0; i < 32; i++) {
 260                 if (mask & 0x01) {
 261                         eventq->last_id[i] = entry->id;
 262                 }
 263                 mask >>= 1;
 264         }
 265 
 266         /* Put event on bottom of queue */
 267         entry->next = NULL;
 268         if (eventq->count == 0) {
 269                 entry->prev = NULL;
 270                 eventq->first = entry;
 271                 eventq->last = entry;
 272         } else {
 273                 entry->prev = eventq->last;
 274                 entry->prev->next = entry;
 275                 eventq->last = entry;
 276         }
 277         eventq->count++;
 278 
 279         if ((entry->evt->mask == EVT_LINK) ||
 280             (entry->evt->mask == EVT_RSCN)) {
 281                 hba->hba_event.new++;
 282         }
 283 
 284         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_queued_msg,
 285             "%s[%d]: bp=%p size=%d cnt=%d", entry->evt->label,
 286             entry->id, bp, size, eventq->count);
 287 
 288         /* Broadcast the event */
 289         cv_broadcast(&eventq->lock_cv);
 290 
 291         mutex_exit(&eventq->lock);
 292 
 293         return;
 294 
 295 failed:
 296 
 297         if (bp && size) {
 298                 kmem_free(bp, size);
 299         }
 300 
 301         return;
 302 
 303 } /* emlxs_event() */
 304 
 305 
 306 extern void
 307 emlxs_timer_check_events(emlxs_hba_t *hba)
 308 {
 309         emlxs_config_t *cfg = &CFG;
 310         emlxs_event_queue_t *eventq = &EVENTQ;
 311         emlxs_event_entry_t *entry;
 312         emlxs_event_entry_t *next;
 313 
 314         if (!cfg[CFG_TIMEOUT_ENABLE].current) {
 315                 return;
 316         }
 317 
 318         if ((hba->event_timer > hba->timer_tics)) {
 319                 return;
 320         }
 321 
 322         if (eventq->count) {
 323                 mutex_enter(&eventq->lock);
 324 
 325                 entry = eventq->first;
 326                 while (entry) {
 327                         if ((!entry->timer) ||
 328                             (entry->timer > hba->timer_tics)) {
 329                                 entry = entry->next;
 330                                 continue;
 331                         }
 332 
 333                         /* Event timed out, destroy it */
 334                         next = entry->next;
 335                         emlxs_event_destroy(hba, entry);
 336                         entry = next;
 337                 }
 338 
 339                 mutex_exit(&eventq->lock);
 340         }
 341 
 342         /* Set next event timer check */
 343         hba->event_timer = hba->timer_tics + EMLXS_EVENT_PERIOD;
 344 
 345         return;
 346 
 347 } /* emlxs_timer_check_events() */
 348 
 349 
 350 extern void
 351 emlxs_log_rscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size)
 352 {
 353         uint8_t *bp;
 354         uint32_t *ptr;
 355 
 356         /* Check if the event is being requested */
 357         if (emlxs_event_check(port, &emlxs_rscn_event) == 0) {
 358                 return;
 359         }
 360 
 361         if (size > MAX_RSCN_PAYLOAD) {
 362                 size = MAX_RSCN_PAYLOAD;
 363         }
 364 
 365         size += sizeof (uint32_t);
 366 
 367         /* Save a copy of the payload for the event log */
 368         if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
 369                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 370                     "%s: Unable to allocate buffer.", emlxs_rscn_event.label);
 371 
 372                 return;
 373         }
 374 
 375         /*
 376          * Buffer Format:
 377          *      word[0] = DID of the RSCN
 378          *      word[1] = RSCN Payload
 379          */
 380         ptr = (uint32_t *)bp;
 381         *ptr++ = port->did;
 382         bcopy(payload, (char *)ptr, (size - sizeof (uint32_t)));
 383 
 384         emlxs_event(port, &emlxs_rscn_event, bp, size);
 385 
 386         return;
 387 
 388 } /* emlxs_log_rscn_event() */
 389 
 390 
 391 extern void
 392 emlxs_log_vportrscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size)
 393 {
 394         uint8_t *bp;
 395         uint8_t *ptr;
 396 
 397         /* Check if the event is being requested */
 398         if (emlxs_event_check(port, &emlxs_vportrscn_event) == 0) {
 399                 return;
 400         }
 401 
 402         if (size > MAX_RSCN_PAYLOAD) {
 403                 size = MAX_RSCN_PAYLOAD;
 404         }
 405 
 406         size += sizeof (NAME_TYPE);
 407 
 408         /* Save a copy of the payload for the event log */
 409         if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
 410                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 411                     "%s: Unable to allocate buffer.",
 412                     emlxs_vportrscn_event.label);
 413 
 414                 return;
 415         }
 416 
 417         /*
 418          * Buffer Format:
 419          *      word[0 - 4] = WWPN of the RSCN
 420          *      word[5] = RSCN Payload
 421          */
 422         ptr = bp;
 423         bcopy(&port->wwpn, ptr, sizeof (NAME_TYPE));
 424         ptr += sizeof (NAME_TYPE);
 425         bcopy(payload, ptr, (size - sizeof (NAME_TYPE)));
 426 
 427         emlxs_event(port, &emlxs_vportrscn_event, bp, size);
 428 
 429         return;
 430 
 431 } /* emlxs_log_vportrscn_event() */
 432 
 433 
 434 extern uint32_t
 435 emlxs_flush_ct_event(emlxs_port_t *port, uint32_t rxid)
 436 {
 437         emlxs_hba_t *hba = HBA;
 438         emlxs_event_queue_t *eventq = &EVENTQ;
 439         emlxs_event_entry_t *entry;
 440         uint32_t *ptr;
 441         uint32_t found = 0;
 442 
 443         mutex_enter(&eventq->lock);
 444 
 445         for (entry = eventq->first; entry != NULL; entry = entry->next) {
 446                 if ((entry->port != port) ||
 447                     (entry->evt != &emlxs_ct_event)) {
 448                         continue;
 449                 }
 450 
 451                 ptr = (uint32_t *)entry->bp;
 452                 if (rxid == *ptr) {
 453                         /* This will prevent a CT exchange abort */
 454                         /* in emlxs_ct_event_destroy() */
 455                         entry->flag |= EMLXS_DFC_EVENT_DONE;
 456 
 457                         emlxs_event_destroy(hba, entry);
 458                         found = 1;
 459                         break;
 460                 }
 461         }
 462 
 463         mutex_exit(&eventq->lock);
 464 
 465         return (found);
 466 
 467 } /* emlxs_flush_ct_event() */
 468 
 469 
 470 extern uint32_t
 471 emlxs_log_ct_event(emlxs_port_t *port, uint8_t *payload, uint32_t size,
 472     uint32_t rxid)
 473 {
 474         uint8_t *bp;
 475         uint32_t *ptr;
 476 
 477         /* Check if the event is being requested */
 478         if (emlxs_event_check(port, &emlxs_ct_event) == 0) {
 479                 return (1);
 480         }
 481 
 482         if (size > MAX_CT_PAYLOAD) {
 483                 size = MAX_CT_PAYLOAD;
 484         }
 485 
 486         size += sizeof (uint32_t);
 487 
 488         /* Save a copy of the payload for the event log */
 489         if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
 490                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 491                     "%s: Unable to allocate buffer.", emlxs_ct_event.label);
 492 
 493                 return (1);
 494         }
 495 
 496         /*
 497          * Buffer Format:
 498          *      word[0] = RXID tag for outgoing reply to this CT request
 499          *      word[1] = CT Payload
 500          */
 501         ptr = (uint32_t *)bp;
 502         *ptr++ = rxid;
 503         bcopy(payload, (char *)ptr, (size - sizeof (uint32_t)));
 504 
 505         emlxs_event(port, &emlxs_ct_event, bp, size);
 506 
 507         return (0);
 508 
 509 } /* emlxs_log_ct_event() */
 510 
 511 
 512 extern void
 513 emlxs_ct_event_destroy(emlxs_event_entry_t *entry)
 514 {
 515         emlxs_port_t *port = (emlxs_port_t *)entry->port;
 516         emlxs_hba_t *hba = HBA;
 517         uint32_t rxid;
 518 
 519         if (!(entry->flag & EMLXS_DFC_EVENT_DONE)) {
 520 
 521                 rxid = *(uint32_t *)entry->bp;
 522 
 523                 /* Abort exchange */
 524                 emlxs_thread_spawn(hba, emlxs_abort_ct_exchange,
 525                     entry->port, (void *)(unsigned long)rxid);
 526         }
 527 
 528         return;
 529 
 530 } /* emlxs_ct_event_destroy() */
 531 
 532 
 533 extern void
 534 emlxs_log_link_event(emlxs_port_t *port)
 535 {
 536         emlxs_hba_t *hba = HBA;
 537         uint8_t *bp;
 538         dfc_linkinfo_t *linkinfo;
 539         uint8_t *byte;
 540         uint8_t *linkspeed;
 541         uint8_t *liptype;
 542         uint8_t *resv1;
 543         uint8_t *resv2;
 544         uint32_t size;
 545 
 546         /* Check if the event is being requested */
 547         if (emlxs_event_check(port, &emlxs_link_event) == 0) {
 548                 return;
 549         }
 550 
 551         size = sizeof (dfc_linkinfo_t) + sizeof (uint32_t);
 552 
 553         /* Save a copy of the buffer for the event log */
 554         if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
 555                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 556                     "%s: Unable to allocate buffer.", emlxs_link_event.label);
 557 
 558                 return;
 559         }
 560 
 561         /*
 562          * Buffer Format:
 563          *      word[0] = Linkspeed:8
 564          *      word[0] = LIP_type:8
 565          *      word[0] = resv1:8
 566          *      word[0] = resv2:8
 567          *      word[1] = dfc_linkinfo_t data
 568          */
 569         byte = (uint8_t *)bp;
 570         linkspeed = &byte[0];
 571         liptype = &byte[1];
 572         resv1 = &byte[2];
 573         resv2 = &byte[3];
 574         linkinfo = (dfc_linkinfo_t *)&byte[4];
 575 
 576         *resv1 = 0;
 577         *resv2 = 0;
 578 
 579         if (hba->state <= FC_LINK_DOWN) {
 580                 *linkspeed = 0;
 581                 *liptype = 0;
 582         } else {
 583                 /* Set linkspeed */
 584                 if (hba->linkspeed == LA_2GHZ_LINK) {
 585                         *linkspeed = HBA_PORTSPEED_2GBIT;
 586                 } else if (hba->linkspeed == LA_4GHZ_LINK) {
 587                         *linkspeed = HBA_PORTSPEED_4GBIT;
 588                 } else if (hba->linkspeed == LA_8GHZ_LINK) {
 589                         *linkspeed = HBA_PORTSPEED_8GBIT;
 590                 } else if (hba->linkspeed == LA_10GHZ_LINK) {
 591                         *linkspeed = HBA_PORTSPEED_10GBIT;
 592                 } else if (hba->linkspeed == LA_16GHZ_LINK) {
 593                         *linkspeed = HBA_PORTSPEED_16GBIT;
 594                 } else {
 595                         *linkspeed = HBA_PORTSPEED_1GBIT;
 596                 }
 597 
 598                 /* Set LIP type */
 599                 *liptype = port->lip_type;
 600         }
 601 
 602         bzero(linkinfo, sizeof (dfc_linkinfo_t));
 603 
 604         linkinfo->a_linkEventTag = hba->link_event_tag;
 605         linkinfo->a_linkUp = HBASTATS.LinkUp;
 606         linkinfo->a_linkDown = HBASTATS.LinkDown;
 607         linkinfo->a_linkMulti = HBASTATS.LinkMultiEvent;
 608 
 609         if (hba->state <= FC_LINK_DOWN) {
 610                 linkinfo->a_linkState = LNK_DOWN;
 611                 linkinfo->a_DID = port->prev_did;
 612         } else if (hba->state < FC_READY) {
 613                 linkinfo->a_linkState = LNK_DISCOVERY;
 614         } else {
 615                 linkinfo->a_linkState = LNK_READY;
 616         }
 617 
 618         if (linkinfo->a_linkState != LNK_DOWN) {
 619                 if (hba->topology == TOPOLOGY_LOOP) {
 620                         if (hba->flag & FC_FABRIC_ATTACHED) {
 621                                 linkinfo->a_topology = LNK_PUBLIC_LOOP;
 622                         } else {
 623                                 linkinfo->a_topology = LNK_LOOP;
 624                         }
 625 
 626                         linkinfo->a_alpa = port->did & 0xff;
 627                         linkinfo->a_DID = linkinfo->a_alpa;
 628                         linkinfo->a_alpaCnt = port->alpa_map[0];
 629 
 630                         if (linkinfo->a_alpaCnt > 127) {
 631                                 linkinfo->a_alpaCnt = 127;
 632                         }
 633 
 634                         bcopy((void *)&port->alpa_map[1], linkinfo->a_alpaMap,
 635                             linkinfo->a_alpaCnt);
 636                 } else {
 637                         if (port->node_count == 1) {
 638                                 linkinfo->a_topology = LNK_PT2PT;
 639                         } else {
 640                                 linkinfo->a_topology = LNK_FABRIC;
 641                         }
 642 
 643                         linkinfo->a_DID = port->did;
 644                 }
 645         }
 646 
 647         bcopy(&hba->wwpn, linkinfo->a_wwpName, 8);
 648         bcopy(&hba->wwnn, linkinfo->a_wwnName, 8);
 649 
 650         emlxs_event(port, &emlxs_link_event, bp, size);
 651 
 652         return;
 653 
 654 } /* emlxs_log_link_event() */
 655 
 656 
 657 extern void
 658 emlxs_log_dump_event(emlxs_port_t *port, uint8_t *buffer, uint32_t size)
 659 {
 660         emlxs_hba_t *hba = HBA;
 661         uint8_t *bp;
 662 
 663         /* Check if the event is being requested */
 664         if (emlxs_event_check(port, &emlxs_dump_event) == 0) {
 665 #ifdef DUMP_SUPPORT
 666                 /* Schedule a dump thread */
 667                 emlxs_dump(hba, EMLXS_DRV_DUMP, 0, 0);
 668 #endif /* DUMP_SUPPORT */
 669                 return;
 670         }
 671 
 672         if (buffer && size) {
 673                 /* Save a copy of the buffer for the event log */
 674                 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
 675                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 676                             "%s: Unable to allocate buffer.",
 677                             emlxs_dump_event.label);
 678 
 679                         return;
 680                 }
 681 
 682                 bcopy(buffer, bp, size);
 683         } else {
 684                 bp = NULL;
 685                 size = 0;
 686         }
 687 
 688         emlxs_event(port, &emlxs_dump_event, bp, size);
 689 
 690         return;
 691 
 692 } /* emlxs_log_dump_event() */
 693 
 694 
 695 extern void
 696 emlxs_log_temp_event(emlxs_port_t *port, uint32_t type, uint32_t temp)
 697 {
 698         emlxs_hba_t *hba = HBA;
 699         uint32_t *bp;
 700         uint32_t size;
 701 
 702         /* Check if the event is being requested */
 703         if (emlxs_event_check(port, &emlxs_temp_event) == 0) {
 704 #ifdef DUMP_SUPPORT
 705                 /* Schedule a dump thread */
 706                 emlxs_dump(hba, EMLXS_TEMP_DUMP, type, temp);
 707 #endif /* DUMP_SUPPORT */
 708                 return;
 709         }
 710 
 711         size = 2 * sizeof (uint32_t);
 712 
 713         if (!(bp = (uint32_t *)kmem_alloc(size, KM_NOSLEEP))) {
 714                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 715                     "%s: Unable to allocate buffer.", emlxs_temp_event.label);
 716 
 717                 return;
 718         }
 719 
 720         bp[0] = type;
 721         bp[1] = temp;
 722 
 723         emlxs_event(port, &emlxs_temp_event, bp, size);
 724 
 725         return;
 726 
 727 } /* emlxs_log_temp_event() */
 728 
 729 
 730 
 731 extern void
 732 emlxs_log_fcoe_event(emlxs_port_t *port, menlo_init_rsp_t *init_rsp)
 733 {
 734         emlxs_hba_t *hba = HBA;
 735         uint8_t *bp;
 736         uint32_t size;
 737 
 738         /* Check if the event is being requested */
 739         if (emlxs_event_check(port, &emlxs_fcoe_event) == 0) {
 740                 return;
 741         }
 742 
 743         /* Check if this is a FCOE adapter */
 744         if (hba->model_info.device_id != PCI_DEVICE_ID_HORNET) {
 745                 return;
 746         }
 747 
 748         size = sizeof (menlo_init_rsp_t);
 749 
 750         if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
 751                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 752                     "%s: Unable to allocate buffer.", emlxs_fcoe_event.label);
 753 
 754                 return;
 755         }
 756 
 757         bcopy((uint8_t *)init_rsp, bp, size);
 758 
 759         emlxs_event(port, &emlxs_fcoe_event, bp, size);
 760 
 761         return;
 762 
 763 } /* emlxs_log_fcoe_event() */
 764 
 765 
 766 extern void
 767 emlxs_log_async_event(emlxs_port_t *port, IOCB *iocb)
 768 {
 769         uint8_t *bp;
 770         uint32_t size;
 771 
 772         if (emlxs_event_check(port, &emlxs_async_event) == 0) {
 773                 return;
 774         }
 775 
 776         /* ASYNC_STATUS_CN response size */
 777         size = 64;
 778 
 779         if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
 780                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 781                     "%s: Unable to allocate buffer.", emlxs_async_event.label);
 782 
 783                 return;
 784         }
 785 
 786         bcopy((uint8_t *)iocb, bp, size);
 787 
 788         emlxs_event(port, &emlxs_async_event, bp, size);
 789 
 790         return;
 791 
 792 } /* emlxs_log_async_event() */
 793 
 794 
 795 extern uint32_t
 796 emlxs_get_dfc_eventinfo(emlxs_port_t *port, HBA_EVENTINFO *eventinfo,
 797     uint32_t *eventcount, uint32_t *missed)
 798 {
 799         emlxs_hba_t *hba = HBA;
 800         emlxs_event_queue_t *eventq = &EVENTQ;
 801         emlxs_event_entry_t *entry;
 802         uint32_t max_events;
 803         dfc_linkinfo_t *linkinfo;
 804         uint32_t *word;
 805         uint8_t *byte;
 806         uint8_t linkspeed;
 807         uint8_t liptype;
 808         fc_affected_id_t *aid;
 809         uint32_t events;
 810         uint8_t format;
 811 
 812         if (!eventinfo || !eventcount || !missed) {
 813                 return (DFC_ARG_NULL);
 814         }
 815 
 816         max_events = *eventcount;
 817         *eventcount = 0;
 818         *missed = 0;
 819 
 820         mutex_enter(&eventq->lock);
 821 
 822         /* Account for missed events */
 823         if (hba->hba_event.new > hba->hba_event.missed) {
 824                 hba->hba_event.new -= hba->hba_event.missed;
 825         } else {
 826                 hba->hba_event.new = 0;
 827         }
 828 
 829         *missed = hba->hba_event.missed;
 830         hba->hba_event.missed = 0;
 831 
 832         if (!hba->hba_event.new) {
 833                 hba->hba_event.last_id = eventq->next_id - 1;
 834                 mutex_exit(&eventq->lock);
 835                 return (0);
 836         }
 837 
 838         /* A new event has occurred since last acquisition */
 839 
 840         events = 0;
 841         entry = eventq->first;
 842         while (entry && (events < max_events)) {
 843 
 844                 /* Skip old events */
 845                 if (entry->id <= hba->hba_event.last_id) {
 846                         entry = entry->next;
 847                         continue;
 848                 }
 849 
 850                 /* Process this entry */
 851                 switch (entry->evt->mask) {
 852                 case EVT_LINK:
 853                         byte = (uint8_t *)entry->bp;
 854                         linkspeed = byte[0];
 855                         liptype = byte[1];
 856                         linkinfo = (dfc_linkinfo_t *)&byte[4];
 857 
 858                         if (linkinfo->a_linkState == LNK_DOWN) {
 859                                 eventinfo->EventCode =
 860                                     HBA_EVENT_LINK_DOWN;
 861                                 eventinfo->Event.Link_EventInfo.
 862                                     PortFcId = linkinfo->a_DID;
 863                                 eventinfo->Event.Link_EventInfo.
 864                                     Reserved[0] = 0;
 865                                 eventinfo->Event.Link_EventInfo.
 866                                     Reserved[1] = 0;
 867                                 eventinfo->Event.Link_EventInfo.
 868                                     Reserved[2] = 0;
 869                         } else {
 870                                 eventinfo->EventCode =
 871                                     HBA_EVENT_LINK_UP;
 872                                 eventinfo->Event.Link_EventInfo.
 873                                     PortFcId = linkinfo->a_DID;
 874 
 875                                 if ((linkinfo->a_topology ==
 876                                     LNK_PUBLIC_LOOP) ||
 877                                     (linkinfo->a_topology ==
 878                                     LNK_LOOP)) {
 879                                         eventinfo->Event.
 880                                             Link_EventInfo.
 881                                             Reserved[0] = 2;
 882                                 } else {
 883                                         eventinfo->Event.
 884                                             Link_EventInfo.
 885                                             Reserved[0] = 1;
 886                                 }
 887 
 888                                 eventinfo->Event.Link_EventInfo.
 889                                     Reserved[1] = liptype;
 890                                 eventinfo->Event.Link_EventInfo.
 891                                     Reserved[2] = linkspeed;
 892                         }
 893 
 894                         eventinfo++;
 895                         events++;
 896                         hba->hba_event.new--;
 897                         break;
 898 
 899                 case EVT_RSCN:
 900                         word = (uint32_t *)entry->bp;
 901                         eventinfo->EventCode = HBA_EVENT_RSCN;
 902                         eventinfo->Event.RSCN_EventInfo.PortFcId =
 903                             word[0] & 0xFFFFFF;
 904                         /* word[1] is the RSCN payload command */
 905 
 906                         aid = (fc_affected_id_t *)&word[2];
 907                         format = aid->aff_format;
 908 
 909                         switch (format) {
 910                         case 0: /* Port */
 911                                 eventinfo->Event.RSCN_EventInfo.
 912                                     NPortPage =
 913                                     aid->aff_d_id & 0x00ffffff;
 914                                 break;
 915 
 916                         case 1: /* Area */
 917                                 eventinfo->Event.RSCN_EventInfo.
 918                                     NPortPage =
 919                                     aid->aff_d_id & 0x00ffff00;
 920                                 break;
 921 
 922                         case 2: /* Domain */
 923                                 eventinfo->Event.RSCN_EventInfo.
 924                                     NPortPage =
 925                                     aid->aff_d_id & 0x00ff0000;
 926                                 break;
 927 
 928                         case 3: /* Network */
 929                                 eventinfo->Event.RSCN_EventInfo.
 930                                     NPortPage = 0;
 931                                 break;
 932                         }
 933 
 934                         eventinfo->Event.RSCN_EventInfo.Reserved[0] =
 935                             0;
 936                         eventinfo->Event.RSCN_EventInfo.Reserved[1] =
 937                             0;
 938 
 939                         eventinfo++;
 940                         events++;
 941                         hba->hba_event.new--;
 942                         break;
 943                 }
 944 
 945                 hba->hba_event.last_id = entry->id;
 946                 entry = entry->next;
 947         }
 948 
 949         /* Return number of events acquired */
 950         *eventcount = events;
 951 
 952         mutex_exit(&eventq->lock);
 953 
 954         return (0);
 955 
 956 } /* emlxs_get_dfc_eventinfo() */
 957 
 958 
 959 void
 960 emlxs_get_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
 961     uint32_t sleep)
 962 {
 963         emlxs_hba_t *hba = HBA;
 964         emlxs_event_queue_t *eventq = &EVENTQ;
 965         emlxs_event_entry_t *entry;
 966         uint32_t found;
 967         uint32_t mask;
 968         uint32_t i;
 969         uint32_t size = 0;
 970         uint32_t rc;
 971 
 972         if (dfc_event->dataout && dfc_event->size) {
 973                 size = dfc_event->size;
 974         }
 975         dfc_event->size = 0;
 976 
 977         /* Calculate the event index */
 978         mask = dfc_event->event;
 979         for (i = 0; i < 32; i++) {
 980                 if (mask & 0x01) {
 981                         break;
 982                 }
 983 
 984                 mask >>= 1;
 985         }
 986 
 987         if (i == 32) {
 988                 return;
 989         }
 990 
 991         mutex_enter(&eventq->lock);
 992 
 993 wait_for_event:
 994 
 995         /* Check if no new event has occurred */
 996         if (dfc_event->last_id == eventq->last_id[i]) {
 997                 if (!sleep) {
 998                         mutex_exit(&eventq->lock);
 999                         return;
1000                 }
1001 
1002                 /* While event is still active and */
1003                 /* no new event has been logged */
1004                 while ((dfc_event->event & hba->event_mask) &&
1005                     (dfc_event->last_id == eventq->last_id[i])) {
1006 
1007                         rc = cv_wait_sig(&eventq->lock_cv, &eventq->lock);
1008 
1009                         /* Check if thread was killed by kernel */
1010                         if (rc == 0) {
1011                                 dfc_event->pid = 0;
1012                                 dfc_event->event = 0;
1013                                 mutex_exit(&eventq->lock);
1014                                 return;
1015                         }
1016                 }
1017 
1018                 /* If the event is no longer registered then */
1019                 /* return immediately */
1020                 if (!(dfc_event->event & hba->event_mask)) {
1021                         mutex_exit(&eventq->lock);
1022                         return;
1023                 }
1024         }
1025 
1026         /* !!! An event has occurred since last_id !!! */
1027 
1028         /* Check if event data is not being requested */
1029         if (!size) {
1030                 /* If so, then just return the last event id */
1031                 dfc_event->last_id = eventq->last_id[i];
1032 
1033                 mutex_exit(&eventq->lock);
1034                 return;
1035         }
1036 
1037         /* !!! The requester wants the next event buffer !!! */
1038 
1039         found = 0;
1040         entry = eventq->first;
1041         while (entry) {
1042                 if ((entry->id > dfc_event->last_id) &&
1043                     (entry->evt->mask == dfc_event->event)) {
1044                         found = 1;
1045                         break;
1046                 }
1047 
1048                 entry = entry->next;
1049         }
1050 
1051         if (!found) {
1052                 /* Update last_id to the last known event */
1053                 dfc_event->last_id = eventq->last_id[i];
1054 
1055                 /* Try waiting again if we can */
1056                 goto wait_for_event;
1057         }
1058 
1059         /* !!! Next event found !!! */
1060 
1061         /* Copy the context buffer to the buffer provided */
1062         if (entry->bp && entry->size) {
1063                 if (entry->size < size) {
1064                         size = entry->size;
1065                 }
1066 
1067                 bcopy((void *)entry->bp, dfc_event->dataout, size);
1068 
1069                 /* Event has been retrieved by DFCLIB */
1070                 entry->flag |= EMLXS_DFC_EVENT_DONE;
1071 
1072                 dfc_event->size = size;
1073         }
1074 
1075         dfc_event->last_id = entry->id;
1076 
1077         mutex_exit(&eventq->lock);
1078 
1079         return;
1080 
1081 } /* emlxs_get_dfc_event() */
1082 
1083 
1084 uint32_t
1085 emlxs_kill_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event)
1086 {
1087         emlxs_hba_t *hba = HBA;
1088         emlxs_event_queue_t *eventq = &EVENTQ;
1089 
1090         mutex_enter(&eventq->lock);
1091         dfc_event->pid = 0;
1092         dfc_event->event = 0;
1093         cv_broadcast(&eventq->lock_cv);
1094         mutex_exit(&eventq->lock);
1095 
1096         return (0);
1097 
1098 } /* emlxs_kill_dfc_event() */
1099 
1100 
1101 #ifdef SAN_DIAG_SUPPORT
1102 extern void
1103 emlxs_log_sd_basic_els_event(emlxs_port_t *port, uint32_t subcat,
1104     HBA_WWN *portname, HBA_WWN *nodename)
1105 {
1106         struct sd_plogi_rcv_v0  *bp;
1107         uint32_t                size;
1108 
1109         /* Check if the event is being requested */
1110         if (emlxs_event_check(port, &emlxs_sd_els_event) == 0) {
1111                 return;
1112         }
1113 
1114         size = sizeof (struct sd_plogi_rcv_v0);
1115 
1116         if (!(bp = (struct sd_plogi_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP))) {
1117                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1118                     "%s: Unable to allocate buffer.", emlxs_sd_els_event.label);
1119 
1120                 return;
1121         }
1122 
1123         /*
1124          * we are using version field to store subtype, libdfc
1125          * will fix this up before returning data to app.
1126          */
1127         bp->sd_plogir_version = subcat;
1128         bcopy((uint8_t *)portname, (uint8_t *)&bp->sd_plogir_portname,
1129             sizeof (HBA_WWN));
1130         bcopy((uint8_t *)nodename, (uint8_t *)&bp->sd_plogir_nodename,
1131             sizeof (HBA_WWN));
1132 
1133         emlxs_event(port, &emlxs_sd_els_event, bp, size);
1134 
1135         return;
1136 
1137 } /* emlxs_log_sd_basic_els_event() */
1138 
1139 
1140 extern void
1141 emlxs_log_sd_prlo_event(emlxs_port_t *port, HBA_WWN *remoteport)
1142 {
1143         struct sd_prlo_rcv_v0   *bp;
1144         uint32_t                size;
1145 
1146         /* Check if the event is being requested */
1147         if (emlxs_event_check(port, &emlxs_sd_els_event) == 0) {
1148                 return;
1149         }
1150 
1151         size = sizeof (struct sd_prlo_rcv_v0);
1152 
1153         if (!(bp = (struct sd_prlo_rcv_v0 *)kmem_alloc(size,
1154             KM_NOSLEEP))) {
1155                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1156                     "%s PRLO: Unable to allocate buffer.",
1157                     emlxs_sd_els_event.label);
1158 
1159                 return;
1160         }
1161 
1162         /*
1163          * we are using version field to store subtype, libdfc
1164          * will fix this up before returning data to app.
1165          */
1166         bp->sd_prlor_version = SD_ELS_SUBCATEGORY_PRLO_RCV;
1167         bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_prlor_remoteport,
1168             sizeof (HBA_WWN));
1169 
1170         emlxs_event(port, &emlxs_sd_els_event, bp, size);
1171 
1172         return;
1173 
1174 } /* emlxs_log_sd_prlo_event() */
1175 
1176 
1177 extern void
1178 emlxs_log_sd_lsrjt_event(emlxs_port_t *port, HBA_WWN *remoteport,
1179     uint32_t orig_cmd, uint32_t reason, uint32_t reason_expl)
1180 {
1181         struct sd_lsrjt_rcv_v0  *bp;
1182         uint32_t                size;
1183 
1184         /* Check if the event is being requested */
1185         if (emlxs_event_check(port, &emlxs_sd_els_event) == 0) {
1186                 return;
1187         }
1188 
1189         size = sizeof (struct sd_lsrjt_rcv_v0);
1190 
1191         if (!(bp = (struct sd_lsrjt_rcv_v0 *)kmem_alloc(size,
1192             KM_NOSLEEP))) {
1193                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1194                     "%s LSRJT: Unable to allocate buffer.",
1195                     emlxs_sd_els_event.label);
1196 
1197                 return;
1198         }
1199 
1200         /*
1201          * we are using version field to store subtype, libdfc
1202          * will fix this up before returning data to app.
1203          */
1204         bp->sd_lsrjtr_version = SD_ELS_SUBCATEGORY_LSRJT_RCV;
1205         bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_lsrjtr_remoteport,
1206             sizeof (HBA_WWN));
1207         bp->sd_lsrjtr_original_cmd = orig_cmd;
1208         bp->sd_lsrjtr_reasoncode = reason;
1209         bp->sd_lsrjtr_reasoncodeexpl = reason_expl;
1210 
1211         emlxs_event(port, &emlxs_sd_els_event, bp, size);
1212 
1213         return;
1214 
1215 } /* emlxs_log_sd_lsrjt_event() */
1216 
1217 
1218 extern void
1219 emlxs_log_sd_fc_bsy_event(emlxs_port_t *port, HBA_WWN *remoteport)
1220 {
1221         struct sd_pbsy_rcv_v0   *bp;
1222         uint32_t                size;
1223 
1224         /* Check if the event is being requested */
1225         if (emlxs_event_check(port, &emlxs_sd_fabric_event) == 0) {
1226                 return;
1227         }
1228 
1229         size = sizeof (struct sd_pbsy_rcv_v0);
1230 
1231         if (!(bp = (struct sd_pbsy_rcv_v0 *)kmem_alloc(size,
1232             KM_NOSLEEP))) {
1233                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1234                     "%s BSY: Unable to allocate buffer.",
1235                     emlxs_sd_fabric_event.label);
1236 
1237                 return;
1238         }
1239 
1240         /*
1241          * we are using version field to store subtype, libdfc
1242          * will fix this up before returning data to app.
1243          */
1244         if (remoteport == NULL)
1245                 bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_FABRIC_BUSY;
1246         else
1247         {
1248                 bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_PORT_BUSY;
1249                 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_pbsyr_rport,
1250                     sizeof (HBA_WWN));
1251         }
1252 
1253         emlxs_event(port, &emlxs_sd_fabric_event, bp, size);
1254 
1255         return;
1256 
1257 } /* emlxs_log_sd_fc_bsy_event() */
1258 
1259 
1260 extern void
1261 emlxs_log_sd_fc_rdchk_event(emlxs_port_t *port, HBA_WWN *remoteport,
1262     uint32_t lun, uint32_t opcode, uint32_t fcp_param)
1263 {
1264         struct sd_fcprdchkerr_v0        *bp;
1265         uint32_t                        size;
1266 
1267         /* Check if the event is being requested */
1268         if (emlxs_event_check(port, &emlxs_sd_fabric_event) == 0) {
1269                 return;
1270         }
1271 
1272         size = sizeof (struct sd_fcprdchkerr_v0);
1273 
1274         if (!(bp = (struct sd_fcprdchkerr_v0 *)kmem_alloc(size,
1275             KM_NOSLEEP))) {
1276                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1277                     "%s RDCHK: Unable to allocate buffer.",
1278                     emlxs_sd_fabric_event.label);
1279 
1280                 return;
1281         }
1282 
1283         /*
1284          * we are using version field to store subtype, libdfc
1285          * will fix this up before returning data to app.
1286          */
1287         bp->sd_fcprdchkerr_version = SD_FABRIC_SUBCATEGORY_FCPRDCHKERR;
1288         bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_fcprdchkerr_rport,
1289             sizeof (HBA_WWN));
1290         bp->sd_fcprdchkerr_lun = lun;
1291         bp->sd_fcprdchkerr_opcode = opcode;
1292         bp->sd_fcprdchkerr_fcpiparam = fcp_param;
1293 
1294         emlxs_event(port, &emlxs_sd_fabric_event, bp, size);
1295 
1296         return;
1297 
1298 } /* emlxs_log_sd_rdchk_event() */
1299 
1300 
1301 extern void
1302 emlxs_log_sd_scsi_event(emlxs_port_t *port, uint32_t type,
1303     HBA_WWN *remoteport, int32_t lun)
1304 {
1305         struct sd_scsi_generic_v0       *bp;
1306         uint32_t                        size;
1307 
1308         /* Check if the event is being requested */
1309         if (emlxs_event_check(port, &emlxs_sd_scsi_event) == 0) {
1310                 return;
1311         }
1312 
1313         size = sizeof (struct sd_scsi_generic_v0);
1314 
1315         if (!(bp = (struct sd_scsi_generic_v0 *)kmem_alloc(size,
1316             KM_NOSLEEP))) {
1317                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1318                     "%s: Unable to allocate buffer.",
1319                     emlxs_sd_scsi_event.label);
1320 
1321                 return;
1322         }
1323 
1324         /*
1325          * we are using version field to store subtype, libdfc
1326          * will fix this up before returning data to app.
1327          */
1328         bp->sd_scsi_generic_version = type;
1329         bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_generic_rport,
1330             sizeof (HBA_WWN));
1331         bp->sd_scsi_generic_lun = lun;
1332 
1333         emlxs_event(port, &emlxs_sd_scsi_event, bp, size);
1334 
1335         return;
1336 
1337 } /* emlxs_log_sd_scsi_event() */
1338 
1339 
1340 extern void
1341 emlxs_log_sd_scsi_check_event(emlxs_port_t *port, HBA_WWN *remoteport,
1342     uint32_t lun, uint32_t cmdcode, uint32_t sensekey,
1343     uint32_t asc, uint32_t ascq)
1344 {
1345         struct sd_scsi_checkcond_v0     *bp;
1346         uint32_t                        size;
1347 
1348         /* Check if the event is being requested */
1349         if (emlxs_event_check(port, &emlxs_sd_scsi_event) == 0) {
1350                 return;
1351         }
1352 
1353         size = sizeof (struct sd_scsi_checkcond_v0);
1354 
1355         if (!(bp = (struct sd_scsi_checkcond_v0 *)kmem_alloc(size,
1356             KM_NOSLEEP))) {
1357                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1358                     "%s CHECK: Unable to allocate buffer.",
1359                     emlxs_sd_scsi_event.label);
1360 
1361                 return;
1362         }
1363 
1364         /*
1365          * we are using version field to store subtype, libdfc
1366          * will fix this up before returning data to app.
1367          */
1368         bp->sd_scsi_checkcond_version = SD_SCSI_SUBCATEGORY_CHECKCONDITION;
1369         bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_checkcond_rport,
1370             sizeof (HBA_WWN));
1371         bp->sd_scsi_checkcond_lun = lun;
1372         bp->sd_scsi_checkcond_cmdcode = cmdcode;
1373         bp->sd_scsi_checkcond_sensekey = sensekey;
1374         bp->sd_scsi_checkcond_asc = asc;
1375         bp->sd_scsi_checkcond_ascq = ascq;
1376 
1377         emlxs_event(port, &emlxs_sd_scsi_event, bp, size);
1378 
1379         return;
1380 
1381 } /* emlxs_log_sd_scsi_check_event() */
1382 
1383 
1384 void
1385 emlxs_get_sd_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
1386     uint32_t sleep)
1387 {
1388         emlxs_hba_t *hba = HBA;
1389         emlxs_event_queue_t *eventq = &EVENTQ;
1390         emlxs_event_entry_t *entry;
1391         uint32_t found;
1392         uint32_t mask;
1393         uint32_t i;
1394         uint32_t size = 0;
1395         uint32_t rc;
1396 
1397         if (dfc_event->dataout && dfc_event->size) {
1398                 size = dfc_event->size;
1399         }
1400         dfc_event->size = 0;
1401 
1402         /* Calculate the event index */
1403         mask = dfc_event->event;
1404         for (i = 0; i < 32; i++) {
1405                 if (mask & 0x01) {
1406                         break;
1407                 }
1408 
1409                 mask >>= 1;
1410         }
1411 
1412         if (i == 32) {
1413                 return;
1414         }
1415 
1416         mutex_enter(&eventq->lock);
1417 
1418 wait_for_event:
1419 
1420         /* Check if no new event has ocurred */
1421         if (dfc_event->last_id == eventq->last_id[i]) {
1422                 if (!sleep) {
1423                         mutex_exit(&eventq->lock);
1424                         return;
1425                 }
1426 
1427                 /* While event is active and no new event has been logged */
1428                 while ((dfc_event->event & port->sd_event_mask) &&
1429                     (dfc_event->last_id == eventq->last_id[i])) {
1430                         rc = cv_wait_sig(&eventq->lock_cv, &eventq->lock);
1431 
1432                         /* Check if thread was killed by kernel */
1433                         if (rc == 0) {
1434                                 dfc_event->pid = 0;
1435                                 dfc_event->event = 0;
1436                                 mutex_exit(&eventq->lock);
1437                                 return;
1438                         }
1439                 }
1440 
1441                 /* If the event is no longer registered then return */
1442                 if (!(dfc_event->event & port->sd_event_mask)) {
1443                         mutex_exit(&eventq->lock);
1444                         return;
1445                 }
1446         }
1447 
1448         /* !!! An event has occurred since last_id !!! */
1449 
1450         /* Check if event data is not being requested */
1451         if (!size) {
1452                 /* If so, then just return the last event id */
1453                 dfc_event->last_id = eventq->last_id[i];
1454 
1455                 mutex_exit(&eventq->lock);
1456                 return;
1457         }
1458 
1459         /* !!! The requester wants the next event buffer !!! */
1460 
1461         found = 0;
1462         entry = eventq->first;
1463         while (entry) {
1464                 if ((entry->id > dfc_event->last_id) &&
1465                     (entry->port == (void *)port) &&
1466                     (entry->evt->mask == dfc_event->event)) {
1467                         found = 1;
1468                         break;
1469                 }
1470 
1471                 entry = entry->next;
1472         }
1473 
1474         if (!found) {
1475                 /* Update last_id to the last known event */
1476                 dfc_event->last_id = eventq->last_id[i];
1477 
1478                 /* Try waiting again if we can */
1479                 goto wait_for_event;
1480         }
1481 
1482         /* !!! Next event found !!! */
1483 
1484         /* Copy the context buffer to the buffer provided */
1485         if (entry->bp && entry->size) {
1486                 if (entry->size < size) {
1487                         size = entry->size;
1488                 }
1489 
1490                 bcopy((void *)entry->bp, dfc_event->dataout, size);
1491 
1492                 /* Event has been retrieved by SANDIAG */
1493                 entry->flag |= EMLXS_SD_EVENT_DONE;
1494 
1495                 dfc_event->size = size;
1496         }
1497 
1498         dfc_event->last_id = entry->id;
1499 
1500         mutex_exit(&eventq->lock);
1501 
1502         return;
1503 
1504 } /* emlxs_get_sd_event */
1505 #endif /* SAN_DIAG_SUPPORT */