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 	uint8_t format;
1551 	emlxs_hba_event_t *hba_event;
1552 
1553 	if (!eventinfo || !eventcount || !missed) {
1554 		return (DFC_ARG_NULL);
1555 	}
1556 
1557 	hba_event = &hba->hba_event;
1558 	max_events = *eventcount;
1559 	*eventcount = 0;
1560 
1561 	log = &LOG;
1562 
1563 	mutex_enter(&log->lock);
1564 
1565 	/* Check if log is empty */
1566 	if (log->count == 0) {
1567 		/* Make sure everything is initialized */
1568 		hba_event->new = 0;
1569 		hba_event->missed = 0;
1570 		hba_event->last_id = 0;
1571 
1572 		mutex_exit(&log->lock);
1573 		return (0);
1574 	}
1575 
1576 	/* Safety check */
1577 	if (hba_event->last_id > (log->count - 1)) {
1578 		hba_event->last_id = log->count - 1;
1579 	}
1580 
1581 	/* Account for missed events */
1582 	if (hba_event->new > hba_event->missed) {
1583 		hba_event->new -= hba_event->missed;
1584 	} else {
1585 		hba_event->new = 0;
1586 	}
1587 
1588 	*missed = hba_event->missed;
1589 	hba_event->missed = 0;
1590 
1591 	if (!hba_event->new) {
1592 		hba_event->last_id = log->count;
1593 		mutex_exit(&log->lock);
1594 		return (0);
1595 	}
1596 
1597 	/* A new event has occurred since last acquisition */
1598 	/* Calculate the current buffer boundaries */
1599 
1600 	/* Get last entry id saved */
1601 	last = log->count - 1;
1602 
1603 	/* Get oldest entry id and its index */
1604 	/* Check if buffer has already been filled once */
1605 	if (log->count >= log->size) {
1606 		first = log->count - log->size;
1607 		index = log->next;
1608 	} else {	/* Buffer not yet filled */
1609 
1610 		first = 0;
1611 		index = 0;
1612 	}
1613 
1614 	/* Check if requested first event is greater than actual. */
1615 	/* If so, adjust for it.  */
1616 	if (hba_event->last_id > first) {
1617 		/* Adjust entry index to first requested message */
1618 		index += (hba_event->last_id - first);
1619 		if (index >= log->size) {
1620 			index -= log->size;
1621 		}
1622 
1623 		first = hba_event->last_id;
1624 	}
1625 
1626 	/* Get the total number of new messages */
1627 	count = last - first;
1628 
1629 	/* Scan log for next event */
1630 	events = 0;
1631 	while (count-- && (events < max_events)) {
1632 		if (++index >= log->size) {
1633 			index = 0;
1634 		}
1635 
1636 		entry = &log->entry[index];
1637 
1638 		if (!entry->msg) {
1639 			break;
1640 		}
1641 
1642 		if ((entry->msg->level == EMLXS_EVENT) &&
1643 		    (entry->msg->mask & (EVT_LINK | EVT_RSCN))) {
1644 			/* Process this event */
1645 			switch (entry->msg->mask) {
1646 			case EVT_LINK:
1647 				byte = (uint8_t *)entry->bp;
1648 				linkspeed = byte[0];
1649 				liptype = byte[1];
1650 				linkinfo = (dfc_linkinfo_t *)&byte[4];
1651 
1652 				if (linkinfo->a_linkState == LNK_DOWN) {
1653 					eventinfo->EventCode =
1654 					    HBA_EVENT_LINK_DOWN;
1655 					eventinfo->Event.Link_EventInfo.
1656 					    PortFcId = linkinfo->a_DID;
1657 					eventinfo->Event.Link_EventInfo.
1658 					    Reserved[0] = 0;
1659 					eventinfo->Event.Link_EventInfo.
1660 					    Reserved[1] = 0;
1661 					eventinfo->Event.Link_EventInfo.
1662 					    Reserved[2] = 0;
1663 				} else {
1664 					eventinfo->EventCode =
1665 					    HBA_EVENT_LINK_UP;
1666 					eventinfo->Event.Link_EventInfo.
1667 					    PortFcId = linkinfo->a_DID;
1668 
1669 					if ((linkinfo->a_topology ==
1670 					    LNK_PUBLIC_LOOP) ||
1671 					    (linkinfo->a_topology ==
1672 					    LNK_LOOP)) {
1673 						eventinfo->Event.
1674 						    Link_EventInfo.
1675 						    Reserved[0] = 2;
1676 					} else {
1677 						eventinfo->Event.
1678 						    Link_EventInfo.
1679 						    Reserved[0] = 1;
1680 					}
1681 
1682 					eventinfo->Event.Link_EventInfo.
1683 					    Reserved[1] = liptype;
1684 					eventinfo->Event.Link_EventInfo.
1685 					    Reserved[2] = linkspeed;
1686 				}
1687 
1688 				break;
1689 
1690 			case EVT_RSCN:
1691 				word = (uint32_t *)entry->bp;
1692 				eventinfo->EventCode = HBA_EVENT_RSCN;
1693 				eventinfo->Event.RSCN_EventInfo.PortFcId =
1694 				    word[0] & 0xFFFFFF;
1695 				/* word[1] is the RSCN payload command */
1696 
1697 				aid = (fc_affected_id_t *)&word[2];
1698 				format = aid->aff_format;
1699 
1700 				switch (format) {
1701 				case 0:	/* Port */
1702 					eventinfo->Event.RSCN_EventInfo.
1703 					    NPortPage =
1704 					    aid->aff_d_id & 0x00ffffff;
1705 					break;
1706 
1707 				case 1:	/* Area */
1708 					eventinfo->Event.RSCN_EventInfo.
1709 					    NPortPage =
1710 					    aid->aff_d_id & 0x00ffff00;
1711 					break;
1712 
1713 				case 2:	/* Domain */
1714 					eventinfo->Event.RSCN_EventInfo.
1715 					    NPortPage =
1716 					    aid->aff_d_id & 0x00ff0000;
1717 					break;
1718 
1719 				case 3:	/* Network */
1720 					eventinfo->Event.RSCN_EventInfo.
1721 					    NPortPage = 0;
1722 					break;
1723 				}
1724 
1725 				eventinfo->Event.RSCN_EventInfo.Reserved[0] =
1726 				    0;
1727 				eventinfo->Event.RSCN_EventInfo.Reserved[1] =
1728 				    0;
1729 
1730 				break;
1731 			}
1732 
1733 			eventinfo++;
1734 			events++;
1735 		}
1736 
1737 		hba_event->last_id = entry->id;
1738 	}
1739 
1740 	/* Adjust new count */
1741 	if (!count || (events >= hba_event->new)) {
1742 		hba_event->new = 0;
1743 	} else {
1744 		hba_event->new -= events;
1745 	}
1746 
1747 	/* Return number of events acquired */
1748 	*eventcount = events;
1749 
1750 	mutex_exit(&log->lock);
1751 
1752 	return (0);
1753 
1754 }  /* emlxs_get_dfc_eventinfo() */
1755 
1756 
1757 uint32_t
1758 emlxs_get_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
1759     uint32_t sleep)
1760 {
1761 	emlxs_hba_t *hba = HBA;
1762 	emlxs_msg_log_t *log;
1763 	uint32_t first;
1764 	uint32_t last;
1765 	uint32_t count;
1766 	uint32_t index;
1767 	uint32_t mask;
1768 	uint32_t i;
1769 	emlxs_msg_entry_t *entry;
1770 	uint32_t size;
1771 	uint32_t rc;
1772 
1773 	size = 0;
1774 
1775 	if (dfc_event->dataout && dfc_event->size) {
1776 		size = dfc_event->size;
1777 	}
1778 	dfc_event->size = 0;
1779 
1780 	/* Get the log file pointer */
1781 	log = &LOG;
1782 
1783 	/* Calculate the event index */
1784 	mask = dfc_event->event;
1785 	for (i = 0; i < 32; i++) {
1786 		if (mask & 0x01) {
1787 			break;
1788 		}
1789 
1790 		mask >>= 1;
1791 	}
1792 	if (i == 32) {
1793 		return (DFC_ARG_INVALID);
1794 	}
1795 
1796 	mutex_enter(&log->lock);
1797 
1798 	/* Check if log is empty */
1799 	if (log->count == 0) {
1800 		/* Make sure everything is initialized */
1801 		log->event_id[i] = 0;
1802 		dfc_event->last_id = 0;
1803 	} else {
1804 		/* Check ranges for safety */
1805 		if (log->event_id[i] > (log->count - 1)) {
1806 			log->event_id[i] = log->count - 1;
1807 		}
1808 
1809 		if (dfc_event->last_id > log->event_id[i]) {
1810 			dfc_event->last_id = log->event_id[i];
1811 		}
1812 	}
1813 
1814 wait_for_event:
1815 
1816 	/* Check if no new event has ocurred */
1817 	if (dfc_event->last_id == log->event_id[i]) {
1818 		if (!sleep) {
1819 			mutex_exit(&log->lock);
1820 			return (0);
1821 		}
1822 
1823 		/* While event is still active and */
1824 		/* no new event has been logged */
1825 		while ((dfc_event->event & hba->log_events) &&
1826 		    (dfc_event->last_id == log->event_id[i])) {
1827 			rc = cv_wait_sig(&log->lock_cv, &log->lock);
1828 
1829 			/* Check if thread was killed by kernel */
1830 			if (rc == 0) {
1831 				dfc_event->pid = 0;
1832 				dfc_event->event = 0;
1833 				mutex_exit(&log->lock);
1834 				return (0);
1835 			}
1836 		}
1837 
1838 		/* If the event is no longer registered then */
1839 		/* return immediately */
1840 		if (!(dfc_event->event & hba->log_events)) {
1841 			mutex_exit(&log->lock);
1842 			return (0);
1843 		}
1844 	}
1845 
1846 	/* !!! An event has occurred since last_id !!! */
1847 
1848 	/* Check if event data is not being requested */
1849 	if (!size) {
1850 		/* If so, then just return the last event id */
1851 		dfc_event->last_id = log->event_id[i];
1852 
1853 		mutex_exit(&log->lock);
1854 		return (0);
1855 	}
1856 
1857 	/* !!! The requester wants the next event buffer !!! */
1858 
1859 	/* Calculate the current buffer boundaries */
1860 
1861 	/* Get last entry id saved */
1862 	last = log->count - 1;
1863 
1864 	/* Get oldest entry id and its index */
1865 	/* Check if buffer has already been filled once */
1866 	if (log->count >= log->size) {
1867 		first = log->count - log->size;
1868 		index = log->next;
1869 	} else {	/* Buffer not yet filled */
1870 
1871 		first = 0;
1872 		index = 0;
1873 	}
1874 
1875 	/* Check to see if the buffer has wrapped since the last event */
1876 	if (first > log->event_id[i]) {
1877 		/* Update last_id to the last known event */
1878 		dfc_event->last_id = log->event_id[i];
1879 
1880 		/* Try waiting again if we can */
1881 		goto wait_for_event;
1882 	}
1883 
1884 	/* Check if requested first event is greater than actual. */
1885 	/* If so, adjust for it.  */
1886 	if (dfc_event->last_id > first) {
1887 		/* Adjust entry index to first requested message */
1888 		index += (dfc_event->last_id - first);
1889 		if (index >= log->size) {
1890 			index -= log->size;
1891 		}
1892 
1893 		first = dfc_event->last_id;
1894 	}
1895 
1896 	/* Get the total number of new messages */
1897 	count = last - first + 1;
1898 
1899 	/* Scan log for next event */
1900 	while (count--) {
1901 		if (++index >= log->size) {
1902 			index = 0;
1903 		}
1904 
1905 		entry = &log->entry[index];
1906 
1907 		if ((entry->msg->level == EMLXS_EVENT) &&
1908 		    (entry->msg->mask == dfc_event->event)) {
1909 			break;
1910 		}
1911 	}
1912 
1913 	/* Check if no new event was found in the current log buffer */
1914 	/* This would indicate that the buffer wrapped since that last event */
1915 	if (!count) {
1916 		/* Update last_id to the last known event */
1917 		dfc_event->last_id = log->event_id[i];
1918 
1919 		/* Try waiting again if we can */
1920 		goto wait_for_event;
1921 	}
1922 
1923 	/* !!! Next event found !!! */
1924 
1925 	/* Copy the context buffer to the buffer provided */
1926 	if (entry->bp && entry->size) {
1927 		if (entry->size < size) {
1928 			size = entry->size;
1929 		}
1930 
1931 		if (ddi_copyout((void *)entry->bp, dfc_event->dataout, size,
1932 		    dfc_event->mode) != 0) {
1933 			mutex_exit(&log->lock);
1934 
1935 			return (DFC_COPYOUT_ERROR);
1936 		}
1937 
1938 		/* Data has been retrieved by the apps */
1939 		entry->flag |= EMLX_EVENT_DONE;
1940 
1941 		dfc_event->size = size;
1942 	}
1943 
1944 	dfc_event->last_id = entry->id;
1945 
1946 	mutex_exit(&log->lock);
1947 	return (0);
1948 
1949 }  /* emlxs_get_dfc_event() */
1950 
1951 
1952 uint32_t
1953 emlxs_kill_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event)
1954 {
1955 	emlxs_hba_t *hba = HBA;
1956 	emlxs_msg_log_t *log;
1957 
1958 	/* Get the log file pointer */
1959 	log = &LOG;
1960 
1961 	mutex_enter(&log->lock);
1962 	dfc_event->pid = 0;
1963 	dfc_event->event = 0;
1964 	cv_broadcast(&log->lock_cv);
1965 	mutex_exit(&log->lock);
1966 
1967 	return (0);
1968 
1969 }  /* emlxs_kill_dfc_event() */
1970 
1971 
1972 #ifdef SAN_DIAG_SUPPORT
1973 uint32_t
1974 emlxs_get_sd_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
1975     uint32_t sleep)
1976 {
1977 	emlxs_hba_t		*hba = HBA;
1978 	emlxs_msg_log_t		*log;
1979 	emlxs_msg_entry_t	*entry;
1980 	uint32_t		size;
1981 	uint32_t		rc;
1982 	uint32_t		first;
1983 	uint32_t		last;
1984 	uint32_t		count;
1985 	uint32_t		index;
1986 	uint32_t		mask;
1987 	uint32_t		i;
1988 
1989 	size = 0;
1990 
1991 	if (dfc_event->dataout && dfc_event->size) {
1992 		size = dfc_event->size;
1993 	}
1994 	dfc_event->size = 0;
1995 
1996 	/* Get the log file pointer */
1997 	log = &LOG;
1998 
1999 	/* Calculate the event index */
2000 	mask = dfc_event->event;
2001 	for (i = 0; i < 32; i++) {
2002 		if (mask & 0x01)
2003 			break;
2004 
2005 		mask >>= 1;
2006 	}
2007 	if (i == 32)
2008 		return (DFC_ARG_INVALID);
2009 
2010 	mutex_enter(&log->lock);
2011 
2012 	/* Check if log is empty */
2013 	if (log->count == 0) {
2014 		/* Make sure everything is initialized */
2015 		log->event_id[i] = 0;
2016 		dfc_event->last_id = 0;
2017 	} else {
2018 		/* Check ranges for safety */
2019 		if (log->event_id[i] > (log->count - 1))
2020 			log->event_id[i] = log->count - 1;
2021 
2022 		if (dfc_event->last_id > log->event_id[i])
2023 			dfc_event->last_id = log->event_id[i];
2024 	}
2025 
2026 wait_for_sd_event:
2027 	/* Check if no new event has ocurred */
2028 	if (dfc_event->last_id == log->event_id[i]) {
2029 		if (!sleep) {
2030 			mutex_exit(&log->lock);
2031 			return (0);
2032 		}
2033 
2034 		/* While event is active and no new event has been logged */
2035 		while ((dfc_event->event & port->sd_reg_events) &&
2036 		    (dfc_event->last_id == log->event_id[i])) {
2037 			rc = cv_wait_sig(&log->lock_cv, &log->lock);
2038 
2039 			/* Check if thread was killed by kernel */
2040 			if (rc == 0) {
2041 				dfc_event->pid = 0;
2042 				dfc_event->event = 0;
2043 				mutex_exit(&log->lock);
2044 				return (0);
2045 			}
2046 		}
2047 
2048 		/* If the event is no longer registered then return */
2049 		if (!(dfc_event->event & port->sd_reg_events)) {
2050 			mutex_exit(&log->lock);
2051 			return (0);
2052 		}
2053 	}
2054 
2055 	/* !!! An event has occurred since last_id !!! */
2056 
2057 	/* Check if event data is not being requested */
2058 	if (!size) {
2059 		/* If so, then just return the last event id */
2060 		dfc_event->last_id = log->event_id[i];
2061 		mutex_exit(&log->lock);
2062 		return (0);
2063 	}
2064 
2065 	/* !!! The requester wants the next event buffer !!! */
2066 
2067 	/* Calculate the current buffer boundaries */
2068 
2069 	/* Get last entry id saved */
2070 	last = log->count - 1;
2071 
2072 	/* Get oldest entry id and its index */
2073 	/* Check if buffer has already been filled once */
2074 	if (log->count >= log->size) {
2075 		first = log->count - log->size;
2076 		index = log->next;
2077 	} else { /* Buffer not yet filled */
2078 		first = 0;
2079 		index = 0;
2080 	}
2081 
2082 	/* Check to see if the buffer has wrapped since the last event */
2083 	if (first > log->event_id[i]) {
2084 		/* Update last_id to the last known event */
2085 		dfc_event->last_id = log->event_id[i];
2086 
2087 		/* Try waiting again if we can */
2088 		goto wait_for_sd_event;
2089 	}
2090 
2091 	/* if requested first event is greater than actual, adjust for it. */
2092 	if (dfc_event->last_id > first) {
2093 		/* Adjust entry index to first requested message */
2094 		index += (dfc_event->last_id - first);
2095 		if (index >= log->size) {
2096 			index -= log->size;
2097 		}
2098 
2099 		first = dfc_event->last_id;
2100 	}
2101 
2102 	/* Get the total number of new messages */
2103 	count = last - first + 1;
2104 
2105 	/* Scan log for next event */
2106 	while (count--) {
2107 		if (++index >= log->size)
2108 			index = 0;
2109 
2110 		entry = &log->entry[index];
2111 
2112 		if ((entry->msg->level == EMLXS_EVENT) &&
2113 		    (entry->vpi == port->vpi) &&
2114 		    (entry->msg->mask == dfc_event->event))
2115 			break;
2116 	}
2117 
2118 	/* Check if no new event was found in the current log buffer */
2119 	/* This would indicate that the buffer wrapped since that last event */
2120 	if (!count) {
2121 		/* Update last_id to the last known event */
2122 		dfc_event->last_id = log->event_id[i];
2123 
2124 		/* Try waiting again if we can */
2125 		goto wait_for_sd_event;
2126 	}
2127 
2128 	/* !!! Next event found !!! */
2129 
2130 	/* Copy the context buffer to the buffer provided */
2131 	if (entry->bp && entry->size) {
2132 		if (entry->size < size)
2133 			size = entry->size;
2134 
2135 		if (ddi_copyout((void *) entry->bp, dfc_event->dataout,
2136 		    size, dfc_event->mode) != 0) {
2137 			mutex_exit(&log->lock);
2138 
2139 			return (DFC_COPYOUT_ERROR);
2140 		}
2141 
2142 		dfc_event->size = size;
2143 	}
2144 
2145 	dfc_event->last_id = entry->id;
2146 	mutex_exit(&log->lock);
2147 
2148 	return (0);
2149 } /* emlxs_get_sd_event */
2150 #endif /* SAN_DIAG_SUPPORT */
2151 
2152 
2153 #endif /* DFC_SUPPORT */
2154