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 if (hba->linkspeed == LA_32GHZ_LINK) {
 595                         *linkspeed = HBA_PORTSPEED_32GBIT;
 596                 } else {
 597                         *linkspeed = HBA_PORTSPEED_1GBIT;
 598                 }
 599 
 600                 /* Set LIP type */
 601                 *liptype = port->lip_type;
 602         }
 603 
 604         bzero(linkinfo, sizeof (dfc_linkinfo_t));
 605 
 606         linkinfo->a_linkEventTag = hba->link_event_tag;
 607         linkinfo->a_linkUp = HBASTATS.LinkUp;
 608         linkinfo->a_linkDown = HBASTATS.LinkDown;
 609         linkinfo->a_linkMulti = HBASTATS.LinkMultiEvent;
 610 
 611         if (hba->state <= FC_LINK_DOWN) {
 612                 linkinfo->a_linkState = LNK_DOWN;
 613                 linkinfo->a_DID = port->prev_did;
 614         } else if (hba->state < FC_READY) {
 615                 linkinfo->a_linkState = LNK_DISCOVERY;
 616         } else {
 617                 linkinfo->a_linkState = LNK_READY;
 618         }
 619 
 620         if (linkinfo->a_linkState != LNK_DOWN) {
 621                 if (hba->topology == TOPOLOGY_LOOP) {
 622                         if (hba->flag & FC_FABRIC_ATTACHED) {
 623                                 linkinfo->a_topology = LNK_PUBLIC_LOOP;
 624                         } else {
 625                                 linkinfo->a_topology = LNK_LOOP;
 626                         }
 627 
 628                         linkinfo->a_alpa = port->did & 0xff;
 629                         linkinfo->a_DID = linkinfo->a_alpa;
 630                         linkinfo->a_alpaCnt = port->alpa_map[0];
 631 
 632                         if (linkinfo->a_alpaCnt > 127) {
 633                                 linkinfo->a_alpaCnt = 127;
 634                         }
 635 
 636                         bcopy((void *)&port->alpa_map[1], linkinfo->a_alpaMap,
 637                             linkinfo->a_alpaCnt);
 638                 } else {
 639                         if (port->node_count == 1) {
 640                                 linkinfo->a_topology = LNK_PT2PT;
 641                         } else {
 642                                 linkinfo->a_topology = LNK_FABRIC;
 643                         }
 644 
 645                         linkinfo->a_DID = port->did;
 646                 }
 647         }
 648 
 649         bcopy(&hba->wwpn, linkinfo->a_wwpName, 8);
 650         bcopy(&hba->wwnn, linkinfo->a_wwnName, 8);
 651 
 652         emlxs_event(port, &emlxs_link_event, bp, size);
 653 
 654         return;
 655 
 656 } /* emlxs_log_link_event() */
 657 
 658 
 659 extern void
 660 emlxs_log_dump_event(emlxs_port_t *port, uint8_t *buffer, uint32_t size)
 661 {
 662         emlxs_hba_t *hba = HBA;
 663         uint8_t *bp;
 664 
 665         /* Check if the event is being requested */
 666         if (emlxs_event_check(port, &emlxs_dump_event) == 0) {
 667 #ifdef DUMP_SUPPORT
 668                 /* Schedule a dump thread */
 669                 emlxs_dump(hba, EMLXS_DRV_DUMP, 0, 0);
 670 #endif /* DUMP_SUPPORT */
 671                 return;
 672         }
 673 
 674         if (buffer && size) {
 675                 /* Save a copy of the buffer for the event log */
 676                 if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
 677                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 678                             "%s: Unable to allocate buffer.",
 679                             emlxs_dump_event.label);
 680 
 681                         return;
 682                 }
 683 
 684                 bcopy(buffer, bp, size);
 685         } else {
 686                 bp = NULL;
 687                 size = 0;
 688         }
 689 
 690         emlxs_event(port, &emlxs_dump_event, bp, size);
 691 
 692         return;
 693 
 694 } /* emlxs_log_dump_event() */
 695 
 696 
 697 extern void
 698 emlxs_log_temp_event(emlxs_port_t *port, uint32_t type, uint32_t temp)
 699 {
 700         emlxs_hba_t *hba = HBA;
 701         uint32_t *bp;
 702         uint32_t size;
 703 
 704         /* Check if the event is being requested */
 705         if (emlxs_event_check(port, &emlxs_temp_event) == 0) {
 706 #ifdef DUMP_SUPPORT
 707                 /* Schedule a dump thread */
 708                 emlxs_dump(hba, EMLXS_TEMP_DUMP, type, temp);
 709 #endif /* DUMP_SUPPORT */
 710                 return;
 711         }
 712 
 713         size = 2 * sizeof (uint32_t);
 714 
 715         if (!(bp = (uint32_t *)kmem_alloc(size, KM_NOSLEEP))) {
 716                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 717                     "%s: Unable to allocate buffer.", emlxs_temp_event.label);
 718 
 719                 return;
 720         }
 721 
 722         bp[0] = type;
 723         bp[1] = temp;
 724 
 725         emlxs_event(port, &emlxs_temp_event, bp, size);
 726 
 727         return;
 728 
 729 } /* emlxs_log_temp_event() */
 730 
 731 
 732 
 733 extern void
 734 emlxs_log_fcoe_event(emlxs_port_t *port, menlo_init_rsp_t *init_rsp)
 735 {
 736         emlxs_hba_t *hba = HBA;
 737         uint8_t *bp;
 738         uint32_t size;
 739 
 740         /* Check if the event is being requested */
 741         if (emlxs_event_check(port, &emlxs_fcoe_event) == 0) {
 742                 return;
 743         }
 744 
 745         /* Check if this is a FCOE adapter */
 746         if (hba->model_info.device_id != PCI_DEVICE_ID_HORNET) {
 747                 return;
 748         }
 749 
 750         size = sizeof (menlo_init_rsp_t);
 751 
 752         if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
 753                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 754                     "%s: Unable to allocate buffer.", emlxs_fcoe_event.label);
 755 
 756                 return;
 757         }
 758 
 759         bcopy((uint8_t *)init_rsp, bp, size);
 760 
 761         emlxs_event(port, &emlxs_fcoe_event, bp, size);
 762 
 763         return;
 764 
 765 } /* emlxs_log_fcoe_event() */
 766 
 767 
 768 extern void
 769 emlxs_log_async_event(emlxs_port_t *port, IOCB *iocb)
 770 {
 771         uint8_t *bp;
 772         uint32_t size;
 773 
 774         if (emlxs_event_check(port, &emlxs_async_event) == 0) {
 775                 return;
 776         }
 777 
 778         /* ASYNC_STATUS_CN response size */
 779         size = 64;
 780 
 781         if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
 782                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
 783                     "%s: Unable to allocate buffer.", emlxs_async_event.label);
 784 
 785                 return;
 786         }
 787 
 788         bcopy((uint8_t *)iocb, bp, size);
 789 
 790         emlxs_event(port, &emlxs_async_event, bp, size);
 791 
 792         return;
 793 
 794 } /* emlxs_log_async_event() */
 795 
 796 
 797 extern uint32_t
 798 emlxs_get_dfc_eventinfo(emlxs_port_t *port, HBA_EVENTINFO *eventinfo,
 799     uint32_t *eventcount, uint32_t *missed)
 800 {
 801         emlxs_hba_t *hba = HBA;
 802         emlxs_event_queue_t *eventq = &EVENTQ;
 803         emlxs_event_entry_t *entry;
 804         uint32_t max_events;
 805         dfc_linkinfo_t *linkinfo;
 806         uint32_t *word;
 807         uint8_t *byte;
 808         uint8_t linkspeed;
 809         uint8_t liptype;
 810         fc_affected_id_t *aid;
 811         uint32_t events;
 812         uint8_t format;
 813 
 814         if (!eventinfo || !eventcount || !missed) {
 815                 return (DFC_ARG_NULL);
 816         }
 817 
 818         max_events = *eventcount;
 819         *eventcount = 0;
 820         *missed = 0;
 821 
 822         mutex_enter(&eventq->lock);
 823 
 824         /* Account for missed events */
 825         if (hba->hba_event.new > hba->hba_event.missed) {
 826                 hba->hba_event.new -= hba->hba_event.missed;
 827         } else {
 828                 hba->hba_event.new = 0;
 829         }
 830 
 831         *missed = hba->hba_event.missed;
 832         hba->hba_event.missed = 0;
 833 
 834         if (!hba->hba_event.new) {
 835                 hba->hba_event.last_id = eventq->next_id - 1;
 836                 mutex_exit(&eventq->lock);
 837                 return (0);
 838         }
 839 
 840         /* A new event has occurred since last acquisition */
 841 
 842         events = 0;
 843         entry = eventq->first;
 844         while (entry && (events < max_events)) {
 845 
 846                 /* Skip old events */
 847                 if (entry->id <= hba->hba_event.last_id) {
 848                         entry = entry->next;
 849                         continue;
 850                 }
 851 
 852                 /* Process this entry */
 853                 switch (entry->evt->mask) {
 854                 case EVT_LINK:
 855                         byte = (uint8_t *)entry->bp;
 856                         linkspeed = byte[0];
 857                         liptype = byte[1];
 858                         linkinfo = (dfc_linkinfo_t *)&byte[4];
 859 
 860                         if (linkinfo->a_linkState == LNK_DOWN) {
 861                                 eventinfo->EventCode =
 862                                     HBA_EVENT_LINK_DOWN;
 863                                 eventinfo->Event.Link_EventInfo.
 864                                     PortFcId = linkinfo->a_DID;
 865                                 eventinfo->Event.Link_EventInfo.
 866                                     Reserved[0] = 0;
 867                                 eventinfo->Event.Link_EventInfo.
 868                                     Reserved[1] = 0;
 869                                 eventinfo->Event.Link_EventInfo.
 870                                     Reserved[2] = 0;
 871                         } else {
 872                                 eventinfo->EventCode =
 873                                     HBA_EVENT_LINK_UP;
 874                                 eventinfo->Event.Link_EventInfo.
 875                                     PortFcId = linkinfo->a_DID;
 876 
 877                                 if ((linkinfo->a_topology ==
 878                                     LNK_PUBLIC_LOOP) ||
 879                                     (linkinfo->a_topology ==
 880                                     LNK_LOOP)) {
 881                                         eventinfo->Event.
 882                                             Link_EventInfo.
 883                                             Reserved[0] = 2;
 884                                 } else {
 885                                         eventinfo->Event.
 886                                             Link_EventInfo.
 887                                             Reserved[0] = 1;
 888                                 }
 889 
 890                                 eventinfo->Event.Link_EventInfo.
 891                                     Reserved[1] = liptype;
 892                                 eventinfo->Event.Link_EventInfo.
 893                                     Reserved[2] = linkspeed;
 894                         }
 895 
 896                         eventinfo++;
 897                         events++;
 898                         hba->hba_event.new--;
 899                         break;
 900 
 901                 case EVT_RSCN:
 902                         word = (uint32_t *)entry->bp;
 903                         eventinfo->EventCode = HBA_EVENT_RSCN;
 904                         eventinfo->Event.RSCN_EventInfo.PortFcId =
 905                             word[0] & 0xFFFFFF;
 906                         /* word[1] is the RSCN payload command */
 907 
 908                         aid = (fc_affected_id_t *)&word[2];
 909                         format = aid->aff_format;
 910 
 911                         switch (format) {
 912                         case 0: /* Port */
 913                                 eventinfo->Event.RSCN_EventInfo.
 914                                     NPortPage =
 915                                     aid->aff_d_id & 0x00ffffff;
 916                                 break;
 917 
 918                         case 1: /* Area */
 919                                 eventinfo->Event.RSCN_EventInfo.
 920                                     NPortPage =
 921                                     aid->aff_d_id & 0x00ffff00;
 922                                 break;
 923 
 924                         case 2: /* Domain */
 925                                 eventinfo->Event.RSCN_EventInfo.
 926                                     NPortPage =
 927                                     aid->aff_d_id & 0x00ff0000;
 928                                 break;
 929 
 930                         case 3: /* Network */
 931                                 eventinfo->Event.RSCN_EventInfo.
 932                                     NPortPage = 0;
 933                                 break;
 934                         }
 935 
 936                         eventinfo->Event.RSCN_EventInfo.Reserved[0] =
 937                             0;
 938                         eventinfo->Event.RSCN_EventInfo.Reserved[1] =
 939                             0;
 940 
 941                         eventinfo++;
 942                         events++;
 943                         hba->hba_event.new--;
 944                         break;
 945                 }
 946 
 947                 hba->hba_event.last_id = entry->id;
 948                 entry = entry->next;
 949         }
 950 
 951         /* Return number of events acquired */
 952         *eventcount = events;
 953 
 954         mutex_exit(&eventq->lock);
 955 
 956         return (0);
 957 
 958 } /* emlxs_get_dfc_eventinfo() */
 959 
 960 
 961 void
 962 emlxs_get_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
 963     uint32_t sleep)
 964 {
 965         emlxs_hba_t *hba = HBA;
 966         emlxs_event_queue_t *eventq = &EVENTQ;
 967         emlxs_event_entry_t *entry;
 968         uint32_t found;
 969         uint32_t mask;
 970         uint32_t i;
 971         uint32_t size = 0;
 972         uint32_t rc;
 973 
 974         if (dfc_event->dataout && dfc_event->size) {
 975                 size = dfc_event->size;
 976         }
 977         dfc_event->size = 0;
 978 
 979         /* Calculate the event index */
 980         mask = dfc_event->event;
 981         for (i = 0; i < 32; i++) {
 982                 if (mask & 0x01) {
 983                         break;
 984                 }
 985 
 986                 mask >>= 1;
 987         }
 988 
 989         if (i == 32) {
 990                 return;
 991         }
 992 
 993         mutex_enter(&eventq->lock);
 994 
 995 wait_for_event:
 996 
 997         /* Check if no new event has occurred */
 998         if (dfc_event->last_id == eventq->last_id[i]) {
 999                 if (!sleep) {
1000                         mutex_exit(&eventq->lock);
1001                         return;
1002                 }
1003 
1004                 /* While event is still active and */
1005                 /* no new event has been logged */
1006                 while ((dfc_event->event & hba->event_mask) &&
1007                     (dfc_event->last_id == eventq->last_id[i])) {
1008 
1009                         rc = cv_wait_sig(&eventq->lock_cv, &eventq->lock);
1010 
1011                         /* Check if thread was killed by kernel */
1012                         if (rc == 0) {
1013                                 dfc_event->pid = 0;
1014                                 dfc_event->event = 0;
1015                                 mutex_exit(&eventq->lock);
1016                                 return;
1017                         }
1018                 }
1019 
1020                 /* If the event is no longer registered then */
1021                 /* return immediately */
1022                 if (!(dfc_event->event & hba->event_mask)) {
1023                         mutex_exit(&eventq->lock);
1024                         return;
1025                 }
1026         }
1027 
1028         /* !!! An event has occurred since last_id !!! */
1029 
1030         /* Check if event data is not being requested */
1031         if (!size) {
1032                 /* If so, then just return the last event id */
1033                 dfc_event->last_id = eventq->last_id[i];
1034 
1035                 mutex_exit(&eventq->lock);
1036                 return;
1037         }
1038 
1039         /* !!! The requester wants the next event buffer !!! */
1040 
1041         found = 0;
1042         entry = eventq->first;
1043         while (entry) {
1044                 if ((entry->id > dfc_event->last_id) &&
1045                     (entry->evt->mask == dfc_event->event)) {
1046                         found = 1;
1047                         break;
1048                 }
1049 
1050                 entry = entry->next;
1051         }
1052 
1053         if (!found) {
1054                 /* Update last_id to the last known event */
1055                 dfc_event->last_id = eventq->last_id[i];
1056 
1057                 /* Try waiting again if we can */
1058                 goto wait_for_event;
1059         }
1060 
1061         /* !!! Next event found !!! */
1062 
1063         /* Copy the context buffer to the buffer provided */
1064         if (entry->bp && entry->size) {
1065                 if (entry->size < size) {
1066                         size = entry->size;
1067                 }
1068 
1069                 bcopy((void *)entry->bp, dfc_event->dataout, size);
1070 
1071                 /* Event has been retrieved by DFCLIB */
1072                 entry->flag |= EMLXS_DFC_EVENT_DONE;
1073 
1074                 dfc_event->size = size;
1075         }
1076 
1077         dfc_event->last_id = entry->id;
1078 
1079         mutex_exit(&eventq->lock);
1080 
1081         return;
1082 
1083 } /* emlxs_get_dfc_event() */
1084 
1085 
1086 uint32_t
1087 emlxs_kill_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event)
1088 {
1089         emlxs_hba_t *hba = HBA;
1090         emlxs_event_queue_t *eventq = &EVENTQ;
1091 
1092         mutex_enter(&eventq->lock);
1093         dfc_event->pid = 0;
1094         dfc_event->event = 0;
1095         cv_broadcast(&eventq->lock_cv);
1096         mutex_exit(&eventq->lock);
1097 
1098         return (0);
1099 
1100 } /* emlxs_kill_dfc_event() */
1101 
1102 
1103 #ifdef SAN_DIAG_SUPPORT
1104 extern void
1105 emlxs_log_sd_basic_els_event(emlxs_port_t *port, uint32_t subcat,
1106     HBA_WWN *portname, HBA_WWN *nodename)
1107 {
1108         struct sd_plogi_rcv_v0  *bp;
1109         uint32_t                size;
1110 
1111         /* Check if the event is being requested */
1112         if (emlxs_event_check(port, &emlxs_sd_els_event) == 0) {
1113                 return;
1114         }
1115 
1116         size = sizeof (struct sd_plogi_rcv_v0);
1117 
1118         if (!(bp = (struct sd_plogi_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP))) {
1119                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1120                     "%s: Unable to allocate buffer.", emlxs_sd_els_event.label);
1121 
1122                 return;
1123         }
1124 
1125         /*
1126          * we are using version field to store subtype, libdfc
1127          * will fix this up before returning data to app.
1128          */
1129         bp->sd_plogir_version = subcat;
1130         bcopy((uint8_t *)portname, (uint8_t *)&bp->sd_plogir_portname,
1131             sizeof (HBA_WWN));
1132         bcopy((uint8_t *)nodename, (uint8_t *)&bp->sd_plogir_nodename,
1133             sizeof (HBA_WWN));
1134 
1135         emlxs_event(port, &emlxs_sd_els_event, bp, size);
1136 
1137         return;
1138 
1139 } /* emlxs_log_sd_basic_els_event() */
1140 
1141 
1142 extern void
1143 emlxs_log_sd_prlo_event(emlxs_port_t *port, HBA_WWN *remoteport)
1144 {
1145         struct sd_prlo_rcv_v0   *bp;
1146         uint32_t                size;
1147 
1148         /* Check if the event is being requested */
1149         if (emlxs_event_check(port, &emlxs_sd_els_event) == 0) {
1150                 return;
1151         }
1152 
1153         size = sizeof (struct sd_prlo_rcv_v0);
1154 
1155         if (!(bp = (struct sd_prlo_rcv_v0 *)kmem_alloc(size,
1156             KM_NOSLEEP))) {
1157                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1158                     "%s PRLO: Unable to allocate buffer.",
1159                     emlxs_sd_els_event.label);
1160 
1161                 return;
1162         }
1163 
1164         /*
1165          * we are using version field to store subtype, libdfc
1166          * will fix this up before returning data to app.
1167          */
1168         bp->sd_prlor_version = SD_ELS_SUBCATEGORY_PRLO_RCV;
1169         bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_prlor_remoteport,
1170             sizeof (HBA_WWN));
1171 
1172         emlxs_event(port, &emlxs_sd_els_event, bp, size);
1173 
1174         return;
1175 
1176 } /* emlxs_log_sd_prlo_event() */
1177 
1178 
1179 extern void
1180 emlxs_log_sd_lsrjt_event(emlxs_port_t *port, HBA_WWN *remoteport,
1181     uint32_t orig_cmd, uint32_t reason, uint32_t reason_expl)
1182 {
1183         struct sd_lsrjt_rcv_v0  *bp;
1184         uint32_t                size;
1185 
1186         /* Check if the event is being requested */
1187         if (emlxs_event_check(port, &emlxs_sd_els_event) == 0) {
1188                 return;
1189         }
1190 
1191         size = sizeof (struct sd_lsrjt_rcv_v0);
1192 
1193         if (!(bp = (struct sd_lsrjt_rcv_v0 *)kmem_alloc(size,
1194             KM_NOSLEEP))) {
1195                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1196                     "%s LSRJT: Unable to allocate buffer.",
1197                     emlxs_sd_els_event.label);
1198 
1199                 return;
1200         }
1201 
1202         /*
1203          * we are using version field to store subtype, libdfc
1204          * will fix this up before returning data to app.
1205          */
1206         bp->sd_lsrjtr_version = SD_ELS_SUBCATEGORY_LSRJT_RCV;
1207         bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_lsrjtr_remoteport,
1208             sizeof (HBA_WWN));
1209         bp->sd_lsrjtr_original_cmd = orig_cmd;
1210         bp->sd_lsrjtr_reasoncode = reason;
1211         bp->sd_lsrjtr_reasoncodeexpl = reason_expl;
1212 
1213         emlxs_event(port, &emlxs_sd_els_event, bp, size);
1214 
1215         return;
1216 
1217 } /* emlxs_log_sd_lsrjt_event() */
1218 
1219 
1220 extern void
1221 emlxs_log_sd_fc_bsy_event(emlxs_port_t *port, HBA_WWN *remoteport)
1222 {
1223         struct sd_pbsy_rcv_v0   *bp;
1224         uint32_t                size;
1225 
1226         /* Check if the event is being requested */
1227         if (emlxs_event_check(port, &emlxs_sd_fabric_event) == 0) {
1228                 return;
1229         }
1230 
1231         size = sizeof (struct sd_pbsy_rcv_v0);
1232 
1233         if (!(bp = (struct sd_pbsy_rcv_v0 *)kmem_alloc(size,
1234             KM_NOSLEEP))) {
1235                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1236                     "%s BSY: Unable to allocate buffer.",
1237                     emlxs_sd_fabric_event.label);
1238 
1239                 return;
1240         }
1241 
1242         /*
1243          * we are using version field to store subtype, libdfc
1244          * will fix this up before returning data to app.
1245          */
1246         if (remoteport == NULL)
1247                 bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_FABRIC_BUSY;
1248         else
1249         {
1250                 bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_PORT_BUSY;
1251                 bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_pbsyr_rport,
1252                     sizeof (HBA_WWN));
1253         }
1254 
1255         emlxs_event(port, &emlxs_sd_fabric_event, bp, size);
1256 
1257         return;
1258 
1259 } /* emlxs_log_sd_fc_bsy_event() */
1260 
1261 
1262 extern void
1263 emlxs_log_sd_fc_rdchk_event(emlxs_port_t *port, HBA_WWN *remoteport,
1264     uint32_t lun, uint32_t opcode, uint32_t fcp_param)
1265 {
1266         struct sd_fcprdchkerr_v0        *bp;
1267         uint32_t                        size;
1268 
1269         /* Check if the event is being requested */
1270         if (emlxs_event_check(port, &emlxs_sd_fabric_event) == 0) {
1271                 return;
1272         }
1273 
1274         size = sizeof (struct sd_fcprdchkerr_v0);
1275 
1276         if (!(bp = (struct sd_fcprdchkerr_v0 *)kmem_alloc(size,
1277             KM_NOSLEEP))) {
1278                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1279                     "%s RDCHK: Unable to allocate buffer.",
1280                     emlxs_sd_fabric_event.label);
1281 
1282                 return;
1283         }
1284 
1285         /*
1286          * we are using version field to store subtype, libdfc
1287          * will fix this up before returning data to app.
1288          */
1289         bp->sd_fcprdchkerr_version = SD_FABRIC_SUBCATEGORY_FCPRDCHKERR;
1290         bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_fcprdchkerr_rport,
1291             sizeof (HBA_WWN));
1292         bp->sd_fcprdchkerr_lun = lun;
1293         bp->sd_fcprdchkerr_opcode = opcode;
1294         bp->sd_fcprdchkerr_fcpiparam = fcp_param;
1295 
1296         emlxs_event(port, &emlxs_sd_fabric_event, bp, size);
1297 
1298         return;
1299 
1300 } /* emlxs_log_sd_rdchk_event() */
1301 
1302 
1303 extern void
1304 emlxs_log_sd_scsi_event(emlxs_port_t *port, uint32_t type,
1305     HBA_WWN *remoteport, int32_t lun)
1306 {
1307         struct sd_scsi_generic_v0       *bp;
1308         uint32_t                        size;
1309 
1310         /* Check if the event is being requested */
1311         if (emlxs_event_check(port, &emlxs_sd_scsi_event) == 0) {
1312                 return;
1313         }
1314 
1315         size = sizeof (struct sd_scsi_generic_v0);
1316 
1317         if (!(bp = (struct sd_scsi_generic_v0 *)kmem_alloc(size,
1318             KM_NOSLEEP))) {
1319                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1320                     "%s: Unable to allocate buffer.",
1321                     emlxs_sd_scsi_event.label);
1322 
1323                 return;
1324         }
1325 
1326         /*
1327          * we are using version field to store subtype, libdfc
1328          * will fix this up before returning data to app.
1329          */
1330         bp->sd_scsi_generic_version = type;
1331         bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_generic_rport,
1332             sizeof (HBA_WWN));
1333         bp->sd_scsi_generic_lun = lun;
1334 
1335         emlxs_event(port, &emlxs_sd_scsi_event, bp, size);
1336 
1337         return;
1338 
1339 } /* emlxs_log_sd_scsi_event() */
1340 
1341 
1342 extern void
1343 emlxs_log_sd_scsi_check_event(emlxs_port_t *port, HBA_WWN *remoteport,
1344     uint32_t lun, uint32_t cmdcode, uint32_t sensekey,
1345     uint32_t asc, uint32_t ascq)
1346 {
1347         struct sd_scsi_checkcond_v0     *bp;
1348         uint32_t                        size;
1349 
1350         /* Check if the event is being requested */
1351         if (emlxs_event_check(port, &emlxs_sd_scsi_event) == 0) {
1352                 return;
1353         }
1354 
1355         size = sizeof (struct sd_scsi_checkcond_v0);
1356 
1357         if (!(bp = (struct sd_scsi_checkcond_v0 *)kmem_alloc(size,
1358             KM_NOSLEEP))) {
1359                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_event_debug_msg,
1360                     "%s CHECK: Unable to allocate buffer.",
1361                     emlxs_sd_scsi_event.label);
1362 
1363                 return;
1364         }
1365 
1366         /*
1367          * we are using version field to store subtype, libdfc
1368          * will fix this up before returning data to app.
1369          */
1370         bp->sd_scsi_checkcond_version = SD_SCSI_SUBCATEGORY_CHECKCONDITION;
1371         bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_checkcond_rport,
1372             sizeof (HBA_WWN));
1373         bp->sd_scsi_checkcond_lun = lun;
1374         bp->sd_scsi_checkcond_cmdcode = cmdcode;
1375         bp->sd_scsi_checkcond_sensekey = sensekey;
1376         bp->sd_scsi_checkcond_asc = asc;
1377         bp->sd_scsi_checkcond_ascq = ascq;
1378 
1379         emlxs_event(port, &emlxs_sd_scsi_event, bp, size);
1380 
1381         return;
1382 
1383 } /* emlxs_log_sd_scsi_check_event() */
1384 
1385 
1386 void
1387 emlxs_get_sd_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
1388     uint32_t sleep)
1389 {
1390         emlxs_hba_t *hba = HBA;
1391         emlxs_event_queue_t *eventq = &EVENTQ;
1392         emlxs_event_entry_t *entry;
1393         uint32_t found;
1394         uint32_t mask;
1395         uint32_t i;
1396         uint32_t size = 0;
1397         uint32_t rc;
1398 
1399         if (dfc_event->dataout && dfc_event->size) {
1400                 size = dfc_event->size;
1401         }
1402         dfc_event->size = 0;
1403 
1404         /* Calculate the event index */
1405         mask = dfc_event->event;
1406         for (i = 0; i < 32; i++) {
1407                 if (mask & 0x01) {
1408                         break;
1409                 }
1410 
1411                 mask >>= 1;
1412         }
1413 
1414         if (i == 32) {
1415                 return;
1416         }
1417 
1418         mutex_enter(&eventq->lock);
1419 
1420 wait_for_event:
1421 
1422         /* Check if no new event has ocurred */
1423         if (dfc_event->last_id == eventq->last_id[i]) {
1424                 if (!sleep) {
1425                         mutex_exit(&eventq->lock);
1426                         return;
1427                 }
1428 
1429                 /* While event is active and no new event has been logged */
1430                 while ((dfc_event->event & port->sd_event_mask) &&
1431                     (dfc_event->last_id == eventq->last_id[i])) {
1432                         rc = cv_wait_sig(&eventq->lock_cv, &eventq->lock);
1433 
1434                         /* Check if thread was killed by kernel */
1435                         if (rc == 0) {
1436                                 dfc_event->pid = 0;
1437                                 dfc_event->event = 0;
1438                                 mutex_exit(&eventq->lock);
1439                                 return;
1440                         }
1441                 }
1442 
1443                 /* If the event is no longer registered then return */
1444                 if (!(dfc_event->event & port->sd_event_mask)) {
1445                         mutex_exit(&eventq->lock);
1446                         return;
1447                 }
1448         }
1449 
1450         /* !!! An event has occurred since last_id !!! */
1451 
1452         /* Check if event data is not being requested */
1453         if (!size) {
1454                 /* If so, then just return the last event id */
1455                 dfc_event->last_id = eventq->last_id[i];
1456 
1457                 mutex_exit(&eventq->lock);
1458                 return;
1459         }
1460 
1461         /* !!! The requester wants the next event buffer !!! */
1462 
1463         found = 0;
1464         entry = eventq->first;
1465         while (entry) {
1466                 if ((entry->id > dfc_event->last_id) &&
1467                     (entry->port == (void *)port) &&
1468                     (entry->evt->mask == dfc_event->event)) {
1469                         found = 1;
1470                         break;
1471                 }
1472 
1473                 entry = entry->next;
1474         }
1475 
1476         if (!found) {
1477                 /* Update last_id to the last known event */
1478                 dfc_event->last_id = eventq->last_id[i];
1479 
1480                 /* Try waiting again if we can */
1481                 goto wait_for_event;
1482         }
1483 
1484         /* !!! Next event found !!! */
1485 
1486         /* Copy the context buffer to the buffer provided */
1487         if (entry->bp && entry->size) {
1488                 if (entry->size < size) {
1489                         size = entry->size;
1490                 }
1491 
1492                 bcopy((void *)entry->bp, dfc_event->dataout, size);
1493 
1494                 /* Event has been retrieved by SANDIAG */
1495                 entry->flag |= EMLXS_SD_EVENT_DONE;
1496 
1497                 dfc_event->size = size;
1498         }
1499 
1500         dfc_event->last_id = entry->id;
1501 
1502         mutex_exit(&eventq->lock);
1503 
1504         return;
1505 
1506 } /* emlxs_get_sd_event */
1507 #endif /* SAN_DIAG_SUPPORT */