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