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 /*
23291a2b48SSukumar Swaminathan  * Copyright 2009 Emulex.  All rights reserved.
24fcf3ce44SJohn Forte  * Use is subject to License terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27291a2b48SSukumar Swaminathan #define	DEF_MSG_STRUCT	/* Needed for emlxs_messages.h in emlxs_msg.h */
28291a2b48SSukumar 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 
34291a2b48SSukumar Swaminathan uint32_t emlxs_log_size		= 2048;
35291a2b48SSukumar Swaminathan uint32_t emlxs_log_debugs	= 0x7FFFFFFF;
36291a2b48SSukumar Swaminathan uint32_t emlxs_log_notices	= 0xFFFFFFFF;
37291a2b48SSukumar Swaminathan uint32_t emlxs_log_warnings	= 0xFFFFFFFF;
38291a2b48SSukumar Swaminathan uint32_t emlxs_log_errors	= 0xFFFFFFFF;
39fcf3ce44SJohn Forte 
40291a2b48SSukumar Swaminathan static uint32_t	emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg);
41291a2b48SSukumar Swaminathan static uint32_t	emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg);
42291a2b48SSukumar 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;
56291a2b48SSukumar 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",
62291a2b48SSukumar Swaminathan 		    DRIVER_NAME, hba->ddiinst, (void *)log);
63fcf3ce44SJohn Forte 		return (0);
64fcf3ce44SJohn Forte 	}
65291a2b48SSukumar 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))) {
71291a2b48SSukumar Swaminathan 		cmn_err(CE_WARN,
72291a2b48SSukumar Swaminathan 		    "?%s%d: Unable to allocate log memory. log=%p",
73291a2b48SSukumar Swaminathan 		    DRIVER_NAME, hba->ddiinst, (void *)log);
74fcf3ce44SJohn Forte 		return (0);
75fcf3ce44SJohn Forte 	}
76291a2b48SSukumar 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 */
94291a2b48SSukumar 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;
100291a2b48SSukumar Swaminathan 		ret =
101291a2b48SSukumar 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) {
105291a2b48SSukumar Swaminathan 			cmn_err(CE_WARN,
106291a2b48SSukumar Swaminathan 			    "?%s%d: Unable to allocate temporary interrupt "
107291a2b48SSukumar Swaminathan 			    "handle. ret=%d actual=%d", DRIVER_NAME,
108291a2b48SSukumar 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 		}
116291a2b48SSukumar 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) {
121291a2b48SSukumar Swaminathan 			cmn_err(CE_WARN,
122291a2b48SSukumar Swaminathan 			    "?%s%d: Unable to get interrupt priority. ret=%d",
123291a2b48SSukumar 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 		}
131291a2b48SSukumar Swaminathan 
132fcf3ce44SJohn Forte 		/* Create the log mutex lock */
133fcf3ce44SJohn Forte 		mutex_init(&log->lock, buf, MUTEX_DRIVER,
134291a2b48SSukumar 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 
143291a2b48SSukumar 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) {
156291a2b48SSukumar Swaminathan 		cmn_err(CE_WARN,
157291a2b48SSukumar Swaminathan 		    "?%s%d: message log already destroyed. log=%p",
158291a2b48SSukumar Swaminathan 		    DRIVER_NAME, hba->ddiinst, (void *)log);
159fcf3ce44SJohn Forte 
160fcf3ce44SJohn Forte 		return (1);
161fcf3ce44SJohn Forte 	}
162291a2b48SSukumar Swaminathan 
163291a2b48SSukumar Swaminathan 	/* If events are being logged there might be */
164291a2b48SSukumar 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 	}
173291a2b48SSukumar 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 
196291a2b48SSukumar Swaminathan }  /* emlxs_msg_log_destroy() */
197291a2b48SSukumar Swaminathan 
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte uint32_t
200fcf3ce44SJohn Forte emlxs_msg_log(emlxs_port_t *port, const uint32_t fileno, const uint32_t line,
201fcf3ce44SJohn Forte     void *bp, uint32_t size, emlxs_msg_t *msg, char *buffer)
202fcf3ce44SJohn Forte {
203fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
204fcf3ce44SJohn Forte 	emlxs_msg_entry_t *entry;
205fcf3ce44SJohn Forte 	emlxs_msg_entry_t *entry2;
206fcf3ce44SJohn Forte 	clock_t time;
207fcf3ce44SJohn Forte 	emlxs_msg_log_t *log;
208fcf3ce44SJohn Forte 	uint32_t last;
209fcf3ce44SJohn Forte 	uint32_t mask;
210fcf3ce44SJohn Forte 	emlxs_msg_t *msg2;
211291a2b48SSukumar Swaminathan 	uint32_t rxid = 0;
212fcf3ce44SJohn Forte 	uint32_t i;
213fcf3ce44SJohn Forte 
214fcf3ce44SJohn Forte 	/* Get the log file for this instance */
215fcf3ce44SJohn Forte 	log = &LOG;
216fcf3ce44SJohn Forte 
217fcf3ce44SJohn Forte 	/* Check if log is initialized */
218fcf3ce44SJohn Forte 	if (log->entry == NULL) {
219fcf3ce44SJohn Forte 
220fcf3ce44SJohn Forte 		if (port->vpi == 0) {
221291a2b48SSukumar Swaminathan 			cmn_err(CE_WARN,
222291a2b48SSukumar Swaminathan 			    "?%s%d: message log not created. log=%p",
223291a2b48SSukumar Swaminathan 			    DRIVER_NAME, hba->ddiinst, (void *)log);
224fcf3ce44SJohn Forte 		} else {
225291a2b48SSukumar Swaminathan 			cmn_err(CE_WARN,
226291a2b48SSukumar Swaminathan 			    "?%s%d.%d: message log not created. log=%p",
227291a2b48SSukumar Swaminathan 			    DRIVER_NAME, hba->ddiinst, port->vpi,
228291a2b48SSukumar Swaminathan 			    (void *)log);
229fcf3ce44SJohn Forte 		}
230fcf3ce44SJohn Forte 
231fcf3ce44SJohn Forte 		if (bp && size) {
232fcf3ce44SJohn Forte 			kmem_free(bp, size);
233fcf3ce44SJohn Forte 		}
234291a2b48SSukumar Swaminathan 
235fcf3ce44SJohn Forte 		return (1);
236fcf3ce44SJohn Forte 	}
237291a2b48SSukumar Swaminathan 
238fcf3ce44SJohn Forte 	mutex_enter(&log->lock);
239fcf3ce44SJohn Forte 
240fcf3ce44SJohn Forte 	/* Get the pointer to the last log entry */
241fcf3ce44SJohn Forte 	if (log->next == 0) {
242fcf3ce44SJohn Forte 		last = log->size - 1;
243fcf3ce44SJohn Forte 	} else {
244fcf3ce44SJohn Forte 		last = log->next - 1;
245fcf3ce44SJohn Forte 	}
246fcf3ce44SJohn Forte 	entry = &log->entry[last];
247fcf3ce44SJohn Forte 
248fcf3ce44SJohn Forte 	/* Check if this matches the last message */
249fcf3ce44SJohn Forte 	if ((entry->instance == log->instance) &&
250fcf3ce44SJohn Forte 	    (entry->vpi == port->vpi) &&
251fcf3ce44SJohn Forte 	    (entry->fileno == fileno) &&
252fcf3ce44SJohn Forte 	    (entry->line == line) &&
253fcf3ce44SJohn Forte 	    (entry->bp == bp) &&
254fcf3ce44SJohn Forte 	    (entry->size == size) &&
255fcf3ce44SJohn Forte 	    (entry->msg == msg) &&
256fcf3ce44SJohn Forte 	    (strcmp(entry->buffer, buffer) == 0)) {
257fcf3ce44SJohn Forte 		/* If the same message is being logged then increment */
258fcf3ce44SJohn Forte 		log->repeat++;
259fcf3ce44SJohn Forte 
260fcf3ce44SJohn Forte 		mutex_exit(&log->lock);
261fcf3ce44SJohn Forte 
262fcf3ce44SJohn Forte 		return (0);
263fcf3ce44SJohn Forte 	} else if (log->repeat) {
264fcf3ce44SJohn Forte 		/* Get the pointer to the next log entry */
265fcf3ce44SJohn Forte 		entry2 = &log->entry[log->next];
266fcf3ce44SJohn Forte 
267fcf3ce44SJohn Forte 		/* Increment and check the next entry index */
268fcf3ce44SJohn Forte 		if (++(log->next) >= log->size) {
269fcf3ce44SJohn Forte 			log->next = 0;
270fcf3ce44SJohn Forte 		}
271291a2b48SSukumar Swaminathan 
272fcf3ce44SJohn Forte 		switch (entry->msg->level) {
273fcf3ce44SJohn Forte 		case EMLXS_DEBUG:
274fcf3ce44SJohn Forte 			msg2 = &emlxs_debug_msg;
275fcf3ce44SJohn Forte 			break;
276fcf3ce44SJohn Forte 
277fcf3ce44SJohn Forte 		case EMLXS_NOTICE:
278fcf3ce44SJohn Forte 			msg2 = &emlxs_notice_msg;
279fcf3ce44SJohn Forte 			break;
280fcf3ce44SJohn Forte 
281fcf3ce44SJohn Forte 		case EMLXS_WARNING:
282fcf3ce44SJohn Forte 			msg2 = &emlxs_warning_msg;
283fcf3ce44SJohn Forte 			break;
284fcf3ce44SJohn Forte 
285fcf3ce44SJohn Forte 		case EMLXS_ERROR:
286fcf3ce44SJohn Forte 			msg2 = &emlxs_error_msg;
287fcf3ce44SJohn Forte 			break;
288fcf3ce44SJohn Forte 
289fcf3ce44SJohn Forte 		case EMLXS_PANIC:
290fcf3ce44SJohn Forte 			msg2 = &emlxs_panic_msg;
291fcf3ce44SJohn Forte 			break;
292fcf3ce44SJohn Forte 
293fcf3ce44SJohn Forte 		case EMLXS_EVENT:
294fcf3ce44SJohn Forte 			msg2 = &emlxs_event_msg;
295fcf3ce44SJohn Forte 			break;
296fcf3ce44SJohn Forte 		}
297fcf3ce44SJohn Forte 
298fcf3ce44SJohn Forte 		/* Check if we are about to overwrite an event entry */
299fcf3ce44SJohn Forte 		if (entry2->msg && (entry2->msg->level == EMLXS_EVENT)) {
300fcf3ce44SJohn Forte 			/* Check if this event has not been acquired */
301fcf3ce44SJohn Forte 			if (log->count > (hba->hba_event.last_id + log->size)) {
302fcf3ce44SJohn Forte 				hba->hba_event.missed++;
303728bdc9bSSukumar Swaminathan 
304291a2b48SSukumar Swaminathan 				if ((entry2->msg->mask == EVT_CT) &&
305291a2b48SSukumar Swaminathan 				    !(entry2->flag & EMLX_EVENT_DONE)) {
306728bdc9bSSukumar Swaminathan 					/* Abort exchange */
307728bdc9bSSukumar Swaminathan 					rxid = *((uint32_t *)entry2->bp);
308728bdc9bSSukumar Swaminathan 				}
309fcf3ce44SJohn Forte 			}
310fcf3ce44SJohn Forte 		}
311291a2b48SSukumar Swaminathan 
312fcf3ce44SJohn Forte 		/* Free the old context buffer since we are about to erase it */
313fcf3ce44SJohn Forte 		if (entry2->bp && entry2->size) {
314fcf3ce44SJohn Forte 			kmem_free(entry2->bp, entry2->size);
315fcf3ce44SJohn Forte 		}
316291a2b48SSukumar Swaminathan 
317fcf3ce44SJohn Forte 		/* Initialize */
318fcf3ce44SJohn Forte 		entry2->id = log->count++;
319fcf3ce44SJohn Forte 		entry2->fileno = entry->fileno;
320fcf3ce44SJohn Forte 		entry2->line = entry->line;
321fcf3ce44SJohn Forte 		entry2->bp = 0;
322fcf3ce44SJohn Forte 		entry2->size = 0;
323fcf3ce44SJohn Forte 		entry2->msg = msg2;
324fcf3ce44SJohn Forte 		entry2->instance = log->instance;
325fcf3ce44SJohn Forte 		entry2->vpi = port->vpi;
326291a2b48SSukumar Swaminathan 		entry2->flag = 0;
327fcf3ce44SJohn Forte 
328fcf3ce44SJohn Forte 		/* Save the additional info buffer */
329fcf3ce44SJohn Forte 		(void) sprintf(entry2->buffer,
330fcf3ce44SJohn Forte 		    "Last message repeated %d time(s).",
331fcf3ce44SJohn Forte 		    log->repeat);
332fcf3ce44SJohn Forte 
333fcf3ce44SJohn Forte 		/* Set the entry time stamp */
334fcf3ce44SJohn Forte 		(void) drv_getparm(LBOLT, &time);
335fcf3ce44SJohn Forte 		entry2->time = time - log->start_time;
336fcf3ce44SJohn Forte 
337fcf3ce44SJohn Forte 		log->repeat = 0;
338fcf3ce44SJohn Forte 	}
339291a2b48SSukumar Swaminathan 
340fcf3ce44SJohn Forte 	/* Get the pointer to the next log entry */
341fcf3ce44SJohn Forte 	entry = &log->entry[log->next];
342fcf3ce44SJohn Forte 
343fcf3ce44SJohn Forte 	/* Increment and check the next entry index */
344fcf3ce44SJohn Forte 	if (++(log->next) >= log->size) {
345fcf3ce44SJohn Forte 		log->next = 0;
346fcf3ce44SJohn Forte 	}
347291a2b48SSukumar Swaminathan 
348fcf3ce44SJohn Forte 	/* Check if we are about to overwrite an event entry */
349fcf3ce44SJohn Forte 	if (entry->msg && (entry->msg->level == EMLXS_EVENT)) {
350fcf3ce44SJohn Forte 		/* Check if this event has not been acquired */
351fcf3ce44SJohn Forte 		if (log->count > (hba->hba_event.last_id + log->size)) {
352fcf3ce44SJohn Forte 			hba->hba_event.missed++;
353728bdc9bSSukumar Swaminathan 
354291a2b48SSukumar Swaminathan 			if ((entry->msg->mask == EVT_CT) &&
355291a2b48SSukumar Swaminathan 			    !(entry->flag & EMLX_EVENT_DONE)) {
356291a2b48SSukumar Swaminathan 
357728bdc9bSSukumar Swaminathan 				/* Abort exchange */
358728bdc9bSSukumar Swaminathan 				rxid = *((uint32_t *)entry->bp);
359728bdc9bSSukumar Swaminathan 			}
360fcf3ce44SJohn Forte 		}
361fcf3ce44SJohn Forte 	}
362291a2b48SSukumar Swaminathan 
363fcf3ce44SJohn Forte 	/* Free the old context buffer since we are about to erase it */
364fcf3ce44SJohn Forte 	if (entry->bp && entry->size) {
365fcf3ce44SJohn Forte 		kmem_free(entry->bp, entry->size);
366fcf3ce44SJohn Forte 	}
367291a2b48SSukumar Swaminathan 
368fcf3ce44SJohn Forte 	/* Initialize */
369fcf3ce44SJohn Forte 	entry->id = log->count++;
370fcf3ce44SJohn Forte 	entry->fileno = fileno;
371fcf3ce44SJohn Forte 	entry->line = line;
372fcf3ce44SJohn Forte 	entry->bp = bp;
373fcf3ce44SJohn Forte 	entry->size = size;
374fcf3ce44SJohn Forte 	entry->msg = msg;
375fcf3ce44SJohn Forte 	entry->instance = log->instance;
376fcf3ce44SJohn Forte 	entry->vpi = port->vpi;
377291a2b48SSukumar Swaminathan 	entry->flag = 0;
378fcf3ce44SJohn Forte 
379fcf3ce44SJohn Forte 	/* Save the additional info buffer */
380fcf3ce44SJohn Forte 	(void) strncpy(entry->buffer, buffer, (MAX_LOG_INFO_LENGTH - 1));
381fcf3ce44SJohn Forte 	entry->buffer[MAX_LOG_INFO_LENGTH - 1] = 0;
382fcf3ce44SJohn Forte 
383fcf3ce44SJohn Forte 	/* Set the entry time stamp */
384fcf3ce44SJohn Forte 	(void) drv_getparm(LBOLT, &time);
385fcf3ce44SJohn Forte 	entry->time = time - log->start_time;
386fcf3ce44SJohn Forte 
387fcf3ce44SJohn Forte 	/* Check for a new event */
388fcf3ce44SJohn Forte 	if (msg->level == EMLXS_EVENT) {
389fcf3ce44SJohn Forte 		/* Update the event id */
390fcf3ce44SJohn Forte 		mask = msg->mask;
391fcf3ce44SJohn Forte 		for (i = 0; i < 32; i++) {
392fcf3ce44SJohn Forte 			if (mask & 0x01) {
393fcf3ce44SJohn Forte 				hba->hba_event.new++;
394fcf3ce44SJohn Forte 				log->event_id[i] = entry->id;
395fcf3ce44SJohn Forte 				cv_broadcast(&log->lock_cv);
396fcf3ce44SJohn Forte 				break;
397fcf3ce44SJohn Forte 			}
398291a2b48SSukumar Swaminathan 
399fcf3ce44SJohn Forte 			mask >>= 1;
400fcf3ce44SJohn Forte 		}
401fcf3ce44SJohn Forte 	}
402291a2b48SSukumar Swaminathan 
403fcf3ce44SJohn Forte 	mutex_exit(&log->lock);
404fcf3ce44SJohn Forte 
405291a2b48SSukumar Swaminathan 	if (rxid) {
406*bb63f56eSSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_abort_ct_exchange,
407*bb63f56eSSukumar Swaminathan 		    (void *)port, (void *)((unsigned long)rxid));
408291a2b48SSukumar Swaminathan 	}
409291a2b48SSukumar Swaminathan 
410fcf3ce44SJohn Forte 	return (0);
411fcf3ce44SJohn Forte 
412291a2b48SSukumar Swaminathan }  /* emlxs_msg_log() */
413fcf3ce44SJohn Forte 
414fcf3ce44SJohn Forte 
415fcf3ce44SJohn Forte static uint32_t
416fcf3ce44SJohn Forte emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg)
417fcf3ce44SJohn Forte {
418fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
419fcf3ce44SJohn Forte 
420fcf3ce44SJohn Forte 	switch (msg->level) {
421fcf3ce44SJohn Forte 	case EMLXS_DEBUG:
422fcf3ce44SJohn Forte 		if (msg->mask & emlxs_log_debugs) {
423fcf3ce44SJohn Forte 			return (1);
424fcf3ce44SJohn Forte 		}
425fcf3ce44SJohn Forte 		break;
426fcf3ce44SJohn Forte 
427fcf3ce44SJohn Forte 	case EMLXS_NOTICE:
428fcf3ce44SJohn Forte 		if (msg->mask & emlxs_log_notices) {
429fcf3ce44SJohn Forte 			return (1);
430fcf3ce44SJohn Forte 		}
431fcf3ce44SJohn Forte 		break;
432fcf3ce44SJohn Forte 
433fcf3ce44SJohn Forte 	case EMLXS_WARNING:
434fcf3ce44SJohn Forte 		if (msg->mask & emlxs_log_warnings) {
435fcf3ce44SJohn Forte 			return (1);
436fcf3ce44SJohn Forte 		}
437fcf3ce44SJohn Forte 		break;
438fcf3ce44SJohn Forte 
439fcf3ce44SJohn Forte 	case EMLXS_ERROR:
440fcf3ce44SJohn Forte 		if (msg->mask & emlxs_log_errors) {
441fcf3ce44SJohn Forte 			return (1);
442fcf3ce44SJohn Forte 		}
443fcf3ce44SJohn Forte 		break;
444fcf3ce44SJohn Forte 
445fcf3ce44SJohn Forte 	case EMLXS_EVENT:
446fcf3ce44SJohn Forte 		if (msg->mask & hba->log_events) {
447fcf3ce44SJohn Forte 			return (1);
448fcf3ce44SJohn Forte 		}
449291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT
450291a2b48SSukumar Swaminathan 		if (msg->mask & port->sd_reg_events) {
451291a2b48SSukumar Swaminathan 			return (1);
452291a2b48SSukumar Swaminathan 		}
453291a2b48SSukumar Swaminathan #endif /* SAN_DIAG_SUPPORT */
454fcf3ce44SJohn Forte 		break;
455fcf3ce44SJohn Forte 
456fcf3ce44SJohn Forte 	case EMLXS_PANIC:
457fcf3ce44SJohn Forte 		return (1);
458fcf3ce44SJohn Forte 	}
459fcf3ce44SJohn Forte 
460fcf3ce44SJohn Forte 	return (0);
461fcf3ce44SJohn Forte 
462291a2b48SSukumar Swaminathan }  /* emlxs_msg_log_check() */
463fcf3ce44SJohn Forte 
464fcf3ce44SJohn Forte 
465fcf3ce44SJohn Forte static uint32_t
466fcf3ce44SJohn Forte emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg)
467fcf3ce44SJohn Forte {
468fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
469fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
470fcf3ce44SJohn Forte 	uint32_t rval = 0;
471fcf3ce44SJohn Forte 
472fcf3ce44SJohn Forte 	cfg = &CFG;
473fcf3ce44SJohn Forte 
474fcf3ce44SJohn Forte 	switch (msg->level) {
475fcf3ce44SJohn Forte 	case EMLXS_DEBUG:
476fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_CONSOLE_DEBUGS].current) {
477fcf3ce44SJohn Forte 			rval |= 2;
478fcf3ce44SJohn Forte 		}
479291a2b48SSukumar Swaminathan 
480fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_LOG_DEBUGS].current) {
481fcf3ce44SJohn Forte 			rval |= 1;
482fcf3ce44SJohn Forte 		}
483291a2b48SSukumar Swaminathan 
484fcf3ce44SJohn Forte 		break;
485fcf3ce44SJohn Forte 
486fcf3ce44SJohn Forte 	case EMLXS_NOTICE:
487fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_CONSOLE_NOTICES].current) {
488fcf3ce44SJohn Forte 			rval |= 2;
489fcf3ce44SJohn Forte 		}
490291a2b48SSukumar Swaminathan 
491fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_LOG_NOTICES].current) {
492fcf3ce44SJohn Forte 			rval |= 1;
493fcf3ce44SJohn Forte 		}
494291a2b48SSukumar Swaminathan 
495fcf3ce44SJohn Forte 		break;
496fcf3ce44SJohn Forte 
497fcf3ce44SJohn Forte 	case EMLXS_WARNING:
498fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_CONSOLE_WARNINGS].current) {
499fcf3ce44SJohn Forte 			rval |= 2;
500fcf3ce44SJohn Forte 		}
501291a2b48SSukumar Swaminathan 
502fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_LOG_WARNINGS].current) {
503fcf3ce44SJohn Forte 			rval |= 1;
504fcf3ce44SJohn Forte 		}
505291a2b48SSukumar Swaminathan 
506fcf3ce44SJohn Forte 		break;
507fcf3ce44SJohn Forte 
508fcf3ce44SJohn Forte 	case EMLXS_ERROR:
509fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_CONSOLE_ERRORS].current) {
510fcf3ce44SJohn Forte 			rval |= 2;
511fcf3ce44SJohn Forte 		}
512291a2b48SSukumar Swaminathan 
513fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_LOG_ERRORS].current) {
514fcf3ce44SJohn Forte 			rval |= 1;
515fcf3ce44SJohn Forte 		}
516fcf3ce44SJohn Forte 		break;
517fcf3ce44SJohn Forte 
518fcf3ce44SJohn Forte 	case EMLXS_EVENT:
519fcf3ce44SJohn Forte 		/* Only print an event if it is being logged internally */
520fcf3ce44SJohn Forte 		if (msg->mask & hba->log_events) {
521fcf3ce44SJohn Forte 			if (msg->mask & cfg[CFG_CONSOLE_EVENTS].current) {
522fcf3ce44SJohn Forte 				rval |= 2;
523fcf3ce44SJohn Forte 			}
524291a2b48SSukumar Swaminathan 
525fcf3ce44SJohn Forte 			if (msg->mask & cfg[CFG_LOG_EVENTS].current) {
526fcf3ce44SJohn Forte 				rval |= 1;
527fcf3ce44SJohn Forte 			}
528fcf3ce44SJohn Forte 		}
529fcf3ce44SJohn Forte 		break;
530fcf3ce44SJohn Forte 
531fcf3ce44SJohn Forte 	case EMLXS_PANIC:
532fcf3ce44SJohn Forte 	default:
533fcf3ce44SJohn Forte 		rval |= 1;
534fcf3ce44SJohn Forte 
535fcf3ce44SJohn Forte 	}
536fcf3ce44SJohn Forte 
537fcf3ce44SJohn Forte 	return (rval);
538fcf3ce44SJohn Forte 
539291a2b48SSukumar Swaminathan }  /* emlxs_msg_print_check() */
540fcf3ce44SJohn Forte 
541fcf3ce44SJohn Forte 
542fcf3ce44SJohn Forte void
543291a2b48SSukumar Swaminathan emlxs_msg_printf(emlxs_port_t *port, const uint32_t fileno,
544291a2b48SSukumar Swaminathan     const uint32_t line, void *bp, uint32_t size, emlxs_msg_t *msg,
545291a2b48SSukumar Swaminathan     const char *fmt, ...)
546fcf3ce44SJohn Forte {
547fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
548fcf3ce44SJohn Forte 	va_list valist;
549fcf3ce44SJohn Forte 	char va_str[256];
550fcf3ce44SJohn Forte 	char msg_str[512];
551fcf3ce44SJohn Forte 	char *level;
552fcf3ce44SJohn Forte 	int32_t cmn_level;
553fcf3ce44SJohn Forte 	uint32_t rval;
554fcf3ce44SJohn Forte 	uint32_t logged;
555fcf3ce44SJohn Forte 	char driver[32];
556fcf3ce44SJohn Forte 
557fcf3ce44SJohn Forte 	va_str[0] = 0;
558fcf3ce44SJohn Forte 
559fcf3ce44SJohn Forte 	if (fmt) {
560fcf3ce44SJohn Forte 		va_start(valist, fmt);
561fcf3ce44SJohn Forte 		(void) vsprintf(va_str, fmt, valist);
562fcf3ce44SJohn Forte 		va_end(valist);
563fcf3ce44SJohn Forte 	}
564291a2b48SSukumar Swaminathan 
565291a2b48SSukumar Swaminathan #ifdef FMA_SUPPORT
566291a2b48SSukumar Swaminathan 	/*
567291a2b48SSukumar Swaminathan 	 * Don't post fault event or/and error event to fmd
568291a2b48SSukumar Swaminathan 	 * if physical port was not bounded yet.
569291a2b48SSukumar Swaminathan 	 */
570*bb63f56eSSukumar Swaminathan 	if (msg->fm_ereport_code) {
571*bb63f56eSSukumar Swaminathan 		emlxs_fm_ereport(hba, msg->fm_ereport_code);
572*bb63f56eSSukumar Swaminathan 	}
573291a2b48SSukumar Swaminathan 
574*bb63f56eSSukumar Swaminathan 	if (msg->fm_impact_code) {
575*bb63f56eSSukumar Swaminathan 		emlxs_fm_service_impact(hba, msg->fm_impact_code);
576291a2b48SSukumar Swaminathan 	}
577291a2b48SSukumar Swaminathan #endif	/* FMA_SUPPORT */
578291a2b48SSukumar Swaminathan 
579fcf3ce44SJohn Forte 	/* Check if msg should be logged */
580fcf3ce44SJohn Forte 	if ((logged = emlxs_msg_log_check(port, msg))) {
581fcf3ce44SJohn Forte 		/* Log the message */
582fcf3ce44SJohn Forte 		if (emlxs_msg_log(port, fileno, line, bp, size, msg, va_str)) {
583fcf3ce44SJohn Forte 			return;
584fcf3ce44SJohn Forte 		}
585fcf3ce44SJohn Forte 	}
586291a2b48SSukumar Swaminathan 
587fcf3ce44SJohn Forte 	/* Check if msg should be printed */
588fcf3ce44SJohn Forte 	if (rval = emlxs_msg_print_check(port, msg)) {
589fcf3ce44SJohn Forte 		cmn_level = CE_CONT;
590fcf3ce44SJohn Forte 
591fcf3ce44SJohn Forte 		switch (msg->level) {
592fcf3ce44SJohn Forte 		case EMLXS_DEBUG:
593fcf3ce44SJohn Forte 			level = "  DEBUG";
594fcf3ce44SJohn Forte 			break;
595fcf3ce44SJohn Forte 
596fcf3ce44SJohn Forte 		case EMLXS_NOTICE:
597fcf3ce44SJohn Forte 			level = " NOTICE";
598fcf3ce44SJohn Forte 			break;
599fcf3ce44SJohn Forte 
600fcf3ce44SJohn Forte 		case EMLXS_WARNING:
601fcf3ce44SJohn Forte 			level = "WARNING";
602fcf3ce44SJohn Forte 			break;
603fcf3ce44SJohn Forte 
604fcf3ce44SJohn Forte 		case EMLXS_ERROR:
605fcf3ce44SJohn Forte 			level = "  ERROR";
606fcf3ce44SJohn Forte 			break;
607fcf3ce44SJohn Forte 
608fcf3ce44SJohn Forte 		case EMLXS_PANIC:
609fcf3ce44SJohn Forte 			cmn_level = CE_PANIC;
610fcf3ce44SJohn Forte 			level = "  PANIC";
611fcf3ce44SJohn Forte 			break;
612fcf3ce44SJohn Forte 
613fcf3ce44SJohn Forte 		case EMLXS_EVENT:
614fcf3ce44SJohn Forte 			level = "  EVENT";
615fcf3ce44SJohn Forte 			break;
616fcf3ce44SJohn Forte 
617fcf3ce44SJohn Forte 		default:
618fcf3ce44SJohn Forte 			level = "UNKNOWN";
619fcf3ce44SJohn Forte 			break;
620fcf3ce44SJohn Forte 		}
621fcf3ce44SJohn Forte 
622fcf3ce44SJohn Forte 		if (port->vpi == 0) {
623fcf3ce44SJohn Forte 			(void) sprintf(driver, "%s%d", DRIVER_NAME,
624fcf3ce44SJohn Forte 			    hba->ddiinst);
625fcf3ce44SJohn Forte 		} else {
626fcf3ce44SJohn Forte 			(void) sprintf(driver, "%s%d.%d", DRIVER_NAME,
627fcf3ce44SJohn Forte 			    hba->ddiinst, port->vpi);
628fcf3ce44SJohn Forte 		}
629fcf3ce44SJohn Forte 
630fcf3ce44SJohn Forte 		/* Generate the message string */
631fcf3ce44SJohn Forte 		if (msg->buffer[0] != 0) {
632fcf3ce44SJohn Forte 			if (va_str[0] != 0) {
633fcf3ce44SJohn Forte 				(void) sprintf(msg_str,
634291a2b48SSukumar Swaminathan 				    "[%2X.%04X]%s:%7s:%4d: %s (%s)\n", fileno,
635291a2b48SSukumar Swaminathan 				    line, driver, level, msg->id, msg->buffer,
636291a2b48SSukumar Swaminathan 				    va_str);
637fcf3ce44SJohn Forte 			} else {
638fcf3ce44SJohn Forte 				(void) sprintf(msg_str,
639fcf3ce44SJohn Forte 				    "[%2X.%04X]%s:%7s:%4d: %s\n",
640fcf3ce44SJohn Forte 				    fileno, line, driver, level, msg->id,
641fcf3ce44SJohn Forte 				    msg->buffer);
642fcf3ce44SJohn Forte 			}
643fcf3ce44SJohn Forte 		} else {
644fcf3ce44SJohn Forte 			if (va_str[0] != 0) {
645fcf3ce44SJohn Forte 				(void) sprintf(msg_str,
646291a2b48SSukumar Swaminathan 				    "[%2X.%04X]%s:%7s:%4d: (%s)\n", fileno,
647291a2b48SSukumar Swaminathan 				    line, driver, level, msg->id, va_str);
648fcf3ce44SJohn Forte 			} else {
649fcf3ce44SJohn Forte 				(void) sprintf(msg_str,
650fcf3ce44SJohn Forte 				    "[%2X.%04X]%s:%7s:%4d\n",
651fcf3ce44SJohn Forte 				    fileno, line, driver, level, msg->id);
652fcf3ce44SJohn Forte 			}
653fcf3ce44SJohn Forte 		}
654fcf3ce44SJohn Forte 
655fcf3ce44SJohn Forte 		switch (rval) {
656fcf3ce44SJohn Forte 		case 1:	/* MESSAGE LOG ONLY */
657291a2b48SSukumar Swaminathan 			/* Message log & console, if system booted in */
658291a2b48SSukumar Swaminathan 			/* verbose mode (CE_CONT only) */
659fcf3ce44SJohn Forte 			cmn_err(cmn_level, "?%s", msg_str);
660fcf3ce44SJohn Forte 			break;
661fcf3ce44SJohn Forte 
662fcf3ce44SJohn Forte 		case 2:	/* CONSOLE ONLY */
663fcf3ce44SJohn Forte 			cmn_err(cmn_level, "^%s", msg_str);
664fcf3ce44SJohn Forte 			break;
665fcf3ce44SJohn Forte 
666fcf3ce44SJohn Forte 		case 3:	/* CONSOLE AND MESSAGE LOG */
667fcf3ce44SJohn Forte 			cmn_err(cmn_level, "%s", msg_str);
668fcf3ce44SJohn Forte 			break;
669fcf3ce44SJohn Forte 
670fcf3ce44SJohn Forte 		}
671fcf3ce44SJohn Forte 
672fcf3ce44SJohn Forte 	}
673291a2b48SSukumar Swaminathan 
674fcf3ce44SJohn Forte 	/* If message was not logged, then free any context buffer provided */
675fcf3ce44SJohn Forte 	if (!logged && bp && size) {
676fcf3ce44SJohn Forte 		kmem_free(bp, size);
677fcf3ce44SJohn Forte 	}
678291a2b48SSukumar Swaminathan 
679fcf3ce44SJohn Forte 	return;
680fcf3ce44SJohn Forte 
681291a2b48SSukumar Swaminathan }  /* emlxs_msg_printf() */
682fcf3ce44SJohn Forte 
683fcf3ce44SJohn Forte 
684fcf3ce44SJohn Forte uint32_t
685fcf3ce44SJohn Forte emlxs_msg_log_get(emlxs_hba_t *hba, emlxs_log_req_t *req,
686fcf3ce44SJohn Forte     emlxs_log_resp_t *resp)
687fcf3ce44SJohn Forte {
688fcf3ce44SJohn Forte 	emlxs_msg_log_t *log;
689fcf3ce44SJohn Forte 	uint32_t first;
690fcf3ce44SJohn Forte 	uint32_t last;
691fcf3ce44SJohn Forte 	uint32_t count;
692fcf3ce44SJohn Forte 	uint32_t index;
693fcf3ce44SJohn Forte 	uint32_t i;
694fcf3ce44SJohn Forte 	char *resp_buf;
695fcf3ce44SJohn Forte 
696fcf3ce44SJohn Forte 	log = &LOG;
697fcf3ce44SJohn Forte 
698fcf3ce44SJohn Forte 	mutex_enter(&log->lock);
699fcf3ce44SJohn Forte 
700fcf3ce44SJohn Forte 	/* Check if buffer is empty */
701fcf3ce44SJohn Forte 	if (log->count == 0) {
702fcf3ce44SJohn Forte 		/* If so, exit now */
703fcf3ce44SJohn Forte 		resp->first = 0;
704fcf3ce44SJohn Forte 		resp->last = 0;
705fcf3ce44SJohn Forte 		resp->count = 0;
706fcf3ce44SJohn Forte 		mutex_exit(&log->lock);
707fcf3ce44SJohn Forte 
708fcf3ce44SJohn Forte 		return (1);
709fcf3ce44SJohn Forte 	}
710291a2b48SSukumar Swaminathan 
711fcf3ce44SJohn Forte 	/* Get current log entry ranges */
712fcf3ce44SJohn Forte 
713fcf3ce44SJohn Forte 	/* Get last entry id saved */
714fcf3ce44SJohn Forte 	last = log->count - 1;
715fcf3ce44SJohn Forte 
716fcf3ce44SJohn Forte 	/* Check if request is out of current range */
717fcf3ce44SJohn Forte 	if (req->first > last) {
718fcf3ce44SJohn Forte 		/* if so, exit now */
719fcf3ce44SJohn Forte 		resp->first = last;
720fcf3ce44SJohn Forte 		resp->last = last;
721fcf3ce44SJohn Forte 		resp->count = 0;
722fcf3ce44SJohn Forte 		mutex_exit(&log->lock);
723fcf3ce44SJohn Forte 
724fcf3ce44SJohn Forte 		return (0);
725fcf3ce44SJohn Forte 	}
726291a2b48SSukumar Swaminathan 
727fcf3ce44SJohn Forte 	/* Get oldest entry id and its index */
728fcf3ce44SJohn Forte 
729fcf3ce44SJohn Forte 	/* Check if buffer has already been filled once */
730fcf3ce44SJohn Forte 	if (log->count >= log->size) {
731fcf3ce44SJohn Forte 		first = log->count - log->size;
732fcf3ce44SJohn Forte 		index = log->next;
733fcf3ce44SJohn Forte 	} else {	/* Buffer not yet filled */
734291a2b48SSukumar Swaminathan 
735fcf3ce44SJohn Forte 		first = 0;
736fcf3ce44SJohn Forte 		index = 0;
737fcf3ce44SJohn Forte 	}
738fcf3ce44SJohn Forte 
739291a2b48SSukumar Swaminathan 	/* Check if requested first message is greater than actual. */
740291a2b48SSukumar Swaminathan 	/* If so, adjust for it.  */
741fcf3ce44SJohn Forte 	if (req->first > first) {
742fcf3ce44SJohn Forte 		/* Adjust entry index to first requested message */
743fcf3ce44SJohn Forte 		index += (req->first - first);
744fcf3ce44SJohn Forte 		if (index >= log->size) {
745fcf3ce44SJohn Forte 			index -= log->size;
746fcf3ce44SJohn Forte 		}
747291a2b48SSukumar Swaminathan 
748fcf3ce44SJohn Forte 		first = req->first;
749fcf3ce44SJohn Forte 	}
750291a2b48SSukumar Swaminathan 
751fcf3ce44SJohn Forte 	/* Get the total number of messages available for return */
752fcf3ce44SJohn Forte 	count = last - first + 1;
753fcf3ce44SJohn Forte 
754fcf3ce44SJohn Forte 	/* Check if requested count is less than actual.  If so, adjust it. */
755fcf3ce44SJohn Forte 	if (req->count < count) {
756fcf3ce44SJohn Forte 		count = req->count;
757fcf3ce44SJohn Forte 	}
758291a2b48SSukumar Swaminathan 
759fcf3ce44SJohn Forte 	/* Fill in the response header */
760fcf3ce44SJohn Forte 	resp->count = count;
761fcf3ce44SJohn Forte 	resp->first = first;
762fcf3ce44SJohn Forte 	resp->last = last;
763fcf3ce44SJohn Forte 
764fcf3ce44SJohn Forte 	/* Fill the response buffer */
765fcf3ce44SJohn Forte 	resp_buf = (char *)resp + sizeof (emlxs_log_resp_t);
766fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
767fcf3ce44SJohn Forte 		emlxs_msg_sprintf(resp_buf, &log->entry[index]);
768fcf3ce44SJohn Forte 
769fcf3ce44SJohn Forte 		/* Increment the response buffer */
770fcf3ce44SJohn Forte 		resp_buf += MAX_LOG_MSG_LENGTH;
771fcf3ce44SJohn Forte 
772fcf3ce44SJohn Forte 		/* Increment index */
773fcf3ce44SJohn Forte 		if (++index >= log->size) {
774fcf3ce44SJohn Forte 			index = 0;
775fcf3ce44SJohn Forte 		}
776fcf3ce44SJohn Forte 	}
777fcf3ce44SJohn Forte 
778fcf3ce44SJohn Forte 	mutex_exit(&log->lock);
779fcf3ce44SJohn Forte 
780fcf3ce44SJohn Forte 	return (1);
781fcf3ce44SJohn Forte 
782291a2b48SSukumar Swaminathan }  /* emlxs_msg_log_get() */
783fcf3ce44SJohn Forte 
784fcf3ce44SJohn Forte 
785fcf3ce44SJohn Forte 
786fcf3ce44SJohn Forte static void
787fcf3ce44SJohn Forte emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry)
788fcf3ce44SJohn Forte {
789fcf3ce44SJohn Forte 	char *level;
790fcf3ce44SJohn Forte 	emlxs_msg_t *msg;
791fcf3ce44SJohn Forte 	uint32_t secs;
792fcf3ce44SJohn Forte 	uint32_t hsecs;
793fcf3ce44SJohn Forte 	char buf[256];
794fcf3ce44SJohn Forte 	uint32_t buflen;
795fcf3ce44SJohn Forte 	char driver[32];
796fcf3ce44SJohn Forte 
797fcf3ce44SJohn Forte 	msg = entry->msg;
798fcf3ce44SJohn Forte 	hsecs = (entry->time % 100);
799fcf3ce44SJohn Forte 	secs = entry->time / 100;
800fcf3ce44SJohn Forte 
801fcf3ce44SJohn Forte 	switch (msg->level) {
802fcf3ce44SJohn Forte 	case EMLXS_DEBUG:
803fcf3ce44SJohn Forte 		level = "  DEBUG";
804fcf3ce44SJohn Forte 		break;
805fcf3ce44SJohn Forte 
806fcf3ce44SJohn Forte 	case EMLXS_NOTICE:
807fcf3ce44SJohn Forte 		level = " NOTICE";
808fcf3ce44SJohn Forte 		break;
809fcf3ce44SJohn Forte 
810fcf3ce44SJohn Forte 	case EMLXS_WARNING:
811fcf3ce44SJohn Forte 		level = "WARNING";
812fcf3ce44SJohn Forte 		break;
813fcf3ce44SJohn Forte 
814fcf3ce44SJohn Forte 	case EMLXS_ERROR:
815fcf3ce44SJohn Forte 		level = "  ERROR";
816fcf3ce44SJohn Forte 		break;
817fcf3ce44SJohn Forte 
818fcf3ce44SJohn Forte 	case EMLXS_PANIC:
819fcf3ce44SJohn Forte 		level = "  PANIC";
820fcf3ce44SJohn Forte 		break;
821fcf3ce44SJohn Forte 
822fcf3ce44SJohn Forte 	case EMLXS_EVENT:
823fcf3ce44SJohn Forte 		level = "  EVENT";
824fcf3ce44SJohn Forte 		break;
825fcf3ce44SJohn Forte 
826fcf3ce44SJohn Forte 	default:
827fcf3ce44SJohn Forte 		level = "UNKNOWN";
828fcf3ce44SJohn Forte 		break;
829fcf3ce44SJohn Forte 	}
830fcf3ce44SJohn Forte 
831fcf3ce44SJohn Forte 	if (entry->vpi == 0) {
832fcf3ce44SJohn Forte 		(void) sprintf(driver, "%s%d", DRIVER_NAME, entry->instance);
833fcf3ce44SJohn Forte 	} else {
834fcf3ce44SJohn Forte 		(void) sprintf(driver, "%s%d.%d", DRIVER_NAME, entry->instance,
835fcf3ce44SJohn Forte 		    entry->vpi);
836fcf3ce44SJohn Forte 	}
837fcf3ce44SJohn Forte 
838fcf3ce44SJohn Forte 	/* Generate the message string */
839fcf3ce44SJohn Forte 	if (msg->buffer[0] != 0) {
840fcf3ce44SJohn Forte 		if (entry->buffer[0] != 0) {
841fcf3ce44SJohn Forte 			(void) sprintf(buf,
842fcf3ce44SJohn Forte 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s (%s)\n",
843291a2b48SSukumar Swaminathan 			    secs, hsecs, entry->id, entry->fileno,
844291a2b48SSukumar Swaminathan 			    entry->line, driver, level, msg->id, msg->buffer,
845291a2b48SSukumar Swaminathan 			    entry->buffer);
846fcf3ce44SJohn Forte 
847fcf3ce44SJohn Forte 		} else {
848fcf3ce44SJohn Forte 			(void) sprintf(buf,
849291a2b48SSukumar Swaminathan 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s\n", secs,
850291a2b48SSukumar Swaminathan 			    hsecs, entry->id, entry->fileno, entry->line,
851fcf3ce44SJohn Forte 			    driver, level, msg->id, msg->buffer);
852fcf3ce44SJohn Forte 		}
853fcf3ce44SJohn Forte 	} else {
854fcf3ce44SJohn Forte 		if (entry->buffer[0] != 0) {
855fcf3ce44SJohn Forte 			(void) sprintf(buf,
856fcf3ce44SJohn Forte 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: (%s)\n",
857291a2b48SSukumar Swaminathan 			    secs, hsecs, entry->id, entry->fileno,
858291a2b48SSukumar Swaminathan 			    entry->line, driver, level, msg->id,
859291a2b48SSukumar Swaminathan 			    entry->buffer);
860fcf3ce44SJohn Forte 		} else {
861fcf3ce44SJohn Forte 			(void) sprintf(buf,
862fcf3ce44SJohn Forte 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d\n",
863291a2b48SSukumar Swaminathan 			    secs, hsecs, entry->id, entry->fileno,
864291a2b48SSukumar Swaminathan 			    entry->line, driver, level, msg->id);
865fcf3ce44SJohn Forte 		}
866fcf3ce44SJohn Forte 	}
867fcf3ce44SJohn Forte 
868fcf3ce44SJohn Forte 	bzero(buffer, MAX_LOG_MSG_LENGTH);
869fcf3ce44SJohn Forte 	buflen = strlen(buf);
870fcf3ce44SJohn Forte 
871fcf3ce44SJohn Forte 	if (buflen > (MAX_LOG_MSG_LENGTH - 1)) {
872fcf3ce44SJohn Forte 		(void) strncpy(buffer, buf, (MAX_LOG_MSG_LENGTH - 2));
873fcf3ce44SJohn Forte 		buffer[MAX_LOG_MSG_LENGTH - 2] = '\n';
874fcf3ce44SJohn Forte 	} else {
875fcf3ce44SJohn Forte 		(void) strncpy(buffer, buf, buflen);
876fcf3ce44SJohn Forte 	}
877fcf3ce44SJohn Forte 
878fcf3ce44SJohn Forte 	return;
879fcf3ce44SJohn Forte 
880291a2b48SSukumar Swaminathan }  /* emlxs_msg_sprintf() */
881fcf3ce44SJohn Forte 
882fcf3ce44SJohn Forte 
883fcf3ce44SJohn Forte 
884fcf3ce44SJohn Forte 
885fcf3ce44SJohn Forte void
886fcf3ce44SJohn Forte emlxs_log_rscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size)
887fcf3ce44SJohn Forte {
888fcf3ce44SJohn Forte #ifdef DFC_SUPPORT
889291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
890fcf3ce44SJohn Forte 	uint8_t *bp;
891fcf3ce44SJohn Forte 	uint32_t *ptr;
892fcf3ce44SJohn Forte 
893fcf3ce44SJohn Forte 	/* Check if the event is being requested */
894291a2b48SSukumar Swaminathan 	if (!(hba->log_events & EVT_RSCN)) {
895291a2b48SSukumar Swaminathan 		return;
896291a2b48SSukumar Swaminathan 	}
897fcf3ce44SJohn Forte 
898fcf3ce44SJohn Forte 	if (size > MAX_RSCN_PAYLOAD) {
899fcf3ce44SJohn Forte 		size = MAX_RSCN_PAYLOAD;
900fcf3ce44SJohn Forte 	}
901291a2b48SSukumar Swaminathan 
902fcf3ce44SJohn Forte 	size += sizeof (uint32_t);
903fcf3ce44SJohn Forte 
904fcf3ce44SJohn Forte 	/* Save a copy of the payload for the event log */
905fcf3ce44SJohn Forte 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
906fcf3ce44SJohn Forte 		return;
907fcf3ce44SJohn Forte 	}
908291a2b48SSukumar Swaminathan 
909291a2b48SSukumar Swaminathan 
910fcf3ce44SJohn Forte 	/*
911291a2b48SSukumar Swaminathan 	 * Buffer Format:
912291a2b48SSukumar Swaminathan 	 *	word[0] = DID of the RSCN
913291a2b48SSukumar Swaminathan 	 *	word[1] = RSCN Payload
914fcf3ce44SJohn Forte 	 */
915fcf3ce44SJohn Forte 	ptr = (uint32_t *)bp;
916fcf3ce44SJohn Forte 	*ptr++ = port->did;
917fcf3ce44SJohn Forte 	bcopy(payload, (char *)ptr, (size - sizeof (uint32_t)));
918fcf3ce44SJohn Forte 
919fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_rscn_event,
920fcf3ce44SJohn Forte 	    "bp=%p size=%d", bp, size);
921fcf3ce44SJohn Forte 
922291a2b48SSukumar Swaminathan #endif /* DFC_SUPPORT */
923fcf3ce44SJohn Forte 	return;
924fcf3ce44SJohn Forte 
925291a2b48SSukumar Swaminathan }  /* emlxs_log_rscn_event() */
926291a2b48SSukumar Swaminathan 
927291a2b48SSukumar Swaminathan 
928291a2b48SSukumar Swaminathan void
929291a2b48SSukumar Swaminathan emlxs_log_vportrscn_event(emlxs_port_t *port, uint8_t *payload, uint32_t size)
930291a2b48SSukumar Swaminathan {
931291a2b48SSukumar Swaminathan #ifdef DFC_SUPPORT
932291a2b48SSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
933291a2b48SSukumar Swaminathan 	uint8_t *bp;
934291a2b48SSukumar Swaminathan 	uint8_t *ptr;
935291a2b48SSukumar Swaminathan 
936291a2b48SSukumar Swaminathan 	/* Check if the event is being requested */
937291a2b48SSukumar Swaminathan 	if (!(hba->log_events & EVT_VPORTRSCN)) {
938291a2b48SSukumar Swaminathan 		return;
939291a2b48SSukumar Swaminathan 	}
940291a2b48SSukumar Swaminathan 
941291a2b48SSukumar Swaminathan 	if (size > MAX_RSCN_PAYLOAD) {
942291a2b48SSukumar Swaminathan 		size = MAX_RSCN_PAYLOAD;
943291a2b48SSukumar Swaminathan 	}
944291a2b48SSukumar Swaminathan 
945291a2b48SSukumar Swaminathan 	/* Save a copy of the payload for the event log */
946291a2b48SSukumar Swaminathan 	if (!(bp =
947291a2b48SSukumar Swaminathan 	    (uint8_t *)kmem_alloc(size + sizeof (NAME_TYPE), KM_NOSLEEP))) {
948291a2b48SSukumar Swaminathan 		return;
949291a2b48SSukumar Swaminathan 	}
950291a2b48SSukumar Swaminathan 
951291a2b48SSukumar Swaminathan 
952291a2b48SSukumar Swaminathan 	/*
953291a2b48SSukumar Swaminathan 	 * Buffer Format:
954291a2b48SSukumar Swaminathan 	 *	word[0 - 4] = WWPN of the RSCN
955291a2b48SSukumar Swaminathan 	 *	word[5] = RSCN Payload
956291a2b48SSukumar Swaminathan 	 */
957291a2b48SSukumar Swaminathan 	ptr = bp;
958291a2b48SSukumar Swaminathan 	bcopy(&port->wwpn, ptr, sizeof (NAME_TYPE));
959291a2b48SSukumar Swaminathan 	ptr += sizeof (NAME_TYPE);
960291a2b48SSukumar Swaminathan 	bcopy(payload, ptr, size);
961291a2b48SSukumar Swaminathan 
962291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size + sizeof (NAME_TYPE),
963291a2b48SSukumar Swaminathan 	    &emlxs_vportrscn_event, "bp=%p size=%d", bp, size);
964291a2b48SSukumar Swaminathan 
965291a2b48SSukumar Swaminathan #endif /* DFC_SUPPORT */
966291a2b48SSukumar Swaminathan 	return;
967291a2b48SSukumar Swaminathan 
968291a2b48SSukumar Swaminathan }  /* emlxs_log_vportrscn_event() */
969fcf3ce44SJohn Forte 
970fcf3ce44SJohn Forte 
971728bdc9bSSukumar Swaminathan uint32_t
972fcf3ce44SJohn Forte emlxs_log_ct_event(emlxs_port_t *port, uint8_t *payload, uint32_t size,
973fcf3ce44SJohn Forte     uint32_t rxid)
974fcf3ce44SJohn Forte {
975fcf3ce44SJohn Forte #ifdef DFC_SUPPORT
976fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
977fcf3ce44SJohn Forte 	uint8_t *bp;
978fcf3ce44SJohn Forte 	uint32_t *ptr;
979fcf3ce44SJohn Forte 
980fcf3ce44SJohn Forte 	/* Check if the event is being requested */
981fcf3ce44SJohn Forte 	if (!(hba->log_events & EVT_CT)) {
982728bdc9bSSukumar Swaminathan 		return (1);
983fcf3ce44SJohn Forte 	}
984291a2b48SSukumar Swaminathan 
985fcf3ce44SJohn Forte 	if (size > MAX_CT_PAYLOAD) {
986fcf3ce44SJohn Forte 		size = MAX_CT_PAYLOAD;
987fcf3ce44SJohn Forte 	}
988291a2b48SSukumar Swaminathan 
989fcf3ce44SJohn Forte 	size += sizeof (uint32_t);
990fcf3ce44SJohn Forte 
991fcf3ce44SJohn Forte 	/* Save a copy of the payload for the event log */
992fcf3ce44SJohn Forte 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
993728bdc9bSSukumar Swaminathan 		return (1);
994fcf3ce44SJohn Forte 	}
995291a2b48SSukumar Swaminathan 
996fcf3ce44SJohn Forte 	/*
997291a2b48SSukumar Swaminathan 	 * Buffer Format:
998291a2b48SSukumar Swaminathan 	 *	word[0] = RXID tag for outgoing reply to this CT request
999291a2b48SSukumar Swaminathan 	 *	word[1] = CT Payload
1000fcf3ce44SJohn Forte 	 */
1001fcf3ce44SJohn Forte 	ptr = (uint32_t *)bp;
1002fcf3ce44SJohn Forte 	*ptr++ = rxid;
1003fcf3ce44SJohn Forte 
1004fcf3ce44SJohn Forte 	bcopy(payload, (char *)ptr, (size - sizeof (uint32_t)));
1005fcf3ce44SJohn Forte 
1006fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_ct_event,
1007fcf3ce44SJohn Forte 	    "bp=%p size=%d rxid=%x", bp, size, rxid);
1008fcf3ce44SJohn Forte 
1009728bdc9bSSukumar Swaminathan 
1010291a2b48SSukumar Swaminathan 	return (0);
1011728bdc9bSSukumar Swaminathan #else
1012728bdc9bSSukumar Swaminathan 
1013291a2b48SSukumar Swaminathan 	return (1);
1014fcf3ce44SJohn Forte 
1015291a2b48SSukumar Swaminathan #endif /* DFC_SUPPORT */
1016fcf3ce44SJohn Forte 
1017291a2b48SSukumar Swaminathan }  /* emlxs_log_ct_event() */
1018fcf3ce44SJohn Forte 
1019fcf3ce44SJohn Forte 
1020fcf3ce44SJohn Forte void
1021fcf3ce44SJohn Forte emlxs_log_link_event(emlxs_port_t *port)
1022fcf3ce44SJohn Forte {
1023fcf3ce44SJohn Forte #ifdef DFC_SUPPORT
1024fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1025fcf3ce44SJohn Forte 	uint8_t *bp;
1026fcf3ce44SJohn Forte 	dfc_linkinfo_t *linkinfo;
1027fcf3ce44SJohn Forte 	uint8_t *byte;
1028fcf3ce44SJohn Forte 	uint8_t *linkspeed;
1029fcf3ce44SJohn Forte 	uint8_t *liptype;
1030fcf3ce44SJohn Forte 	uint8_t *resv1;
1031fcf3ce44SJohn Forte 	uint8_t *resv2;
1032fcf3ce44SJohn Forte 	uint32_t size;
1033fcf3ce44SJohn Forte 
1034fcf3ce44SJohn Forte 	/* Check if the event is being requested */
1035fcf3ce44SJohn Forte 	/*
1036fcf3ce44SJohn Forte 	 * if(!(hba->log_events & EVT_LINK)) { return; }
1037fcf3ce44SJohn Forte 	 */
1038fcf3ce44SJohn Forte 	size = sizeof (dfc_linkinfo_t) + sizeof (uint32_t);
1039fcf3ce44SJohn Forte 
1040fcf3ce44SJohn Forte 	/* Save a copy of the buffer for the event log */
1041fcf3ce44SJohn Forte 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
1042fcf3ce44SJohn Forte 		return;
1043fcf3ce44SJohn Forte 	}
1044291a2b48SSukumar Swaminathan 
1045fcf3ce44SJohn Forte 	/*
1046291a2b48SSukumar Swaminathan 	 * Buffer Format:
1047291a2b48SSukumar Swaminathan 	 *	word[0] = Linkspeed:8
1048291a2b48SSukumar Swaminathan 	 *	word[0] = LIP_type:8
1049291a2b48SSukumar Swaminathan 	 *	word[0] = resv1:8
1050291a2b48SSukumar Swaminathan 	 *	word[0] = resv2:8
1051291a2b48SSukumar Swaminathan 	 *	word[1] = dfc_linkinfo_t data
1052fcf3ce44SJohn Forte 	 */
1053fcf3ce44SJohn Forte 	byte = (uint8_t *)bp;
1054fcf3ce44SJohn Forte 	linkspeed = &byte[0];
1055fcf3ce44SJohn Forte 	liptype = &byte[1];
1056fcf3ce44SJohn Forte 	resv1 = &byte[2];
1057fcf3ce44SJohn Forte 	resv2 = &byte[3];
1058291a2b48SSukumar Swaminathan 	linkinfo = (dfc_linkinfo_t *)&byte[4];
1059fcf3ce44SJohn Forte 
1060fcf3ce44SJohn Forte 	*resv1 = 0;
1061fcf3ce44SJohn Forte 	*resv2 = 0;
1062fcf3ce44SJohn Forte 
1063fcf3ce44SJohn Forte 	if (hba->state <= FC_LINK_DOWN) {
1064fcf3ce44SJohn Forte 		*linkspeed = 0;
1065fcf3ce44SJohn Forte 		*liptype = 0;
1066fcf3ce44SJohn Forte 	} else {
1067fcf3ce44SJohn Forte 		/* Set linkspeed */
1068fcf3ce44SJohn Forte 		if (hba->linkspeed == LA_2GHZ_LINK) {
1069fcf3ce44SJohn Forte 			*linkspeed = HBA_PORTSPEED_2GBIT;
1070fcf3ce44SJohn Forte 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
1071fcf3ce44SJohn Forte 			*linkspeed = HBA_PORTSPEED_4GBIT;
1072fcf3ce44SJohn Forte 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
1073fcf3ce44SJohn Forte 			*linkspeed = HBA_PORTSPEED_8GBIT;
1074fcf3ce44SJohn Forte 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
1075fcf3ce44SJohn Forte 			*linkspeed = HBA_PORTSPEED_10GBIT;
1076fcf3ce44SJohn Forte 		} else {
1077fcf3ce44SJohn Forte 			*linkspeed = HBA_PORTSPEED_1GBIT;
1078fcf3ce44SJohn Forte 		}
1079fcf3ce44SJohn Forte 
1080fcf3ce44SJohn Forte 		/* Set LIP type */
1081fcf3ce44SJohn Forte 		*liptype = port->lip_type;
1082fcf3ce44SJohn Forte 	}
1083fcf3ce44SJohn Forte 
1084fcf3ce44SJohn Forte 	bzero(linkinfo, sizeof (dfc_linkinfo_t));
1085fcf3ce44SJohn Forte 
1086fcf3ce44SJohn Forte 	linkinfo->a_linkEventTag = hba->link_event_tag;
1087fcf3ce44SJohn Forte 	linkinfo->a_linkUp = HBASTATS.LinkUp;
1088fcf3ce44SJohn Forte 	linkinfo->a_linkDown = HBASTATS.LinkDown;
1089fcf3ce44SJohn Forte 	linkinfo->a_linkMulti = HBASTATS.LinkMultiEvent;
1090fcf3ce44SJohn Forte 
1091fcf3ce44SJohn Forte 	if (hba->state <= FC_LINK_DOWN) {
1092fcf3ce44SJohn Forte 		linkinfo->a_linkState = LNK_DOWN;
1093fcf3ce44SJohn Forte 		linkinfo->a_DID = port->prev_did;
1094fcf3ce44SJohn Forte 	} else if (hba->state < FC_READY) {
1095fcf3ce44SJohn Forte 		linkinfo->a_linkState = LNK_DISCOVERY;
1096fcf3ce44SJohn Forte 	} else {
1097fcf3ce44SJohn Forte 		linkinfo->a_linkState = LNK_READY;
1098fcf3ce44SJohn Forte 	}
1099fcf3ce44SJohn Forte 
1100fcf3ce44SJohn Forte 	if (linkinfo->a_linkState != LNK_DOWN) {
1101fcf3ce44SJohn Forte 		if (hba->topology == TOPOLOGY_LOOP) {
1102fcf3ce44SJohn Forte 			if (hba->flag & FC_FABRIC_ATTACHED) {
1103fcf3ce44SJohn Forte 				linkinfo->a_topology = LNK_PUBLIC_LOOP;
1104fcf3ce44SJohn Forte 			} else {
1105fcf3ce44SJohn Forte 				linkinfo->a_topology = LNK_LOOP;
1106fcf3ce44SJohn Forte 			}
1107fcf3ce44SJohn Forte 
1108fcf3ce44SJohn Forte 			linkinfo->a_alpa = port->did & 0xff;
1109fcf3ce44SJohn Forte 			linkinfo->a_DID = linkinfo->a_alpa;
1110fcf3ce44SJohn Forte 			linkinfo->a_alpaCnt = port->alpa_map[0];
1111fcf3ce44SJohn Forte 
1112fcf3ce44SJohn Forte 			if (linkinfo->a_alpaCnt > 127) {
1113fcf3ce44SJohn Forte 				linkinfo->a_alpaCnt = 127;
1114fcf3ce44SJohn Forte 			}
1115291a2b48SSukumar Swaminathan 
1116291a2b48SSukumar Swaminathan 			bcopy((void *)&port->alpa_map[1], linkinfo->a_alpaMap,
1117fcf3ce44SJohn Forte 			    linkinfo->a_alpaCnt);
1118fcf3ce44SJohn Forte 		} else {
1119fcf3ce44SJohn Forte 			if (port->node_count == 1) {
1120fcf3ce44SJohn Forte 				linkinfo->a_topology = LNK_PT2PT;
1121fcf3ce44SJohn Forte 			} else {
1122fcf3ce44SJohn Forte 				linkinfo->a_topology = LNK_FABRIC;
1123fcf3ce44SJohn Forte 			}
1124fcf3ce44SJohn Forte 
1125fcf3ce44SJohn Forte 			linkinfo->a_DID = port->did;
1126fcf3ce44SJohn Forte 		}
1127fcf3ce44SJohn Forte 	}
1128291a2b48SSukumar Swaminathan 
1129fcf3ce44SJohn Forte 	bcopy(&hba->wwpn, linkinfo->a_wwpName, 8);
1130fcf3ce44SJohn Forte 	bcopy(&hba->wwnn, linkinfo->a_wwnName, 8);
1131fcf3ce44SJohn Forte 
1132fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_link_event,
1133fcf3ce44SJohn Forte 	    "bp=%p size=%d tag=%x", bp, size, hba->link_event_tag);
1134fcf3ce44SJohn Forte 
1135291a2b48SSukumar Swaminathan #endif /* DFC_SUPPORT */
1136fcf3ce44SJohn Forte 
1137fcf3ce44SJohn Forte 	return;
1138fcf3ce44SJohn Forte 
1139291a2b48SSukumar Swaminathan }  /* emlxs_log_link_event() */
1140fcf3ce44SJohn Forte 
1141fcf3ce44SJohn Forte 
1142fcf3ce44SJohn Forte void
1143fcf3ce44SJohn Forte emlxs_log_dump_event(emlxs_port_t *port, uint8_t *buffer, uint32_t size)
1144fcf3ce44SJohn Forte {
1145fcf3ce44SJohn Forte #ifdef DFC_SUPPORT
1146fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1147fcf3ce44SJohn Forte 	uint8_t *bp;
1148fcf3ce44SJohn Forte 
1149fcf3ce44SJohn Forte 	/* Check if the event is being requested */
1150fcf3ce44SJohn Forte 	if (!(hba->log_events & EVT_DUMP)) {
1151291a2b48SSukumar Swaminathan #ifdef DUMP_SUPPORT
1152291a2b48SSukumar Swaminathan 		/* Schedule a dump thread */
1153291a2b48SSukumar Swaminathan 		emlxs_dump(hba, EMLXS_DRV_DUMP, 0, 0);
1154291a2b48SSukumar Swaminathan #endif /* DUMP_SUPPORT */
1155fcf3ce44SJohn Forte 		return;
1156fcf3ce44SJohn Forte 	}
1157291a2b48SSukumar Swaminathan 
1158fcf3ce44SJohn Forte 	if (buffer && size) {
1159fcf3ce44SJohn Forte 		/* Save a copy of the buffer for the event log */
1160fcf3ce44SJohn Forte 		if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
1161fcf3ce44SJohn Forte 			return;
1162fcf3ce44SJohn Forte 		}
1163291a2b48SSukumar Swaminathan 
1164fcf3ce44SJohn Forte 		bcopy(buffer, bp, size);
1165fcf3ce44SJohn Forte 	} else {
1166fcf3ce44SJohn Forte 		bp = NULL;
1167fcf3ce44SJohn Forte 		size = 0;
1168fcf3ce44SJohn Forte 	}
1169fcf3ce44SJohn Forte 
1170fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_dump_event,
1171fcf3ce44SJohn Forte 	    "bp=%p size=%d", bp, size);
1172291a2b48SSukumar Swaminathan #else
1173291a2b48SSukumar Swaminathan 
1174291a2b48SSukumar Swaminathan #ifdef DUMP_SUPPORT
1175291a2b48SSukumar Swaminathan 	/* Schedule a dump thread */
1176291a2b48SSukumar Swaminathan 	emlxs_dump(hba, EMLXS_DRV_DUMP, 0, 0);
1177291a2b48SSukumar Swaminathan #endif /* DUMP_SUPPORT */
1178fcf3ce44SJohn Forte 
1179291a2b48SSukumar Swaminathan #endif /* DFC_SUPPORT */
1180fcf3ce44SJohn Forte 
1181fcf3ce44SJohn Forte 	return;
1182fcf3ce44SJohn Forte 
1183291a2b48SSukumar Swaminathan }  /* emlxs_log_dump_event() */
1184fcf3ce44SJohn Forte 
1185fcf3ce44SJohn Forte 
1186fcf3ce44SJohn Forte extern void
1187fcf3ce44SJohn Forte emlxs_log_temp_event(emlxs_port_t *port, uint32_t type, uint32_t temp)
1188fcf3ce44SJohn Forte {
1189fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1190291a2b48SSukumar Swaminathan 
1191291a2b48SSukumar Swaminathan #ifdef DFC_SUPPORT
1192fcf3ce44SJohn Forte 	uint32_t *bp;
1193fcf3ce44SJohn Forte 	uint32_t size;
1194fcf3ce44SJohn Forte 
1195fcf3ce44SJohn Forte 	/* Check if the event is being requested */
1196fcf3ce44SJohn Forte 	if (!(hba->log_events & EVT_TEMP)) {
1197291a2b48SSukumar Swaminathan #ifdef DUMP_SUPPORT
1198291a2b48SSukumar Swaminathan 		/* Schedule a dump thread */
1199291a2b48SSukumar Swaminathan 		emlxs_dump(hba, EMLXS_TEMP_DUMP, type, temp);
1200291a2b48SSukumar Swaminathan #endif /* DUMP_SUPPORT */
1201fcf3ce44SJohn Forte 		return;
1202fcf3ce44SJohn Forte 	}
1203291a2b48SSukumar Swaminathan 
1204fcf3ce44SJohn Forte 	size = 2 * sizeof (uint32_t);
1205fcf3ce44SJohn Forte 
1206fcf3ce44SJohn Forte 	if (!(bp = (uint32_t *)kmem_alloc(size, KM_NOSLEEP))) {
1207fcf3ce44SJohn Forte 		return;
1208fcf3ce44SJohn Forte 	}
1209291a2b48SSukumar Swaminathan 
1210fcf3ce44SJohn Forte 	bp[0] = type;
1211fcf3ce44SJohn Forte 	bp[1] = temp;
1212fcf3ce44SJohn Forte 
1213fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_temp_event,
1214fcf3ce44SJohn Forte 	    "type=%x temp=%d bp=%p size=%d", type, temp, bp, size);
1215fcf3ce44SJohn Forte 
1216291a2b48SSukumar Swaminathan #else /* !DFC_SUPPORT */
1217291a2b48SSukumar Swaminathan 
1218291a2b48SSukumar Swaminathan #ifdef DUMP_SUPPORT
1219291a2b48SSukumar Swaminathan 	/* Schedule a dump thread */
1220291a2b48SSukumar Swaminathan 	emlxs_dump(hba, EMLXS_TEMP_DUMP, type, temp);
1221291a2b48SSukumar Swaminathan #endif /* DUMP_SUPPORT */
1222291a2b48SSukumar Swaminathan 
1223291a2b48SSukumar Swaminathan #endif /* DFC_SUPPORT */
1224fcf3ce44SJohn Forte 
1225fcf3ce44SJohn Forte 	return;
1226fcf3ce44SJohn Forte 
1227291a2b48SSukumar Swaminathan }  /* emlxs_log_temp_event() */
1228fcf3ce44SJohn Forte 
1229fcf3ce44SJohn Forte 
1230fcf3ce44SJohn Forte 
1231fcf3ce44SJohn Forte extern void
1232fcf3ce44SJohn Forte emlxs_log_fcoe_event(emlxs_port_t *port, menlo_init_rsp_t *init_rsp)
1233fcf3ce44SJohn Forte {
1234fcf3ce44SJohn Forte #ifdef DFC_SUPPORT
1235fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1236fcf3ce44SJohn Forte 	uint8_t *bp;
1237fcf3ce44SJohn Forte 	uint32_t size;
1238fcf3ce44SJohn Forte 
1239fcf3ce44SJohn Forte 	/* Check if the event is being requested */
1240fcf3ce44SJohn Forte 	if (!(hba->log_events & EVT_FCOE)) {
1241fcf3ce44SJohn Forte 		return;
1242fcf3ce44SJohn Forte 	}
1243291a2b48SSukumar Swaminathan 
1244fcf3ce44SJohn Forte 	/* Check if this is a FCOE adapter */
1245fcf3ce44SJohn Forte 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
1246fcf3ce44SJohn Forte 		return;
1247fcf3ce44SJohn Forte 	}
1248291a2b48SSukumar Swaminathan 
1249fcf3ce44SJohn Forte 	size = sizeof (menlo_init_rsp_t);
1250fcf3ce44SJohn Forte 
1251fcf3ce44SJohn Forte 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
1252fcf3ce44SJohn Forte 		return;
1253fcf3ce44SJohn Forte 	}
1254291a2b48SSukumar Swaminathan 
1255fcf3ce44SJohn Forte 	bcopy((uint8_t *)init_rsp, bp, size);
1256fcf3ce44SJohn Forte 
1257fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_fcoe_event,
1258fcf3ce44SJohn Forte 	    "bp=%p size=%d", bp, size);
1259291a2b48SSukumar Swaminathan #endif /* DFC_SUPPORT */
1260291a2b48SSukumar Swaminathan 
1261291a2b48SSukumar Swaminathan 	return;
1262291a2b48SSukumar Swaminathan 
1263291a2b48SSukumar Swaminathan }  /* emlxs_log_fcoe_event() */
1264291a2b48SSukumar Swaminathan 
1265291a2b48SSukumar Swaminathan 
1266291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT
1267291a2b48SSukumar Swaminathan extern void
1268291a2b48SSukumar Swaminathan emlxs_log_sd_basic_els_event(emlxs_port_t *port, uint32_t subcat,
1269291a2b48SSukumar Swaminathan     HBA_WWN *portname, HBA_WWN *nodename)
1270291a2b48SSukumar Swaminathan {
1271291a2b48SSukumar Swaminathan 	struct sd_plogi_rcv_v0	*bp;
1272291a2b48SSukumar Swaminathan 	uint32_t		size;
1273291a2b48SSukumar Swaminathan 
1274291a2b48SSukumar Swaminathan 	/* Check if the event is being requested */
1275291a2b48SSukumar Swaminathan 	if (!(port->sd_reg_events & EVT_SD_ELS))
1276291a2b48SSukumar Swaminathan 		return;
1277291a2b48SSukumar Swaminathan 
1278291a2b48SSukumar Swaminathan 	size = sizeof (struct sd_plogi_rcv_v0);
1279291a2b48SSukumar Swaminathan 
1280291a2b48SSukumar Swaminathan 	if (!(bp = (struct sd_plogi_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1281291a2b48SSukumar Swaminathan 		return;
1282291a2b48SSukumar Swaminathan 
1283291a2b48SSukumar Swaminathan 	/*
1284291a2b48SSukumar Swaminathan 	 * we are using version field to store subtype, libdfc
1285291a2b48SSukumar Swaminathan 	 * will fix this up before returning data to app.
1286291a2b48SSukumar Swaminathan 	 */
1287291a2b48SSukumar Swaminathan 	bp->sd_plogir_version = subcat;
1288291a2b48SSukumar Swaminathan 	bcopy((uint8_t *)portname, (uint8_t *)&bp->sd_plogir_portname,
1289291a2b48SSukumar Swaminathan 	    sizeof (HBA_WWN));
1290291a2b48SSukumar Swaminathan 	bcopy((uint8_t *)nodename, (uint8_t *)&bp->sd_plogir_nodename,
1291291a2b48SSukumar Swaminathan 	    sizeof (HBA_WWN));
1292291a2b48SSukumar Swaminathan 
1293291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_els_event,
1294291a2b48SSukumar Swaminathan 	    "bp=%p size=%d", bp, size);
1295291a2b48SSukumar Swaminathan 
1296291a2b48SSukumar Swaminathan 	return;
1297291a2b48SSukumar Swaminathan 
1298291a2b48SSukumar Swaminathan } /* emlxs_log_sd_basic_els_event() */
1299291a2b48SSukumar Swaminathan 
1300291a2b48SSukumar Swaminathan 
1301291a2b48SSukumar Swaminathan extern void
1302291a2b48SSukumar Swaminathan emlxs_log_sd_prlo_event(emlxs_port_t *port, HBA_WWN *remoteport)
1303291a2b48SSukumar Swaminathan {
1304291a2b48SSukumar Swaminathan 	struct sd_prlo_rcv_v0	*bp;
1305291a2b48SSukumar Swaminathan 	uint32_t		size;
1306291a2b48SSukumar Swaminathan 
1307291a2b48SSukumar Swaminathan 	/* Check if the event is being requested */
1308291a2b48SSukumar Swaminathan 	if (!(port->sd_reg_events & EVT_SD_ELS))
1309291a2b48SSukumar Swaminathan 		return;
1310291a2b48SSukumar Swaminathan 
1311291a2b48SSukumar Swaminathan 	size = sizeof (struct sd_prlo_rcv_v0);
1312291a2b48SSukumar Swaminathan 
1313291a2b48SSukumar Swaminathan 	if (!(bp = (struct sd_prlo_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1314291a2b48SSukumar Swaminathan 		return;
1315291a2b48SSukumar Swaminathan 
1316291a2b48SSukumar Swaminathan 	/*
1317291a2b48SSukumar Swaminathan 	 * we are using version field to store subtype, libdfc
1318291a2b48SSukumar Swaminathan 	 * will fix this up before returning data to app.
1319291a2b48SSukumar Swaminathan 	 */
1320291a2b48SSukumar Swaminathan 	bp->sd_prlor_version = SD_ELS_SUBCATEGORY_PRLO_RCV;
1321291a2b48SSukumar Swaminathan 	bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_prlor_remoteport,
1322291a2b48SSukumar Swaminathan 	    sizeof (HBA_WWN));
1323291a2b48SSukumar Swaminathan 
1324291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_els_event,
1325291a2b48SSukumar Swaminathan 	    "bp=%p size=%d", bp, size);
1326291a2b48SSukumar Swaminathan 
1327291a2b48SSukumar Swaminathan 	return;
1328291a2b48SSukumar Swaminathan 
1329291a2b48SSukumar Swaminathan } /* emlxs_log_sd_prlo_event() */
1330291a2b48SSukumar Swaminathan 
1331291a2b48SSukumar Swaminathan 
1332291a2b48SSukumar Swaminathan extern void
1333291a2b48SSukumar Swaminathan emlxs_log_sd_lsrjt_event(emlxs_port_t *port, HBA_WWN *remoteport,
1334291a2b48SSukumar Swaminathan     uint32_t orig_cmd, uint32_t reason, uint32_t reason_expl)
1335291a2b48SSukumar Swaminathan {
1336291a2b48SSukumar Swaminathan 	struct sd_lsrjt_rcv_v0	*bp;
1337291a2b48SSukumar Swaminathan 	uint32_t		size;
1338291a2b48SSukumar Swaminathan 
1339291a2b48SSukumar Swaminathan 	/* Check if the event is being requested */
1340291a2b48SSukumar Swaminathan 	if (!(port->sd_reg_events & EVT_SD_ELS))
1341291a2b48SSukumar Swaminathan 		return;
1342291a2b48SSukumar Swaminathan 
1343291a2b48SSukumar Swaminathan 	size = sizeof (struct sd_lsrjt_rcv_v0);
1344291a2b48SSukumar Swaminathan 
1345291a2b48SSukumar Swaminathan 	if (!(bp = (struct sd_lsrjt_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1346291a2b48SSukumar Swaminathan 		return;
1347291a2b48SSukumar Swaminathan 
1348291a2b48SSukumar Swaminathan 	/*
1349291a2b48SSukumar Swaminathan 	 * we are using version field to store subtype, libdfc
1350291a2b48SSukumar Swaminathan 	 * will fix this up before returning data to app.
1351291a2b48SSukumar Swaminathan 	 */
1352291a2b48SSukumar Swaminathan 	bp->sd_lsrjtr_version = SD_ELS_SUBCATEGORY_LSRJT_RCV;
1353291a2b48SSukumar Swaminathan 	bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_lsrjtr_remoteport,
1354291a2b48SSukumar Swaminathan 	    sizeof (HBA_WWN));
1355291a2b48SSukumar Swaminathan 	bp->sd_lsrjtr_original_cmd = orig_cmd;
1356291a2b48SSukumar Swaminathan 	bp->sd_lsrjtr_reasoncode = reason;
1357291a2b48SSukumar Swaminathan 	bp->sd_lsrjtr_reasoncodeexpl = reason_expl;
1358291a2b48SSukumar Swaminathan 
1359291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_els_event,
1360291a2b48SSukumar Swaminathan 	    "bp=%p size=%d", bp, size);
1361291a2b48SSukumar Swaminathan 
1362291a2b48SSukumar Swaminathan 	return;
1363291a2b48SSukumar Swaminathan 
1364291a2b48SSukumar Swaminathan } /* emlxs_log_sd_lsrjt_event() */
1365291a2b48SSukumar Swaminathan 
1366291a2b48SSukumar Swaminathan 
1367291a2b48SSukumar Swaminathan 
1368291a2b48SSukumar Swaminathan extern void
1369291a2b48SSukumar Swaminathan emlxs_log_sd_fc_bsy_event(emlxs_port_t *port, HBA_WWN *remoteport)
1370291a2b48SSukumar Swaminathan {
1371291a2b48SSukumar Swaminathan 	struct sd_pbsy_rcv_v0	*bp;
1372291a2b48SSukumar Swaminathan 	uint32_t		size;
1373291a2b48SSukumar Swaminathan 
1374291a2b48SSukumar Swaminathan 	/* Check if the event is being requested */
1375291a2b48SSukumar Swaminathan 	if (!(port->sd_reg_events & EVT_SD_FABRIC))
1376291a2b48SSukumar Swaminathan 		return;
1377291a2b48SSukumar Swaminathan 
1378291a2b48SSukumar Swaminathan 	size = sizeof (struct sd_pbsy_rcv_v0);
1379291a2b48SSukumar Swaminathan 
1380291a2b48SSukumar Swaminathan 	if (!(bp = (struct sd_pbsy_rcv_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1381291a2b48SSukumar Swaminathan 		return;
1382291a2b48SSukumar Swaminathan 
1383291a2b48SSukumar Swaminathan 	/*
1384291a2b48SSukumar Swaminathan 	 * we are using version field to store subtype, libdfc
1385291a2b48SSukumar Swaminathan 	 * will fix this up before returning data to app.
1386291a2b48SSukumar Swaminathan 	 */
1387291a2b48SSukumar Swaminathan 	if (remoteport == NULL)
1388291a2b48SSukumar Swaminathan 		bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_FABRIC_BUSY;
1389291a2b48SSukumar Swaminathan 	else
1390291a2b48SSukumar Swaminathan 	{
1391291a2b48SSukumar Swaminathan 		bp->sd_pbsyr_evt_version = SD_FABRIC_SUBCATEGORY_PORT_BUSY;
1392291a2b48SSukumar Swaminathan 		bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_pbsyr_rport,
1393291a2b48SSukumar Swaminathan 		    sizeof (HBA_WWN));
1394291a2b48SSukumar Swaminathan 	}
1395291a2b48SSukumar Swaminathan 
1396291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_fabric_event,
1397291a2b48SSukumar Swaminathan 	    "bp=%p size=%d", bp, size);
1398291a2b48SSukumar Swaminathan 
1399291a2b48SSukumar Swaminathan 	return;
1400291a2b48SSukumar Swaminathan 
1401291a2b48SSukumar Swaminathan } /* emlxs_log_sd_fc_bsy_event() */
1402291a2b48SSukumar Swaminathan 
1403291a2b48SSukumar Swaminathan 
1404291a2b48SSukumar Swaminathan extern void
1405291a2b48SSukumar Swaminathan emlxs_log_sd_fc_rdchk_event(emlxs_port_t *port, HBA_WWN *remoteport,
1406291a2b48SSukumar Swaminathan     uint32_t lun, uint32_t opcode, uint32_t fcp_param)
1407291a2b48SSukumar Swaminathan {
1408291a2b48SSukumar Swaminathan 	struct sd_fcprdchkerr_v0	*bp;
1409291a2b48SSukumar Swaminathan 	uint32_t			size;
1410291a2b48SSukumar Swaminathan 
1411291a2b48SSukumar Swaminathan 	/* Check if the event is being requested */
1412291a2b48SSukumar Swaminathan 	if (!(port->sd_reg_events & EVT_SD_FABRIC))
1413291a2b48SSukumar Swaminathan 		return;
1414291a2b48SSukumar Swaminathan 
1415291a2b48SSukumar Swaminathan 	size = sizeof (struct sd_fcprdchkerr_v0);
1416291a2b48SSukumar Swaminathan 
1417291a2b48SSukumar Swaminathan 	if (!(bp = (struct sd_fcprdchkerr_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1418291a2b48SSukumar Swaminathan 		return;
1419291a2b48SSukumar Swaminathan 
1420291a2b48SSukumar Swaminathan 	/*
1421291a2b48SSukumar Swaminathan 	 * we are using version field to store subtype, libdfc
1422291a2b48SSukumar Swaminathan 	 * will fix this up before returning data to app.
1423291a2b48SSukumar Swaminathan 	 */
1424291a2b48SSukumar Swaminathan 	bp->sd_fcprdchkerr_version = SD_FABRIC_SUBCATEGORY_FCPRDCHKERR;
1425291a2b48SSukumar Swaminathan 	bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_fcprdchkerr_rport,
1426291a2b48SSukumar Swaminathan 	    sizeof (HBA_WWN));
1427291a2b48SSukumar Swaminathan 	bp->sd_fcprdchkerr_lun = lun;
1428291a2b48SSukumar Swaminathan 	bp->sd_fcprdchkerr_opcode = opcode;
1429291a2b48SSukumar Swaminathan 	bp->sd_fcprdchkerr_fcpiparam = fcp_param;
1430291a2b48SSukumar Swaminathan 
1431291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_fabric_event,
1432291a2b48SSukumar Swaminathan 	    "bp=%p size=%d", bp, size);
1433291a2b48SSukumar Swaminathan 
1434291a2b48SSukumar Swaminathan 	return;
1435291a2b48SSukumar Swaminathan 
1436291a2b48SSukumar Swaminathan } /* emlxs_log_sd_rdchk_event() */
1437291a2b48SSukumar Swaminathan 
1438291a2b48SSukumar Swaminathan 
1439291a2b48SSukumar Swaminathan extern void
1440291a2b48SSukumar Swaminathan emlxs_log_sd_scsi_event(emlxs_port_t *port, uint32_t type,
1441291a2b48SSukumar Swaminathan     HBA_WWN *remoteport, int32_t lun)
1442291a2b48SSukumar Swaminathan {
1443291a2b48SSukumar Swaminathan 	struct sd_scsi_generic_v0	*bp;
1444291a2b48SSukumar Swaminathan 	uint32_t			size;
1445291a2b48SSukumar Swaminathan 
1446291a2b48SSukumar Swaminathan 	/* Check if the event is being requested */
1447291a2b48SSukumar Swaminathan 	if (!(port->sd_reg_events & EVT_SD_SCSI))
1448291a2b48SSukumar Swaminathan 		return;
1449291a2b48SSukumar Swaminathan 
1450291a2b48SSukumar Swaminathan 	size = sizeof (struct sd_scsi_generic_v0);
1451291a2b48SSukumar Swaminathan 
1452291a2b48SSukumar Swaminathan 	if (!(bp = (struct sd_scsi_generic_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1453291a2b48SSukumar Swaminathan 		return;
1454fcf3ce44SJohn Forte 
1455291a2b48SSukumar Swaminathan 	/*
1456291a2b48SSukumar Swaminathan 	 * we are using version field to store subtype, libdfc
1457291a2b48SSukumar Swaminathan 	 * will fix this up before returning data to app.
1458291a2b48SSukumar Swaminathan 	 */
1459291a2b48SSukumar Swaminathan 	bp->sd_scsi_generic_version = type;
1460291a2b48SSukumar Swaminathan 	bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_generic_rport,
1461291a2b48SSukumar Swaminathan 	    sizeof (HBA_WWN));
1462291a2b48SSukumar Swaminathan 	bp->sd_scsi_generic_lun = lun;
1463291a2b48SSukumar Swaminathan 
1464291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_scsi_event,
1465291a2b48SSukumar Swaminathan 	    "bp=%p size=%d", bp, size);
1466fcf3ce44SJohn Forte 
1467fcf3ce44SJohn Forte 	return;
1468fcf3ce44SJohn Forte 
1469291a2b48SSukumar Swaminathan } /* emlxs_log_sd_scsi_event() */
1470291a2b48SSukumar Swaminathan 
1471291a2b48SSukumar Swaminathan 
1472291a2b48SSukumar Swaminathan extern void
1473291a2b48SSukumar Swaminathan emlxs_log_sd_scsi_check_event(emlxs_port_t *port, HBA_WWN *remoteport,
1474291a2b48SSukumar Swaminathan     uint32_t lun, uint32_t cmdcode, uint32_t sensekey,
1475291a2b48SSukumar Swaminathan     uint32_t asc, uint32_t ascq)
1476291a2b48SSukumar Swaminathan {
1477291a2b48SSukumar Swaminathan 	struct sd_scsi_checkcond_v0	*bp;
1478291a2b48SSukumar Swaminathan 	uint32_t			size;
1479291a2b48SSukumar Swaminathan 
1480291a2b48SSukumar Swaminathan 	/* Check if the event is being requested */
1481291a2b48SSukumar Swaminathan 	if (!(port->sd_reg_events & EVT_SD_SCSI))
1482291a2b48SSukumar Swaminathan 		return;
1483291a2b48SSukumar Swaminathan 
1484291a2b48SSukumar Swaminathan 	size = sizeof (struct sd_scsi_checkcond_v0);
1485291a2b48SSukumar Swaminathan 
1486291a2b48SSukumar Swaminathan 	if (!(bp = (struct sd_scsi_checkcond_v0 *)kmem_alloc(size, KM_NOSLEEP)))
1487291a2b48SSukumar Swaminathan 		return;
1488291a2b48SSukumar Swaminathan 
1489291a2b48SSukumar Swaminathan 	/*
1490291a2b48SSukumar Swaminathan 	 * we are using version field to store subtype, libdfc
1491291a2b48SSukumar Swaminathan 	 * will fix this up before returning data to app.
1492291a2b48SSukumar Swaminathan 	 */
1493291a2b48SSukumar Swaminathan 	bp->sd_scsi_checkcond_version = SD_SCSI_SUBCATEGORY_CHECKCONDITION;
1494291a2b48SSukumar Swaminathan 	bcopy((uint8_t *)remoteport, (uint8_t *)&bp->sd_scsi_checkcond_rport,
1495291a2b48SSukumar Swaminathan 	    sizeof (HBA_WWN));
1496291a2b48SSukumar Swaminathan 	bp->sd_scsi_checkcond_lun = lun;
1497291a2b48SSukumar Swaminathan 	bp->sd_scsi_checkcond_cmdcode = cmdcode;
1498291a2b48SSukumar Swaminathan 	bp->sd_scsi_checkcond_sensekey = sensekey;
1499291a2b48SSukumar Swaminathan 	bp->sd_scsi_checkcond_asc = asc;
1500291a2b48SSukumar Swaminathan 	bp->sd_scsi_checkcond_ascq = ascq;
1501291a2b48SSukumar Swaminathan 
1502291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_sd_scsi_event,
1503291a2b48SSukumar Swaminathan 	    "bp=%p size=%d", bp, size);
1504291a2b48SSukumar Swaminathan 
1505291a2b48SSukumar Swaminathan }
1506291a2b48SSukumar Swaminathan #endif	/* SAN_DIAG_SUPPORT */
1507291a2b48SSukumar Swaminathan 
1508291a2b48SSukumar Swaminathan 
1509291a2b48SSukumar Swaminathan extern void
1510291a2b48SSukumar Swaminathan emlxs_log_async_event(emlxs_port_t *port, IOCB *iocb)
1511291a2b48SSukumar Swaminathan {
1512291a2b48SSukumar Swaminathan 	uint8_t *bp;
1513291a2b48SSukumar Swaminathan 	uint32_t size;
1514291a2b48SSukumar Swaminathan 
1515291a2b48SSukumar Swaminathan 	/* ASYNC_STATUS_CN response size */
1516291a2b48SSukumar Swaminathan 	size = 64;
1517291a2b48SSukumar Swaminathan 
1518291a2b48SSukumar Swaminathan 	if (!(bp = (uint8_t *)kmem_alloc(size, KM_NOSLEEP))) {
1519291a2b48SSukumar Swaminathan 		return;
1520291a2b48SSukumar Swaminathan 	}
1521fcf3ce44SJohn Forte 
1522291a2b48SSukumar Swaminathan 	bcopy((uint8_t *)iocb, bp, size);
1523fcf3ce44SJohn Forte 
1524291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT_BP, bp, size, &emlxs_async_event,
1525291a2b48SSukumar Swaminathan 	    "bp=%p size=%d", bp, size);
1526291a2b48SSukumar Swaminathan 
1527291a2b48SSukumar Swaminathan }  /* emlxs_log_async_event() */
1528fcf3ce44SJohn Forte 
1529fcf3ce44SJohn Forte #ifdef DFC_SUPPORT
1530fcf3ce44SJohn Forte 
1531fcf3ce44SJohn Forte extern uint32_t
1532fcf3ce44SJohn Forte emlxs_get_dfc_eventinfo(emlxs_port_t *port, HBA_EVENTINFO *eventinfo,
1533fcf3ce44SJohn Forte     uint32_t *eventcount, uint32_t *missed)
1534fcf3ce44SJohn Forte {
1535fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1536fcf3ce44SJohn Forte 	emlxs_msg_log_t *log;
1537fcf3ce44SJohn Forte 	uint32_t first;
1538fcf3ce44SJohn Forte 	uint32_t last;
1539fcf3ce44SJohn Forte 	uint32_t count;
1540fcf3ce44SJohn Forte 	uint32_t index;
1541fcf3ce44SJohn Forte 	emlxs_msg_entry_t *entry;
1542fcf3ce44SJohn Forte 	dfc_linkinfo_t *linkinfo;
1543fcf3ce44SJohn Forte 	uint32_t *word;
1544fcf3ce44SJohn Forte 	uint8_t *byte;
1545fcf3ce44SJohn Forte 	uint8_t linkspeed;
1546fcf3ce44SJohn Forte 	uint8_t liptype;
1547fcf3ce44SJohn Forte 	fc_affected_id_t *aid;
1548fcf3ce44SJohn Forte 	uint32_t max_events;
1549fcf3ce44SJohn Forte 	uint32_t events;
1550fcf3ce44SJohn Forte 	emlxs_hba_event_t *hba_event;
1551fcf3ce44SJohn Forte 
1552fcf3ce44SJohn Forte 	if (!eventinfo || !eventcount || !missed) {
1553fcf3ce44SJohn Forte 		return (DFC_ARG_NULL);
1554fcf3ce44SJohn Forte 	}
1555291a2b48SSukumar Swaminathan 
1556fcf3ce44SJohn Forte 	hba_event = &hba->hba_event;
1557fcf3ce44SJohn Forte 	max_events = *eventcount;
1558fcf3ce44SJohn Forte 	*eventcount = 0;
1559fcf3ce44SJohn Forte 
1560fcf3ce44SJohn Forte 	log = &LOG;
1561fcf3ce44SJohn Forte 
1562fcf3ce44SJohn Forte 	mutex_enter(&log->lock);
1563fcf3ce44SJohn Forte 
1564fcf3ce44SJohn Forte 	/* Check if log is empty */
1565fcf3ce44SJohn Forte 	if (log->count == 0) {
1566fcf3ce44SJohn Forte 		/* Make sure everything is initialized */
1567fcf3ce44SJohn Forte 		hba_event->new = 0;
1568fcf3ce44SJohn Forte 		hba_event->missed = 0;
1569fcf3ce44SJohn Forte 		hba_event->last_id = 0;
1570fcf3ce44SJohn Forte 
1571fcf3ce44SJohn Forte 		mutex_exit(&log->lock);
1572fcf3ce44SJohn Forte 		return (0);
1573fcf3ce44SJohn Forte 	}
1574291a2b48SSukumar Swaminathan 
1575fcf3ce44SJohn Forte 	/* Safety check */
1576fcf3ce44SJohn Forte 	if (hba_event->last_id > (log->count - 1)) {
1577fcf3ce44SJohn Forte 		hba_event->last_id = log->count - 1;
1578fcf3ce44SJohn Forte 	}
1579291a2b48SSukumar Swaminathan 
1580fcf3ce44SJohn Forte 	/* Account for missed events */
1581fcf3ce44SJohn Forte 	if (hba_event->new > hba_event->missed) {
1582fcf3ce44SJohn Forte 		hba_event->new -= hba_event->missed;
1583fcf3ce44SJohn Forte 	} else {
1584fcf3ce44SJohn Forte 		hba_event->new = 0;
1585fcf3ce44SJohn Forte 	}
1586fcf3ce44SJohn Forte 
1587fcf3ce44SJohn Forte 	*missed = hba_event->missed;
1588fcf3ce44SJohn Forte 	hba_event->missed = 0;
1589fcf3ce44SJohn Forte 
1590fcf3ce44SJohn Forte 	if (!hba_event->new) {
1591fcf3ce44SJohn Forte 		hba_event->last_id = log->count;
1592fcf3ce44SJohn Forte 		mutex_exit(&log->lock);
1593fcf3ce44SJohn Forte 		return (0);
1594fcf3ce44SJohn Forte 	}
1595291a2b48SSukumar Swaminathan 
1596fcf3ce44SJohn Forte 	/* A new event has occurred since last acquisition */
1597fcf3ce44SJohn Forte 	/* Calculate the current buffer boundaries */
1598fcf3ce44SJohn Forte 
1599fcf3ce44SJohn Forte 	/* Get last entry id saved */
1600fcf3ce44SJohn Forte 	last = log->count - 1;
1601fcf3ce44SJohn Forte 
1602fcf3ce44SJohn Forte 	/* Get oldest entry id and its index */
1603fcf3ce44SJohn Forte 	/* Check if buffer has already been filled once */
1604fcf3ce44SJohn Forte 	if (log->count >= log->size) {
1605fcf3ce44SJohn Forte 		first = log->count - log->size;
1606fcf3ce44SJohn Forte 		index = log->next;
1607fcf3ce44SJohn Forte 	} else {	/* Buffer not yet filled */
1608291a2b48SSukumar Swaminathan 
1609fcf3ce44SJohn Forte 		first = 0;
1610fcf3ce44SJohn Forte 		index = 0;
1611fcf3ce44SJohn Forte 	}
1612fcf3ce44SJohn Forte 
1613291a2b48SSukumar Swaminathan 	/* Check if requested first event is greater than actual. */
1614291a2b48SSukumar Swaminathan 	/* If so, adjust for it.  */
1615fcf3ce44SJohn Forte 	if (hba_event->last_id > first) {
1616fcf3ce44SJohn Forte 		/* Adjust entry index to first requested message */
1617fcf3ce44SJohn Forte 		index += (hba_event->last_id - first);
1618fcf3ce44SJohn Forte 		if (index >= log->size) {
1619fcf3ce44SJohn Forte 			index -= log->size;
1620fcf3ce44SJohn Forte 		}
1621291a2b48SSukumar Swaminathan 
1622fcf3ce44SJohn Forte 		first = hba_event->last_id;
1623fcf3ce44SJohn Forte 	}
1624291a2b48SSukumar Swaminathan 
1625fcf3ce44SJohn Forte 	/* Get the total number of new messages */
1626fcf3ce44SJohn Forte 	count = last - first;
1627fcf3ce44SJohn Forte 
1628fcf3ce44SJohn Forte 	/* Scan log for next event */
1629fcf3ce44SJohn Forte 	events = 0;
1630fcf3ce44SJohn Forte 	while (count-- && (events < max_events)) {
1631fcf3ce44SJohn Forte 		if (++index >= log->size) {
1632fcf3ce44SJohn Forte 			index = 0;
1633fcf3ce44SJohn Forte 		}
1634291a2b48SSukumar Swaminathan 
1635fcf3ce44SJohn Forte 		entry = &log->entry[index];
1636fcf3ce44SJohn Forte 
1637fcf3ce44SJohn Forte 		if (!entry->msg) {
1638fcf3ce44SJohn Forte 			break;
1639fcf3ce44SJohn Forte 		}
1640291a2b48SSukumar Swaminathan 
1641fcf3ce44SJohn Forte 		if ((entry->msg->level == EMLXS_EVENT) &&
1642fcf3ce44SJohn Forte 		    (entry->msg->mask & (EVT_LINK | EVT_RSCN))) {
1643fcf3ce44SJohn Forte 			/* Process this event */
1644fcf3ce44SJohn Forte 			switch (entry->msg->mask) {
1645fcf3ce44SJohn Forte 			case EVT_LINK:
1646fcf3ce44SJohn Forte 				byte = (uint8_t *)entry->bp;
1647fcf3ce44SJohn Forte 				linkspeed = byte[0];
1648fcf3ce44SJohn Forte 				liptype = byte[1];
1649291a2b48SSukumar Swaminathan 				linkinfo = (dfc_linkinfo_t *)&byte[4];
1650fcf3ce44SJohn Forte 
1651fcf3ce44SJohn Forte 				if (linkinfo->a_linkState == LNK_DOWN) {
1652fcf3ce44SJohn Forte 					eventinfo->EventCode =
1653fcf3ce44SJohn Forte 					    HBA_EVENT_LINK_DOWN;
1654fcf3ce44SJohn Forte 					eventinfo->Event.Link_EventInfo.
1655fcf3ce44SJohn Forte 					    PortFcId = linkinfo->a_DID;
1656fcf3ce44SJohn Forte 					eventinfo->Event.Link_EventInfo.
1657fcf3ce44SJohn Forte 					    Reserved[0] = 0;
1658fcf3ce44SJohn Forte 					eventinfo->Event.Link_EventInfo.
1659fcf3ce44SJohn Forte 					    Reserved[1] = 0;
1660fcf3ce44SJohn Forte 					eventinfo->Event.Link_EventInfo.
1661fcf3ce44SJohn Forte 					    Reserved[2] = 0;
1662fcf3ce44SJohn Forte 				} else {
1663fcf3ce44SJohn Forte 					eventinfo->EventCode =
1664fcf3ce44SJohn Forte 					    HBA_EVENT_LINK_UP;
1665fcf3ce44SJohn Forte 					eventinfo->Event.Link_EventInfo.
1666fcf3ce44SJohn Forte 					    PortFcId = linkinfo->a_DID;
1667fcf3ce44SJohn Forte 
1668fcf3ce44SJohn Forte 					if ((linkinfo->a_topology ==
1669fcf3ce44SJohn Forte 					    LNK_PUBLIC_LOOP) ||
1670fcf3ce44SJohn Forte 					    (linkinfo->a_topology ==
1671fcf3ce44SJohn Forte 					    LNK_LOOP)) {
1672291a2b48SSukumar Swaminathan 						eventinfo->Event.
1673291a2b48SSukumar Swaminathan 						    Link_EventInfo.
1674fcf3ce44SJohn Forte 						    Reserved[0] = 2;
1675fcf3ce44SJohn Forte 					} else {
1676291a2b48SSukumar Swaminathan 						eventinfo->Event.
1677291a2b48SSukumar Swaminathan 						    Link_EventInfo.
1678fcf3ce44SJohn Forte 						    Reserved[0] = 1;
1679fcf3ce44SJohn Forte 					}
1680fcf3ce44SJohn Forte 
1681fcf3ce44SJohn Forte 					eventinfo->Event.Link_EventInfo.
1682fcf3ce44SJohn Forte 					    Reserved[1] = liptype;
1683fcf3ce44SJohn Forte 					eventinfo->Event.Link_EventInfo.
1684fcf3ce44SJohn Forte 					    Reserved[2] = linkspeed;
1685fcf3ce44SJohn Forte 				}
1686fcf3ce44SJohn Forte 
1687fcf3ce44SJohn Forte 				break;
1688fcf3ce44SJohn Forte 
1689fcf3ce44SJohn Forte 			case EVT_RSCN:
1690fcf3ce44SJohn Forte 				word = (uint32_t *)entry->bp;
1691fcf3ce44SJohn Forte 				eventinfo->EventCode = HBA_EVENT_RSCN;
1692fcf3ce44SJohn Forte 				eventinfo->Event.RSCN_EventInfo.PortFcId =
1693fcf3ce44SJohn Forte 				    word[0] & 0xFFFFFF;
1694fcf3ce44SJohn Forte 				/* word[1] is the RSCN payload command */
1695fcf3ce44SJohn Forte 
1696291a2b48SSukumar Swaminathan 				aid = (fc_affected_id_t *)&word[2];
1697fcf3ce44SJohn Forte 
1698fcf3ce44SJohn Forte 				switch (aid->aff_format) {
1699fcf3ce44SJohn Forte 				case 0:	/* Port */
1700fcf3ce44SJohn Forte 					eventinfo->Event.RSCN_EventInfo.
1701fcf3ce44SJohn Forte 					    NPortPage =
1702fcf3ce44SJohn Forte 					    aid->aff_d_id & 0x00ffffff;
1703fcf3ce44SJohn Forte 					break;
1704fcf3ce44SJohn Forte 
1705fcf3ce44SJohn Forte 				case 1:	/* Area */
1706fcf3ce44SJohn Forte 					eventinfo->Event.RSCN_EventInfo.
1707fcf3ce44SJohn Forte 					    NPortPage =
1708fcf3ce44SJohn Forte 					    aid->aff_d_id & 0x00ffff00;
1709fcf3ce44SJohn Forte 					break;
1710fcf3ce44SJohn Forte 
1711fcf3ce44SJohn Forte 				case 2:	/* Domain */
1712fcf3ce44SJohn Forte 					eventinfo->Event.RSCN_EventInfo.
1713fcf3ce44SJohn Forte 					    NPortPage =
1714fcf3ce44SJohn Forte 					    aid->aff_d_id & 0x00ff0000;
1715fcf3ce44SJohn Forte 					break;
1716fcf3ce44SJohn Forte 
1717fcf3ce44SJohn Forte 				case 3:	/* Network */
1718fcf3ce44SJohn Forte 					eventinfo->Event.RSCN_EventInfo.
1719fcf3ce44SJohn Forte 					    NPortPage = 0;
1720fcf3ce44SJohn Forte 					break;
1721fcf3ce44SJohn Forte 				}
1722fcf3ce44SJohn Forte 
1723291a2b48SSukumar Swaminathan 				eventinfo->Event.RSCN_EventInfo.Reserved[0] =
1724291a2b48SSukumar Swaminathan 				    0;
1725291a2b48SSukumar Swaminathan 				eventinfo->Event.RSCN_EventInfo.Reserved[1] =
1726291a2b48SSukumar Swaminathan 				    0;
1727fcf3ce44SJohn Forte 
1728fcf3ce44SJohn Forte 				break;
1729fcf3ce44SJohn Forte 			}
1730fcf3ce44SJohn Forte 
1731fcf3ce44SJohn Forte 			eventinfo++;
1732fcf3ce44SJohn Forte 			events++;
1733fcf3ce44SJohn Forte 		}
1734291a2b48SSukumar Swaminathan 
1735fcf3ce44SJohn Forte 		hba_event->last_id = entry->id;
1736fcf3ce44SJohn Forte 	}
1737fcf3ce44SJohn Forte 
1738fcf3ce44SJohn Forte 	/* Adjust new count */
1739fcf3ce44SJohn Forte 	if (!count || (events >= hba_event->new)) {
1740fcf3ce44SJohn Forte 		hba_event->new = 0;
1741fcf3ce44SJohn Forte 	} else {
1742fcf3ce44SJohn Forte 		hba_event->new -= events;
1743fcf3ce44SJohn Forte 	}
1744fcf3ce44SJohn Forte 
1745fcf3ce44SJohn Forte 	/* Return number of events acquired */
1746fcf3ce44SJohn Forte 	*eventcount = events;
1747fcf3ce44SJohn Forte 
1748fcf3ce44SJohn Forte 	mutex_exit(&log->lock);
1749fcf3ce44SJohn Forte 
1750fcf3ce44SJohn Forte 	return (0);
1751fcf3ce44SJohn Forte 
1752291a2b48SSukumar Swaminathan }  /* emlxs_get_dfc_eventinfo() */
1753fcf3ce44SJohn Forte 
1754fcf3ce44SJohn Forte 
1755fcf3ce44SJohn Forte uint32_t
1756fcf3ce44SJohn Forte emlxs_get_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
1757fcf3ce44SJohn Forte     uint32_t sleep)
1758fcf3ce44SJohn Forte {
1759fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1760fcf3ce44SJohn Forte 	emlxs_msg_log_t *log;
1761fcf3ce44SJohn Forte 	uint32_t first;
1762fcf3ce44SJohn Forte 	uint32_t last;
1763fcf3ce44SJohn Forte 	uint32_t count;
1764fcf3ce44SJohn Forte 	uint32_t index;
1765fcf3ce44SJohn Forte 	uint32_t mask;
1766fcf3ce44SJohn Forte 	uint32_t i;
1767fcf3ce44SJohn Forte 	emlxs_msg_entry_t *entry;
1768fcf3ce44SJohn Forte 	uint32_t size;
1769fcf3ce44SJohn Forte 	uint32_t rc;
1770fcf3ce44SJohn Forte 
1771fcf3ce44SJohn Forte 	size = 0;
1772fcf3ce44SJohn Forte 
1773fcf3ce44SJohn Forte 	if (dfc_event->dataout && dfc_event->size) {
1774fcf3ce44SJohn Forte 		size = dfc_event->size;
1775fcf3ce44SJohn Forte 	}
1776fcf3ce44SJohn Forte 	dfc_event->size = 0;
1777fcf3ce44SJohn Forte 
1778fcf3ce44SJohn Forte 	/* Get the log file pointer */
1779fcf3ce44SJohn Forte 	log = &LOG;
1780fcf3ce44SJohn Forte 
1781fcf3ce44SJohn Forte 	/* Calculate the event index */
1782fcf3ce44SJohn Forte 	mask = dfc_event->event;
1783fcf3ce44SJohn Forte 	for (i = 0; i < 32; i++) {
1784fcf3ce44SJohn Forte 		if (mask & 0x01) {
1785fcf3ce44SJohn Forte 			break;
1786fcf3ce44SJohn Forte 		}
1787291a2b48SSukumar Swaminathan 
1788fcf3ce44SJohn Forte 		mask >>= 1;
1789fcf3ce44SJohn Forte 	}
1790fcf3ce44SJohn Forte 	if (i == 32) {
1791fcf3ce44SJohn Forte 		return (DFC_ARG_INVALID);
1792fcf3ce44SJohn Forte 	}
1793291a2b48SSukumar Swaminathan 
1794fcf3ce44SJohn Forte 	mutex_enter(&log->lock);
1795fcf3ce44SJohn Forte 
1796fcf3ce44SJohn Forte 	/* Check if log is empty */
1797fcf3ce44SJohn Forte 	if (log->count == 0) {
1798fcf3ce44SJohn Forte 		/* Make sure everything is initialized */
1799fcf3ce44SJohn Forte 		log->event_id[i] = 0;
1800fcf3ce44SJohn Forte 		dfc_event->last_id = 0;
1801fcf3ce44SJohn Forte 	} else {
1802fcf3ce44SJohn Forte 		/* Check ranges for safety */
1803fcf3ce44SJohn Forte 		if (log->event_id[i] > (log->count - 1)) {
1804fcf3ce44SJohn Forte 			log->event_id[i] = log->count - 1;
1805fcf3ce44SJohn Forte 		}
1806291a2b48SSukumar Swaminathan 
1807fcf3ce44SJohn Forte 		if (dfc_event->last_id > log->event_id[i]) {
1808fcf3ce44SJohn Forte 			dfc_event->last_id = log->event_id[i];
1809fcf3ce44SJohn Forte 		}
1810fcf3ce44SJohn Forte 	}
1811fcf3ce44SJohn Forte 
1812fcf3ce44SJohn Forte wait_for_event:
1813fcf3ce44SJohn Forte 
1814fcf3ce44SJohn Forte 	/* Check if no new event has ocurred */
1815fcf3ce44SJohn Forte 	if (dfc_event->last_id == log->event_id[i]) {
1816fcf3ce44SJohn Forte 		if (!sleep) {
1817fcf3ce44SJohn Forte 			mutex_exit(&log->lock);
1818fcf3ce44SJohn Forte 			return (0);
1819fcf3ce44SJohn Forte 		}
1820291a2b48SSukumar Swaminathan 
1821291a2b48SSukumar Swaminathan 		/* While event is still active and */
1822291a2b48SSukumar Swaminathan 		/* no new event has been logged */
1823fcf3ce44SJohn Forte 		while ((dfc_event->event & hba->log_events) &&
1824fcf3ce44SJohn Forte 		    (dfc_event->last_id == log->event_id[i])) {
1825fcf3ce44SJohn Forte 			rc = cv_wait_sig(&log->lock_cv, &log->lock);
1826fcf3ce44SJohn Forte 
1827fcf3ce44SJohn Forte 			/* Check if thread was killed by kernel */
1828fcf3ce44SJohn Forte 			if (rc == 0) {
1829fcf3ce44SJohn Forte 				dfc_event->pid = 0;
1830fcf3ce44SJohn Forte 				dfc_event->event = 0;
1831fcf3ce44SJohn Forte 				mutex_exit(&log->lock);
1832fcf3ce44SJohn Forte 				return (0);
1833fcf3ce44SJohn Forte 			}
1834fcf3ce44SJohn Forte 		}
1835fcf3ce44SJohn Forte 
1836291a2b48SSukumar Swaminathan 		/* If the event is no longer registered then */
1837291a2b48SSukumar Swaminathan 		/* return immediately */
1838fcf3ce44SJohn Forte 		if (!(dfc_event->event & hba->log_events)) {
1839fcf3ce44SJohn Forte 			mutex_exit(&log->lock);
1840fcf3ce44SJohn Forte 			return (0);
1841fcf3ce44SJohn Forte 		}
1842fcf3ce44SJohn Forte 	}
1843291a2b48SSukumar Swaminathan 
1844fcf3ce44SJohn Forte 	/* !!! An event has occurred since last_id !!! */
1845fcf3ce44SJohn Forte 
1846fcf3ce44SJohn Forte 	/* Check if event data is not being requested */
1847fcf3ce44SJohn Forte 	if (!size) {
1848fcf3ce44SJohn Forte 		/* If so, then just return the last event id */
1849fcf3ce44SJohn Forte 		dfc_event->last_id = log->event_id[i];
1850fcf3ce44SJohn Forte 
1851fcf3ce44SJohn Forte 		mutex_exit(&log->lock);
1852fcf3ce44SJohn Forte 		return (0);
1853fcf3ce44SJohn Forte 	}
1854291a2b48SSukumar Swaminathan 
1855fcf3ce44SJohn Forte 	/* !!! The requester wants the next event buffer !!! */
1856fcf3ce44SJohn Forte 
1857fcf3ce44SJohn Forte 	/* Calculate the current buffer boundaries */
1858fcf3ce44SJohn Forte 
1859fcf3ce44SJohn Forte 	/* Get last entry id saved */
1860fcf3ce44SJohn Forte 	last = log->count - 1;
1861fcf3ce44SJohn Forte 
1862fcf3ce44SJohn Forte 	/* Get oldest entry id and its index */
1863fcf3ce44SJohn Forte 	/* Check if buffer has already been filled once */
1864fcf3ce44SJohn Forte 	if (log->count >= log->size) {
1865fcf3ce44SJohn Forte 		first = log->count - log->size;
1866fcf3ce44SJohn Forte 		index = log->next;
1867fcf3ce44SJohn Forte 	} else {	/* Buffer not yet filled */
1868291a2b48SSukumar Swaminathan 
1869fcf3ce44SJohn Forte 		first = 0;
1870fcf3ce44SJohn Forte 		index = 0;
1871fcf3ce44SJohn Forte 	}
1872fcf3ce44SJohn Forte 
1873fcf3ce44SJohn Forte 	/* Check to see if the buffer has wrapped since the last event */
1874fcf3ce44SJohn Forte 	if (first > log->event_id[i]) {
1875fcf3ce44SJohn Forte 		/* Update last_id to the last known event */
1876fcf3ce44SJohn Forte 		dfc_event->last_id = log->event_id[i];
1877fcf3ce44SJohn Forte 
1878fcf3ce44SJohn Forte 		/* Try waiting again if we can */
1879fcf3ce44SJohn Forte 		goto wait_for_event;
1880fcf3ce44SJohn Forte 	}
1881291a2b48SSukumar Swaminathan 
1882291a2b48SSukumar Swaminathan 	/* Check if requested first event is greater than actual. */
1883291a2b48SSukumar Swaminathan 	/* If so, adjust for it.  */
1884fcf3ce44SJohn Forte 	if (dfc_event->last_id > first) {
1885fcf3ce44SJohn Forte 		/* Adjust entry index to first requested message */
1886fcf3ce44SJohn Forte 		index += (dfc_event->last_id - first);
1887fcf3ce44SJohn Forte 		if (index >= log->size) {
1888fcf3ce44SJohn Forte 			index -= log->size;
1889fcf3ce44SJohn Forte 		}
1890291a2b48SSukumar Swaminathan 
1891fcf3ce44SJohn Forte 		first = dfc_event->last_id;
1892fcf3ce44SJohn Forte 	}
1893291a2b48SSukumar Swaminathan 
1894fcf3ce44SJohn Forte 	/* Get the total number of new messages */
1895fcf3ce44SJohn Forte 	count = last - first + 1;
1896fcf3ce44SJohn Forte 
1897fcf3ce44SJohn Forte 	/* Scan log for next event */
1898fcf3ce44SJohn Forte 	while (count--) {
1899fcf3ce44SJohn Forte 		if (++index >= log->size) {
1900fcf3ce44SJohn Forte 			index = 0;
1901fcf3ce44SJohn Forte 		}
1902291a2b48SSukumar Swaminathan 
1903fcf3ce44SJohn Forte 		entry = &log->entry[index];
1904fcf3ce44SJohn Forte 
1905fcf3ce44SJohn Forte 		if ((entry->msg->level == EMLXS_EVENT) &&
1906fcf3ce44SJohn Forte 		    (entry->msg->mask == dfc_event->event)) {
1907fcf3ce44SJohn Forte 			break;
1908fcf3ce44SJohn Forte 		}
1909fcf3ce44SJohn Forte 	}
1910fcf3ce44SJohn Forte 
1911291a2b48SSukumar Swaminathan 	/* Check if no new event was found in the current log buffer */
1912291a2b48SSukumar Swaminathan 	/* This would indicate that the buffer wrapped since that last event */
1913fcf3ce44SJohn Forte 	if (!count) {
1914fcf3ce44SJohn Forte 		/* Update last_id to the last known event */
1915fcf3ce44SJohn Forte 		dfc_event->last_id = log->event_id[i];
1916fcf3ce44SJohn Forte 
1917fcf3ce44SJohn Forte 		/* Try waiting again if we can */
1918fcf3ce44SJohn Forte 		goto wait_for_event;
1919fcf3ce44SJohn Forte 	}
1920291a2b48SSukumar Swaminathan 
1921fcf3ce44SJohn Forte 	/* !!! Next event found !!! */
1922fcf3ce44SJohn Forte 
1923fcf3ce44SJohn Forte 	/* Copy the context buffer to the buffer provided */
1924fcf3ce44SJohn Forte 	if (entry->bp && entry->size) {
1925fcf3ce44SJohn Forte 		if (entry->size < size) {
1926fcf3ce44SJohn Forte 			size = entry->size;
1927fcf3ce44SJohn Forte 		}
1928291a2b48SSukumar Swaminathan 
1929291a2b48SSukumar Swaminathan 		if (ddi_copyout((void *)entry->bp, dfc_event->dataout, size,
1930fcf3ce44SJohn Forte 		    dfc_event->mode) != 0) {
1931fcf3ce44SJohn Forte 			mutex_exit(&log->lock);
1932fcf3ce44SJohn Forte 
1933fcf3ce44SJohn Forte 			return (DFC_COPYOUT_ERROR);
1934fcf3ce44SJohn Forte 		}
1935291a2b48SSukumar Swaminathan 
1936291a2b48SSukumar Swaminathan 		/* Data has been retrieved by the apps */
1937291a2b48SSukumar Swaminathan 		entry->flag |= EMLX_EVENT_DONE;
1938291a2b48SSukumar Swaminathan 
1939fcf3ce44SJohn Forte 		dfc_event->size = size;
1940fcf3ce44SJohn Forte 	}
1941291a2b48SSukumar Swaminathan 
1942fcf3ce44SJohn Forte 	dfc_event->last_id = entry->id;
1943fcf3ce44SJohn Forte 
1944fcf3ce44SJohn Forte 	mutex_exit(&log->lock);
1945fcf3ce44SJohn Forte 	return (0);
1946fcf3ce44SJohn Forte 
1947291a2b48SSukumar Swaminathan }  /* emlxs_get_dfc_event() */
1948fcf3ce44SJohn Forte 
1949fcf3ce44SJohn Forte 
1950fcf3ce44SJohn Forte uint32_t
1951fcf3ce44SJohn Forte emlxs_kill_dfc_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event)
1952fcf3ce44SJohn Forte {
1953fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1954fcf3ce44SJohn Forte 	emlxs_msg_log_t *log;
1955fcf3ce44SJohn Forte 
1956fcf3ce44SJohn Forte 	/* Get the log file pointer */
1957fcf3ce44SJohn Forte 	log = &LOG;
1958fcf3ce44SJohn Forte 
1959fcf3ce44SJohn Forte 	mutex_enter(&log->lock);
1960fcf3ce44SJohn Forte 	dfc_event->pid = 0;
1961fcf3ce44SJohn Forte 	dfc_event->event = 0;
1962fcf3ce44SJohn Forte 	cv_broadcast(&log->lock_cv);
1963fcf3ce44SJohn Forte 	mutex_exit(&log->lock);
1964fcf3ce44SJohn Forte 
1965fcf3ce44SJohn Forte 	return (0);
1966fcf3ce44SJohn Forte 
1967291a2b48SSukumar Swaminathan }  /* emlxs_kill_dfc_event() */
1968291a2b48SSukumar Swaminathan 
1969291a2b48SSukumar Swaminathan 
1970291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT
1971291a2b48SSukumar Swaminathan uint32_t
1972291a2b48SSukumar Swaminathan emlxs_get_sd_event(emlxs_port_t *port, emlxs_dfc_event_t *dfc_event,
1973291a2b48SSukumar Swaminathan     uint32_t sleep)
1974291a2b48SSukumar Swaminathan {
1975291a2b48SSukumar Swaminathan 	emlxs_hba_t		*hba = HBA;
1976291a2b48SSukumar Swaminathan 	emlxs_msg_log_t		*log;
1977291a2b48SSukumar Swaminathan 	emlxs_msg_entry_t	*entry;
1978291a2b48SSukumar Swaminathan 	uint32_t		size;
1979291a2b48SSukumar Swaminathan 	uint32_t		rc;
1980291a2b48SSukumar Swaminathan 	uint32_t		first;
1981291a2b48SSukumar Swaminathan 	uint32_t		last;
1982291a2b48SSukumar Swaminathan 	uint32_t		count;
1983291a2b48SSukumar Swaminathan 	uint32_t		index;
1984291a2b48SSukumar Swaminathan 	uint32_t		mask;
1985291a2b48SSukumar Swaminathan 	uint32_t		i;
1986291a2b48SSukumar Swaminathan 
1987291a2b48SSukumar Swaminathan 	size = 0;
1988291a2b48SSukumar Swaminathan 
1989291a2b48SSukumar Swaminathan 	if (dfc_event->dataout && dfc_event->size) {
1990291a2b48SSukumar Swaminathan 		size = dfc_event->size;
1991291a2b48SSukumar Swaminathan 	}
1992291a2b48SSukumar Swaminathan 	dfc_event->size = 0;
1993291a2b48SSukumar Swaminathan 
1994291a2b48SSukumar Swaminathan 	/* Get the log file pointer */
1995291a2b48SSukumar Swaminathan 	log = &LOG;
1996291a2b48SSukumar Swaminathan 
1997291a2b48SSukumar Swaminathan 	/* Calculate the event index */
1998291a2b48SSukumar Swaminathan 	mask = dfc_event->event;
1999291a2b48SSukumar Swaminathan 	for (i = 0; i < 32; i++) {
2000291a2b48SSukumar Swaminathan 		if (mask & 0x01)
2001291a2b48SSukumar Swaminathan 			break;
2002291a2b48SSukumar Swaminathan 
2003291a2b48SSukumar Swaminathan 		mask >>= 1;
2004291a2b48SSukumar Swaminathan 	}
2005291a2b48SSukumar Swaminathan 	if (i == 32)
2006291a2b48SSukumar Swaminathan 		return (DFC_ARG_INVALID);
2007291a2b48SSukumar Swaminathan 
2008291a2b48SSukumar Swaminathan 	mutex_enter(&log->lock);
2009fcf3ce44SJohn Forte 
2010291a2b48SSukumar Swaminathan 	/* Check if log is empty */
2011291a2b48SSukumar Swaminathan 	if (log->count == 0) {
2012291a2b48SSukumar Swaminathan 		/* Make sure everything is initialized */
2013291a2b48SSukumar Swaminathan 		log->event_id[i] = 0;
2014291a2b48SSukumar Swaminathan 		dfc_event->last_id = 0;
2015291a2b48SSukumar Swaminathan 	} else {
2016291a2b48SSukumar Swaminathan 		/* Check ranges for safety */
2017291a2b48SSukumar Swaminathan 		if (log->event_id[i] > (log->count - 1))
2018291a2b48SSukumar Swaminathan 			log->event_id[i] = log->count - 1;
2019291a2b48SSukumar Swaminathan 
2020291a2b48SSukumar Swaminathan 		if (dfc_event->last_id > log->event_id[i])
2021291a2b48SSukumar Swaminathan 			dfc_event->last_id = log->event_id[i];
2022291a2b48SSukumar Swaminathan 	}
2023291a2b48SSukumar Swaminathan 
2024291a2b48SSukumar Swaminathan wait_for_sd_event:
2025291a2b48SSukumar Swaminathan 	/* Check if no new event has ocurred */
2026291a2b48SSukumar Swaminathan 	if (dfc_event->last_id == log->event_id[i]) {
2027291a2b48SSukumar Swaminathan 		if (!sleep) {
2028291a2b48SSukumar Swaminathan 			mutex_exit(&log->lock);
2029291a2b48SSukumar Swaminathan 			return (0);
2030291a2b48SSukumar Swaminathan 		}
2031291a2b48SSukumar Swaminathan 
2032291a2b48SSukumar Swaminathan 		/* While event is active and no new event has been logged */
2033291a2b48SSukumar Swaminathan 		while ((dfc_event->event & port->sd_reg_events) &&
2034291a2b48SSukumar Swaminathan 		    (dfc_event->last_id == log->event_id[i])) {
2035291a2b48SSukumar Swaminathan 			rc = cv_wait_sig(&log->lock_cv, &log->lock);
2036291a2b48SSukumar Swaminathan 
2037291a2b48SSukumar Swaminathan 			/* Check if thread was killed by kernel */
2038291a2b48SSukumar Swaminathan 			if (rc == 0) {
2039291a2b48SSukumar Swaminathan 				dfc_event->pid = 0;
2040291a2b48SSukumar Swaminathan 				dfc_event->event = 0;
2041291a2b48SSukumar Swaminathan 				mutex_exit(&log->lock);
2042291a2b48SSukumar Swaminathan 				return (0);
2043291a2b48SSukumar Swaminathan 			}
2044291a2b48SSukumar Swaminathan 		}
2045291a2b48SSukumar Swaminathan 
2046291a2b48SSukumar Swaminathan 		/* If the event is no longer registered then return */
2047291a2b48SSukumar Swaminathan 		if (!(dfc_event->event & port->sd_reg_events)) {
2048291a2b48SSukumar Swaminathan 			mutex_exit(&log->lock);
2049291a2b48SSukumar Swaminathan 			return (0);
2050291a2b48SSukumar Swaminathan 		}
2051291a2b48SSukumar Swaminathan 	}
2052291a2b48SSukumar Swaminathan 
2053291a2b48SSukumar Swaminathan 	/* !!! An event has occurred since last_id !!! */
2054291a2b48SSukumar Swaminathan 
2055291a2b48SSukumar Swaminathan 	/* Check if event data is not being requested */
2056291a2b48SSukumar Swaminathan 	if (!size) {
2057291a2b48SSukumar Swaminathan 		/* If so, then just return the last event id */
2058291a2b48SSukumar Swaminathan 		dfc_event->last_id = log->event_id[i];
2059291a2b48SSukumar Swaminathan 		mutex_exit(&log->lock);
2060291a2b48SSukumar Swaminathan 		return (0);
2061291a2b48SSukumar Swaminathan 	}
2062291a2b48SSukumar Swaminathan 
2063291a2b48SSukumar Swaminathan 	/* !!! The requester wants the next event buffer !!! */
2064291a2b48SSukumar Swaminathan 
2065291a2b48SSukumar Swaminathan 	/* Calculate the current buffer boundaries */
2066291a2b48SSukumar Swaminathan 
2067291a2b48SSukumar Swaminathan 	/* Get last entry id saved */
2068291a2b48SSukumar Swaminathan 	last = log->count - 1;
2069291a2b48SSukumar Swaminathan 
2070291a2b48SSukumar Swaminathan 	/* Get oldest entry id and its index */
2071291a2b48SSukumar Swaminathan 	/* Check if buffer has already been filled once */
2072291a2b48SSukumar Swaminathan 	if (log->count >= log->size) {
2073291a2b48SSukumar Swaminathan 		first = log->count - log->size;
2074291a2b48SSukumar Swaminathan 		index = log->next;
2075291a2b48SSukumar Swaminathan 	} else { /* Buffer not yet filled */
2076291a2b48SSukumar Swaminathan 		first = 0;
2077291a2b48SSukumar Swaminathan 		index = 0;
2078291a2b48SSukumar Swaminathan 	}
2079291a2b48SSukumar Swaminathan 
2080291a2b48SSukumar Swaminathan 	/* Check to see if the buffer has wrapped since the last event */
2081291a2b48SSukumar Swaminathan 	if (first > log->event_id[i]) {
2082291a2b48SSukumar Swaminathan 		/* Update last_id to the last known event */
2083291a2b48SSukumar Swaminathan 		dfc_event->last_id = log->event_id[i];
2084291a2b48SSukumar Swaminathan 
2085291a2b48SSukumar Swaminathan 		/* Try waiting again if we can */
2086291a2b48SSukumar Swaminathan 		goto wait_for_sd_event;
2087291a2b48SSukumar Swaminathan 	}
2088291a2b48SSukumar Swaminathan 
2089291a2b48SSukumar Swaminathan 	/* if requested first event is greater than actual, adjust for it. */
2090291a2b48SSukumar Swaminathan 	if (dfc_event->last_id > first) {
2091291a2b48SSukumar Swaminathan 		/* Adjust entry index to first requested message */
2092291a2b48SSukumar Swaminathan 		index += (dfc_event->last_id - first);
2093291a2b48SSukumar Swaminathan 		if (index >= log->size) {
2094291a2b48SSukumar Swaminathan 			index -= log->size;
2095291a2b48SSukumar Swaminathan 		}
2096291a2b48SSukumar Swaminathan 
2097291a2b48SSukumar Swaminathan 		first = dfc_event->last_id;
2098291a2b48SSukumar Swaminathan 	}
2099291a2b48SSukumar Swaminathan 
2100291a2b48SSukumar Swaminathan 	/* Get the total number of new messages */
2101291a2b48SSukumar Swaminathan 	count = last - first + 1;
2102291a2b48SSukumar Swaminathan 
2103291a2b48SSukumar Swaminathan 	/* Scan log for next event */
2104291a2b48SSukumar Swaminathan 	while (count--) {
2105291a2b48SSukumar Swaminathan 		if (++index >= log->size)
2106291a2b48SSukumar Swaminathan 			index = 0;
2107291a2b48SSukumar Swaminathan 
2108291a2b48SSukumar Swaminathan 		entry = &log->entry[index];
2109291a2b48SSukumar Swaminathan 
2110291a2b48SSukumar Swaminathan 		if ((entry->msg->level == EMLXS_EVENT) &&
2111291a2b48SSukumar Swaminathan 		    (entry->vpi == port->vpi) &&
2112291a2b48SSukumar Swaminathan 		    (entry->msg->mask == dfc_event->event))
2113291a2b48SSukumar Swaminathan 			break;
2114291a2b48SSukumar Swaminathan 	}
2115291a2b48SSukumar Swaminathan 
2116291a2b48SSukumar Swaminathan 	/* Check if no new event was found in the current log buffer */
2117291a2b48SSukumar Swaminathan 	/* This would indicate that the buffer wrapped since that last event */
2118291a2b48SSukumar Swaminathan 	if (!count) {
2119291a2b48SSukumar Swaminathan 		/* Update last_id to the last known event */
2120291a2b48SSukumar Swaminathan 		dfc_event->last_id = log->event_id[i];
2121291a2b48SSukumar Swaminathan 
2122291a2b48SSukumar Swaminathan 		/* Try waiting again if we can */
2123291a2b48SSukumar Swaminathan 		goto wait_for_sd_event;
2124291a2b48SSukumar Swaminathan 	}
2125291a2b48SSukumar Swaminathan 
2126291a2b48SSukumar Swaminathan 	/* !!! Next event found !!! */
2127291a2b48SSukumar Swaminathan 
2128291a2b48SSukumar Swaminathan 	/* Copy the context buffer to the buffer provided */
2129291a2b48SSukumar Swaminathan 	if (entry->bp && entry->size) {
2130291a2b48SSukumar Swaminathan 		if (entry->size < size)
2131291a2b48SSukumar Swaminathan 			size = entry->size;
2132291a2b48SSukumar Swaminathan 
2133291a2b48SSukumar Swaminathan 		if (ddi_copyout((void *) entry->bp, dfc_event->dataout,
2134291a2b48SSukumar Swaminathan 		    size, dfc_event->mode) != 0) {
2135291a2b48SSukumar Swaminathan 			mutex_exit(&log->lock);
2136291a2b48SSukumar Swaminathan 
2137291a2b48SSukumar Swaminathan 			return (DFC_COPYOUT_ERROR);
2138291a2b48SSukumar Swaminathan 		}
2139291a2b48SSukumar Swaminathan 
2140291a2b48SSukumar Swaminathan 		dfc_event->size = size;
2141291a2b48SSukumar Swaminathan 	}
2142291a2b48SSukumar Swaminathan 
2143291a2b48SSukumar Swaminathan 	dfc_event->last_id = entry->id;
2144291a2b48SSukumar Swaminathan 	mutex_exit(&log->lock);
2145291a2b48SSukumar Swaminathan 
2146291a2b48SSukumar Swaminathan 	return (0);
2147291a2b48SSukumar Swaminathan } /* emlxs_get_sd_event */
2148291a2b48SSukumar Swaminathan #endif /* SAN_DIAG_SUPPORT */
2149fcf3ce44SJohn Forte 
2150fcf3ce44SJohn Forte 
2151291a2b48SSukumar Swaminathan #endif /* DFC_SUPPORT */
2152