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