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 usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
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 2009 Emulex.  All rights reserved.
24  * Use is subject to License terms.
25  */
26 
27 #define	DEF_MSG_STRUCT	/* Needed for emlxs_messages.h in emlxs_msg.h */
28 #include <emlxs.h>
29 
30 
31 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
32 EMLXS_MSG_DEF(EMLXS_MSG_C);
33 
34 uint32_t emlxs_log_size		= 2048;
35 uint32_t emlxs_log_debugs	= 0x7FFFFFFF;
36 uint32_t emlxs_log_notices	= 0xFFFFFFFF;
37 uint32_t emlxs_log_warnings	= 0xFFFFFFFF;
38 uint32_t emlxs_log_errors	= 0xFFFFFFFF;
39 
40 static uint32_t	emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg);
41 static uint32_t	emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg);
42 static void	emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry);
43 
44 
45 uint32_t
46 emlxs_msg_log_create(emlxs_hba_t *hba)
47 {
48 	emlxs_msg_log_t *log = &LOG;
49 	uint32_t size = sizeof (emlxs_msg_entry_t) * emlxs_log_size;
50 	char buf[40];
51 #ifdef MSI_SUPPORT
52 	ddi_intr_handle_t handle;
53 	uint32_t intr_pri;
54 	int32_t actual;
55 	uint32_t ret;
56 #endif /* MSI_SUPPORT */
57 	ddi_iblock_cookie_t iblock;
58 
59 	/* Check if log is already created */
60 	if (log->entry) {
61 		cmn_err(CE_WARN, "?%s%d: message log already created. log=%p",
62 		    DRIVER_NAME, hba->ddiinst, (void *)log);
63 		return (0);
64 	}
65 
66 	/* Clear the log */
67 	bzero(log, sizeof (emlxs_msg_log_t));
68 
69 	/* Allocate the memory needed for the log file */
70 	if (!(log->entry = (emlxs_msg_entry_t *)kmem_zalloc(size, KM_SLEEP))) {
71 		cmn_err(CE_WARN,
72 		    "?%s%d: Unable to allocate log memory. log=%p",
73 		    DRIVER_NAME, hba->ddiinst, (void *)log);
74 		return (0);
75 	}
76 
77 	/* Initialize */
78 	log->size = emlxs_log_size;
79 	log->instance = hba->ddiinst;
80 	log->start_time = emlxs_device.log_timestamp;
81 
82 	(void) sprintf(buf, "?%s%d_log_lock control variable", DRIVER_NAME,
83 	    hba->ddiinst);
84 	cv_init(&log->lock_cv, buf, CV_DRIVER, NULL);
85 
86 	(void) sprintf(buf, "?%s%d_log_lock mutex", DRIVER_NAME, hba->ddiinst);
87 
88 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
89 		/* Get the current interrupt block cookie */
90 		(void) ddi_get_iblock_cookie(hba->dip, (uint_t)EMLXS_INUMBER,
91 		    &iblock);
92 
93 		/* Create the log mutex lock */
94 		mutex_init(&log->lock, buf, MUTEX_DRIVER, (void *)iblock);
95 	}
96 #ifdef  MSI_SUPPORT
97 	else {
98 		/* Allocate a temporary interrupt handle */
99 		actual = 0;
100 		ret =
101 		    ddi_intr_alloc(hba->dip, &handle, DDI_INTR_TYPE_FIXED,
102 		    EMLXS_MSI_INUMBER, 1, &actual, DDI_INTR_ALLOC_NORMAL);
103 
104 		if (ret != DDI_SUCCESS || actual == 0) {
105 			cmn_err(CE_WARN,
106 			    "?%s%d: Unable to allocate temporary interrupt "
107 			    "handle. ret=%d actual=%d", DRIVER_NAME,
108 			    hba->ddiinst, ret, actual);
109 
110 			/* Free the log buffer */
111 			kmem_free(log->entry, size);
112 			bzero(log, sizeof (emlxs_msg_log_t));
113 
114 			return (0);
115 		}
116 
117 		/* Get the current interrupt priority */
118 		ret = ddi_intr_get_pri(handle, &intr_pri);
119 
120 		if (ret != DDI_SUCCESS) {
121 			cmn_err(CE_WARN,
122 			    "?%s%d: Unable to get interrupt priority. ret=%d",
123 			    DRIVER_NAME, hba->ddiinst, ret);
124 
125 			/* Free the log buffer */
126 			kmem_free(log->entry, size);
127 			bzero(log, sizeof (emlxs_msg_log_t));
128 
129 			return (0);
130 		}
131 
132 		/* Create the log mutex lock */
133 		mutex_init(&log->lock, buf, MUTEX_DRIVER,
134 		    (void *)((unsigned long)intr_pri));
135 
136 		/* Free the temporary handle */
137 		(void) ddi_intr_free(handle);
138 	}
139 #endif
140 
141 	return (1);
142 
143 }  /* emlxs_msg_log_create() */
144 
145 
146 uint32_t
147 emlxs_msg_log_destroy(emlxs_hba_t *hba)
148 {
149 	emlxs_msg_log_t *log = &LOG;
150 	uint32_t size;
151 	emlxs_msg_entry_t *entry;
152 	uint32_t i;
153 
154 	/* Check if log is already destroyed */
155 	if (!log->entry) {
156 		cmn_err(CE_WARN,
157 		    "?%s%d: message log already destroyed. log=%p",
158 		    DRIVER_NAME, hba->ddiinst, (void *)log);
159 
160 		return (1);
161 	}
162 
163 	/* If events are being logged there might be */
164 	/* threads waiting so release them */
165 	if (hba->log_events) {
166 		mutex_enter(&log->lock);
167 		hba->log_events = 0;
168 		cv_broadcast(&log->lock_cv);
169 		mutex_exit(&log->lock);
170 
171 		DELAYMS(1);
172 	}
173 
174 	/* Destroy the lock */
175 	mutex_destroy(&log->lock);
176 	cv_destroy(&log->lock_cv);
177 
178 	/* Free the context buffers */
179 	for (i = 0; i < log->size; i++) {
180 		entry = &log->entry[i];
181 
182 		if (entry->bp && entry->size) {
183 			kmem_free(entry->bp, entry->size);
184 		}
185 	}
186 
187 	/* Free the log buffer */
188 	size = sizeof (emlxs_msg_entry_t) * log->size;
189 	kmem_free(log->entry, size);
190 
191 	/* Clear the log */
192 	bzero(log, sizeof (emlxs_msg_log_t));
193 
194 	return (1);
195 
196 }  /* emlxs_msg_log_destroy() */
197 
198 
199 uint32_t
200 emlxs_msg_log(emlxs_port_t *port, const uint32_t fileno, const uint32_t line,
201     void *bp, uint32_t size, emlxs_msg_t *msg, char *buffer)
202 {
203 	emlxs_hba_t *hba = HBA;
204 	emlxs_msg_entry_t *entry;
205 	emlxs_msg_entry_t *entry2;
206 	clock_t time;
207 	emlxs_msg_log_t *log;
208 	uint32_t last;
209 	uint32_t mask;
210 	emlxs_msg_t *msg2;
211 	uint32_t rxid = 0;
212 	uint32_t i;
213 
214 	/* Get the log file for this instance */
215 	log = &LOG;
216 
217 	/* Check if log is initialized */
218 	if (log->entry == NULL) {
219 
220 		if (port->vpi == 0) {
221 			cmn_err(CE_WARN,
222 			    "?%s%d: message log not created. log=%p",
223 			    DRIVER_NAME, hba->ddiinst, (void *)log);
224 		} else {
225 			cmn_err(CE_WARN,
226 			    "?%s%d.%d: message log not created. log=%p",
227 			    DRIVER_NAME, hba->ddiinst, port->vpi,
228 			    (void *)log);
229 		}
230 
231 		if (bp && size) {
232 			kmem_free(bp, size);
233 		}
234 
235 		return (1);
236 	}
237 
238 	mutex_enter(&log->lock);
239 
240 	/* Get the pointer to the last log entry */
241 	if (log->next == 0) {
242 		last = log->size - 1;
243 	} else {
244 		last = log->next - 1;
245 	}
246 	entry = &log->entry[last];
247 
248 	/* Check if this matches the last message */
249 	if ((entry->instance == log->instance) &&
250 	    (entry->vpi == port->vpi) &&
251 	    (entry->fileno == fileno) &&
252 	    (entry->line == line) &&
253 	    (entry->bp == bp) &&
254 	    (entry->size == size) &&
255 	    (entry->msg == msg) &&
256 	    (strcmp(entry->buffer, buffer) == 0)) {
257 		/* If the same message is being logged then increment */
258 		log->repeat++;
259 
260 		mutex_exit(&log->lock);
261 
262 		return (0);
263 	} else if (log->repeat) {
264 		/* Get the pointer to the next log entry */
265 		entry2 = &log->entry[log->next];
266 
267 		/* Increment and check the next entry index */
268 		if (++(log->next) >= log->size) {
269 			log->next = 0;
270 		}
271 
272 		switch (entry->msg->level) {
273 		case EMLXS_DEBUG:
274 			msg2 = &emlxs_debug_msg;
275 			break;
276 
277 		case EMLXS_NOTICE:
278 			msg2 = &emlxs_notice_msg;
279 			break;
280 
281 		case EMLXS_WARNING:
282 			msg2 = &emlxs_warning_msg;
283 			break;
284 
285 		case EMLXS_ERROR:
286 			msg2 = &emlxs_error_msg;
287 			break;
288 
289 		case EMLXS_PANIC:
290 			msg2 = &emlxs_panic_msg;
291 			break;
292 
293 		case EMLXS_EVENT:
294 			msg2 = &emlxs_event_msg;
295 			break;
296 		}
297 
298 		/* Check if we are about to overwrite an event entry */
299 		if (entry2->msg && (entry2->msg->level == EMLXS_EVENT)) {
300 			/* Check if this event has not been acquired */
301 			if (log->count > (hba->hba_event.last_id + log->size)) {
302 				hba->hba_event.missed++;
303 
304 				if ((entry2->msg->mask == EVT_CT) &&
305 				    !(entry2->flag & EMLX_EVENT_DONE)) {
306 					/* Abort exchange */
307 					rxid = *((uint32_t *)entry2->bp);
308 				}
309 			}
310 		}
311 
312 		/* Free the old context buffer since we are about to erase it */
313 		if (entry2->bp && entry2->size) {
314 			kmem_free(entry2->bp, entry2->size);
315 		}
316 
317 		/* Initialize */
318 		entry2->id = log->count++;
319 		entry2->fileno = entry->fileno;
320 		entry2->line = entry->line;
321 		entry2->bp = 0;
322 		entry2->size = 0;
323 		entry2->msg = msg2;
324 		entry2->instance = log->instance;
325 		entry2->vpi = port->vpi;
326 		entry2->flag = 0;
327 
328 		/* Save the additional info buffer */
329 		(void) sprintf(entry2->buffer,
330 		    "Last message repeated %d time(s).",
331 		    log->repeat);
332 
333 		/* Set the entry time stamp */
334 		(void) drv_getparm(LBOLT, &time);
335 		entry2->time = time - log->start_time;
336 
337 		log->repeat = 0;
338 	}
339 
340 	/* Get the pointer to the next log entry */
341 	entry = &log->entry[log->next];
342 
343 	/* Increment and check the next entry index */
344 	if (++(log->next) >= log->size) {
345 		log->next = 0;
346 	}
347 
348 	/* Check if we are about to overwrite an event entry */
349 	if (entry->msg && (entry->msg->level == EMLXS_EVENT)) {
350 		/* Check if this event has not been acquired */
351 		if (log->count > (hba->hba_event.last_id + log->size)) {
352 			hba->hba_event.missed++;
353 
354 			if ((entry->msg->mask == EVT_CT) &&
355 			    !(entry->flag & EMLX_EVENT_DONE)) {
356 
357 				/* Abort exchange */
358 				rxid = *((uint32_t *)entry->bp);
359 			}
360 		}
361 	}
362 
363 	/* Free the old context buffer since we are about to erase it */
364 	if (entry->bp && entry->size) {
365 		kmem_free(entry->bp, entry->size);
366 	}
367 
368 	/* Initialize */
369 	entry->id = log->count++;
370 	entry->fileno = fileno;
371 	entry->line = line;
372 	entry->bp = bp;
373 	entry->size = size;
374 	entry->msg = msg;
375 	entry->instance = log->instance;
376 	entry->vpi = port->vpi;
377 	entry->flag = 0;
378 
379 	/* Save the additional info buffer */
380 	(void) strncpy(entry->buffer, buffer, (MAX_LOG_INFO_LENGTH - 1));
381 	entry->buffer[MAX_LOG_INFO_LENGTH - 1] = 0;
382 
383 	/* Set the entry time stamp */
384 	(void) drv_getparm(LBOLT, &time);
385 	entry->time = time - log->start_time;
386 
387 	/* Check for a new event */
388 	if (msg->level == EMLXS_EVENT) {
389 		/* Update the event id */
390 		mask = msg->mask;
391 		for (i = 0; i < 32; i++) {
392 			if (mask & 0x01) {
393 				hba->hba_event.new++;
394 				log->event_id[i] = entry->id;
395 				cv_broadcast(&log->lock_cv);
396 				break;
397 			}
398 
399 			mask >>= 1;
400 		}
401 	}
402 
403 	mutex_exit(&log->lock);
404 
405 	if (rxid) {
406 		emlxs_thread_spawn(hba, emlxs_abort_ct_exchange,
407 		    (void *)port, (void *)((unsigned long)rxid));
408 	}
409 
410 	return (0);
411 
412 }  /* emlxs_msg_log() */
413 
414 
415 static uint32_t
416 emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg)
417 {
418 	emlxs_hba_t *hba = HBA;
419 
420 	switch (msg->level) {
421 	case EMLXS_DEBUG:
422 		if (msg->mask & emlxs_log_debugs) {
423 			return (1);
424 		}
425 		break;
426 
427 	case EMLXS_NOTICE:
428 		if (msg->mask & emlxs_log_notices) {
429 			return (1);
430 		}
431 		break;
432 
433 	case EMLXS_WARNING:
434 		if (msg->mask & emlxs_log_warnings) {
435 			return (1);
436 		}
437 		break;
438 
439 	case EMLXS_ERROR:
440 		if (msg->mask & emlxs_log_errors) {
441 			return (1);
442 		}
443 		break;
444 
445 	case EMLXS_EVENT:
446 		if (msg->mask & hba->log_events) {
447 			return (1);
448 		}
449 #ifdef SAN_DIAG_SUPPORT
450 		if (msg->mask & port->sd_reg_events) {
451 			return (1);
452 		}
453 #endif /* SAN_DIAG_SUPPORT */
454 		break;
455 
456 	case EMLXS_PANIC:
457 		return (1);
458 	}
459 
460 	return (0);
461 
462 }  /* emlxs_msg_log_check() */
463 
464 
465 static uint32_t
466 emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg)
467 {
468 	emlxs_hba_t *hba = HBA;
469 	emlxs_config_t *cfg;
470 	uint32_t rval = 0;
471 
472 	cfg = &CFG;
473 
474 	switch (msg->level) {
475 	case EMLXS_DEBUG:
476 		if (msg->mask & cfg[CFG_CONSOLE_DEBUGS].current) {
477 			rval |= 2;
478 		}
479 
480 		if (msg->mask & cfg[CFG_LOG_DEBUGS].current) {
481 			rval |= 1;
482 		}
483 
484 		break;
485 
486 	case EMLXS_NOTICE:
487 		if (msg->mask & cfg[CFG_CONSOLE_NOTICES].current) {
488 			rval |= 2;
489 		}
490 
491 		if (msg->mask & cfg[CFG_LOG_NOTICES].current) {
492 			rval |= 1;
493 		}
494 
495 		break;
496 
497 	case EMLXS_WARNING:
498 		if (msg->mask & cfg[CFG_CONSOLE_WARNINGS].current) {
499 			rval |= 2;
500 		}
501 
502 		if (msg->mask & cfg[CFG_LOG_WARNINGS].current) {
503 			rval |= 1;
504 		}
505 
506 		break;
507 
508 	case EMLXS_ERROR:
509 		if (msg->mask & cfg[CFG_CONSOLE_ERRORS].current) {
510 			rval |= 2;
511 		}
512 
513 		if (msg->mask & cfg[CFG_LOG_ERRORS].current) {
514 			rval |= 1;
515 		}
516 		break;
517 
518 	case EMLXS_EVENT:
519 		/* Only print an event if it is being logged internally */
520 		if (msg->mask & hba->log_events) {
521 			if (msg->mask & cfg[CFG_CONSOLE_EVENTS].current) {
522 				rval |= 2;
523 			}
524 
525 			if (msg->mask & cfg[CFG_LOG_EVENTS].current) {
526 				rval |= 1;
527 			}
528 		}
529 		break;
530 
531 	case EMLXS_PANIC:
532 	default:
533 		rval |= 1;
534 
535 	}
536 
537 	return (rval);
538 
539 }  /* emlxs_msg_print_check() */
540 
541 
542 void
543 emlxs_msg_printf(emlxs_port_t *port, const uint32_t fileno,
544     const uint32_t line, void *bp, uint32_t size, emlxs_msg_t *msg,
545     const char *fmt, ...)
546 {
547 	emlxs_hba_t *hba = HBA;
548 	va_list valist;
549 	char va_str[256];
550 	char msg_str[512];
551 	char *level;
552 	int32_t cmn_level;
553 	uint32_t rval;
554 	uint32_t logged;
555 	char driver[32];
556 
557 	va_str[0] = 0;
558 
559 	if (fmt) {
560 		va_start(valist, fmt);
561 		(void) vsprintf(va_str, fmt, valist);
562 		va_end(valist);
563 	}
564 
565 #ifdef FMA_SUPPORT
566 	/*
567 	 * Don't post fault event or/and error event to fmd
568 	 * if physical port was not bounded yet.
569 	 */
570 	if (msg->fm_ereport_code) {
571 		emlxs_fm_ereport(hba, msg->fm_ereport_code);
572 	}
573 
574 	if (msg->fm_impact_code) {
575 		emlxs_fm_service_impact(hba, msg->fm_impact_code);
576 	}
577 #endif	/* FMA_SUPPORT */
578 
579 	/* Check if msg should be logged */
580 	if ((logged = emlxs_msg_log_check(port, msg))) {
581 		/* Log the message */
582 		if (emlxs_msg_log(port, fileno, line, bp, size, msg, va_str)) {
583 			return;
584 		}
585 	}
586 
587 	/* Check if msg should be printed */
588 	if (rval = emlxs_msg_print_check(port, msg)) {
589 		cmn_level = CE_CONT;
590 
591 		switch (msg->level) {
592 		case EMLXS_DEBUG:
593 			level = "  DEBUG";
594 			break;
595 
596 		case EMLXS_NOTICE:
597 			level = " NOTICE";
598 			break;
599 
600 		case EMLXS_WARNING:
601 			level = "WARNING";
602 			break;
603 
604 		case EMLXS_ERROR:
605 			level = "  ERROR";
606 			break;
607 
608 		case EMLXS_PANIC:
609 			cmn_level = CE_PANIC;
610 			level = "  PANIC";
611 			break;
612 
613 		case EMLXS_EVENT:
614 			level = "  EVENT";
615 			break;
616 
617 		default:
618 			level = "UNKNOWN";
619 			break;
620 		}
621 
622 		if (port->vpi == 0) {
623 			(void) sprintf(driver, "%s%d", DRIVER_NAME,
624 			    hba->ddiinst);
625 		} else {
626 			(void) sprintf(driver, "%s%d.%d", DRIVER_NAME,
627 			    hba->ddiinst, port->vpi);
628 		}
629 
630 		/* Generate the message string */
631 		if (msg->buffer[0] != 0) {
632 			if (va_str[0] != 0) {
633 				(void) sprintf(msg_str,
634 				    "[%2X.%04X]%s:%7s:%4d: %s (%s)\n", fileno,
635 				    line, driver, level, msg->id, msg->buffer,
636 				    va_str);
637 			} else {
638 				(void) sprintf(msg_str,
639 				    "[%2X.%04X]%s:%7s:%4d: %s\n",
640 				    fileno, line, driver, level, msg->id,
641 				    msg->buffer);
642 			}
643 		} else {
644 			if (va_str[0] != 0) {
645 				(void) sprintf(msg_str,
646 				    "[%2X.%04X]%s:%7s:%4d: (%s)\n", fileno,
647 				    line, driver, level, msg->id, va_str);
648 			} else {
649 				(void) sprintf(msg_str,
650 				    "[%2X.%04X]%s:%7s:%4d\n",
651 				    fileno, line, driver, level, msg->id);
652 			}
653 		}
654 
655 		switch (rval) {
656 		case 1:	/* MESSAGE LOG ONLY */
657 			/* Message log & console, if system booted in */
658 			/* verbose mode (CE_CONT only) */
659 			cmn_err(cmn_level, "?%s", msg_str);
660 			break;
661 
662 		case 2:	/* CONSOLE ONLY */
663 			cmn_err(cmn_level, "^%s", msg_str);
664 			break;
665 
666 		case 3:	/* CONSOLE AND MESSAGE LOG */
667 			cmn_err(cmn_level, "%s", msg_str);
668 			break;
669 
670 		}
671 
672 	}
673 
674 	/* If message was not logged, then free any context buffer provided */
675 	if (!logged && bp && size) {
676 		kmem_free(bp, size);
677 	}
678 
679 	return;
680 
681 }  /* emlxs_msg_printf() */
682 
683 
684 uint32_t
685 emlxs_msg_log_get(emlxs_hba_t *hba, emlxs_log_req_t *req,
686     emlxs_log_resp_t *resp)
687 {
688 	emlxs_msg_log_t *log;
689 	uint32_t first;
690 	uint32_t last;
691 	uint32_t count;
692 	uint32_t index;
693 	uint32_t i;
694 	char *resp_buf;
695 
696 	log = &LOG;
697 
698 	mutex_enter(&log->lock);
699 
700 	/* Check if buffer is empty */
701 	if (log->count == 0) {
702 		/* If so, exit now */
703 		resp->first = 0;
704 		resp->last = 0;
705 		resp->count = 0;
706 		mutex_exit(&log->lock);
707 
708 		return (1);
709 	}
710 
711 	/* Get current log entry ranges */
712 
713 	/* Get last entry id saved */
714 	last = log->count - 1;
715 
716 	/* Check if request is out of current range */
717 	if (req->first > last) {
718 		/* if so, exit now */
719 		resp->first = last;
720 		resp->last = last;
721 		resp->count = 0;
722 		mutex_exit(&log->lock);
723 
724 		return (0);
725 	}
726 
727 	/* Get oldest entry id and its index */
728 
729 	/* Check if buffer has already been filled once */
730 	if (log->count >= log->size) {
731 		first = log->count - log->size;
732 		index = log->next;
733 	} else {	/* Buffer not yet filled */
734 
735 		first = 0;
736 		index = 0;
737 	}
738 
739 	/* Check if requested first message is greater than actual. */
740 	/* If so, adjust for it.  */
741 	if (req->first > first) {
742 		/* Adjust entry index to first requested message */
743 		index += (req->first - first);
744 		if (index >= log->size) {
745 			index -= log->size;
746 		}
747 
748 		first = req->first;
749 	}
750 
751 	/* Get the total number of messages available for return */
752 	count = last - first + 1;
753 
754 	/* Check if requested count is less than actual.  If so, adjust it. */
755 	if (req->count < count) {
756 		count = req->count;
757 	}
758 
759 	/* Fill in the response header */
760 	resp->count = count;
761 	resp->first = first;
762 	resp->last = last;
763 
764 	/* Fill the response buffer */
765 	resp_buf = (char *)resp + sizeof (emlxs_log_resp_t);
766 	for (i = 0; i < count; i++) {
767 		emlxs_msg_sprintf(resp_buf, &log->entry[index]);
768 
769 		/* Increment the response buffer */
770 		resp_buf += MAX_LOG_MSG_LENGTH;
771 
772 		/* Increment index */
773 		if (++index >= log->size) {
774 			index = 0;
775 		}
776 	}
777 
778 	mutex_exit(&log->lock);
779 
780 	return (1);
781 
782 }  /* emlxs_msg_log_get() */
783 
784 
785 
786 static void
787 emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry)
788 {
789 	char *level;
790 	emlxs_msg_t *msg;
791 	uint32_t secs;
792 	uint32_t hsecs;
793 	char buf[256];
794 	uint32_t buflen;
795 	char driver[32];
796 
797 	msg = entry->msg;
798 	hsecs = (entry->time % 100);
799 	secs = entry->time / 100;
800 
801 	switch (msg->level) {
802 	case EMLXS_DEBUG:
803 		level = "  DEBUG";
804 		break;
805 
806 	case EMLXS_NOTICE:
807 		level = " NOTICE";
808 		break;
809 
810 	case EMLXS_WARNING:
811 		level = "WARNING";
812 		break;
813 
814 	case EMLXS_ERROR:
815 		level = "  ERROR";
816 		break;
817 
818 	case EMLXS_PANIC:
819 		level = "  PANIC";
820 		break;
821 
822 	case EMLXS_EVENT:
823 		level = "  EVENT";
824 		break;
825 
826 	default:
827 		level = "UNKNOWN";
828 		break;
829 	}
830 
831 	if (entry->vpi == 0) {
832 		(void) sprintf(driver, "%s%d", DRIVER_NAME, entry->instance);
833 	} else {
834 		(void) sprintf(driver, "%s%d.%d", DRIVER_NAME, entry->instance,
835 		    entry->vpi);
836 	}
837 
838 	/* Generate the message string */
839 	if (msg->buffer[0] != 0) {
840 		if (entry->buffer[0] != 0) {
841 			(void) sprintf(buf,
842 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s (%s)\n",
843 			    secs, hsecs, entry->id, entry->fileno,
844 			    entry->line, driver, level, msg->id, msg->buffer,
845 			    entry->buffer);
846 
847 		} else {
848 			(void) sprintf(buf,
849 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s\n", secs,
850 			    hsecs, entry->id, entry->fileno, entry->line,
851 			    driver, level, msg->id, msg->buffer);
852 		}
853 	} else {
854 		if (entry->buffer[0] != 0) {
855 			(void) sprintf(buf,
856 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: (%s)\n",
857 			    secs, hsecs, entry->id, entry->fileno,
858 			    entry->line, driver, level, msg->id,
859 			    entry->buffer);
860 		} else {
861 			(void) sprintf(buf,
862 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d\n",
863 			    secs, hsecs, entry->id, entry->fileno,
864 			    entry->line, driver, level, msg->id);
865 		}
866 	}
867 
868 	bzero(buffer, MAX_LOG_MSG_LENGTH);
869 	buflen = strlen(buf);
870 
871 	if (buflen > (MAX_LOG_MSG_LENGTH - 1)) {
872 		(void) strncpy(buffer, buf, (MAX_LOG_MSG_LENGTH - 2));
873 		buffer[MAX_LOG_MSG_LENGTH - 2] = '\n';
874 	} else {
875 		(void) strncpy(buffer, buf, buflen);
876 	}
877 
878 	return;
879 
880 }  /* emlxs_msg_sprintf() */
881 
882 
883 
884 
885 void
886 emlxs_log_rscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size)
887 {
888 #ifdef DFC_SUPPORT
889 	emlxs_hba_t *hba = HBA;
890 	uint8_t *bp;
891 	uint32_t *ptr;
892 
893 	/* Check if the event is being requested */
894 	if (!(hba->log_events & EVT_RSCN)) {
895 		return;
896 	}
897 
898 	if (size > MAX_RSCN_PAYLOAD) {
899 		size = MAX_RSCN_PAYLOAD;
900 	}
901 
902 	size += sizeof (uint32_t);
903 
904 	/* Save a copy of the payload for the event log */
905 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
906 		return;
907 	}
908 
909 
910 	/*
911 	 * Buffer Format:
912 	 *	word[0] = DID of the RSCN
913 	 *	word[1] = RSCN Payload
914 	 */
915 	ptr = (uint32_t *)bp;
916 	*ptr++ = port->did;
917 	bcopy(payload, (char *)ptr, (size - sizeof (uint32_t)));
918 
919 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_rscn_event,
920 	    "bp=%p size=%d", bp, size);
921 
922 #endif /* DFC_SUPPORT */
923 	return;
924 
925 }  /* emlxs_log_rscn_event() */
926 
927 
928 void
929 emlxs_log_vportrscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size)
930 {
931 #ifdef DFC_SUPPORT
932 	emlxs_hba_t *hba = HBA;
933 	uint8_t *bp;
934 	uint8_t *ptr;
935 
936 	/* Check if the event is being requested */
937 	if (!(hba->log_events & EVT_VPORTRSCN)) {
938 		return;
939 	}
940 
941 	if (size > MAX_RSCN_PAYLOAD) {
942 		size = MAX_RSCN_PAYLOAD;
943 	}
944 
945 	/* Save a copy of the payload for the event log */
946 	if (!(bp =
947 	    (uint8_t *)kmem_alloc(size + sizeof (NAME_TYPE), KM_NOSLEEP))) {
948 		return;
949 	}
950 
951 
952 	/*
953 	 * Buffer Format:
954 	 *	word[0 - 4] = WWPN of the RSCN
955 	 *	word[5] = RSCN Payload
956 	 */
957 	ptr = bp;
958 	bcopy(&port->wwpn, ptr, sizeof (NAME_TYPE));
959 	ptr += sizeof (NAME_TYPE);
960 	bcopy(payload, ptr, size);
961 
962 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size + sizeof (NAME_TYPE),
963 	    &emlxs_vportrscn_event, "bp=%p size=%d", bp, size);
964 
965 #endif /* DFC_SUPPORT */
966 	return;
967 
968 }  /* emlxs_log_vportrscn_event() */
969 
970 
971 uint32_t
972 emlxs_log_ct_event(emlxs_port_t *port, uint8_t *payload, uint32_t size,
973     uint32_t rxid)
974 {
975 #ifdef DFC_SUPPORT
976 	emlxs_hba_t *hba = HBA;
977 	uint8_t *bp;
978 	uint32_t *ptr;
979 
980 	/* Check if the event is being requested */
981 	if (!(hba->log_events & EVT_CT)) {
982 		return (1);
983 	}
984 
985 	if (size > MAX_CT_PAYLOAD) {
986 		size = MAX_CT_PAYLOAD;
987 	}
988 
989 	size += sizeof (uint32_t);
990 
991 	/* Save a copy of the payload for the event log */
992 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
993 		return (1);
994 	}
995 
996 	/*
997 	 * Buffer Format:
998 	 *	word[0] = RXID tag for outgoing reply to this CT request
999 	 *	word[1] = CT Payload
1000 	 */
1001 	ptr = (uint32_t *)bp;
1002 	*ptr++ = rxid;
1003 
1004 	bcopy(payload, (char *)ptr, (size - sizeof (uint32_t)));
1005 
1006 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_ct_event,
1007 	    "bp=%p size=%d rxid=%x", bp, size, rxid);
1008 
1009 
1010 	return (0);
1011 #else
1012 
1013 	return (1);
1014 
1015 #endif /* DFC_SUPPORT */
1016 
1017 }  /* emlxs_log_ct_event() */
1018 
1019 
1020 void
1021 emlxs_log_link_event(emlxs_port_t *port)
1022 {
1023 #ifdef DFC_SUPPORT
1024 	emlxs_hba_t *hba = HBA;
1025 	uint8_t *bp;
1026 	dfc_linkinfo_t *linkinfo;
1027 	uint8_t *byte;
1028 	uint8_t *linkspeed;
1029 	uint8_t *liptype;
1030 	uint8_t *resv1;
1031 	uint8_t *resv2;
1032 	uint32_t size;
1033 
1034 	/* Check if the event is being requested */
1035 	/*
1036 	 * if(!(hba->log_events & EVT_LINK)) { return; }
1037 	 */
1038 	size = sizeof (dfc_linkinfo_t) + sizeof (uint32_t);
1039 
1040 	/* Save a copy of the buffer for the event log */
1041 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
1042 		return;
1043 	}
1044 
1045 	/*
1046 	 * Buffer Format:
1047 	 *	word[0] = Linkspeed:8
1048 	 *	word[0] = LIP_type:8
1049 	 *	word[0] = resv1:8
1050 	 *	word[0] = resv2:8
1051 	 *	word[1] = dfc_linkinfo_t data
1052 	 */
1053 	byte = (uint8_t *)bp;
1054 	linkspeed = &byte[0];
1055 	liptype = &byte[1];
1056 	resv1 = &byte[2];
1057 	resv2 = &byte[3];
1058 	linkinfo = (dfc_linkinfo_t *)&byte[4];
1059 
1060 	*resv1 = 0;
1061 	*resv2 = 0;
1062 
1063 	if (hba->state <= FC_LINK_DOWN) {
1064 		*linkspeed = 0;
1065 		*liptype = 0;
1066 	} else {
1067 		/* Set linkspeed */
1068 		if (hba->linkspeed == LA_2GHZ_LINK) {
1069 			*linkspeed = HBA_PORTSPEED_2GBIT;
1070 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
1071 			*linkspeed = HBA_PORTSPEED_4GBIT;
1072 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
1073 			*linkspeed = HBA_PORTSPEED_8GBIT;
1074 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
1075 			*linkspeed = HBA_PORTSPEED_10GBIT;
1076 		} else {
1077 			*linkspeed = HBA_PORTSPEED_1GBIT;
1078 		}
1079 
1080 		/* Set LIP type */
1081 		*liptype = port->lip_type;
1082 	}
1083 
1084 	bzero(linkinfo, sizeof (dfc_linkinfo_t));
1085 
1086 	linkinfo->a_linkEventTag = hba->link_event_tag;
1087 	linkinfo->a_linkUp = HBASTATS.LinkUp;
1088 	linkinfo->a_linkDown = HBASTATS.LinkDown;
1089 	linkinfo->a_linkMulti = HBASTATS.LinkMultiEvent;
1090 
1091 	if (hba->state <= FC_LINK_DOWN) {
1092 		linkinfo->a_linkState = LNK_DOWN;
1093 		linkinfo->a_DID = port->prev_did;
1094 	} else if (hba->state < FC_READY) {
1095 		linkinfo->a_linkState = LNK_DISCOVERY;
1096 	} else {
1097 		linkinfo->a_linkState = LNK_READY;
1098 	}
1099 
1100 	if (linkinfo->a_linkState != LNK_DOWN) {
1101 		if (hba->topology == TOPOLOGY_LOOP) {
1102 			if (hba->flag & FC_FABRIC_ATTACHED) {
1103 				linkinfo->a_topology = LNK_PUBLIC_LOOP;
1104 			} else {
1105 				linkinfo->a_topology = LNK_LOOP;
1106 			}
1107 
1108 			linkinfo->a_alpa = port->did & 0xff;
1109 			linkinfo->a_DID = linkinfo->a_alpa;
1110 			linkinfo->a_alpaCnt = port->alpa_map[0];
1111 
1112 			if (linkinfo->a_alpaCnt > 127) {
1113 				linkinfo->a_alpaCnt = 127;
1114 			}
1115 
1116 			bcopy((void *)&port->alpa_map[1], linkinfo->a_alpaMap,
1117 			    linkinfo->a_alpaCnt);
1118 		} else {
1119 			if (port->node_count == 1) {
1120 				linkinfo->a_topology = LNK_PT2PT;
1121 			} else {
1122 				linkinfo->a_topology = LNK_FABRIC;
1123 			}
1124 
1125 			linkinfo->a_DID = port->did;
1126 		}
1127 	}
1128 
1129 	bcopy(&hba->wwpn, linkinfo->a_wwpName, 8);
1130 	bcopy(&hba->wwnn, linkinfo->a_wwnName, 8);
1131 
1132 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_link_event,
1133 	    "bp=%p size=%d tag=%x", bp, size, hba->link_event_tag);
1134 
1135 #endif /* DFC_SUPPORT */
1136 
1137 	return;
1138 
1139 }  /* emlxs_log_link_event() */
1140 
1141 
1142 void
1143 emlxs_log_dump_event(emlxs_port_t *port, uint8_t *buffer, uint32_t size)
1144 {
1145 #ifdef DFC_SUPPORT
1146 	emlxs_hba_t *hba = HBA;
1147 	uint8_t *bp;
1148 
1149 	/* Check if the event is being requested */
1150 	if (!(hba->log_events & EVT_DUMP)) {
1151 #ifdef DUMP_SUPPORT
1152 		/* Schedule a dump thread */
1153 		emlxs_dump(hba, EMLXS_DRV_DUMP, 0, 0);
1154 #endif /* DUMP_SUPPORT */
1155 		return;
1156 	}
1157 
1158 	if (buffer && size) {
1159 		/* Save a copy of the buffer for the event log */
1160 		if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
1161 			return;
1162 		}
1163 
1164 		bcopy(buffer, bp, size);
1165 	} else {
1166 		bp = NULL;
1167 		size = 0;
1168 	}
1169 
1170 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_dump_event,
1171 	    "bp=%p size=%d", bp, size);
1172 #else
1173 
1174 #ifdef DUMP_SUPPORT
1175 	/* Schedule a dump thread */
1176 	emlxs_dump(hba, EMLXS_DRV_DUMP, 0, 0);
1177 #endif /* DUMP_SUPPORT */
1178 
1179 #endif /* DFC_SUPPORT */
1180 
1181 	return;
1182 
1183 }  /* emlxs_log_dump_event() */
1184 
1185 
1186 extern void
1187 emlxs_log_temp_event(emlxs_port_t *port, uint32_t type, uint32_t temp)
1188 {
1189 	emlxs_hba_t *hba = HBA;
1190 
1191 #ifdef DFC_SUPPORT
1192 	uint32_t *bp;
1193 	uint32_t size;
1194 
1195 	/* Check if the event is being requested */
1196 	if (!(hba->log_events & EVT_TEMP)) {
1197 #ifdef DUMP_SUPPORT
1198 		/* Schedule a dump thread */
1199 		emlxs_dump(hba, EMLXS_TEMP_DUMP, type, temp);
1200 #endif /* DUMP_SUPPORT */
1201 		return;
1202 	}
1203 
1204 	size = 2 * sizeof (uint32_t);
1205 
1206 	if (!(bp = (uint32_t *)kmem_alloc(size, KM_NOSLEEP))) {
1207 		return;
1208 	}
1209 
1210 	bp[0] = type;
1211 	bp[1] = temp;
1212 
1213 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_temp_event,
1214 	    "type=%x temp=%d bp=%p size=%d", type, temp, bp, size);
1215 
1216 #else /* !DFC_SUPPORT */
1217 
1218 #ifdef DUMP_SUPPORT
1219 	/* Schedule a dump thread */
1220 	emlxs_dump(hba, EMLXS_TEMP_DUMP, type, temp);
1221 #endif /* DUMP_SUPPORT */
1222 
1223 #endif /* DFC_SUPPORT */
1224 
1225 	return;
1226 
1227 }  /* emlxs_log_temp_event() */
1228 
1229 
1230 
1231 extern void
1232 emlxs_log_fcoe_event(emlxs_port_t *port, menlo_init_rsp_t *init_rsp)
1233 {
1234 #ifdef DFC_SUPPORT
1235 	emlxs_hba_t *hba = HBA;
1236 	uint8_t *bp;
1237 	uint32_t size;
1238 
1239 	/* Check if the event is being requested */
1240 	if (!(hba->log_events & EVT_FCOE)) {
1241 		return;
1242 	}
1243 
1244 	/* Check if this is a FCOE adapter */
1245 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
1246 		return;
1247 	}
1248 
1249 	size = sizeof (menlo_init_rsp_t);
1250 
1251 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
1252 		return;
1253 	}
1254 
1255 	bcopy((uint8_t *)init_rsp, bp, size);
1256 
1257 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_fcoe_event,
1258 	    "bp=%p size=%d", bp, size);
1259 #endif /* DFC_SUPPORT */
1260 
1261 	return;
1262 
1263 }  /* emlxs_log_fcoe_event() */
1264 
1265 
1266 #ifdef SAN_DIAG_SUPPORT
1267 extern void
1268 emlxs_log_sd_basic_els_event(emlxs_port_t *port, uint32_t subcat,
1269     HBA_WWN *portname, HBA_WWN *nodename)
1270 {
1271 	struct sd_plogi_rcv_v0	*bp;
1272 	uint32_t		size;
1273 
1274 	/* Check if the event is being requested */
1275 	if (!(port->sd_reg_events & EVT_SD_ELS))
1276 		return;
1277 
1278 	size = sizeof (struct sd_plogi_rcv_v0);
1279 
1280 	if (!(bp = (struct sd_plogi_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1281 		return;
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_plogir_version = subcat;
1288 	bcopy((uint8_t *)portname, (uint8_t *)&bp->sd_plogir_portname,
1289 	    sizeof (HBA_WWN));
1290 	bcopy((uint8_t *)nodename, (uint8_t *)&bp->sd_plogir_nodename,
1291 	    sizeof (HBA_WWN));
1292 
1293 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_els_event,
1294 	    "bp=%p size=%d", bp, size);
1295 
1296 	return;
1297 
1298 } /* emlxs_log_sd_basic_els_event() */
1299 
1300 
1301 extern void
1302 emlxs_log_sd_prlo_event(emlxs_port_t *port, HBA_WWN *remoteport)
1303 {
1304 	struct sd_prlo_rcv_v0	*bp;
1305 	uint32_t		size;
1306 
1307 	/* Check if the event is being requested */
1308 	if (!(port->sd_reg_events & EVT_SD_ELS))
1309 		return;
1310 
1311 	size = sizeof (struct sd_prlo_rcv_v0);
1312 
1313 	if (!(bp = (struct sd_prlo_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1314 		return;
1315 
1316 	/*
1317 	 * we are using version field to store subtype, libdfc
1318 	 * will fix this up before returning data to app.
1319 	 */
1320 	bp->sd_prlor_version = SD_ELS_SUBCATEGORY_PRLO_RCV;
1321 	bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_prlor_remoteport,
1322 	    sizeof (HBA_WWN));
1323 
1324 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_els_event,
1325 	    "bp=%p size=%d", bp, size);
1326 
1327 	return;
1328 
1329 } /* emlxs_log_sd_prlo_event() */
1330 
1331 
1332 extern void
1333 emlxs_log_sd_lsrjt_event(emlxs_port_t *port, HBA_WWN *remoteport,
1334     uint32_t orig_cmd, uint32_t reason, uint32_t reason_expl)
1335 {
1336 	struct sd_lsrjt_rcv_v0	*bp;
1337 	uint32_t		size;
1338 
1339 	/* Check if the event is being requested */
1340 	if (!(port->sd_reg_events & EVT_SD_ELS))
1341 		return;
1342 
1343 	size = sizeof (struct sd_lsrjt_rcv_v0);
1344 
1345 	if (!(bp = (struct sd_lsrjt_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1346 		return;
1347 
1348 	/*
1349 	 * we are using version field to store subtype, libdfc
1350 	 * will fix this up before returning data to app.
1351 	 */
1352 	bp->sd_lsrjtr_version = SD_ELS_SUBCATEGORY_LSRJT_RCV;
1353 	bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_lsrjtr_remoteport,
1354 	    sizeof (HBA_WWN));
1355 	bp->sd_lsrjtr_original_cmd = orig_cmd;
1356 	bp->sd_lsrjtr_reasoncode = reason;
1357 	bp->sd_lsrjtr_reasoncodeexpl = reason_expl;
1358 
1359 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_els_event,
1360 	    "bp=%p size=%d", bp, size);
1361 
1362 	return;
1363 
1364 } /* emlxs_log_sd_lsrjt_event() */
1365 
1366 
1367 
1368 extern void
1369 emlxs_log_sd_fc_bsy_event(emlxs_port_t *port, HBA_WWN *remoteport)
1370 {
1371 	struct sd_pbsy_rcv_v0	*bp;
1372 	uint32_t		size;
1373 
1374 	/* Check if the event is being requested */
1375 	if (!(port->sd_reg_events & EVT_SD_FABRIC))
1376 		return;
1377 
1378 	size = sizeof (struct sd_pbsy_rcv_v0);
1379 
1380 	if (!(bp = (struct sd_pbsy_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1381 		return;
1382 
1383 	/*
1384 	 * we are using version field to store subtype, libdfc
1385 	 * will fix this up before returning data to app.
1386 	 */
1387 	if (remoteport == NULL)
1388 		bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_FABRIC_BUSY;
1389 	else
1390 	{
1391 		bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_PORT_BUSY;
1392 		bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_pbsyr_rport,
1393 		    sizeof (HBA_WWN));
1394 	}
1395 
1396 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_fabric_event,
1397 	    "bp=%p size=%d", bp, size);
1398 
1399 	return;
1400 
1401 } /* emlxs_log_sd_fc_bsy_event() */
1402 
1403 
1404 extern void
1405 emlxs_log_sd_fc_rdchk_event(emlxs_port_t *port, HBA_WWN *remoteport,
1406     uint32_t lun, uint32_t opcode, uint32_t fcp_param)
1407 {
1408 	struct sd_fcprdchkerr_v0	*bp;
1409 	uint32_t			size;
1410 
1411 	/* Check if the event is being requested */
1412 	if (!(port->sd_reg_events & EVT_SD_FABRIC))
1413 		return;
1414 
1415 	size = sizeof (struct sd_fcprdchkerr_v0);
1416 
1417 	if (!(bp = (struct sd_fcprdchkerr_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1418 		return;
1419 
1420 	/*
1421 	 * we are using version field to store subtype, libdfc
1422 	 * will fix this up before returning data to app.
1423 	 */
1424 	bp->sd_fcprdchkerr_version = SD_FABRIC_SUBCATEGORY_FCPRDCHKERR;
1425 	bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_fcprdchkerr_rport,
1426 	    sizeof (HBA_WWN));
1427 	bp->sd_fcprdchkerr_lun = lun;
1428 	bp->sd_fcprdchkerr_opcode = opcode;
1429 	bp->sd_fcprdchkerr_fcpiparam = fcp_param;
1430 
1431 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_fabric_event,
1432 	    "bp=%p size=%d", bp, size);
1433 
1434 	return;
1435 
1436 } /* emlxs_log_sd_rdchk_event() */
1437 
1438 
1439 extern void
1440 emlxs_log_sd_scsi_event(emlxs_port_t *port, uint32_t type,
1441     HBA_WWN *remoteport, int32_t lun)
1442 {
1443 	struct sd_scsi_generic_v0	*bp;
1444 	uint32_t			size;
1445 
1446 	/* Check if the event is being requested */
1447 	if (!(port->sd_reg_events & EVT_SD_SCSI))
1448 		return;
1449 
1450 	size = sizeof (struct sd_scsi_generic_v0);
1451 
1452 	if (!(bp = (struct sd_scsi_generic_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1453 		return;
1454 
1455 	/*
1456 	 * we are using version field to store subtype, libdfc
1457 	 * will fix this up before returning data to app.
1458 	 */
1459 	bp->sd_scsi_generic_version = type;
1460 	bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_generic_rport,
1461 	    sizeof (HBA_WWN));
1462 	bp->sd_scsi_generic_lun = lun;
1463 
1464 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_scsi_event,
1465 	    "bp=%p size=%d", bp, size);
1466 
1467 	return;
1468 
1469 } /* emlxs_log_sd_scsi_event() */
1470 
1471 
1472 extern void
1473 emlxs_log_sd_scsi_check_event(emlxs_port_t *port, HBA_WWN *remoteport,
1474     uint32_t lun, uint32_t cmdcode, uint32_t sensekey,
1475     uint32_t asc, uint32_t ascq)
1476 {
1477 	struct sd_scsi_checkcond_v0	*bp;
1478 	uint32_t			size;
1479 
1480 	/* Check if the event is being requested */
1481 	if (!(port->sd_reg_events & EVT_SD_SCSI))
1482 		return;
1483 
1484 	size = sizeof (struct sd_scsi_checkcond_v0);
1485 
1486 	if (!(bp = (struct sd_scsi_checkcond_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1487 		return;
1488 
1489 	/*
1490 	 * we are using version field to store subtype, libdfc
1491 	 * will fix this up before returning data to app.
1492 	 */
1493 	bp->sd_scsi_checkcond_version = SD_SCSI_SUBCATEGORY_CHECKCONDITION;
1494 	bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_checkcond_rport,
1495 	    sizeof (HBA_WWN));
1496 	bp->sd_scsi_checkcond_lun = lun;
1497 	bp->sd_scsi_checkcond_cmdcode = cmdcode;
1498 	bp->sd_scsi_checkcond_sensekey = sensekey;
1499 	bp->sd_scsi_checkcond_asc = asc;
1500 	bp->sd_scsi_checkcond_ascq = ascq;
1501 
1502 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_scsi_event,
1503 	    "bp=%p size=%d", bp, size);
1504 
1505 }
1506 #endif	/* SAN_DIAG_SUPPORT */
1507 
1508 
1509 extern void
1510 emlxs_log_async_event(emlxs_port_t *port, IOCB *iocb)
1511 {
1512 	uint8_t *bp;
1513 	uint32_t size;
1514 
1515 	/* ASYNC_STATUS_CN response size */
1516 	size = 64;
1517 
1518 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
1519 		return;
1520 	}
1521 
1522 	bcopy((uint8_t *)iocb, bp, size);
1523 
1524 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_async_event,
1525 	    "bp=%p size=%d", bp, size);
1526 
1527 }  /* emlxs_log_async_event() */
1528 
1529 #ifdef DFC_SUPPORT
1530 
1531 extern uint32_t
1532 emlxs_get_dfc_eventinfo(emlxs_port_t *port, HBA_EVENTINFO *eventinfo,
1533     uint32_t *eventcount, uint32_t *missed)
1534 {
1535 	emlxs_hba_t *hba = HBA;
1536 	emlxs_msg_log_t *log;
1537 	uint32_t first;
1538 	uint32_t last;
1539 	uint32_t count;
1540 	uint32_t index;
1541 	emlxs_msg_entry_t *entry;
1542 	dfc_linkinfo_t *linkinfo;
1543 	uint32_t *word;
1544 	uint8_t *byte;
1545 	uint8_t linkspeed;
1546 	uint8_t liptype;
1547 	fc_affected_id_t *aid;
1548 	uint32_t max_events;
1549 	uint32_t events;
1550 	emlxs_hba_event_t *hba_event;
1551 
1552 	if (!eventinfo || !eventcount || !missed) {
1553 		return (DFC_ARG_NULL);
1554 	}
1555 
1556 	hba_event = &hba->hba_event;
1557 	max_events = *eventcount;
1558 	*eventcount = 0;
1559 
1560 	log = &LOG;
1561 
1562 	mutex_enter(&log->lock);
1563 
1564 	/* Check if log is empty */
1565 	if (log->count == 0) {
1566 		/* Make sure everything is initialized */
1567 		hba_event->new = 0;
1568 		hba_event->missed = 0;
1569 		hba_event->last_id = 0;
1570 
1571 		mutex_exit(&log->lock);
1572 		return (0);
1573 	}
1574 
1575 	/* Safety check */
1576 	if (hba_event->last_id > (log->count - 1)) {
1577 		hba_event->last_id = log->count - 1;
1578 	}
1579 
1580 	/* Account for missed events */
1581 	if (hba_event->new > hba_event->missed) {
1582 		hba_event->new -= hba_event->missed;
1583 	} else {
1584 		hba_event->new = 0;
1585 	}
1586 
1587 	*missed = hba_event->missed;
1588 	hba_event->missed = 0;
1589 
1590 	if (!hba_event->new) {
1591 		hba_event->last_id = log->count;
1592 		mutex_exit(&log->lock);
1593 		return (0);
1594 	}
1595 
1596 	/* A new event has occurred since last acquisition */
1597 	/* Calculate the current buffer boundaries */
1598 
1599 	/* Get last entry id saved */
1600 	last = log->count - 1;
1601 
1602 	/* Get oldest entry id and its index */
1603 	/* Check if buffer has already been filled once */
1604 	if (log->count >= log->size) {
1605 		first = log->count - log->size;
1606 		index = log->next;
1607 	} else {	/* Buffer not yet filled */
1608 
1609 		first = 0;
1610 		index = 0;
1611 	}
1612 
1613 	/* Check if requested first event is greater than actual. */
1614 	/* If so, adjust for it.  */
1615 	if (hba_event->last_id > first) {
1616 		/* Adjust entry index to first requested message */
1617 		index += (hba_event->last_id - first);
1618 		if (index >= log->size) {
1619 			index -= log->size;
1620 		}
1621 
1622 		first = hba_event->last_id;
1623 	}
1624 
1625 	/* Get the total number of new messages */
1626 	count = last - first;
1627 
1628 	/* Scan log for next event */
1629 	events = 0;
1630 	while (count-- && (events < max_events)) {
1631 		if (++index >= log->size) {
1632 			index = 0;
1633 		}
1634 
1635 		entry = &log->entry[index];
1636 
1637 		if (!entry->msg) {
1638 			break;
1639 		}
1640 
1641 		if ((entry->msg->level == EMLXS_EVENT) &&
1642 		    (entry->msg->mask & (EVT_LINK | EVT_RSCN))) {
1643 			/* Process this event */
1644 			switch (entry->msg->mask) {
1645 			case EVT_LINK:
1646 				byte = (uint8_t *)entry->bp;
1647 				linkspeed = byte[0];
1648 				liptype = byte[1];
1649 				linkinfo = (dfc_linkinfo_t *)&byte[4];
1650 
1651 				if (linkinfo->a_linkState == LNK_DOWN) {
1652 					eventinfo->EventCode =
1653 					    HBA_EVENT_LINK_DOWN;
1654 					eventinfo->Event.Link_EventInfo.
1655 					    PortFcId = linkinfo->a_DID;
1656 					eventinfo->Event.Link_EventInfo.
1657 					    Reserved[0] = 0;
1658 					eventinfo->Event.Link_EventInfo.
1659 					    Reserved[1] = 0;
1660 					eventinfo->Event.Link_EventInfo.
1661 					    Reserved[2] = 0;
1662 				} else {
1663 					eventinfo->EventCode =
1664 					    HBA_EVENT_LINK_UP;
1665 					eventinfo->Event.Link_EventInfo.
1666 					    PortFcId = linkinfo->a_DID;
1667 
1668 					if ((linkinfo->a_topology ==
1669 					    LNK_PUBLIC_LOOP) ||
1670 					    (linkinfo->a_topology ==
1671 					    LNK_LOOP)) {
1672 						eventinfo->Event.
1673 						    Link_EventInfo.
1674 						    Reserved[0] = 2;
1675 					} else {
1676 						eventinfo->Event.
1677 						    Link_EventInfo.
1678 						    Reserved[0] = 1;
1679 					}
1680 
1681 					eventinfo->Event.Link_EventInfo.
1682 					    Reserved[1] = liptype;
1683 					eventinfo->Event.Link_EventInfo.
1684 					    Reserved[2] = linkspeed;
1685 				}
1686 
1687 				break;
1688 
1689 			case EVT_RSCN:
1690 				word = (uint32_t *)entry->bp;
1691 				eventinfo->EventCode = HBA_EVENT_RSCN;
1692 				eventinfo->Event.RSCN_EventInfo.PortFcId =
1693 				    word[0] & 0xFFFFFF;
1694 				/* word[1] is the RSCN payload command */
1695 
1696 				aid = (fc_affected_id_t *)&word[2];
1697 
1698 				switch (aid->aff_format) {
1699 				case 0:	/* Port */
1700 					eventinfo->Event.RSCN_EventInfo.
1701 					    NPortPage =
1702 					    aid->aff_d_id & 0x00ffffff;
1703 					break;
1704 
1705 				case 1:	/* Area */
1706 					eventinfo->Event.RSCN_EventInfo.
1707 					    NPortPage =
1708 					    aid->aff_d_id & 0x00ffff00;
1709 					break;
1710 
1711 				case 2:	/* Domain */
1712 					eventinfo->Event.RSCN_EventInfo.
1713 					    NPortPage =
1714 					    aid->aff_d_id & 0x00ff0000;
1715 					break;
1716 
1717 				case 3:	/* Network */
1718 					eventinfo->Event.RSCN_EventInfo.
1719 					    NPortPage = 0;
1720 					break;
1721 				}
1722 
1723 				eventinfo->Event.RSCN_EventInfo.Reserved[0] =
1724 				    0;
1725 				eventinfo->Event.RSCN_EventInfo.Reserved[1] =
1726 				    0;
1727 
1728 				break;
1729 			}
1730 
1731 			eventinfo++;
1732 			events++;
1733 		}
1734 
1735 		hba_event->last_id = entry->id;
1736 	}
1737 
1738 	/* Adjust new count */
1739 	if (!count || (events >= hba_event->new)) {
1740 		hba_event->new = 0;
1741 	} else {
1742 		hba_event->new -= events;
1743 	}
1744 
1745 	/* Return number of events acquired */
1746 	*eventcount = events;
1747 
1748 	mutex_exit(&log->lock);
1749 
1750 	return (0);
1751 
1752 }  /* emlxs_get_dfc_eventinfo() */
1753 
1754 
1755 uint32_t
1756 emlxs_get_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
1757     uint32_t sleep)
1758 {
1759 	emlxs_hba_t *hba = HBA;
1760 	emlxs_msg_log_t *log;
1761 	uint32_t first;
1762 	uint32_t last;
1763 	uint32_t count;
1764 	uint32_t index;
1765 	uint32_t mask;
1766 	uint32_t i;
1767 	emlxs_msg_entry_t *entry;
1768 	uint32_t size;
1769 	uint32_t rc;
1770 
1771 	size = 0;
1772 
1773 	if (dfc_event->dataout && dfc_event->size) {
1774 		size = dfc_event->size;
1775 	}
1776 	dfc_event->size = 0;
1777 
1778 	/* Get the log file pointer */
1779 	log = &LOG;
1780 
1781 	/* Calculate the event index */
1782 	mask = dfc_event->event;
1783 	for (i = 0; i < 32; i++) {
1784 		if (mask & 0x01) {
1785 			break;
1786 		}
1787 
1788 		mask >>= 1;
1789 	}
1790 	if (i == 32) {
1791 		return (DFC_ARG_INVALID);
1792 	}
1793 
1794 	mutex_enter(&log->lock);
1795 
1796 	/* Check if log is empty */
1797 	if (log->count == 0) {
1798 		/* Make sure everything is initialized */
1799 		log->event_id[i] = 0;
1800 		dfc_event->last_id = 0;
1801 	} else {
1802 		/* Check ranges for safety */
1803 		if (log->event_id[i] > (log->count - 1)) {
1804 			log->event_id[i] = log->count - 1;
1805 		}
1806 
1807 		if (dfc_event->last_id > log->event_id[i]) {
1808 			dfc_event->last_id = log->event_id[i];
1809 		}
1810 	}
1811 
1812 wait_for_event:
1813 
1814 	/* Check if no new event has ocurred */
1815 	if (dfc_event->last_id == log->event_id[i]) {
1816 		if (!sleep) {
1817 			mutex_exit(&log->lock);
1818 			return (0);
1819 		}
1820 
1821 		/* While event is still active and */
1822 		/* no new event has been logged */
1823 		while ((dfc_event->event & hba->log_events) &&
1824 		    (dfc_event->last_id == log->event_id[i])) {
1825 			rc = cv_wait_sig(&log->lock_cv, &log->lock);
1826 
1827 			/* Check if thread was killed by kernel */
1828 			if (rc == 0) {
1829 				dfc_event->pid = 0;
1830 				dfc_event->event = 0;
1831 				mutex_exit(&log->lock);
1832 				return (0);
1833 			}
1834 		}
1835 
1836 		/* If the event is no longer registered then */
1837 		/* return immediately */
1838 		if (!(dfc_event->event & hba->log_events)) {
1839 			mutex_exit(&log->lock);
1840 			return (0);
1841 		}
1842 	}
1843 
1844 	/* !!! An event has occurred since last_id !!! */
1845 
1846 	/* Check if event data is not being requested */
1847 	if (!size) {
1848 		/* If so, then just return the last event id */
1849 		dfc_event->last_id = log->event_id[i];
1850 
1851 		mutex_exit(&log->lock);
1852 		return (0);
1853 	}
1854 
1855 	/* !!! The requester wants the next event buffer !!! */
1856 
1857 	/* Calculate the current buffer boundaries */
1858 
1859 	/* Get last entry id saved */
1860 	last = log->count - 1;
1861 
1862 	/* Get oldest entry id and its index */
1863 	/* Check if buffer has already been filled once */
1864 	if (log->count >= log->size) {
1865 		first = log->count - log->size;
1866 		index = log->next;
1867 	} else {	/* Buffer not yet filled */
1868 
1869 		first = 0;
1870 		index = 0;
1871 	}
1872 
1873 	/* Check to see if the buffer has wrapped since the last event */
1874 	if (first > log->event_id[i]) {
1875 		/* Update last_id to the last known event */
1876 		dfc_event->last_id = log->event_id[i];
1877 
1878 		/* Try waiting again if we can */
1879 		goto wait_for_event;
1880 	}
1881 
1882 	/* Check if requested first event is greater than actual. */
1883 	/* If so, adjust for it.  */
1884 	if (dfc_event->last_id > first) {
1885 		/* Adjust entry index to first requested message */
1886 		index += (dfc_event->last_id - first);
1887 		if (index >= log->size) {
1888 			index -= log->size;
1889 		}
1890 
1891 		first = dfc_event->last_id;
1892 	}
1893 
1894 	/* Get the total number of new messages */
1895 	count = last - first + 1;
1896 
1897 	/* Scan log for next event */
1898 	while (count--) {
1899 		if (++index >= log->size) {
1900 			index = 0;
1901 		}
1902 
1903 		entry = &log->entry[index];
1904 
1905 		if ((entry->msg->level == EMLXS_EVENT) &&
1906 		    (entry->msg->mask == dfc_event->event)) {
1907 			break;
1908 		}
1909 	}
1910 
1911 	/* Check if no new event was found in the current log buffer */
1912 	/* This would indicate that the buffer wrapped since that last event */
1913 	if (!count) {
1914 		/* Update last_id to the last known event */
1915 		dfc_event->last_id = log->event_id[i];
1916 
1917 		/* Try waiting again if we can */
1918 		goto wait_for_event;
1919 	}
1920 
1921 	/* !!! Next event found !!! */
1922 
1923 	/* Copy the context buffer to the buffer provided */
1924 	if (entry->bp && entry->size) {
1925 		if (entry->size < size) {
1926 			size = entry->size;
1927 		}
1928 
1929 		if (ddi_copyout((void *)entry->bp, dfc_event->dataout, size,
1930 		    dfc_event->mode) != 0) {
1931 			mutex_exit(&log->lock);
1932 
1933 			return (DFC_COPYOUT_ERROR);
1934 		}
1935 
1936 		/* Data has been retrieved by the apps */
1937 		entry->flag |= EMLX_EVENT_DONE;
1938 
1939 		dfc_event->size = size;
1940 	}
1941 
1942 	dfc_event->last_id = entry->id;
1943 
1944 	mutex_exit(&log->lock);
1945 	return (0);
1946 
1947 }  /* emlxs_get_dfc_event() */
1948 
1949 
1950 uint32_t
1951 emlxs_kill_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event)
1952 {
1953 	emlxs_hba_t *hba = HBA;
1954 	emlxs_msg_log_t *log;
1955 
1956 	/* Get the log file pointer */
1957 	log = &LOG;
1958 
1959 	mutex_enter(&log->lock);
1960 	dfc_event->pid = 0;
1961 	dfc_event->event = 0;
1962 	cv_broadcast(&log->lock_cv);
1963 	mutex_exit(&log->lock);
1964 
1965 	return (0);
1966 
1967 }  /* emlxs_kill_dfc_event() */
1968 
1969 
1970 #ifdef SAN_DIAG_SUPPORT
1971 uint32_t
1972 emlxs_get_sd_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
1973     uint32_t sleep)
1974 {
1975 	emlxs_hba_t		*hba = HBA;
1976 	emlxs_msg_log_t		*log;
1977 	emlxs_msg_entry_t	*entry;
1978 	uint32_t		size;
1979 	uint32_t		rc;
1980 	uint32_t		first;
1981 	uint32_t		last;
1982 	uint32_t		count;
1983 	uint32_t		index;
1984 	uint32_t		mask;
1985 	uint32_t		i;
1986 
1987 	size = 0;
1988 
1989 	if (dfc_event->dataout && dfc_event->size) {
1990 		size = dfc_event->size;
1991 	}
1992 	dfc_event->size = 0;
1993 
1994 	/* Get the log file pointer */
1995 	log = &LOG;
1996 
1997 	/* Calculate the event index */
1998 	mask = dfc_event->event;
1999 	for (i = 0; i < 32; i++) {
2000 		if (mask & 0x01)
2001 			break;
2002 
2003 		mask >>= 1;
2004 	}
2005 	if (i == 32)
2006 		return (DFC_ARG_INVALID);
2007 
2008 	mutex_enter(&log->lock);
2009 
2010 	/* Check if log is empty */
2011 	if (log->count == 0) {
2012 		/* Make sure everything is initialized */
2013 		log->event_id[i] = 0;
2014 		dfc_event->last_id = 0;
2015 	} else {
2016 		/* Check ranges for safety */
2017 		if (log->event_id[i] > (log->count - 1))
2018 			log->event_id[i] = log->count - 1;
2019 
2020 		if (dfc_event->last_id > log->event_id[i])
2021 			dfc_event->last_id = log->event_id[i];
2022 	}
2023 
2024 wait_for_sd_event:
2025 	/* Check if no new event has ocurred */
2026 	if (dfc_event->last_id == log->event_id[i]) {
2027 		if (!sleep) {
2028 			mutex_exit(&log->lock);
2029 			return (0);
2030 		}
2031 
2032 		/* While event is active and no new event has been logged */
2033 		while ((dfc_event->event & port->sd_reg_events) &&
2034 		    (dfc_event->last_id == log->event_id[i])) {
2035 			rc = cv_wait_sig(&log->lock_cv, &log->lock);
2036 
2037 			/* Check if thread was killed by kernel */
2038 			if (rc == 0) {
2039 				dfc_event->pid = 0;
2040 				dfc_event->event = 0;
2041 				mutex_exit(&log->lock);
2042 				return (0);
2043 			}
2044 		}
2045 
2046 		/* If the event is no longer registered then return */
2047 		if (!(dfc_event->event & port->sd_reg_events)) {
2048 			mutex_exit(&log->lock);
2049 			return (0);
2050 		}
2051 	}
2052 
2053 	/* !!! An event has occurred since last_id !!! */
2054 
2055 	/* Check if event data is not being requested */
2056 	if (!size) {
2057 		/* If so, then just return the last event id */
2058 		dfc_event->last_id = log->event_id[i];
2059 		mutex_exit(&log->lock);
2060 		return (0);
2061 	}
2062 
2063 	/* !!! The requester wants the next event buffer !!! */
2064 
2065 	/* Calculate the current buffer boundaries */
2066 
2067 	/* Get last entry id saved */
2068 	last = log->count - 1;
2069 
2070 	/* Get oldest entry id and its index */
2071 	/* Check if buffer has already been filled once */
2072 	if (log->count >= log->size) {
2073 		first = log->count - log->size;
2074 		index = log->next;
2075 	} else { /* Buffer not yet filled */
2076 		first = 0;
2077 		index = 0;
2078 	}
2079 
2080 	/* Check to see if the buffer has wrapped since the last event */
2081 	if (first > log->event_id[i]) {
2082 		/* Update last_id to the last known event */
2083 		dfc_event->last_id = log->event_id[i];
2084 
2085 		/* Try waiting again if we can */
2086 		goto wait_for_sd_event;
2087 	}
2088 
2089 	/* if requested first event is greater than actual, adjust for it. */
2090 	if (dfc_event->last_id > first) {
2091 		/* Adjust entry index to first requested message */
2092 		index += (dfc_event->last_id - first);
2093 		if (index >= log->size) {
2094 			index -= log->size;
2095 		}
2096 
2097 		first = dfc_event->last_id;
2098 	}
2099 
2100 	/* Get the total number of new messages */
2101 	count = last - first + 1;
2102 
2103 	/* Scan log for next event */
2104 	while (count--) {
2105 		if (++index >= log->size)
2106 			index = 0;
2107 
2108 		entry = &log->entry[index];
2109 
2110 		if ((entry->msg->level == EMLXS_EVENT) &&
2111 		    (entry->vpi == port->vpi) &&
2112 		    (entry->msg->mask == dfc_event->event))
2113 			break;
2114 	}
2115 
2116 	/* Check if no new event was found in the current log buffer */
2117 	/* This would indicate that the buffer wrapped since that last event */
2118 	if (!count) {
2119 		/* Update last_id to the last known event */
2120 		dfc_event->last_id = log->event_id[i];
2121 
2122 		/* Try waiting again if we can */
2123 		goto wait_for_sd_event;
2124 	}
2125 
2126 	/* !!! Next event found !!! */
2127 
2128 	/* Copy the context buffer to the buffer provided */
2129 	if (entry->bp && entry->size) {
2130 		if (entry->size < size)
2131 			size = entry->size;
2132 
2133 		if (ddi_copyout((void *) entry->bp, dfc_event->dataout,
2134 		    size, dfc_event->mode) != 0) {
2135 			mutex_exit(&log->lock);
2136 
2137 			return (DFC_COPYOUT_ERROR);
2138 		}
2139 
2140 		dfc_event->size = size;
2141 	}
2142 
2143 	dfc_event->last_id = entry->id;
2144 	mutex_exit(&log->lock);
2145 
2146 	return (0);
2147 } /* emlxs_get_sd_event */
2148 #endif /* SAN_DIAG_SUPPORT */
2149 
2150 
2151 #endif /* DFC_SUPPORT */
2152