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 2008 Emulex.  All rights reserved.
24  * Use is subject to License terms.
25  */
26 
27 
28 #define	 DEF_MSG_STRUCT	/* Needed for emlxs_messages.h in emlxs_msg.h */
29 #include "emlxs.h"
30 
31 
32 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
33 EMLXS_MSG_DEF(EMLXS_MSG_C);
34 
35 uint32_t emlxs_log_size = 1024;
36 /* uint32_t emlxs_log_debugs   = 0x000FFFFF; */
37 uint32_t emlxs_log_debugs = 0x7FFFFFFF;
38 uint32_t emlxs_log_notices = 0xFFFFFFFF;
39 uint32_t emlxs_log_warnings = 0xFFFFFFFF;
40 uint32_t emlxs_log_errors = 0xFFFFFFFF;
41 
42 static uint32_t emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg);
43 static uint32_t emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg);
44 static void emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry);
45 
46 
47 uint32_t
48 emlxs_msg_log_create(emlxs_hba_t *hba)
49 {
50 	emlxs_msg_log_t *log = &LOG;
51 	uint32_t size = sizeof (emlxs_msg_entry_t) * emlxs_log_size;
52 	char buf[40];
53 #ifdef MSI_SUPPORT
54 	ddi_intr_handle_t handle;
55 	uint32_t intr_pri;
56 	int32_t actual;
57 	uint32_t ret;
58 #endif	/* MSI_SUPPORT */
59 	ddi_iblock_cookie_t iblock;
60 
61 	/* Check if log is already created */
62 	if (log->entry) {
63 		cmn_err(CE_WARN, "?%s%d: message log already created. log=%p",
64 		    DRIVER_NAME, hba->ddiinst, (void *) log);
65 		return (0);
66 	}
67 	/* Clear the log */
68 	bzero(log, sizeof (emlxs_msg_log_t));
69 
70 	/* Allocate the memory needed for the log file */
71 	if (!(log->entry = (emlxs_msg_entry_t *)kmem_zalloc(size, KM_SLEEP))) {
72 		cmn_err(CE_WARN, "?%s%d: Unable to allocate log memory. log=%p",
73 		    DRIVER_NAME, hba->ddiinst, (void *) log);
74 		return (0);
75 	}
76 	/* Initialize */
77 	log->size = emlxs_log_size;
78 	log->instance = hba->ddiinst;
79 	log->start_time = emlxs_device.log_timestamp;
80 
81 	(void) sprintf(buf, "?%s%d_log_lock control variable", DRIVER_NAME,
82 	    hba->ddiinst);
83 	cv_init(&log->lock_cv, buf, CV_DRIVER, NULL);
84 
85 	(void) sprintf(buf, "?%s%d_log_lock mutex", DRIVER_NAME, hba->ddiinst);
86 
87 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
88 		/* Get the current interrupt block cookie */
89 		(void) ddi_get_iblock_cookie(hba->dip, (uint_t)EMLXS_INUMBER,
90 		    &iblock);
91 
92 		/* Create the log mutex lock */
93 		mutex_init(&log->lock, buf, MUTEX_DRIVER, (void *) iblock);
94 	}
95 #ifdef  MSI_SUPPORT
96 	else {
97 
98 		/* Allocate a temporary interrupt handle */
99 		actual = 0;
100 		ret = ddi_intr_alloc(hba->dip, &handle, DDI_INTR_TYPE_FIXED,
101 		    EMLXS_MSI_INUMBER, 1, &actual, DDI_INTR_ALLOC_NORMAL);
102 
103 		if (ret != DDI_SUCCESS || actual == 0) {
104 			cmn_err(CE_WARN, "?%s%d: Unable to allocate "
105 			    "temporary interrupt handle. ret=%d actual=%d",
106 			    DRIVER_NAME, hba->ddiinst, ret, actual);
107 
108 			/* Free the log buffer */
109 			kmem_free(log->entry, size);
110 			bzero(log, sizeof (emlxs_msg_log_t));
111 
112 			return (0);
113 		}
114 		/* Get the current interrupt priority */
115 		ret = ddi_intr_get_pri(handle, &intr_pri);
116 
117 		if (ret != DDI_SUCCESS) {
118 			cmn_err(CE_WARN, "?%s%d: Unable to get interrupt "
119 			    "priority. ret=%d", DRIVER_NAME, hba->ddiinst, ret);
120 
121 			/* Free the log buffer */
122 			kmem_free(log->entry, size);
123 			bzero(log, sizeof (emlxs_msg_log_t));
124 
125 			return (0);
126 		}
127 		/* Create the log mutex lock */
128 		mutex_init(&log->lock, buf, MUTEX_DRIVER,
129 		    (void *)(unsigned long) intr_pri);
130 
131 		/* Free the temporary handle */
132 		(void) ddi_intr_free(handle);
133 	}
134 #endif
135 
136 	return (1);
137 
138 } /* emlxs_msg_log_create() */
139 
140 
141 uint32_t
142 emlxs_msg_log_destroy(emlxs_hba_t *hba)
143 {
144 	emlxs_msg_log_t *log = &LOG;
145 	uint32_t size;
146 	emlxs_msg_entry_t *entry;
147 	uint32_t i;
148 
149 	/* Check if log is already destroyed */
150 	if (!log->entry) {
151 		cmn_err(CE_WARN, "?%s%d: message log already destroyed. log=%p",
152 		    DRIVER_NAME, hba->ddiinst, (void *) log);
153 
154 		return (1);
155 	}
156 	/*
157 	 * If events are being logged there might be threads waiting so
158 	 * release them
159 	 */
160 	if (hba->log_events) {
161 		mutex_enter(&log->lock);
162 		hba->log_events = 0;
163 		cv_broadcast(&log->lock_cv);
164 		mutex_exit(&log->lock);
165 
166 		DELAYMS(1);
167 	}
168 	/* Destroy the lock */
169 	mutex_destroy(&log->lock);
170 	cv_destroy(&log->lock_cv);
171 
172 	/* Free the context buffers */
173 	for (i = 0; i < log->size; i++) {
174 		entry = &log->entry[i];
175 
176 		if (entry->bp && entry->size) {
177 			kmem_free(entry->bp, entry->size);
178 		}
179 	}
180 
181 	/* Free the log buffer */
182 	size = sizeof (emlxs_msg_entry_t) * log->size;
183 	kmem_free(log->entry, size);
184 
185 	/* Clear the log */
186 	bzero(log, sizeof (emlxs_msg_log_t));
187 
188 	return (1);
189 
190 } /* emlxs_msg_log_destroy() */
191 
192 
193 
194 uint32_t
195 emlxs_msg_log(emlxs_port_t *port, const uint32_t fileno, const uint32_t line,
196     void *bp, uint32_t size, emlxs_msg_t *msg, char *buffer)
197 {
198 	emlxs_hba_t *hba = HBA;
199 	emlxs_msg_entry_t *entry;
200 	emlxs_msg_entry_t *entry2;
201 	clock_t time;
202 	emlxs_msg_log_t *log;
203 	uint32_t last;
204 	uint32_t mask;
205 	emlxs_msg_t *msg2;
206 	uint32_t i;
207 
208 	/* Get the log file for this instance */
209 	log = &LOG;
210 
211 	/* Check if log is initialized */
212 	if (log->entry == NULL) {
213 
214 		if (port->vpi == 0) {
215 			cmn_err(CE_WARN, "?%s%d: message log not created. "
216 			    "log=%p", DRIVER_NAME, hba->ddiinst, (void *) log);
217 		} else {
218 			cmn_err(CE_WARN, "?%s%d.%d: message log not created. "
219 			    "log=%p", DRIVER_NAME, hba->ddiinst, port->vpi,
220 			    (void *) log);
221 		}
222 
223 		if (bp && size) {
224 			kmem_free(bp, size);
225 		}
226 		return (1);
227 	}
228 	mutex_enter(&log->lock);
229 
230 	/* Get the pointer to the last log entry */
231 	if (log->next == 0) {
232 		last = log->size - 1;
233 	} else {
234 		last = log->next - 1;
235 	}
236 	entry = &log->entry[last];
237 
238 	/* Check if this matches the last message */
239 	if ((entry->instance == log->instance) &&
240 	    (entry->vpi == port->vpi) &&
241 	    (entry->fileno == fileno) &&
242 	    (entry->line == line) &&
243 	    (entry->bp == bp) &&
244 	    (entry->size == size) &&
245 	    (entry->msg == msg) &&
246 	    (strcmp(entry->buffer, buffer) == 0)) {
247 		/* If the same message is being logged then increment */
248 		log->repeat++;
249 
250 		mutex_exit(&log->lock);
251 
252 		return (0);
253 	} else if (log->repeat) {
254 		/* Get the pointer to the next log entry */
255 		entry2 = &log->entry[log->next];
256 
257 		/* Increment and check the next entry index */
258 		if (++(log->next) >= log->size) {
259 			log->next = 0;
260 		}
261 		switch (entry->msg->level) {
262 		case EMLXS_DEBUG:
263 			msg2 = &emlxs_debug_msg;
264 			break;
265 
266 		case EMLXS_NOTICE:
267 			msg2 = &emlxs_notice_msg;
268 			break;
269 
270 		case EMLXS_WARNING:
271 			msg2 = &emlxs_warning_msg;
272 			break;
273 
274 		case EMLXS_ERROR:
275 			msg2 = &emlxs_error_msg;
276 			break;
277 
278 		case EMLXS_PANIC:
279 			msg2 = &emlxs_panic_msg;
280 			break;
281 
282 		case EMLXS_EVENT:
283 			msg2 = &emlxs_event_msg;
284 			break;
285 		}
286 
287 		/* Check if we are about to overwrite an event entry */
288 		if (entry2->msg && (entry2->msg->level == EMLXS_EVENT)) {
289 			/* Check if this event has not been acquired */
290 			if (log->count > (hba->hba_event.last_id + log->size)) {
291 				hba->hba_event.missed++;
292 			}
293 		}
294 		/* Free the old context buffer since we are about to erase it */
295 		if (entry2->bp && entry2->size) {
296 			kmem_free(entry2->bp, entry2->size);
297 		}
298 		/* Initialize */
299 		entry2->id = log->count++;
300 		entry2->fileno = entry->fileno;
301 		entry2->line = entry->line;
302 		entry2->bp = 0;
303 		entry2->size = 0;
304 		entry2->msg = msg2;
305 		entry2->instance = log->instance;
306 		entry2->vpi = port->vpi;
307 
308 		/* Save the additional info buffer */
309 		(void) sprintf(entry2->buffer,
310 		    "Last message repeated %d time(s).",
311 		    log->repeat);
312 
313 		/* Set the entry time stamp */
314 		(void) drv_getparm(LBOLT, &time);
315 		entry2->time = time - log->start_time;
316 
317 		log->repeat = 0;
318 	}
319 	/* Get the pointer to the next log entry */
320 	entry = &log->entry[log->next];
321 
322 	/* Increment and check the next entry index */
323 	if (++(log->next) >= log->size) {
324 		log->next = 0;
325 	}
326 	/* Check if we are about to overwrite an event entry */
327 	if (entry->msg && (entry->msg->level == EMLXS_EVENT)) {
328 		/* Check if this event has not been acquired */
329 		if (log->count > (hba->hba_event.last_id + log->size)) {
330 			hba->hba_event.missed++;
331 		}
332 	}
333 	/* Free the old context buffer since we are about to erase it */
334 	if (entry->bp && entry->size) {
335 		kmem_free(entry->bp, entry->size);
336 	}
337 	/* Initialize */
338 	entry->id = log->count++;
339 	entry->fileno = fileno;
340 	entry->line = line;
341 	entry->bp = bp;
342 	entry->size = size;
343 	entry->msg = msg;
344 	entry->instance = log->instance;
345 	entry->vpi = port->vpi;
346 
347 	/* Save the additional info buffer */
348 	(void) strncpy(entry->buffer, buffer, (MAX_LOG_INFO_LENGTH - 1));
349 	entry->buffer[MAX_LOG_INFO_LENGTH - 1] = 0;
350 
351 	/* Set the entry time stamp */
352 	(void) drv_getparm(LBOLT, &time);
353 	entry->time = time - log->start_time;
354 
355 	/* Check for a new event */
356 	if (msg->level == EMLXS_EVENT) {
357 		/* Update the event id */
358 		mask = msg->mask;
359 		for (i = 0; i < 32; i++) {
360 			if (mask & 0x01) {
361 				hba->hba_event.new++;
362 				log->event_id[i] = entry->id;
363 				cv_broadcast(&log->lock_cv);
364 				break;
365 			}
366 			mask >>= 1;
367 		}
368 	}
369 	mutex_exit(&log->lock);
370 
371 	return (0);
372 
373 } /* emlxs_msg_log() */
374 
375 
376 static uint32_t
377 emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg)
378 {
379 	emlxs_hba_t *hba = HBA;
380 
381 	switch (msg->level) {
382 	case EMLXS_DEBUG:
383 		if (msg->mask & emlxs_log_debugs) {
384 			return (1);
385 		}
386 		break;
387 
388 	case EMLXS_NOTICE:
389 		if (msg->mask & emlxs_log_notices) {
390 			return (1);
391 		}
392 		break;
393 
394 	case EMLXS_WARNING:
395 		if (msg->mask & emlxs_log_warnings) {
396 			return (1);
397 		}
398 		break;
399 
400 	case EMLXS_ERROR:
401 		if (msg->mask & emlxs_log_errors) {
402 			return (1);
403 		}
404 		break;
405 
406 	case EMLXS_EVENT:
407 		if (msg->mask & hba->log_events) {
408 			return (1);
409 		}
410 		break;
411 
412 	case EMLXS_PANIC:
413 		return (1);
414 	}
415 
416 	return (0);
417 
418 } /* emlxs_msg_log_check() */
419 
420 
421 static uint32_t
422 emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg)
423 {
424 	emlxs_hba_t *hba = HBA;
425 	emlxs_config_t *cfg;
426 	uint32_t rval = 0;
427 
428 	cfg = &CFG;
429 
430 	switch (msg->level) {
431 	case EMLXS_DEBUG:
432 		if (msg->mask & cfg[CFG_CONSOLE_DEBUGS].current) {
433 			rval |= 2;
434 		}
435 		if (msg->mask & cfg[CFG_LOG_DEBUGS].current) {
436 			rval |= 1;
437 		}
438 		break;
439 
440 	case EMLXS_NOTICE:
441 		if (msg->mask & cfg[CFG_CONSOLE_NOTICES].current) {
442 			rval |= 2;
443 		}
444 		if (msg->mask & cfg[CFG_LOG_NOTICES].current) {
445 			rval |= 1;
446 		}
447 		break;
448 
449 	case EMLXS_WARNING:
450 		if (msg->mask & cfg[CFG_CONSOLE_WARNINGS].current) {
451 			rval |= 2;
452 		}
453 		if (msg->mask & cfg[CFG_LOG_WARNINGS].current) {
454 			rval |= 1;
455 		}
456 		break;
457 
458 	case EMLXS_ERROR:
459 		if (msg->mask & cfg[CFG_CONSOLE_ERRORS].current) {
460 			rval |= 2;
461 		}
462 		if (msg->mask & cfg[CFG_LOG_ERRORS].current) {
463 			rval |= 1;
464 		}
465 		break;
466 
467 	case EMLXS_EVENT:
468 		/* Only print an event if it is being logged internally */
469 		if (msg->mask & hba->log_events) {
470 			if (msg->mask & cfg[CFG_CONSOLE_EVENTS].current) {
471 				rval |= 2;
472 			}
473 			if (msg->mask & cfg[CFG_LOG_EVENTS].current) {
474 				rval |= 1;
475 			}
476 		}
477 		break;
478 
479 	case EMLXS_PANIC:
480 	default:
481 		rval |= 1;
482 
483 	}
484 
485 	return (rval);
486 
487 } /* emlxs_msg_print_check() */
488 
489 
490 void
491 emlxs_msg_printf(emlxs_port_t *port, const uint32_t fileno, const uint32_t line,
492     void *bp, uint32_t size, emlxs_msg_t *msg, const char *fmt, ...)
493 {
494 	emlxs_hba_t *hba = HBA;
495 	va_list valist;
496 	char va_str[256];
497 	char msg_str[512];
498 	char *level;
499 	int32_t cmn_level;
500 	uint32_t rval;
501 	uint32_t logged;
502 	char driver[32];
503 
504 	va_str[0] = 0;
505 
506 	if (fmt) {
507 		va_start(valist, fmt);
508 		(void) vsprintf(va_str, fmt, valist);
509 		va_end(valist);
510 	}
511 	/* Check if msg should be logged */
512 	if ((logged = emlxs_msg_log_check(port, msg))) {
513 		/* Log the message */
514 		if (emlxs_msg_log(port, fileno, line, bp, size, msg, va_str)) {
515 			return;
516 		}
517 	}
518 	/* Check if msg should be printed */
519 	if (rval = emlxs_msg_print_check(port, msg)) {
520 		cmn_level = CE_CONT;
521 
522 		switch (msg->level) {
523 		case EMLXS_DEBUG:
524 			level = "  DEBUG";
525 			break;
526 
527 		case EMLXS_NOTICE:
528 			level = " NOTICE";
529 			break;
530 
531 		case EMLXS_WARNING:
532 			level = "WARNING";
533 			break;
534 
535 		case EMLXS_ERROR:
536 			level = "  ERROR";
537 			break;
538 
539 		case EMLXS_PANIC:
540 			cmn_level = CE_PANIC;
541 			level = "  PANIC";
542 			break;
543 
544 		case EMLXS_EVENT:
545 			level = "  EVENT";
546 			break;
547 
548 		default:
549 			level = "UNKNOWN";
550 			break;
551 		}
552 
553 		if (port->vpi == 0) {
554 			(void) sprintf(driver, "%s%d", DRIVER_NAME,
555 			    hba->ddiinst);
556 		} else {
557 			(void) sprintf(driver, "%s%d.%d", DRIVER_NAME,
558 			    hba->ddiinst, port->vpi);
559 		}
560 
561 		/* Generate the message string */
562 		if (msg->buffer[0] != 0) {
563 			if (va_str[0] != 0) {
564 				(void) sprintf(msg_str,
565 				    "[%2X.%04X]%s:%7s:%4d: %s (%s)\n",
566 				    fileno, line, driver, level, msg->id,
567 				    msg->buffer, va_str);
568 			} else {
569 				(void) sprintf(msg_str,
570 				    "[%2X.%04X]%s:%7s:%4d: %s\n",
571 				    fileno, line, driver, level, msg->id,
572 				    msg->buffer);
573 			}
574 		} else {
575 			if (va_str[0] != 0) {
576 				(void) sprintf(msg_str,
577 				    "[%2X.%04X]%s:%7s:%4d: (%s)\n",
578 				    fileno, line, driver, level, msg->id,
579 				    va_str);
580 			} else {
581 				(void) sprintf(msg_str,
582 				    "[%2X.%04X]%s:%7s:%4d\n",
583 				    fileno, line, driver, level, msg->id);
584 			}
585 		}
586 
587 		switch (rval) {
588 		case 1:	/* MESSAGE LOG ONLY */
589 			/* cmn_err(cmn_level, "!%s", msg_str); */
590 			/*
591 			 * Message log & console, if system booted in verbose
592 			 *   mode (CE_CONT only)
593 			 */
594 			cmn_err(cmn_level, "?%s", msg_str);
595 			break;
596 
597 		case 2:	/* CONSOLE ONLY */
598 			cmn_err(cmn_level, "^%s", msg_str);
599 			break;
600 
601 		case 3:	/* CONSOLE AND MESSAGE LOG */
602 			cmn_err(cmn_level, "%s", msg_str);
603 			break;
604 
605 		}
606 
607 	}
608 	/* If message was not logged, then free any context buffer provided */
609 	if (!logged && bp && size) {
610 		kmem_free(bp, size);
611 	}
612 	return;
613 
614 } /* emlxs_msg_printf() */
615 
616 
617 uint32_t
618 emlxs_msg_log_get(emlxs_hba_t *hba, emlxs_log_req_t *req,
619     emlxs_log_resp_t *resp)
620 {
621 	emlxs_msg_log_t *log;
622 	uint32_t first;
623 	uint32_t last;
624 	uint32_t count;
625 	uint32_t index;
626 	uint32_t i;
627 	char *resp_buf;
628 
629 	log = &LOG;
630 
631 	mutex_enter(&log->lock);
632 
633 	/* Check if buffer is empty */
634 	if (log->count == 0) {
635 		/* If so, exit now */
636 		resp->first = 0;
637 		resp->last = 0;
638 		resp->count = 0;
639 		mutex_exit(&log->lock);
640 
641 		return (1);
642 	}
643 	/* Get current log entry ranges */
644 
645 	/* Get last entry id saved */
646 	last = log->count - 1;
647 
648 	/* Check if request is out of current range */
649 	if (req->first > last) {
650 		/* if so, exit now */
651 		resp->first = last;
652 		resp->last = last;
653 		resp->count = 0;
654 		mutex_exit(&log->lock);
655 
656 		return (0);
657 	}
658 	/* Get oldest entry id and its index */
659 
660 	/* Check if buffer has already been filled once */
661 	if (log->count >= log->size) {
662 		first = log->count - log->size;
663 		index = log->next;
664 	} else {	/* Buffer not yet filled */
665 		first = 0;
666 		index = 0;
667 	}
668 
669 	/*
670 	 * Check if requested first message is greater than actual. If so,
671 	 * adjust for it.
672 	 */
673 	if (req->first > first) {
674 		/* Adjust entry index to first requested message */
675 		index += (req->first - first);
676 		if (index >= log->size) {
677 			index -= log->size;
678 		}
679 		first = req->first;
680 	}
681 	/* Get the total number of messages available for return */
682 	count = last - first + 1;
683 
684 	/* Check if requested count is less than actual.  If so, adjust it. */
685 	if (req->count < count) {
686 		count = req->count;
687 	}
688 	/* Fill in the response header */
689 	resp->count = count;
690 	resp->first = first;
691 	resp->last = last;
692 
693 	/* Fill the response buffer */
694 	resp_buf = (char *)resp + sizeof (emlxs_log_resp_t);
695 	for (i = 0; i < count; i++) {
696 		emlxs_msg_sprintf(resp_buf, &log->entry[index]);
697 
698 		/* Increment the response buffer */
699 		resp_buf += MAX_LOG_MSG_LENGTH;
700 
701 		/* Increment index */
702 		if (++index >= log->size) {
703 			index = 0;
704 		}
705 	}
706 
707 	mutex_exit(&log->lock);
708 
709 	return (1);
710 
711 } /* emlxs_msg_log_get() */
712 
713 
714 
715 static void
716 emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry)
717 {
718 	char *level;
719 	emlxs_msg_t *msg;
720 	uint32_t secs;
721 	uint32_t hsecs;
722 	char buf[256];
723 	uint32_t buflen;
724 	char driver[32];
725 
726 	msg = entry->msg;
727 	hsecs = (entry->time % 100);
728 	secs = entry->time / 100;
729 
730 	switch (msg->level) {
731 	case EMLXS_DEBUG:
732 		level = "  DEBUG";
733 		break;
734 
735 	case EMLXS_NOTICE:
736 		level = " NOTICE";
737 		break;
738 
739 	case EMLXS_WARNING:
740 		level = "WARNING";
741 		break;
742 
743 	case EMLXS_ERROR:
744 		level = "  ERROR";
745 		break;
746 
747 	case EMLXS_PANIC:
748 		level = "  PANIC";
749 		break;
750 
751 	case EMLXS_EVENT:
752 		level = "  EVENT";
753 		break;
754 
755 	default:
756 		level = "UNKNOWN";
757 		break;
758 	}
759 
760 	if (entry->vpi == 0) {
761 		(void) sprintf(driver, "%s%d", DRIVER_NAME, entry->instance);
762 	} else {
763 		(void) sprintf(driver, "%s%d.%d", DRIVER_NAME, entry->instance,
764 		    entry->vpi);
765 	}
766 
767 	/* Generate the message string */
768 	if (msg->buffer[0] != 0) {
769 		if (entry->buffer[0] != 0) {
770 			(void) sprintf(buf,
771 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s (%s)\n",
772 			    secs, hsecs, entry->id, entry->fileno, entry->line,
773 			    driver, level, msg->id, msg->buffer, entry->buffer);
774 
775 		} else {
776 			(void) sprintf(buf,
777 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s\n",
778 			    secs, hsecs, entry->id, entry->fileno, entry->line,
779 			    driver, level, msg->id, msg->buffer);
780 		}
781 	} else {
782 		if (entry->buffer[0] != 0) {
783 			(void) sprintf(buf,
784 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: (%s)\n",
785 			    secs, hsecs, entry->id, entry->fileno, entry->line,
786 			    driver, level, msg->id, entry->buffer);
787 		} else {
788 			(void) sprintf(buf,
789 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d\n",
790 			    secs, hsecs, entry->id, entry->fileno, entry->line,
791 			    driver, level, msg->id);
792 		}
793 	}
794 
795 	bzero(buffer, MAX_LOG_MSG_LENGTH);
796 	buflen = strlen(buf);
797 
798 	if (buflen > (MAX_LOG_MSG_LENGTH - 1)) {
799 		(void) strncpy(buffer, buf, (MAX_LOG_MSG_LENGTH - 2));
800 		buffer[MAX_LOG_MSG_LENGTH - 2] = '\n';
801 	} else {
802 		(void) strncpy(buffer, buf, buflen);
803 	}
804 
805 	return;
806 
807 } /* emlxs_msg_sprintf() */
808 
809 
810 
811 
812 void
813 emlxs_log_rscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size)
814 {
815 #ifdef DFC_SUPPORT
816 	uint8_t *bp;
817 	uint32_t *ptr;
818 
819 	/* Check if the event is being requested */
820 	/*
821 	 * if(!(hba->log_events & EVT_RSCN)) { return; }
822 	 */
823 
824 	if (size > MAX_RSCN_PAYLOAD) {
825 		size = MAX_RSCN_PAYLOAD;
826 	}
827 	size += sizeof (uint32_t);
828 
829 	/* Save a copy of the payload for the event log */
830 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
831 		return;
832 	}
833 	/*
834 	 * Buffer Format: word[0] = DID of the RSCN word[1] = RSCN Payload
835 	 */
836 	ptr = (uint32_t *)bp;
837 	*ptr++ = port->did;
838 	bcopy(payload, (char *)ptr, (size - sizeof (uint32_t)));
839 
840 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_rscn_event,
841 	    "bp=%p size=%d", bp, size);
842 
843 #endif	/* DFC_SUPPORT */
844 	return;
845 
846 } /* emlxs_log_rscn_event() */
847 
848 
849 void
850 emlxs_log_ct_event(emlxs_port_t *port, uint8_t *payload, uint32_t size,
851     uint32_t rxid)
852 {
853 #ifdef DFC_SUPPORT
854 	emlxs_hba_t *hba = HBA;
855 	uint8_t *bp;
856 	uint32_t *ptr;
857 
858 	/* Check if the event is being requested */
859 	if (!(hba->log_events & EVT_CT)) {
860 		return;
861 	}
862 	if (size > MAX_CT_PAYLOAD) {
863 		size = MAX_CT_PAYLOAD;
864 	}
865 	size += sizeof (uint32_t);
866 
867 	/* Save a copy of the payload for the event log */
868 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
869 		return;
870 	}
871 	/*
872 	 * Buffer Format: word[0] = RXID tag for outgoing reply to this CT
873 	 * request word[1] = CT Payload
874 	 */
875 	ptr = (uint32_t *)bp;
876 	*ptr++ = rxid;
877 
878 	bcopy(payload, (char *)ptr, (size - sizeof (uint32_t)));
879 
880 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_ct_event,
881 	    "bp=%p size=%d rxid=%x", bp, size, rxid);
882 
883 #endif	/* DFC_SUPPORT */
884 
885 	return;
886 
887 } /* emlxs_log_ct_event() */
888 
889 
890 void
891 emlxs_log_link_event(emlxs_port_t *port)
892 {
893 #ifdef DFC_SUPPORT
894 	emlxs_hba_t *hba = HBA;
895 	uint8_t *bp;
896 	dfc_linkinfo_t *linkinfo;
897 	uint8_t *byte;
898 	uint8_t *linkspeed;
899 	uint8_t *liptype;
900 	uint8_t *resv1;
901 	uint8_t *resv2;
902 	uint32_t size;
903 
904 	/* Check if the event is being requested */
905 	/*
906 	 * if(!(hba->log_events & EVT_LINK)) { return; }
907 	 */
908 	size = sizeof (dfc_linkinfo_t) + sizeof (uint32_t);
909 
910 	/* Save a copy of the buffer for the event log */
911 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
912 		return;
913 	}
914 	/*
915 	 * Buffer Format: word[0] = Linkspeed:8 word[0] = LIP_type:8 word[0]
916 	 * = resv1:8 word[0] = resv2:8 word[1] = dfc_linkinfo_t data
917 	 */
918 	byte = (uint8_t *)bp;
919 	linkspeed = &byte[0];
920 	liptype = &byte[1];
921 	resv1 = &byte[2];
922 	resv2 = &byte[3];
923 	linkinfo = (dfc_linkinfo_t *)& byte[4];
924 
925 	*resv1 = 0;
926 	*resv2 = 0;
927 
928 	if (hba->state <= FC_LINK_DOWN) {
929 		*linkspeed = 0;
930 		*liptype = 0;
931 	} else {
932 		/* Set linkspeed */
933 		if (hba->linkspeed == LA_2GHZ_LINK) {
934 			*linkspeed = HBA_PORTSPEED_2GBIT;
935 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
936 			*linkspeed = HBA_PORTSPEED_4GBIT;
937 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
938 			*linkspeed = HBA_PORTSPEED_8GBIT;
939 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
940 			*linkspeed = HBA_PORTSPEED_10GBIT;
941 		} else {
942 			*linkspeed = HBA_PORTSPEED_1GBIT;
943 		}
944 
945 		/* Set LIP type */
946 		*liptype = port->lip_type;
947 	}
948 
949 	bzero(linkinfo, sizeof (dfc_linkinfo_t));
950 
951 	linkinfo->a_linkEventTag = hba->link_event_tag;
952 	linkinfo->a_linkUp = HBASTATS.LinkUp;
953 	linkinfo->a_linkDown = HBASTATS.LinkDown;
954 	linkinfo->a_linkMulti = HBASTATS.LinkMultiEvent;
955 
956 	if (hba->state <= FC_LINK_DOWN) {
957 		linkinfo->a_linkState = LNK_DOWN;
958 		linkinfo->a_DID = port->prev_did;
959 	} else if (hba->state < FC_READY) {
960 		linkinfo->a_linkState = LNK_DISCOVERY;
961 	} else {
962 		linkinfo->a_linkState = LNK_READY;
963 	}
964 
965 	if (linkinfo->a_linkState != LNK_DOWN) {
966 		if (hba->topology == TOPOLOGY_LOOP) {
967 			if (hba->flag & FC_FABRIC_ATTACHED) {
968 				linkinfo->a_topology = LNK_PUBLIC_LOOP;
969 			} else {
970 				linkinfo->a_topology = LNK_LOOP;
971 			}
972 
973 			linkinfo->a_alpa = port->did & 0xff;
974 			linkinfo->a_DID = linkinfo->a_alpa;
975 			linkinfo->a_alpaCnt = port->alpa_map[0];
976 
977 			if (linkinfo->a_alpaCnt > 127) {
978 				linkinfo->a_alpaCnt = 127;
979 			}
980 			bcopy((void *) &port->alpa_map[1], linkinfo->a_alpaMap,
981 			    linkinfo->a_alpaCnt);
982 		} else {
983 			if (port->node_count == 1) {
984 				linkinfo->a_topology = LNK_PT2PT;
985 			} else {
986 				linkinfo->a_topology = LNK_FABRIC;
987 			}
988 
989 			linkinfo->a_DID = port->did;
990 		}
991 	}
992 	bcopy(&hba->wwpn, linkinfo->a_wwpName, 8);
993 	bcopy(&hba->wwnn, linkinfo->a_wwnName, 8);
994 
995 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_link_event,
996 	    "bp=%p size=%d tag=%x", bp, size, hba->link_event_tag);
997 
998 #endif	/* DFC_SUPPORT */
999 
1000 	return;
1001 
1002 } /* emlxs_log_link_event() */
1003 
1004 
1005 void
1006 emlxs_log_dump_event(emlxs_port_t *port, uint8_t *buffer, uint32_t size)
1007 {
1008 #ifdef DFC_SUPPORT
1009 	emlxs_hba_t *hba = HBA;
1010 	uint8_t *bp;
1011 
1012 	/* Check if the event is being requested */
1013 	if (!(hba->log_events & EVT_DUMP)) {
1014 		return;
1015 	}
1016 	if (buffer && size) {
1017 		/* Save a copy of the buffer for the event log */
1018 		if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
1019 			return;
1020 		}
1021 		bcopy(buffer, bp, size);
1022 	} else {
1023 		bp = NULL;
1024 		size = 0;
1025 	}
1026 
1027 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_dump_event,
1028 	    "bp=%p size=%d", bp, size);
1029 
1030 #endif	/* DFC_SUPPORT */
1031 
1032 	return;
1033 
1034 } /* emlxs_log_dump_event() */
1035 
1036 
1037 extern void
1038 emlxs_log_temp_event(emlxs_port_t *port, uint32_t type, uint32_t temp)
1039 {
1040 #ifdef DFC_SUPPORT
1041 	emlxs_hba_t *hba = HBA;
1042 	uint32_t *bp;
1043 	uint32_t size;
1044 
1045 	/* Check if the event is being requested */
1046 	if (!(hba->log_events & EVT_TEMP)) {
1047 		return;
1048 	}
1049 	size = 2 * sizeof (uint32_t);
1050 
1051 	if (!(bp = (uint32_t *)kmem_alloc(size, KM_NOSLEEP))) {
1052 		return;
1053 	}
1054 	bp[0] = type;
1055 	bp[1] = temp;
1056 
1057 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_temp_event,
1058 	    "type=%x temp=%d bp=%p size=%d", type, temp, bp, size);
1059 
1060 #endif	/* DFC_SUPPORT */
1061 
1062 	return;
1063 
1064 } /* emlxs_log_temp_event() */
1065 
1066 
1067 
1068 extern void
1069 emlxs_log_fcoe_event(emlxs_port_t *port, menlo_init_rsp_t *init_rsp)
1070 {
1071 #ifdef DFC_SUPPORT
1072 	emlxs_hba_t *hba = HBA;
1073 	uint8_t *bp;
1074 	uint32_t size;
1075 
1076 	/* Check if the event is being requested */
1077 	if (!(hba->log_events & EVT_FCOE)) {
1078 		return;
1079 	}
1080 	/* Check if this is a FCOE adapter */
1081 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
1082 		return;
1083 	}
1084 	size = sizeof (menlo_init_rsp_t);
1085 
1086 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
1087 		return;
1088 	}
1089 	bcopy((uint8_t *)init_rsp, bp, size);
1090 
1091 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_fcoe_event,
1092 	    "bp=%p size=%d", bp, size);
1093 
1094 #endif	/* DFC_SUPPORT */
1095 
1096 	return;
1097 
1098 } /* emlxs_log_fcoe_event() */
1099 
1100 
1101 
1102 #ifdef DFC_SUPPORT
1103 
1104 extern uint32_t
1105 emlxs_get_dfc_eventinfo(emlxs_port_t *port, HBA_EVENTINFO *eventinfo,
1106     uint32_t *eventcount, uint32_t *missed)
1107 {
1108 	emlxs_hba_t *hba = HBA;
1109 	emlxs_msg_log_t *log;
1110 	uint32_t first;
1111 	uint32_t last;
1112 	uint32_t count;
1113 	uint32_t index;
1114 	emlxs_msg_entry_t *entry;
1115 	dfc_linkinfo_t *linkinfo;
1116 	uint32_t *word;
1117 	uint8_t *byte;
1118 	uint8_t linkspeed;
1119 	uint8_t liptype;
1120 	fc_affected_id_t *aid;
1121 	uint32_t max_events;
1122 	uint32_t events;
1123 	emlxs_hba_event_t *hba_event;
1124 
1125 	if (!eventinfo || !eventcount || !missed) {
1126 		return (DFC_ARG_NULL);
1127 	}
1128 	hba_event = &hba->hba_event;
1129 	max_events = *eventcount;
1130 	*eventcount = 0;
1131 
1132 	log = &LOG;
1133 
1134 	mutex_enter(&log->lock);
1135 
1136 	/* Check if log is empty */
1137 	if (log->count == 0) {
1138 		/* Make sure everything is initialized */
1139 		hba_event->new = 0;
1140 		hba_event->missed = 0;
1141 		hba_event->last_id = 0;
1142 
1143 		mutex_exit(&log->lock);
1144 		return (0);
1145 	}
1146 	/* Safety check */
1147 	if (hba_event->last_id > (log->count - 1)) {
1148 		hba_event->last_id = log->count - 1;
1149 	}
1150 	/* Account for missed events */
1151 	if (hba_event->new > hba_event->missed) {
1152 		hba_event->new -= hba_event->missed;
1153 	} else {
1154 		hba_event->new = 0;
1155 	}
1156 
1157 	*missed = hba_event->missed;
1158 	hba_event->missed = 0;
1159 
1160 	if (!hba_event->new) {
1161 		hba_event->last_id = log->count;
1162 		mutex_exit(&log->lock);
1163 		return (0);
1164 	}
1165 	/* A new event has occurred since last acquisition */
1166 	/* Calculate the current buffer boundaries */
1167 
1168 	/* Get last entry id saved */
1169 	last = log->count - 1;
1170 
1171 	/* Get oldest entry id and its index */
1172 	/* Check if buffer has already been filled once */
1173 	if (log->count >= log->size) {
1174 		first = log->count - log->size;
1175 		index = log->next;
1176 	} else {	/* Buffer not yet filled */
1177 		first = 0;
1178 		index = 0;
1179 	}
1180 
1181 	/*
1182 	 * Check if requested first event is greater than actual. If so,
1183 	 * adjust for it.
1184 	 */
1185 	if (hba_event->last_id > first) {
1186 		/* Adjust entry index to first requested message */
1187 		index += (hba_event->last_id - first);
1188 		if (index >= log->size) {
1189 			index -= log->size;
1190 		}
1191 		first = hba_event->last_id;
1192 	}
1193 	/* Get the total number of new messages */
1194 	count = last - first;
1195 
1196 	/* Scan log for next event */
1197 	events = 0;
1198 	while (count-- && (events < max_events)) {
1199 		if (++index >= log->size) {
1200 			index = 0;
1201 		}
1202 		entry = &log->entry[index];
1203 
1204 		if (!entry->msg) {
1205 			break;
1206 		}
1207 		if ((entry->msg->level == EMLXS_EVENT) &&
1208 		    (entry->msg->mask & (EVT_LINK | EVT_RSCN))) {
1209 			/* Process this event */
1210 			switch (entry->msg->mask) {
1211 			case EVT_LINK:
1212 				byte = (uint8_t *)entry->bp;
1213 				linkspeed = byte[0];
1214 				liptype = byte[1];
1215 				linkinfo = (dfc_linkinfo_t *)& byte[4];
1216 
1217 				if (linkinfo->a_linkState == LNK_DOWN) {
1218 					eventinfo->EventCode =
1219 					    HBA_EVENT_LINK_DOWN;
1220 					eventinfo->Event.Link_EventInfo.
1221 					    PortFcId = linkinfo->a_DID;
1222 					eventinfo->Event.Link_EventInfo.
1223 					    Reserved[0] = 0;
1224 					eventinfo->Event.Link_EventInfo.
1225 					    Reserved[1] = 0;
1226 					eventinfo->Event.Link_EventInfo.
1227 					    Reserved[2] = 0;
1228 				} else {
1229 					eventinfo->EventCode =
1230 					    HBA_EVENT_LINK_UP;
1231 					eventinfo->Event.Link_EventInfo.
1232 					    PortFcId = linkinfo->a_DID;
1233 
1234 					if ((linkinfo->a_topology ==
1235 					    LNK_PUBLIC_LOOP) ||
1236 					    (linkinfo->a_topology ==
1237 					    LNK_LOOP)) {
1238 						eventinfo->Event.Link_EventInfo.
1239 						    Reserved[0] = 2;
1240 					} else {
1241 						eventinfo->Event.Link_EventInfo.
1242 						    Reserved[0] = 1;
1243 					}
1244 
1245 					eventinfo->Event.Link_EventInfo.
1246 					    Reserved[1] = liptype;
1247 					eventinfo->Event.Link_EventInfo.
1248 					    Reserved[2] = linkspeed;
1249 				}
1250 
1251 				break;
1252 
1253 			case EVT_RSCN:
1254 				word = (uint32_t *)entry->bp;
1255 				eventinfo->EventCode = HBA_EVENT_RSCN;
1256 				eventinfo->Event.RSCN_EventInfo.PortFcId =
1257 				    word[0] & 0xFFFFFF;
1258 				/* word[1] is the RSCN payload command */
1259 
1260 				aid = (fc_affected_id_t *)& word[2];
1261 
1262 				switch (aid->aff_format) {
1263 				case 0:	/* Port */
1264 					eventinfo->Event.RSCN_EventInfo.
1265 					    NPortPage =
1266 					    aid->aff_d_id & 0x00ffffff;
1267 					break;
1268 
1269 				case 1:	/* Area */
1270 					eventinfo->Event.RSCN_EventInfo.
1271 					    NPortPage =
1272 					    aid->aff_d_id & 0x00ffff00;
1273 					break;
1274 
1275 				case 2:	/* Domain */
1276 					eventinfo->Event.RSCN_EventInfo.
1277 					    NPortPage =
1278 					    aid->aff_d_id & 0x00ff0000;
1279 					break;
1280 
1281 				case 3:	/* Network */
1282 					eventinfo->Event.RSCN_EventInfo.
1283 					    NPortPage = 0;
1284 					break;
1285 				}
1286 
1287 				eventinfo->Event.RSCN_EventInfo.Reserved[0] = 0;
1288 				eventinfo->Event.RSCN_EventInfo.Reserved[1] = 0;
1289 
1290 				break;
1291 			}
1292 
1293 			eventinfo++;
1294 			events++;
1295 		}
1296 		hba_event->last_id = entry->id;
1297 	}
1298 
1299 	/* Adjust new count */
1300 	if (!count || (events >= hba_event->new)) {
1301 		hba_event->new = 0;
1302 	} else {
1303 		hba_event->new -= events;
1304 	}
1305 
1306 	/* Return number of events acquired */
1307 	*eventcount = events;
1308 
1309 	mutex_exit(&log->lock);
1310 
1311 	return (0);
1312 
1313 } /* emlxs_get_dfc_eventinfo() */
1314 
1315 
1316 uint32_t
1317 emlxs_get_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
1318     uint32_t sleep)
1319 {
1320 	emlxs_hba_t *hba = HBA;
1321 	emlxs_msg_log_t *log;
1322 	uint32_t first;
1323 	uint32_t last;
1324 	uint32_t count;
1325 	uint32_t index;
1326 	uint32_t mask;
1327 	uint32_t i;
1328 	emlxs_msg_entry_t *entry;
1329 	uint32_t size;
1330 	uint32_t rc;
1331 
1332 	size = 0;
1333 
1334 	if (dfc_event->dataout && dfc_event->size) {
1335 		size = dfc_event->size;
1336 	}
1337 	dfc_event->size = 0;
1338 
1339 	/* Get the log file pointer */
1340 	log = &LOG;
1341 
1342 	/* Calculate the event index */
1343 	mask = dfc_event->event;
1344 	for (i = 0; i < 32; i++) {
1345 		if (mask & 0x01) {
1346 			break;
1347 		}
1348 		mask >>= 1;
1349 	}
1350 	if (i == 32) {
1351 		return (DFC_ARG_INVALID);
1352 	}
1353 	mutex_enter(&log->lock);
1354 
1355 	/* Check if log is empty */
1356 	if (log->count == 0) {
1357 		/* Make sure everything is initialized */
1358 		log->event_id[i] = 0;
1359 		dfc_event->last_id = 0;
1360 	} else {
1361 		/* Check ranges for safety */
1362 		if (log->event_id[i] > (log->count - 1)) {
1363 			log->event_id[i] = log->count - 1;
1364 		}
1365 		if (dfc_event->last_id > log->event_id[i]) {
1366 			dfc_event->last_id = log->event_id[i];
1367 		}
1368 	}
1369 
1370 wait_for_event:
1371 
1372 	/* Check if no new event has ocurred */
1373 	if (dfc_event->last_id == log->event_id[i]) {
1374 		if (!sleep) {
1375 			mutex_exit(&log->lock);
1376 			return (0);
1377 		}
1378 		/*
1379 		 * While event is still active and no new event has been
1380 		 * logged
1381 		 */
1382 		while ((dfc_event->event & hba->log_events) &&
1383 		    (dfc_event->last_id == log->event_id[i])) {
1384 			rc = cv_wait_sig(&log->lock_cv, &log->lock);
1385 
1386 			/* Check if thread was killed by kernel */
1387 			if (rc == 0) {
1388 				dfc_event->pid = 0;
1389 				dfc_event->event = 0;
1390 				mutex_exit(&log->lock);
1391 				return (0);
1392 			}
1393 		}
1394 
1395 		/*
1396 		 * If the event is no longer registered then return
1397 		 * immediately
1398 		 */
1399 		if (!(dfc_event->event & hba->log_events)) {
1400 			mutex_exit(&log->lock);
1401 			return (0);
1402 		}
1403 	}
1404 	/* !!! An event has occurred since last_id !!! */
1405 
1406 	/* Check if event data is not being requested */
1407 	if (!size) {
1408 		/* If so, then just return the last event id */
1409 		dfc_event->last_id = log->event_id[i];
1410 
1411 		mutex_exit(&log->lock);
1412 		return (0);
1413 	}
1414 	/* !!! The requester wants the next event buffer !!! */
1415 
1416 	/* Calculate the current buffer boundaries */
1417 
1418 	/* Get last entry id saved */
1419 	last = log->count - 1;
1420 
1421 	/* Get oldest entry id and its index */
1422 	/* Check if buffer has already been filled once */
1423 	if (log->count >= log->size) {
1424 		first = log->count - log->size;
1425 		index = log->next;
1426 	} else {	/* Buffer not yet filled */
1427 		first = 0;
1428 		index = 0;
1429 	}
1430 
1431 	/* Check to see if the buffer has wrapped since the last event */
1432 	if (first > log->event_id[i]) {
1433 		/* Update last_id to the last known event */
1434 		dfc_event->last_id = log->event_id[i];
1435 
1436 		/* Try waiting again if we can */
1437 		goto wait_for_event;
1438 	}
1439 	/*
1440 	 * Check if requested first event is greater than actual. If so,
1441 	 * adjust for it.
1442 	 */
1443 	if (dfc_event->last_id > first) {
1444 		/* Adjust entry index to first requested message */
1445 		index += (dfc_event->last_id - first);
1446 		if (index >= log->size) {
1447 			index -= log->size;
1448 		}
1449 		first = dfc_event->last_id;
1450 	}
1451 	/* Get the total number of new messages */
1452 	count = last - first + 1;
1453 
1454 	/* Scan log for next event */
1455 	while (count--) {
1456 		if (++index >= log->size) {
1457 			index = 0;
1458 		}
1459 		entry = &log->entry[index];
1460 
1461 		if ((entry->msg->level == EMLXS_EVENT) &&
1462 		    (entry->msg->mask == dfc_event->event)) {
1463 			break;
1464 		}
1465 	}
1466 
1467 	/*
1468 	 * Check if no new event was found in the current log buffer.
1469 	 * This would indicate that the buffer wrapped since that last event
1470 	 */
1471 	if (!count) {
1472 		/* Update last_id to the last known event */
1473 		dfc_event->last_id = log->event_id[i];
1474 
1475 		/* Try waiting again if we can */
1476 		goto wait_for_event;
1477 	}
1478 	/* !!! Next event found !!! */
1479 
1480 	/* Copy the context buffer to the buffer provided */
1481 	if (entry->bp && entry->size) {
1482 		if (entry->size < size) {
1483 			size = entry->size;
1484 		}
1485 		if (ddi_copyout((void *) entry->bp, dfc_event->dataout, size,
1486 		    dfc_event->mode) != 0) {
1487 			mutex_exit(&log->lock);
1488 
1489 			return (DFC_COPYOUT_ERROR);
1490 		}
1491 		dfc_event->size = size;
1492 	}
1493 	dfc_event->last_id = entry->id;
1494 
1495 	mutex_exit(&log->lock);
1496 	return (0);
1497 
1498 } /* emlxs_get_dfc_event() */
1499 
1500 
1501 uint32_t
1502 emlxs_kill_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event)
1503 {
1504 	emlxs_hba_t *hba = HBA;
1505 	emlxs_msg_log_t *log;
1506 
1507 	/* Get the log file pointer */
1508 	log = &LOG;
1509 
1510 	mutex_enter(&log->lock);
1511 	dfc_event->pid = 0;
1512 	dfc_event->event = 0;
1513 	cv_broadcast(&log->lock_cv);
1514 	mutex_exit(&log->lock);
1515 
1516 	return (0);
1517 
1518 } /* emlxs_kill_dfc_event() */
1519 
1520 
1521 
1522 #endif	/* DFC_SUPPORT */
1523