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