1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #include <emlxs.h>
29 
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_FCF_C);
32 
33 /*
34  * STATE MACHINE RULES:
35  *
36  * - State change requests to an XXXX object when operating within
37  * an emlxs_XXXX state management function must be made
38  * using the emlxs_XXXX_state() call.
39  *
40  * - State change requests to an XXXX object when operating outside
41  * an emlxs_XXXX state management function must be made
42  * using the emlxs_XXXX_alloc(), emlxs_XXXX_free(), emlxs_XXXX_event()
43  * or emlxs_XXXX_..._notify() calls.
44  *
45  * - emlxs_XXXX_..._notify() calls are used by routines outside
46  * this fcf module to enter the state machine.
47  *
48  * - It is forbidden to make direct calls to emlxs_XXXX_...._action()
49  * functions.  Only emlxs_XXXX_action() routines may make calls to
50  * emlxs_XXXX_...._action() functions.
51  *
52  * - Its is forbidden to make direct calls to emlxs_XXXX_action().
53  * Only emlxs_XXXX_state() and emlxs_XXXX_event() routines may make
54  * calls to emlxs_XXXX_action().
55  *
56  * - The EMLXS_FCF_LOCK must be held before calling:
57  * emlxs_XXXX_state(), emlxs_XXXX_event() and emlxs_XXXX_action().
58  *
59  * - All other calls touching fctab, fcfi, vfi, vpi, rpi objects must hold
60  * the EMLXS_FCF_LOCK to protect these objects.
61  */
62 
63 /* ************************************************************************** */
64 /* FCF Generic */
65 /* ************************************************************************** */
66 
67 /*
68  * EVENT			ARG1
69  * --------------------------------------------
70  * FCF_EVENT_STATE_ENTER	None
71  *
72  * FCF_EVENT_LINKUP		None
73  * FCF_EVENT_LINKDOWN		None
74  * FCF_EVENT_CVL		vpi
75  * FCF_EVENT_FCFTAB_FULL	None
76  * FCF_EVENT_FCF_FOUND		fcf_index
77  * FCF_EVENT_FCF_LOST		fcf_index
78  * FCF_EVENT_FCF_CHANGED	fcf_index
79  *
80  * FCF_EVENT_FCFI_ONLINE	FCFIobj_t*
81  * FCF_EVENT_FCFI_OFFLINE	FCFIobj_t*
82  * FCF_EVENT_FCFI_PAUSE		FCFIobj_t*
83  *
84  * FCF_EVENT_VFI_ONLINE		VFIobj_t*
85  * FCF_EVENT_VFI_OFFLINE	VFIobj_t*
86  * FCF_EVENT_VFI_PAUSE		VFIobj_t*
87  *
88  * FCF_EVENT_VPI_ONLINE		VPIobj_t*
89  * FCF_EVENT_VPI_OFFLINE	VPIobj_t*
90  * FCF_EVENT_VPI_PAUSE		VPIobj_t*
91  *
92  * FCF_EVENT_RPI_ONLINE		RPIobj_t*
93  * FCF_EVENT_RPI_OFFLINE	RPIobj_t*
94  * FCF_EVENT_RPI_PAUSE		RPIobj_t*
95  * FCF_EVENT_RPI_RESUME		RPIobj_t*
96  */
97 
98 /* Order does not matter */
99 emlxs_table_t emlxs_fcf_event_table[] =
100 {
101 	{FCF_EVENT_STATE_ENTER, "STATE_ENTER"},
102 
103 	{FCF_EVENT_SHUTDOWN, "SHUTDOWN"},
104 	{FCF_EVENT_LINKUP, "LINK_UP"},
105 	{FCF_EVENT_LINKDOWN, "LINK_DOWN"},
106 	{FCF_EVENT_CVL, "CVL_RECD"},
107 	{FCF_EVENT_FCFTAB_FULL, "TABLE_FULL"},
108 	{FCF_EVENT_FCF_FOUND, "FCF_FOUND"},
109 	{FCF_EVENT_FCF_LOST, "FCF_LOST"},
110 	{FCF_EVENT_FCF_CHANGED, "FCF_CHANGED"},
111 
112 	{FCF_EVENT_FCFI_ONLINE, "FCFI_ONLINE"},
113 	{FCF_EVENT_FCFI_OFFLINE, "FCFI_OFFLINE"},
114 	{FCF_EVENT_FCFI_PAUSE, "FCFI_PAUSE"},
115 
116 	{FCF_EVENT_VFI_ONLINE, "VFI_ONLINE"},
117 	{FCF_EVENT_VFI_OFFLINE, "VFI_OFFLINE"},
118 	{FCF_EVENT_VFI_PAUSE, "VFI_PAUSE"},
119 
120 	{FCF_EVENT_VPI_ONLINE, "VPI_ONLINE"},
121 	{FCF_EVENT_VPI_OFFLINE, "VPI_OFFLINE"},
122 	{FCF_EVENT_VPI_PAUSE, "VPI_PAUSE"},
123 
124 	{FCF_EVENT_RPI_ONLINE, "RPI_ONLINE"},
125 	{FCF_EVENT_RPI_OFFLINE, "RPI_OFFLINE"},
126 	{FCF_EVENT_RPI_PAUSE, "RPI_PAUSE"},
127 	{FCF_EVENT_RPI_RESUME, "RPI_RESUME"},
128 
129 }; /* emlxs_fcf_event_table */
130 
131 
132 /* Order does not matter */
133 emlxs_table_t emlxs_fcf_reason_table[] =
134 {
135 	{FCF_REASON_NONE, "REASON_NONE"},
136 	{FCF_REASON_REENTER, "REASON_REENTER"},
137 	{FCF_REASON_EVENT, "REASON_EVENT"},
138 	{FCF_REASON_REQUESTED, "REASON_REQUESTED"},
139 	{FCF_REASON_NO_MBOX, "REASON_NO_MBOX"},
140 	{FCF_REASON_NO_BUFFER, "REASON_NO_BUFFER"},
141 	{FCF_REASON_SEND_FAILED, "REASON_SEND_FAILED"},
142 	{FCF_REASON_MBOX_FAILED, "REASON_MBOX_FAILED"},
143 	{FCF_REASON_NO_FCFI, "REASON_NO_FCFI"},
144 	{FCF_REASON_NO_VFI, "REASON_NO_VFI"},
145 	{FCF_REASON_ONLINE_FAILED, "REASON_ONLINE_FAILED"},
146 	{FCF_REASON_OFFLINE_FAILED, "REASON_OFFLINE_FAILED"},
147 	{FCF_REASON_OP_FAILED, "REASON_OP_FAILED"},
148 	{FCF_REASON_NO_PKT, "FCF_REASON_NO_PKT"},
149 	{FCF_REASON_NO_NODE, "FCF_REASON_NO_NODE"},
150 	{FCF_REASON_NOT_ALLOWED, "FCF_REASON_NOT_ALLOWED"},
151 
152 }; /* emlxs_fcf_reason_table */
153 
154 
155 /* ********************************************************************** */
156 /* FCFTAB */
157 /* ********************************************************************** */
158 
159 /* Order does not matter */
160 emlxs_table_t emlxs_fcftab_state_table[] =
161 {
162 	{FCFTAB_STATE_SHUTDOWN, "FCFTAB_STATE_SHUTDOWN"},
163 	{FCFTAB_STATE_OFFLINE, "FCFTAB_STATE_OFFLINE"},
164 
165 	{FCFTAB_STATE_SOLICIT, "FCFTAB_STATE_SOLICIT"},
166 	{FCFTAB_STATE_SOLICIT_FAILED, "FCFTAB_STATE_SOLICIT_FAILED"},
167 	{FCFTAB_STATE_SOLICIT_CMPL, "FCFTAB_STATE_SOLICIT_CMPL"},
168 
169 	{FCFTAB_STATE_READ, "FCFTAB_STATE_READ"},
170 	{FCFTAB_STATE_READ_FAILED, "FCFTAB_STATE_READ_FAILED"},
171 	{FCFTAB_STATE_READ_CMPL, "FCFTAB_STATE_READ_CMPL"},
172 
173 	{FCFTAB_STATE_FCFI_OFFLINE, "FCFTAB_STATE_FCFI_OFFLINE"},
174 	{FCFTAB_STATE_FCFI_OFFLINE_CMPL, "FCFTAB_STATE_FCFI_OFFLINE_CMPL"},
175 
176 	{FCFTAB_STATE_FCFI_ONLINE, "FCFTAB_STATE_FCFI_ONLINE"},
177 	{FCFTAB_STATE_FCFI_ONLINE_CMPL, "FCFTAB_STATE_FCFI_ONLINE_CMPL"},
178 
179 	{FCFTAB_STATE_ONLINE, "FCFTAB_STATE_ONLINE"},
180 
181 }; /* emlxs_fcftab_state_table */
182 
183 
184 static uint32_t emlxs_fcftab_sol_cmpl_action(emlxs_port_t *port,
185 			uint32_t evt, void *arg1);
186 static uint32_t emlxs_fcftab_sol_failed_action(emlxs_port_t *port,
187 			uint32_t evt, void *arg1);
188 static uint32_t emlxs_fcftab_sol_action(emlxs_port_t *port,
189 			uint32_t evt, void *arg1);
190 static uint32_t emlxs_fcftab_shutdown_evt_action(emlxs_port_t *port,
191 			uint32_t evt, void *arg1);
192 static uint32_t emlxs_fcftab_linkdown_evt_action(emlxs_port_t *port,
193 			uint32_t evt, void *arg1);
194 static uint32_t emlxs_fcftab_read_action(emlxs_port_t *port,
195 			uint32_t evt, void *arg1);
196 static uint32_t emlxs_fcftab_read_failed_action(emlxs_port_t *port,
197 			uint32_t evt, void *arg1);
198 static uint32_t emlxs_fcftab_read_cmpl_action(emlxs_port_t *port,
199 			uint32_t evt, void *arg1);
200 static uint32_t emlxs_fcftab_fcfi_online_action(emlxs_port_t *port,
201 			uint32_t evt, void *arg1);
202 static uint32_t emlxs_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port,
203 			uint32_t evt, void *arg1);
204 static uint32_t emlxs_fcftab_fcfi_offline_action(emlxs_port_t *port,
205 			uint32_t evt, void *arg1);
206 static uint32_t emlxs_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port,
207 			uint32_t evt, void *arg1);
208 static uint32_t emlxs_fcftab_found_evt_action(emlxs_port_t *port,
209 			uint32_t evt, void *arg1);
210 static uint32_t emlxs_fcftab_lost_evt_action(emlxs_port_t *port,
211 			uint32_t evt, void *arg1);
212 static uint32_t emlxs_fcftab_changed_evt_action(emlxs_port_t *port,
213 			uint32_t evt, void *arg1);
214 static uint32_t emlxs_fcftab_full_evt_action(emlxs_port_t *port,
215 			uint32_t evt, void *arg1);
216 static uint32_t emlxs_fcftab_linkup_evt_action(emlxs_port_t *port,
217 			uint32_t evt, void *arg1);
218 static uint32_t emlxs_fcftab_cvl_evt_action(emlxs_port_t *port,
219 			uint32_t evt, void *arg1);
220 static uint32_t emlxs_fcftab_online_action(emlxs_port_t *port,
221 			uint32_t evt, void *arg1);
222 static uint32_t emlxs_fcftab_offline_action(emlxs_port_t *port,
223 			uint32_t evt, void *arg1);
224 static uint32_t emlxs_fcftab_fcfi_offline_evt_action(emlxs_port_t *port,
225 			uint32_t evt, void *arg1);
226 static uint32_t emlxs_fcftab_fcfi_online_evt_action(emlxs_port_t *port,
227 			uint32_t evt, void *arg1);
228 static uint32_t emlxs_fcftab_shutdown_action(emlxs_port_t *port,
229 			uint32_t evt, void *arg1);
230 
231 static void emlxs_fcftab_read_timer(emlxs_hba_t *hba);
232 static void emlxs_fcftab_sol_timer(emlxs_hba_t *hba);
233 static void emlxs_fcftab_offline_timer(emlxs_hba_t *hba);
234 static char *emlxs_fcftab_state_xlate(uint32_t state);
235 static uint32_t emlxs_fcftab_event(emlxs_port_t *port,
236 			uint32_t evt, void *arg1);
237 
238 /*
239  * - Online sequencing can start from FCFI_STATE_OFFLINE state
240  *
241  * - Offline sequencing can interrupt the online sequencing at the
242  * entry of the next wait state.
243  *
244  * NORMAL ONLINE SEQ
245  * ---------------------------
246  * LINK_UP event <-- Adapter
247  * FCFTAB_STATE_OFFLINE
248  * FCFTAB_STATE_SOLICIT
249  *     FCFTAB_STATE_SOLICIT_CMPL
250  * FCFTAB_STATE_READ
251  *     FCFTAB_STATE_READ_CMPL
252  * FCFTAB_STATE_FCFI_OFFLINE
253  *     FCFTAB_STATE_FCFI_OFFLINE_CMPL
254  * FCFTAB_STATE_FCFI_ONLINE
255  *     FCFTAB_STATE_FCFI_ONLINE_CMPL
256  * FCFTAB_STATE_ONLINE
257  *
258  *
259  * NORMAL OFFLINE SEQ
260  * ---------------------------
261  * LINK_DOWN event <-- Adapter
262  * FCFTAB_STATE_ONLINE
263  * FCFTAB_STATE_FCFI_OFFLINE
264  *     FCFTAB_STATE_FCFI_OFFLINE_CMPL
265  * FCFTAB_STATE_OFFLINE
266  *
267  */
268 /* Order does matter */
269 static void *emlxs_fcftab_action_table[] =
270 {
271 	/* Action routine				Event */
272 /* FCFTAB_STATE_SHUTDOWN  0		(Requires adapter reset) */
273 	(void *) emlxs_fcftab_shutdown_action,		/* STATE_ENTER */
274 	(void *) NULL,					/* SHUTDOWN */
275 	(void *) NULL,					/* LINK_UP */
276 	(void *) NULL,					/* LINK_DOWN */
277 	(void *) NULL,					/* CVL_RECD */
278 	(void *) NULL,					/* FCF_FOUND */
279 	(void *) NULL,					/* FCF_LOST */
280 	(void *) NULL,					/* FCF_CHANGED */
281 	(void *) NULL,					/* TABLE_FULL */
282 	(void *) NULL,					/* FCFI_ONLINE */
283 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
284 
285 /* FCFTAB_STATE_OFFLINE  1		(Wait for LINK_UP event) */
286 	(void *) emlxs_fcftab_offline_action,		/* STATE_ENTER */
287 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
288 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
289 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
290 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
291 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
292 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
293 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
294 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
295 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
296 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
297 
298 
299 /* FCFTAB_STATE_SOLICIT  2		(Wait on fcf_solicit cmpl) */
300 	(void *) emlxs_fcftab_sol_action,		/* STATE_ENTER */
301 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
302 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
303 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
304 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
305 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
306 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
307 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
308 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
309 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
310 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
311 
312 /* FCFTAB_STATE_SOLICIT_FAILED  3	(Transitional) */
313 	(void *) emlxs_fcftab_sol_failed_action,	/* STATE_ENTER */
314 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
315 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
316 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
317 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
318 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
319 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
320 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
321 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
322 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
323 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
324 
325 /* FCFTAB_STATE_SOLICIT_CMPL  4		(Wait on fcf timer cmpl) */
326 	(void *) emlxs_fcftab_sol_cmpl_action,		/* STATE_ENTER */
327 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
328 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
329 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
330 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
331 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
332 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
333 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
334 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
335 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
336 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
337 
338 
339 /* FCFTAB_STATE_READ  5			(Wait on fcf_read cmpl) */
340 	(void *) emlxs_fcftab_read_action,		/* STATE_ENTER */
341 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
342 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
343 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
344 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
345 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
346 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
347 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
348 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
349 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
350 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
351 
352 /* FCFTAB_STATE_READ_FAILED  6		(Transitional) */
353 	(void *) emlxs_fcftab_read_failed_action,	/* STATE_ENTER */
354 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
355 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
356 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
357 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
358 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
359 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
360 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
361 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
362 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
363 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
364 
365 /* FCFTAB_STATE_READ_CMPL  7		(Transitional) */
366 	(void *) emlxs_fcftab_read_cmpl_action,		/* STATE_ENTER */
367 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
368 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
369 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
370 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
371 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
372 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
373 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
374 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
375 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
376 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
377 
378 
379 /* FCFTAB_STATE_FCFI_OFFLINE_CMPL  8	(Transitional) */
380 	(void *) emlxs_fcftab_fcfi_offline_cmpl_action,	/* STATE_ENTER */
381 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
382 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
383 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
384 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
385 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
386 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
387 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
388 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
389 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
390 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
391 
392 /* FCFTAB_STATE_FCFI_OFFLINE  9		(Wait for FCFI_OFFLINE event) */
393 	(void *) emlxs_fcftab_fcfi_offline_action,	/* STATE_ENTER */
394 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
395 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
396 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
397 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
398 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
399 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
400 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
401 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
402 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
403 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
404 
405 
406 /* FCFTAB_STATE_FCFI_ONLINE  10		(Wait on FCFI_ONLINE event) */
407 	(void *) emlxs_fcftab_fcfi_online_action,	/* STATE_ENTER */
408 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
409 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
410 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
411 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
412 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
413 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
414 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
415 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
416 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
417 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
418 
419 /* FCFTAB_STATE_FCFI_ONLINE_CMPL  11	(Transitional) */
420 	(void *) emlxs_fcftab_fcfi_online_cmpl_action,	/* STATE_ENTER */
421 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
422 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
423 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
424 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
425 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
426 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
427 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
428 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
429 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
430 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
431 
432 
433 /* FCFTAB_STATE_ONLINE  12		(Wait for LINK_DOWN event) */
434 	(void *) emlxs_fcftab_online_action,		/* STATE_ENTER */
435 	(void *) emlxs_fcftab_shutdown_evt_action,	/* SHUTDOWN */
436 	(void *) emlxs_fcftab_linkup_evt_action,	/* LINK_UP */
437 	(void *) emlxs_fcftab_linkdown_evt_action,	/* LINK_DOWN */
438 	(void *) emlxs_fcftab_cvl_evt_action,		/* CVL_RECD */
439 	(void *) emlxs_fcftab_found_evt_action,		/* FCF_FOUND */
440 	(void *) emlxs_fcftab_lost_evt_action,		/* FCF_LOST */
441 	(void *) emlxs_fcftab_changed_evt_action,	/* FCF_CHANGED */
442 	(void *) emlxs_fcftab_full_evt_action,		/* TABLE_FULL */
443 	(void *) emlxs_fcftab_fcfi_online_evt_action,	/* FCFI_ONLINE */
444 	(void *) emlxs_fcftab_fcfi_offline_evt_action,	/* FCFI_OFFLINE */
445 
446 }; /* emlxs_fcftab_action_table[] */
447 #define	FCFTAB_ACTION_EVENTS			11
448 #define	FCFTAB_ACTION_STATES			\
449 	(sizeof (emlxs_fcftab_action_table)/ \
450 	(FCFTAB_ACTION_EVENTS * sizeof (void *)))
451 
452 
453 /* ********************************************************************** */
454 /* VFTAB - This will be needed for multi-virtual fabric environments */
455 /* ********************************************************************** */
456 
457 /* Order does not matter */
458 emlxs_table_t emlxs_vftab_state_table[] =
459 {
460 	{VFTAB_STATE_DISABLED, "VFTAB_STATE_DISABLED"},
461 
462 }; /* emlxs_vftab_state_table */
463 
464 
465 
466 /* ********************************************************************** */
467 /* FCFI */
468 /* ********************************************************************** */
469 
470 /* Order does not matter */
471 emlxs_table_t emlxs_fcfi_state_table[] =
472 {
473 	{FCFI_STATE_FREE, "FCFI_STATE_FREE"},
474 
475 	{FCFI_STATE_OFFLINE, "FCFI_STATE_OFFLINE"},
476 
477 	{FCFI_STATE_UNREG_CMPL, "FCFI_STATE_UNREG_CMPL"},
478 	{FCFI_STATE_UNREG_FAILED, "FCFI_STATE_UNREG_FAILED"},
479 	{FCFI_STATE_UNREG, "FCFI_STATE_UNREG"},
480 
481 	{FCFI_STATE_REG, "FCFI_STATE_REG"},
482 	{FCFI_STATE_REG_FAILED, "FCFI_STATE_REG_FAILED"},
483 	{FCFI_STATE_REG_CMPL, "FCFI_STATE_REG_CMPL"},
484 
485 	{FCFI_STATE_VFI_OFFLINE_CMPL, "FCFI_STATE_VFI_OFFLINE_CMPL"},
486 	{FCFI_STATE_VFI_OFFLINE, "FCFI_STATE_VFI_OFFLINE"},
487 
488 	{FCFI_STATE_VFI_ONLINE, "FCFI_STATE_VFI_ONLINE"},
489 	{FCFI_STATE_VFI_ONLINE_CMPL, "FCFI_STATE_VFI_ONLINE_CMPL"},
490 
491 	{FCFI_STATE_PAUSED, "FCFI_STATE_PAUSED"},
492 	{FCFI_STATE_ONLINE, "FCFI_STATE_ONLINE"},
493 
494 }; /* emlxs_fcfi_state_table */
495 
496 
497 static uint32_t emlxs_fcfi_free_action(emlxs_port_t *port,
498 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
499 static uint32_t emlxs_fcfi_online_evt_action(emlxs_port_t *port,
500 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
501 static uint32_t emlxs_fcfi_offline_evt_action(emlxs_port_t *port,
502 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
503 static uint32_t emlxs_fcfi_pause_evt_action(emlxs_port_t *port,
504 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
505 static uint32_t emlxs_fcfi_reg_action(emlxs_port_t *port,
506 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
507 static uint32_t emlxs_fcfi_unreg_action(emlxs_port_t *port,
508 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
509 static uint32_t emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port,
510 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
511 static uint32_t emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port,
512 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
513 static uint32_t emlxs_fcfi_vfi_online_action(emlxs_port_t *port,
514 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
515 static uint32_t emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port,
516 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
517 static uint32_t emlxs_fcfi_reg_failed_action(emlxs_port_t *port,
518 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
519 static uint32_t emlxs_fcfi_unreg_failed_action(emlxs_port_t *port,
520 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
521 static uint32_t emlxs_fcfi_vfi_offline_action(emlxs_port_t *port,
522 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
523 static uint32_t emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port,
524 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
525 static uint32_t emlxs_fcfi_online_action(emlxs_port_t *port,
526 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
527 static uint32_t emlxs_fcfi_paused_action(emlxs_port_t *port,
528 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
529 static uint32_t emlxs_fcfi_offline_action(emlxs_port_t *port,
530 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
531 static uint32_t emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port,
532 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
533 static uint32_t emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port,
534 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
535 
536 static uint32_t emlxs_fcfi_event(emlxs_port_t *port,
537 			uint32_t evt, void *arg1);
538 static FCFIobj_t *emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec,
539 			uint32_t *fcf_index);
540 static FCFIobj_t *emlxs_fcfi_alloc(emlxs_port_t *port);
541 static uint32_t emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp);
542 static void emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp,
543 			FCF_RECORD_t *fcf_rec, uint32_t event_tag);
544 static char *emlxs_fcfi_state_xlate(uint32_t state);
545 
546 /*
547  * - Online sequencing can start from FCFI_STATE_OFFLINE state or
548  * the FCFI_STATE_VFI_OFFLINE state.
549  *
550  * - Offline sequencing can interrupt the online sequencing at the
551  * entry of the next wait state.
552  *
553  * NORMAL ONLINE SEQ
554  * ---------------------------
555  * FCFI_ONLINE event <-- FCFTAB
556  * FCFI_STATE_OFFLINE
557  * FCFI_STATE_REG
558  *     FCFI_STATE_REG_CMPL
559  * FCFI_STATE_VFI_ONLINE
560  *     FCFI_STATE_VFI_ONLINE_CMPL
561  * FCFI_STATE_ONLINE
562  * FCFI_ONLINE event-->FCFTAB
563  *
564  *
565  * NORMAL OFFLINE SEQ
566  * ---------------------------
567  * FCFI_OFFLINE event <-- FCFTAB
568  * FCFI_STATE_ONLINE
569  * FCFI_STATE_VFI_OFFLINE
570  *     FCFI_STATE_VFI_OFFLINE_CMPL
571  * FCFI_STATE_UNREG
572  *     FCFI_STATE_UNREG_CMPL
573  * FCFI_STATE_OFFLINE
574  * FCFI_OFFLINE event-->FCFTAB
575  *
576  *
577  * NORMAL PAUSE SEQ
578  * ---------------------------
579  * FCFI_PAUSE event <-- FCFTAB
580  * FCFI_STATE_ONLINE
581  * FCFI_STATE_PAUSED
582  *
583  */
584 /* Order does matter */
585 static void *emlxs_fcfi_action_table[] =
586 {
587 	/* Action routine				Event */
588 /* FCFI_STATE_FREE  0			(Wait for allocation) */
589 	(void *) emlxs_fcfi_free_action,		/* STATE_ENTER */
590 	(void *) NULL,					/* FCFI_ONLINE */
591 	(void *) NULL,					/* FCFI_OFFLINE */
592 	(void *) NULL,					/* FCFI_PAUSE */
593 	(void *) NULL,					/* VFI_ONLINE */
594 	(void *) NULL,					/* VFI_OFFLINE */
595 
596 /* FCFI_STATE_OFFLINE  1		(Wait for FCFI_ONLINE event) */
597 	(void *) emlxs_fcfi_offline_action,		/* STATE_ENTER */
598 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
599 	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
600 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
601 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
602 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
603 
604 /* FCFI_STATE_UNREG_CMPL  2		(Transitional)  */
605 	(void *) emlxs_fcfi_unreg_cmpl_action,		/* STATE_ENTER */
606 	(void *) emlxs_fcfi_online_evt_action,  	/* FCFI_ONLINE */
607 	(void *) emlxs_fcfi_offline_evt_action, 	/* FCFI_OFFLINE */
608 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
609 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
610 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
611 
612 /* FCFI_STATE_UNREG_FAILED  3		(Transitional) */
613 	(void *) emlxs_fcfi_unreg_failed_action, 	/* STATE_ENTER */
614 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
615 	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
616 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
617 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
618 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
619 
620 /* FCFI_STATE_UNREG  4			(Wait for unreg_fcfi cmpl) */
621 	(void *) emlxs_fcfi_unreg_action,		/* STATE_ENTER */
622 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
623 	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
624 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
625 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
626 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
627 
628 /* FCFI_STATE_REG  5			(Wait for reg_fcfi cmpl) */
629 	(void *) emlxs_fcfi_reg_action,			/* STATE_ENTER */
630 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
631 	(void *) emlxs_fcfi_offline_evt_action, 	/* FCFI_OFFLINE */
632 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
633 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
634 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
635 
636 /* FCFI_STATE_REG_FAILED  6		(Transitional) */
637 	(void *) emlxs_fcfi_reg_failed_action,		/*  STATE_ENTER */
638 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
639 	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
640 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
641 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
642 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
643 
644 /* FCFI_STATE_REG_CMPL  7		(Transitional) */
645 	(void *) emlxs_fcfi_reg_cmpl_action,		/* STATE_ENTER */
646 	(void *) emlxs_fcfi_online_evt_action,  	/* FCFI_ONLINE */
647 	(void *) emlxs_fcfi_offline_evt_action, 	/* FCFI_OFFLINE */
648 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
649 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
650 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
651 
652 /* FCFI_STATE_VFI_OFFLINE_CMPL  8 	(Transitional) */
653 	(void *) emlxs_fcfi_vfi_offline_cmpl_action,	/* STATE_ENTER */
654 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
655 	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
656 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
657 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
658 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
659 
660 /* FCFI_STATE_VFI_OFFLINE  9		(Wait for VFI_OFFLINE event) */
661 	(void *) emlxs_fcfi_vfi_offline_action,		/* STATE_ENTER */
662 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
663 	(void *) emlxs_fcfi_offline_evt_action, 	/* FCFI_OFFLINE */
664 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
665 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
666 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE * */
667 
668 /* FCFI_STATE_VFI_ONLINE  10		(Wait for VFI_ONLINE event) */
669 	(void *) emlxs_fcfi_vfi_online_action,		/* STATE_ENTER */
670 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
671 	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
672 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
673 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
674 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
675 
676 /* FCFI_STATE_VFI_ONLINE_CMPL  11	(Transitional) */
677 	(void *) emlxs_fcfi_vfi_online_cmpl_action, 	/* STATE_ENTER */
678 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
679 	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
680 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
681 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
682 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
683 
684 
685 /* FCFI_STATE_PAUSED 12			(Wait for FCFI_ONLINE event) */
686 	(void *) emlxs_fcfi_paused_action,		/* STATE_ENTER */
687 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
688 	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
689 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
690 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
691 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
692 
693 /* FCFI_STATE_ONLINE 13			(Wait for FCFI_OFFLINE event) */
694 	(void *) emlxs_fcfi_online_action,		/* STATE_ENTER */
695 	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
696 	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
697 	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
698 	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
699 	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
700 
701 }; /* emlxs_fcfi_action_table[] */
702 #define	FCFI_ACTION_EVENTS			6
703 #define	FCFI_ACTION_STATES			\
704 	(sizeof (emlxs_fcfi_action_table)/ \
705 	(FCFI_ACTION_EVENTS * sizeof (void *)))
706 
707 
708 /* ********************************************************************** */
709 /* VFI */
710 /* ********************************************************************** */
711 
712 /* Order does not matter */
713 emlxs_table_t emlxs_vfi_state_table[] =
714 {
715 	{VFI_STATE_OFFLINE, "VFI_STATE_OFFLINE"},
716 
717 	{VFI_STATE_INIT, "VFI_STATE_INIT"},
718 	{VFI_STATE_INIT_FAILED, "VFI_STATE_INIT_FAILED"},
719 	{VFI_STATE_INIT_CMPL, "VFI_STATE_INIT_CMPL"},
720 
721 	{VFI_STATE_VPI_OFFLINE_CMPL, "VFI_STATE_VPI_OFFLINE_CMPL"},
722 	{VFI_STATE_VPI_OFFLINE, "VFI_STATE_VPI_OFFLINE"},
723 
724 	{VFI_STATE_VPI_ONLINE, "VFI_STATE_VPI_ONLINE"},
725 	{VFI_STATE_VPI_ONLINE_CMPL, "VFI_STATE_VPI_ONLINE_CMPL"},
726 
727 	{VFI_STATE_UNREG_CMPL, "VFI_STATE_UNREG_CMPL"},
728 	{VFI_STATE_UNREG_FAILED, "VFI_STATE_UNREG_FAILED"},
729 	{VFI_STATE_UNREG, "VFI_STATE_UNREG"},
730 
731 	{VFI_STATE_REG, "VFI_STATE_REG"},
732 	{VFI_STATE_REG_FAILED, "VFI_STATE_REG_FAILED"},
733 	{VFI_STATE_REG_CMPL, "VFI_STATE_REG_CMPL"},
734 
735 	{VFI_STATE_PAUSED, "VFI_STATE_PAUSED"},
736 	{VFI_STATE_ONLINE, "VFI_STATE_ONLINE"},
737 
738 }; /* emlxs_vfi_state_table */
739 
740 
741 static uint32_t emlxs_vfi_pause_evt_action(emlxs_port_t *port,
742 			VFIobj_t *vfip, uint32_t evt, void *arg1);
743 static uint32_t emlxs_vfi_online_evt_action(emlxs_port_t *port,
744 			VFIobj_t *vfip, uint32_t evt, void *arg1);
745 static uint32_t emlxs_vfi_offline_evt_action(emlxs_port_t *port,
746 			VFIobj_t *vfip, uint32_t evt, void *arg1);
747 static uint32_t emlxs_vfi_init_action(emlxs_port_t *port,
748 			VFIobj_t *vfip, uint32_t evt, void *arg1);
749 static uint32_t emlxs_vfi_init_failed_action(emlxs_port_t *port,
750 			VFIobj_t *vfip, uint32_t evt, void *arg1);
751 static uint32_t emlxs_vfi_init_cmpl_action(emlxs_port_t *port,
752 			VFIobj_t *vfip, uint32_t evt, void *arg1);
753 static uint32_t emlxs_vfi_offline_action(emlxs_port_t *port,
754 			VFIobj_t *vfip, uint32_t evt, void *arg1);
755 static uint32_t emlxs_vfi_online_action(emlxs_port_t *port,
756 			VFIobj_t *vfip, uint32_t evt, void *arg1);
757 static uint32_t emlxs_vfi_paused_action(emlxs_port_t *port,
758 			VFIobj_t *vfip, uint32_t evt, void *arg1);
759 static uint32_t emlxs_vfi_vpi_online_action(emlxs_port_t *port,
760 			VFIobj_t *vfip, uint32_t evt, void *arg1);
761 static uint32_t emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port,
762 			VFIobj_t *vfip, uint32_t evt, void *arg1);
763 static uint32_t emlxs_vfi_vpi_offline_action(emlxs_port_t *port,
764 			VFIobj_t *vfip, uint32_t evt, void *arg1);
765 static uint32_t emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port,
766 			VFIobj_t *vfip, uint32_t evt, void *arg1);
767 static uint32_t emlxs_vfi_reg_action(emlxs_port_t *port,
768 			VFIobj_t *vfip, uint32_t evt, void *arg1);
769 static uint32_t emlxs_vfi_reg_failed_action(emlxs_port_t *port,
770 			VFIobj_t *vfip, uint32_t evt, void *arg1);
771 static uint32_t emlxs_vfi_reg_cmpl_action(emlxs_port_t *port,
772 			VFIobj_t *vfip, uint32_t evt, void *arg1);
773 static uint32_t emlxs_vfi_unreg_action(emlxs_port_t *port,
774 			VFIobj_t *vfip, uint32_t evt, void *arg1);
775 static uint32_t emlxs_vfi_unreg_failed_action(emlxs_port_t *port,
776 			VFIobj_t *vfip, uint32_t evt, void *arg1);
777 static uint32_t emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port,
778 			VFIobj_t *vfip, uint32_t evt, void *arg1);
779 static uint32_t emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port,
780 			VFIobj_t *vfip, uint32_t evt, void *arg1);
781 static uint32_t emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port,
782 			VFIobj_t *vfip, uint32_t evt, void *arg1);
783 
784 static uint32_t emlxs_vfi_event(emlxs_port_t *port,
785 			uint32_t evt, void *arg1);
786 
787 
788 /*
789  * - Online sequencing can start from VFI_STATE_OFFLINE state or
790  * the VFI_STATE_VPI_OFFLINE state.
791  *
792  * - Offline sequencing can interrupt the online sequencing at the
793  * entry of the next wait state.
794  *
795  * NORMAL ONLINE SEQ
796  * ---------------------------
797  * VFI_ONLINE event <-- FCFI
798  * VFI_STATE_OFFLINE
799  * VFI_STATE_INIT
800  *     VFI_STATE_INIT_CMPL
801  * VFI_STATE_VPI_ONLINE
802  *     VFI_STATE_VPI_ONLINE_CMPL
803  * VFI_STATE_REG
804  *     VFI_STATE_REG_CMPL
805  * VFI_STATE_ONLINE
806  * VFI_ONLINE event-->FCFI
807  *
808  *
809  * NORMAL OFFLINE SEQ
810  * ---------------------------
811  * VFI_OFFLINE event <-- FCFI
812  * VFI_STATE_ONLINE
813  * VFI_STATE_VPI_OFFLINE
814  *     VFI_STATE_VPI_OFFLINE_CMPL
815  * VFI_STATE_UNREG
816  *     VFI_STATE_UNREG_CMPL
817  * VFI_STATE_OFFLINE
818  * VFI_OFFLINE event-->FCFI
819  *
820  *
821  * NORMAL PAUSE SEQ
822  * ---------------------------
823  * VFI_PAUSE event <-- FCFI
824  * VFI_STATE_ONLINE
825  * VFI_STATE_PAUSED
826  *
827  */
828 /* Order does matter */
829 static void *emlxs_vfi_action_table[] =
830 {
831 	/* Action routine				Event */
832 /* VFI_STATE_OFFLINE  0			(Wait for VFI_ONLINE event) */
833 	(void *) emlxs_vfi_offline_action,		/* STATE_ENTER */
834 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
835 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
836 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
837 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
838 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
839 
840 
841 /* VFI_STATE_INIT  1			(Wait for init_vfi cmpl) */
842 	(void *) emlxs_vfi_init_action,			/* STATE_ENTER */
843 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
844 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
845 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
846 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
847 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
848 
849 /* VFI_STATE_INIT_FAILED  2		(Transitional) */
850 	(void *) emlxs_vfi_init_failed_action,		/* STATE_ENTER */
851 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
852 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
853 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
854 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
855 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
856 
857 /* VFI_STATE_INIT_CMPL  3		(Transitional) */
858 	(void *) emlxs_vfi_init_cmpl_action,		/* STATE_ENTER */
859 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
860 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
861 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
862 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
863 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
864 
865 
866 /* VFI_STATE_VPI_OFFLINE_CMPL  4	(Wait for VPI_OFFLINE event) */
867 	(void *) emlxs_vfi_vpi_offline_cmpl_action,	/* STATE_ENTER */
868 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
869 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
870 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
871 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
872 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
873 
874 /* VFI_STATE_VPI_OFFLINE  5		(Wait for VPI_OFFLINE event) */
875 	(void *) emlxs_vfi_vpi_offline_action,		/* STATE_ENTER */
876 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
877 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
878 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
879 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
880 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
881 
882 
883 /* VFI_STATE_VPI_ONLINE 6		(Wait for VPI_ONLINE event) */
884 	(void *) emlxs_vfi_vpi_online_action,		/* STATE_ENTER */
885 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
886 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
887 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
888 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
889 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
890 
891 /* VFI_STATE_VPI_ONLINE_CMPL  7		(Transitional) */
892 	(void *) emlxs_vfi_vpi_online_cmpl_action,	/* STATE_ENTER */
893 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
894 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
895 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
896 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
897 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
898 
899 
900 /* VFI_STATE_UNREG_CMPL  8		(Transitional) */
901 	(void *) emlxs_vfi_unreg_cmpl_action,		/* STATE_ENTER */
902 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
903 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
904 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
905 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
906 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
907 
908 /* VFI_STATE_UNREG_FAILED  9		(Transitional) */
909 	(void *) emlxs_vfi_unreg_failed_action,		/* STATE_ENTER */
910 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
911 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
912 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
913 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
914 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
915 
916 /* VFI_STATE_UNREG  10			(Wait for unreg_vfi cmpl) */
917 	(void *) emlxs_vfi_unreg_action,		/* STATE_ENTER */
918 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
919 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
920 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
921 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
922 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
923 
924 
925 /* VFI_STATE_REG  11			(Wait for reg_vfi cmpl) */
926 	(void *) emlxs_vfi_reg_action,			/* STATE_ENTER */
927 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
928 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
929 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
930 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
931 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
932 
933 /* VFI_STATE_REG_FAILED  12		(Transitional) */
934 	(void *) emlxs_vfi_reg_failed_action,		/* STATE_ENTER */
935 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
936 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
937 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
938 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
939 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
940 
941 /* VFI_STATE_REG_CMPL  13		(Transitional) */
942 	(void *) emlxs_vfi_reg_cmpl_action,		/* STATE_ENTER */
943 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
944 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
945 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
946 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
947 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
948 
949 
950 /* VFI_STATE_PAUSED  14			(Wait for VFI_OFFLINE event) */
951 	(void *) emlxs_vfi_paused_action,		/* STATE_ENTER */
952 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
953 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
954 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
955 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
956 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
957 
958 /* VFI_STATE_ONLINE  14			(Wait for VFI_OFFLINE event) */
959 	(void *) emlxs_vfi_online_action,		/* STATE_ENTER */
960 	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
961 	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
962 	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
963 	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
964 	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
965 
966 }; /* emlxs_vfi_action_table[] */
967 #define	VFI_ACTION_EVENTS			6
968 #define	VFI_ACTION_STATES			\
969 	(sizeof (emlxs_vfi_action_table)/ \
970 	(VFI_ACTION_EVENTS * sizeof (void *)))
971 
972 
973 /* ********************************************************************** */
974 /* VPI */
975 /* ********************************************************************** */
976 
977 /* Order does not matter */
978 emlxs_table_t emlxs_vpi_state_table[] =
979 {
980 	{VPI_STATE_OFFLINE, "VPI_STATE_OFFLINE"},
981 
982 	{VPI_STATE_INIT, "VPI_STATE_INIT"},
983 	{VPI_STATE_INIT_FAILED, "VPI_STATE_INIT_FAILED"},
984 	{VPI_STATE_INIT_CMPL, "VPI_STATE_INIT_CMPL"},
985 
986 	{VPI_STATE_UNREG_CMPL, "VPI_STATE_UNREG_CMPL"},
987 	{VPI_STATE_UNREG_FAILED, "VPI_STATE_UNREG_FAILED"},
988 	{VPI_STATE_UNREG, "VPI_STATE_UNREG"},
989 
990 	{VPI_STATE_LOGO_CMPL, "VPI_STATE_LOGO_CMPL"},
991 	{VPI_STATE_LOGO_FAILED, "VPI_STATE_LOGO_FAILED"},
992 	{VPI_STATE_LOGO, "VPI_STATE_LOGO"},
993 
994 	{VPI_STATE_PORT_OFFLINE, "VPI_STATE_PORT_OFFLINE"},
995 	{VPI_STATE_PORT_ONLINE, "VPI_STATE_PORT_ONLINE"},
996 
997 	{VPI_STATE_LOGI, "VPI_STATE_LOGI"},
998 	{VPI_STATE_LOGI_FAILED, "VPI_STATE_LOGI_FAILED"},
999 	{VPI_STATE_LOGI_CMPL, "VPI_STATE_LOGI_CMPL"},
1000 
1001 	{VPI_STATE_REG, "VPI_STATE_REG"},
1002 	{VPI_STATE_REG_FAILED, "VPI_STATE_REG_FAILED"},
1003 	{VPI_STATE_REG_CMPL, "VPI_STATE_REG_CMPL"},
1004 
1005 	{VPI_STATE_PAUSED, "VPI_STATE_PAUSED"},
1006 	{VPI_STATE_ONLINE, "VPI_STATE_ONLINE"},
1007 
1008 }; /* emlxs_vpi_state_table */
1009 
1010 
1011 static uint32_t emlxs_vpi_online_evt_action(emlxs_port_t *port,
1012 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1013 static uint32_t emlxs_vpi_offline_evt_action(emlxs_port_t *port,
1014 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1015 static uint32_t emlxs_vpi_pause_evt_action(emlxs_port_t *port,
1016 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1017 static uint32_t emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port,
1018 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1019 static uint32_t emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port,
1020 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1021 static uint32_t emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port,
1022 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1023 
1024 static uint32_t emlxs_vpi_init_action(emlxs_port_t *port,
1025 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1026 static uint32_t emlxs_vpi_init_failed_action(emlxs_port_t *port,
1027 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1028 static uint32_t emlxs_vpi_init_cmpl_action(emlxs_port_t *port,
1029 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1030 
1031 static uint32_t emlxs_vpi_offline_action(emlxs_port_t *port,
1032 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1033 static uint32_t emlxs_vpi_online_action(emlxs_port_t *port,
1034 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1035 static uint32_t emlxs_vpi_paused_action(emlxs_port_t *port,
1036 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1037 
1038 static uint32_t emlxs_vpi_port_online_action(emlxs_port_t *port,
1039 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1040 static uint32_t emlxs_vpi_port_offline_action(emlxs_port_t *port,
1041 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1042 
1043 static uint32_t emlxs_vpi_logi_cmpl_action(emlxs_port_t *port,
1044 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1045 static uint32_t emlxs_vpi_logi_failed_action(emlxs_port_t *port,
1046 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1047 static uint32_t emlxs_vpi_logi_action(emlxs_port_t *port,
1048 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1049 
1050 static uint32_t emlxs_vpi_reg_action(emlxs_port_t *port,
1051 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1052 static uint32_t emlxs_vpi_reg_failed_action(emlxs_port_t *port,
1053 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1054 static uint32_t emlxs_vpi_reg_cmpl_action(emlxs_port_t *port,
1055 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1056 
1057 static uint32_t emlxs_vpi_unreg_action(emlxs_port_t *port,
1058 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1059 static uint32_t emlxs_vpi_unreg_failed_action(emlxs_port_t *port,
1060 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1061 static uint32_t emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port,
1062 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1063 
1064 static uint32_t emlxs_vpi_logo_action(emlxs_port_t *port,
1065 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1066 static uint32_t emlxs_vpi_logo_failed_action(emlxs_port_t *port,
1067 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1068 static uint32_t emlxs_vpi_logo_cmpl_action(emlxs_port_t *port,
1069 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1070 
1071 static uint32_t emlxs_vpi_event(emlxs_port_t *port,
1072 			uint32_t evt, void *arg1);
1073 static void emlxs_vpi_flogi_cmpl(emlxs_port_t *port, VPIobj_t *vpip,
1074 			uint32_t status);
1075 
1076 /*
1077  * - Online sequencing can only start from VPI_STATE_OFFLINE or
1078  * VPI_STATE_PORT_OFFLINE state.
1079  *
1080  * - Offline sequencing can interrupt the online sequencing at the
1081  * entry of the next wait state.
1082  *
1083  * NORMAL ONLINE SEQ
1084  * ---------------------------
1085  * VPI_ONLINE event <-- VFI
1086  * VPI_STATE_OFFLINE
1087  * VPI_STATE_INIT
1088  *     VPI_STATE_INIT_CMPL
1089  * VPI_STATE_PORT_ONLINE
1090  * VPI_STATE_LOGI
1091  *     VPI_STATE_LOGI_CMPL
1092  * VPI_STATE_REG
1093  *     VPI_STATE_REG_CMPL
1094  * VPI_STATE_ONLINE
1095  * VPI_ONLINE event-->VFI
1096  *
1097  *
1098  * NORMAL OFFLINE SEQ
1099  * ---------------------------
1100  * VPI_OFFLINE event <-- VFI
1101  * VPI_STATE_ONLINE
1102  * VPI_STATE_PORT_OFFLINE
1103  * VPI_STATE_LOGO
1104  *     VPI_STATE_LOGO_CMPL
1105  * VPI_STATE_UNREG
1106  *     VPI_STATE_UNREG_CMPL
1107  * VPI_STATE_OFFLINE
1108  * VPI_OFFLINE event-->VFI
1109  *
1110  *
1111  * NORMAL PAUSE SEQ
1112  * ---------------------------
1113  * VPI_PAUSE event <-- VFI
1114  * VPI_STATE_ONLINE
1115  * VPI_STATE_PORT_OFFLINE
1116  * VPI_STATE_PAUSED
1117  *
1118  */
1119 /* Order does matter */
1120 static void *emlxs_vpi_action_table[] =
1121 {
1122 	/* Action routine				Event */
1123 /* VPI_STATE_OFFLINE  0 		(Wait for VPI_ONLINE event) */
1124 	(void *) emlxs_vpi_offline_action,		/* STATE_ENTER */
1125 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1126 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1127 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1128 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1129 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1130 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1131 
1132 
1133 /* VPI_STATE_INIT  1 			(Wait for init_vpi cmpl) */
1134 	(void *) emlxs_vpi_init_action,			/* STATE_ENTER */
1135 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1136 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1137 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1138 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1139 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1140 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1141 
1142 /* VPI_STATE_INIT_FAILED  2  		(Transitional) */
1143 	(void *) emlxs_vpi_init_failed_action,		/* STATE_ENTER */
1144 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1145 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1146 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1147 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1148 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1149 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1150 
1151 /* VPI_STATE_INIT_CMPL  3 		(Transitional) */
1152 	(void *) emlxs_vpi_init_cmpl_action,		/* STATE_ENTER */
1153 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1154 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1155 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1156 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1157 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1158 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1159 
1160 
1161 /* VPI_STATE_UNREG_CMPL  4 		(Transitional) */
1162 	(void *) emlxs_vpi_unreg_cmpl_action,		/* STATE_ENTER */
1163 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1164 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1165 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1166 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1167 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1168 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1169 
1170 /* VPI_STATE_UNREG_FAILED  5  		(Transitional) */
1171 	(void *) emlxs_vpi_unreg_failed_action,		/* STATE_ENTER */
1172 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1173 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1174 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1175 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1176 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1177 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1178 
1179 /* VPI_STATE_UNREG  6 			(Wait for unreg_vpi cmpl) */
1180 	(void *) emlxs_vpi_unreg_action,		/* STATE_ENTER */
1181 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1182 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1183 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1184 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1185 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1186 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1187 
1188 
1189 /* VPI_STATE_LOGO_CMPL  7 		(Transitional) */
1190 	(void *) emlxs_vpi_logo_cmpl_action,		/* STATE_ENTER */
1191 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1192 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1193 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1194 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1195 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1196 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1197 
1198 /* VPI_STATE_LOGO_FAILED  8  		(Transitional) */
1199 	(void *) emlxs_vpi_logo_failed_action,		/* STATE_ENTER */
1200 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1201 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1202 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1203 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1204 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1205 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1206 
1207 /* VPI_STATE_LOGO  9 			(Transitional) */
1208 	(void *) emlxs_vpi_logo_action,			/* STATE_ENTER */
1209 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1210 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1211 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1212 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1213 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1214 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1215 
1216 
1217 /* VPI_STATE_PORT_OFFLINE  10	(Wait for RPI_OFFLINE or VPI_ONLINE) */
1218 	(void *) emlxs_vpi_port_offline_action,		/* STATE_ENTER */
1219 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1220 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1221 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1222 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1223 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1224 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1225 
1226 /* VPI_STATE_PORT_ONLINE  11 	(Wait for emlxs_vpi_logi_notify() ) */
1227 	(void *) emlxs_vpi_port_online_action,		/* STATE_ENTER */
1228 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1229 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1230 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1231 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1232 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1233 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1234 
1235 
1236 /* VPI_STATE_LOGI  12 		(Wait for emlxs_vpi_logi_cmpl_notify() ) */
1237 	(void *) emlxs_vpi_logi_action,			/* STATE_ENTER */
1238 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1239 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1240 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1241 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1242 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1243 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1244 
1245 /* VPI_STATE_LOGI_FAILED  13  		(Transitional) */
1246 	(void *) emlxs_vpi_logi_failed_action,		/* STATE_ENTER */
1247 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1248 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1249 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1250 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1251 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1252 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1253 
1254 /* VPI_STATE_LOGI_CMPL  14 		(Transitional) */
1255 	(void *) emlxs_vpi_logi_cmpl_action,		/* STATE_ENTER */
1256 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1257 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1258 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1259 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1260 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1261 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1262 
1263 
1264 /* VPI_STATE_REG  15 			(Wait for reg_vpi cmpl) */
1265 	(void *) emlxs_vpi_reg_action,			/* STATE_ENTER */
1266 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1267 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1268 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1269 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1270 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1271 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1272 
1273 /* VPI_STATE_REG_FAILED  16  		(Transitional) */
1274 	(void *) emlxs_vpi_reg_failed_action,		/* STATE_ENTER */
1275 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1276 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1277 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1278 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1279 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1280 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1281 
1282 /* VPI_STATE_REG_CMPL  17 		(Transitional) */
1283 	(void *) emlxs_vpi_reg_cmpl_action,		/* STATE_ENTER */
1284 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1285 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1286 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1287 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1288 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1289 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1290 
1291 
1292 /* VPI_STATE_PAUSED 18			(Wait for VPI_ONLINE() ) */
1293 	(void *) emlxs_vpi_paused_action,		/* STATE_ENTER */
1294 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1295 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1296 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1297 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1298 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1299 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1300 
1301 /* VPI_STATE_ONLINE  19 		(Wait for VPI_OFFLINE event) */
1302 	(void *) emlxs_vpi_online_action,		/* STATE_ENTER */
1303 	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1304 	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1305 	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1306 	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1307 	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1308 	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1309 
1310 }; /* emlxs_vpi_action_table() */
1311 #define	VPI_ACTION_EVENTS			7
1312 #define	VPI_ACTION_STATES			\
1313 	(sizeof (emlxs_vpi_action_table)/ \
1314 	(VPI_ACTION_EVENTS * sizeof (void *)))
1315 
1316 
1317 /* ********************************************************************** */
1318 /* RPI */
1319 /* ********************************************************************** */
1320 
1321 /* Order does not matter */
1322 emlxs_table_t emlxs_rpi_state_table[] =
1323 {
1324 	{RPI_STATE_FREE, "RPI_STATE_FREE"},
1325 
1326 	{RPI_STATE_OFFLINE, "RPI_STATE_OFFLINE"},
1327 
1328 	{RPI_STATE_UNREG_CMPL, "RPI_STATE_UNREG_CMPL"},
1329 	{RPI_STATE_UNREG_FAILED, "RPI_STATE_UNREG_FAILED"},
1330 	{RPI_STATE_UNREG, "RPI_STATE_UNREG"},
1331 
1332 	{RPI_STATE_REG, "RPI_STATE_REG"},
1333 	{RPI_STATE_REG_FAILED, "RPI_STATE_REG_FAILED"},
1334 	{RPI_STATE_REG_CMPL, "RPI_STATE_REG_CMPL"},
1335 
1336 	{RPI_STATE_PAUSED, "RPI_STATE_PAUSED"},
1337 
1338 	{RPI_STATE_RESUME, "RPI_STATE_RESUME"},
1339 	{RPI_STATE_RESUME_FAILED, "RPI_STATE_RESUME_FAILED"},
1340 	{RPI_STATE_RESUME_CMPL, "RPI_STATE_RESUME_CMPL"},
1341 
1342 	{RPI_STATE_ONLINE, "RPI_STATE_ONLINE"},
1343 
1344 }; /* emlxs_rpi_state_table */
1345 
1346 static uint32_t emlxs_rpi_free_action(emlxs_port_t *port,
1347 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1348 
1349 static uint32_t emlxs_rpi_online_evt_action(emlxs_port_t *port,
1350 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1351 static uint32_t emlxs_rpi_offline_evt_action(emlxs_port_t *port,
1352 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1353 static uint32_t emlxs_rpi_pause_evt_action(emlxs_port_t *port,
1354 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1355 static uint32_t emlxs_rpi_resume_evt_action(emlxs_port_t *port,
1356 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1357 
1358 static uint32_t emlxs_rpi_reg_action(emlxs_port_t *port,
1359 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1360 static uint32_t emlxs_rpi_reg_cmpl_action(emlxs_port_t *port,
1361 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1362 static uint32_t emlxs_rpi_reg_failed_action(emlxs_port_t *port,
1363 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1364 
1365 static uint32_t emlxs_rpi_unreg_action(emlxs_port_t *port,
1366 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1367 static uint32_t emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port,
1368 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1369 static uint32_t emlxs_rpi_unreg_failed_action(emlxs_port_t *port,
1370 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1371 
1372 static uint32_t emlxs_rpi_online_action(emlxs_port_t *port,
1373 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1374 static uint32_t emlxs_rpi_paused_action(emlxs_port_t *port,
1375 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1376 static uint32_t emlxs_rpi_offline_action(emlxs_port_t *port,
1377 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1378 
1379 static uint32_t emlxs_rpi_resume_failed_action(emlxs_port_t *port,
1380 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1381 static uint32_t emlxs_rpi_resume_cmpl_action(emlxs_port_t *port,
1382 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1383 static uint32_t emlxs_rpi_resume_action(emlxs_port_t *port,
1384 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1385 
1386 static uint32_t emlxs_rpi_event(emlxs_port_t *port,
1387 			uint32_t evt, void *arg1);
1388 static RPIobj_t *emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did);
1389 static uint32_t emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip);
1390 static RPIobj_t *emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did);
1391 
1392 static void emlxs_rpi_resume_handler(emlxs_port_t *port,
1393 			RPIobj_t *rpip);
1394 static void emlxs_rpi_unreg_handler(emlxs_port_t *port,
1395 			RPIobj_t *rpip);
1396 static uint32_t emlxs_rpi_reg_handler(emlxs_port_t *port,
1397 			RPIobj_t *rpip);
1398 /*
1399  * - Online sequencing can start from RPI_STATE_OFFLINE state or
1400  * the RPI_STATE_PAUSED state.
1401  *
1402  * - Offline sequencing can interrupt the online sequencing at the
1403  * entry of the next wait state.
1404  *
1405  * NORMAL ONLINE SEQ
1406  * ---------------------------
1407  * RPI_ONLINE event <-- VPI
1408  * RPI_STATE_OFFLINE
1409  * RPI_STATE_REG
1410  *     RPI_STATE_REG_CMPL
1411  * RPI_STATE_ONLINE
1412  * RPI_ONLINE event-->VPI
1413  *
1414  *
1415  * NORMAL OFFLINE SEQ
1416  * ---------------------------
1417  * RPI_OFFLINE event <-- VPI
1418  * RPI_STATE_ONLINE
1419  * RPI_STATE_UNREG
1420  *     RPI_STATE_UNREG_CMPL
1421  * RPI_STATE_OFFLINE
1422  * RPI_OFFLINE event-->VPI
1423  *
1424  *
1425  * NORMAL PAUSE SEQ
1426  * ---------------------------
1427  * RPI_PAUSE event <-- VPI
1428  * RPI_STATE_ONLINE
1429  * RPI_STATE_PAUSED
1430  *
1431  */
1432 /* Order does matter */
1433 static void *emlxs_rpi_action_table[] =
1434 {
1435 	/* Action routine				Event */
1436 /* RPI_STATE_FREE  0			(Wait for allocation) */
1437 	(void *) emlxs_rpi_free_action,			/* STATE_ENTER */
1438 	(void *) NULL,					/* RPI_ONLINE */
1439 	(void *) NULL,					/* RPI_OFFLINE */
1440 	(void *) NULL,					/* RPI_PAUSE */
1441 	(void *) NULL,					/* RPI_RESUME */
1442 
1443 /* RPI_STATE_OFFLINE  1			(Wait for RPI_ONLINE event) */
1444 	(void *) emlxs_rpi_offline_action,		/* STATE_ENTER */
1445 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1446 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1447 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1448 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1449 
1450 /* RPI_STATE_UNREG_CMPL  2		(Transitional)  */
1451 	(void *) emlxs_rpi_unreg_cmpl_action,		/* STATE_ENTER */
1452 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1453 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1454 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1455 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1456 
1457 /* RPI_STATE_UNREG_FAILED  3		(Transitional) */
1458 	(void *) emlxs_rpi_unreg_failed_action, 	/* STATE_ENTER */
1459 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1460 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1461 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1462 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1463 
1464 /* RPI_STATE_UNREG  4			(Wait for unreg_rpi cmpl) */
1465 	(void *) emlxs_rpi_unreg_action,		/* STATE_ENTER */
1466 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1467 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1468 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1469 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1470 
1471 
1472 /* RPI_STATE_REG  5			(Wait for reg_rpi cmpl) */
1473 	(void *) emlxs_rpi_reg_action,			/* STATE_ENTER */
1474 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1475 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1476 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1477 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1478 
1479 /* RPI_STATE_REG_FAILED  6		(Transitional) */
1480 	(void *) emlxs_rpi_reg_failed_action,		/* STATE_ENTER */
1481 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1482 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1483 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1484 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1485 
1486 /* RPI_STATE_REG_CMPL  7		(Transitional) */
1487 	(void *) emlxs_rpi_reg_cmpl_action,		/* STATE_ENTER */
1488 	(void *) emlxs_rpi_online_evt_action,  		/* RPI_ONLINE */
1489 	(void *) emlxs_rpi_offline_evt_action, 		/* RPI_OFFLINE */
1490 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1491 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1492 
1493 
1494 /* RPI_STATE_PAUSED  8			(Wait for RPI_ONLINE) */
1495 	(void *) emlxs_rpi_paused_action,		/* STATE_ENTER */
1496 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1497 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1498 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1499 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1500 
1501 
1502 /* RPI_STATE_RESUME  9			(Wait for resume_rpi mbcmpl) */
1503 	(void *) emlxs_rpi_resume_action,		/* STATE_ENTER */
1504 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1505 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1506 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1507 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1508 
1509 /* RPI_STATE_RESUME_FAILED  10		(Transitional) */
1510 	(void *) emlxs_rpi_resume_failed_action,	/* STATE_ENTER */
1511 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1512 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1513 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1514 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1515 
1516 /* RPI_STATE_RESUME_CMPL  11		(Transitional) */
1517 	(void *) emlxs_rpi_resume_cmpl_action, 		/* STATE_ENTER */
1518 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1519 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1520 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1521 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1522 
1523 
1524 /* RPI_STATE_ONLINE 12			(Wait for RPI_OFFLINE event) */
1525 	(void *) emlxs_rpi_online_action,		/* STATE_ENTER */
1526 	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1527 	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1528 	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1529 	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1530 
1531 }; /* emlxs_rpi_action_table[] */
1532 #define	RPI_ACTION_EVENTS			5
1533 #define	RPI_ACTION_STATES			\
1534 	(sizeof (emlxs_rpi_action_table)/ \
1535 	(RPI_ACTION_EVENTS * sizeof (void *)))
1536 
1537 
1538 /* ************************************************************************** */
1539 /* FCF Generic */
1540 /* ************************************************************************** */
1541 
1542 extern void
1543 emlxs_fcf_fini(emlxs_hba_t *hba)
1544 {
1545 	emlxs_port_t	*port = &PPORT;
1546 	emlxs_port_t	*vport;
1547 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
1548 	uint32_t	i;
1549 	RPIobj_t	*rpip;
1550 
1551 	if (!fcftab->table) {
1552 		return;
1553 	}
1554 
1555 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
1556 	    "emlxs_fcf_fini: %s flag=%x fcfi_online=%d.",
1557 	    emlxs_fcftab_state_xlate(fcftab->state),
1558 	    fcftab->flag, fcftab->fcfi_online);
1559 
1560 	if (fcftab->state != FCFTAB_STATE_SHUTDOWN) {
1561 		(void) emlxs_fcf_shutdown_notify(port, 1);
1562 	}
1563 
1564 	mutex_enter(&EMLXS_FCF_LOCK);
1565 
1566 	/* Free the FCF memory */
1567 
1568 	kmem_free(fcftab->table,
1569 	    (sizeof (FCFIobj_t) * fcftab->table_count));
1570 
1571 	fcftab->table = NULL;
1572 	fcftab->table_count = 0;
1573 
1574 	/* Free the VFI memory */
1575 
1576 	kmem_free(hba->sli.sli4.VFI_table,
1577 	    (sizeof (VFIobj_t) * hba->sli.sli4.VFICount));
1578 
1579 	hba->sli.sli4.VFI_table = NULL;
1580 	hba->sli.sli4.VFICount = 0;
1581 
1582 	/* Free the VPI Fabric RPI's */
1583 
1584 	for (i = 0; i < MAX_VPORTS; i++) {
1585 		vport = &VPORT(i);
1586 		rpip = &vport->VPIobj.fcf_rpi;
1587 
1588 		if (rpip->state == RPI_STATE_FREE) {
1589 			continue;
1590 		}
1591 
1592 		(void) emlxs_rpi_free(port, rpip);
1593 	}
1594 
1595 	/* Free the RPI memory */
1596 
1597 	rpip = hba->sli.sli4.RPIp;
1598 	for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
1599 		if (rpip->state == RPI_STATE_FREE) {
1600 			continue;
1601 		}
1602 
1603 		(void) emlxs_rpi_free(port, rpip);
1604 	}
1605 
1606 	kmem_free(hba->sli.sli4.RPIp,
1607 	    (sizeof (RPIobj_t) * hba->sli.sli4.RPICount));
1608 
1609 	hba->sli.sli4.RPIp = NULL;
1610 	hba->sli.sli4.RPICount = 0;
1611 
1612 	/* Free the mutex */
1613 
1614 	mutex_exit(&EMLXS_FCF_LOCK);
1615 	mutex_destroy(&EMLXS_FCF_LOCK);
1616 
1617 	return;
1618 
1619 } /* emlxs_fcf_fini() */
1620 
1621 
1622 extern void
1623 emlxs_fcf_init(emlxs_hba_t *hba)
1624 {
1625 	emlxs_port_t	*port = &PPORT;
1626 	emlxs_port_t	*vport;
1627 	uint16_t	i;
1628 	FCFIobj_t	*fcfp;
1629 	VFIobj_t	*vfip;
1630 	RPIobj_t	*rpip;
1631 	char		buf[64];
1632 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
1633 	uint16_t	index;
1634 
1635 	if (fcftab->table) {
1636 		return;
1637 	}
1638 
1639 	/* FCFTAB */
1640 
1641 	bzero(fcftab, sizeof (FCFTable_t));
1642 
1643 	(void) sprintf(buf, "%s_fcf_lock mutex", DRIVER_NAME);
1644 	mutex_init(&EMLXS_FCF_LOCK, buf, MUTEX_DRIVER, NULL);
1645 	mutex_enter(&EMLXS_FCF_LOCK);
1646 
1647 	fcftab->state = FCFTAB_STATE_OFFLINE;
1648 
1649 	/* FCFI */
1650 
1651 	fcftab->table_count = hba->sli.sli4.FCFICount;
1652 	fcftab->table = (FCFIobj_t *)kmem_zalloc(
1653 	    (sizeof (FCFIobj_t) * fcftab->table_count), KM_SLEEP);
1654 
1655 	fcfp = fcftab->table;
1656 	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
1657 		fcfp->index = i;
1658 		fcfp->FCFI  = 0xFFFF;
1659 		fcfp->state = FCFI_STATE_FREE;
1660 	}
1661 
1662 	/* VFI */
1663 
1664 	hba->sli.sli4.VFI_table = (VFIobj_t *)kmem_zalloc(
1665 	    (sizeof (VFIobj_t) * hba->sli.sli4.VFICount), KM_SLEEP);
1666 
1667 	vfip = hba->sli.sli4.VFI_table;
1668 	index = hba->sli.sli4.VFIBase;
1669 	for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++, index++) {
1670 		vfip->VFI = index;
1671 		vfip->index = i;
1672 		vfip->state = VPI_STATE_OFFLINE;
1673 	}
1674 
1675 	/* VPI */
1676 
1677 	for (i = 0; i < MAX_VPORTS; i++) {
1678 		vport = &VPORT(i);
1679 		bzero(&vport->VPIobj, sizeof (VPIobj_t));
1680 
1681 		vport->VPIobj.index = i;
1682 		vport->VPIobj.VPI = i + hba->sli.sli4.VPIBase;
1683 		vport->VPIobj.port = vport;
1684 		vport->VPIobj.state = VPI_STATE_OFFLINE;
1685 
1686 		/* Init the Fabric RPI's */
1687 		rpip = &vport->VPIobj.fcf_rpi;
1688 		rpip->state = RPI_STATE_FREE;
1689 		rpip->RPI   = 0xffff;
1690 		rpip->index = 0xffff;
1691 		rpip->did   = FABRIC_DID;
1692 		rpip->vpip  = &vport->VPIobj;
1693 		vport->VPIobj.rpip = rpip;
1694 	}
1695 
1696 	/* RPI */
1697 
1698 	hba->sli.sli4.RPIp = (RPIobj_t *)kmem_zalloc(
1699 	    (sizeof (RPIobj_t) * hba->sli.sli4.RPICount), KM_SLEEP);
1700 
1701 	rpip = hba->sli.sli4.RPIp;
1702 	index = hba->sli.sli4.RPIBase;
1703 	for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++, index++) {
1704 		rpip->state = RPI_STATE_FREE;
1705 		rpip->RPI = index;
1706 		rpip->index = i;
1707 	}
1708 
1709 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
1710 	    "emlxs_fcf_init: %s flag=%x fcfi=%d vfi=%d vpi=%d rpi=%d",
1711 	    emlxs_fcftab_state_xlate(fcftab->state),
1712 	    fcftab->flag,
1713 	    fcftab->table_count,
1714 	    hba->sli.sli4.VFICount,
1715 	    MAX_VPORTS,
1716 	    hba->sli.sli4.RPICount);
1717 
1718 	mutex_exit(&EMLXS_FCF_LOCK);
1719 
1720 	return;
1721 
1722 } /* emlxs_fcf_init() */
1723 
1724 
1725 static char *
1726 emlxs_fcf_event_xlate(uint32_t state)
1727 {
1728 	static char buffer[32];
1729 	uint32_t i;
1730 	uint32_t count;
1731 
1732 	count = sizeof (emlxs_fcf_event_table) / sizeof (emlxs_table_t);
1733 	for (i = 0; i < count; i++) {
1734 		if (state == emlxs_fcf_event_table[i].code) {
1735 			return (emlxs_fcf_event_table[i].string);
1736 		}
1737 	}
1738 
1739 	(void) sprintf(buffer, "event=0x%x", state);
1740 	return (buffer);
1741 
1742 } /* emlxs_fcf_event_xlate() */
1743 
1744 
1745 static char *
1746 emlxs_fcf_reason_xlate(uint32_t reason)
1747 {
1748 	static char buffer[32];
1749 	uint32_t i;
1750 	uint32_t count;
1751 
1752 	count = sizeof (emlxs_fcf_reason_table) / sizeof (emlxs_table_t);
1753 	for (i = 0; i < count; i++) {
1754 		if (reason == emlxs_fcf_reason_table[i].code) {
1755 			return (emlxs_fcf_reason_table[i].string);
1756 		}
1757 	}
1758 
1759 	(void) sprintf(buffer, "reason=0x%x", reason);
1760 	return (buffer);
1761 
1762 } /* emlxs_fcf_reason_xlate() */
1763 
1764 
1765 extern void
1766 emlxs_fcf_timer_notify(emlxs_hba_t *hba)
1767 {
1768 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
1769 
1770 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
1771 		return;
1772 	}
1773 
1774 	if (fcftab->table == 0) {
1775 		return;
1776 	}
1777 
1778 	mutex_enter(&EMLXS_FCF_LOCK);
1779 
1780 	emlxs_fcftab_sol_timer(hba);
1781 
1782 	emlxs_fcftab_read_timer(hba);
1783 
1784 	emlxs_fcftab_offline_timer(hba);
1785 
1786 	mutex_exit(&EMLXS_FCF_LOCK);
1787 
1788 	return;
1789 
1790 } /* emlxs_fcf_timer_notify() */
1791 
1792 
1793 extern uint32_t
1794 emlxs_fcf_shutdown_notify(emlxs_port_t *port, uint32_t wait)
1795 {
1796 	emlxs_hba_t *hba = HBA;
1797 	emlxs_port_t *pport = &PPORT;
1798 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
1799 	uint32_t rval;
1800 	uint32_t i;
1801 
1802 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
1803 		return (1);
1804 	}
1805 
1806 	if (!(pport->flag & EMLXS_PORT_BOUND)) {
1807 		return (1);
1808 	}
1809 
1810 	mutex_enter(&EMLXS_FCF_LOCK);
1811 
1812 	rval = emlxs_fcftab_event(port, FCF_EVENT_SHUTDOWN, 0);
1813 
1814 	if (wait && (rval == 0)) {
1815 		/* Wait for FCF table to shutdown */
1816 		i = 0;
1817 		while (i++ < 120) {
1818 			if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) {
1819 				break;
1820 			}
1821 
1822 			mutex_exit(&EMLXS_FCF_LOCK);
1823 			DELAYMS(1000);
1824 			mutex_enter(&EMLXS_FCF_LOCK);
1825 		}
1826 
1827 		if (i >= 120) {
1828 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
1829 			    "fcf_shutdown_notify: %s flag=%x fcfi_online=%d. "
1830 			    "Shutdown timeout.",
1831 			    emlxs_fcftab_state_xlate(fcftab->state),
1832 			    fcftab->flag, fcftab->fcfi_online);
1833 		}
1834 	}
1835 
1836 	mutex_exit(&EMLXS_FCF_LOCK);
1837 
1838 	return (rval);
1839 
1840 } /* emlxs_fcf_shutdown_notify() */
1841 
1842 
1843 extern uint32_t
1844 emlxs_fcf_linkup_notify(emlxs_port_t *port)
1845 {
1846 	emlxs_hba_t *hba = HBA;
1847 	emlxs_port_t *pport = &PPORT;
1848 	uint32_t rval;
1849 
1850 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
1851 		return (1);
1852 	}
1853 
1854 	if (!(pport->flag & EMLXS_PORT_BOUND)) {
1855 		return (1);
1856 	}
1857 
1858 	mutex_enter(&EMLXS_FCF_LOCK);
1859 
1860 	rval = emlxs_fcftab_event(port, FCF_EVENT_LINKUP, 0);
1861 
1862 	mutex_exit(&EMLXS_FCF_LOCK);
1863 
1864 	return (rval);
1865 
1866 } /* emlxs_fcf_linkup_notify() */
1867 
1868 
1869 extern uint32_t
1870 emlxs_fcf_linkdown_notify(emlxs_port_t *port)
1871 {
1872 	emlxs_hba_t *hba = HBA;
1873 	emlxs_port_t *pport = &PPORT;
1874 	uint32_t rval;
1875 
1876 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
1877 		return (1);
1878 	}
1879 
1880 	if (!(pport->flag & EMLXS_PORT_BOUND)) {
1881 		return (1);
1882 	}
1883 
1884 	mutex_enter(&EMLXS_FCF_LOCK);
1885 
1886 	rval = emlxs_fcftab_event(port, FCF_EVENT_LINKDOWN, 0);
1887 
1888 	mutex_exit(&EMLXS_FCF_LOCK);
1889 
1890 	return (rval);
1891 
1892 } /* emlxs_fcf_linkdown_notify() */
1893 
1894 
1895 extern uint32_t
1896 emlxs_fcf_cvl_notify(emlxs_port_t *port, uint32_t vpi)
1897 {
1898 	emlxs_hba_t *hba = HBA;
1899 	emlxs_port_t *pport = &PPORT;
1900 	uint32_t rval;
1901 
1902 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
1903 		return (1);
1904 	}
1905 
1906 	if (!(pport->flag & EMLXS_PORT_BOUND)) {
1907 		return (1);
1908 	}
1909 
1910 	mutex_enter(&EMLXS_FCF_LOCK);
1911 
1912 	rval = emlxs_fcftab_event(port, FCF_EVENT_CVL,
1913 	    (void *)((uintptr_t)vpi));
1914 
1915 	mutex_exit(&EMLXS_FCF_LOCK);
1916 
1917 	return (rval);
1918 
1919 } /* emlxs_fcf_cvl_notify() */
1920 
1921 
1922 extern uint32_t
1923 emlxs_fcf_full_notify(emlxs_port_t *port)
1924 {
1925 	emlxs_hba_t *hba = HBA;
1926 	emlxs_port_t *pport = &PPORT;
1927 	uint32_t rval;
1928 
1929 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
1930 		return (1);
1931 	}
1932 
1933 	if (!(pport->flag & EMLXS_PORT_BOUND)) {
1934 		return (1);
1935 	}
1936 
1937 	mutex_enter(&EMLXS_FCF_LOCK);
1938 
1939 	rval = emlxs_fcftab_event(port, FCF_EVENT_FCFTAB_FULL, 0);
1940 
1941 	mutex_exit(&EMLXS_FCF_LOCK);
1942 
1943 	return (rval);
1944 
1945 } /* emlxs_fcf_full_notify() */
1946 
1947 
1948 extern uint32_t
1949 emlxs_fcf_found_notify(emlxs_port_t *port, uint32_t fcf_index)
1950 {
1951 	emlxs_hba_t *hba = HBA;
1952 	emlxs_port_t *pport = &PPORT;
1953 	uint32_t rval;
1954 
1955 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
1956 		return (1);
1957 	}
1958 
1959 	if (!(pport->flag & EMLXS_PORT_BOUND)) {
1960 		return (1);
1961 	}
1962 
1963 	mutex_enter(&EMLXS_FCF_LOCK);
1964 
1965 	rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_FOUND,
1966 	    (void *)((uintptr_t)fcf_index));
1967 
1968 	mutex_exit(&EMLXS_FCF_LOCK);
1969 
1970 	return (rval);
1971 
1972 } /* emlxs_fcf_found_notify() */
1973 
1974 
1975 extern uint32_t
1976 emlxs_fcf_changed_notify(emlxs_port_t *port, uint32_t fcf_index)
1977 {
1978 	emlxs_hba_t *hba = HBA;
1979 	emlxs_port_t *pport = &PPORT;
1980 	uint32_t rval;
1981 
1982 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
1983 		return (1);
1984 	}
1985 
1986 	if (!(pport->flag & EMLXS_PORT_BOUND)) {
1987 		return (1);
1988 	}
1989 
1990 	mutex_enter(&EMLXS_FCF_LOCK);
1991 
1992 	rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_CHANGED,
1993 	    (void *)((uintptr_t)fcf_index));
1994 
1995 	mutex_exit(&EMLXS_FCF_LOCK);
1996 
1997 	return (rval);
1998 
1999 } /* emlxs_fcf_changed_notify() */
2000 
2001 
2002 extern uint32_t
2003 emlxs_fcf_lost_notify(emlxs_port_t *port, uint32_t fcf_index)
2004 {
2005 	emlxs_hba_t *hba = HBA;
2006 	emlxs_port_t *pport = &PPORT;
2007 	uint32_t rval;
2008 
2009 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2010 		return (1);
2011 	}
2012 
2013 	if (!(pport->flag & EMLXS_PORT_BOUND)) {
2014 		return (1);
2015 	}
2016 
2017 	mutex_enter(&EMLXS_FCF_LOCK);
2018 
2019 	rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_LOST,
2020 	    (void *)((uintptr_t)fcf_index));
2021 
2022 	mutex_exit(&EMLXS_FCF_LOCK);
2023 
2024 	return (rval);
2025 
2026 } /* emlxs_fcf_lost_notify() */
2027 
2028 
2029 
2030 /* ************************************************************************** */
2031 /* FCFTAB */
2032 /* ************************************************************************** */
2033 
2034 static char *
2035 emlxs_fcftab_state_xlate(uint32_t state)
2036 {
2037 	static char buffer[32];
2038 	uint32_t i;
2039 	uint32_t count;
2040 
2041 	count = sizeof (emlxs_fcftab_state_table) / sizeof (emlxs_table_t);
2042 	for (i = 0; i < count; i++) {
2043 		if (state == emlxs_fcftab_state_table[i].code) {
2044 			return (emlxs_fcftab_state_table[i].string);
2045 		}
2046 	}
2047 
2048 	(void) sprintf(buffer, "state=0x%x", state);
2049 	return (buffer);
2050 
2051 } /* emlxs_fcftab_state_xlate() */
2052 
2053 
2054 static uint32_t
2055 emlxs_fcftab_action(emlxs_port_t *port, uint32_t evt,
2056     void *arg1)
2057 {
2058 	emlxs_hba_t *hba = HBA;
2059 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2060 	uint32_t rval;
2061 	uint32_t(*func) (emlxs_port_t *, uint32_t, void *);
2062 	uint32_t index;
2063 	uint32_t events;
2064 	uint16_t state;
2065 
2066 	/* Convert event to action table index */
2067 	switch (evt) {
2068 	case FCF_EVENT_STATE_ENTER:
2069 		index = 0;
2070 		break;
2071 	case FCF_EVENT_SHUTDOWN:
2072 		index = 1;
2073 		break;
2074 	case FCF_EVENT_LINKUP:
2075 		index = 2;
2076 		break;
2077 	case FCF_EVENT_LINKDOWN:
2078 		index = 3;
2079 		break;
2080 	case FCF_EVENT_CVL:
2081 		index = 4;
2082 		break;
2083 	case FCF_EVENT_FCF_FOUND:
2084 		index = 5;
2085 		break;
2086 	case FCF_EVENT_FCF_LOST:
2087 		index = 6;
2088 		break;
2089 	case FCF_EVENT_FCF_CHANGED:
2090 		index = 7;
2091 		break;
2092 	case FCF_EVENT_FCFTAB_FULL:
2093 		index = 8;
2094 		break;
2095 	case FCF_EVENT_FCFI_ONLINE:
2096 		index = 9;
2097 		break;
2098 	case FCF_EVENT_FCFI_OFFLINE:
2099 		index = 10;
2100 		break;
2101 	default:
2102 		return (1);
2103 	}
2104 
2105 	events = FCFTAB_ACTION_EVENTS;
2106 	state  = fcftab->state;
2107 
2108 	index += (state * events);
2109 	func   = (uint32_t(*) (emlxs_port_t *, uint32_t, void *))
2110 	    emlxs_fcftab_action_table[index];
2111 
2112 	if (!func) {
2113 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
2114 		    "fcftab: %s:%s arg=%p. No action. Terminated.",
2115 		    emlxs_fcftab_state_xlate(fcftab->state),
2116 		    emlxs_fcf_event_xlate(evt), arg1);
2117 
2118 		return (1);
2119 	}
2120 
2121 	rval = (func)(port, evt, arg1);
2122 
2123 	return (rval);
2124 
2125 } /* emlxs_fcftab_action() */
2126 
2127 
2128 static uint32_t
2129 emlxs_fcftab_event(emlxs_port_t *port, uint32_t evt,
2130     void *arg1)
2131 {
2132 	emlxs_hba_t *hba = HBA;
2133 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2134 	uint32_t rval;
2135 
2136 	/* Filter events */
2137 	switch (evt) {
2138 	case FCF_EVENT_SHUTDOWN:
2139 	case FCF_EVENT_LINKUP:
2140 	case FCF_EVENT_LINKDOWN:
2141 	case FCF_EVENT_CVL:
2142 	case FCF_EVENT_FCF_FOUND:
2143 	case FCF_EVENT_FCF_LOST:
2144 	case FCF_EVENT_FCF_CHANGED:
2145 	case FCF_EVENT_FCFTAB_FULL:
2146 	case FCF_EVENT_FCFI_OFFLINE:
2147 	case FCF_EVENT_FCFI_ONLINE:
2148 		break;
2149 
2150 	default:
2151 		return (1);
2152 	}
2153 
2154 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
2155 	    "fcftab: %s:%s arg=%p.",
2156 	    emlxs_fcftab_state_xlate(fcftab->state),
2157 	    emlxs_fcf_event_xlate(evt), arg1);
2158 
2159 	rval = emlxs_fcftab_action(port, evt, arg1);
2160 
2161 	return (rval);
2162 
2163 } /* emlxs_fcftab_event() */
2164 
2165 
2166 /* EMLXS_FCF_LOCK must be held to enter */
2167 /*ARGSUSED*/
2168 static uint32_t
2169 emlxs_fcftab_state(emlxs_port_t *port, uint16_t state, uint16_t reason,
2170     uint32_t explain, void *arg1)
2171 {
2172 	emlxs_hba_t *hba = HBA;
2173 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2174 	uint32_t rval = 0;
2175 
2176 	if (state >= FCFTAB_ACTION_STATES) {
2177 		return (1);
2178 	}
2179 
2180 	if ((fcftab->state == state) &&
2181 	    (reason != FCF_REASON_REENTER)) {
2182 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2183 		    "fcftab_state: %s:%s:0x%x arg=%p. "
2184 		    "State not changed. Terminated.",
2185 		    emlxs_fcftab_state_xlate(state),
2186 		    emlxs_fcf_reason_xlate(reason),
2187 		    explain, arg1);
2188 
2189 		return (1);
2190 	}
2191 
2192 	if (!reason) {
2193 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2194 		    "fcftab:%s-->%s arg=%p",
2195 		    emlxs_fcftab_state_xlate(fcftab->state),
2196 		    emlxs_fcftab_state_xlate(state), arg1);
2197 	} else if (reason == FCF_REASON_EVENT) {
2198 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2199 		    "fcftab:%s-->%s:%s:%s arg=%p",
2200 		    emlxs_fcftab_state_xlate(fcftab->state),
2201 		    emlxs_fcftab_state_xlate(state),
2202 		    emlxs_fcf_reason_xlate(reason),
2203 		    emlxs_fcf_event_xlate(explain), arg1);
2204 	} else if (explain) {
2205 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2206 		    "fcftab:%s-->%s:%s:0x%x arg=%p",
2207 		    emlxs_fcftab_state_xlate(fcftab->state),
2208 		    emlxs_fcftab_state_xlate(state),
2209 		    emlxs_fcf_reason_xlate(reason),
2210 		    explain, arg1);
2211 	} else {
2212 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2213 		    "fcftab:%s-->%s:%s arg=%p",
2214 		    emlxs_fcftab_state_xlate(fcftab->state),
2215 		    emlxs_fcftab_state_xlate(state),
2216 		    emlxs_fcf_reason_xlate(reason), arg1);
2217 	}
2218 
2219 	fcftab->prev_state = fcftab->state;
2220 	fcftab->prev_reason = fcftab->reason;
2221 	fcftab->state = state;
2222 	fcftab->reason = reason;
2223 
2224 	rval = emlxs_fcftab_action(port, FCF_EVENT_STATE_ENTER, arg1);
2225 
2226 	return (rval);
2227 
2228 } /* emlxs_fcftab_state() */
2229 
2230 
2231 /*ARGSUSED*/
2232 static uint32_t
2233 emlxs_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, uint32_t evt,
2234     void *arg1)
2235 {
2236 	emlxs_hba_t *hba = HBA;
2237 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2238 	uint32_t rval = 0;
2239 	FCFIobj_t *fcfp;
2240 
2241 	if (evt != FCF_EVENT_FCFI_OFFLINE) {
2242 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2243 		    "fcftab_fcfi_offline_evt_action: %s:%s arg=%p flag=%x. "
2244 		    "Invalid event type. Terminated.",
2245 		    emlxs_fcftab_state_xlate(fcftab->state),
2246 		    emlxs_fcf_event_xlate(evt), arg1,
2247 		    fcftab->flag);
2248 		return (1);
2249 	}
2250 
2251 	fcfp = (FCFIobj_t *)arg1;
2252 
2253 	switch (fcftab->state) {
2254 	case FCFTAB_STATE_SHUTDOWN:
2255 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2256 		    "fcftab_fcfi_offline_evt_action:%d. Shutting down.",
2257 		    fcfp->fcf_index);
2258 
2259 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SHUTDOWN,
2260 		    FCF_REASON_REENTER, evt, arg1);
2261 		break;
2262 
2263 	case FCFTAB_STATE_FCFI_OFFLINE:
2264 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2265 		    "fcftab_fcfi_offline_evt_action:%d. Offlining.",
2266 		    fcfp->fcf_index);
2267 
2268 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_OFFLINE,
2269 		    FCF_REASON_REENTER, evt, arg1);
2270 		break;
2271 
2272 	case FCFTAB_STATE_FCFI_ONLINE:
2273 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2274 		    "fcftab_fcfi_offline_evt_action:%d. Attempting failover.",
2275 		    fcfp->fcf_index);
2276 
2277 		fcfp->flag |= EMLXS_FCFI_FAILED;
2278 
2279 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE,
2280 		    FCF_REASON_REENTER, evt, arg1);
2281 		break;
2282 
2283 	case FCFTAB_STATE_ONLINE:
2284 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2285 		    "fcftab_fcfi_offline_evt_action:%d.",
2286 		    fcfp->fcf_index);
2287 
2288 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_ONLINE,
2289 		    FCF_REASON_REENTER, evt, arg1);
2290 		break;
2291 
2292 	default:
2293 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2294 		    "fcftab_fcfi_offline_evt_action:%d %s. Terminated.",
2295 		    fcfp->fcf_index,
2296 		    emlxs_fcftab_state_xlate(fcftab->state));
2297 		break;
2298 	}
2299 
2300 	return (rval);
2301 
2302 } /* emlxs_fcftab_fcfi_offline_evt_action() */
2303 
2304 
2305 /*ARGSUSED*/
2306 static uint32_t
2307 emlxs_fcftab_fcfi_online_evt_action(emlxs_port_t *port, uint32_t evt,
2308     void *arg1)
2309 {
2310 	emlxs_hba_t *hba = HBA;
2311 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2312 	uint32_t rval = 0;
2313 	FCFIobj_t *fcfp;
2314 
2315 	if (evt != FCF_EVENT_FCFI_ONLINE) {
2316 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2317 		    "fcftab_fcfi_online_evt_action: %s:%s arg=%p flag=%x. "
2318 		    "Invalid event type. Terminated.",
2319 		    emlxs_fcftab_state_xlate(fcftab->state),
2320 		    emlxs_fcf_event_xlate(evt), arg1,
2321 		    fcftab->flag);
2322 		return (1);
2323 	}
2324 
2325 	fcfp = (FCFIobj_t *)arg1;
2326 
2327 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2328 	    "fcftab_fcfi_online_evt_action:%d. Terminated.",
2329 	    fcfp->fcf_index);
2330 
2331 	return (rval);
2332 
2333 } /* emlxs_fcftab_fcfi_online_evt_action() */
2334 
2335 
2336 /*ARGSUSED*/
2337 static uint32_t
2338 emlxs_fcftab_cvl_evt_action(emlxs_port_t *port, uint32_t evt,
2339     void *arg1)
2340 {
2341 	emlxs_hba_t *hba = HBA;
2342 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2343 	uint32_t rval;
2344 	emlxs_port_t *vport;
2345 	uint32_t vpi;
2346 	VPIobj_t *vpip;
2347 
2348 	if (evt != FCF_EVENT_CVL) {
2349 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2350 		    "fcftab_cvl_evt_action: %s:%s arg=%p flag=%x. "
2351 		    "Invalid event type. Terminated.",
2352 		    emlxs_fcftab_state_xlate(fcftab->state),
2353 		    emlxs_fcf_event_xlate(evt), arg1,
2354 		    fcftab->flag);
2355 		return (1);
2356 	}
2357 
2358 	/* Pause VPI */
2359 	vpi = (uint32_t)((uintptr_t)arg1);
2360 	vport = &VPORT(vpi);
2361 	vpip = &vport->VPIobj;
2362 
2363 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2364 	    "fcftab_cvl_evt_action: %s gen=%x. Pausing VPI:%d.",
2365 	    emlxs_fcftab_state_xlate(fcftab->state),
2366 	    fcftab->generation,
2367 	    vpip->VPI);
2368 
2369 	rval = emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip);
2370 
2371 	switch (fcftab->state) {
2372 	case FCFTAB_STATE_SOLICIT:
2373 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2374 		    "fcftab_cvl_evt_action: %s gen=%x. "
2375 		    "Already soliciting. Terminated.",
2376 		    emlxs_fcftab_state_xlate(fcftab->state),
2377 		    fcftab->generation);
2378 		break;
2379 
2380 	default:
2381 		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
2382 		fcftab->flag |= EMLXS_FCFTAB_SOL_REQ;
2383 		fcftab->generation++;
2384 
2385 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2386 		    "fcftab_cvl_evt_action: %s gen=%x. Soliciting.",
2387 		    emlxs_fcftab_state_xlate(fcftab->state),
2388 		    fcftab->generation);
2389 
2390 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT,
2391 		    FCF_REASON_EVENT, evt, arg1);
2392 		break;
2393 	}
2394 
2395 	return (rval);
2396 
2397 } /* emlxs_fcftab_cvl_evt_action() */
2398 
2399 
2400 /*ARGSUSED*/
2401 static uint32_t
2402 emlxs_fcftab_linkup_evt_action(emlxs_port_t *port, uint32_t evt,
2403     void *arg1)
2404 {
2405 	emlxs_hba_t *hba = HBA;
2406 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2407 	uint32_t rval = 0;
2408 	emlxs_config_t *cfg = &CFG;
2409 
2410 	if (evt != FCF_EVENT_LINKUP) {
2411 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2412 		    "fcftab_linkup_evt_action: %s:%s arg=%p flag=%x. "
2413 		    "Invalid event type. Terminated.",
2414 		    emlxs_fcftab_state_xlate(fcftab->state),
2415 		    emlxs_fcf_event_xlate(evt), arg1,
2416 		    fcftab->flag);
2417 		return (1);
2418 	}
2419 
2420 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2421 	    "fcftab_linkup_evt_action: %s:%s arg=%p gen=%x. Link up.",
2422 	    emlxs_fcftab_state_xlate(fcftab->state),
2423 	    emlxs_fcf_event_xlate(evt), arg1,
2424 	    fcftab->generation);
2425 
2426 	mutex_enter(&EMLXS_PORT_LOCK);
2427 	if (hba->state < FC_LINK_UP) {
2428 		HBASTATS.LinkUp++;
2429 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP);
2430 	}
2431 	hba->discovery_timer =
2432 	    hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current +
2433 	    cfg[CFG_DISC_TIMEOUT].current;
2434 	mutex_exit(&EMLXS_PORT_LOCK);
2435 
2436 	emlxs_log_link_event(port);
2437 
2438 	switch (fcftab->state) {
2439 	case FCFTAB_STATE_SOLICIT:
2440 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2441 		    "fcftab_linkup_evt_action: %s gen=%x. "
2442 		    "Already soliciting. Terminated.",
2443 		    emlxs_fcftab_state_xlate(fcftab->state),
2444 		    fcftab->generation);
2445 		break;
2446 
2447 	default:
2448 		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
2449 		fcftab->flag |= EMLXS_FCFTAB_SOL_REQ;
2450 		fcftab->generation++;
2451 
2452 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2453 		    "fcftab_linkup_evt_action: %s gen=%x. Soliciting.",
2454 		    emlxs_fcftab_state_xlate(fcftab->state),
2455 		    fcftab->generation);
2456 
2457 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT,
2458 		    FCF_REASON_EVENT, evt, arg1);
2459 		break;
2460 	}
2461 
2462 	return (rval);
2463 
2464 } /* emlxs_fcftab_linkup_evt_action() */
2465 
2466 
2467 /*ARGSUSED*/
2468 static uint32_t
2469 emlxs_fcftab_linkdown_evt_action(emlxs_port_t *port, uint32_t evt,
2470     void *arg1)
2471 {
2472 	emlxs_hba_t *hba = HBA;
2473 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2474 	uint32_t rval = 0;
2475 	int32_t i;
2476 	FCFIobj_t *fcfp;
2477 
2478 	if (evt != FCF_EVENT_LINKDOWN) {
2479 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2480 		    "fcftab_linkdown_evt_action: %s:%s arg=%p flag=%x. "
2481 		    "Invalid event type. Terminated.",
2482 		    emlxs_fcftab_state_xlate(fcftab->state),
2483 		    emlxs_fcf_event_xlate(evt), arg1,
2484 		    fcftab->flag);
2485 		return (1);
2486 	}
2487 
2488 	fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
2489 	fcftab->flag |= EMLXS_FCFTAB_OFFLINE_REQ;
2490 
2491 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2492 	    "fcftab_linkdown_evt_action: %s:%s arg=%p flag=%x. Linkdown.",
2493 	    emlxs_fcftab_state_xlate(fcftab->state),
2494 	    emlxs_fcf_event_xlate(evt), arg1,
2495 	    fcftab->flag);
2496 
2497 	mutex_enter(&EMLXS_PORT_LOCK);
2498 	if (hba->state > FC_LINK_DOWN) {
2499 		HBASTATS.LinkDown++;
2500 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN);
2501 	}
2502 	hba->flag &= FC_LINKDOWN_MASK;
2503 	hba->discovery_timer = 0;
2504 	mutex_exit(&EMLXS_PORT_LOCK);
2505 
2506 	emlxs_log_link_event(port);
2507 
2508 	/* Pause all active FCFI's */
2509 	for (i = 0; i < fcftab->fcfi_count; i++) {
2510 		fcfp = fcftab->fcfi[i];
2511 
2512 		if ((fcfp->state == FCFI_STATE_OFFLINE) ||
2513 		    (fcfp->state == FCFI_STATE_PAUSED)) {
2514 			break;
2515 		}
2516 
2517 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2518 		    "fcftab_linkdown_evt_action: Pausing FCFI:%d.",
2519 		    fcfp->fcf_index);
2520 
2521 		(void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_PAUSE, fcfp);
2522 	}
2523 
2524 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2525 	    "fcftab_linkdown_evt_action: Going offline.");
2526 
2527 	switch (fcftab->state) {
2528 	case FCFTAB_STATE_OFFLINE:
2529 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_OFFLINE,
2530 		    FCF_REASON_REENTER, evt, arg1);
2531 		break;
2532 
2533 	default:
2534 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_OFFLINE,
2535 		    FCF_REASON_EVENT, evt, arg1);
2536 		break;
2537 	}
2538 
2539 	return (rval);
2540 
2541 } /* emlxs_fcftab_linkdown_evt_action() */
2542 
2543 
2544 /*ARGSUSED*/
2545 static uint32_t
2546 emlxs_fcftab_shutdown_evt_action(emlxs_port_t *port, uint32_t evt,
2547     void *arg1)
2548 {
2549 	emlxs_hba_t *hba = HBA;
2550 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2551 	uint32_t rval = 0;
2552 
2553 	if (evt != FCF_EVENT_SHUTDOWN) {
2554 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2555 		    "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. "
2556 		    "Invalid event type. Terminated.",
2557 		    emlxs_fcftab_state_xlate(fcftab->state),
2558 		    emlxs_fcf_event_xlate(evt), arg1,
2559 		    fcftab->flag);
2560 		return (1);
2561 	}
2562 
2563 	if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) {
2564 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2565 		    "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. "
2566 		    "Already shut down. Terminated.",
2567 		    emlxs_fcftab_state_xlate(fcftab->state),
2568 		    emlxs_fcf_event_xlate(evt), arg1,
2569 		    fcftab->flag);
2570 		return (1);
2571 	}
2572 
2573 	if (fcftab->state == FCFTAB_STATE_SHUTDOWN) {
2574 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2575 		    "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. "
2576 		    "Already shutting down. Terminated.",
2577 		    emlxs_fcftab_state_xlate(fcftab->state),
2578 		    emlxs_fcf_event_xlate(evt), arg1,
2579 		    fcftab->flag);
2580 		return (1);
2581 	}
2582 
2583 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2584 	    "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. "
2585 	    "Shutting down.",
2586 	    emlxs_fcftab_state_xlate(fcftab->state),
2587 	    emlxs_fcf_event_xlate(evt), arg1,
2588 	    fcftab->flag);
2589 
2590 	if (hba->state > FC_LINK_DOWN) {
2591 		mutex_enter(&EMLXS_PORT_LOCK);
2592 		if (hba->state > FC_LINK_DOWN) {
2593 			HBASTATS.LinkDown++;
2594 			EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN);
2595 		}
2596 		hba->flag &= FC_LINKDOWN_MASK;
2597 		hba->discovery_timer = 0;
2598 		mutex_exit(&EMLXS_PORT_LOCK);
2599 
2600 		emlxs_log_link_event(port);
2601 	}
2602 
2603 	rval = emlxs_fcftab_state(port, FCFTAB_STATE_SHUTDOWN,
2604 	    FCF_REASON_EVENT, evt, arg1);
2605 
2606 	return (rval);
2607 
2608 } /* emlxs_fcftab_shutdown_evt_action() */
2609 
2610 
2611 static uint32_t
2612 emlxs_fcftab_req_handler(emlxs_port_t *port, void *arg1)
2613 {
2614 	emlxs_hba_t *hba = HBA;
2615 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2616 	uint32_t rval = 0;
2617 
2618 	if (!(fcftab->flag & EMLXS_FCFTAB_REQ_MASK)) {
2619 		return (1);
2620 	}
2621 
2622 	if (fcftab->flag & EMLXS_FCFTAB_OFFLINE_REQ) {
2623 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_OFFLINE,
2624 		    FCF_REASON_REQUESTED, 0, arg1);
2625 	}
2626 
2627 	else if (fcftab->flag & EMLXS_FCFTAB_SOL_REQ) {
2628 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT,
2629 		    FCF_REASON_REQUESTED, 0, arg1);
2630 	}
2631 
2632 	else if (fcftab->flag & EMLXS_FCFTAB_READ_REQ) {
2633 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ,
2634 		    FCF_REASON_REQUESTED, 0, FCFTAB_READ_ALL);
2635 	}
2636 
2637 	return (rval);
2638 
2639 } /* emlxs_fcftab_req_handler() */
2640 
2641 
2642 static void
2643 emlxs_fcftab_read_timer(emlxs_hba_t *hba)
2644 {
2645 	emlxs_port_t *port = &PPORT;
2646 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2647 
2648 	/* Check FCF timer */
2649 	if (!fcftab->read_timer ||
2650 	    (hba->timer_tics <= fcftab->read_timer)) {
2651 		return;
2652 	}
2653 	fcftab->read_timer = 0;
2654 	fcftab->flag |= EMLXS_FCFTAB_READ_REQ;
2655 
2656 	switch (fcftab->state) {
2657 	case FCFTAB_STATE_SOLICIT_CMPL:
2658 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2659 		    "fcftab_timer: %s",
2660 		    emlxs_fcftab_state_xlate(fcftab->state));
2661 
2662 		(void) emlxs_fcftab_state(port, FCFTAB_STATE_READ, 0, 0,
2663 		    FCFTAB_READ_ALL);
2664 		break;
2665 
2666 	default:
2667 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2668 		    "fcftab_timer: %s Terminated.",
2669 		    emlxs_fcftab_state_xlate(fcftab->state));
2670 		break;
2671 	}
2672 
2673 	return;
2674 
2675 }  /* emlxs_fcftab_read_timer() */
2676 
2677 
2678 static void
2679 emlxs_fcftab_sol_timer(emlxs_hba_t *hba)
2680 {
2681 	emlxs_port_t *port = &PPORT;
2682 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2683 
2684 	/* Check FCF timer */
2685 	if (!fcftab->sol_timer ||
2686 	    (hba->timer_tics <= fcftab->sol_timer)) {
2687 		return;
2688 	}
2689 	fcftab->sol_timer = 0;
2690 
2691 	switch (fcftab->state) {
2692 	case FCFTAB_STATE_ONLINE:
2693 		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
2694 		fcftab->flag |= EMLXS_FCFTAB_SOL_REQ;
2695 		fcftab->generation++;
2696 
2697 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2698 		    "fcftab_sol_timer: %s gen=%x. Soliciting.",
2699 		    emlxs_fcftab_state_xlate(fcftab->state),
2700 		    fcftab->generation);
2701 
2702 		(void) emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT,
2703 		    FCF_REASON_EVENT, 0, 0);
2704 		break;
2705 
2706 	default:
2707 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2708 		    "fcftab_sol_timer: %s Terminated.",
2709 		    emlxs_fcftab_state_xlate(fcftab->state));
2710 		break;
2711 	}
2712 
2713 	return;
2714 
2715 }  /* emlxs_fcftab_sol_timer() */
2716 
2717 
2718 static void
2719 emlxs_fcftab_offline_timer(emlxs_hba_t *hba)
2720 {
2721 	emlxs_port_t *port = &PPORT;
2722 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2723 	uint32_t i;
2724 	FCFIobj_t *fcfp;
2725 
2726 	for (i = 0; i < fcftab->fcfi_count; i++) {
2727 		fcfp = fcftab->fcfi[i];
2728 
2729 		/* Check offline timer */
2730 		if (!fcfp->offline_timer ||
2731 		    (hba->timer_tics <= fcfp->offline_timer)) {
2732 			continue;
2733 		}
2734 		fcfp->offline_timer = 0;
2735 
2736 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2737 		    "fcftab_offline_timer:%d %s. Offlining.",
2738 		    fcfp->fcf_index,
2739 		    emlxs_fcfi_state_xlate(fcfp->state));
2740 
2741 		(void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp);
2742 	}
2743 
2744 	return;
2745 
2746 }  /* emlxs_fcftab_offline_timer() */
2747 
2748 
2749 /*ARGSUSED*/
2750 static uint32_t
2751 emlxs_fcftab_sol_failed_action(emlxs_port_t *port, uint32_t evt,
2752     void *arg1)
2753 {
2754 	emlxs_hba_t *hba = HBA;
2755 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2756 	uint32_t rval;
2757 
2758 	fcftab->attempts++;
2759 
2760 	if (fcftab->state != FCFTAB_STATE_SOLICIT_FAILED) {
2761 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2762 		    "fcftab_sol_failed_action: %s:%s arg=%p attempt=%d. "
2763 		    "Invalid state. Terminated.",
2764 		    emlxs_fcftab_state_xlate(fcftab->state),
2765 		    emlxs_fcf_event_xlate(evt),
2766 		    arg1, fcftab->attempts);
2767 		return (1);
2768 	}
2769 
2770 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2771 	    "fcftab_sol_failed_action: %s:%s arg=%p attempt=%d reason=%x",
2772 	    emlxs_fcftab_state_xlate(fcftab->state),
2773 	    emlxs_fcf_event_xlate(evt), arg1,
2774 	    fcftab->attempts,
2775 	    fcftab->reason);
2776 
2777 	if ((fcftab->reason == FCF_REASON_SEND_FAILED) ||
2778 	    (fcftab->attempts >= 3)) {
2779 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_CMPL,
2780 		    FCF_REASON_OP_FAILED, 0, arg1);
2781 	} else {
2782 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT,
2783 		    FCF_REASON_OP_FAILED, 0, arg1);
2784 	}
2785 
2786 	return (rval);
2787 
2788 } /* emlxs_fcftab_sol_failed_action() */
2789 
2790 
2791 /*ARGSUSED*/
2792 static uint32_t
2793 emlxs_fcftab_sol_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
2794 {
2795 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
2796 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2797 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
2798 	uint32_t generation;
2799 	mbox_rsp_hdr_t *hdr_rsp;
2800 	MATCHMAP *mp;
2801 	uint32_t status = MGMT_STATUS_FCF_IN_USE;
2802 	uint32_t xstatus = 0;
2803 	uint32_t fip_mode = 1;
2804 
2805 	mutex_enter(&EMLXS_FCF_LOCK);
2806 
2807 	if (mbq->nonembed) {
2808 		fip_mode = 0;
2809 
2810 		mp = (MATCHMAP *)mbq->nonembed;
2811 		mbq->nonembed = NULL;
2812 
2813 		hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
2814 		status  = hdr_rsp->status;
2815 		xstatus = hdr_rsp->extra_status;
2816 
2817 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
2818 	}
2819 
2820 	if (fcftab->state != FCFTAB_STATE_SOLICIT) {
2821 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2822 		    "fcftab_sol_mbcmpl: %s. Terminated.",
2823 		    emlxs_fcftab_state_xlate(fcftab->state));
2824 
2825 		mutex_exit(&EMLXS_FCF_LOCK);
2826 		return (0);
2827 	}
2828 
2829 	generation = (uint32_t)((uintptr_t)mbq->context);
2830 	if (generation != fcftab->generation) {
2831 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2832 		    "fcftab_sol_mbcmpl: %s gen=%x,%x. "
2833 		    "Incorrect generation. Terminated.",
2834 		    emlxs_fcftab_state_xlate(fcftab->state),
2835 		    generation, fcftab->generation);
2836 
2837 		mutex_exit(&EMLXS_FCF_LOCK);
2838 		return (0);
2839 	}
2840 
2841 	if (mb4->mbxStatus) {
2842 		if (fip_mode) {
2843 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2844 			    "fcftab_sol_mbcmpl:failed. status=%x",
2845 			    mb4->mbxStatus);
2846 
2847 			(void) emlxs_fcftab_state(port,
2848 			    FCFTAB_STATE_SOLICIT_FAILED,
2849 			    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
2850 
2851 			mutex_exit(&EMLXS_FCF_LOCK);
2852 			return (0);
2853 
2854 		} else if ((status == 0)||(status != MGMT_STATUS_FCF_IN_USE)) {
2855 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2856 			    "fcftab_sol_mbcmpl:failed. status=%x,%x,%x",
2857 			    mb4->mbxStatus, status,
2858 			    xstatus);
2859 
2860 			(void) emlxs_fcftab_state(port,
2861 			    FCFTAB_STATE_SOLICIT_FAILED,
2862 			    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
2863 
2864 			mutex_exit(&EMLXS_FCF_LOCK);
2865 			return (0);
2866 		}
2867 	}
2868 
2869 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2870 	    "fcftab_sol_mbcmpl: %s gen=%x",
2871 	    emlxs_fcftab_state_xlate(fcftab->state),
2872 	    fcftab->generation);
2873 
2874 	(void) emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_CMPL,
2875 	    0, 0, 0);
2876 
2877 	mutex_exit(&EMLXS_FCF_LOCK);
2878 	return (0);
2879 
2880 } /* emlxs_fcftab_sol_mbcmpl() */
2881 
2882 
2883 /*ARGSUSED*/
2884 static uint32_t
2885 emlxs_fcftab_sol_action(emlxs_port_t *port, uint32_t evt,
2886     void *arg1)
2887 {
2888 	emlxs_hba_t *hba = HBA;
2889 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2890 	MAILBOXQ *mbq;
2891 	MAILBOX4 *mb4;
2892 	MATCHMAP *mp = NULL;
2893 	uint32_t rval;
2894 
2895 	if (fcftab->state != FCFTAB_STATE_SOLICIT) {
2896 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2897 		    "fcftab_sol_action: %s:%s arg=%p. "
2898 		    "Invalid state. Terminated.",
2899 		    emlxs_fcftab_state_xlate(fcftab->state),
2900 		    emlxs_fcf_event_xlate(evt), arg1);
2901 		return (1);
2902 	}
2903 
2904 	if ((fcftab->prev_state != FCFTAB_STATE_SOLICIT_FAILED) ||
2905 	    (fcftab->flag & EMLXS_FCFTAB_SOL_REQ)) {
2906 		fcftab->flag &= ~EMLXS_FCFTAB_SOL_REQ;
2907 		fcftab->attempts = 0;
2908 	}
2909 
2910 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
2911 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2912 		    "fcftab_sol_action: %s:%s arg=%p gen=%d flag=%x. "
2913 		    "Handling request.",
2914 		    emlxs_fcftab_state_xlate(fcftab->state),
2915 		    emlxs_fcf_event_xlate(evt), arg1,
2916 		    fcftab->generation,
2917 		    fcftab->flag);
2918 
2919 		rval = emlxs_fcftab_req_handler(port, arg1);
2920 		return (rval);
2921 	}
2922 
2923 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2924 	    "fcftab_sol_action: %s:%s arg = %p gen=%x fip=%x. "
2925 	    "Requesting solicit.",
2926 	    emlxs_fcftab_state_xlate(fcftab->state),
2927 	    emlxs_fcf_event_xlate(evt), arg1,
2928 	    fcftab->generation,
2929 	    ((hba->flag & FC_FIP_SUPPORTED)? 1:0));
2930 
2931 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
2932 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_FAILED,
2933 		    FCF_REASON_NO_MBOX, 0, 0);
2934 		return (rval);
2935 	}
2936 
2937 	mb4 = (MAILBOX4*)mbq;
2938 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
2939 
2940 	if (hba->flag & FC_FIP_SUPPORTED) {
2941 		IOCTL_FCOE_REDISCOVER_FCF_TABLE *fcf;
2942 
2943 		mbq->nonembed = NULL;
2944 		mbq->mbox_cmpl = emlxs_fcftab_sol_mbcmpl;
2945 		mbq->context = (void *)((uintptr_t)fcftab->generation);
2946 		mbq->port = (void *)port;
2947 
2948 		mb4->un.varSLIConfig.be.embedded = 1;
2949 		mb4->mbxCommand = MBX_SLI_CONFIG;
2950 		mb4->mbxOwner = OWN_HOST;
2951 		mb4->un.varSLIConfig.be.payload_length =
2952 		    sizeof (IOCTL_FCOE_REDISCOVER_FCF_TABLE) +
2953 		    IOCTL_HEADER_SZ;
2954 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
2955 		    IOCTL_SUBSYSTEM_FCOE;
2956 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
2957 		    FCOE_OPCODE_REDISCOVER_FCF_TABLE;
2958 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
2959 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
2960 		    sizeof (IOCTL_FCOE_REDISCOVER_FCF_TABLE);
2961 
2962 		fcf = (IOCTL_FCOE_REDISCOVER_FCF_TABLE *)
2963 		    &mb4->un.varSLIConfig.payload;
2964 		fcf->params.request.fcf_count = 0; /* invalidate FCF table */
2965 
2966 	} else { /* Non-FIP */
2967 
2968 		/* Non-FIP uses a persistent FCF entry that */
2969 		/* we must add to the table */
2970 
2971 		IOCTL_FCOE_ADD_FCF_TABLE *fcf;
2972 		mbox_req_hdr_t *hdr_req;
2973 		FCF_RECORD_t *fcf_rec;
2974 		uint8_t bitmap[512];
2975 		uint16_t i;
2976 
2977 		if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
2978 			emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2979 
2980 			rval = emlxs_fcftab_state(port,
2981 			    FCFTAB_STATE_SOLICIT_FAILED,
2982 			    FCF_REASON_NO_BUFFER, 0, arg1);
2983 			return (rval);
2984 		}
2985 		bzero(mp->virt, mp->size);
2986 
2987 		mbq->nonembed = (void *)mp;
2988 		mbq->mbox_cmpl = emlxs_fcftab_sol_mbcmpl;
2989 		mbq->context = (void *)((uintptr_t)fcftab->generation);
2990 		mbq->port = (void *)port;
2991 
2992 		mb4->un.varSLIConfig.be.embedded = 0;
2993 		mb4->mbxCommand = MBX_SLI_CONFIG;
2994 		mb4->mbxOwner = OWN_HOST;
2995 
2996 		hdr_req = (mbox_req_hdr_t *)mp->virt;
2997 		hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
2998 		hdr_req->opcode = FCOE_OPCODE_ADD_FCF_TABLE;
2999 		hdr_req->timeout = 0;
3000 		hdr_req->req_length = sizeof (IOCTL_FCOE_ADD_FCF_TABLE);
3001 
3002 		fcf = (IOCTL_FCOE_ADD_FCF_TABLE *)(hdr_req + 1);
3003 		fcf->params.request.fcf_index = 0;
3004 
3005 		fcf_rec = &fcf->params.request.fcf_entry;
3006 		fcf_rec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ;
3007 		fcf_rec->fka_adv_period = 0;
3008 		fcf_rec->fip_priority = 128;
3009 
3010 #ifdef EMLXS_BIG_ENDIAN
3011 		fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC3;
3012 		fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC2;
3013 		fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC1;
3014 		fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC0;
3015 		fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC5;
3016 		fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC4;
3017 		fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[2];
3018 		fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
3019 		fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[0];
3020 #endif /* EMLXS_BIG_ENDIAN */
3021 #ifdef EMLXS_LITTLE_ENDIAN
3022 		fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC0;
3023 		fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC1;
3024 		fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC2;
3025 		fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC3;
3026 		fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC4;
3027 		fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC5;
3028 		fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[0];
3029 		fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
3030 		fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[2];
3031 #endif /* EMLXS_LITTLE_ENDIAN */
3032 
3033 		if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) {
3034 			bzero((void *) bitmap, 512);
3035 			i = hba->sli.sli4.cfgFCOE.VLanId;
3036 			bitmap[i / 8] = (1 << (i % 8));
3037 			BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512);
3038 		} else {
3039 			bzero((void *) bitmap, 512);
3040 			bitmap[0] = 1; /* represents bit 0 */
3041 			BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512);
3042 		}
3043 
3044 		fcf_rec->fcf_valid = 1;
3045 		fcf_rec->fcf_available = 1;
3046 	}
3047 
3048 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3049 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3050 		if (mp) {
3051 			emlxs_mem_put(hba, MEM_BUF, (void *)mp);
3052 		}
3053 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3054 
3055 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_FAILED,
3056 		    FCF_REASON_SEND_FAILED, rval, 0);
3057 
3058 		return (rval);
3059 	}
3060 
3061 	return (0);
3062 
3063 
3064 } /* emlxs_fcftab_sol_action() */
3065 
3066 
3067 /*ARGSUSED*/
3068 static uint32_t
3069 emlxs_fcftab_sol_cmpl_action(emlxs_port_t *port, uint32_t evt,
3070     void *arg1)
3071 {
3072 	emlxs_hba_t *hba = HBA;
3073 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3074 	uint32_t rval;
3075 	emlxs_config_t *cfg = &CFG;
3076 
3077 	if (fcftab->state != FCFTAB_STATE_SOLICIT_CMPL) {
3078 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3079 		    "fcftab_sol_cmpl_action: %s:%s arg=%p "
3080 		    "Invalid state. Terminated.",
3081 		    emlxs_fcftab_state_xlate(fcftab->state),
3082 		    emlxs_fcf_event_xlate(evt), arg1);
3083 		return (1);
3084 	}
3085 
3086 	/* Increment the generation counter */
3087 	fcftab->generation++;
3088 
3089 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3090 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3091 		    "fcftab_sol_cmpl_action: %s:%s arg=%p gen=%d flag=%x. "
3092 		    "Handling request.",
3093 		    emlxs_fcftab_state_xlate(fcftab->state),
3094 		    emlxs_fcf_event_xlate(evt), arg1,
3095 		    fcftab->generation,
3096 		    fcftab->flag);
3097 
3098 		rval = emlxs_fcftab_req_handler(port, arg1);
3099 		return (rval);
3100 	}
3101 
3102 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3103 	    "fcftab_sol_cmpl_action: %s:%s arg=%p gen=%d. "
3104 	    "Starting timer (%d secs).",
3105 	    emlxs_fcftab_state_xlate(fcftab->state),
3106 	    emlxs_fcf_event_xlate(evt), arg1,
3107 	    fcftab->generation,
3108 	    cfg[CFG_FCF_SOLICIT_DELAY].current);
3109 
3110 	/* Start the read timer */
3111 	fcftab->read_timer = hba->timer_tics +
3112 	    cfg[CFG_FCF_SOLICIT_DELAY].current;
3113 
3114 	return (0);
3115 
3116 } /* emlxs_fcftab_sol_cmpl_action() */
3117 
3118 
3119 /*ARGSUSED*/
3120 static uint32_t
3121 emlxs_fcftab_read_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
3122 {
3123 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
3124 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3125 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
3126 	mbox_rsp_hdr_t	*hdr_rsp;
3127 	IOCTL_FCOE_READ_FCF_TABLE *fcf;
3128 	FCF_RECORD_t *fcfrec;
3129 	FCFIobj_t *fcfp;
3130 	MATCHMAP *mp;
3131 	uint32_t index;
3132 	uint32_t event_tag;
3133 
3134 	mutex_enter(&EMLXS_FCF_LOCK);
3135 
3136 	if (fcftab->state != FCFTAB_STATE_READ) {
3137 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3138 		    "fcftab_read_mbcmpl: state=%s. Terminated.",
3139 		    emlxs_fcftab_state_xlate(fcftab->state));
3140 
3141 		mutex_exit(&EMLXS_FCF_LOCK);
3142 		return (0);
3143 	}
3144 
3145 	index =	(uint32_t)((uintptr_t)mbq->context);
3146 	mp = (MATCHMAP *)mbq->nonembed;
3147 	hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
3148 
3149 	if (mb4->mbxStatus || hdr_rsp->status) {
3150 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3151 		    "fcftab_read_mbcmpl:%d failed. status=%x,%x,%x",
3152 		    index, mb4->mbxStatus, hdr_rsp->status,
3153 		    hdr_rsp->extra_status);
3154 
3155 		(void) emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED,
3156 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
3157 
3158 		mutex_exit(&EMLXS_FCF_LOCK);
3159 		return (0);
3160 	}
3161 
3162 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3163 	    "fcftab_read_mbcmpl: state=%s",
3164 	    emlxs_fcftab_state_xlate(fcftab->state));
3165 
3166 	fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_rsp + 1);
3167 	fcfrec = &fcf->params.response.fcf_entry[0];
3168 
3169 #ifdef EMLXS_BIG_ENDIAN
3170 {
3171 	uint32_t *iptr;
3172 	uint32_t i;
3173 	uint8_t  j;
3174 	uint16_t s;
3175 	uint16_t *sptr;
3176 
3177 	/* Fix up data in FCF record */
3178 	SWAP32_BUFFER(&fcfrec->fabric_name_identifier[0], 8);
3179 	SWAP32_BUFFER(&fcfrec->switch_name_identifier[0], 8);
3180 	SWAP32_BUFFER(&fcfrec->vlan_bitmap[0], 512);
3181 
3182 	iptr = (uint32_t *)&fcfrec->fcf_mac_address_hi[0];
3183 	i = *iptr;
3184 	*iptr = SWAP32(i);
3185 
3186 	sptr = (uint16_t *)&fcfrec->fcf_mac_address_low[0];
3187 	s = *sptr;
3188 	*sptr = SWAP16(s);
3189 
3190 	j = fcfrec->fc_map[0];
3191 	fcfrec->fc_map[0] = fcfrec->fc_map[2];
3192 	fcfrec->fc_map[2] = j;
3193 }
3194 #endif /* EMLXS_BIG_ENDIAN */
3195 
3196 	event_tag = fcf->params.response.event_tag;
3197 
3198 	/* Try to find existing fcfrec */
3199 	fcfp = emlxs_fcfi_find(port, fcfrec, 0);
3200 
3201 	/* If not found, allocate a new one */
3202 	if (!fcfp) {
3203 		fcfp = emlxs_fcfi_alloc(port);
3204 	}
3205 
3206 	if (!fcfp) {
3207 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3208 		    "fcftab_read_mbcmpl:%d failed. Unable to allocate fcfi.",
3209 		    index);
3210 
3211 		(void) emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED,
3212 		    FCF_REASON_NO_FCFI, 0, 0);
3213 
3214 		mutex_exit(&EMLXS_FCF_LOCK);
3215 		return (0);
3216 	}
3217 
3218 	/* Update the FCFI */
3219 	emlxs_fcfi_update(port, fcfp, fcfrec, event_tag);
3220 
3221 	/* Check if another record needs to be acquired */
3222 	if (fcf->params.response.next_valid_fcf_index != 0xffff) {
3223 		fcftab->index = fcf->params.response.next_valid_fcf_index;
3224 
3225 		(void) emlxs_fcftab_state(port, FCFTAB_STATE_READ,
3226 		    FCF_REASON_REENTER, 0,
3227 		    (void *)((uintptr_t)fcf->params.response.
3228 		    next_valid_fcf_index));
3229 	} else {
3230 		(void) emlxs_fcftab_state(port, FCFTAB_STATE_READ_CMPL,
3231 		    0, 0, 0);
3232 	}
3233 
3234 	mutex_exit(&EMLXS_FCF_LOCK);
3235 	return (0);
3236 
3237 } /* emlxs_fcftab_read_mbcmpl() */
3238 
3239 
3240 /*ARGSUSED*/
3241 static uint32_t
3242 emlxs_fcftab_read_action(emlxs_port_t *port, uint32_t evt,
3243     void *arg1)
3244 {
3245 	emlxs_hba_t *hba = HBA;
3246 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3247 	MAILBOXQ *mbq;
3248 	MAILBOX4 *mb4;
3249 	IOCTL_FCOE_READ_FCF_TABLE *fcf;
3250 	uint32_t rval;
3251 	MATCHMAP *mp;
3252 	mbox_req_hdr_t	*hdr_req;
3253 	uint16_t index;
3254 
3255 	if (fcftab->state != FCFTAB_STATE_READ) {
3256 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3257 		    "fcftab_read_action: %s:%s arg=%p. "
3258 		    "Invalid state. Terminated.",
3259 		    emlxs_fcftab_state_xlate(fcftab->state),
3260 		    emlxs_fcf_event_xlate(evt), arg1);
3261 		return (1);
3262 	}
3263 
3264 	fcftab->flag &= ~EMLXS_FCFTAB_READ_REQ;
3265 
3266 	if (fcftab->prev_state != FCFTAB_STATE_READ_FAILED) {
3267 		fcftab->attempts = 0;
3268 	}
3269 
3270 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3271 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3272 		    "fcftab_read_action: %s:%s arg=%p flag=%x. "
3273 		    "Handling request.",
3274 		    emlxs_fcftab_state_xlate(fcftab->state),
3275 		    emlxs_fcf_event_xlate(evt), arg1,
3276 		    fcftab->flag);
3277 
3278 		rval = emlxs_fcftab_req_handler(port, arg1);
3279 		return (rval);
3280 	}
3281 
3282 	index = (uint16_t)((uintptr_t)arg1);
3283 
3284 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3285 	    "fcftab_read_action: %s:%s arg=%p attempts=%d. Reading FCF.",
3286 	    emlxs_fcftab_state_xlate(fcftab->state),
3287 	    emlxs_fcf_event_xlate(evt), arg1,
3288 	    fcftab->attempts);
3289 
3290 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
3291 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED,
3292 		    FCF_REASON_NO_MBOX, 0, arg1);
3293 		return (rval);
3294 	}
3295 	mb4 = (MAILBOX4*)mbq;
3296 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
3297 
3298 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
3299 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3300 
3301 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED,
3302 		    FCF_REASON_NO_BUFFER, 0, arg1);
3303 		return (rval);
3304 	}
3305 	bzero(mp->virt, mp->size);
3306 
3307 	mbq->nonembed = (void *)mp;
3308 	mbq->mbox_cmpl = emlxs_fcftab_read_mbcmpl;
3309 	mbq->context = (void *)((uintptr_t)index);
3310 	mbq->port = (void *)port;
3311 
3312 	mb4->un.varSLIConfig.be.embedded = 0;
3313 	mb4->mbxCommand = MBX_SLI_CONFIG;
3314 	mb4->mbxOwner = OWN_HOST;
3315 
3316 	hdr_req = (mbox_req_hdr_t *)mp->virt;
3317 	hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
3318 	hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE;
3319 	hdr_req->timeout = 0;
3320 	hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE);
3321 
3322 	fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1);
3323 	fcf->params.request.fcf_index = index;
3324 
3325 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3326 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3327 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
3328 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3329 
3330 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED,
3331 		    FCF_REASON_SEND_FAILED, rval, arg1);
3332 
3333 		return (rval);
3334 	}
3335 
3336 	return (0);
3337 
3338 } /* emlxs_fcftab_read_action() */
3339 
3340 
3341 /*ARGSUSED*/
3342 static uint32_t
3343 emlxs_fcftab_read_failed_action(emlxs_port_t *port, uint32_t evt,
3344     void *arg1)
3345 {
3346 	emlxs_hba_t *hba = HBA;
3347 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3348 	uint32_t rval;
3349 
3350 	fcftab->attempts++;
3351 
3352 	if (fcftab->state != FCFTAB_STATE_READ_FAILED) {
3353 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3354 		    "fcftab_read_failed_action: %s:%s arg=%p attempt=%d. "
3355 		    "Invalid state. Terminated.",
3356 		    emlxs_fcftab_state_xlate(fcftab->state),
3357 		    emlxs_fcf_event_xlate(evt),
3358 		    arg1, fcftab->attempts);
3359 
3360 		return (1);
3361 	}
3362 
3363 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3364 	    "fcftab_read_failed_action: %s:%s arg=%p attempt=%d reason=%x",
3365 	    emlxs_fcftab_state_xlate(fcftab->state),
3366 	    emlxs_fcf_event_xlate(evt), arg1,
3367 	    fcftab->attempts,
3368 	    fcftab->reason);
3369 
3370 	if ((fcftab->reason == FCF_REASON_SEND_FAILED) ||
3371 	    (fcftab->attempts >= 3)) {
3372 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_CMPL,
3373 		    FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3374 	} else {
3375 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ,
3376 		    FCF_REASON_OP_FAILED, fcftab->attempts, FCFTAB_READ_ALL);
3377 	}
3378 
3379 	return (rval);
3380 
3381 } /* emlxs_fcftab_read_failed_action() */
3382 
3383 
3384 /*ARGSUSED*/
3385 static uint32_t
3386 emlxs_fcftab_read_cmpl_action(emlxs_port_t *port, uint32_t evt,
3387     void *arg1)
3388 {
3389 	emlxs_hba_t *hba = HBA;
3390 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3391 	uint32_t rval;
3392 	FCFIobj_t *fcfp;
3393 	uint32_t i;
3394 
3395 	if (fcftab->state != FCFTAB_STATE_READ_CMPL) {
3396 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3397 		    "fcftab_read_cmpl_action: %s:%s arg=%p. "
3398 		    "Invalid state. Terminated.",
3399 		    emlxs_fcftab_state_xlate(fcftab->state),
3400 		    emlxs_fcf_event_xlate(evt), arg1);
3401 		return (1);
3402 	}
3403 
3404 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3405 	    "fcftab_read_cmpl_action: %s:%s arg=%p attempts=%d. "
3406 	    "Cleaning table.",
3407 	    emlxs_fcftab_state_xlate(fcftab->state),
3408 	    emlxs_fcf_event_xlate(evt), arg1,
3409 	    fcftab->attempts);
3410 
3411 	/* Clean FCFI table */
3412 	fcfp = fcftab->table;
3413 	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
3414 		if (fcfp->state == FCFI_STATE_FREE) {
3415 			continue;
3416 		}
3417 
3418 		/* Adjust the freshness flag */
3419 		if (fcfp->generation == fcftab->generation) {
3420 			fcfp->flag |= EMLXS_FCFI_FRESH;
3421 		} else {
3422 			fcfp->flag &= ~EMLXS_FCFI_FRESH;
3423 		}
3424 
3425 		/* Clear the failed bit */
3426 		fcfp->flag &= ~EMLXS_FCFI_FAILED;
3427 
3428 		/* Free all stale unselected entries now */
3429 		if (!(fcfp->flag & EMLXS_FCFI_FRESH) &&
3430 		    !(fcfp->flag & EMLXS_FCFI_SELECTED)) {
3431 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3432 			    "fcftab_read_cmpl_action:%d %s. "
3433 			    "FCF stale. Freeing FCF.",
3434 			    fcfp->fcf_index,
3435 			    emlxs_fcfi_state_xlate(fcfp->state));
3436 
3437 			(void) emlxs_fcfi_free(port, fcfp);
3438 			continue;
3439 		}
3440 	}
3441 
3442 	rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE,
3443 	    FCF_REASON_EVENT, evt, arg1);
3444 
3445 	return (rval);
3446 
3447 } /* emlxs_fcftab_read_cmpl_action() */
3448 
3449 
3450 static FCFIobj_t *
3451 emlxs_fcftab_fcfi_select(emlxs_port_t *port, char *fabric_wwn)
3452 {
3453 	emlxs_hba_t *hba = HBA;
3454 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3455 	FCFIobj_t *fcfp;
3456 	FCFIobj_t *fcfp1;
3457 	uint32_t mask;
3458 	uint32_t viable;
3459 	uint32_t i;
3460 	uint32_t j;
3461 	uint32_t rnum;
3462 	timespec_t time;
3463 	FCFIobj_t **fcf_table;
3464 	uint32_t fcf_table_count;
3465 
3466 	mask =   (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
3467 	    EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH|
3468 	    EMLXS_FCFI_FAILED|EMLXS_FCFI_SELECTED);
3469 	viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
3470 	    EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH);
3471 
3472 	/* Tag & count viable entries */
3473 	fcf_table_count = 0;
3474 	fcfp = 0;
3475 	fcfp1 = fcftab->table;
3476 	for (i = 0; i < fcftab->table_count; i++, fcfp1++) {
3477 		if (fcfp1->state == FCFI_STATE_FREE) {
3478 			fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
3479 			continue;
3480 		}
3481 
3482 		if ((fcfp1->flag & mask) != viable) {
3483 			fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
3484 			continue;
3485 		}
3486 
3487 		if (fabric_wwn &&
3488 		    bcmp(fabric_wwn,
3489 		    fcfp1->fcf_rec.fabric_name_identifier, 8)) {
3490 			fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
3491 			continue;
3492 		}
3493 
3494 		fcfp1->flag |= EMLXS_FCFI_TAGGED;
3495 		fcfp = fcfp1;
3496 		fcf_table_count++;
3497 	}
3498 
3499 	if (fcf_table_count == 0) {
3500 		return (NULL);
3501 	}
3502 
3503 	if (fcf_table_count == 1) {
3504 		return (fcfp);
3505 	}
3506 
3507 	/* We found more than one viable entry */
3508 
3509 	fcf_table = (FCFIobj_t **)kmem_zalloc(
3510 	    (sizeof (uintptr_t) * fcf_table_count), KM_SLEEP);
3511 
3512 	/* Find the highest priority tagged entry(s) */
3513 	for (i = 0; i < fcf_table_count; i++) {
3514 		fcfp  = 0;
3515 		fcfp1 = fcftab->table;
3516 		for (j = 0; j < fcftab->table_count; j++, fcfp1++) {
3517 			if (!(fcfp1->flag & EMLXS_FCFI_TAGGED)) {
3518 				continue;
3519 			}
3520 
3521 			if (!fcfp ||
3522 			    (fcfp1->priority > fcfp->priority)) {
3523 				fcfp = fcfp1;
3524 			}
3525 		}
3526 
3527 		if (fcf_table[0] &&
3528 		    (fcf_table[0]->priority > fcfp->priority)) {
3529 			break;
3530 		}
3531 
3532 		fcfp->flag &= ~EMLXS_FCFI_TAGGED;
3533 		fcf_table[i] = fcfp;
3534 	}
3535 
3536 	/* If more than one entry has the highest priority, */
3537 	/* then randomly select one of the highest. */
3538 	if (i > 1) {
3539 		/* Pick a random number from 0 to (i-1) */
3540 		/* This algorithm uses the lower 16 bits of the nanosecond */
3541 		/* clock to determine the value */
3542 		bzero(&time, sizeof (timespec_t));
3543 		gethrestime(&time);
3544 		rnum = (uint32_t)(time.tv_nsec & 0xFFFF);
3545 
3546 		fcfp = fcf_table[(rnum%i)];
3547 	} else {
3548 		fcfp = fcf_table[0];
3549 	}
3550 
3551 	/* Free the priority table */
3552 	kmem_free(fcf_table, (sizeof (uintptr_t) * fcf_table_count));
3553 
3554 	return (fcfp);
3555 
3556 } /* emlxs_fcftab_fcfi_select() */
3557 
3558 
3559 /*ARGSUSED*/
3560 static void
3561 emlxs_fcftab_process(emlxs_port_t *port)
3562 {
3563 	emlxs_hba_t *hba = HBA;
3564 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3565 	FCFIobj_t *fcfp;
3566 	FCFIobj_t *prev_fcfp;
3567 	uint32_t i;
3568 	uint32_t j;
3569 	uint32_t count;
3570 	uint32_t mask;
3571 	uint32_t viable;
3572 	emlxs_config_t *cfg = &CFG;
3573 
3574 	mask =   (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
3575 	    EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH|
3576 	    EMLXS_FCFI_FAILED);
3577 	viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
3578 	    EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH);
3579 
3580 	/* Deselection process */
3581 	for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
3582 		fcfp = fcftab->fcfi[i];
3583 
3584 		if (!fcfp) {
3585 			continue;
3586 		}
3587 
3588 		/* Check if entry is viable */
3589 		if ((fcfp->flag & mask) == viable) {
3590 			if (fcfp->offline_timer) {
3591 				fcfp->offline_timer = 0;
3592 
3593 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3594 				    "fcftab_process:%d fcfi=%d %s. "
3595 				    "FCF viable. Offline timer disabled.",
3596 				    i, fcfp->fcf_index,
3597 				    emlxs_fcfi_state_xlate(fcfp->state),
3598 				    cfg[CFG_FCF_FAILOVER_DELAY].current);
3599 			}
3600 			continue;
3601 		}
3602 
3603 		/* Previous entry is no longer viable */
3604 
3605 		/* If FCF is still online */
3606 		if (fcfp->state > FCFI_STATE_OFFLINE) {
3607 			if (fcfp->offline_timer == 0) {
3608 				/* Set the offline timer */
3609 				fcfp->offline_timer = hba->timer_tics +
3610 				    cfg[CFG_FCF_FAILOVER_DELAY].current;
3611 
3612 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3613 				    "fcftab_process:%d fcfi=%d %s. "
3614 				    "No longer viable. "
3615 				    "Offlining FCF (%d secs).",
3616 				    i, fcfp->fcf_index,
3617 				    emlxs_fcfi_state_xlate(fcfp->state),
3618 				    cfg[CFG_FCF_FAILOVER_DELAY].current);
3619 			}
3620 			continue;
3621 		}
3622 
3623 		/* Deselect it */
3624 		fcfp->flag &= ~EMLXS_FCFI_SELECTED;
3625 
3626 		if (!(fcfp->flag & EMLXS_FCFI_FRESH)) {
3627 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3628 			    "fcftab_process:%d fcfi=%d %s. "
3629 			    "No longer viable. Freeing FCF.",
3630 			    i, fcfp->fcf_index,
3631 			    emlxs_fcfi_state_xlate(fcfp->state));
3632 
3633 			(void) emlxs_fcfi_free(port, fcfp);
3634 		} else {
3635 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3636 			    "fcftab_process:%d fcfi=%d %s. "
3637 			    "No longer viable. FCF deselected.",
3638 			    i, fcfp->fcf_index,
3639 			    emlxs_fcfi_state_xlate(fcfp->state));
3640 		}
3641 	}
3642 
3643 	/* Reselection process */
3644 	for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
3645 		prev_fcfp = fcftab->fcfi[i];
3646 		fcftab->fcfi[i] = NULL;
3647 
3648 		/* If no previous selection, then make new one */
3649 		if (!prev_fcfp) {
3650 			/* Select an fcf on any fabric */
3651 			fcfp = emlxs_fcftab_fcfi_select(port, 0);
3652 
3653 			if (fcfp) {
3654 				fcfp->flag |= EMLXS_FCFI_SELECTED;
3655 				fcftab->fcfi[i] = fcfp;
3656 
3657 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3658 				    "fcftab_process:%d fcfi=%d %s. "
3659 				    "New FCF selected.",
3660 				    i, fcfp->fcf_index,
3661 				    emlxs_fcfi_state_xlate(fcfp->state));
3662 			} else {
3663 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3664 				    "fcftab_process:%d. No FCF available.",
3665 				    i);
3666 			}
3667 			continue;
3668 		}
3669 
3670 		/* If previous entry is still selected, keep it */
3671 		if (prev_fcfp->flag & EMLXS_FCFI_SELECTED) {
3672 			fcfp = prev_fcfp;
3673 			fcftab->fcfi[i] = fcfp;
3674 
3675 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3676 			    "fcftab_process:%d fcfi=%d %s. "
3677 			    "FCF still selected.",
3678 			    i, fcfp->fcf_index,
3679 			    emlxs_fcfi_state_xlate(fcfp->state));
3680 			continue;
3681 		}
3682 
3683 		/* Previous entry is no longer selected */
3684 
3685 		/* Select a new fcf from same fabric */
3686 		fcfp = emlxs_fcftab_fcfi_select(port,
3687 		    (char *)prev_fcfp->fcf_rec.fabric_name_identifier);
3688 
3689 		if (fcfp) {
3690 			fcfp->flag |= EMLXS_FCFI_SELECTED;
3691 			fcftab->fcfi[i] = fcfp;
3692 
3693 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3694 			    "fcftab_process:%d fcfi=%d %s. "
3695 			    "New FCF, same fabric selected.",
3696 			    i, fcfp->fcf_index,
3697 			    emlxs_fcfi_state_xlate(fcfp->state));
3698 			continue;
3699 		}
3700 
3701 		/* Select fcf from any fabric */
3702 		fcfp = emlxs_fcftab_fcfi_select(port, 0);
3703 
3704 		if (fcfp) {
3705 			fcfp->flag |= EMLXS_FCFI_SELECTED;
3706 			fcftab->fcfi[i] = fcfp;
3707 
3708 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3709 			    "fcftab_process:%d fcfi=%d %s. "
3710 			    "New FCF, new fabric selected.",
3711 			    i, fcfp->fcf_index,
3712 			    emlxs_fcfi_state_xlate(fcfp->state));
3713 			continue;
3714 		}
3715 
3716 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3717 		    "fcftab_process:%d. No FCF available.",
3718 		    i);
3719 	}
3720 
3721 	/* Pack entries */
3722 	count = 0;
3723 	for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
3724 		if (fcftab->fcfi[i]) {
3725 			count++;
3726 			continue;
3727 		}
3728 
3729 		for (j = i+1; j < FCFTAB_MAX_FCFI_COUNT; j++) {
3730 			if (fcftab->fcfi[j] == NULL) {
3731 				continue;
3732 			}
3733 
3734 			fcftab->fcfi[i] = fcftab->fcfi[j];
3735 			fcftab->fcfi[j] = NULL;
3736 			count++;
3737 			break;
3738 		}
3739 
3740 		if (j == FCFTAB_MAX_FCFI_COUNT) {
3741 			break;
3742 		}
3743 	}
3744 	fcftab->fcfi_count = count;
3745 
3746 	return;
3747 
3748 } /* emlxs_fcftab_process() */
3749 
3750 
3751 
3752 /*ARGSUSED*/
3753 static uint32_t
3754 emlxs_fcftab_fcfi_online_action(emlxs_port_t *port, uint32_t evt,
3755     void *arg1)
3756 {
3757 	emlxs_hba_t *hba = HBA;
3758 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3759 	FCFIobj_t *fcfp;
3760 	uint32_t rval = 0;
3761 	uint32_t i;
3762 	uint32_t offline_count = 0;
3763 	uint32_t online_count = 0;
3764 
3765 	if (fcftab->state != FCFTAB_STATE_FCFI_ONLINE) {
3766 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3767 		    "fcftab_fcfi_online_action: %s:%s arg=%p. "
3768 		    "Invalid state. Terminated.",
3769 		    emlxs_fcftab_state_xlate(fcftab->state),
3770 		    emlxs_fcf_event_xlate(evt), arg1);
3771 		return (1);
3772 	}
3773 
3774 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3775 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3776 		    "fcftab_fcfi_online_action: %s:%s arg=%p flag=%x. "
3777 		    "Handling request.",
3778 		    emlxs_fcftab_state_xlate(fcftab->state),
3779 		    emlxs_fcf_event_xlate(evt), arg1,
3780 		    fcftab->flag);
3781 
3782 		rval = emlxs_fcftab_req_handler(port, arg1);
3783 		return (rval);
3784 	}
3785 
3786 	emlxs_fcftab_process(port);
3787 
3788 	for (i = 0; i < fcftab->fcfi_count; i++) {
3789 		fcfp = fcftab->fcfi[i];
3790 
3791 		if (fcfp->offline_timer == 0) {
3792 			online_count++;
3793 
3794 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3795 			    "fcftab_fcfi_online_action: fcfi_count=%d. "
3796 			    "Onlining FCF:%d.",
3797 			    fcftab->fcfi_count,
3798 			    fcfp->fcf_index);
3799 
3800 			(void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_ONLINE,
3801 			    fcfp);
3802 		} else {
3803 			offline_count++;
3804 
3805 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3806 			    "fcftab_fcfi_online_action: fcfi_count=%d. "
3807 			    "Offlining FCF:%d.",
3808 			    fcftab->fcfi_count,
3809 			    fcfp->fcf_index);
3810 		}
3811 	}
3812 
3813 	if (offline_count) {
3814 		/* Wait for FCF's to go offline */
3815 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_OFFLINE,
3816 		    FCF_REASON_EVENT, evt, arg1);
3817 
3818 		/* Service timer now */
3819 		emlxs_fcftab_offline_timer(hba);
3820 
3821 		return (rval);
3822 	}
3823 
3824 	if (!online_count) {
3825 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3826 		    "fcftab_fcfi_online_action: fcfi_count=%d.",
3827 		    fcftab->fcfi_count);
3828 	}
3829 
3830 	rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE_CMPL,
3831 	    FCF_REASON_EVENT, evt, arg1);
3832 
3833 	return (rval);
3834 
3835 } /* emlxs_fcftab_fcfi_online_action() */
3836 
3837 
3838 /*ARGSUSED*/
3839 static uint32_t
3840 emlxs_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, uint32_t evt,
3841     void *arg1)
3842 {
3843 	emlxs_hba_t *hba = HBA;
3844 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3845 	uint32_t rval;
3846 
3847 	if (fcftab->state != FCFTAB_STATE_FCFI_ONLINE_CMPL) {
3848 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3849 		    "fcftab_fcfi_online_cmpl_action: %s:%s arg=%p. "
3850 		    "Invalid state. Terminated.",
3851 		    emlxs_fcftab_state_xlate(fcftab->state),
3852 		    emlxs_fcf_event_xlate(evt), arg1);
3853 		return (1);
3854 	}
3855 
3856 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3857 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3858 		    "fcftab_fcfi_online_cmpl_action: %s:%s arg=%p flag=%x. "
3859 		    "Handling request.",
3860 		    emlxs_fcftab_state_xlate(fcftab->state),
3861 		    emlxs_fcf_event_xlate(evt), arg1,
3862 		    fcftab->flag);
3863 
3864 		rval = emlxs_fcftab_req_handler(port, arg1);
3865 		return (rval);
3866 	}
3867 
3868 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3869 	    "fcftab_fcfi_online_cmpl_action: %s:%s arg=%p",
3870 	    emlxs_fcftab_state_xlate(fcftab->state),
3871 	    emlxs_fcf_event_xlate(evt), arg1);
3872 
3873 	rval = emlxs_fcftab_state(port, FCFTAB_STATE_ONLINE,
3874 	    FCF_REASON_EVENT, evt, arg1);
3875 
3876 	return (rval);
3877 
3878 } /* emlxs_fcftab_fcfi_online_cmpl_action() */
3879 
3880 
3881 /*ARGSUSED*/
3882 static uint32_t
3883 emlxs_fcftab_fcfi_offline_action(emlxs_port_t *port, uint32_t evt,
3884     void *arg1)
3885 {
3886 	emlxs_hba_t *hba = HBA;
3887 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3888 	FCFIobj_t *fcfp;
3889 	uint32_t rval;
3890 	int32_t i;
3891 	uint32_t fcfi_offline;
3892 
3893 	if (fcftab->state != FCFTAB_STATE_FCFI_OFFLINE) {
3894 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3895 		    "fcftab_fcfi_offline_action: %s:%s arg=%p. "
3896 		    "Invalid state. Terminated.",
3897 		    emlxs_fcftab_state_xlate(fcftab->state),
3898 		    emlxs_fcf_event_xlate(evt), arg1);
3899 		return (1);
3900 	}
3901 
3902 	/* Check for FCF's going offline */
3903 	fcfi_offline = 0;
3904 	for (i = 0; i < fcftab->fcfi_count; i++) {
3905 		fcfp = fcftab->fcfi[i];
3906 
3907 		if (fcfp->state <= FCFI_STATE_OFFLINE) {
3908 			continue;
3909 		}
3910 
3911 		if (fcfp->offline_timer ||
3912 		    (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
3913 			fcfi_offline++;
3914 		}
3915 	}
3916 
3917 	if (fcfi_offline) {
3918 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3919 		    "fcftab_fcfi_offline_action: %s:%s arg=%p "
3920 		    "fcfi_offline=%d. Terminated.",
3921 		    emlxs_fcftab_state_xlate(fcftab->state),
3922 		    emlxs_fcf_event_xlate(evt), arg1,
3923 		    fcfi_offline);
3924 
3925 		return (0);
3926 	}
3927 
3928 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3929 	    "fcftab_fcfi_offline_action: %s:%s arg=%p.",
3930 	    emlxs_fcftab_state_xlate(fcftab->state),
3931 	    emlxs_fcf_event_xlate(evt), arg1);
3932 
3933 	rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_OFFLINE_CMPL,
3934 	    FCF_REASON_EVENT, evt, arg1);
3935 	return (rval);
3936 
3937 } /* emlxs_fcftab_fcfi_offline_action() */
3938 
3939 
3940 /*ARGSUSED*/
3941 static uint32_t
3942 emlxs_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, uint32_t evt,
3943     void *arg1)
3944 {
3945 	emlxs_hba_t *hba = HBA;
3946 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3947 	uint32_t rval;
3948 
3949 	if (fcftab->state != FCFTAB_STATE_FCFI_OFFLINE_CMPL) {
3950 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3951 		    "fcftab_fcfi_offline_cmpl_action: %s:%s arg=%p. "
3952 		    "Invalid state. Terminated.",
3953 		    emlxs_fcftab_state_xlate(fcftab->state),
3954 		    emlxs_fcf_event_xlate(evt), arg1);
3955 		return (1);
3956 	}
3957 
3958 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3959 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3960 		    "fcftab_fcfi_offline_cmpl_action: %s:%s arg=%p. "
3961 		    "Handling request.",
3962 		    emlxs_fcftab_state_xlate(fcftab->state),
3963 		    emlxs_fcf_event_xlate(evt), arg1);
3964 
3965 		rval = emlxs_fcftab_req_handler(port, arg1);
3966 		return (rval);
3967 	}
3968 
3969 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3970 	    "fcftab_fcfi_offline_cmpl_action: %s:%s arg=%p.",
3971 	    emlxs_fcftab_state_xlate(fcftab->state),
3972 	    emlxs_fcf_event_xlate(evt), arg1);
3973 
3974 	rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE,
3975 	    FCF_REASON_EVENT, evt, arg1);
3976 
3977 	return (rval);
3978 
3979 } /* emlxs_fcftab_fcfi_offline_cmpl_action() */
3980 
3981 
3982 /*ARGSUSED*/
3983 static uint32_t
3984 emlxs_fcftab_found_evt_action(emlxs_port_t *port, uint32_t evt,
3985     void *arg1)
3986 {
3987 	emlxs_hba_t *hba = HBA;
3988 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3989 	uint32_t fcf_index = (uint32_t)((uintptr_t)arg1);
3990 	FCFIobj_t *fcfp;
3991 	uint32_t rval = 0;
3992 
3993 	if (evt != FCF_EVENT_FCF_FOUND) {
3994 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3995 		    "fcftab_found_evt_action: %s:%s fcf_index=%d. "
3996 		    "Invalid event type. Terminated.",
3997 		    emlxs_fcftab_state_xlate(fcftab->state),
3998 		    emlxs_fcf_event_xlate(evt),
3999 		    fcf_index);
4000 
4001 		return (1);
4002 	}
4003 
4004 	switch (fcftab->state) {
4005 	case FCFTAB_STATE_SOLICIT:
4006 	case FCFTAB_STATE_SOLICIT_CMPL:
4007 	case FCFTAB_STATE_READ:
4008 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4009 		    "fcftab_found_evt_action: %s:%s fcf_index=%d gen=%x. "
4010 		    "Terminated.",
4011 		    emlxs_fcftab_state_xlate(fcftab->state),
4012 		    emlxs_fcf_event_xlate(evt),
4013 		    fcf_index, fcftab->generation);
4014 		break;
4015 
4016 	/* case FCFTAB_STATE_FCFI_OFFLINE: */
4017 	default:
4018 
4019 		/* Scan for matching fcf index in table */
4020 		fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
4021 
4022 		if (fcfp && (fcfp->flag & EMLXS_FCFI_SELECTED)) {
4023 
4024 			/* Trigger table read */
4025 			fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4026 			fcftab->flag |= EMLXS_FCFTAB_READ_REQ;
4027 			fcftab->generation++;
4028 
4029 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4030 			    "fcftab_found_evt_action: %s:%s fcf_index=%d "
4031 			    "gen=%x. Read FCF table.",
4032 			    emlxs_fcftab_state_xlate(fcftab->state),
4033 			    emlxs_fcf_event_xlate(evt),
4034 			    fcf_index, fcftab->generation);
4035 
4036 			rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ,
4037 			    FCF_REASON_EVENT, evt, arg1);
4038 
4039 			break;
4040 		}
4041 
4042 		/* Check if we need more FCF's */
4043 		if (fcftab->fcfi_online < FCFTAB_MAX_FCFI_COUNT) {
4044 
4045 			/* Trigger table read */
4046 			fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4047 			fcftab->flag |= EMLXS_FCFTAB_READ_REQ;
4048 			fcftab->generation++;
4049 
4050 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4051 			    "fcftab_found_evt_action: %s:%s fcf_index=%d "
4052 			    "gen=%x fcfi_online=%d. Read FCF table.",
4053 			    emlxs_fcftab_state_xlate(fcftab->state),
4054 			    emlxs_fcf_event_xlate(evt),
4055 			    fcf_index, fcftab->generation,
4056 			    fcftab->fcfi_online);
4057 
4058 			rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ,
4059 			    FCF_REASON_EVENT, evt, arg1);
4060 
4061 			break;
4062 		}
4063 
4064 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4065 		    "fcftab_found_evt_action: %s:%s fcfi=%d. "
4066 		    "FCF not needed. Terminated.",
4067 		    emlxs_fcftab_state_xlate(fcftab->state),
4068 		    emlxs_fcf_event_xlate(evt),
4069 		    fcf_index);
4070 
4071 		break;
4072 	}
4073 
4074 	return (rval);
4075 
4076 } /* emlxs_fcftab_found_evt_action() */
4077 
4078 
4079 /*ARGSUSED*/
4080 static uint32_t
4081 emlxs_fcftab_lost_evt_action(emlxs_port_t *port, uint32_t evt,
4082     void *arg1)
4083 {
4084 	emlxs_hba_t *hba = HBA;
4085 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4086 	FCFIobj_t *fcfp;
4087 	uint32_t fcf_index = (uint32_t)((uintptr_t)arg1);
4088 	emlxs_port_t *vport;
4089 	VPIobj_t *vpip;
4090 	uint32_t i;
4091 	uint32_t rval;
4092 
4093 	if (evt != FCF_EVENT_FCF_LOST) {
4094 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4095 		    "fcftab_lost_evt_action: %s:%s fcf_index=%d. "
4096 		    "Invalid event type. Terminated",
4097 		    emlxs_fcftab_state_xlate(fcftab->state),
4098 		    emlxs_fcf_event_xlate(evt),
4099 		    fcf_index);
4100 
4101 		return (1);
4102 	}
4103 
4104 	/* Scan for matching fcf index in table */
4105 	fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
4106 
4107 	if (!fcfp) {
4108 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4109 		    "fcftab_lost_evt_action: %s:%s fcf_index=%d. "
4110 		    "FCF not found. Terminated.",
4111 		    emlxs_fcftab_state_xlate(fcftab->state),
4112 		    emlxs_fcf_event_xlate(evt),
4113 		    fcf_index);
4114 
4115 		return (0);
4116 	}
4117 
4118 	if (!(fcfp->flag & EMLXS_FCFI_SELECTED)) {
4119 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4120 		    "fcftab_changed_evt_action: %s:%s fcf_index=%d. "
4121 		    "FCF not selected. Terminated.",
4122 		    emlxs_fcftab_state_xlate(fcftab->state),
4123 		    emlxs_fcf_event_xlate(evt),
4124 		    fcf_index);
4125 
4126 		return (0);
4127 	}
4128 
4129 	/* Offline VPI's of this FCFI */
4130 	for (i = 0; i <= hba->vpi_max; i++) {
4131 		vport = &VPORT(i);
4132 		vpip = &vport->VPIobj;
4133 
4134 		if ((vpip->state == VPI_STATE_OFFLINE) ||
4135 		    (vpip->vfip->fcfp != fcfp)) {
4136 			continue;
4137 		}
4138 
4139 		/* Fabric logo is implied */
4140 		vpip->flag &= ~EMLXS_VPI_LOGI;
4141 		if (vpip->flag & EMLXS_VPI_VFI_LOGI) {
4142 			vpip->flag &= ~EMLXS_VPI_VFI_LOGI;
4143 
4144 			if (vpip->vfip->logi_count > 0) {
4145 				vpip->vfip->logi_count--;
4146 			}
4147 		}
4148 
4149 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4150 		    "fcftab_lost_evt_action: %s:%s fcf_index=%d gen=%x. "
4151 		    "Offlining VPI:%d.",
4152 		    emlxs_fcftab_state_xlate(fcftab->state),
4153 		    emlxs_fcf_event_xlate(evt),
4154 		    fcf_index, fcftab->generation,
4155 		    vpip->VPI);
4156 
4157 		(void) emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
4158 	}
4159 
4160 	switch (fcftab->state) {
4161 	case FCFTAB_STATE_SOLICIT:
4162 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4163 		    "fcftab_lost_evt_action: %s gen=%x. "
4164 		    "Already soliciting. Terminated.",
4165 		    emlxs_fcftab_state_xlate(fcftab->state),
4166 		    fcftab->generation);
4167 		break;
4168 
4169 	default:
4170 		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4171 		fcftab->flag |= EMLXS_FCFTAB_SOL_REQ;
4172 		fcftab->generation++;
4173 
4174 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4175 		    "fcftab_lost_evt_action: %s gen=%x. Soliciting.",
4176 		    emlxs_fcftab_state_xlate(fcftab->state),
4177 		    fcftab->generation);
4178 
4179 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT,
4180 		    FCF_REASON_EVENT, evt, arg1);
4181 		break;
4182 	}
4183 
4184 	return (rval);
4185 
4186 } /* emlxs_fcftab_lost_evt_action() */
4187 
4188 
4189 /*ARGSUSED*/
4190 static uint32_t
4191 emlxs_fcftab_changed_evt_action(emlxs_port_t *port, uint32_t evt,
4192     void *arg1)
4193 {
4194 	emlxs_hba_t *hba = HBA;
4195 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4196 	FCFIobj_t *fcfp;
4197 	uint32_t fcf_index = (uint32_t)((uintptr_t)arg1);
4198 	uint32_t rval;
4199 
4200 	if (evt != FCF_EVENT_FCF_CHANGED) {
4201 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4202 		    "fcftab_changed_evt_action: %s:%s fcf_index=%d. "
4203 		    "Invalid event type. Terminated",
4204 		    emlxs_fcftab_state_xlate(fcftab->state),
4205 		    emlxs_fcf_event_xlate(evt),
4206 		    fcf_index);
4207 
4208 		return (1);
4209 	}
4210 
4211 	/* Scan for matching fcf index in table */
4212 	fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
4213 
4214 	if (!fcfp) {
4215 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4216 		    "fcftab_changed_evt_action: %s:%s fcf_index=%d. "
4217 		    "FCFI not found. Terminated.",
4218 		    emlxs_fcftab_state_xlate(fcftab->state),
4219 		    emlxs_fcf_event_xlate(evt),
4220 		    fcf_index);
4221 
4222 		return (1);
4223 	}
4224 
4225 	if (!(fcfp->flag & EMLXS_FCFI_SELECTED)) {
4226 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4227 		    "fcftab_changed_evt_action: %s:%s fcf_index=%d. "
4228 		    "FCFI not selected. Terminated.",
4229 		    emlxs_fcftab_state_xlate(fcftab->state),
4230 		    emlxs_fcf_event_xlate(evt),
4231 		    fcf_index);
4232 
4233 		return (1);
4234 	}
4235 
4236 	switch (fcftab->state) {
4237 	case FCFTAB_STATE_SOLICIT:
4238 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4239 		    "fcftab_changed_evt_action: %s gen=%x. "
4240 		    "Already soliciting. Terminated.",
4241 		    emlxs_fcftab_state_xlate(fcftab->state),
4242 		    fcftab->generation);
4243 		break;
4244 
4245 	default:
4246 		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4247 		fcftab->flag |= EMLXS_FCFTAB_SOL_REQ;
4248 		fcftab->generation++;
4249 
4250 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4251 		    "fcftab_changed_evt_action: %s gen=%x. Soliciting.",
4252 		    emlxs_fcftab_state_xlate(fcftab->state),
4253 		    fcftab->generation);
4254 
4255 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT,
4256 		    FCF_REASON_EVENT, evt, arg1);
4257 		break;
4258 	}
4259 
4260 	return (rval);
4261 
4262 } /* emlxs_fcftab_changed_evt_action() */
4263 
4264 
4265 /*ARGSUSED*/
4266 static uint32_t
4267 emlxs_fcftab_fcf_delete(emlxs_port_t *port, uint32_t fcf_index)
4268 {
4269 	emlxs_hba_t *hba = HBA;
4270 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4271 	MAILBOXQ *mbq;
4272 	MAILBOX4 *mb4;
4273 	MATCHMAP *mp = NULL;
4274 	uint32_t rval;
4275 
4276 	IOCTL_FCOE_DELETE_FCF_TABLE *fcf;
4277 	mbox_req_hdr_t *hdr_req;
4278 
4279 	if (fcf_index >= fcftab->fcfi_count) {
4280 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4281 		    "fcftab_fcf_delete:%d failed.  Out of range.",
4282 		    fcf_index);
4283 
4284 		return (1);
4285 	}
4286 
4287 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
4288 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4289 		    "fcftab_fcf_delete:%d failed. Unable to allocate mailbox.",
4290 		    fcf_index);
4291 
4292 		return (1);
4293 	}
4294 
4295 	mb4 = (MAILBOX4*)mbq;
4296 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
4297 
4298 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
4299 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4300 		    "fcftab_fcf_delete:%d failed.  Unable to allocate buffer.",
4301 		    fcf_index);
4302 
4303 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
4304 		return (1);
4305 	}
4306 	bzero(mp->virt, mp->size);
4307 
4308 	mbq->nonembed = (void *)mp;
4309 	mbq->mbox_cmpl = NULL;
4310 	mbq->context = (void *)((uintptr_t)fcf_index);
4311 	mbq->port = (void *)port;
4312 
4313 	mb4->un.varSLIConfig.be.embedded = 0;
4314 	mb4->mbxCommand = MBX_SLI_CONFIG;
4315 	mb4->mbxOwner = OWN_HOST;
4316 
4317 	hdr_req = (mbox_req_hdr_t *)mp->virt;
4318 	hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
4319 	hdr_req->opcode = FCOE_OPCODE_DELETE_FCF_TABLE;
4320 	hdr_req->timeout = 0;
4321 	hdr_req->req_length = sizeof (IOCTL_FCOE_DELETE_FCF_TABLE);
4322 
4323 	fcf = (IOCTL_FCOE_DELETE_FCF_TABLE *)(hdr_req + 1);
4324 	fcf->params.request.fcf_count = 1;
4325 	fcf->params.request.fcf_indexes[0] = (uint16_t)fcf_index;
4326 
4327 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4328 	    "fcftab_fcf_delete:%d.",
4329 	    fcf_index);
4330 
4331 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
4332 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
4333 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4334 		    "fcftab_fcf_delete:%d failed.  Unable to send request.",
4335 		    fcf_index);
4336 
4337 		if (mp) {
4338 			emlxs_mem_put(hba, MEM_BUF, (void *)mp);
4339 		}
4340 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
4341 
4342 		return (1);
4343 	}
4344 
4345 	return (0);
4346 
4347 
4348 } /* emlxs_fcftab_fcf_delete() */
4349 
4350 
4351 /*ARGSUSED*/
4352 static uint32_t
4353 emlxs_fcftab_full_evt_action(emlxs_port_t *port, uint32_t evt,
4354     void *arg1)
4355 {
4356 	emlxs_hba_t *hba = HBA;
4357 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4358 	FCFIobj_t *fcfp;
4359 	uint32_t rval;
4360 	uint32_t mask;
4361 	uint32_t viable;
4362 	uint32_t i;
4363 	uint32_t count;
4364 
4365 	if (evt != FCF_EVENT_FCFTAB_FULL) {
4366 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4367 		    "fcftab_full_evt_action: %s:%s arg=%p. "
4368 		    "Invalid event type. Terminated",
4369 		    emlxs_fcftab_state_xlate(fcftab->state),
4370 		    emlxs_fcf_event_xlate(evt), arg1);
4371 
4372 		return (1);
4373 	}
4374 
4375 	if (fcftab->fcfi_online == FCFTAB_MAX_FCFI_COUNT) {
4376 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4377 		    "fcftab_full_evt_action: %s:%s arg=%p fcfi_online=%d. "
4378 		    "Terminated.",
4379 		    emlxs_fcftab_state_xlate(fcftab->state),
4380 		    emlxs_fcf_event_xlate(evt), arg1,
4381 		    fcftab->fcfi_online);
4382 
4383 		return (0);
4384 	}
4385 
4386 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4387 	    "fcftab_full_evt_action: %s:%s arg=%p fcfi_online=%d. "
4388 	    "Cleaning table...",
4389 	    emlxs_fcftab_state_xlate(fcftab->state),
4390 	    emlxs_fcf_event_xlate(evt), arg1,
4391 	    fcftab->fcfi_online);
4392 
4393 	mask =   (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
4394 	    EMLXS_FCFI_CONFIGURED);
4395 	viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
4396 	    EMLXS_FCFI_CONFIGURED);
4397 
4398 	count = 0;
4399 	fcfp = fcftab->table;
4400 	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
4401 		if (fcfp->state == FCFI_STATE_FREE) {
4402 			continue;
4403 		}
4404 
4405 		if (fcfp->flag & EMLXS_FCFI_SELECTED) {
4406 			continue;
4407 		}
4408 
4409 		if ((fcfp->flag & mask) == viable) {
4410 			continue;
4411 		}
4412 
4413 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4414 		    "fcftab_full_evt_action: fcfi=%d %s flag=%x. "
4415 		    "Deleting FCF.",
4416 		    fcfp->fcf_index,
4417 		    emlxs_fcfi_state_xlate(fcfp->state),
4418 		    fcfp->flag);
4419 
4420 		(void) emlxs_fcfi_free(port, fcfp);
4421 
4422 		(void) emlxs_fcftab_fcf_delete(port, fcfp->fcf_index);
4423 
4424 		count++;
4425 	}
4426 
4427 	if (!count) {
4428 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4429 		    "fcftab_full_evt_action: %s:%s arg=%p. "
4430 		    "All FCF's are viable. Terminated.",
4431 		    emlxs_fcftab_state_xlate(fcftab->state),
4432 		    emlxs_fcf_event_xlate(evt), arg1);
4433 
4434 		return (0);
4435 	}
4436 
4437 	switch (fcftab->state) {
4438 	case FCFTAB_STATE_SOLICIT:
4439 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4440 		    "fcftab_full_evt_action: %s gen=%x. "
4441 		    "Already soliciting. Terminated.",
4442 		    emlxs_fcftab_state_xlate(fcftab->state),
4443 		    fcftab->generation);
4444 		break;
4445 
4446 	default:
4447 		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4448 		fcftab->flag |= EMLXS_FCFTAB_SOL_REQ;
4449 		fcftab->generation++;
4450 
4451 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4452 		    "fcftab_full_evt_action: %s gen=%x. Soliciting.",
4453 		    emlxs_fcftab_state_xlate(fcftab->state),
4454 		    fcftab->generation);
4455 
4456 		rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT,
4457 		    FCF_REASON_EVENT, evt, arg1);
4458 		break;
4459 	}
4460 
4461 	return (rval);
4462 
4463 } /* emlxs_fcftab_full_evt_action() */
4464 
4465 
4466 /*ARGSUSED*/
4467 static uint32_t
4468 emlxs_fcftab_online_action(emlxs_port_t *port, uint32_t evt,
4469     void *arg1)
4470 {
4471 	emlxs_hba_t *hba = HBA;
4472 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4473 	emlxs_config_t *cfg = &CFG;
4474 	FCFIobj_t *fcfp;
4475 	uint32_t rval;
4476 	uint32_t mask;
4477 	uint32_t viable;
4478 	uint32_t i;
4479 	uint32_t count = 0;
4480 
4481 	if (fcftab->state != FCFTAB_STATE_ONLINE) {
4482 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4483 		    "fcftab_online_action: %s:%s arg=%p. "
4484 		    "Invalid state. Terminated.",
4485 		    emlxs_fcftab_state_xlate(fcftab->state),
4486 		    emlxs_fcf_event_xlate(evt), arg1);
4487 		return (1);
4488 	}
4489 
4490 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
4491 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4492 		    "fcftab_online_action: %s:%s arg=%p flag=%x. "
4493 		    "Handling request.",
4494 		    emlxs_fcftab_state_xlate(fcftab->state),
4495 		    emlxs_fcf_event_xlate(evt), arg1,
4496 		    fcftab->flag);
4497 
4498 		rval = emlxs_fcftab_req_handler(port, arg1);
4499 		return (rval);
4500 	}
4501 
4502 	if (fcftab->fcfi_online == 0) {
4503 		mask =   (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
4504 		    EMLXS_FCFI_CONFIGURED);
4505 		viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
4506 		    EMLXS_FCFI_CONFIGURED);
4507 
4508 		/* Count viable FCF's in table */
4509 		count = 0;
4510 		fcfp = fcftab->table;
4511 		for (i = 0; i < fcftab->table_count; i++, fcfp++) {
4512 			if (fcfp->state == FCFI_STATE_FREE) {
4513 				continue;
4514 			}
4515 
4516 			if ((fcfp->flag & mask) == viable) {
4517 				count++;
4518 			}
4519 		}
4520 
4521 		if (count) {
4522 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4523 			    "fcftab_online_action: %s:%s "
4524 			    "fcfi_online=0,%d,%d. Starting solicit timer.",
4525 			    emlxs_fcftab_state_xlate(fcftab->state),
4526 			    emlxs_fcf_event_xlate(evt),
4527 			    fcftab->fcfi_count, count);
4528 
4529 			/* Start the solicit timer */
4530 			fcftab->sol_timer = hba->timer_tics +
4531 			    cfg[CFG_FCF_RESOLICIT_DELAY].current;
4532 		} else {
4533 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4534 			    "fcftab_online_action: %s:%s "
4535 			    "fcfi_online=0,%d,0. Wait for FCF event.",
4536 			    emlxs_fcftab_state_xlate(fcftab->state),
4537 			    emlxs_fcf_event_xlate(evt),
4538 			    fcftab->fcfi_count);
4539 		}
4540 
4541 		if (hba->state > FC_LINK_DOWN) {
4542 			mutex_enter(&EMLXS_PORT_LOCK);
4543 			if (hba->state > FC_LINK_DOWN) {
4544 				HBASTATS.LinkDown++;
4545 				EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN);
4546 			}
4547 			hba->flag &= FC_LINKDOWN_MASK;
4548 			hba->discovery_timer = 0;
4549 			mutex_exit(&EMLXS_PORT_LOCK);
4550 
4551 			emlxs_log_link_event(port);
4552 		}
4553 
4554 		return (0);
4555 	}
4556 
4557 	if (hba->state < FC_LINK_UP) {
4558 		mutex_enter(&EMLXS_PORT_LOCK);
4559 		if (hba->state < FC_LINK_UP) {
4560 			HBASTATS.LinkUp++;
4561 			EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP);
4562 		}
4563 		hba->discovery_timer =
4564 		    hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current +
4565 		    cfg[CFG_DISC_TIMEOUT].current;
4566 		mutex_exit(&EMLXS_PORT_LOCK);
4567 
4568 		emlxs_log_link_event(port);
4569 	}
4570 
4571 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4572 	    "fcftab_online_action: %s:%s arg=%p fcfi_online=%d. Terminated.",
4573 	    emlxs_fcftab_state_xlate(fcftab->state),
4574 	    emlxs_fcf_event_xlate(evt), arg1,
4575 	    fcftab->fcfi_online);
4576 
4577 	return (0);
4578 
4579 } /* emlxs_fcftab_online_action() */
4580 
4581 
4582 /*ARGSUSED*/
4583 static uint32_t
4584 emlxs_fcftab_offline_action(emlxs_port_t *port, uint32_t evt,
4585     void *arg1)
4586 {
4587 	emlxs_hba_t *hba = HBA;
4588 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4589 	uint32_t rval;
4590 
4591 	if (fcftab->state != FCFTAB_STATE_OFFLINE) {
4592 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4593 		    "fcftab_offline_action: %s:%s arg=%p. "
4594 		    "Invalid state. Terminated.",
4595 		    emlxs_fcftab_state_xlate(fcftab->state),
4596 		    emlxs_fcf_event_xlate(evt), arg1);
4597 		return (1);
4598 	}
4599 
4600 	fcftab->flag &= ~EMLXS_FCFTAB_OFFLINE_REQ;
4601 
4602 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
4603 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4604 		    "fcftab_offline_action: %s:%s arg=%p flag=%x. "
4605 		    "Handling request.",
4606 		    emlxs_fcftab_state_xlate(fcftab->state),
4607 		    emlxs_fcf_event_xlate(evt), arg1,
4608 		    fcftab->flag);
4609 
4610 		rval = emlxs_fcftab_req_handler(port, arg1);
4611 		return (rval);
4612 	}
4613 
4614 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4615 	    "fcftab_offline_action: %s:%s arg=%p fcfi_online=%d. Terminated.",
4616 	    emlxs_fcftab_state_xlate(fcftab->state),
4617 	    emlxs_fcf_event_xlate(evt), arg1,
4618 	    fcftab->fcfi_online);
4619 
4620 	return (0);
4621 
4622 } /* emlxs_fcftab_offline_action() */
4623 
4624 
4625 /*ARGSUSED*/
4626 static uint32_t
4627 emlxs_fcftab_shutdown_action(emlxs_port_t *port, uint32_t evt,
4628     void *arg1)
4629 {
4630 	emlxs_hba_t *hba = HBA;
4631 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4632 	FCFIobj_t *fcfp;
4633 	uint32_t i;
4634 	uint32_t online;
4635 
4636 	if (fcftab->state != FCFTAB_STATE_SHUTDOWN) {
4637 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4638 		    "fcftab_shutdown_action: %s:%s arg=%p. "
4639 		    "Invalid state. Terminated.",
4640 		    emlxs_fcftab_state_xlate(fcftab->state),
4641 		    emlxs_fcf_event_xlate(evt), arg1);
4642 		return (1);
4643 	}
4644 
4645 	fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4646 
4647 	if (fcftab->prev_state != FCFTAB_STATE_SHUTDOWN) {
4648 		/* Offline all FCF's */
4649 		fcfp = fcftab->table;
4650 		for (i = 0; i < fcftab->table_count; i++, fcfp++) {
4651 
4652 			if (fcfp->state <= FCFI_STATE_OFFLINE) {
4653 				continue;
4654 			}
4655 
4656 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4657 			    "fcftab_shutdown_action: fcfi=%d %s "
4658 			    "fcfi_online=%d. Offlining FCF.",
4659 			    fcfp->fcf_index,
4660 			    emlxs_fcfi_state_xlate(fcfp->state),
4661 			    fcftab->fcfi_online);
4662 
4663 			(void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE,
4664 			    fcfp);
4665 		}
4666 
4667 		return (0);
4668 	}
4669 
4670 	/* Check FCF state */
4671 	online = 0;
4672 	fcfp = fcftab->table;
4673 	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
4674 
4675 		if (fcfp->state <= FCFI_STATE_OFFLINE) {
4676 			continue;
4677 		}
4678 
4679 		online++;
4680 	}
4681 
4682 	if (online) {
4683 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4684 		    "fcftab_shutdown_action: %s:%s arg=%p. "
4685 		    "fcfi_online=%d,%d Terminated.",
4686 		    emlxs_fcftab_state_xlate(fcftab->state),
4687 		    emlxs_fcf_event_xlate(evt), arg1,
4688 		    online, fcftab->fcfi_online);
4689 
4690 		return (0);
4691 	}
4692 
4693 	/* Free FCF table */
4694 	fcfp = fcftab->table;
4695 	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
4696 
4697 		if (fcfp->state == FCFI_STATE_FREE) {
4698 			continue;
4699 		}
4700 
4701 		(void) emlxs_fcfi_free(port, fcfp);
4702 	}
4703 
4704 	/* Clean the selection table */
4705 	bzero(fcftab->fcfi, sizeof (fcftab->fcfi));
4706 	fcftab->fcfi_count = 0;
4707 
4708 	fcftab->flag |= EMLXS_FCFTAB_SHUTDOWN;
4709 
4710 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4711 	    "fcftab_shutdown_action: %s:%s arg=%p flag=%x fcfi_online=%d. "
4712 	    "Shutdown.",
4713 	    emlxs_fcftab_state_xlate(fcftab->state),
4714 	    emlxs_fcf_event_xlate(evt), arg1,
4715 	    fcftab->flag, fcftab->fcfi_online);
4716 
4717 	return (0);
4718 
4719 } /* emlxs_fcftab_shutdown_action() */
4720 
4721 
4722 
4723 /* ************************************************************************** */
4724 /* FCFI */
4725 /* ************************************************************************** */
4726 
4727 static char *
4728 emlxs_fcfi_state_xlate(uint32_t state)
4729 {
4730 	static char buffer[32];
4731 	uint32_t i;
4732 	uint32_t count;
4733 
4734 	count = sizeof (emlxs_fcfi_state_table) / sizeof (emlxs_table_t);
4735 	for (i = 0; i < count; i++) {
4736 		if (state == emlxs_fcfi_state_table[i].code) {
4737 			return (emlxs_fcfi_state_table[i].string);
4738 		}
4739 	}
4740 
4741 	(void) sprintf(buffer, "state=0x%x", state);
4742 	return (buffer);
4743 
4744 } /* emlxs_fcfi_state_xlate() */
4745 
4746 
4747 static uint32_t
4748 emlxs_fcfi_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
4749     void *arg1)
4750 {
4751 	uint32_t rval;
4752 	uint32_t(*func) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *);
4753 	uint32_t index;
4754 	uint32_t events;
4755 	uint16_t state;
4756 
4757 	/* Convert event to action table index */
4758 	switch (evt) {
4759 	case FCF_EVENT_STATE_ENTER:
4760 		index = 0;
4761 		break;
4762 	case FCF_EVENT_FCFI_ONLINE:
4763 		index = 1;
4764 		break;
4765 	case FCF_EVENT_FCFI_OFFLINE:
4766 		index = 2;
4767 		break;
4768 	case FCF_EVENT_FCFI_PAUSE:
4769 		index = 3;
4770 		break;
4771 	case FCF_EVENT_VFI_ONLINE:
4772 		index = 4;
4773 		break;
4774 	case FCF_EVENT_VFI_OFFLINE:
4775 		index = 5;
4776 		break;
4777 	default:
4778 		return (1);
4779 	}
4780 
4781 	events = FCFI_ACTION_EVENTS;
4782 	state  = fcfp->state;
4783 
4784 	index += (state * events);
4785 	func   = (uint32_t(*) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *))
4786 	    emlxs_fcfi_action_table[index];
4787 
4788 	if (!func) {
4789 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
4790 		    "fcfi:%d %s:%s arg=%p. No action. Terminated.",
4791 		    fcfp->fcf_index,
4792 		    emlxs_fcfi_state_xlate(fcfp->state),
4793 		    emlxs_fcf_event_xlate(evt), arg1);
4794 
4795 		return (1);
4796 	}
4797 
4798 	rval = (func)(port, fcfp, evt, arg1);
4799 
4800 	return (rval);
4801 
4802 } /* emlxs_fcfi_action() */
4803 
4804 
4805 static uint32_t
4806 emlxs_fcfi_event(emlxs_port_t *port, uint32_t evt,
4807     void *arg1)
4808 {
4809 	FCFIobj_t *fcfp = NULL;
4810 	VFIobj_t *vfip = NULL;
4811 	uint32_t rval;
4812 
4813 	/* Filter events and acquire fcfi context */
4814 	switch (evt) {
4815 	case FCF_EVENT_VFI_ONLINE:
4816 	case FCF_EVENT_VFI_OFFLINE:
4817 		vfip = (VFIobj_t *)arg1;
4818 
4819 		if (!vfip) {
4820 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
4821 			    "fcfi: %s arg=%p. Null VFI found. Terminated.",
4822 			    emlxs_fcf_event_xlate(evt), arg1);
4823 
4824 			return (1);
4825 		}
4826 
4827 		fcfp = vfip->fcfp;
4828 		if (!fcfp) {
4829 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
4830 			    "fcfi: %s arg=%p. FCF not found. Terminated.",
4831 			    emlxs_fcf_event_xlate(evt), arg1);
4832 
4833 			return (1);
4834 		}
4835 		break;
4836 
4837 	case FCF_EVENT_FCFI_ONLINE:
4838 	case FCF_EVENT_FCFI_OFFLINE:
4839 	case FCF_EVENT_FCFI_PAUSE:
4840 		fcfp = (FCFIobj_t *)arg1;
4841 		if (!fcfp) {
4842 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
4843 			    "fcfi: %s arg=%p. Null FCFI found. Terminated.",
4844 			    emlxs_fcf_event_xlate(evt), arg1);
4845 
4846 			return (1);
4847 		}
4848 		break;
4849 
4850 	default:
4851 		return (1);
4852 	}
4853 
4854 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
4855 	    "fcfi:%d %s:%s arg=%p",
4856 	    fcfp->fcf_index,
4857 	    emlxs_fcfi_state_xlate(fcfp->state),
4858 	    emlxs_fcf_event_xlate(evt), arg1);
4859 
4860 	rval = emlxs_fcfi_action(port, fcfp, evt, arg1);
4861 
4862 	return (rval);
4863 
4864 } /* emlxs_fcfi_event() */
4865 
4866 
4867 /* EMLXS_FCF_LOCK must be held to enter */
4868 /*ARGSUSED*/
4869 static uint32_t
4870 emlxs_fcfi_state(emlxs_port_t *port, FCFIobj_t *fcfp, uint16_t state,
4871     uint16_t reason, uint32_t explain, void *arg1)
4872 {
4873 	uint32_t rval = 0;
4874 
4875 	if (state >= FCFI_ACTION_STATES) {
4876 		return (1);
4877 	}
4878 
4879 	if ((fcfp->state == state) &&
4880 	    (reason != FCF_REASON_REENTER)) {
4881 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4882 		    "fcfi_state:%d %s:%s:0x%x arg=%p. "
4883 		    "State not changed. Terminated.",
4884 		    fcfp->fcf_index,
4885 		    emlxs_fcfi_state_xlate(state),
4886 		    emlxs_fcf_reason_xlate(reason),
4887 		    explain, arg1);
4888 
4889 		return (1);
4890 	}
4891 
4892 	if (!reason) {
4893 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4894 		    "fcfi:%d %s-->%s arg=%p",
4895 		    fcfp->fcf_index,
4896 		    emlxs_fcfi_state_xlate(fcfp->state),
4897 		    emlxs_fcfi_state_xlate(state), arg1);
4898 	} else if (reason == FCF_REASON_EVENT) {
4899 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4900 		    "fcfi:%d %s-->%s:%s:%s arg=%p",
4901 		    fcfp->fcf_index,
4902 		    emlxs_fcfi_state_xlate(fcfp->state),
4903 		    emlxs_fcfi_state_xlate(state),
4904 		    emlxs_fcf_reason_xlate(reason),
4905 		    emlxs_fcf_event_xlate(explain), arg1);
4906 	} else if (explain) {
4907 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4908 		    "fcfi:%d %s-->%s:%s:0x%x arg=%p",
4909 		    fcfp->fcf_index,
4910 		    emlxs_fcfi_state_xlate(fcfp->state),
4911 		    emlxs_fcfi_state_xlate(state),
4912 		    emlxs_fcf_reason_xlate(reason),
4913 		    explain, arg1);
4914 	} else {
4915 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4916 		    "fcfi:%d %s-->%s:%s arg=%p",
4917 		    fcfp->fcf_index,
4918 		    emlxs_fcfi_state_xlate(fcfp->state),
4919 		    emlxs_fcfi_state_xlate(state),
4920 		    emlxs_fcf_reason_xlate(reason), arg1);
4921 	}
4922 
4923 	fcfp->prev_state = fcfp->state;
4924 	fcfp->prev_reason = fcfp->reason;
4925 	fcfp->state = state;
4926 	fcfp->reason = reason;
4927 
4928 	rval = emlxs_fcfi_action(port, fcfp, FCF_EVENT_STATE_ENTER, arg1);
4929 
4930 	return (rval);
4931 
4932 } /* emlxs_fcfi_state() */
4933 
4934 
4935 static FCFIobj_t *
4936 emlxs_fcfi_alloc(emlxs_port_t *port)
4937 {
4938 	emlxs_hba_t	*hba = HBA;
4939 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4940 	uint16_t	i;
4941 	FCFIobj_t	*fcfp;
4942 
4943 	fcfp = fcftab->table;
4944 	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
4945 		if (fcfp->state == FCFI_STATE_FREE) {
4946 
4947 			bzero(fcfp, sizeof (FCFIobj_t));
4948 			fcfp->index = i;
4949 			fcfp->FCFI  = 0xFFFF;
4950 
4951 			(void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
4952 			    0, 0, 0);
4953 			return (fcfp);
4954 		}
4955 	}
4956 
4957 	return (NULL);
4958 
4959 } /* emlxs_fcfi_alloc() */
4960 
4961 
4962 static uint32_t
4963 emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp)
4964 {
4965 	uint32_t rval;
4966 
4967 	rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_FREE, 0, 0, 0);
4968 
4969 	return (rval);
4970 
4971 } /* emlxs_fcfi_free() */
4972 
4973 
4974 static FCFIobj_t *
4975 emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec, uint32_t *fcf_index)
4976 {
4977 	emlxs_hba_t	*hba = HBA;
4978 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
4979 	uint32_t	i;
4980 	uint32_t	index;
4981 	FCFIobj_t	*fcfp;
4982 
4983 	if (fcfrec) {
4984 		/* Check for a matching FCF index, fabric name, */
4985 		/* and mac address */
4986 		fcfp = fcftab->table;
4987 		for (i = 0; i < fcftab->table_count; i++, fcfp++) {
4988 			if (fcfp->state == FCFI_STATE_FREE) {
4989 				continue;
4990 			}
4991 
4992 			if ((fcfp->fcf_index == fcfrec->fcf_index) &&
4993 			    (bcmp((char *)fcfrec->fabric_name_identifier,
4994 			    fcfp->fcf_rec.fabric_name_identifier, 8) == 0) &&
4995 			    (bcmp((char *)fcfrec->fcf_mac_address_hi,
4996 			    fcfp->fcf_rec.fcf_mac_address_hi, 4) == 0) &&
4997 			    (bcmp((char *)fcfrec->fcf_mac_address_low,
4998 			    fcfp->fcf_rec.fcf_mac_address_low, 2) == 0)) {
4999 				return (fcfp);
5000 			}
5001 		}
5002 
5003 	} else if (fcf_index) {
5004 		/* Check for a matching FCF index only */
5005 		index = *fcf_index;
5006 		fcfp = fcftab->table;
5007 		for (i = 0; i < fcftab->table_count; i++, fcfp++) {
5008 			if (fcfp->state == FCFI_STATE_FREE) {
5009 				continue;
5010 			}
5011 
5012 			if (fcfp->fcf_index == index) {
5013 				return (fcfp);
5014 			}
5015 		}
5016 	}
5017 
5018 	return (NULL);
5019 
5020 } /* emlxs_fcfi_find() */
5021 
5022 
5023 /*ARGSUSED*/
5024 static uint32_t
5025 emlxs_fcfi_free_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
5026     void *arg1)
5027 {
5028 
5029 	if (fcfp->state != FCFI_STATE_FREE) {
5030 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5031 		    "fcfi_free_action:%d %s:%s arg=%p. "
5032 		    "Invalid state. Terminated.",
5033 		    fcfp->fcf_index,
5034 		    emlxs_fcfi_state_xlate(fcfp->state),
5035 		    emlxs_fcf_event_xlate(evt), arg1);
5036 		return (1);
5037 	}
5038 
5039 	if (fcfp->vfi_online) {
5040 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5041 		    "fcfi_free_action:%d flag=%x vfi_online=%d",
5042 		    fcfp->fcf_index,
5043 		    fcfp->flag,
5044 		    fcfp->vfi_online);
5045 	}
5046 
5047 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5048 	    "fcfi_free_action:%d flag=%x. FCF freed.",
5049 	    fcfp->fcf_index,
5050 	    fcfp->flag);
5051 
5052 	fcfp->flag = 0;
5053 
5054 	return (0);
5055 
5056 } /* emlxs_fcfi_free_action() */
5057 
5058 
5059 /*ARGSUSED*/
5060 static uint32_t
5061 emlxs_fcfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
5062     void *arg1)
5063 {
5064 	emlxs_hba_t *hba = HBA;
5065 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
5066 	uint32_t rval;
5067 
5068 	if (fcfp->state != FCFI_STATE_OFFLINE) {
5069 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5070 		    "fcfi_offline_action:%d %s:%s arg=%p. "
5071 		    "Invalid state. Terminated.",
5072 		    fcfp->fcf_index,
5073 		    emlxs_fcfi_state_xlate(fcfp->state),
5074 		    emlxs_fcf_event_xlate(evt), arg1);
5075 		return (1);
5076 	}
5077 
5078 	fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
5079 
5080 	if (fcfp->prev_state == FCFI_STATE_FREE) {
5081 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5082 		    "fcfi_offline_action:%d fcfi_online=%d. Terminated.",
5083 		    fcfp->fcf_index,
5084 		    fcftab->fcfi_online);
5085 
5086 		return (0);
5087 	}
5088 
5089 	if (fcfp->vfi_online) {
5090 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5091 		    "fcfi_offline_action:%d vfi_online=%d.",
5092 		    fcfp->fcf_index,
5093 		    fcfp->vfi_online);
5094 	}
5095 
5096 	if (fcfp->flag & EMLXS_FCFI_FCFTAB) {
5097 		fcfp->flag &= ~EMLXS_FCFI_FCFTAB;
5098 
5099 		if (fcftab->fcfi_online) {
5100 			fcftab->fcfi_online--;
5101 		}
5102 	}
5103 
5104 	/* Check if online was requested */
5105 	if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) {
5106 
5107 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5108 		    "fcfi_offline_action:%d fcfi_online=%d. "
5109 		    "Online requested.",
5110 		    fcfp->fcf_index,
5111 		    fcftab->fcfi_online);
5112 
5113 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
5114 		    FCF_REASON_REQUESTED, 0, arg1);
5115 		return (rval);
5116 	}
5117 
5118 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5119 	    "fcfi_offline_action:%d fcfi_online=%d. "
5120 	    "FCFI offline. Notifying fcftab.",
5121 	    fcfp->fcf_index,
5122 	    fcftab->fcfi_online);
5123 
5124 	/* Notify FCFTAB */
5125 	rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp);
5126 
5127 	return (rval);
5128 
5129 } /* emlxs_fcfi_offline_action() */
5130 
5131 
5132 /*ARGSUSED*/
5133 static uint32_t
5134 emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
5135     uint32_t evt, void *arg1)
5136 {
5137 	uint32_t rval;
5138 
5139 	if (evt != FCF_EVENT_VFI_ONLINE) {
5140 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5141 		    "fcfi_vfi_online_evt_action:%d %s:%s arg=%p flag=%x. "
5142 		    "Invalid event type. Terminated.",
5143 		    fcfp->fcf_index,
5144 		    emlxs_fcfi_state_xlate(fcfp->state),
5145 		    emlxs_fcf_event_xlate(evt), arg1,
5146 		    fcfp->flag);
5147 		return (1);
5148 	}
5149 
5150 	switch (fcfp->state) {
5151 	case FCFI_STATE_ONLINE:
5152 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5153 		    "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. "
5154 		    "Reentering online.",
5155 		    fcfp->fcf_index,
5156 		    fcfp->flag,
5157 		    fcfp->vfi_online);
5158 
5159 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
5160 		    FCF_REASON_REENTER, evt, arg1);
5161 		break;
5162 
5163 	case FCFI_STATE_VFI_ONLINE:
5164 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5165 		    "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. "
5166 		    "Online cmpl.",
5167 		    fcfp->fcf_index,
5168 		    fcfp->flag,
5169 		    fcfp->vfi_online);
5170 
5171 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE_CMPL,
5172 		    FCF_REASON_EVENT, evt, arg1);
5173 		break;
5174 
5175 	default:
5176 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5177 		    "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. "
5178 		    "Terminated.",
5179 		    fcfp->fcf_index,
5180 		    fcfp->flag,
5181 		    fcfp->vfi_online);
5182 		return (0);
5183 	}
5184 
5185 	return (rval);
5186 
5187 } /* emlxs_fcfi_vfi_online_evt_action() */
5188 
5189 
5190 /*ARGSUSED*/
5191 static uint32_t
5192 emlxs_fcfi_offline_handler(emlxs_port_t *port, FCFIobj_t *fcfp, void *arg1)
5193 {
5194 	uint32_t rval;
5195 
5196 	if (!(fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
5197 		return (0);
5198 	}
5199 
5200 	if (fcfp->vfi_online != 0) {
5201 		if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) {
5202 			rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED,
5203 			    FCF_REASON_REQUESTED, 0, arg1);
5204 		} else {
5205 			rval = emlxs_fcfi_state(port, fcfp,
5206 			    FCFI_STATE_VFI_OFFLINE, FCF_REASON_REQUESTED,
5207 			    0, arg1);
5208 		}
5209 
5210 	} else if (fcfp->flag & EMLXS_FCFI_REG) {
5211 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
5212 		    FCF_REASON_REQUESTED, 0, arg1);
5213 
5214 	} else {
5215 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
5216 		    FCF_REASON_REQUESTED, 0, arg1);
5217 	}
5218 
5219 	return (rval);
5220 
5221 } /* emlxs_fcfi_offline_handler() */
5222 
5223 
5224 /*ARGSUSED*/
5225 static uint32_t
5226 emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
5227     uint32_t evt, void *arg1)
5228 {
5229 	uint32_t rval;
5230 	VFIobj_t *vfip;
5231 
5232 	if (evt != FCF_EVENT_VFI_OFFLINE) {
5233 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5234 		    "fcfi_vfi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
5235 		    "Invalid event type. Terminated.",
5236 		    fcfp->fcf_index,
5237 		    emlxs_fcfi_state_xlate(fcfp->state),
5238 		    emlxs_fcf_event_xlate(evt), arg1,
5239 		    fcfp->flag);
5240 		return (1);
5241 	}
5242 
5243 	vfip = (VFIobj_t *)arg1;
5244 	vfip->fcfp = NULL;
5245 
5246 	switch (fcfp->state) {
5247 	case FCFI_STATE_VFI_ONLINE:
5248 	case FCFI_STATE_ONLINE:
5249 		if (fcfp->vfi_online == 0) {
5250 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5251 			    "fcfi_vfi_offline_evt_action:%d flag=%x "
5252 			    "vfi_online=%d. Offlining.",
5253 			    fcfp->fcf_index,
5254 			    fcfp->flag, fcfp->vfi_online);
5255 
5256 			fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
5257 			fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
5258 
5259 			rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
5260 		} else {
5261 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5262 			    "fcfi_vfi_offline_evt_action:%d flag=%x "
5263 			    "vfi_online=%d. Terminated.",
5264 			    fcfp->fcf_index,
5265 			    fcfp->flag, fcfp->vfi_online);
5266 		}
5267 		break;
5268 
5269 	case FCFI_STATE_PAUSED:
5270 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5271 		    "fcfi_vfi_offline_evt_action:%d flag=%x vfi_online=%d. "
5272 		    "Terminated.",
5273 		    fcfp->fcf_index,
5274 		    fcfp->flag, fcfp->vfi_online);
5275 		break;
5276 
5277 	case FCFI_STATE_VFI_OFFLINE:
5278 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5279 		    "fcfi_vfi_offline_evt_action:%d flag=%x. Offline cmpl.",
5280 		    fcfp->fcf_index,
5281 		    fcfp->flag);
5282 
5283 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL,
5284 		    FCF_REASON_EVENT, evt, arg1);
5285 		break;
5286 
5287 	case FCFI_STATE_VFI_OFFLINE_CMPL:
5288 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5289 		    "fcfi_vfi_offline_evt_action:%d flag=%x. Offline cmpl.",
5290 		    fcfp->fcf_index,
5291 		    fcfp->flag);
5292 
5293 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL,
5294 		    FCF_REASON_REENTER, evt, arg1);
5295 		break;
5296 
5297 	default:
5298 		if (fcfp->vfi_online == 0) {
5299 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5300 			    "fcfi_vfi_offline_evt_action:%d flag=%x "
5301 			    "vfi_online=%d. Offline requested.",
5302 			    fcfp->fcf_index,
5303 			    fcfp->flag, fcfp->vfi_online);
5304 
5305 			fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
5306 			fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
5307 		} else {
5308 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5309 			    "fcfi_vfi_offline_evt_action:%d flag = %x "
5310 			    "vfi_online=%d. Terminated.",
5311 			    fcfp->fcf_index,
5312 			    fcfp->flag, fcfp->vfi_online);
5313 		}
5314 		return (0);
5315 	}
5316 
5317 	return (rval);
5318 
5319 } /* emlxs_fcfi_vfi_offline_evt_action() */
5320 
5321 
5322 /*ARGSUSED*/
5323 static uint32_t
5324 emlxs_fcfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
5325     uint32_t evt, void *arg1)
5326 {
5327 	uint32_t rval = 0;
5328 
5329 	if (evt != FCF_EVENT_FCFI_ONLINE) {
5330 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5331 		    "fcfi_online_evt_action:%d %s:%s arg=%p. "
5332 		    "Invalid event type. Terminated.",
5333 		    fcfp->fcf_index,
5334 		    emlxs_fcfi_state_xlate(fcfp->state),
5335 		    emlxs_fcf_event_xlate(evt), arg1);
5336 		return (1);
5337 	}
5338 
5339 	if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) {
5340 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5341 		    "fcfi_online_evt_action:%d. "
5342 		    "Online already requested. Terminated.",
5343 		    fcfp->fcf_index);
5344 		return (1);
5345 	}
5346 
5347 	fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
5348 	fcfp->flag |= EMLXS_FCFI_ONLINE_REQ;
5349 
5350 	switch (fcfp->state) {
5351 	case FCFI_STATE_OFFLINE:
5352 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5353 		    "fcfi_online_evt_action:%d flag=%x. Initiating online.",
5354 		    fcfp->fcf_index,
5355 		    fcfp->flag);
5356 
5357 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
5358 		    FCF_REASON_EVENT, evt, arg1);
5359 		break;
5360 
5361 	case FCFI_STATE_VFI_OFFLINE:
5362 	case FCFI_STATE_PAUSED:
5363 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5364 		    "fcfi_online_evt_action:%d flag=%x. Initiating online.",
5365 		    fcfp->fcf_index,
5366 		    fcfp->flag);
5367 
5368 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
5369 		    FCF_REASON_EVENT, evt, arg1);
5370 		break;
5371 
5372 	case FCFI_STATE_ONLINE:
5373 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5374 		    "fcfi_online_evt_action:%d flag=%x. Reentering online.",
5375 		    fcfp->fcf_index,
5376 		    fcfp->flag);
5377 
5378 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
5379 		    FCF_REASON_REENTER, evt, arg1);
5380 		break;
5381 
5382 	default:
5383 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5384 		    "fcfi_online_evt_action:%d flag=%x. Terminated.",
5385 		    fcfp->fcf_index,
5386 		    fcfp->flag);
5387 		break;
5388 	}
5389 
5390 	return (rval);
5391 
5392 } /* emlxs_fcfi_online_evt_action() */
5393 
5394 
5395 /*ARGSUSED*/
5396 static uint32_t
5397 emlxs_fcfi_vfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp,
5398     uint32_t evt, void *arg1)
5399 {
5400 	emlxs_hba_t *hba = HBA;
5401 	uint32_t i;
5402 	uint32_t rval;
5403 	VFIobj_t *vfip;
5404 
5405 	if (fcfp->state != FCFI_STATE_VFI_ONLINE) {
5406 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5407 		    "fcfi_vfi_online_action:%d %s:%s arg=%p. "
5408 		    "Invalid state. Terminated.",
5409 		    fcfp->fcf_index,
5410 		    emlxs_fcfi_state_xlate(fcfp->state),
5411 		    emlxs_fcf_event_xlate(evt), arg1);
5412 		return (1);
5413 	}
5414 
5415 	if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
5416 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5417 		    "fcfi_vfi_online_action:%d. Offline requested.",
5418 		    fcfp->fcf_index);
5419 
5420 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
5421 		return (rval);
5422 	}
5423 
5424 	if (fcfp->vfi_online > 0) {
5425 		/* Waking up out after being paused */
5426 
5427 		/* Find first VFI of this FCFI */
5428 		vfip = hba->sli.sli4.VFI_table;
5429 		for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
5430 			if (vfip->fcfp == fcfp) {
5431 				break;
5432 			}
5433 		}
5434 
5435 	} else {
5436 
5437 		/* Find first available VFI */
5438 		vfip = hba->sli.sli4.VFI_table;
5439 		for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
5440 			if (vfip->fcfp == NULL) {
5441 				vfip->fcfp = fcfp;
5442 				break;
5443 			}
5444 		}
5445 	}
5446 
5447 	if (i == hba->sli.sli4.VFICount) {
5448 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5449 		    "fcfi_vfi_online_action:%d vfi_online=%d. "
5450 		    "No VFI found. Offlining.",
5451 		    fcfp->fcf_index,
5452 		    fcfp->vfi_online);
5453 
5454 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
5455 		fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
5456 
5457 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
5458 		return (rval);
5459 	}
5460 
5461 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5462 	    "fcfi_vfi_online_action:%d vfi_online=%d. Onlining VFI:%d.",
5463 	    fcfp->fcf_index,
5464 	    fcfp->vfi_online,
5465 	    vfip->VFI);
5466 
5467 	rval = emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
5468 
5469 	/* Wait for FCF_EVENT_VFI_ONLINE in return */
5470 
5471 	return (rval);
5472 
5473 } /* emlxs_fcfi_vfi_online_action() */
5474 
5475 
5476 /*ARGSUSED*/
5477 static uint32_t
5478 emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp,
5479     uint32_t evt, void *arg1)
5480 {
5481 	uint32_t rval;
5482 
5483 	if (fcfp->state != FCFI_STATE_VFI_ONLINE_CMPL) {
5484 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5485 		    "fcfi_vfi_online_cmpl_action:%d %s:%s arg=%p. "
5486 		    "Invalid state. Terminated.",
5487 		    fcfp->fcf_index,
5488 		    emlxs_fcfi_state_xlate(fcfp->state),
5489 		    emlxs_fcf_event_xlate(evt), arg1);
5490 		return (1);
5491 	}
5492 
5493 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5494 	    "fcfi_vfi_online_cmpl_action:%d. Going online.",
5495 	    fcfp->fcf_index);
5496 
5497 	rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
5498 	    FCF_REASON_EVENT, evt, arg1);
5499 
5500 	return (rval);
5501 
5502 } /* emlxs_fcfi_vfi_online_cmpl_action() */
5503 
5504 
5505 /*ARGSUSED*/
5506 static uint32_t
5507 emlxs_fcfi_vfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
5508     void *arg1)
5509 {
5510 	emlxs_hba_t *hba = HBA;
5511 	VFIobj_t *vfip;
5512 	uint32_t rval;
5513 	int32_t i;
5514 
5515 	if (fcfp->state != FCFI_STATE_VFI_OFFLINE) {
5516 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5517 		    "fcfi_vfi_offline_action:%d %s:%s arg=%p. "
5518 		    "Invalid state. Terminated.",
5519 		    fcfp->fcf_index,
5520 		    emlxs_fcfi_state_xlate(fcfp->state),
5521 		    emlxs_fcf_event_xlate(evt), arg1);
5522 
5523 		return (1);
5524 	}
5525 
5526 	if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) {
5527 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5528 		    "fcfi_vfi_offline_action:%d vfi_online=%d. Pausing.",
5529 		    fcfp->fcf_index,
5530 		    fcfp->vfi_online);
5531 
5532 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED,
5533 		    FCF_REASON_EVENT, evt, arg1);
5534 
5535 		return (rval);
5536 	}
5537 
5538 	if (fcfp->vfi_online == 0) {
5539 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5540 		    "fcfi_vfi_offline_action:%d. "
5541 		    "VFI already offline. Skipping VFI offline.",
5542 		    fcfp->fcf_index);
5543 
5544 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
5545 		    FCF_REASON_EVENT, evt, arg1);
5546 
5547 		return (rval);
5548 	}
5549 
5550 	/* Offline VFI's of this FCFI */
5551 	for (i = (hba->sli.sli4.VFICount-1); i >= 0; i--) {
5552 		vfip = &hba->sli.sli4.VFI_table[i];
5553 
5554 		if ((vfip->fcfp != fcfp) ||
5555 		    (vfip->state == VFI_STATE_OFFLINE) ||
5556 		    (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
5557 			continue;
5558 		}
5559 
5560 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5561 		    "fcfi_vfi_offline_action:%d. Offlining VFI:%d",
5562 		    fcfp->fcf_index,
5563 		    vfip->VFI);
5564 
5565 		(void) emlxs_vfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip);
5566 	}
5567 
5568 	/* Wait for FCF_EVENT_VFI_OFFLINE in return */
5569 
5570 	return (0);
5571 
5572 } /* emlxs_fcfi_vfi_offline_action() */
5573 
5574 
5575 /*ARGSUSED*/
5576 static uint32_t
5577 emlxs_fcfi_paused_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
5578     void *arg1)
5579 {
5580 	emlxs_hba_t *hba = HBA;
5581 	VFIobj_t *vfip;
5582 	int32_t i;
5583 
5584 	if (fcfp->state != FCFI_STATE_PAUSED) {
5585 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5586 		    "fcfi_paused_action:%d %s:%s arg=%p. "
5587 		    "Invalid state. Terminated.",
5588 		    fcfp->fcf_index,
5589 		    emlxs_fcfi_state_xlate(fcfp->state),
5590 		    emlxs_fcf_event_xlate(evt), arg1);
5591 
5592 		return (1);
5593 	}
5594 
5595 	fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
5596 
5597 	/* Pause all VFI's of this FCFI */
5598 	for (i = (hba->sli.sli4.VFICount-1); i >= 0; i--) {
5599 		vfip = &hba->sli.sli4.VFI_table[i];
5600 
5601 		if ((vfip->state == VFI_STATE_OFFLINE) ||
5602 		    (vfip->state == VFI_STATE_PAUSED) ||
5603 		    (vfip->fcfp != fcfp)) {
5604 			continue;
5605 		}
5606 
5607 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5608 		    "fcfi_paused_action:%d vfi_online=%d. Pausing VFI:%d.",
5609 		    fcfp->fcf_index,
5610 		    fcfp->vfi_online,
5611 		    vfip->VFI);
5612 
5613 		(void) emlxs_vfi_event(port, FCF_EVENT_VFI_PAUSE, vfip);
5614 	}
5615 
5616 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5617 	    "fcfi_paused_action:%d vfi_online=%d. FCFI paused.",
5618 	    fcfp->fcf_index,
5619 	    fcfp->vfi_online);
5620 
5621 	return (0);
5622 
5623 } /* emlxs_fcfi_paused_action() */
5624 
5625 
5626 /*ARGSUSED*/
5627 static uint32_t
5628 emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp,
5629     uint32_t evt, void *arg1)
5630 {
5631 	uint32_t rval = 0;
5632 
5633 	if (fcfp->state != FCFI_STATE_VFI_OFFLINE_CMPL) {
5634 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5635 		    "fcfi_vfi_offline_cmpl_action:%d %s:%s arg=%p. "
5636 		    "Invalid state. Terminated.",
5637 		    fcfp->fcf_index,
5638 		    emlxs_fcfi_state_xlate(fcfp->state),
5639 		    emlxs_fcf_event_xlate(evt), arg1);
5640 		return (1);
5641 	}
5642 
5643 	if ((fcfp->vfi_online == 0) &&
5644 	    (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
5645 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5646 		    "fcfi_vfi_offline_cmpl_action:%d vfi_online=%d. "
5647 		    "Unregistering.",
5648 		    fcfp->fcf_index,
5649 		    fcfp->vfi_online);
5650 
5651 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
5652 		    FCF_REASON_EVENT, evt, arg1);
5653 	} else {
5654 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5655 		    "fcfi_vfi_offline_cmpl_action:%d vfi_online=%d. "
5656 		    "Terminated.",
5657 		    fcfp->fcf_index,
5658 		    fcfp->vfi_online);
5659 	}
5660 
5661 	return (rval);
5662 
5663 } /* emlxs_fcfi_vfi_offline_cmpl_action() */
5664 
5665 
5666 /*ARGSUSED*/
5667 static uint32_t
5668 emlxs_fcfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
5669     void *arg1)
5670 {
5671 	uint32_t rval;
5672 
5673 	if (evt != FCF_EVENT_FCFI_OFFLINE) {
5674 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5675 		    "fcfi_offline_evt_action:%d %s:%s arg=%p. "
5676 		    "Invalid event type. Terminated.",
5677 		    fcfp->fcf_index,
5678 		    emlxs_fcfi_state_xlate(fcfp->state),
5679 		    emlxs_fcf_event_xlate(evt), arg1);
5680 		return (1);
5681 	}
5682 
5683 	if ((fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) &&
5684 	    !(fcfp->flag & EMLXS_FCFI_PAUSE_REQ)) {
5685 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5686 		    "fcfi_offline_evt_action:%d. Offline already requested. "
5687 		    "Terminated.",
5688 		    fcfp->fcf_index);
5689 		return (1);
5690 	}
5691 
5692 	switch (fcfp->state) {
5693 	case FCFI_STATE_OFFLINE:
5694 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5695 		    "fcfi_offline_evt_action:%d flag=%x. Already offline. "
5696 		    "Terminated.",
5697 		    fcfp->fcf_index,
5698 		    fcfp->flag);
5699 		break;
5700 
5701 	/* Wait states */
5702 	case FCFI_STATE_VFI_ONLINE:
5703 	case FCFI_STATE_VFI_OFFLINE:
5704 	case FCFI_STATE_REG:
5705 	case FCFI_STATE_ONLINE:
5706 	case FCFI_STATE_PAUSED:
5707 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
5708 		fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
5709 
5710 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5711 		    "fcfi_offline_evt_action:%d flag=%x.  Handling offline.",
5712 		    fcfp->fcf_index,
5713 		    fcfp->flag);
5714 
5715 		/* Handle offline now */
5716 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
5717 		break;
5718 
5719 	/* Transitional states */
5720 	default:
5721 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
5722 		fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
5723 
5724 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5725 		    "fcfi_offline_evt_action:%d. "
5726 		    "Invalid state. Terminated.",
5727 		    fcfp->fcf_index);
5728 		break;
5729 	}
5730 
5731 	return (rval);
5732 
5733 } /* emlxs_fcfi_offline_evt_action() */
5734 
5735 
5736 /*ARGSUSED*/
5737 static uint32_t
5738 emlxs_fcfi_pause_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
5739     void *arg1)
5740 {
5741 	uint32_t rval;
5742 
5743 	if (evt != FCF_EVENT_FCFI_PAUSE) {
5744 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5745 		    "fcfi_pause_evt_action:%d %s:%s arg=%p. "
5746 		    "Invalid event type. Terminated.",
5747 		    fcfp->fcf_index,
5748 		    emlxs_fcfi_state_xlate(fcfp->state),
5749 		    emlxs_fcf_event_xlate(evt), arg1);
5750 		return (1);
5751 	}
5752 
5753 	if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) {
5754 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5755 		    "fcfi_pause_evt_action:%d. Pause already requested. "
5756 		    "Terminated.",
5757 		    fcfp->fcf_index);
5758 		return (1);
5759 	}
5760 
5761 	if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
5762 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5763 		    "fcfi_pause_evt_action:%d. Offline already requested. "
5764 		    "Terminated.",
5765 		    fcfp->fcf_index);
5766 		return (1);
5767 	}
5768 
5769 	switch (fcfp->state) {
5770 	case FCFI_STATE_OFFLINE:
5771 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5772 		    "fcfi_pause_evt_action:%d flag=%x. Already offline. "
5773 		    "Terminated.",
5774 		    fcfp->fcf_index,
5775 		    fcfp->flag);
5776 		break;
5777 
5778 	case FCFI_STATE_PAUSED:
5779 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5780 		    "fcfi_pause_evt_action:%d flag=%x. Already paused. "
5781 		    "Terminated.",
5782 		    fcfp->fcf_index,
5783 		    fcfp->flag);
5784 		break;
5785 
5786 	/* Wait states */
5787 	case FCFI_STATE_VFI_ONLINE:
5788 	case FCFI_STATE_VFI_OFFLINE:
5789 	case FCFI_STATE_REG:
5790 	case FCFI_STATE_ONLINE:
5791 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
5792 		fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
5793 
5794 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5795 		    "fcfi_pause_evt_action:%d flag=%x. Handle pause request.",
5796 		    fcfp->fcf_index,
5797 		    fcfp->flag);
5798 
5799 		/* Handle offline now */
5800 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
5801 		break;
5802 
5803 	/* Transitional states */
5804 	default:
5805 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
5806 		fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
5807 
5808 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5809 		    "fcfi_pause_evt_action:%d. "
5810 		    "Invalid state. Terminated.",
5811 		    fcfp->fcf_index);
5812 		break;
5813 	}
5814 
5815 	return (rval);
5816 
5817 } /* emlxs_fcfi_pause_evt_action() */
5818 
5819 
5820 /*ARGSUSED*/
5821 static uint32_t
5822 emlxs_fcfi_unreg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp,
5823     uint32_t evt, void *arg1)
5824 {
5825 	uint32_t rval;
5826 
5827 	fcfp->attempts++;
5828 
5829 	if (fcfp->state != FCFI_STATE_UNREG_FAILED) {
5830 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5831 		    "fcfi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
5832 		    "Invalid state. Terminated.",
5833 		    fcfp->fcf_index,
5834 		    emlxs_fcfi_state_xlate(fcfp->state),
5835 		    emlxs_fcf_event_xlate(evt),
5836 		    arg1, fcfp->attempts);
5837 
5838 		return (1);
5839 	}
5840 
5841 	if ((fcfp->reason == FCF_REASON_SEND_FAILED) ||
5842 	    (fcfp->attempts >= 3)) {
5843 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5844 		    "fcfi_unreg_failed_action:%d attempt=%d reason=%x. "
5845 		    "Unreg cmpl.",
5846 		    fcfp->fcf_index,
5847 		    fcfp->attempts,
5848 		    fcfp->reason);
5849 
5850 		fcfp->flag &= ~EMLXS_FCFI_REG;
5851 
5852 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL,
5853 		    FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
5854 	} else {
5855 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5856 		    "fcfi_unreg_failed_action:%d attempt=%d. Unregistering.",
5857 		    fcfp->fcf_index,
5858 		    arg1, fcfp->attempts);
5859 
5860 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
5861 		    FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
5862 	}
5863 
5864 	return (rval);
5865 
5866 } /* emlxs_fcfi_unreg_failed_action() */
5867 
5868 
5869 /*ARGSUSED*/
5870 static uint32_t
5871 emlxs_fcfi_reg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
5872     void *arg1)
5873 {
5874 	uint32_t rval;
5875 
5876 	fcfp->attempts++;
5877 
5878 	if (fcfp->state != FCFI_STATE_REG_FAILED) {
5879 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5880 		    "fcfi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
5881 		    "Invalid state. Terminated.",
5882 		    fcfp->fcf_index,
5883 		    emlxs_fcfi_state_xlate(fcfp->state),
5884 		    emlxs_fcf_event_xlate(evt), arg1,
5885 		    fcfp->attempts);
5886 
5887 		return (1);
5888 	}
5889 
5890 	if ((fcfp->reason == FCF_REASON_SEND_FAILED) ||
5891 	    (fcfp->attempts >= 3)) {
5892 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5893 		    "fcfi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.",
5894 		    fcfp->fcf_index,
5895 		    fcfp->attempts,
5896 		    fcfp->reason);
5897 
5898 		fcfp->flag &= ~EMLXS_FCFI_REG;
5899 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
5900 		fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
5901 
5902 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL,
5903 		    FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
5904 	} else {
5905 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5906 		    "fcfi_reg_failed_action:%d attempt=%d. Registering.",
5907 		    fcfp->fcf_index,
5908 		    fcfp->attempts);
5909 
5910 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
5911 		    FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
5912 	}
5913 
5914 	return (rval);
5915 
5916 } /* emlxs_fcfi_reg_failed_action() */
5917 
5918 
5919 /*ARGSUSED*/
5920 static uint32_t
5921 emlxs_fcfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
5922 {
5923 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
5924 	MAILBOX4 *mb4;
5925 	FCFIobj_t *fcfp;
5926 
5927 	fcfp = (FCFIobj_t *)mbq->context;
5928 	mb4 = (MAILBOX4 *)mbq;
5929 
5930 	mutex_enter(&EMLXS_FCF_LOCK);
5931 
5932 	if (fcfp->state != FCFI_STATE_REG) {
5933 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5934 		    "fcfi_reg_mbcmpl:%d state=%s. Terminated.",
5935 		    fcfp->fcf_index,
5936 		    emlxs_fcfi_state_xlate(fcfp->state));
5937 
5938 		mutex_exit(&EMLXS_FCF_LOCK);
5939 		return (0);
5940 	}
5941 
5942 	if (mb4->mbxStatus) {
5943 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5944 		    "fcfi_reg_mbcmpl:%d failed. status=%x",
5945 		    fcfp->fcf_index,
5946 		    mb4->mbxStatus);
5947 
5948 		(void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
5949 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
5950 
5951 		mutex_exit(&EMLXS_FCF_LOCK);
5952 		return (0);
5953 	}
5954 
5955 	fcfp->FCFI = mb4->un.varRegFCFI.FCFI;
5956 
5957 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5958 	    "fcfi_reg_mbcmpl:%d Registered. FCFI=%d",
5959 	    fcfp->fcf_index,
5960 	    fcfp->FCFI);
5961 
5962 	fcfp->flag |= EMLXS_FCFI_REG;
5963 
5964 	(void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL,
5965 	    0, 0, 0);
5966 	mutex_exit(&EMLXS_FCF_LOCK);
5967 	return (0);
5968 
5969 } /* emlxs_fcfi_reg_mbcmpl() */
5970 
5971 
5972 /*ARGSUSED*/
5973 static uint32_t
5974 emlxs_fcfi_reg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
5975     void *arg1)
5976 {
5977 	emlxs_hba_t *hba = HBA;
5978 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
5979 	MAILBOX4 *mb4;
5980 	MAILBOXQ *mbq;
5981 	uint32_t rval;
5982 
5983 	if (fcfp->state != FCFI_STATE_REG) {
5984 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5985 		    "fcfi_reg_action:%d %s:%s arg=%p. "
5986 		    "Invalid state. Terminated.",
5987 		    fcfp->fcf_index,
5988 		    emlxs_fcfi_state_xlate(fcfp->state),
5989 		    emlxs_fcf_event_xlate(evt), arg1);
5990 		return (1);
5991 	}
5992 
5993 	if (!(fcfp->flag & EMLXS_FCFI_FCFTAB)) {
5994 		fcfp->flag |= EMLXS_FCFI_FCFTAB;
5995 		fcftab->fcfi_online++;
5996 	}
5997 
5998 	if (fcfp->prev_state != FCFI_STATE_REG_FAILED) {
5999 		fcfp->attempts = 0;
6000 	}
6001 
6002 	if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
6003 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6004 		    "fcfi_reg_action:%d attempts=%d. Offline requested.",
6005 		    fcfp->fcf_index,
6006 		    fcfp->attempts);
6007 
6008 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
6009 		return (rval);
6010 	}
6011 
6012 	if (fcfp->flag & EMLXS_FCFI_REG) {
6013 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6014 		    "fcfi_reg_action:%d. Already registered. Skipping reg.",
6015 		    fcfp->fcf_index);
6016 
6017 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
6018 		    FCF_REASON_EVENT, evt, arg1);
6019 		return (rval);
6020 	}
6021 
6022 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6023 	    "fcfi_reg_action:%d attempts=%d. Sending FCFI_REG.",
6024 	    fcfp->fcf_index,
6025 	    fcfp->attempts);
6026 
6027 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
6028 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
6029 		    FCF_REASON_NO_MBOX, 0, arg1);
6030 
6031 		return (rval);
6032 	}
6033 	mb4 = (MAILBOX4*)mbq;
6034 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
6035 
6036 	mbq->mbox_cmpl = emlxs_fcfi_reg_mbcmpl;
6037 	mbq->context = (void *)fcfp;
6038 	mbq->port = (void *)port;
6039 
6040 	mb4->mbxCommand = MBX_REG_FCFI;
6041 	mb4->mbxOwner = OWN_HOST;
6042 	mb4->un.varRegFCFI.FCFI = 0; /* FCFI will be returned by firmware */
6043 	mb4->un.varRegFCFI.InfoIndex = fcfp->fcf_index;
6044 
6045 	mb4->un.varRegFCFI.RQId0 = hba->sli.sli4.rq[EMLXS_FCFI_RQ0_INDEX].qid;
6046 	mb4->un.varRegFCFI.Id0_rctl_mask = EMLXS_FCFI_RQ0_RMASK;
6047 	mb4->un.varRegFCFI.Id0_rctl = EMLXS_FCFI_RQ0_RCTL;
6048 	mb4->un.varRegFCFI.Id0_type_mask = EMLXS_FCFI_RQ0_TMASK;
6049 	mb4->un.varRegFCFI.Id0_type = EMLXS_FCFI_RQ0_TYPE;
6050 
6051 	mb4->un.varRegFCFI.RQId1 = 0xffff;
6052 	mb4->un.varRegFCFI.RQId2 = 0xffff;
6053 	mb4->un.varRegFCFI.RQId3 = 0xffff;
6054 
6055 	if (fcfp->flag & EMLXS_FCFI_VLAN_ID) {
6056 		mb4->un.varRegFCFI.vv = 1;
6057 		mb4->un.varRegFCFI.vlanTag = fcfp->vlan_id;
6058 	}
6059 
6060 	/* Ignore the fcf record and force FPMA */
6061 	mb4->un.varRegFCFI.mam = EMLXS_REG_FCFI_MAM_FPMA;
6062 
6063 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
6064 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
6065 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
6066 
6067 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
6068 		    FCF_REASON_SEND_FAILED, rval, arg1);
6069 
6070 		return (rval);
6071 	}
6072 
6073 	return (0);
6074 
6075 } /* emlxs_fcfi_reg_action() */
6076 
6077 
6078 /*ARGSUSED*/
6079 static uint32_t
6080 emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
6081     void *arg1)
6082 {
6083 	uint32_t rval;
6084 
6085 	if (fcfp->state != FCFI_STATE_REG_CMPL) {
6086 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6087 		    "fcfi_reg_cmpl_action:%d %s:%s arg=%p. "
6088 		    "Invalid state. Terminated.",
6089 		    fcfp->fcf_index,
6090 		    emlxs_fcfi_state_xlate(fcfp->state),
6091 		    emlxs_fcf_event_xlate(evt), arg1);
6092 		return (1);
6093 	}
6094 
6095 	if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
6096 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6097 		    "fcfi_reg_cmpl_action:%d. Offline requested.",
6098 		    fcfp->fcf_index);
6099 
6100 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
6101 		return (rval);
6102 	}
6103 
6104 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6105 	    "fcfi_reg_cmpl_action:%d attempts=%d. Reg cmpl.",
6106 	    fcfp->fcf_index,
6107 	    fcfp->attempts);
6108 
6109 	rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
6110 	    FCF_REASON_EVENT, evt, arg1);
6111 
6112 	return (rval);
6113 
6114 } /* emlxs_fcfi_reg_cmpl_action() */
6115 
6116 
6117 /*ARGSUSED*/
6118 static uint32_t
6119 emlxs_fcfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
6120 {
6121 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
6122 	MAILBOX4 *mb4;
6123 	FCFIobj_t *fcfp;
6124 
6125 	fcfp = (FCFIobj_t *)mbq->context;
6126 	mb4 = (MAILBOX4 *)mbq;
6127 
6128 	mutex_enter(&EMLXS_FCF_LOCK);
6129 
6130 	if (fcfp->state != FCFI_STATE_UNREG) {
6131 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6132 		    "fcfi_unreg_mbcmpl:%d state=%s. Terminated.",
6133 		    fcfp->fcf_index,
6134 		    emlxs_fcfi_state_xlate(fcfp->state));
6135 
6136 		mutex_exit(&EMLXS_FCF_LOCK);
6137 		return (0);
6138 	}
6139 
6140 	if (mb4->mbxStatus) {
6141 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6142 		    "fcfi_unreg_mbcmpl:%d failed. status=%x",
6143 		    fcfp->fcf_index,
6144 		    mb4->mbxStatus);
6145 
6146 		(void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
6147 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
6148 
6149 		mutex_exit(&EMLXS_FCF_LOCK);
6150 		return (0);
6151 	}
6152 
6153 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6154 	    "fcfi_unreg_mbcmpl:%d Unregistered.",
6155 	    fcfp->fcf_index);
6156 
6157 	fcfp->flag &= ~EMLXS_FCFI_REG;
6158 	(void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL,
6159 	    0, 0, 0);
6160 
6161 	mutex_exit(&EMLXS_FCF_LOCK);
6162 	return (0);
6163 
6164 } /* emlxs_fcfi_unreg_mbcmpl() */
6165 
6166 
6167 /*ARGSUSED*/
6168 static uint32_t
6169 emlxs_fcfi_unreg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
6170     void *arg1)
6171 {
6172 	emlxs_hba_t *hba = HBA;
6173 	MAILBOX4 *mb4;
6174 	MAILBOXQ *mbq;
6175 	uint32_t rval;
6176 
6177 	if (fcfp->state != FCFI_STATE_UNREG) {
6178 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6179 		    "fcfi_unreg_action:%d %s:%s arg=%p. "
6180 		    "Invalid state. Terminated.",
6181 		    fcfp->fcf_index,
6182 		    emlxs_fcfi_state_xlate(fcfp->state),
6183 		    emlxs_fcf_event_xlate(evt), arg1);
6184 
6185 		return (1);
6186 	}
6187 
6188 	if (!(fcfp->flag & EMLXS_FCFI_REG)) {
6189 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6190 		    "fcfi_unreg_action:%d. Not registered. Skipping unreg.",
6191 		    fcfp->fcf_index);
6192 
6193 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
6194 		    FCF_REASON_EVENT, evt, arg1);
6195 		return (rval);
6196 	}
6197 
6198 	if (fcfp->prev_state != FCFI_STATE_UNREG_FAILED) {
6199 		fcfp->attempts = 0;
6200 	}
6201 
6202 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6203 	    "fcfi_unreg_action:%d attempts=%d. Sending FCFI_UNREG.",
6204 	    fcfp->fcf_index,
6205 	    fcfp->attempts);
6206 
6207 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
6208 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
6209 		    FCF_REASON_NO_MBOX, 0, arg1);
6210 		return (rval);
6211 	}
6212 	mb4 = (MAILBOX4*)mbq;
6213 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
6214 
6215 	mbq->mbox_cmpl = emlxs_fcfi_unreg_mbcmpl;
6216 	mbq->context = (void *)fcfp;
6217 	mbq->port = (void *)port;
6218 
6219 	mb4->mbxCommand = MBX_UNREG_FCFI;
6220 	mb4->mbxOwner = OWN_HOST;
6221 	mb4->un.varUnRegFCFI.FCFI = fcfp->FCFI;
6222 
6223 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
6224 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
6225 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
6226 
6227 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
6228 		    FCF_REASON_SEND_FAILED, rval, arg1);
6229 
6230 		return (rval);
6231 	}
6232 
6233 	return (0);
6234 
6235 } /* emlxs_fcfi_unreg_action() */
6236 
6237 
6238 /*ARGSUSED*/
6239 static uint32_t
6240 emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
6241     void *arg1)
6242 {
6243 	uint32_t rval;
6244 
6245 	if (fcfp->state != FCFI_STATE_UNREG_CMPL) {
6246 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6247 		    "fcfi_unreg_cmpl_action:%d %s:%s arg=%p. "
6248 		    "Invalid state. Terminated.",
6249 		    fcfp->fcf_index,
6250 		    emlxs_fcfi_state_xlate(fcfp->state),
6251 		    emlxs_fcf_event_xlate(evt), arg1);
6252 		return (1);
6253 	}
6254 
6255 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6256 	    "fcfi_unreg_cmpl_action:%d attempts=%d. Going offline.",
6257 	    fcfp->fcf_index,
6258 	    emlxs_fcfi_state_xlate(fcfp->state),
6259 	    emlxs_fcf_event_xlate(evt), arg1,
6260 	    fcfp->attempts);
6261 
6262 	rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
6263 	    FCF_REASON_EVENT, evt, arg1);
6264 
6265 	return (rval);
6266 
6267 } /* emlxs_fcfi_unreg_cmpl_action() */
6268 
6269 
6270 /*ARGSUSED*/
6271 static uint32_t
6272 emlxs_fcfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
6273     void *arg1)
6274 {
6275 	emlxs_hba_t *hba = HBA;
6276 	uint32_t rval;
6277 	VFIobj_t *vfip;
6278 	uint32_t i;
6279 
6280 	if (fcfp->state != FCFI_STATE_ONLINE) {
6281 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6282 		    "fcfi_online_action:%d %s:%s arg=%p. "
6283 		    "Invalid state. Terminated.",
6284 		    fcfp->fcf_index,
6285 		    emlxs_fcfi_state_xlate(fcfp->state),
6286 		    emlxs_fcf_event_xlate(evt), arg1);
6287 		return (1);
6288 	}
6289 
6290 	fcfp->flag &= ~EMLXS_FCFI_ONLINE_REQ;
6291 
6292 	if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
6293 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6294 		    "fcfi_online_action:%d attempts=%d. Offline requested.",
6295 		    fcfp->fcf_index,
6296 		    fcfp->attempts);
6297 
6298 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
6299 		return (1);
6300 	}
6301 
6302 	/* Online remaining VFI's for this FCFI */
6303 	vfip = hba->sli.sli4.VFI_table;
6304 	for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
6305 		if (vfip->fcfp != fcfp) {
6306 			continue;
6307 		}
6308 
6309 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6310 		    "fcfi_online_action:%d vfi_online=%d. Onlining VFI:%d.",
6311 		    fcfp->fcf_index,
6312 		    fcfp->vfi_online,
6313 		    vfip->VFI);
6314 
6315 		(void) emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
6316 	}
6317 
6318 	if (fcfp->prev_state != FCFI_STATE_ONLINE) {
6319 		/* Perform VSAN discovery check when first VFI goes online */
6320 		if (fcfp->vfi_online < FCFI_MAX_VFI_COUNT) {
6321 
6322 			/* Perform VSAN Discovery (TBD) */
6323 			/* For now we only need 1 VFI */
6324 
6325 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6326 			    "fcfi_online_action:%d vfi_online=%d. "
6327 			    "VSAN discovery required.",
6328 			    fcfp->fcf_index,
6329 			    fcfp->vfi_online);
6330 		}
6331 	}
6332 
6333 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6334 	    "fcfi_online_action:%d vfi_online=%d. "
6335 	    "FCFI online. Notifying fcftab.",
6336 	    fcfp->fcf_index,
6337 	    fcfp->vfi_online);
6338 
6339 	/* Notify FCFTAB */
6340 	rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_ONLINE, fcfp);
6341 
6342 	return (rval);
6343 
6344 } /* emlxs_fcfi_online_action() */
6345 
6346 
6347 /*ARGSUSED*/
6348 static int
6349 emlxs_fcf_configured(emlxs_port_t *port,  FCFIobj_t *fcfp)
6350 {
6351 	emlxs_hba_t *hba = HBA;
6352 	int i;
6353 	uint32_t entry_count;
6354 	uint32_t valid_entry;
6355 	uint32_t match_found;
6356 	uint16_t VLanId;
6357 	FCF_RECORD_t *fcfrec = &fcfp->fcf_rec;
6358 	uint32_t j;
6359 	uint32_t k;
6360 
6361 	/* Init the primary flag, we may set it later */
6362 	fcfp->flag &= ~(EMLXS_FCFI_PRIMARY|EMLXS_FCFI_BOOT);
6363 
6364 	if (!(hba->flag & FC_FIP_SUPPORTED)) {
6365 		if (!hba->sli.sli4.cfgFCOE.length) {
6366 			/* Nothing specified, so everything matches */
6367 			/* For nonFIP only use index 0 */
6368 			if (fcfrec->fcf_index == 0) {
6369 				return (1);  /* success */
6370 			}
6371 			return (0);
6372 		}
6373 
6374 		/* Just check FCMap for now */
6375 		if (bcmp((char *)fcfrec->fc_map,
6376 		    hba->sli.sli4.cfgFCOE.FCMap, 3) == 0) {
6377 			return (1);  /* success */
6378 		}
6379 		return (0);
6380 	}
6381 
6382 	/* For FIP mode, the FCF record must match Config Region 23 */
6383 
6384 	entry_count = (hba->sli.sli4.cfgFCF.length * sizeof (uint32_t)) /
6385 	    sizeof (tlv_fcfconnectentry_t);
6386 	valid_entry = 0;
6387 	match_found = 0;
6388 
6389 	for (i = 0; i < entry_count; i++) {
6390 
6391 		if (!hba->sli.sli4.cfgFCF.entry[i].Valid) {
6392 			continue;
6393 		}
6394 
6395 		if (hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) {
6396 			valid_entry = 1;
6397 
6398 			if (bcmp((char *)fcfrec->fabric_name_identifier,
6399 			    hba->sli.sli4.cfgFCF.entry[i].FabricName, 8)) {
6400 				match_found = 0;
6401 				continue;
6402 			}
6403 
6404 			match_found = 1;
6405 		}
6406 
6407 		if (hba->sli.sli4.cfgFCF.entry[i].SwitchNameValid) {
6408 			valid_entry = 1;
6409 
6410 			if (bcmp((char *)fcfrec->switch_name_identifier,
6411 			    hba->sli.sli4.cfgFCF.entry[i].SwitchName, 8)) {
6412 				match_found = 0;
6413 				continue;
6414 			}
6415 
6416 			match_found = 1;
6417 		}
6418 
6419 		if (hba->sli.sli4.cfgFCF.entry[i].VLanValid) {
6420 			valid_entry = 1;
6421 
6422 			if (!(fcfp->flag & EMLXS_FCFI_VLAN_ID)) {
6423 				match_found = 0;
6424 				continue;
6425 			}
6426 
6427 			VLanId = hba->sli.sli4.cfgFCF.entry[i].VLanId;
6428 			j = VLanId / 8;
6429 			k = 1 << (VLanId % 8);
6430 
6431 			if (!(fcfrec->vlan_bitmap[j] & k)) {
6432 				match_found = 0;
6433 				continue;
6434 			}
6435 
6436 			/* Assign requested vlan_id to this FCF */
6437 			fcfp->vlan_id = VLanId;
6438 
6439 			match_found = 1;
6440 		}
6441 
6442 		/* If a match was found */
6443 		if (match_found) {
6444 			if (hba->sli.sli4.cfgFCF.entry[i].Primary) {
6445 				fcfp->flag |= EMLXS_FCFI_PRIMARY;
6446 			}
6447 			if (hba->sli.sli4.cfgFCF.entry[i].Boot) {
6448 				fcfp->flag |= EMLXS_FCFI_BOOT;
6449 			}
6450 			return (1);
6451 		}
6452 	}
6453 
6454 	/* If no valid entries found, then allow any fabric */
6455 	if (!valid_entry) {
6456 		return (1);
6457 	}
6458 
6459 	return (0);
6460 
6461 } /* emlxs_fcf_configured() */
6462 
6463 
6464 static void
6465 emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp, FCF_RECORD_t *fcf_rec,
6466     uint32_t event_tag)
6467 {
6468 	emlxs_hba_t	*hba = HBA;
6469 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
6470 	uint16_t	i;
6471 
6472 	bcopy((char *)fcf_rec, &fcfp->fcf_rec, sizeof (FCF_RECORD_t));
6473 	fcfp->fcf_index = fcf_rec->fcf_index;
6474 
6475 	/* Clear VLAN info */
6476 	fcfp->vlan_id = 0;
6477 	fcfp->flag &= ~EMLXS_FCFI_VLAN_ID;
6478 
6479 	/* Check if fcf is a member of a VLAN */
6480 	for (i = 0; i < 4096; i++) {
6481 		if (fcf_rec->vlan_bitmap[i / 8] & (1 << (i % 8))) {
6482 			/* For now assign the VLAN id of the first VLAN found */
6483 			fcfp->vlan_id = i;
6484 			fcfp->flag |= EMLXS_FCFI_VLAN_ID;
6485 			break;
6486 		}
6487 	}
6488 
6489 	if (fcf_rec->fcf_available) {
6490 		fcfp->flag |= EMLXS_FCFI_AVAILABLE;
6491 	} else {
6492 		fcfp->flag &= ~EMLXS_FCFI_AVAILABLE;
6493 	}
6494 
6495 	if (fcf_rec->fcf_valid) {
6496 		fcfp->flag |= EMLXS_FCFI_VALID;
6497 	} else {
6498 		fcfp->flag &= ~EMLXS_FCFI_VALID;
6499 	}
6500 
6501 	/* Check config region 23 */
6502 	/* Also sets BOOT and PRIMARY cfg bits as needed */
6503 	if (emlxs_fcf_configured(port, fcfp)) {
6504 		fcfp->flag |= EMLXS_FCFI_CONFIGURED;
6505 	} else {
6506 		fcfp->flag &= ~EMLXS_FCFI_CONFIGURED;
6507 	}
6508 
6509 	/* Set fcfp priority.  Used by selection alogithm */
6510 	/* Combination of BOOT:PRIMARY:~fip_priority */
6511 	fcfp->priority  = (fcfp->flag & EMLXS_FCFI_BOOT)? 0x200:0;
6512 	fcfp->priority |= (fcfp->flag & EMLXS_FCFI_PRIMARY)? 0x100:0;
6513 	fcfp->priority |= ~(fcf_rec->fip_priority & 0xff);
6514 
6515 	fcfp->event_tag  = event_tag;
6516 	fcfp->generation = fcftab->generation;
6517 	fcfp->flag |= EMLXS_FCFI_FRESH;
6518 
6519 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6520 	    "fcfi:%d gen=%x tag=%x flag=%x avl=%x val=%x state=%x "
6521 	    "map=%x pri=%x vid=%x",
6522 	    fcf_rec->fcf_index,
6523 	    fcfp->generation,
6524 	    fcfp->event_tag,
6525 	    fcfp->flag,
6526 	    fcf_rec->fcf_available,
6527 	    fcf_rec->fcf_valid,
6528 	    fcf_rec->fcf_state,
6529 	    fcf_rec->mac_address_provider,
6530 	    fcfp->priority,
6531 	    fcfp->vlan_id);
6532 
6533 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6534 	    "fcfi:%d mac=%02x:%02x:%02x:%02x:%02x:%02x "
6535 	    "fabric=%02x%02x%02x%02x%02x%02x%02x%02x "
6536 	    "switch=%02x%02x%02x%02x%02x%02x%02x%02x",
6537 	    fcfp->fcf_index,
6538 	    fcf_rec->fcf_mac_address_hi[0],
6539 	    fcf_rec->fcf_mac_address_hi[1],
6540 	    fcf_rec->fcf_mac_address_hi[2],
6541 	    fcf_rec->fcf_mac_address_hi[3],
6542 	    fcf_rec->fcf_mac_address_low[0],
6543 	    fcf_rec->fcf_mac_address_low[1],
6544 
6545 	    fcf_rec->fabric_name_identifier[0],
6546 	    fcf_rec->fabric_name_identifier[1],
6547 	    fcf_rec->fabric_name_identifier[2],
6548 	    fcf_rec->fabric_name_identifier[3],
6549 	    fcf_rec->fabric_name_identifier[4],
6550 	    fcf_rec->fabric_name_identifier[5],
6551 	    fcf_rec->fabric_name_identifier[6],
6552 	    fcf_rec->fabric_name_identifier[7],
6553 
6554 	    fcf_rec->switch_name_identifier[0],
6555 	    fcf_rec->switch_name_identifier[1],
6556 	    fcf_rec->switch_name_identifier[2],
6557 	    fcf_rec->switch_name_identifier[3],
6558 	    fcf_rec->switch_name_identifier[4],
6559 	    fcf_rec->switch_name_identifier[5],
6560 	    fcf_rec->switch_name_identifier[6],
6561 	    fcf_rec->switch_name_identifier[7]);
6562 
6563 	return;
6564 
6565 } /* emlxs_fcfi_update() */
6566 
6567 
6568 /* ************************************************************************** */
6569 /* VFI */
6570 /* ************************************************************************** */
6571 
6572 static char *
6573 emlxs_vfi_state_xlate(uint32_t state)
6574 {
6575 	static char buffer[32];
6576 	uint32_t i;
6577 	uint32_t count;
6578 
6579 	count = sizeof (emlxs_vfi_state_table) / sizeof (emlxs_table_t);
6580 	for (i = 0; i < count; i++) {
6581 		if (state == emlxs_vfi_state_table[i].code) {
6582 			return (emlxs_vfi_state_table[i].string);
6583 		}
6584 	}
6585 
6586 	(void) sprintf(buffer, "state=0x%x", state);
6587 	return (buffer);
6588 
6589 } /* emlxs_vfi_state_xlate() */
6590 
6591 
6592 static uint32_t
6593 emlxs_vfi_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
6594     void *arg1)
6595 {
6596 	uint32_t rval;
6597 	uint32_t(*func) (emlxs_port_t *, VFIobj_t *, uint32_t, void *);
6598 	uint32_t index;
6599 	uint32_t events;
6600 	uint16_t state;
6601 
6602 	/* Convert event to action table index */
6603 	switch (evt) {
6604 	case FCF_EVENT_STATE_ENTER:
6605 		index = 0;
6606 		break;
6607 	case FCF_EVENT_VFI_ONLINE:
6608 		index = 1;
6609 		break;
6610 	case FCF_EVENT_VFI_OFFLINE:
6611 		index = 2;
6612 		break;
6613 	case FCF_EVENT_VFI_PAUSE:
6614 		index = 3;
6615 		break;
6616 	case FCF_EVENT_VPI_ONLINE:
6617 		index = 4;
6618 		break;
6619 	case FCF_EVENT_VPI_OFFLINE:
6620 		index = 5;
6621 		break;
6622 	default:
6623 		return (1);
6624 	}
6625 
6626 	events = VFI_ACTION_EVENTS;
6627 	state  = vfip->state;
6628 
6629 	index += (state * events);
6630 	func   = (uint32_t(*) (emlxs_port_t *, VFIobj_t *, uint32_t, void *))
6631 	    emlxs_vfi_action_table[index];
6632 
6633 	if (!func) {
6634 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
6635 		    "vfi:%d %s:%s arg=%p. No action. Terminated.",
6636 		    vfip->VFI,
6637 		    emlxs_vfi_state_xlate(state),
6638 		    emlxs_fcf_event_xlate(evt), arg1);
6639 
6640 		return (1);
6641 	}
6642 
6643 	rval = (func)(port, vfip, evt, arg1);
6644 
6645 	return (rval);
6646 
6647 } /* emlxs_vfi_action() */
6648 
6649 
6650 static uint32_t
6651 emlxs_vfi_event(emlxs_port_t *port, uint32_t evt,
6652     void *arg1)
6653 {
6654 	VPIobj_t *vpip = NULL;
6655 	VFIobj_t *vfip = NULL;
6656 	uint32_t rval = 0;
6657 
6658 	/* Filter events and acquire fcfi context */
6659 	switch (evt) {
6660 	case FCF_EVENT_VPI_ONLINE:
6661 	case FCF_EVENT_VPI_OFFLINE:
6662 		vpip = (VPIobj_t *)arg1;
6663 
6664 		if (!vpip) {
6665 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
6666 			    "vfi: %s arg=%p. Null VPI found. Terminated.",
6667 			    emlxs_fcf_event_xlate(evt), arg1);
6668 
6669 			return (1);
6670 		}
6671 
6672 		vfip = vpip->vfip;
6673 
6674 		if (!vfip) {
6675 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
6676 			    "vfi: %s arg=%p. VFI not found. Terminated.",
6677 			    emlxs_fcf_event_xlate(evt), arg1);
6678 
6679 			return (1);
6680 		}
6681 		break;
6682 
6683 	case FCF_EVENT_VFI_ONLINE:
6684 	case FCF_EVENT_VFI_OFFLINE:
6685 	case FCF_EVENT_VFI_PAUSE:
6686 		vfip = (VFIobj_t *)arg1;
6687 
6688 		if (!vfip) {
6689 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
6690 			    "vfi: %s arg=%p. VFI not found. Terminated.",
6691 			    emlxs_fcf_event_xlate(evt), arg1);
6692 
6693 			return (1);
6694 		}
6695 		break;
6696 
6697 	default:
6698 		return (1);
6699 	}
6700 
6701 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
6702 	    "vfi:%d %s:%s arg=%p",
6703 	    vfip->VFI,
6704 	    emlxs_vfi_state_xlate(vfip->state),
6705 	    emlxs_fcf_event_xlate(evt), arg1);
6706 
6707 	rval = emlxs_vfi_action(port, vfip, evt, arg1);
6708 
6709 	return (rval);
6710 
6711 } /* emlxs_vfi_event() */
6712 
6713 
6714 /*ARGSUSED*/
6715 static uint32_t
6716 emlxs_vfi_state(emlxs_port_t *port, VFIobj_t *vfip, uint16_t state,
6717     uint16_t reason, uint32_t explain, void *arg1)
6718 {
6719 	uint32_t rval;
6720 
6721 	if (state >= VFI_ACTION_STATES) {
6722 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6723 		    "vfi_state:%d %s. "
6724 		    "Invalid state. Terminated.",
6725 		    vfip->VFI,
6726 		    emlxs_vfi_state_xlate(vfip->state));
6727 
6728 		return (1);
6729 	}
6730 
6731 	if ((vfip->state == state) &&
6732 	    (reason != FCF_REASON_REENTER)) {
6733 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6734 		    "vfi_state:%d %s:%s:0x%x arg=%p. "
6735 		    "State not changed. Terminated.",
6736 		    vfip->VFI,
6737 		    emlxs_vfi_state_xlate(vfip->state),
6738 		    emlxs_fcf_reason_xlate(reason),
6739 		    explain, arg1);
6740 
6741 		return (1);
6742 	}
6743 
6744 	if (!reason) {
6745 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
6746 		    "vfi:%d %s-->%s arg=%p",
6747 		    vfip->VFI,
6748 		    emlxs_vfi_state_xlate(vfip->state),
6749 		    emlxs_vfi_state_xlate(state), arg1);
6750 	} else if (reason == FCF_REASON_EVENT) {
6751 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
6752 		    "vfi:%d %s-->%s:%s:%s arg=%p",
6753 		    vfip->VFI,
6754 		    emlxs_vfi_state_xlate(vfip->state),
6755 		    emlxs_vfi_state_xlate(state),
6756 		    emlxs_fcf_reason_xlate(reason),
6757 		    emlxs_fcf_event_xlate(explain), arg1);
6758 	} else if (explain) {
6759 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
6760 		    "vfi:%d %s-->%s:%s:0x%x arg=%p",
6761 		    vfip->VFI,
6762 		    emlxs_vfi_state_xlate(vfip->state),
6763 		    emlxs_vfi_state_xlate(state),
6764 		    emlxs_fcf_reason_xlate(reason),
6765 		    explain, arg1);
6766 	} else {
6767 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
6768 		    "vfi:%d %s-->%s:%s arg=%p",
6769 		    vfip->VFI,
6770 		    emlxs_vfi_state_xlate(vfip->state),
6771 		    emlxs_vfi_state_xlate(state),
6772 		    emlxs_fcf_reason_xlate(reason), arg1);
6773 	}
6774 
6775 	vfip->prev_state = vfip->state;
6776 	vfip->prev_reason = vfip->reason;
6777 	vfip->state = state;
6778 	vfip->reason = reason;
6779 
6780 	rval = emlxs_vfi_action(port, vfip, FCF_EVENT_STATE_ENTER, arg1);
6781 
6782 	return (rval);
6783 
6784 } /* emlxs_vfi_state() */
6785 
6786 
6787 /*ARGSUSED*/
6788 static uint32_t
6789 emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip,
6790     uint32_t evt, void *arg1)
6791 {
6792 	uint32_t rval;
6793 
6794 	if (evt != FCF_EVENT_VPI_ONLINE) {
6795 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6796 		    "vfi_vpi_online_evt_action:%d %s:%s arg=%p flag=%x. "
6797 		    "Invalid event type. Terminated.",
6798 		    vfip->VFI,
6799 		    emlxs_vfi_state_xlate(vfip->state),
6800 		    emlxs_fcf_event_xlate(evt), arg1,
6801 		    vfip->flag);
6802 
6803 		return (1);
6804 	}
6805 
6806 	switch (vfip->state) {
6807 	case VFI_STATE_ONLINE:
6808 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6809 		    "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. "
6810 		    "Reentering online.",
6811 		    vfip->VFI,
6812 		    vfip->flag,
6813 		    vfip->vpi_online);
6814 
6815 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
6816 		    FCF_REASON_REENTER, evt, arg1);
6817 		break;
6818 
6819 	case VFI_STATE_VPI_ONLINE:
6820 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6821 		    "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. "
6822 		    "Online cmpl.",
6823 		    vfip->VFI,
6824 		    vfip->flag,
6825 		    vfip->vpi_online);
6826 
6827 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE_CMPL,
6828 		    FCF_REASON_EVENT, evt, arg1);
6829 		break;
6830 
6831 	default:
6832 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6833 		    "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. "
6834 		    "Terminated.",
6835 		    vfip->VFI,
6836 		    vfip->flag,
6837 		    vfip->vpi_online);
6838 
6839 		return (1);
6840 	}
6841 
6842 	return (rval);
6843 
6844 } /* emlxs_vfi_vpi_online_evt_action() */
6845 
6846 
6847 /*ARGSUSED*/
6848 static uint32_t
6849 emlxs_vfi_offline_handler(emlxs_port_t *port, VFIobj_t *vfip, void *arg1)
6850 {
6851 	uint32_t rval;
6852 
6853 	if (!(vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
6854 		return (0);
6855 	}
6856 
6857 	if (vfip->vpi_online > 0) {
6858 		if (vfip->flag & EMLXS_VFI_PAUSE_REQ) {
6859 			rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED,
6860 			    FCF_REASON_REQUESTED, 0, arg1);
6861 		} else {
6862 			rval = emlxs_vfi_state(port, vfip,
6863 			    VFI_STATE_VPI_OFFLINE, FCF_REASON_REQUESTED,
6864 			    0, arg1);
6865 		}
6866 
6867 	} else if (vfip->flag & EMLXS_VFI_REG) {
6868 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
6869 		    FCF_REASON_REQUESTED, 0, arg1);
6870 
6871 	} else if (vfip->flag & EMLXS_VFI_INIT) {
6872 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
6873 		    FCF_REASON_REQUESTED, 0, arg1);
6874 
6875 	} else {
6876 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
6877 		    FCF_REASON_REQUESTED, 0, arg1);
6878 	}
6879 
6880 	return (rval);
6881 
6882 } /* emlxs_vfi_offline_handler() */
6883 
6884 
6885 /*ARGSUSED*/
6886 static uint32_t
6887 emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip,
6888     uint32_t evt, void *arg1)
6889 {
6890 	uint32_t rval;
6891 	VPIobj_t *vpip;
6892 
6893 	if (evt != FCF_EVENT_VPI_OFFLINE) {
6894 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6895 		    "vfi_vpi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
6896 		    "Invalid event type. Terminated.",
6897 		    vfip->VFI,
6898 		    emlxs_vfi_state_xlate(vfip->state),
6899 		    emlxs_fcf_event_xlate(evt), arg1,
6900 		    vfip->flag);
6901 		return (1);
6902 	}
6903 
6904 	/* Disconnect VPI object from VFI */
6905 	vpip = (VPIobj_t *)arg1;
6906 	vpip->vfip = NULL;
6907 
6908 	switch (vfip->state) {
6909 	case VFI_STATE_ONLINE:
6910 	case VFI_STATE_VPI_ONLINE:
6911 		if (vfip->vpi_online == 0) {
6912 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6913 			    "vfi_vpi_offline_evt_action:%d flag=%x "
6914 			    "vpi_online=%d. Offlining.",
6915 			    vfip->VFI,
6916 			    vfip->flag, vfip->vpi_online);
6917 
6918 			vfip->flag &= ~EMLXS_VFI_REQ_MASK;
6919 			vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
6920 			rval = emlxs_vfi_offline_handler(port, vfip, arg1);
6921 		} else {
6922 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6923 			    "vfi_vpi_offline_evt_action:%d flag=%x "
6924 			    "vpi_online=%d. Terminated.",
6925 			    vfip->VFI,
6926 			    vfip->flag, vfip->vpi_online);
6927 		}
6928 		break;
6929 
6930 	case VFI_STATE_PAUSED:
6931 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6932 		    "vfi_vpi_offline_evt_action:%d flag=%x vpi_online=%d. "
6933 		    "Terminated.",
6934 		    vfip->VFI,
6935 		    vfip->flag, vfip->vpi_online);
6936 		break;
6937 
6938 	case VFI_STATE_VPI_OFFLINE:
6939 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6940 		    "vfi_vpi_offline_evt_action:%d flag=%x. VPI offline cmpl.",
6941 		    vfip->VFI,
6942 		    vfip->flag);
6943 
6944 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL,
6945 		    FCF_REASON_EVENT, evt, arg1);
6946 		break;
6947 
6948 	case VFI_STATE_VPI_OFFLINE_CMPL:
6949 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6950 		    "vfi_vpi_offline_evt_action:%d flag=%x. VPI offline cmpl.",
6951 		    vfip->VFI,
6952 		    vfip->flag);
6953 
6954 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL,
6955 		    FCF_REASON_REENTER, evt, arg1);
6956 		break;
6957 
6958 	default:
6959 		if (vfip->vpi_online == 0) {
6960 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6961 			    "vfi_vpi_offline_evt_action:%d flag=%x "\
6962 			    "vpi_online=%d. Requesting offline.",
6963 			    vfip->VFI,
6964 			    vfip->flag, vfip->vpi_online);
6965 
6966 			vfip->flag &= ~EMLXS_VFI_REQ_MASK;
6967 			vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
6968 		} else {
6969 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6970 			    "vfi_vpi_offline_evt_action:%d flag=%x "\
6971 			    "vpi_online=%d. Terminated.",
6972 			    vfip->VFI,
6973 			    vfip->flag, vfip->vpi_online);
6974 		}
6975 		return (1);
6976 	}
6977 
6978 	return (rval);
6979 
6980 } /* emlxs_vfi_vpi_offline_evt_action() */
6981 
6982 
6983 /*ARGSUSED*/
6984 static uint32_t
6985 emlxs_vfi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
6986     void *arg1)
6987 {
6988 	emlxs_hba_t *hba = HBA;
6989 	emlxs_port_t *vport;
6990 	VPIobj_t *vpip;
6991 	uint32_t rval = 0;
6992 	uint32_t i;
6993 
6994 	if (evt != FCF_EVENT_VFI_ONLINE) {
6995 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6996 		    "vfi_online_evt_action:%d %s:%s arg=%p flag=%x. "
6997 		    "Invalid event type. Terminated.",
6998 		    vfip->VFI,
6999 		    emlxs_vfi_state_xlate(vfip->state),
7000 		    emlxs_fcf_event_xlate(evt), arg1,
7001 		    vfip->flag);
7002 		return (1);
7003 	}
7004 
7005 	if (vfip->flag & EMLXS_VFI_ONLINE_REQ) {
7006 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7007 		    "vfi_online_evt_action:%d flag=%x. "
7008 		    "Online already requested. Terminated.",
7009 		    vfip->VFI,
7010 		    vfip->flag);
7011 		return (0);
7012 	}
7013 
7014 	vfip->flag &= ~EMLXS_VFI_REQ_MASK;
7015 	vfip->flag |= EMLXS_VFI_ONLINE_REQ;
7016 
7017 	switch (vfip->state) {
7018 	case VFI_STATE_OFFLINE:
7019 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7020 		    "vfi_online_evt_action:%d flag=%x. Initiating online.",
7021 		    vfip->VFI,
7022 		    vfip->flag);
7023 
7024 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
7025 		    FCF_REASON_EVENT, evt, arg1);
7026 		break;
7027 
7028 	case VFI_STATE_VPI_OFFLINE:
7029 	case VFI_STATE_PAUSED:
7030 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7031 		    "vfi_online_evt_action:%d flag=%x. Initiating online.",
7032 		    vfip->VFI,
7033 		    vfip->flag);
7034 
7035 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
7036 		    FCF_REASON_EVENT, evt, arg1);
7037 		break;
7038 
7039 	case VFI_STATE_ONLINE:
7040 		/* Online all VPI's belonging to this vfi */
7041 		for (i = 0; i <= hba->vpi_max; i++) {
7042 			vport = &VPORT(i);
7043 			vpip = &vport->VPIobj;
7044 
7045 			if (!(vport->flag & EMLXS_PORT_BOUND)) {
7046 				continue;
7047 			}
7048 
7049 			if (vpip->vfip != vfip) {
7050 				continue;
7051 			}
7052 
7053 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7054 			    "vfi_online_evt_action:%d. Onlining VPI:%d",
7055 			    vfip->VFI,
7056 			    vpip->VPI);
7057 
7058 			(void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE,
7059 			    vpip);
7060 		}
7061 		break;
7062 
7063 	default:
7064 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7065 		    "vfi_online_evt_action:%d flag=%x. Terminated.",
7066 		    vfip->VFI,
7067 		    vfip->flag);
7068 		return (1);
7069 	}
7070 
7071 	return (rval);
7072 
7073 } /* emlxs_vfi_online_evt_action() */
7074 
7075 
7076 /*ARGSUSED*/
7077 static uint32_t
7078 emlxs_vfi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7079     void *arg1)
7080 {
7081 	uint32_t rval = 0;
7082 
7083 	if (evt != FCF_EVENT_VFI_OFFLINE) {
7084 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7085 		    "vfi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
7086 		    "Invalid event type. Terminated.",
7087 		    vfip->VFI,
7088 		    emlxs_vfi_state_xlate(vfip->state),
7089 		    emlxs_fcf_event_xlate(evt), arg1,
7090 		    vfip->flag);
7091 		return (1);
7092 	}
7093 
7094 	if ((vfip->flag & EMLXS_VFI_OFFLINE_REQ) &&
7095 	    !(vfip->flag & EMLXS_VFI_PAUSE_REQ)) {
7096 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7097 		    "vfi_offline_evt_action:%d flag=%x. "
7098 		    "Offline already requested. Terminated.",
7099 		    vfip->VFI,
7100 		    vfip->flag);
7101 		return (0);
7102 	}
7103 
7104 	switch (vfip->state) {
7105 	case VFI_STATE_OFFLINE:
7106 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7107 		    "vfi_offline_evt_action:%d flag=%x. "
7108 		    "Already offline. Terminated.",
7109 		    vfip->VFI,
7110 		    vfip->flag);
7111 		break;
7112 
7113 	/* Wait states */
7114 	case VFI_STATE_VPI_ONLINE:
7115 	case VFI_STATE_VPI_OFFLINE:
7116 	case VFI_STATE_VPI_OFFLINE_CMPL:
7117 	case VFI_STATE_INIT:
7118 	case VFI_STATE_REG:
7119 	case VFI_STATE_ONLINE:
7120 	case VFI_STATE_PAUSED:
7121 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
7122 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
7123 
7124 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7125 		    "vfi_offline_evt_action:%d flag=%x.  Handling offline.",
7126 		    vfip->VFI,
7127 		    vfip->flag);
7128 
7129 		/* Handle offline now */
7130 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
7131 		break;
7132 
7133 	default:
7134 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
7135 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
7136 
7137 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7138 		    "vfi_offline_evt_action:%d flag=%x. Terminated.",
7139 		    vfip->VFI,
7140 		    vfip->flag);
7141 		break;
7142 	}
7143 
7144 	return (rval);
7145 
7146 } /* emlxs_vfi_offline_evt_action() */
7147 
7148 
7149 /*ARGSUSED*/
7150 static uint32_t
7151 emlxs_vfi_pause_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7152     void *arg1)
7153 {
7154 	uint32_t rval = 0;
7155 
7156 	if (evt != FCF_EVENT_VFI_PAUSE) {
7157 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7158 		    "vfi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
7159 		    "Invalid event type. Terminated.",
7160 		    vfip->VFI,
7161 		    emlxs_vfi_state_xlate(vfip->state),
7162 		    emlxs_fcf_event_xlate(evt), arg1,
7163 		    vfip->flag);
7164 		return (1);
7165 	}
7166 
7167 	if (vfip->flag & EMLXS_VFI_PAUSE_REQ) {
7168 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7169 		    "vfi_pause_evt_action:%d flag=%x. "
7170 		    "Pause already requested. Terminated.",
7171 		    vfip->VFI,
7172 		    vfip->flag);
7173 		return (0);
7174 	}
7175 
7176 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
7177 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7178 		    "vfi_pause_evt_action:%d flag=%x. "
7179 		    "Offline already requested. Terminated.",
7180 		    vfip->VFI,
7181 		    vfip->flag);
7182 		return (0);
7183 	}
7184 
7185 	switch (vfip->state) {
7186 	case VFI_STATE_OFFLINE:
7187 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7188 		    "vfi_pause_evt_action:%d flag=%x. "
7189 		    "Already offline. Terminated.",
7190 		    vfip->VFI,
7191 		    vfip->flag);
7192 		break;
7193 
7194 	case VFI_STATE_PAUSED:
7195 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7196 		    "vfi_pause_evt_action:%d flag=%x. "
7197 		    "Already paused. Terminated.",
7198 		    vfip->VFI,
7199 		    vfip->flag);
7200 		break;
7201 
7202 	/* Wait states */
7203 	case VFI_STATE_VPI_ONLINE:
7204 	case VFI_STATE_VPI_OFFLINE_CMPL:
7205 	case VFI_STATE_INIT:
7206 	case VFI_STATE_REG:
7207 	case VFI_STATE_ONLINE:
7208 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
7209 		vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
7210 
7211 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7212 		    "vfi_pause_evt_action:%d flag=%x. Handling offline.",
7213 		    vfip->VFI,
7214 		    vfip->flag);
7215 
7216 		/* Handle offline now */
7217 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
7218 		break;
7219 
7220 	default:
7221 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
7222 		vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
7223 
7224 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7225 		    "vfi_pause_evt_action:%d flag=%x. Terminated.",
7226 		    vfip->VFI,
7227 		    vfip->flag);
7228 		break;
7229 	}
7230 
7231 	return (rval);
7232 
7233 } /* emlxs_vfi_pause_evt_action() */
7234 
7235 
7236 /*ARGSUSED*/
7237 static uint32_t
7238 emlxs_vfi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7239     void *arg1)
7240 {
7241 	uint32_t rval;
7242 
7243 	if (vfip->state != VFI_STATE_OFFLINE) {
7244 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7245 		    "vfi_offline_action:%d %s:%s arg=%p. "
7246 		    "Invalid state. Terminated.",
7247 		    vfip->VFI,
7248 		    emlxs_vfi_state_xlate(vfip->state),
7249 		    emlxs_fcf_event_xlate(evt), arg1);
7250 		return (1);
7251 	}
7252 
7253 	if (!vfip->fcfp) {
7254 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7255 		    "vfi_offline_action:%d %s:%s arg=%p flag=%x. "
7256 		    "Null fcfp found. Terminated.",
7257 		    vfip->VFI,
7258 		    emlxs_vfi_state_xlate(vfip->state),
7259 		    emlxs_fcf_event_xlate(evt), arg1,
7260 		    vfip->flag);
7261 		return (1);
7262 	}
7263 
7264 	vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
7265 
7266 	if (vfip->prev_state == VFI_STATE_OFFLINE) {
7267 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7268 		    "vfi_offline_action:%d vfi_online=%d. Terminated.",
7269 		    vfip->VFI,
7270 		    vfip->fcfp->vfi_online);
7271 
7272 		return (0);
7273 	}
7274 
7275 	if (vfip->vpi_online) {
7276 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7277 		    "vfi_offline_action:%d vpi_online=%d. VPI's still online.",
7278 		    vfip->VFI,
7279 		    vfip->vpi_online);
7280 	}
7281 
7282 	if (vfip->flag & EMLXS_VFI_FCFI) {
7283 		vfip->flag &= ~EMLXS_VFI_FCFI;
7284 
7285 		if (vfip->fcfp->vfi_online) {
7286 			vfip->fcfp->vfi_online--;
7287 		}
7288 	}
7289 
7290 	/* Check if online was requested */
7291 	if (vfip->flag & EMLXS_VFI_ONLINE_REQ) {
7292 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7293 		    "vfi_offline_action:%d vfi_online=%d. Online requested.",
7294 		    vfip->VFI,
7295 		    vfip->fcfp->vfi_online);
7296 
7297 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
7298 		    FCF_REASON_REQUESTED, 0, arg1);
7299 		return (rval);
7300 	}
7301 
7302 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7303 	    "vfi_offline_action:%d vfi_online=%d. "
7304 	    "VFI offline. Notifying FCFI:%d",
7305 	    vfip->VFI,
7306 	    vfip->fcfp->vfi_online,
7307 	    vfip->fcfp->fcf_index);
7308 
7309 	/* Notify FCFI */
7310 	rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip);
7311 
7312 	return (rval);
7313 
7314 } /* emlxs_vfi_offline_action() */
7315 
7316 
7317 /*ARGSUSED*/
7318 static uint32_t
7319 emlxs_vfi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
7320 {
7321 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
7322 	VFIobj_t *vfip;
7323 	MAILBOX4 *mb4;
7324 
7325 	vfip = (VFIobj_t *)mbq->context;
7326 	mb4 = (MAILBOX4 *)mbq;
7327 
7328 	mutex_enter(&EMLXS_FCF_LOCK);
7329 
7330 	if (vfip->state != VFI_STATE_INIT) {
7331 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7332 		    "vfi_init_mbcmpl:%d %s. Terminated.",
7333 		    vfip->VFI,
7334 		    emlxs_vfi_state_xlate(vfip->state));
7335 
7336 		mutex_exit(&EMLXS_FCF_LOCK);
7337 		return (0);
7338 	}
7339 
7340 	if (mb4->mbxStatus) {
7341 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7342 		    "vfi_init_mbcmpl:%d failed. status=%x",
7343 		    vfip->VFI,
7344 		    mb4->mbxStatus);
7345 
7346 		(void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED,
7347 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
7348 
7349 		mutex_exit(&EMLXS_FCF_LOCK);
7350 		return (0);
7351 	}
7352 
7353 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7354 	    "vfi_init_mbcmpl:%d Initialized.",
7355 	    vfip->VFI,
7356 	    mb4->mbxStatus);
7357 
7358 	vfip->flag |= EMLXS_VFI_INIT;
7359 	(void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL, 0, 0, 0);
7360 
7361 	mutex_exit(&EMLXS_FCF_LOCK);
7362 	return (0);
7363 
7364 } /* emlxs_vfi_init_mbcmpl() */
7365 
7366 
7367 /*ARGSUSED*/
7368 static uint32_t
7369 emlxs_vfi_init_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7370     void *arg1)
7371 {
7372 	emlxs_hba_t *hba = HBA;
7373 	MAILBOXQ *mbq;
7374 	MAILBOX4 *mb4;
7375 	uint32_t rval;
7376 
7377 	if (vfip->state != VFI_STATE_INIT) {
7378 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7379 		    "vfi_init_action:%d %s:%s arg=%p. "
7380 		    "Invalid state. Terminated.",
7381 		    vfip->VFI,
7382 		    emlxs_vfi_state_xlate(vfip->state),
7383 		    emlxs_fcf_event_xlate(evt), arg1);
7384 		return (1);
7385 	}
7386 
7387 	if (!(vfip->flag & EMLXS_VFI_FCFI)) {
7388 		vfip->flag |= EMLXS_VFI_FCFI;
7389 		vfip->fcfp->vfi_online++;
7390 	}
7391 
7392 	if (vfip->prev_state != VFI_STATE_INIT_FAILED) {
7393 		vfip->attempts = 0;
7394 	}
7395 
7396 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
7397 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7398 		    "vfi_init_action:%d attempts=%d. Offline requested.",
7399 		    vfip->VFI,
7400 		    vfip->attempts);
7401 
7402 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
7403 		return (rval);
7404 	}
7405 
7406 	if (vfip->flag & EMLXS_VFI_INIT) {
7407 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7408 		    "vfi_init_action:%d flag=%x. "
7409 		    "Already init'd. Skipping init.",
7410 		    vfip->VFI);
7411 
7412 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
7413 		    FCF_REASON_EVENT, evt, arg1);
7414 		return (rval);
7415 	}
7416 
7417 	if (vfip->fcfp->vfi_online == 1) {
7418 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7419 		    "vfi_init_action:%d vfi_online=%d. Skipping init.",
7420 		    vfip->VFI,
7421 		    vfip->fcfp->vfi_online);
7422 
7423 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
7424 		    FCF_REASON_EVENT, evt, arg1);
7425 		return (rval);
7426 	}
7427 
7428 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7429 	    "vfi_init_action:%d vfi_online=%d attempts=%d",
7430 	    vfip->VFI,
7431 	    vfip->fcfp->vfi_online,
7432 	    vfip->attempts);
7433 
7434 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
7435 		rval = emlxs_vfi_state(port, vfip, FCFI_STATE_REG_FAILED,
7436 		    FCF_REASON_NO_MBOX, 0, arg1);
7437 		return (rval);
7438 	}
7439 	mb4 = (MAILBOX4*)mbq;
7440 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
7441 
7442 	mbq->nonembed = NULL;
7443 	mbq->mbox_cmpl = emlxs_vfi_init_mbcmpl;
7444 	mbq->context = (void *)vfip;
7445 	mbq->port = (void *)port;
7446 
7447 	mb4->mbxCommand = MBX_INIT_VFI;
7448 	mb4->mbxOwner = OWN_HOST;
7449 	mb4->un.varInitVFI4.fcfi = vfip->fcfp->FCFI;
7450 	mb4->un.varInitVFI4.vfi = vfip->VFI;
7451 
7452 	/* ??? This function is untested and incomplete */
7453 
7454 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
7455 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
7456 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7457 
7458 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED,
7459 		    FCF_REASON_SEND_FAILED, rval, arg1);
7460 
7461 		return (rval);
7462 	}
7463 
7464 	return (0);
7465 
7466 } /* emlxs_vfi_init_action() */
7467 
7468 
7469 /*ARGSUSED*/
7470 static uint32_t
7471 emlxs_vfi_init_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7472     void *arg1)
7473 {
7474 	uint32_t rval;
7475 
7476 	vfip->attempts++;
7477 
7478 	if (vfip->state != VFI_STATE_INIT_FAILED) {
7479 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7480 		    "vfi_init_action:%d %s:%s arg=%p attempt=%d. "
7481 		    "Invalid state. Terminated.",
7482 		    vfip->VFI,
7483 		    emlxs_vfi_state_xlate(vfip->state),
7484 		    emlxs_fcf_event_xlate(evt), arg1,
7485 		    vfip->attempts);
7486 
7487 		return (1);
7488 	}
7489 
7490 	if ((vfip->reason == FCF_REASON_SEND_FAILED) ||
7491 	    (vfip->attempts >= 3)) {
7492 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7493 		    "vfi_init_action:%d attempt=%d reason=%x. Init cmpl.",
7494 		    vfip->VFI,
7495 		    vfip->attempts,
7496 		    vfip->reason);
7497 
7498 		vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT);
7499 
7500 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
7501 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
7502 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL,
7503 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
7504 	} else {
7505 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7506 		    "vfi_init_action:%d attempt=%d. Initializing.",
7507 		    vfip->VFI,
7508 		    vfip->attempts);
7509 
7510 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
7511 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
7512 	}
7513 
7514 	return (rval);
7515 
7516 } /* emlxs_vfi_init_failed_action() */
7517 
7518 
7519 /*ARGSUSED*/
7520 static uint32_t
7521 emlxs_vfi_init_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7522     void *arg1)
7523 {
7524 	uint32_t rval;
7525 
7526 	if (vfip->state != VFI_STATE_INIT_CMPL) {
7527 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7528 		    "vfi_init_cmpl_action:%d %s:%s arg=%p. "
7529 		    "Invalid state. Terminated.",
7530 		    vfip->VFI,
7531 		    emlxs_vfi_state_xlate(vfip->state),
7532 		    emlxs_fcf_event_xlate(evt), arg1);
7533 		return (1);
7534 	}
7535 
7536 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7537 	    "vfi_init_cmpl_action:%d attempts=%d. Init cmpl.",
7538 	    vfip->VFI,
7539 	    vfip->attempts);
7540 
7541 	rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
7542 	    FCF_REASON_EVENT, evt, arg1);
7543 
7544 	return (rval);
7545 
7546 } /* emlxs_vfi_init_cmpl_action() */
7547 
7548 
7549 /*ARGSUSED*/
7550 static uint32_t
7551 emlxs_vfi_vpi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7552     void *arg1)
7553 {
7554 	emlxs_hba_t *hba = HBA;
7555 	uint32_t rval;
7556 	uint32_t i;
7557 	emlxs_port_t *vport;
7558 	VPIobj_t *vpip;
7559 
7560 	if (vfip->state != VFI_STATE_VPI_ONLINE) {
7561 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7562 		    "vfi_vpi_online_action:%d %s:%s arg=%p. "
7563 		    "Invalid state. Terminated.",
7564 		    vfip->VFI,
7565 		    emlxs_vfi_state_xlate(vfip->state),
7566 		    emlxs_fcf_event_xlate(evt), arg1);
7567 		return (1);
7568 	}
7569 
7570 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
7571 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7572 		    "vfi_vpi_online_action:%d. Offline requested.",
7573 		    vfip->VFI);
7574 
7575 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
7576 		return (rval);
7577 	}
7578 
7579 	if (vfip->logi_count > 0) {
7580 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7581 		    "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. "
7582 		    "VPI already logged in.",
7583 		    vfip->VFI,
7584 		    vfip->vpi_online,
7585 		    vfip->logi_count);
7586 	}
7587 
7588 	if (vfip->vpi_online > 0) {
7589 		/* Waking up out after being paused */
7590 
7591 		/* Find first VPI of this VFI */
7592 		for (i = 0; i <= hba->vpi_max; i++) {
7593 			vport = &VPORT(i);
7594 			vpip = &vport->VPIobj;
7595 
7596 			if (!(vport->flag & EMLXS_PORT_BOUND)) {
7597 				continue;
7598 			}
7599 
7600 			if (vpip->vfip == vfip) {
7601 				break;
7602 			}
7603 		}
7604 
7605 	} else {
7606 
7607 		/* Find first available VPI */
7608 		for (i = 0; i <= hba->vpi_max; i++) {
7609 			vport = &VPORT(i);
7610 			vpip = &vport->VPIobj;
7611 
7612 			if (!(vport->flag & EMLXS_PORT_BOUND)) {
7613 				continue;
7614 			}
7615 
7616 			if (vpip->vfip == NULL) {
7617 				vpip->vfip = vfip;
7618 				break;
7619 			}
7620 		}
7621 	}
7622 
7623 	if (i > hba->vpi_max) {
7624 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7625 		    "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. "
7626 		    "No VPI found. Offlining.",
7627 		    vfip->VFI,
7628 		    vfip->vpi_online,
7629 		    vfip->logi_count);
7630 
7631 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
7632 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
7633 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
7634 		return (rval);
7635 	}
7636 
7637 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7638 	    "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. "
7639 	    "Onlining VPI:%d",
7640 	    vfip->VFI,
7641 	    vfip->vpi_online,
7642 	    vfip->logi_count,
7643 	    vpip->VPI);
7644 
7645 	rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
7646 
7647 	/* Wait for FCF_EVENT_VPI_ONLINE in return */
7648 
7649 	return (rval);
7650 
7651 } /* emlxs_vfi_vpi_online_action() */
7652 
7653 
7654 /*ARGSUSED*/
7655 static uint32_t
7656 emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip,
7657     uint32_t evt, void *arg1)
7658 {
7659 	uint32_t rval;
7660 
7661 	if (vfip->state != VFI_STATE_VPI_ONLINE_CMPL) {
7662 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7663 		    "vfi_vpi_online_cmpl_action:%d %s:%s arg=%p. "
7664 		    "Invalid state. Terminated.",
7665 		    vfip->VFI,
7666 		    emlxs_vfi_state_xlate(vfip->state),
7667 		    emlxs_fcf_event_xlate(evt), arg1);
7668 		return (1);
7669 	}
7670 
7671 	if (vfip->vpi_online > 1) {
7672 		/* Waking up after pause */
7673 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7674 		    "vfi_vpi_online_cmpl_action:%d flag=%x vpi_online=%d "
7675 		    "logi_count=%d. Going online.",
7676 		    vfip->VFI,
7677 		    vfip->flag,
7678 		    vfip->vpi_online,
7679 		    vfip->logi_count);
7680 
7681 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
7682 		    FCF_REASON_EVENT, evt, arg1);
7683 	} else {
7684 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7685 		    "vfi_vpi_online_cmpl_action:%d flag=%x vpi_online=%d "
7686 		    "logi_count=%d. Registering.",
7687 		    vfip->VFI,
7688 		    vfip->flag,
7689 		    vfip->vpi_online,
7690 		    vfip->logi_count);
7691 
7692 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG,
7693 		    FCF_REASON_EVENT, evt, arg1);
7694 	}
7695 
7696 	return (rval);
7697 
7698 } /* emlxs_vfi_vpi_online_cmpl_action() */
7699 
7700 
7701 /*ARGSUSED*/
7702 static uint32_t
7703 emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip,
7704     uint32_t evt, void *arg1)
7705 {
7706 	uint32_t rval = 0;
7707 
7708 	if (vfip->state != VFI_STATE_VPI_OFFLINE_CMPL) {
7709 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7710 		    "vfi_vpi_offline_cmpl_action:%d %s:%s arg=%p. "
7711 		    "Invalid state. Terminated.",
7712 		    vfip->VFI,
7713 		    emlxs_vfi_state_xlate(vfip->state),
7714 		    emlxs_fcf_event_xlate(evt), arg1);
7715 		return (1);
7716 	}
7717 
7718 	if ((vfip->vpi_online == 0) &&
7719 	    (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
7720 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7721 		    "vfi_vpi_offline_cmpl_action:%d vpi_online=%d. "
7722 		    "Unregistering.",
7723 		    vfip->VFI,
7724 		    vfip->vpi_online);
7725 
7726 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
7727 		    FCF_REASON_EVENT, evt, arg1);
7728 	} else {
7729 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7730 		    "vfi_vpi_offline_cmpl_action:%d vpi_online=%d. Terminated.",
7731 		    vfip->VFI,
7732 		    vfip->vpi_online);
7733 	}
7734 
7735 	return (rval);
7736 
7737 } /* emlxs_vfi_vpi_offline_cmpl_action() */
7738 
7739 
7740 /*ARGSUSED*/
7741 static uint32_t
7742 emlxs_vfi_vpi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7743     void *arg1)
7744 {
7745 	emlxs_hba_t *hba = HBA;
7746 	emlxs_port_t *vport;
7747 	uint32_t rval;
7748 	int32_t i;
7749 	VPIobj_t *vpip;
7750 
7751 	if (vfip->state != VFI_STATE_VPI_OFFLINE) {
7752 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7753 		    "vfi_vpi_offline_action:%d %s:%s arg=%p. "
7754 		    "Invalid state. Terminated.",
7755 		    vfip->VFI,
7756 		    emlxs_vfi_state_xlate(vfip->state),
7757 		    emlxs_fcf_event_xlate(evt), arg1);
7758 		return (1);
7759 	}
7760 
7761 	if (vfip->flag & EMLXS_VFI_PAUSE_REQ) {
7762 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7763 		    "vfi_vpi_offline_action:%d vpi_online=%d. Pausing.",
7764 		    vfip->VFI,
7765 		    vfip->vpi_online);
7766 
7767 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED,
7768 		    FCF_REASON_EVENT, evt, arg1);
7769 
7770 		return (rval);
7771 	}
7772 
7773 	if (vfip->vpi_online == 0) {
7774 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7775 		    "vfi_vpi_offline_action:%d vpi_online=%d. "
7776 		    "VPI already offline. Skipping offline.",
7777 		    vfip->VFI,
7778 		    vfip->vpi_online);
7779 
7780 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
7781 		    FCF_REASON_EVENT, evt, arg1);
7782 
7783 		return (rval);
7784 	}
7785 
7786 	/* Offline all VPI's of this VFI */
7787 	for (i = hba->vpi_max; i >= 0; i--) {
7788 		vport = &VPORT(i);
7789 		vpip = &vport->VPIobj;
7790 
7791 		if ((vpip->state == VPI_STATE_OFFLINE) ||
7792 		    (vpip->vfip != vfip)) {
7793 			continue;
7794 		}
7795 
7796 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7797 		    "vfi_vpi_offline_action:%d. Offlining VPI:%d.",
7798 		    vfip->VFI,
7799 		    vpip->VPI);
7800 
7801 		(void) emlxs_vpi_event(vport, FCF_EVENT_VPI_OFFLINE, vpip);
7802 	}
7803 
7804 	/* Wait for FCF_EVENT_VPI_OFFLINE in return */
7805 
7806 	return (0);
7807 
7808 } /* emlxs_vfi_vpi_offline_action() */
7809 
7810 
7811 /*ARGSUSED*/
7812 static uint32_t
7813 emlxs_vfi_paused_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7814     void *arg1)
7815 {
7816 	emlxs_hba_t *hba = HBA;
7817 	emlxs_port_t *vport;
7818 	int32_t i;
7819 	VPIobj_t *vpip;
7820 
7821 	if (vfip->state != VFI_STATE_PAUSED) {
7822 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7823 		    "vfi_paused_action:%d %s:%s arg=%p. "
7824 		    "Invalid state. Terminated.",
7825 		    vfip->VFI,
7826 		    emlxs_vfi_state_xlate(vfip->state),
7827 		    emlxs_fcf_event_xlate(evt), arg1);
7828 		return (1);
7829 	}
7830 
7831 	vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
7832 
7833 	/* Pause all VPI's of this VFI */
7834 	for (i = hba->vpi_max; i >= 0; i--) {
7835 		vport = &VPORT(i);
7836 		vpip = &vport->VPIobj;
7837 
7838 		if ((vpip->state == VPI_STATE_PAUSED) ||
7839 		    (vpip->vfip != vfip)) {
7840 			continue;
7841 		}
7842 
7843 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7844 		    "vfi_paused_action:%d vpi_online=%d. Pausing VPI:%d.",
7845 		    vfip->VFI,
7846 		    vfip->vpi_online,
7847 		    vpip->VPI);
7848 
7849 		(void) emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip);
7850 	}
7851 
7852 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7853 	    "vfi_paused_action:%d vpi_online=%d. VFI paused.",
7854 	    vfip->VFI,
7855 	    vfip->vpi_online);
7856 
7857 	return (0);
7858 
7859 } /* emlxs_vfi_paused_action() */
7860 
7861 
7862 /*ARGSUSED*/
7863 static uint32_t
7864 emlxs_vfi_unreg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7865     void *arg1)
7866 {
7867 	uint32_t rval;
7868 
7869 	vfip->attempts++;
7870 
7871 	if (vfip->state != VFI_STATE_UNREG_FAILED) {
7872 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7873 		    "vfi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
7874 		    "Invalid state. Terminated.",
7875 		    vfip->VFI,
7876 		    emlxs_vfi_state_xlate(vfip->state),
7877 		    emlxs_fcf_event_xlate(evt), arg1,
7878 		    vfip->attempts);
7879 
7880 		return (1);
7881 	}
7882 
7883 	if (vfip->attempts >= 3) {
7884 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7885 		    "vfi_unreg_failed_action:%d attempt=%d. Unreg cmpl.",
7886 		    vfip->VFI,
7887 		    vfip->attempts);
7888 
7889 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
7890 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
7891 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL,
7892 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
7893 	} else {
7894 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7895 		    "vfi_unreg_failed_action:%d attempt=%d. Unregistering.",
7896 		    vfip->VFI,
7897 		    vfip->attempts);
7898 
7899 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
7900 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
7901 	}
7902 
7903 	return (rval);
7904 
7905 } /* emlxs_vfi_unreg_failed_action() */
7906 
7907 
7908 /*ARGSUSED*/
7909 static uint32_t
7910 emlxs_vfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
7911 {
7912 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
7913 	MAILBOX4 *mb4;
7914 	VFIobj_t *vfip;
7915 
7916 	vfip = (VFIobj_t *)mbq->context;
7917 	mb4 = (MAILBOX4 *)mbq;
7918 
7919 	mutex_enter(&EMLXS_FCF_LOCK);
7920 
7921 	if (vfip->state != VFI_STATE_UNREG) {
7922 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7923 		    "vfi_unreg_mbcmpl:%d state=%s. Terminated.",
7924 		    vfip->VFI,
7925 		    emlxs_vfi_state_xlate(vfip->state));
7926 
7927 		mutex_exit(&EMLXS_FCF_LOCK);
7928 		return (0);
7929 	}
7930 
7931 	if (mb4->mbxStatus) {
7932 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7933 		    "vfi_unreg_mbcmpl:%d failed. status=%x",
7934 		    vfip->VFI,
7935 		    mb4->mbxStatus);
7936 
7937 		(void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
7938 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
7939 
7940 		mutex_exit(&EMLXS_FCF_LOCK);
7941 		return (0);
7942 	}
7943 
7944 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7945 	    "vfi_unreg_mbcmpl:%d Unregistered.",
7946 	    vfip->VFI);
7947 
7948 	vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT);
7949 	(void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL,
7950 	    0, 0, 0);
7951 
7952 	mutex_exit(&EMLXS_FCF_LOCK);
7953 	return (0);
7954 
7955 } /* emlxs_vfi_unreg_mbcmpl() */
7956 
7957 
7958 /*ARGSUSED*/
7959 static uint32_t
7960 emlxs_vfi_unreg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
7961     void *arg1)
7962 {
7963 	emlxs_hba_t *hba = HBA;
7964 	MAILBOX4 *mb4;
7965 	MAILBOXQ *mbq;
7966 	uint32_t rval;
7967 
7968 	if (vfip->state != VFI_STATE_UNREG) {
7969 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7970 		    "vfi_unreg_action:%d %s:%s arg=%p. "
7971 		    "Invalid state. Terminated.",
7972 		    vfip->VFI,
7973 		    emlxs_vfi_state_xlate(vfip->state),
7974 		    emlxs_fcf_event_xlate(evt), arg1);
7975 
7976 		return (1);
7977 	}
7978 
7979 	if (!(vfip->flag & EMLXS_VFI_REG)) {
7980 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7981 		    "vfi_unreg_action:%d. Not registered. Skipping unreg.",
7982 		    vfip->VFI);
7983 
7984 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
7985 		    FCF_REASON_EVENT, evt, arg1);
7986 		return (rval);
7987 	}
7988 
7989 	if (vfip->prev_state != VFI_STATE_UNREG_FAILED) {
7990 		vfip->attempts = 0;
7991 	}
7992 
7993 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7994 	    "vfi_unreg_action:%d attempts=%d. Sending UNREG_VFI.",
7995 	    vfip->VFI,
7996 	    vfip->attempts);
7997 
7998 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
7999 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
8000 		    FCF_REASON_NO_MBOX, 0, arg1);
8001 
8002 		return (rval);
8003 	}
8004 	mb4 = (MAILBOX4*)mbq;
8005 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
8006 
8007 	mbq->nonembed = NULL;
8008 	mbq->mbox_cmpl = emlxs_vfi_unreg_mbcmpl;
8009 	mbq->context = (void *)vfip;
8010 	mbq->port = (void *)port;
8011 
8012 	mb4->un.varUnRegVFI4.vfi = vfip->VFI;
8013 	mb4->mbxCommand = MBX_UNREG_VFI;
8014 	mb4->mbxOwner = OWN_HOST;
8015 
8016 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
8017 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
8018 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
8019 
8020 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
8021 		    FCF_REASON_SEND_FAILED, rval, arg1);
8022 
8023 		return (rval);
8024 	}
8025 
8026 	return (0);
8027 
8028 } /* emlxs_vfi_unreg_action() */
8029 
8030 
8031 /*ARGSUSED*/
8032 static uint32_t
8033 emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
8034     void *arg1)
8035 {
8036 	uint32_t rval;
8037 
8038 	if (vfip->state != VFI_STATE_UNREG_CMPL) {
8039 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8040 		    "vfi_unreg_cmpl_action:%d %s:%s arg=%p. "
8041 		    "Invalid state. Terminated.",
8042 		    vfip->VFI,
8043 		    emlxs_vfi_state_xlate(vfip->state),
8044 		    emlxs_fcf_event_xlate(evt), arg1);
8045 		return (1);
8046 	}
8047 
8048 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8049 	    "vfi_unreg_cmpl_action:%d attempts=%d. Going offline.",
8050 	    vfip->VFI,
8051 	    vfip->attempts);
8052 
8053 	rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
8054 	    FCF_REASON_EVENT, evt, arg1);
8055 
8056 	return (rval);
8057 
8058 } /* emlxs_vfi_unreg_cmpl_action() */
8059 
8060 
8061 /*ARGSUSED*/
8062 static uint32_t
8063 emlxs_vfi_reg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
8064     void *arg1)
8065 {
8066 	uint32_t rval;
8067 
8068 	vfip->attempts++;
8069 
8070 	if (vfip->state != VFI_STATE_REG_FAILED) {
8071 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8072 		    "vfi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
8073 		    "Invalid state. Terminated.",
8074 		    vfip->VFI,
8075 		    emlxs_vfi_state_xlate(vfip->state),
8076 		    emlxs_fcf_event_xlate(evt), arg1,
8077 		    vfip->attempts);
8078 
8079 		return (1);
8080 	}
8081 
8082 	if ((vfip->reason == FCF_REASON_SEND_FAILED) ||
8083 	    (vfip->attempts >= 3)) {
8084 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8085 		    "vfi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.",
8086 		    vfip->VFI,
8087 		    vfip->attempts,
8088 		    vfip->reason);
8089 
8090 		vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT);
8091 
8092 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
8093 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
8094 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL,
8095 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
8096 	} else {
8097 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8098 		    "vfi_reg_failed_action:%d attempt=%d. Registering.",
8099 		    vfip->VFI,
8100 		    vfip->attempts);
8101 
8102 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG,
8103 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
8104 	}
8105 
8106 	return (rval);
8107 
8108 } /* emlxs_vfi_reg_failed_action() */
8109 
8110 
8111 /*ARGSUSED*/
8112 static uint32_t
8113 emlxs_vfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
8114 {
8115 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
8116 	MAILBOX4 *mb4;
8117 	VFIobj_t *vfip;
8118 
8119 	vfip = (VFIobj_t *)mbq->context;
8120 	mb4 = (MAILBOX4 *)mbq;
8121 
8122 	mutex_enter(&EMLXS_FCF_LOCK);
8123 
8124 	if (vfip->state != VFI_STATE_REG) {
8125 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8126 		    "vfi_reg_mbcmpl:%d state=%s. Terminated.",
8127 		    vfip->VFI,
8128 		    emlxs_vfi_state_xlate(vfip->state));
8129 
8130 		mutex_exit(&EMLXS_FCF_LOCK);
8131 		return (0);
8132 	}
8133 
8134 	if (mb4->mbxStatus) {
8135 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8136 		    "vfi_reg_mbcmpl:%d failed. status=%x",
8137 		    vfip->VFI,
8138 		    mb4->mbxStatus);
8139 
8140 		(void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
8141 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
8142 
8143 		mutex_exit(&EMLXS_FCF_LOCK);
8144 		return (0);
8145 	}
8146 
8147 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8148 	    "vfi_reg_mbcmpl:%d Registered.",
8149 	    vfip->VFI);
8150 
8151 	if (vfip->vpi_online == 1) {
8152 		port->VPIobj.flag |= EMLXS_VPI_REG;
8153 	}
8154 
8155 	vfip->flag |= EMLXS_VFI_REG;
8156 
8157 	(void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL, 0, 0, 0);
8158 
8159 	mutex_exit(&EMLXS_FCF_LOCK);
8160 	return (0);
8161 
8162 } /* emlxs_vfi_reg_mbcmpl() */
8163 
8164 
8165 /*ARGSUSED*/
8166 static uint32_t
8167 emlxs_vfi_reg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
8168     void *arg1)
8169 {
8170 	emlxs_hba_t *hba = HBA;
8171 	FCFIobj_t *fcfp;
8172 	MAILBOX4 *mb4;
8173 	MAILBOXQ *mbq;
8174 	MATCHMAP *mp;
8175 	uint32_t rval;
8176 	uint32_t edtov;
8177 	uint32_t ratov;
8178 
8179 	if (vfip->state != VFI_STATE_REG) {
8180 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8181 		    "vfi_reg_action:%d %s:%s arg=%p. "
8182 		    "Invalid state. Terminated.",
8183 		    vfip->VFI,
8184 		    emlxs_vfi_state_xlate(vfip->state),
8185 		    emlxs_fcf_event_xlate(evt), arg1);
8186 
8187 		return (1);
8188 	}
8189 
8190 	if (vfip->prev_state != VFI_STATE_REG_FAILED) {
8191 		vfip->attempts = 0;
8192 	}
8193 
8194 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
8195 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8196 		    "vfi_reg_action:%d %attempts=%d. Offline requested.",
8197 		    vfip->VFI,
8198 		    vfip->attempts);
8199 
8200 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
8201 		return (rval);
8202 	}
8203 
8204 	if (vfip->flag & EMLXS_VFI_REG) {
8205 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8206 		    "vfi_reg_action:%d flag=%x. "
8207 		    "Already registered. Skipping reg.",
8208 		    vfip->VFI);
8209 
8210 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
8211 		    FCF_REASON_EVENT, evt, arg1);
8212 		return (rval);
8213 	}
8214 
8215 	if (vfip->fcf_sparam.cmn.edtovResolution) {
8216 		edtov = (LE_SWAP32(vfip->fcf_sparam.cmn.e_d_tov) + 999999) /
8217 		    1000000;
8218 	} else {
8219 		edtov = LE_SWAP32(vfip->fcf_sparam.cmn.e_d_tov);
8220 	}
8221 
8222 	ratov = (LE_SWAP32(vfip->fcf_sparam.cmn.w2.r_a_tov) + 999) / 1000;
8223 
8224 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8225 	    "vfi_reg_action:%d attempts=%d edtov=%d ratov=%d. "
8226 	    "Sending REG_VFI.",
8227 	    vfip->VFI,
8228 	    vfip->attempts,
8229 	    edtov, ratov);
8230 
8231 	fcfp = vfip->fcfp;
8232 
8233 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
8234 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
8235 		    FCF_REASON_NO_MBOX, 0, arg1);
8236 
8237 		return (rval);
8238 	}
8239 	mb4 = (MAILBOX4*)mbq;
8240 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
8241 
8242 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
8243 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
8244 
8245 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
8246 		    FCF_REASON_NO_BUFFER, 0, arg1);
8247 
8248 		return (1);
8249 	}
8250 
8251 	mbq->bp = (void *)mp;
8252 	mbq->nonembed = NULL;
8253 
8254 	mbq->mbox_cmpl = emlxs_vfi_reg_mbcmpl;
8255 	mbq->context = (void *)vfip;
8256 	mbq->port = (void *)port;
8257 
8258 	mb4->mbxCommand = MBX_REG_VFI;
8259 	mb4->mbxOwner = OWN_HOST;
8260 	mb4->un.varRegVFI4.vfi = vfip->VFI;
8261 
8262 	if (vfip->fcfp->vfi_online == 1) {
8263 		mb4->un.varRegVFI4.vp = 1;
8264 		mb4->un.varRegVFI4.vpi = port->VPIobj.VPI;
8265 	}
8266 
8267 	mb4->un.varRegVFI4.fcfi = fcfp->FCFI;
8268 	mb4->un.varRegVFI4.sid = port->did;
8269 	mb4->un.varRegVFI4.edtov = edtov;
8270 
8271 	/* Convert to seconds */
8272 	mb4->un.varRegVFI4.ratov = ratov;
8273 	mb4->un.varRegVFI4.bde.tus.f.bdeSize = sizeof (SERV_PARM);
8274 	mb4->un.varRegVFI4.bde.addrHigh = PADDR_HI(mp->phys);
8275 	mb4->un.varRegVFI4.bde.addrLow = PADDR_LO(mp->phys);
8276 	bcopy((uint32_t *)&vfip->fcf_sparam,
8277 	    (uint32_t *)mp->virt, sizeof (SERV_PARM));
8278 
8279 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
8280 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
8281 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
8282 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
8283 
8284 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
8285 		    FCF_REASON_SEND_FAILED, rval, arg1);
8286 
8287 		return (rval);
8288 	}
8289 
8290 	return (0);
8291 
8292 } /* emlxs_vfi_reg_action() */
8293 
8294 
8295 /*ARGSUSED*/
8296 static uint32_t
8297 emlxs_vfi_reg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
8298     void *arg1)
8299 {
8300 	uint32_t rval;
8301 
8302 	if (vfip->state != VFI_STATE_REG_CMPL) {
8303 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8304 		    "vfi_reg_cmpl_action:%d %s:%s arg=%p. "
8305 		    "Invalid state. Terminated.",
8306 		    vfip->VFI,
8307 		    emlxs_vfi_state_xlate(vfip->state),
8308 		    emlxs_fcf_event_xlate(evt), arg1);
8309 		return (1);
8310 	}
8311 
8312 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
8313 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8314 		    "vfi_reg_cmpl_action:%d attempts=%d. Offline requested.",
8315 		    vfip->VFI,
8316 		    vfip->attempts);
8317 
8318 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
8319 		return (rval);
8320 	}
8321 
8322 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8323 	    "vfi_reg_cmpl_action:%d attempts=%d. Going online.",
8324 	    vfip->VFI,
8325 	    vfip->attempts);
8326 
8327 	rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
8328 	    FCF_REASON_EVENT, evt, arg1);
8329 
8330 	return (rval);
8331 
8332 } /* emlxs_vfi_reg_cmpl_action() */
8333 
8334 
8335 /*ARGSUSED*/
8336 static uint32_t
8337 emlxs_vfi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
8338     void *arg1)
8339 {
8340 	emlxs_hba_t *hba = HBA;
8341 	uint32_t i;
8342 	uint32_t rval;
8343 	VPIobj_t *vpip;
8344 	emlxs_port_t *vport;
8345 
8346 	if (vfip->state != VFI_STATE_ONLINE) {
8347 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8348 		    "vfi_online_action:%d %s:%s arg=%p. "
8349 		    "Invalid state. Terminated.",
8350 		    vfip->VFI,
8351 		    emlxs_vfi_state_xlate(vfip->state),
8352 		    emlxs_fcf_event_xlate(evt), arg1);
8353 		return (1);
8354 	}
8355 
8356 	vfip->flag &= ~EMLXS_VFI_ONLINE_REQ;
8357 
8358 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
8359 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8360 		    "vfi_online_action:%d attempts=%d. Offline requested.",
8361 		    vfip->VFI,
8362 		    vfip->attempts);
8363 
8364 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
8365 		return (rval);
8366 	}
8367 
8368 	vpip = &port->VPIobj;
8369 
8370 	/* Take Fabric RPI online now */
8371 	if (vpip->rpip->state != RPI_STATE_ONLINE) {
8372 		/* This will complete the FLOGI/FDISC back to Leadville */
8373 		(void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE, vpip->rpip);
8374 	}
8375 
8376 	/* FLOGI/FDISC has been completed back to Leadville */
8377 	/* It is now safe to accept unsolicited requests */
8378 	vpip->flag |= EMLXS_VPI_PORT_ENABLED;
8379 
8380 	/* Online remaining VPI's */
8381 	for (i = 0; i <= hba->vpi_max; i++) {
8382 		vport = &VPORT(i);
8383 		vpip = &vport->VPIobj;
8384 
8385 		if (!(vport->flag & EMLXS_PORT_BOUND)) {
8386 			continue;
8387 		}
8388 
8389 		if ((vpip->state == VPI_STATE_ONLINE) ||
8390 		    (vpip->flag & EMLXS_VPI_ONLINE_REQ)) {
8391 			continue;
8392 		}
8393 
8394 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8395 		    "vfi_online_action:%d vpi_online=%d logi_count=%d. "
8396 		    "Onlining VPI:%d",
8397 		    vfip->VFI,
8398 		    vfip->vpi_online,
8399 		    vfip->logi_count,
8400 		    vpip->VPI);
8401 
8402 		vpip->vfip = vfip;
8403 		(void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE, vpip);
8404 	}
8405 
8406 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8407 	    "vfi_online_action:%d vpi_online=%d logi_count=%d. "
8408 	    "VFI online. Notifying FCFI:%d.",
8409 	    vfip->VFI,
8410 	    vfip->vpi_online,
8411 	    vfip->logi_count,
8412 	    vfip->fcfp->fcf_index);
8413 
8414 	/* Notify FCFI */
8415 	rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
8416 
8417 	return (rval);
8418 
8419 } /* emlxs_vfi_online_action() */
8420 
8421 
8422 /* ************************************************************************** */
8423 /* VPI */
8424 /* ************************************************************************** */
8425 
8426 static char *
8427 emlxs_vpi_state_xlate(uint32_t state)
8428 {
8429 	static char buffer[32];
8430 	uint32_t i;
8431 	uint32_t count;
8432 
8433 	count = sizeof (emlxs_vpi_state_table) / sizeof (emlxs_table_t);
8434 	for (i = 0; i < count; i++) {
8435 		if (state == emlxs_vpi_state_table[i].code) {
8436 			return (emlxs_vpi_state_table[i].string);
8437 		}
8438 	}
8439 
8440 	(void) sprintf(buffer, "state=0x%x", state);
8441 	return (buffer);
8442 
8443 } /* emlxs_vpi_state_xlate() */
8444 
8445 
8446 static uint32_t
8447 emlxs_vpi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
8448     void *arg1)
8449 {
8450 	uint32_t rval;
8451 	uint32_t(*func) (emlxs_port_t *, VPIobj_t *, uint32_t, void *);
8452 	uint32_t index;
8453 	uint32_t events;
8454 	uint16_t state;
8455 
8456 	/* Convert event to action table index */
8457 	switch (evt) {
8458 	case FCF_EVENT_STATE_ENTER:
8459 		index = 0;
8460 		break;
8461 	case FCF_EVENT_VPI_ONLINE:
8462 		index = 1;
8463 		break;
8464 	case FCF_EVENT_VPI_OFFLINE:
8465 		index = 2;
8466 		break;
8467 	case FCF_EVENT_VPI_PAUSE:
8468 		index = 3;
8469 		break;
8470 	case FCF_EVENT_RPI_ONLINE:
8471 		index = 4;
8472 		break;
8473 	case FCF_EVENT_RPI_OFFLINE:
8474 		index = 5;
8475 		break;
8476 	case FCF_EVENT_RPI_PAUSE:
8477 		index = 6;
8478 		break;
8479 	default:
8480 		return (1);
8481 	}
8482 
8483 	events = VPI_ACTION_EVENTS;
8484 	state  = vpip->state;
8485 
8486 	index += (state * events);
8487 	func   = (uint32_t(*) (emlxs_port_t *, VPIobj_t *, uint32_t, void *))
8488 	    emlxs_vpi_action_table[index];
8489 
8490 	if (!func) {
8491 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
8492 		    "vpi:%d %s:%s arg=%p. No action. Terminated.",
8493 		    vpip->VPI,
8494 		    emlxs_vpi_state_xlate(vpip->state),
8495 		    emlxs_fcf_event_xlate(evt), arg1);
8496 
8497 		return (1);
8498 	}
8499 
8500 	rval = (func)(port, vpip, evt, arg1);
8501 
8502 	return (rval);
8503 
8504 } /* emlxs_vpi_action() */
8505 
8506 
8507 static uint32_t
8508 emlxs_vpi_event(emlxs_port_t *port, uint32_t evt,
8509     void *arg1)
8510 {
8511 	VPIobj_t *vpip = NULL;
8512 	RPIobj_t *rpip;
8513 	uint32_t rval;
8514 
8515 	/* Filter events and acquire fcfi context */
8516 	switch (evt) {
8517 	case FCF_EVENT_RPI_ONLINE:
8518 	case FCF_EVENT_RPI_OFFLINE:
8519 	case FCF_EVENT_RPI_PAUSE:
8520 		rpip = (RPIobj_t *)arg1;
8521 
8522 		if (!rpip) {
8523 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
8524 			    "rpi: %s arg=%p. Null RPI found. Terminated.",
8525 			    emlxs_fcf_event_xlate(evt), arg1);
8526 
8527 			return (1);
8528 		}
8529 
8530 		vpip = rpip->vpip;
8531 		break;
8532 
8533 	case FCF_EVENT_VPI_ONLINE:
8534 	case FCF_EVENT_VPI_PAUSE:
8535 	case FCF_EVENT_VPI_OFFLINE:
8536 		vpip = (VPIobj_t *)arg1;
8537 
8538 		if (!vpip) {
8539 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
8540 			    "vpi: %s arg=%p. Null VPI found. Terminated.",
8541 			    emlxs_fcf_event_xlate(evt), arg1);
8542 
8543 			return (1);
8544 		}
8545 
8546 		break;
8547 
8548 	default:
8549 		return (1);
8550 	}
8551 
8552 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
8553 	    "vpi:%d %s:%s arg=%p",
8554 	    vpip->VPI,
8555 	    emlxs_vpi_state_xlate(vpip->state),
8556 	    emlxs_fcf_event_xlate(evt), arg1);
8557 
8558 	rval = emlxs_vpi_action(port, vpip, evt, arg1);
8559 
8560 	return (rval);
8561 
8562 } /* emlxs_vpi_event() */
8563 
8564 
8565 /*ARGSUSED*/
8566 static uint32_t
8567 emlxs_vpi_state(emlxs_port_t *port, VPIobj_t *vpip, uint16_t state,
8568     uint16_t reason, uint32_t explain, void *arg1)
8569 {
8570 	uint32_t rval = 0;
8571 
8572 	if (state >= VPI_ACTION_STATES) {
8573 		return (1);
8574 	}
8575 
8576 	if ((vpip->state == state) &&
8577 	    (reason != FCF_REASON_REENTER)) {
8578 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8579 		    "vpi_state:%d %s:%s:0x%x arg=%p. "
8580 		    "State not changed. Terminated.",
8581 		    vpip->VPI,
8582 		    emlxs_vpi_state_xlate(vpip->state),
8583 		    emlxs_fcf_reason_xlate(reason),
8584 		    explain, arg1);
8585 
8586 		return (1);
8587 	}
8588 
8589 	if (!reason) {
8590 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
8591 		    "vpi:%d %s-->%s arg=%p",
8592 		    vpip->VPI,
8593 		    emlxs_vpi_state_xlate(vpip->state),
8594 		    emlxs_vpi_state_xlate(state), arg1);
8595 	} else if (reason == FCF_REASON_EVENT) {
8596 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
8597 		    "vpi:%d %s-->%s:%s:%s arg=%p",
8598 		    vpip->VPI,
8599 		    emlxs_vpi_state_xlate(vpip->state),
8600 		    emlxs_vpi_state_xlate(state),
8601 		    emlxs_fcf_reason_xlate(reason),
8602 		    emlxs_fcf_event_xlate(explain), arg1);
8603 	} else if (explain) {
8604 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
8605 		    "vpi:%d %s-->%s:%s:0x%x arg=%p",
8606 		    vpip->VPI,
8607 		    emlxs_vpi_state_xlate(vpip->state),
8608 		    emlxs_vpi_state_xlate(state),
8609 		    emlxs_fcf_reason_xlate(reason),
8610 		    explain, arg1);
8611 	} else {
8612 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
8613 		    "vpi:%d %s-->%s:%s arg=%p",
8614 		    vpip->VPI,
8615 		    emlxs_vpi_state_xlate(vpip->state),
8616 		    emlxs_vpi_state_xlate(state),
8617 		    emlxs_fcf_reason_xlate(reason), arg1);
8618 	}
8619 
8620 	vpip->prev_state = vpip->state;
8621 	vpip->prev_reason = vpip->reason;
8622 	vpip->state = state;
8623 	vpip->reason = reason;
8624 
8625 	rval = emlxs_vpi_action(port, vpip, FCF_EVENT_STATE_ENTER, arg1);
8626 
8627 	return (rval);
8628 
8629 } /* emlxs_vpi_state() */
8630 
8631 
8632 extern uint32_t
8633 emlxs_vpi_port_bind_notify(emlxs_port_t *port)
8634 {
8635 	emlxs_hba_t *hba = HBA;
8636 	VPIobj_t 	*vpip = &port->VPIobj;
8637 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
8638 	uint32_t rval = 0;
8639 	VFIobj_t *vfip;
8640 	VFIobj_t *vfip1;
8641 	uint32_t i;
8642 	FCFIobj_t *fcfp;
8643 	FCFIobj_t *fcfp1;
8644 
8645 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
8646 		return (1);
8647 	}
8648 
8649 	if (hba->state < FC_LINK_UP) {
8650 		if (port->vpi == 0) {
8651 			(void) emlxs_reset_link(hba, 1, 0);
8652 		}
8653 		return (0);
8654 	}
8655 
8656 	mutex_enter(&EMLXS_FCF_LOCK);
8657 
8658 	if (vpip->vfip) {
8659 		vfip = vpip->vfip;
8660 		fcfp = vfip->fcfp;
8661 		goto done;
8662 	}
8663 
8664 	/* We need to select a VFI for this VPI */
8665 
8666 	/* First find a selected Fabric */
8667 	fcfp = NULL;
8668 	for (i = 0; i < fcftab->fcfi_count; i++) {
8669 		fcfp1 = fcftab->fcfi[i];
8670 
8671 		if (fcfp1->flag & EMLXS_FCFI_SELECTED) {
8672 			fcfp = fcfp1;
8673 			break;
8674 		}
8675 	}
8676 
8677 	if (!fcfp) {
8678 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8679 		    "vpi_port_bind_notify:%d %s. "
8680 		    "No FCF available yet. Terminated.",
8681 		    vpip->VPI,
8682 		    emlxs_vpi_state_xlate(vpip->state));
8683 
8684 		mutex_exit(&EMLXS_FCF_LOCK);
8685 		return (0);
8686 	}
8687 
8688 	/* Find first available VFI for this FCFI */
8689 	vfip = NULL;
8690 	vfip1 = hba->sli.sli4.VFI_table;
8691 	for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip1++) {
8692 		if (vfip1->fcfp == fcfp) {
8693 			vfip = vfip1;
8694 			break;
8695 		}
8696 	}
8697 
8698 	if (!vfip) {
8699 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8700 		    "vpi_port_bind_notify:%d %s fcfi:%d. "
8701 		    "No VFI available yet. Terminated.",
8702 		    vpip->VPI,
8703 		    emlxs_vpi_state_xlate(vpip->state),
8704 		    fcfp->fcf_index);
8705 
8706 		mutex_exit(&EMLXS_FCF_LOCK);
8707 		return (0);
8708 	}
8709 
8710 	vpip->vfip = vfip;
8711 done:
8712 
8713 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8714 	    "vpi_port_bind_notify:%d %s fcfi:%d vfi:%d. Onlining VPI:%d",
8715 	    vpip->VPI,
8716 	    emlxs_vpi_state_xlate(vpip->state),
8717 	    fcfp->fcf_index,
8718 	    vfip->VFI,
8719 	    vpip->VPI);
8720 
8721 	rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
8722 
8723 	mutex_exit(&EMLXS_FCF_LOCK);
8724 
8725 	return (rval);
8726 
8727 } /* emlxs_vpi_port_bind_notify() */
8728 
8729 
8730 extern uint32_t
8731 emlxs_vpi_port_unbind_notify(emlxs_port_t *port, uint32_t wait)
8732 {
8733 	emlxs_hba_t *hba = HBA;
8734 	VPIobj_t 	*vpip = &port->VPIobj;
8735 	uint32_t rval = 0;
8736 	VFIobj_t *vfip;
8737 	uint32_t i;
8738 	FCFIobj_t *fcfp;
8739 
8740 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
8741 		return (1);
8742 	}
8743 
8744 	mutex_enter(&EMLXS_FCF_LOCK);
8745 
8746 	if (vpip->state == VPI_STATE_OFFLINE) {
8747 		mutex_exit(&EMLXS_FCF_LOCK);
8748 		return (0);
8749 	}
8750 
8751 	vfip = vpip->vfip;
8752 	fcfp = vfip->fcfp;
8753 
8754 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8755 	    "vpi_port_unbind_notify:%d %s fcfi:%d vfi:%d. "
8756 	    "Offlining VPI:%d,%d",
8757 	    vpip->VPI,
8758 	    emlxs_vpi_state_xlate(vpip->state),
8759 	    fcfp->fcf_index,
8760 	    vfip->VFI,
8761 	    vpip->index, vpip->VPI);
8762 
8763 	rval = emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
8764 
8765 	if (wait && (rval == 0)) {
8766 		/* Wait for VPI to go offline */
8767 		i = 0;
8768 		while (i++ < 120) {
8769 			if (vpip->state == VPI_STATE_OFFLINE) {
8770 				break;
8771 			}
8772 
8773 			mutex_exit(&EMLXS_FCF_LOCK);
8774 			DELAYMS(1000);
8775 			mutex_enter(&EMLXS_FCF_LOCK);
8776 		}
8777 
8778 		if (i >= 120) {
8779 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8780 			    "vpi_port_unbind_notify:%d %s fcfi:%d vfi:%d "
8781 			    "rpi_online=%d,%d. Offline timeout.",
8782 			    vpip->VPI,
8783 			    emlxs_vpi_state_xlate(vpip->state),
8784 			    fcfp->fcf_index,
8785 			    vfip->VFI,
8786 			    vpip->rpi_online, vpip->rpi_paused);
8787 		}
8788 	}
8789 
8790 	mutex_exit(&EMLXS_FCF_LOCK);
8791 
8792 	return (rval);
8793 
8794 } /* emlxs_vpi_port_unbind_notify() */
8795 
8796 
8797 /*ARGSUSED*/
8798 static uint32_t
8799 emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
8800     uint32_t evt, void *arg1)
8801 {
8802 	uint32_t rval;
8803 	RPIobj_t *rpip = (RPIobj_t *)arg1;
8804 
8805 	if (evt != FCF_EVENT_RPI_OFFLINE) {
8806 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8807 		    "vpi_rpi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
8808 		    "Invalid event type. Terminated.",
8809 		    vpip->VPI,
8810 		    emlxs_vpi_state_xlate(vpip->state),
8811 		    emlxs_fcf_event_xlate(evt), arg1,
8812 		    vpip->flag);
8813 		return (1);
8814 	}
8815 
8816 	switch (vpip->state) {
8817 	case VPI_STATE_LOGO:
8818 		/* rpi_online will be checked when LOGO is complete */
8819 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8820 		    "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
8821 		    "rpi=%d. Waiting for LOGO. Terminated.",
8822 		    vpip->VPI,
8823 		    vpip->rpi_online, vpip->rpi_paused,
8824 		    rpip->did, rpip->RPI);
8825 
8826 		rval = 0;
8827 		break;
8828 
8829 	case VPI_STATE_PORT_OFFLINE:
8830 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8831 		    "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
8832 		    "rpi=%d.",
8833 		    vpip->VPI,
8834 		    vpip->rpi_online, vpip->rpi_paused,
8835 		    rpip->did, rpip->RPI);
8836 
8837 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
8838 		    FCF_REASON_REENTER, evt, arg1);
8839 		break;
8840 
8841 	case VPI_STATE_PAUSED:
8842 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8843 		    "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
8844 		    "rpi=%d. VPI paused. Terminated.",
8845 		    vpip->VPI,
8846 		    vpip->rpi_online, vpip->rpi_paused,
8847 		    rpip->did, rpip->RPI);
8848 
8849 		rval = 0;
8850 		break;
8851 
8852 	case VPI_STATE_ONLINE:
8853 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8854 		    "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
8855 		    "rpi=%d. Terminated.",
8856 		    vpip->VPI,
8857 		    vpip->rpi_online, vpip->rpi_paused,
8858 		    rpip->did, rpip->RPI);
8859 
8860 		rval = 0;
8861 		break;
8862 
8863 	default:
8864 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8865 		    "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
8866 		    "rpi=%d. "
8867 		    "Invalid state. Terminated.",
8868 		    vpip->VPI,
8869 		    vpip->rpi_online, vpip->rpi_paused,
8870 		    rpip->did, rpip->RPI);
8871 
8872 		rval = 1;
8873 		break;
8874 	}
8875 
8876 	return (rval);
8877 
8878 } /* emlxs_vpi_rpi_offline_evt_action() */
8879 
8880 
8881 /*ARGSUSED*/
8882 static uint32_t
8883 emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
8884     uint32_t evt, void *arg1)
8885 {
8886 	uint32_t rval;
8887 	RPIobj_t *rpip = (RPIobj_t *)arg1;
8888 
8889 	if (evt != FCF_EVENT_RPI_PAUSE) {
8890 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8891 		    "vpi_rpi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
8892 		    "Invalid event type. Terminated.",
8893 		    vpip->VPI,
8894 		    emlxs_vpi_state_xlate(vpip->state),
8895 		    emlxs_fcf_event_xlate(evt), arg1,
8896 		    vpip->flag);
8897 		return (1);
8898 	}
8899 
8900 	switch (vpip->state) {
8901 	case VPI_STATE_LOGO:
8902 		/* rpi_online will be checked when LOGO is complete */
8903 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8904 		    "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
8905 		    "rpi=%d. Waiting for LOGO. Terminated.",
8906 		    vpip->VPI,
8907 		    vpip->rpi_online, vpip->rpi_paused,
8908 		    rpip->did, rpip->RPI);
8909 
8910 		rval = 0;
8911 		break;
8912 
8913 	case VPI_STATE_PORT_OFFLINE:
8914 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8915 		    "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
8916 		    "rpi=%d.",
8917 		    vpip->VPI,
8918 		    vpip->rpi_online, vpip->rpi_paused,
8919 		    rpip->did, rpip->RPI);
8920 
8921 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
8922 		    FCF_REASON_REENTER, 0, 0);
8923 		break;
8924 
8925 	case VPI_STATE_PAUSED:
8926 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8927 		    "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
8928 		    "rpi=%d. VPI already paused. Terminated.",
8929 		    vpip->VPI,
8930 		    vpip->rpi_online, vpip->rpi_paused,
8931 		    rpip->did, rpip->RPI);
8932 
8933 		rval = 0;
8934 		break;
8935 
8936 	default:
8937 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8938 		    "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
8939 		    "rpi=%d. "
8940 		    "Invalid state. Terminated.",
8941 		    vpip->VPI,
8942 		    vpip->rpi_online, vpip->rpi_paused,
8943 		    rpip->did, rpip->RPI);
8944 
8945 		rval = 1;
8946 		break;
8947 	}
8948 
8949 	return (rval);
8950 
8951 } /* emlxs_vpi_rpi_pause_evt_action() */
8952 
8953 
8954 /*ARGSUSED*/
8955 static uint32_t
8956 emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
8957     uint32_t evt, void *arg1)
8958 {
8959 	RPIobj_t *rpip = (RPIobj_t *)arg1;
8960 
8961 	if (evt != FCF_EVENT_RPI_ONLINE) {
8962 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8963 		    "vpi_rpi_online_evt_action:%d %s:%s arg=%p flag=%x. "
8964 		    "Invalid event type. Terminated.",
8965 		    vpip->VPI,
8966 		    emlxs_vpi_state_xlate(vpip->state),
8967 		    emlxs_fcf_event_xlate(evt), arg1,
8968 		    vpip->flag);
8969 		return (1);
8970 	}
8971 
8972 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8973 	    "vpi_rpi_online_evt_action:%d rpi_online=%d,%d did=%x rpi=%d. "
8974 	    "Terminated.",
8975 	    vpip->VPI,
8976 	    vpip->rpi_online, vpip->rpi_paused,
8977 	    rpip->did, rpip->RPI);
8978 
8979 	return (0);
8980 
8981 } /* emlxs_vpi_rpi_online_evt_action() */
8982 
8983 
8984 /*ARGSUSED*/
8985 static uint32_t
8986 emlxs_vpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
8987     void *arg1)
8988 {
8989 	uint32_t rval;
8990 
8991 	if (evt != FCF_EVENT_VPI_ONLINE) {
8992 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8993 		    "vpi_online_evt_action:%d %s:%s arg=%p flag=%x. "
8994 		    "Invalid event type. Terminated.",
8995 		    vpip->VPI,
8996 		    emlxs_vpi_state_xlate(vpip->state),
8997 		    emlxs_fcf_event_xlate(evt), arg1,
8998 		    vpip->flag);
8999 		return (1);
9000 	}
9001 
9002 	if (vpip->flag & EMLXS_VPI_ONLINE_REQ) {
9003 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9004 		    "vpi_online_evt_action:%d flag=%x. "
9005 		    "Online already requested. Terminated.",
9006 		    vpip->VPI,
9007 		    vpip->flag);
9008 		return (1);
9009 	}
9010 
9011 	vpip->flag &= ~EMLXS_VPI_REQ_MASK;
9012 	vpip->flag |= EMLXS_VPI_ONLINE_REQ;
9013 
9014 	switch (vpip->state) {
9015 	case VPI_STATE_OFFLINE:
9016 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9017 		    "vpi_online_evt_action:%d flag=%x. Initiating online.",
9018 		    vpip->VPI,
9019 		    vpip->flag);
9020 
9021 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
9022 		    FCF_REASON_EVENT, evt, arg1);
9023 		break;
9024 
9025 	case VPI_STATE_PORT_OFFLINE:
9026 	case VPI_STATE_PAUSED:
9027 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9028 		    "vpi_online_evt_action:%d flag=%x. Initiating online.",
9029 		    vpip->VPI,
9030 		    vpip->flag);
9031 
9032 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
9033 		    FCF_REASON_EVENT, evt, arg1);
9034 		break;
9035 
9036 	default:
9037 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9038 		    "vpi_online_evt_action:%d flag=%x. Terminated.",
9039 		    vpip->VPI,
9040 		    vpip->flag);
9041 		return (1);
9042 	}
9043 
9044 	return (rval);
9045 
9046 } /* emlxs_vpi_online_evt_action() */
9047 
9048 
9049 /*ARGSUSED*/
9050 static uint32_t
9051 emlxs_vpi_offline_handler(emlxs_port_t *port, VPIobj_t *vpip, void *arg1)
9052 {
9053 	uint32_t rval;
9054 
9055 	if (!(vpip->flag & EMLXS_VPI_OFFLINE_REQ)) {
9056 		return (0);
9057 	}
9058 
9059 	if (vpip->flag & EMLXS_VPI_PORT_ONLINE) {
9060 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
9061 		    FCF_REASON_REQUESTED, 0, arg1);
9062 
9063 	} else if (vpip->flag & EMLXS_VPI_LOGI) {
9064 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
9065 		    FCF_REASON_REQUESTED, 0, arg1);
9066 
9067 	} else if (vpip->flag & EMLXS_VPI_REG) {
9068 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
9069 		    FCF_REASON_REQUESTED, 0, arg1);
9070 
9071 	} else if (vpip->flag & EMLXS_VPI_INIT) {
9072 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
9073 		    FCF_REASON_REQUESTED, 0, arg1);
9074 
9075 	} else {
9076 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
9077 		    FCF_REASON_REQUESTED, 0, arg1);
9078 	}
9079 
9080 	return (rval);
9081 
9082 } /* emlxs_vpi_offline_handler() */
9083 
9084 
9085 /*ARGSUSED*/
9086 static uint32_t
9087 emlxs_vpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
9088     void *arg1)
9089 {
9090 	uint32_t rval;
9091 	uint32_t pause_req;
9092 
9093 	if (evt != FCF_EVENT_VPI_OFFLINE) {
9094 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9095 		    "vpi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
9096 		    "Invalid event type. Terminated.",
9097 		    vpip->VPI,
9098 		    emlxs_vpi_state_xlate(vpip->state),
9099 		    emlxs_fcf_event_xlate(evt), arg1,
9100 		    vpip->flag);
9101 		return (1);
9102 	}
9103 
9104 	if ((vpip->flag & EMLXS_VPI_OFFLINE_REQ) &&
9105 	    !(vpip->flag & EMLXS_VPI_PAUSE_REQ)) {
9106 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9107 		    "vpi_offline_evt_action:%d flag=%x. "
9108 		    "Offline already requested. Terminated.",
9109 		    vpip->VPI,
9110 		    vpip->flag);
9111 		return (1);
9112 	}
9113 
9114 	pause_req = vpip->flag & EMLXS_VPI_PAUSE_REQ;
9115 
9116 	vpip->flag &= ~EMLXS_VPI_REQ_MASK;
9117 	vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
9118 
9119 	switch (vpip->state) {
9120 	case VPI_STATE_PORT_OFFLINE:
9121 		if (pause_req || vpip->rpi_paused) {
9122 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9123 			    "vpi_offline_evt_action:%d flag=%x. Clear nodes.",
9124 			    vpip->VPI,
9125 			    vpip->flag);
9126 
9127 			vpip->flag |= EMLXS_VPI_PORT_ONLINE;
9128 
9129 			rval = emlxs_vpi_state(port, vpip,
9130 			    VPI_STATE_PORT_OFFLINE, FCF_REASON_REENTER, evt,
9131 			    arg1);
9132 
9133 			break;
9134 		}
9135 
9136 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9137 		    "vpi_offline_evt_action:%d flag=%x. Handling offline.",
9138 		    vpip->VPI,
9139 		    vpip->flag);
9140 
9141 		/* Handle offline now */
9142 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
9143 		break;
9144 
9145 	case VPI_STATE_PAUSED:
9146 		if (vpip->rpi_paused) {
9147 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9148 			    "vpi_offline_evt_action:%d flag=%x. Clear nodes.",
9149 			    vpip->VPI,
9150 			    vpip->flag);
9151 
9152 			vpip->flag |= EMLXS_VPI_PORT_ONLINE;
9153 
9154 			rval = emlxs_vpi_state(port, vpip,
9155 			    VPI_STATE_PORT_OFFLINE, FCF_REASON_EVENT, evt,
9156 			    arg1);
9157 
9158 			break;
9159 		}
9160 
9161 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9162 		    "vpi_offline_evt_action:%d flag=%x. Handling offline.",
9163 		    vpip->VPI,
9164 		    vpip->flag);
9165 
9166 		/* Handle offline now */
9167 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
9168 		break;
9169 
9170 	/* wait states */
9171 	case VPI_STATE_UNREG:
9172 	case VPI_STATE_PORT_ONLINE:
9173 	case VPI_STATE_LOGI:
9174 	case VPI_STATE_INIT:
9175 	case VPI_STATE_REG:
9176 	case VPI_STATE_ONLINE:
9177 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9178 		    "vpi_offline_evt_action:%d flag=%x. Handling offline.",
9179 		    vpip->VPI,
9180 		    vpip->flag);
9181 
9182 		/* Handle offline now */
9183 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
9184 		break;
9185 
9186 	/* Transitional states */
9187 	default:
9188 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9189 		    "vpi_offline_evt_action:%d flag=%x. Terminated.",
9190 		    vpip->VPI,
9191 		    vpip->flag);
9192 		break;
9193 	}
9194 
9195 	return (rval);
9196 
9197 } /* emlxs_vpi_offline_evt_action() */
9198 
9199 
9200 /*ARGSUSED*/
9201 static uint32_t
9202 emlxs_vpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
9203     void *arg1)
9204 {
9205 	emlxs_hba_t *hba = HBA;
9206 	uint32_t rval;
9207 
9208 	if (evt != FCF_EVENT_VPI_PAUSE) {
9209 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9210 		    "vpi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
9211 		    "Invalid event type. Terminated.",
9212 		    vpip->VPI,
9213 		    emlxs_vpi_state_xlate(vpip->state),
9214 		    emlxs_fcf_event_xlate(evt), arg1,
9215 		    vpip->flag);
9216 		return (1);
9217 	}
9218 
9219 	if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
9220 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9221 		    "vpi_pause_evt_action:%d flag=%x. "
9222 		    "Pause already requested. Terminated.",
9223 		    vpip->VPI,
9224 		    vpip->flag);
9225 		return (1);
9226 	}
9227 
9228 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
9229 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9230 		    "vpi_pause_evt_action:%d flag=%x. "
9231 		    "Offline already requested. Terminated.",
9232 		    vpip->VPI,
9233 		    vpip->flag);
9234 		return (1);
9235 	}
9236 
9237 	if (!(hba->sli.sli4.flag & EMLXS_SLI4_DOWN_LINK)) {
9238 		/* Fabric logo is implied */
9239 		vpip->flag &= ~EMLXS_VPI_LOGI;
9240 		if (vpip->flag & EMLXS_VPI_VFI_LOGI) {
9241 			vpip->flag &= ~EMLXS_VPI_VFI_LOGI;
9242 
9243 			if (vpip->vfip->logi_count > 0) {
9244 				vpip->vfip->logi_count--;
9245 			}
9246 		}
9247 	}
9248 
9249 	switch (vpip->state) {
9250 	case VPI_STATE_PORT_OFFLINE:
9251 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9252 		    "vpi_pause_evt_action:%d flag=%x. "
9253 		    "Already offline. Terminated.",
9254 		    vpip->VPI,
9255 		    vpip->flag);
9256 		break;
9257 
9258 	case VPI_STATE_PAUSED:
9259 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9260 		    "vpi_pause_evt_action:%d flag=%x. "
9261 		    "Already paused. Terminated.",
9262 		    vpip->VPI,
9263 		    vpip->flag);
9264 		break;
9265 
9266 	/* Wait states */
9267 	case VPI_STATE_UNREG:
9268 	case VPI_STATE_PORT_ONLINE:
9269 	case VPI_STATE_LOGI:
9270 	case VPI_STATE_INIT:
9271 	case VPI_STATE_REG:
9272 	case VPI_STATE_ONLINE:
9273 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
9274 		vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
9275 
9276 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9277 		    "vpi_pause_evt_action:%d flag=%x. Handling offline.",
9278 		    vpip->VPI,
9279 		    vpip->flag);
9280 
9281 		/* Handle offline now */
9282 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
9283 		break;
9284 
9285 	/* Transitional states */
9286 	default:
9287 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
9288 		vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
9289 
9290 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9291 		    "vpi_pause_evt_action:%d flag=%x. Terminated.",
9292 		    vpip->VPI,
9293 		    vpip->flag);
9294 		break;
9295 	}
9296 
9297 	return (rval);
9298 
9299 } /* emlxs_vpi_pause_evt_action() */
9300 
9301 
9302 /* ARGSUSED */
9303 static void
9304 emlxs_pkt_cmpl_thread(emlxs_hba_t *hba,
9305 	void *arg1, void *arg2)
9306 {
9307 	emlxs_buf_t *sbp = (emlxs_buf_t *)arg1;
9308 	emlxs_pkt_complete(sbp, -1, 0, 1);
9309 
9310 	return;
9311 
9312 } /* emlxs_pkt_cmpl_thread() */
9313 
9314 
9315 /* ARGSUSED */
9316 static void
9317 emlxs_port_offline_thread(emlxs_hba_t *hba,
9318 	void *arg1, void *arg2)
9319 {
9320 	emlxs_port_t *port = (emlxs_port_t *)arg1;
9321 	uint32_t scope = (uint32_t)((uintptr_t)arg2);
9322 
9323 	(void) emlxs_port_offline(port, scope);
9324 	return;
9325 
9326 } /* emlxs_port_offline_thread() */
9327 
9328 
9329 /* ARGSUSED */
9330 static void
9331 emlxs_port_online_thread(emlxs_hba_t *hba,
9332 	void *arg1, void *arg2)
9333 {
9334 	emlxs_port_t *port = (emlxs_port_t *)arg1;
9335 
9336 	(void) emlxs_port_online(port);
9337 	return;
9338 
9339 } /* emlxs_port_online_thread() */
9340 
9341 
9342 /*ARGSUSED*/
9343 static uint32_t
9344 emlxs_vpi_port_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
9345     void *arg1)
9346 {
9347 	emlxs_hba_t *hba = HBA;
9348 	uint32_t rval = 0;
9349 	uint32_t scope;
9350 
9351 	if (vpip->state != VPI_STATE_PORT_OFFLINE) {
9352 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9353 		    "vpi_port_offline_action:%d %s:%s arg=%p. "
9354 		    "Invalid state. Terminated.",
9355 		    vpip->VPI,
9356 		    emlxs_vpi_state_xlate(vpip->state),
9357 		    emlxs_fcf_event_xlate(evt), arg1);
9358 		return (1);
9359 	}
9360 
9361 	if (vpip->flag & EMLXS_VPI_PORT_ONLINE) {
9362 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9363 		    "vpi_port_offline_action:%d flag=%x. Offline port.",
9364 		    vpip->VPI,
9365 		    vpip->flag);
9366 
9367 		vpip->flag &= ~(EMLXS_VPI_PORT_ONLINE|EMLXS_VPI_PORT_ENABLED);
9368 
9369 		if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
9370 			scope = 0xFFFFFFFF; /* Clear all non-FCP2 nodes */
9371 					    /* Pause FCP2 nodes */
9372 		} else {
9373 			scope = 0xFDFFFFFF; /* Clear all nodes */
9374 		}
9375 
9376 		emlxs_thread_spawn(hba, emlxs_port_offline_thread,
9377 		    (void *)vpip->port, (void *)((uintptr_t)scope));
9378 
9379 		if (vpip->flag & EMLXS_VPI_LOGI) {
9380 			rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
9381 			    FCF_REASON_EVENT, evt, arg1);
9382 
9383 			return (rval);
9384 		}
9385 	}
9386 
9387 	if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
9388 		if (vpip->rpi_online > vpip->rpi_paused) {
9389 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9390 			    "vpi_port_offline_action:%d rpi_online=%d,%d. "
9391 			    "Pausing. Waiting for RPI's.",
9392 			    vpip->VPI,
9393 			    vpip->rpi_online, vpip->rpi_paused);
9394 			return (0);
9395 		}
9396 
9397 		/* Take the Fabric RPI offline now */
9398 		if (vpip->rpip->state != RPI_STATE_FREE) {
9399 			(void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE,
9400 			    vpip->rpip);
9401 		}
9402 
9403 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9404 		    "vpi_port_offline_action:%d rpi_online=%d,%d. Pausing.",
9405 		    vpip->VPI,
9406 		    vpip->rpi_online, vpip->rpi_paused);
9407 
9408 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED,
9409 		    FCF_REASON_EVENT, evt, arg1);
9410 
9411 		return (rval);
9412 	}
9413 
9414 	if (vpip->rpi_online > 0) {
9415 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9416 		    "vpi_port_offline_action:%d rpi_online=%d,%d. Offlining. "
9417 		    "Waiting for RPI's.",
9418 		    vpip->VPI,
9419 		    vpip->rpi_online, vpip->rpi_paused);
9420 
9421 		return (0);
9422 	}
9423 
9424 	/* Take the Fabric RPI offline now */
9425 	if (vpip->rpip->state != RPI_STATE_FREE) {
9426 		(void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, vpip->rpip);
9427 	}
9428 
9429 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9430 	    "vpi_port_offline_action:%d rpi_online=%d,%d. Offlining. "
9431 	    "Unreg VPI.",
9432 	    vpip->VPI,
9433 	    vpip->rpi_online, vpip->rpi_paused);
9434 
9435 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
9436 	    FCF_REASON_EVENT, evt, arg1);
9437 
9438 	return (rval);
9439 
9440 } /* emlxs_vpi_port_offline_action() */
9441 
9442 
9443 /*ARGSUSED*/
9444 static uint32_t
9445 emlxs_vpi_paused_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
9446     void *arg1)
9447 {
9448 	if (vpip->state != VPI_STATE_PAUSED) {
9449 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9450 		    "vpi_paused_action:%d %s:%s arg=%p. "
9451 		    "Invalid state. Terminated.",
9452 		    vpip->VPI,
9453 		    emlxs_vpi_state_xlate(vpip->state),
9454 		    emlxs_fcf_event_xlate(evt), arg1);
9455 		return (1);
9456 	}
9457 
9458 	vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
9459 
9460 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9461 	    "vpi_paused_action:%d rpi_online=%d,%d. VPI paused.",
9462 	    vpip->VPI,
9463 	    vpip->rpi_online, vpip->rpi_paused);
9464 
9465 	return (0);
9466 
9467 } /* emlxs_vpi_paused_action() */
9468 
9469 
9470 /*ARGSUSED*/
9471 static uint32_t
9472 emlxs_vpi_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
9473     void *arg1)
9474 {
9475 	uint32_t rval;
9476 
9477 	if (vpip->state != VPI_STATE_OFFLINE) {
9478 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9479 		    "vpi_offline_action:%d %s:%s arg=%p. "
9480 		    "Invalid state. Terminated.",
9481 		    vpip->VPI,
9482 		    emlxs_vpi_state_xlate(vpip->state),
9483 		    emlxs_fcf_event_xlate(evt), arg1);
9484 		return (1);
9485 	}
9486 
9487 	if (!vpip->vfip) {
9488 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9489 		    "vpi_offline_action:%d %s:%s arg=%p flag=%x. "
9490 		    "Null vfip found. Terminated.",
9491 		    vpip->VPI,
9492 		    emlxs_vpi_state_xlate(vpip->state),
9493 		    emlxs_fcf_event_xlate(evt), arg1,
9494 		    vpip->flag);
9495 		return (1);
9496 	}
9497 
9498 	/* Take the Fabric RPI offline, if still active */
9499 	if (vpip->rpip->state != RPI_STATE_FREE) {
9500 		(void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, vpip->rpip);
9501 	}
9502 
9503 	vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
9504 
9505 	if (vpip->flag & EMLXS_VPI_VFI) {
9506 		vpip->flag &= ~EMLXS_VPI_VFI;
9507 
9508 		if (vpip->vfip->vpi_online) {
9509 			vpip->vfip->vpi_online--;
9510 		}
9511 	}
9512 
9513 	/* Check if online was requested */
9514 	if (vpip->flag & EMLXS_VPI_ONLINE_REQ) {
9515 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9516 		    "vpi_offline_action:%d vpi_online=%d. Online requested.",
9517 		    vpip->VPI,
9518 		    vpip->vfip->vpi_online);
9519 
9520 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
9521 		    FCF_REASON_REQUESTED, 0, arg1);
9522 		return (rval);
9523 	}
9524 
9525 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9526 	    "vpi_offline_action:%d vpi_online=%d. "
9527 	    "VPI offline. Notifying VFI:%d.",
9528 	    vpip->VPI,
9529 	    vpip->vfip->vpi_online,
9530 	    vpip->vfip->VFI);
9531 
9532 	/* Notify VFI */
9533 	rval = emlxs_vfi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
9534 
9535 	return (rval);
9536 
9537 } /* emlxs_vpi_offline_action() */
9538 
9539 
9540 /*ARGSUSED*/
9541 static uint32_t
9542 emlxs_vpi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
9543 {
9544 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
9545 	VPIobj_t *vpip;
9546 	MAILBOX4 *mb4;
9547 
9548 	vpip = (VPIobj_t *)mbq->context;
9549 	mb4 = (MAILBOX4 *)mbq;
9550 
9551 	mutex_enter(&EMLXS_FCF_LOCK);
9552 
9553 	if (vpip->state != VPI_STATE_INIT) {
9554 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9555 		    "vpi_init_mbcmpl:%d %s. Terminated.",
9556 		    vpip->VPI,
9557 		    emlxs_vpi_state_xlate(vpip->state));
9558 
9559 		mutex_exit(&EMLXS_FCF_LOCK);
9560 		return (0);
9561 	}
9562 
9563 	if (mb4->mbxStatus) {
9564 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9565 		    "vpi_init_mbcmpl:%d failed. status=%x",
9566 		    vpip->VPI,
9567 		    mb4->mbxStatus);
9568 
9569 		(void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED,
9570 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
9571 
9572 		mutex_exit(&EMLXS_FCF_LOCK);
9573 		return (0);
9574 	}
9575 
9576 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9577 	    "vpi_init_mbcmpl:%d Initialized.",
9578 	    vpip->VPI,
9579 	    mb4->mbxStatus);
9580 
9581 	vpip->flag |= EMLXS_VPI_INIT;
9582 	(void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL,
9583 	    0, 0, 0);
9584 
9585 	mutex_exit(&EMLXS_FCF_LOCK);
9586 	return (0);
9587 
9588 } /* emlxs_vpi_init_mbcmpl() */
9589 
9590 
9591 /*ARGSUSED*/
9592 static uint32_t
9593 emlxs_vpi_init_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
9594     void *arg1)
9595 {
9596 	emlxs_hba_t *hba = HBA;
9597 	MAILBOXQ *mbq;
9598 	MAILBOX4 *mb4;
9599 	uint32_t rval;
9600 
9601 	if (vpip->state != VPI_STATE_INIT) {
9602 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9603 		    "vpi_init_action:%d %s:%s arg=%p. "
9604 		    "Invalid state. Terminated.",
9605 		    vpip->VPI,
9606 		    emlxs_vpi_state_xlate(vpip->state),
9607 		    emlxs_fcf_event_xlate(evt), arg1);
9608 		return (1);
9609 	}
9610 
9611 	if (vpip->prev_state != VPI_STATE_INIT_FAILED) {
9612 		vpip->attempts = 0;
9613 	}
9614 
9615 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
9616 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9617 		    "vpi_init_action:%d attempts=%d. Offline requested.",
9618 		    vpip->VPI,
9619 		    vpip->attempts);
9620 
9621 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
9622 		return (rval);
9623 	}
9624 
9625 	if (!(vpip->flag & EMLXS_VPI_VFI)) {
9626 		vpip->flag |= EMLXS_VPI_VFI;
9627 		vpip->vfip->vpi_online++;
9628 	}
9629 
9630 	if (vpip->vfip->vpi_online == 1) {
9631 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9632 		    "vpi_init_action:%d vpi_online=%d. Skipping init.",
9633 		    vpip->VPI,
9634 		    vpip->vfip->vpi_online);
9635 
9636 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
9637 		    FCF_REASON_EVENT, evt, arg1);
9638 		return (rval);
9639 	}
9640 
9641 	if (vpip->flag & EMLXS_VPI_INIT) {
9642 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9643 		    "vpi_init_action:%d flag=%x. "
9644 		    "Already init'd. Skipping init.",
9645 		    vpip->VPI);
9646 
9647 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
9648 		    FCF_REASON_EVENT, evt, arg1);
9649 		return (rval);
9650 	}
9651 
9652 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9653 	    "vpi_init_action:%d vpi_online=%d attempts=%d. Sending INIT_VPI.",
9654 	    vpip->VPI,
9655 	    vpip->vfip->vpi_online,
9656 	    vpip->attempts);
9657 
9658 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
9659 		rval = emlxs_vpi_state(port, vpip, FCFI_STATE_REG_FAILED,
9660 		    FCF_REASON_NO_MBOX, 0, arg1);
9661 		return (rval);
9662 	}
9663 	mb4 = (MAILBOX4*)mbq;
9664 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
9665 
9666 	mbq->nonembed = NULL;
9667 	mbq->mbox_cmpl = emlxs_vpi_init_mbcmpl;
9668 	mbq->context = (void *)vpip;
9669 	mbq->port = (void *)port;
9670 
9671 	mb4->mbxCommand = MBX_INIT_VPI;
9672 	mb4->mbxOwner = OWN_HOST;
9673 	mb4->un.varInitVPI4.vfi = vpip->vfip->VFI;
9674 	mb4->un.varInitVPI4.vpi = vpip->VPI;
9675 
9676 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
9677 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
9678 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
9679 
9680 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED,
9681 		    FCF_REASON_SEND_FAILED, rval, arg1);
9682 
9683 		return (rval);
9684 	}
9685 
9686 	return (0);
9687 
9688 } /* emlxs_vpi_init_action() */
9689 
9690 
9691 /*ARGSUSED*/
9692 static uint32_t
9693 emlxs_vpi_init_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
9694     void *arg1)
9695 {
9696 	uint32_t rval;
9697 
9698 	vpip->attempts++;
9699 
9700 	if (vpip->state != VPI_STATE_INIT_FAILED) {
9701 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9702 		    "vpi_init_action:%d %s:%s arg=%p attempt=%d. "
9703 		    "Invalid state. Terminated.",
9704 		    vpip->VPI,
9705 		    emlxs_vpi_state_xlate(vpip->state),
9706 		    emlxs_fcf_event_xlate(evt), arg1,
9707 		    vpip->attempts);
9708 
9709 		return (1);
9710 	}
9711 
9712 	if ((vpip->reason == FCF_REASON_SEND_FAILED) ||
9713 	    (vpip->attempts >= 3)) {
9714 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9715 		    "vpi_init_action:%d attempt=%d reason=%x. Init cmpl.",
9716 		    vpip->VPI,
9717 		    vpip->attempts,
9718 		    vpip->reason);
9719 
9720 		vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
9721 
9722 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
9723 		vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
9724 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL,
9725 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
9726 	} else {
9727 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9728 		    "vpi_init_action:%d attempt=%d. Initializing.",
9729 		    vpip->VPI,
9730 		    vpip->attempts);
9731 
9732 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
9733 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
9734 	}
9735 
9736 	return (rval);
9737 
9738 } /* emlxs_vpi_init_failed_action() */
9739 
9740 
9741 /*ARGSUSED*/
9742 static uint32_t
9743 emlxs_vpi_init_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
9744     void *arg1)
9745 {
9746 	uint32_t rval;
9747 
9748 	if (vpip->state != VPI_STATE_INIT_CMPL) {
9749 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9750 		    "vpi_init_cmpl_action:%d %s:%s arg=%p. "
9751 		    "Invalid state. Terminated.",
9752 		    vpip->VPI,
9753 		    emlxs_vpi_state_xlate(vpip->state),
9754 		    emlxs_fcf_event_xlate(evt), arg1);
9755 		return (1);
9756 	}
9757 
9758 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9759 	    "vpi_init_cmpl_action:%d attempts=%d. Onlining port.",
9760 	    vpip->VPI,
9761 	    vpip->attempts);
9762 
9763 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
9764 	    FCF_REASON_EVENT, evt, arg1);
9765 	return (rval);
9766 
9767 } /* emlxs_vpi_init_cmpl_action() */
9768 
9769 
9770 /*ARGSUSED*/
9771 static uint32_t
9772 emlxs_vpi_port_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
9773     void *arg1)
9774 {
9775 	emlxs_hba_t *hba = HBA;
9776 	uint32_t rval;
9777 
9778 	if (vpip->state != VPI_STATE_PORT_ONLINE) {
9779 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9780 		    "vpi_port_online_action:%d %s:%s arg=%p. "
9781 		    "Invalid state. Terminated.",
9782 		    vpip->VPI,
9783 		    emlxs_vpi_state_xlate(vpip->state),
9784 		    emlxs_fcf_event_xlate(evt), arg1);
9785 		return (1);
9786 	}
9787 
9788 	if (vpip->flag & EMLXS_VPI_PORT_ONLINE) {
9789 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9790 		    "vpi_port_online_action:%d. Port already online.",
9791 		    vpip->VPI);
9792 	}
9793 
9794 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
9795 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9796 		    "vpi_port_online_action:%d. Offline requested.",
9797 		    vpip->VPI);
9798 
9799 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
9800 		return (rval);
9801 	}
9802 
9803 	/* Initialize the Fabric RPI */
9804 	if (vpip->rpip->state == RPI_STATE_FREE) {
9805 		(void) emlxs_rpi_alloc(port, FABRIC_DID);
9806 	}
9807 
9808 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9809 	    "vpi_port_online_action:%d vpi_online=%d. Onlining port.",
9810 	    vpip->VPI,
9811 	    vpip->vfip->vpi_online);
9812 
9813 	/* Notify ULP */
9814 	vpip->flag |= EMLXS_VPI_PORT_ONLINE;
9815 
9816 	emlxs_thread_spawn(hba, emlxs_port_online_thread,
9817 	    (void *)vpip->port, 0);
9818 
9819 	/* Wait for emlxs_vpi_logi_notify() */
9820 
9821 	return (0);
9822 
9823 } /* emlxs_vpi_port_online_action() */
9824 
9825 
9826 extern uint32_t
9827 emlxs_vpi_logi_notify(emlxs_port_t *port, emlxs_buf_t *sbp)
9828 {
9829 	VPIobj_t *vpip = &port->VPIobj;
9830 	emlxs_hba_t *hba = HBA;
9831 	uint32_t rval;
9832 
9833 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
9834 		return (1);
9835 	}
9836 
9837 	mutex_enter(&EMLXS_FCF_LOCK);
9838 
9839 	if (vpip->state == VPI_STATE_OFFLINE) {
9840 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9841 		    "port_logi_notify:%d %s. Terminated.",
9842 		    vpip->VPI,
9843 		    emlxs_vpi_state_xlate(vpip->state));
9844 
9845 		mutex_exit(&EMLXS_FCF_LOCK);
9846 
9847 		return (1);
9848 	}
9849 
9850 	if (vpip->state != VPI_STATE_PORT_ONLINE) {
9851 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9852 		    "port_logi_notify:%d %s. "
9853 		    "Invalid state. Terminated.",
9854 		    vpip->VPI,
9855 		    emlxs_vpi_state_xlate(vpip->state));
9856 
9857 		mutex_exit(&EMLXS_FCF_LOCK);
9858 
9859 		return (1);
9860 	}
9861 
9862 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI,
9863 	    0, 0, sbp);
9864 
9865 	if (rval) {
9866 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9867 		    "port_logi_notify:%d %s rval=%d.",
9868 		    vpip->VPI,
9869 		    emlxs_vpi_state_xlate(vpip->state),
9870 		    rval);
9871 	}
9872 
9873 	mutex_exit(&EMLXS_FCF_LOCK);
9874 
9875 	return (rval);
9876 
9877 } /* emlxs_vpi_logi_notify() */
9878 
9879 
9880 extern uint32_t
9881 emlxs_vpi_logi_cmpl_notify(emlxs_port_t *port, emlxs_buf_t *sbp)
9882 {
9883 	VPIobj_t *vpip = &port->VPIobj;
9884 	emlxs_hba_t *hba = HBA;
9885 	uint32_t rval;
9886 
9887 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
9888 		emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
9889 		    IOERR_NO_RESOURCES, 1);
9890 		return (1);
9891 	}
9892 
9893 	mutex_enter(&EMLXS_FCF_LOCK);
9894 
9895 	if (vpip->state != VPI_STATE_LOGI) {
9896 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9897 		    "port_logi_cmpl_notify:%d %s. "
9898 		    "Invalid state. Terminated.",
9899 		    vpip->VPI,
9900 		    emlxs_vpi_state_xlate(vpip->state));
9901 
9902 		mutex_exit(&EMLXS_FCF_LOCK);
9903 		return (1);
9904 	}
9905 
9906 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_CMPL,
9907 	    0, 0, sbp);
9908 
9909 	if (rval) {
9910 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9911 		    "port_logi_cmpl_notify:%d %s rval=%d.",
9912 		    vpip->VPI,
9913 		    emlxs_vpi_state_xlate(vpip->state),
9914 		    rval);
9915 	}
9916 
9917 	mutex_exit(&EMLXS_FCF_LOCK);
9918 
9919 	return (rval);
9920 
9921 } /* emlxs_vpi_logi_cmpl_notify() */
9922 
9923 
9924 extern uint32_t
9925 emlxs_vpi_logi_failed_notify(emlxs_port_t *port)
9926 {
9927 	emlxs_hba_t *hba = HBA;
9928 	VPIobj_t *vpip = &port->VPIobj;
9929 	uint32_t rval;
9930 
9931 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
9932 		return (1);
9933 	}
9934 
9935 	mutex_enter(&EMLXS_FCF_LOCK);
9936 
9937 	if (vpip->state != VPI_STATE_LOGI) {
9938 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9939 		    "port_logi_failed_notify:%d %s. "
9940 		    "Invalid state. Terminated.",
9941 		    vpip->VPI,
9942 		    emlxs_vpi_state_xlate(vpip->state));
9943 
9944 		mutex_exit(&EMLXS_FCF_LOCK);
9945 
9946 		return (1);
9947 	}
9948 
9949 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_FAILED,
9950 	    FCF_REASON_OP_FAILED, 1, 0);
9951 
9952 	if (rval) {
9953 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9954 		    "port_logi_failed_notify:%d %s rval=%d.",
9955 		    vpip->VPI,
9956 		    emlxs_vpi_state_xlate(vpip->state),
9957 		    rval);
9958 	}
9959 
9960 	mutex_exit(&EMLXS_FCF_LOCK);
9961 
9962 	return (rval);
9963 
9964 } /* emlxs_vpi_logi_failed_notify() */
9965 
9966 
9967 /*ARGSUSED*/
9968 static uint32_t
9969 emlxs_vpi_logi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
9970     void *arg1)
9971 {
9972 	emlxs_buf_t *sbp = (emlxs_buf_t *)arg1;
9973 	fc_packet_t *pkt = PRIV2PKT(sbp);
9974 	uint32_t rval;
9975 
9976 	if (vpip->state != VPI_STATE_LOGI) {
9977 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9978 		    "vpi_logi_action:%d %s:%s arg=%p. "
9979 		    "Invalid state. Terminated.",
9980 		    vpip->VPI,
9981 		    emlxs_vpi_state_xlate(vpip->state),
9982 		    emlxs_fcf_event_xlate(evt), arg1);
9983 		return (1);
9984 	}
9985 
9986 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
9987 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9988 		    "vpi_logi_action:%d. Offline requested.",
9989 		    vpip->VPI);
9990 
9991 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
9992 		return (rval);
9993 	}
9994 
9995 	if (vpip->flag & EMLXS_VPI_LOGI) {
9996 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9997 		    "vpi_logi_action:%d flag=%x. LOGI already set.",
9998 		    vpip->VPI);
9999 
10000 		vpip->flag &= ~EMLXS_VPI_LOGI;
10001 		if (vpip->flag & EMLXS_VPI_VFI_LOGI) {
10002 			vpip->flag &= ~EMLXS_VPI_VFI_LOGI;
10003 
10004 			if (vpip->vfip->logi_count > 0) {
10005 				vpip->vfip->logi_count--;
10006 			}
10007 		}
10008 	}
10009 
10010 	/* Set login command based on vfi logi_count */
10011 	if (vpip->vfip->logi_count == 0) {
10012 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10013 		    "vpi_logi_action:%d logi_count=%d. FLOGI set.",
10014 		    vpip->VPI,
10015 		    vpip->vfip->logi_count);
10016 
10017 		*((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FLOGI;
10018 	} else {
10019 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10020 		    "vpi_logi_action:%d logi_count=%d. FDISC set.",
10021 		    vpip->VPI,
10022 		    vpip->vfip->logi_count);
10023 
10024 		*((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FDISC;
10025 	}
10026 
10027 	vpip->vfip->logi_count++;
10028 	vpip->flag |= EMLXS_VPI_VFI_LOGI;
10029 
10030 	return (0);
10031 
10032 } /* emlxs_vpi_logi_action() */
10033 
10034 
10035 /*ARGSUSED*/
10036 static uint32_t
10037 emlxs_vpi_logi_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10038     void *arg1)
10039 {
10040 	uint32_t rval;
10041 
10042 	if (vpip->state != VPI_STATE_LOGI_FAILED) {
10043 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10044 		    "vpi_logi_failed_action:%d %s:%s arg=%p. "
10045 		    "Invalid state. Terminated.",
10046 		    vpip->VPI,
10047 		    emlxs_vpi_state_xlate(vpip->state),
10048 		    emlxs_fcf_event_xlate(evt), arg1);
10049 		return (1);
10050 	}
10051 
10052 	vpip->flag &= ~EMLXS_VPI_LOGI;
10053 	if (vpip->flag & EMLXS_VPI_VFI_LOGI) {
10054 		vpip->flag &= ~EMLXS_VPI_VFI_LOGI;
10055 
10056 		if (vpip->vfip->logi_count > 0) {
10057 			vpip->vfip->logi_count--;
10058 		}
10059 	}
10060 
10061 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10062 	    "vpi_logi_failed_action:%d. Requesting offline.",
10063 	    vpip->VPI);
10064 
10065 	vpip->flag &= ~EMLXS_VPI_REQ_MASK;
10066 	vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
10067 	rval = emlxs_vpi_offline_handler(port, vpip, arg1);
10068 
10069 	return (rval);
10070 
10071 } /* emlxs_vpi_logi_failed_action() */
10072 
10073 
10074 static void
10075 emlxs_vpi_flogi_cmpl(emlxs_port_t *port, VPIobj_t *vpip, uint32_t status)
10076 {
10077 	emlxs_hba_t *hba = HBA;
10078 	emlxs_buf_t *sbp;
10079 
10080 	sbp = vpip->flogi_sbp;
10081 	if (!sbp) {
10082 		return;
10083 	}
10084 	vpip->flogi_sbp = NULL;
10085 
10086 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10087 	    "vpi_flogi_cmpl:%d. status=%x",
10088 	    vpip->VPI,
10089 	    status);
10090 
10091 	sbp->pkt_flags &= ~PACKET_STATE_VALID;
10092 
10093 	if (status) {
10094 		emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
10095 		    IOERR_NO_RESOURCES, 1);
10096 	} else {
10097 		emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1);
10098 	}
10099 
10100 	emlxs_thread_spawn(hba, emlxs_pkt_cmpl_thread, (void *)sbp, 0);
10101 
10102 	return;
10103 
10104 } /* emlxs_vpi_flogi_cmpl() */
10105 
10106 
10107 /*ARGSUSED*/
10108 static uint32_t
10109 emlxs_vpi_logi_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10110     void *arg1)
10111 {
10112 	uint32_t rval;
10113 	SERV_PARM *sp;
10114 	fc_packet_t *pkt;
10115 	emlxs_buf_t *sbp;
10116 	char buffer1[64];
10117 	char buffer2[64];
10118 
10119 	if (vpip->state != VPI_STATE_LOGI_CMPL) {
10120 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10121 		    "vpi_logi_cmpl_action:%d %s:%s arg=%p. "
10122 		    "Invalid state. Terminated.",
10123 		    vpip->VPI,
10124 		    emlxs_vpi_state_xlate(vpip->state),
10125 		    emlxs_fcf_event_xlate(evt), arg1);
10126 		return (1);
10127 	}
10128 
10129 	vpip->flag |= EMLXS_VPI_LOGI;
10130 
10131 	sbp = (emlxs_buf_t *)arg1;
10132 	if (!sbp) {
10133 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10134 		    "vpi_logi_cmpl_action:%d. Null sbp. Terminated.",
10135 		    vpip->VPI);
10136 		return (1);
10137 	}
10138 
10139 	/* Check login parameters */
10140 	pkt = PRIV2PKT(sbp);
10141 	sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t));
10142 
10143 	/* For safety */
10144 	if (vpip->flogi_sbp) {
10145 		emlxs_vpi_flogi_cmpl(port, vpip, 1);
10146 	}
10147 	vpip->flogi_sbp = sbp;
10148 
10149 	/* Update the Fabric RPI */
10150 	bcopy((void *)sp, (void *)&vpip->rpip->sparam, sizeof (SERV_PARM));
10151 
10152 	if (vpip->vfip->vpi_online == 1) {
10153 		bcopy((void *)sp, (void *)&vpip->vfip->fcf_sparam,
10154 		    sizeof (SERV_PARM));
10155 	}
10156 
10157 	if (port->prev_did &&
10158 	    ((port->prev_did != port->did) ||
10159 	    bcmp(&port->prev_fabric_sparam.portName,
10160 	    &port->fabric_sparam.portName, 8)) &&
10161 	    emlxs_nport_count(port)) {
10162 
10163 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10164 		    "vpi_logi_cmpl_action:%d. "
10165 		    "New fabric. Offlining port.",
10166 		    vpip->VPI);
10167 
10168 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10169 		    "vpi_logi_cmpl_action: prev_wwpn=%s wwpn=%s prev_did=%x "
10170 		    "did=%x.",
10171 		    emlxs_wwn_xlate(buffer1,
10172 		    (uint8_t *)&port->prev_fabric_sparam.portName),
10173 		    emlxs_wwn_xlate(buffer2,
10174 		    (uint8_t *)&port->fabric_sparam.portName),
10175 		    port->prev_did, port->did);
10176 
10177 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
10178 		vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
10179 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
10180 
10181 		return (rval);
10182 	}
10183 
10184 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10185 	    "vpi_logi_cmpl_action:%d. Registering.",
10186 	    vpip->VPI);
10187 
10188 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
10189 	    FCF_REASON_EVENT, evt, arg1);
10190 
10191 	return (rval);
10192 
10193 } /* emlxs_vpi_logi_cmpl_action() */
10194 
10195 
10196 /*ARGSUSED*/
10197 static uint32_t
10198 emlxs_vpi_logo_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10199     void *arg1)
10200 {
10201 	emlxs_hba_t *hba = HBA;
10202 	uint32_t rval;
10203 
10204 	vpip->attempts++;
10205 
10206 	if (vpip->state != VPI_STATE_LOGO_FAILED) {
10207 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10208 		    "vpi_logo_failed_action:%d %s:%s arg=%p attempt=%d. "
10209 		    "Invalid state. Terminated.",
10210 		    vpip->VPI,
10211 		    emlxs_vpi_state_xlate(vpip->state),
10212 		    emlxs_fcf_event_xlate(evt), arg1,
10213 		    vpip->attempts);
10214 
10215 		return (1);
10216 	}
10217 
10218 	if (hba->state <= FC_LINK_DOWN) {
10219 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10220 		    "vpi_logo_failed_action:%d attempt=%d. Logo cmpl.",
10221 		    vpip->VPI,
10222 		    vpip->attempts);
10223 
10224 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL,
10225 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
10226 	} else if (vpip->attempts >= 3) {
10227 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10228 		    "vpi_logo_failed_action:%d attempt=%d. Logo cmpl.",
10229 		    vpip->VPI,
10230 		    vpip->attempts);
10231 
10232 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL,
10233 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
10234 	} else {
10235 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10236 		    "vpi_logo_failed_action:%d attempt=%d. Logging out.",
10237 		    vpip->VPI,
10238 		    vpip->attempts);
10239 
10240 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
10241 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
10242 	}
10243 
10244 	return (rval);
10245 
10246 } /* emlxs_vpi_logo_failed_action() */
10247 
10248 
10249 /*ARGSUSED*/
10250 static uint32_t
10251 emlxs_vpi_logo_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10252     void *arg1)
10253 {
10254 	emlxs_hba_t *hba = HBA;
10255 	emlxs_port_t *vport = vpip->port;
10256 	uint32_t rval;
10257 	uint32_t did;
10258 	uint32_t sid;
10259 	fc_packet_t *pkt;
10260 	ELS_PKT *els;
10261 
10262 	if (vpip->state != VPI_STATE_LOGO) {
10263 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10264 		    "vpi_logo_action:%d %s:%s arg=%p. "
10265 		    "Invalid state. Terminated.",
10266 		    vpip->VPI,
10267 		    emlxs_vpi_state_xlate(vpip->state),
10268 		    emlxs_fcf_event_xlate(evt), arg1);
10269 
10270 		return (1);
10271 	}
10272 
10273 	if (!(vpip->flag & EMLXS_VPI_LOGI)) {
10274 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10275 		    "vpi_logo_action:%d. No login. Skipping logo.",
10276 		    vpip->VPI);
10277 
10278 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
10279 		    FCF_REASON_EVENT, evt, arg1);
10280 		return (rval);
10281 	}
10282 
10283 	if (!(hba->flag & FC_ONLINE_MODE)) {
10284 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10285 		    "vpi_logo_action:%d. HBA offline. Skipping logo.",
10286 		    vpip->VPI);
10287 
10288 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
10289 		    FCF_REASON_EVENT, evt, arg1);
10290 		return (rval);
10291 	}
10292 
10293 	if (vpip->prev_state != VPI_STATE_LOGO_FAILED) {
10294 		vpip->attempts = 0;
10295 	}
10296 
10297 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10298 	    "vpi_logo_action:%d. Sending logo. Sending LOGO.",
10299 	    vpip->VPI,
10300 	    vpip->attempts);
10301 
10302 	pkt = emlxs_pkt_alloc(vport,
10303 	    (sizeof (uint32_t) + sizeof (LOGO)),
10304 	    (sizeof (uint32_t) + sizeof (LOGO)), 0, KM_NOSLEEP);
10305 
10306 	if (!pkt) {
10307 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED,
10308 		    FCF_REASON_NO_PKT, 0, arg1);
10309 
10310 		return (rval);
10311 	}
10312 
10313 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
10314 	pkt->pkt_timeout = (2 * hba->fc_ratov);
10315 
10316 	/* Build the fc header */
10317 	did = FABRIC_DID;
10318 	sid = (vport->did)? vport->did:vport->prev_did;
10319 
10320 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
10321 	pkt->pkt_cmd_fhdr.r_ctl =
10322 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
10323 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid);
10324 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
10325 	pkt->pkt_cmd_fhdr.f_ctl =
10326 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
10327 	pkt->pkt_cmd_fhdr.seq_id = 0;
10328 	pkt->pkt_cmd_fhdr.df_ctl = 0;
10329 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
10330 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
10331 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
10332 	pkt->pkt_cmd_fhdr.ro = 0;
10333 
10334 	/* Build the command */
10335 	els = (ELS_PKT *)pkt->pkt_cmd;
10336 	els->elsCode = 0x05;
10337 	els->un.logo.un.nPortId32 = pkt->pkt_cmd_fhdr.s_id;
10338 	bcopy((uint8_t *)&vport->wwpn,
10339 	    (uint8_t *)&els->un.logo.portName, 8);
10340 
10341 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10342 	    "vpi_logo_action:%d  LOGO:sid=%x did=%x.",
10343 	    vpip->VPI,
10344 	    sid, did);
10345 
10346 	/* Send the pkt now */
10347 	rval = emlxs_pkt_send(pkt, 1);
10348 	if (rval != FC_SUCCESS) {
10349 		/* Free the pkt */
10350 		emlxs_pkt_free(pkt);
10351 
10352 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED,
10353 		    FCF_REASON_SEND_FAILED, rval, arg1);
10354 
10355 		return (rval);
10356 	}
10357 
10358 	/* For now we will send and forget */
10359 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL,
10360 	    FCF_REASON_EVENT, evt, arg1);
10361 
10362 	return (rval);
10363 
10364 } /* emlxs_vpi_logo_action() */
10365 
10366 
10367 /*ARGSUSED*/
10368 static uint32_t
10369 emlxs_vpi_logo_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10370     void *arg1)
10371 {
10372 	uint32_t rval;
10373 
10374 	if (vpip->state != VPI_STATE_LOGO_CMPL) {
10375 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10376 		    "vpi_logo_cmpl_action:%d %s:%s arg=%p. "
10377 		    "Invalid state. Terminated.",
10378 		    vpip->VPI,
10379 		    emlxs_vpi_state_xlate(vpip->state),
10380 		    emlxs_fcf_event_xlate(evt), arg1);
10381 		return (1);
10382 	}
10383 
10384 	vpip->flag &= ~EMLXS_VPI_LOGI;
10385 	if (vpip->flag & EMLXS_VPI_VFI_LOGI) {
10386 		vpip->flag &= ~EMLXS_VPI_VFI_LOGI;
10387 
10388 		if (vpip->vfip->logi_count > 0) {
10389 			vpip->vfip->logi_count--;
10390 		}
10391 	}
10392 
10393 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10394 	    "vpi_logo_cmpl_action:%d attempts=%d. Offline RPI's.",
10395 	    vpip->VPI,
10396 	    vpip->attempts);
10397 
10398 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
10399 	    FCF_REASON_EVENT, evt, arg1);
10400 
10401 	return (rval);
10402 
10403 } /* emlxs_vpi_logo_cmpl_action() */
10404 
10405 
10406 /*ARGSUSED*/
10407 static uint32_t
10408 emlxs_vpi_unreg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10409     void *arg1)
10410 {
10411 	uint32_t rval;
10412 
10413 	vpip->attempts++;
10414 
10415 	if (vpip->state != VPI_STATE_UNREG_FAILED) {
10416 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10417 		    "vpi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
10418 		    "Invalid state. Terminated.",
10419 		    vpip->VPI,
10420 		    emlxs_vpi_state_xlate(vpip->state),
10421 		    emlxs_fcf_event_xlate(evt), arg1,
10422 		    vpip->attempts);
10423 
10424 		return (1);
10425 	}
10426 
10427 	if ((vpip->reason == FCF_REASON_SEND_FAILED) ||
10428 	    (vpip->attempts >= 3)) {
10429 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10430 		    "vpi_unreg_failed_action:%d attempt=%d. Unreg cmpl.",
10431 		    vpip->VPI,
10432 		    vpip->attempts);
10433 
10434 		vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
10435 
10436 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
10437 		vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
10438 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL,
10439 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
10440 	} else {
10441 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10442 		    "vpi_unreg_failed_action:%d attempt=%d. Unregistering.",
10443 		    vpip->VPI,
10444 		    vpip->attempts);
10445 
10446 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
10447 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
10448 	}
10449 
10450 	return (rval);
10451 
10452 } /* emlxs_vpi_unreg_failed_action() */
10453 
10454 
10455 /*ARGSUSED*/
10456 static uint32_t
10457 emlxs_vpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
10458 {
10459 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
10460 	MAILBOX4 *mb4;
10461 	VPIobj_t *vpip;
10462 
10463 	vpip = (VPIobj_t *)mbq->context;
10464 	mb4 = (MAILBOX4 *)mbq;
10465 
10466 	mutex_enter(&EMLXS_FCF_LOCK);
10467 
10468 	if (vpip->state != VPI_STATE_UNREG) {
10469 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10470 		    "vpi_unreg_mbcmpl:%d state=%s. Terminated.",
10471 		    vpip->VPI,
10472 		    emlxs_vpi_state_xlate(vpip->state));
10473 
10474 		mutex_exit(&EMLXS_FCF_LOCK);
10475 		return (0);
10476 	}
10477 
10478 	if (mb4->mbxStatus) {
10479 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10480 		    "vpi_unreg_mbcmpl:%d failed. status=%x",
10481 		    vpip->VPI,
10482 		    mb4->mbxStatus);
10483 
10484 		(void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
10485 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
10486 
10487 		mutex_exit(&EMLXS_FCF_LOCK);
10488 		return (0);
10489 	}
10490 
10491 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10492 	    "vpi_unreg_mbcmpl:%d Unregistered.",
10493 	    vpip->VPI);
10494 
10495 	vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
10496 	(void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL, 0, 0, 0);
10497 
10498 	mutex_exit(&EMLXS_FCF_LOCK);
10499 	return (0);
10500 
10501 } /* emlxs_vpi_unreg_mbcmpl() */
10502 
10503 
10504 /*ARGSUSED*/
10505 static uint32_t
10506 emlxs_vpi_unreg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10507     void *arg1)
10508 {
10509 	emlxs_hba_t *hba = HBA;
10510 	MAILBOX4 *mb4;
10511 	MAILBOXQ *mbq;
10512 	uint32_t rval;
10513 
10514 	if (vpip->state != VPI_STATE_UNREG) {
10515 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10516 		    "vpi_unreg_action:%d %s:%s arg=%p. "
10517 		    "Invalid state. Terminated.",
10518 		    vpip->VPI,
10519 		    emlxs_vpi_state_xlate(vpip->state),
10520 		    emlxs_fcf_event_xlate(evt), arg1);
10521 
10522 		return (1);
10523 	}
10524 
10525 	if ((vpip->rpi_online > 0) ||
10526 	    (vpip->rpip->state != RPI_STATE_FREE)) {
10527 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10528 		    "vpi_unreg_action:%d rpi_online=%d,%d. Waiting for RPI's.",
10529 		    vpip->VPI,
10530 		    vpip->rpi_online, vpip->rpi_paused);
10531 
10532 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
10533 		    FCF_REASON_EVENT, evt, arg1);
10534 		return (rval);
10535 	}
10536 
10537 	if (!(vpip->flag & EMLXS_VPI_REG)) {
10538 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10539 		    "vpi_unreg_action:%d. Not registered. Skipping unreg.",
10540 		    vpip->VPI);
10541 
10542 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
10543 		    FCF_REASON_EVENT, evt, arg1);
10544 		return (rval);
10545 	}
10546 
10547 	if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
10548 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10549 		    "vpi_unreg_action:%d rpi_online=%d,%d. Pausing.",
10550 		    vpip->VPI,
10551 		    vpip->rpi_online, vpip->rpi_paused);
10552 
10553 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED,
10554 		    FCF_REASON_EVENT, evt, arg1);
10555 		return (rval);
10556 	}
10557 
10558 	if (vpip->prev_state != VPI_STATE_UNREG_FAILED) {
10559 		vpip->attempts = 0;
10560 	}
10561 
10562 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10563 	    "vpi_unreg_action:%d attempts=%d. Sending UNREG_VPI.",
10564 	    vpip->VPI,
10565 	    vpip->attempts);
10566 
10567 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
10568 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
10569 		    FCF_REASON_NO_MBOX, 0, arg1);
10570 
10571 		return (rval);
10572 	}
10573 	mb4 = (MAILBOX4*)mbq;
10574 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
10575 
10576 	mbq->nonembed = NULL;
10577 	mbq->mbox_cmpl = emlxs_vpi_unreg_mbcmpl;
10578 	mbq->context = (void *)vpip;
10579 	mbq->port = (void *)vpip->port;
10580 
10581 	mb4->un.varUnRegVPI4.ii = 0; /* index is a VPI */
10582 	mb4->un.varUnRegVPI4.index = vpip->VPI;
10583 	mb4->mbxCommand = MBX_UNREG_VPI;
10584 	mb4->mbxOwner = OWN_HOST;
10585 
10586 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
10587 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
10588 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10589 
10590 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
10591 		    FCF_REASON_SEND_FAILED, rval, arg1);
10592 
10593 		return (rval);
10594 	}
10595 
10596 	return (0);
10597 
10598 } /* emlxs_vpi_unreg_action() */
10599 
10600 
10601 /*ARGSUSED*/
10602 static uint32_t
10603 emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10604     void *arg1)
10605 {
10606 	uint32_t rval;
10607 
10608 	if (vpip->state != VPI_STATE_UNREG_CMPL) {
10609 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10610 		    "vpi_unreg_cmpl_action:%d %s:%s arg=%p. "
10611 		    "Invalid state. Terminated.",
10612 		    vpip->VPI,
10613 		    emlxs_vpi_state_xlate(vpip->state),
10614 		    emlxs_fcf_event_xlate(evt), arg1);
10615 		return (1);
10616 	}
10617 
10618 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10619 	    "vpi_unreg_cmpl_action:%d attempts=%d. Going offline.",
10620 	    vpip->VPI,
10621 	    vpip->attempts);
10622 
10623 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
10624 	    FCF_REASON_EVENT, evt, arg1);
10625 
10626 	return (rval);
10627 
10628 } /* emlxs_vpi_unreg_cmpl_action() */
10629 
10630 
10631 /*ARGSUSED*/
10632 static uint32_t
10633 emlxs_vpi_reg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10634     void *arg1)
10635 {
10636 	uint32_t rval;
10637 
10638 	vpip->attempts++;
10639 
10640 	if (vpip->state != VPI_STATE_REG_FAILED) {
10641 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10642 		    "vpi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
10643 		    "Invalid state. Terminated.",
10644 		    vpip->VPI,
10645 		    emlxs_vpi_state_xlate(vpip->state),
10646 		    emlxs_fcf_event_xlate(evt), arg1,
10647 		    vpip->attempts);
10648 		return (1);
10649 	}
10650 
10651 	if ((vpip->reason == FCF_REASON_SEND_FAILED) ||
10652 	    (vpip->attempts >= 3)) {
10653 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10654 		    "vpi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.",
10655 		    vpip->VPI,
10656 		    vpip->attempts,
10657 		    vpip->reason);
10658 
10659 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
10660 		vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
10661 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL,
10662 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
10663 	} else {
10664 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10665 		    "vpi_reg_failed_action:%d attempt=%d. Registering.",
10666 		    vpip->VPI,
10667 		    vpip->attempts);
10668 
10669 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
10670 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
10671 	}
10672 
10673 	return (rval);
10674 
10675 } /* emlxs_vpi_reg_failed_action() */
10676 
10677 
10678 /*ARGSUSED*/
10679 static uint32_t
10680 emlxs_vpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
10681 {
10682 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
10683 	MAILBOX4 *mb4;
10684 	VPIobj_t *vpip;
10685 
10686 	vpip = (VPIobj_t *)mbq->context;
10687 	mb4 = (MAILBOX4 *)mbq;
10688 
10689 	mutex_enter(&EMLXS_FCF_LOCK);
10690 
10691 	if (vpip->state != VPI_STATE_REG) {
10692 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10693 		    "vpi_reg_mbcmpl:%d state=%s. Terminated.",
10694 		    vpip->VPI,
10695 		    emlxs_vpi_state_xlate(vpip->state));
10696 
10697 		mutex_exit(&EMLXS_FCF_LOCK);
10698 		return (0);
10699 	}
10700 
10701 	if (mb4->mbxStatus) {
10702 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10703 		    "vpi_reg_mbcmpl:%d failed. status=%x",
10704 		    vpip->VPI,
10705 		    mb4->mbxStatus);
10706 
10707 		(void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
10708 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
10709 
10710 		mutex_exit(&EMLXS_FCF_LOCK);
10711 		return (0);
10712 	}
10713 
10714 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10715 	    "vpi_reg_mbcmpl:%d. Registered.",
10716 	    vpip->VPI);
10717 
10718 	vpip->flag |= EMLXS_VPI_REG;
10719 	(void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL,
10720 	    0, 0, 0);
10721 
10722 	mutex_exit(&EMLXS_FCF_LOCK);
10723 	return (0);
10724 
10725 } /* emlxs_vpi_reg_mbcmpl() */
10726 
10727 
10728 /*ARGSUSED*/
10729 static uint32_t
10730 emlxs_vpi_reg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10731     void *arg1)
10732 {
10733 	emlxs_hba_t *hba = HBA;
10734 	uint32_t *wwpn;
10735 	MAILBOX *mb;
10736 	MAILBOXQ *mbq;
10737 	uint32_t rval;
10738 
10739 	if (vpip->state != VPI_STATE_REG) {
10740 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10741 		    "vpi_reg_action:%d %s:%s arg=%p. "
10742 		    "Invalid state. Terminated.",
10743 		    vpip->VPI,
10744 		    emlxs_vpi_state_xlate(vpip->state),
10745 		    emlxs_fcf_event_xlate(evt), arg1);
10746 		return (1);
10747 	}
10748 
10749 	if (vpip->prev_state != VPI_STATE_REG_FAILED) {
10750 		vpip->attempts = 0;
10751 	}
10752 
10753 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
10754 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10755 		    "vpi_reg_action:%d attempts=%d. Offline requested.",
10756 		    vpip->VPI,
10757 		    vpip->attempts);
10758 
10759 		rval = emlxs_vpi_offline_handler(port, vpip, 0);
10760 		return (rval);
10761 	}
10762 
10763 	if (!(vpip->flag & EMLXS_VPI_REG) &&
10764 	    (vpip->vfip->vpi_online == 1)) {
10765 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10766 		    "vpi_reg_action:%d. First vpi. Skipping reg.",
10767 		    vpip->VPI);
10768 
10769 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE,
10770 		    FCF_REASON_EVENT, evt, arg1);
10771 
10772 		return (rval);
10773 	}
10774 
10775 	if (vpip->flag & EMLXS_VPI_REG) {
10776 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10777 		    "vpi_reg_action:%d attempts=%d. Updating REG_VPI.",
10778 		    vpip->VPI,
10779 		    vpip->attempts);
10780 	} else {
10781 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10782 		    "vpi_reg_action:%d attempts=%d. Sending REG_VPI.",
10783 		    vpip->VPI,
10784 		    vpip->attempts);
10785 	}
10786 
10787 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
10788 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
10789 		    FCF_REASON_NO_MBOX, 0, arg1);
10790 
10791 		return (rval);
10792 	}
10793 	mb = (MAILBOX*)mbq;
10794 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
10795 
10796 	mbq->nonembed = NULL;
10797 	mbq->mbox_cmpl = emlxs_vpi_reg_mbcmpl;
10798 	mbq->context = (void *)vpip;
10799 	mbq->port = (void *)vpip->port;
10800 
10801 	mb->un.varRegVpi.vfi = vpip->vfip->VFI;
10802 	mb->un.varRegVpi.upd = (vpip->flag & EMLXS_VPI_REG)? 1:0;
10803 
10804 	wwpn = (uint32_t *)&port->wwpn;
10805 	mb->un.varRegVpi.portname[0] = BE_SWAP32(*wwpn);
10806 	wwpn++;
10807 	mb->un.varRegVpi.portname[1] = BE_SWAP32(*wwpn);
10808 
10809 	mb->un.varRegVpi.vpi = vpip->VPI;
10810 	mb->un.varRegVpi.sid = vpip->port->did;
10811 	mb->mbxCommand = MBX_REG_VPI;
10812 	mb->mbxOwner = OWN_HOST;
10813 
10814 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
10815 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
10816 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10817 
10818 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
10819 		    FCF_REASON_SEND_FAILED, rval, arg1);
10820 
10821 		return (rval);
10822 	}
10823 
10824 	return (0);
10825 
10826 } /* emlxs_vpi_reg_action() */
10827 
10828 
10829 /*ARGSUSED*/
10830 static uint32_t
10831 emlxs_vpi_reg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10832     void *arg1)
10833 {
10834 	uint32_t rval;
10835 
10836 	if (vpip->state != VPI_STATE_REG_CMPL) {
10837 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10838 		    "vpi_reg_cmpl_action:%d %s:%s arg=%p. "
10839 		    "Invalid state. Terminated.",
10840 		    vpip->VPI,
10841 		    emlxs_vpi_state_xlate(vpip->state),
10842 		    emlxs_fcf_event_xlate(evt), arg1);
10843 		return (1);
10844 	}
10845 
10846 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
10847 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10848 		    "vpi_reg_cmpl_action:%d attempts=%d. Offline requested.",
10849 		    vpip->VPI,
10850 		    vpip->attempts);
10851 
10852 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
10853 		return (rval);
10854 	}
10855 
10856 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10857 	    "vpi_reg_cmpl_action:%d attempts=%d. Going online.",
10858 	    vpip->VPI,
10859 	    vpip->attempts);
10860 
10861 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE,
10862 	    FCF_REASON_EVENT, evt, arg1);
10863 
10864 	return (rval);
10865 
10866 } /* emlxs_vpi_reg_cmpl_action() */
10867 
10868 
10869 /*ARGSUSED*/
10870 static uint32_t
10871 emlxs_vpi_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
10872     void *arg1)
10873 {
10874 	uint32_t rval;
10875 
10876 	if (vpip->state != VPI_STATE_ONLINE) {
10877 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10878 		    "vpi_online_action:%d %s:%s arg=%p. "
10879 		    "Invalid state. Terminated.",
10880 		    vpip->VPI,
10881 		    emlxs_vpi_state_xlate(vpip->state),
10882 		    emlxs_fcf_event_xlate(evt), arg1);
10883 		return (1);
10884 	}
10885 
10886 	vpip->flag &= ~EMLXS_VPI_ONLINE_REQ;
10887 
10888 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
10889 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10890 		    "vpi_online_action:%d attempts=%d. Offline requested.",
10891 		    vpip->VPI,
10892 		    vpip->attempts);
10893 
10894 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
10895 		return (rval);
10896 	}
10897 
10898 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10899 	    "vpi_online_action:%d. VPI online. Notifying VFI:%d",
10900 	    vpip->VPI,
10901 	    vpip->vfip->VFI);
10902 
10903 	/* Notify VFI */
10904 	rval = emlxs_vfi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
10905 
10906 	return (rval);
10907 
10908 } /* emlxs_vpi_online_action() */
10909 
10910 
10911 /* ************************************************************************** */
10912 /* RPI */
10913 /* ************************************************************************** */
10914 
10915 static char *
10916 emlxs_rpi_state_xlate(uint32_t state)
10917 {
10918 	static char buffer[32];
10919 	uint32_t i;
10920 	uint32_t count;
10921 
10922 	count = sizeof (emlxs_rpi_state_table) / sizeof (emlxs_table_t);
10923 	for (i = 0; i < count; i++) {
10924 		if (state == emlxs_rpi_state_table[i].code) {
10925 			return (emlxs_rpi_state_table[i].string);
10926 		}
10927 	}
10928 
10929 	(void) sprintf(buffer, "state=0x%x", state);
10930 	return (buffer);
10931 
10932 } /* emlxs_rpi_state_xlate() */
10933 
10934 
10935 static uint32_t
10936 emlxs_rpi_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
10937     void *arg1)
10938 {
10939 	uint32_t rval;
10940 	uint32_t(*func) (emlxs_port_t *, RPIobj_t *, uint32_t, void *);
10941 	uint32_t index;
10942 	uint32_t events;
10943 	uint16_t state;
10944 
10945 	/* Convert event to action table index */
10946 	switch (evt) {
10947 	case FCF_EVENT_STATE_ENTER:
10948 		index = 0;
10949 		break;
10950 	case FCF_EVENT_RPI_ONLINE:
10951 		index = 1;
10952 		break;
10953 	case FCF_EVENT_RPI_OFFLINE:
10954 		index = 2;
10955 		break;
10956 	case FCF_EVENT_RPI_PAUSE:
10957 		index = 3;
10958 		break;
10959 	case FCF_EVENT_RPI_RESUME:
10960 		index = 4;
10961 		break;
10962 	default:
10963 		return (1);
10964 	}
10965 
10966 	events = RPI_ACTION_EVENTS;
10967 	state  = rpip->state;
10968 
10969 	index += (state * events);
10970 	func   = (uint32_t(*) (emlxs_port_t *, RPIobj_t *, uint32_t, void *))
10971 	    emlxs_rpi_action_table[index];
10972 
10973 	if (!func) {
10974 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
10975 		    "rpi:%d %s:%s arg=%p. No action. Terminated.",
10976 		    rpip->RPI,
10977 		    emlxs_rpi_state_xlate(rpip->state),
10978 		    emlxs_fcf_event_xlate(evt), arg1);
10979 
10980 		return (1);
10981 	}
10982 
10983 	rval = (func)(port, rpip, evt, arg1);
10984 
10985 	return (rval);
10986 
10987 } /* emlxs_rpi_action() */
10988 
10989 
10990 static uint32_t
10991 emlxs_rpi_event(emlxs_port_t *port, uint32_t evt,
10992     void *arg1)
10993 {
10994 	RPIobj_t *rpip = NULL;
10995 	uint32_t rval;
10996 
10997 	/* Filter events and acquire fcfi context */
10998 	switch (evt) {
10999 	case FCF_EVENT_RPI_ONLINE:
11000 	case FCF_EVENT_RPI_OFFLINE:
11001 	case FCF_EVENT_RPI_PAUSE:
11002 	case FCF_EVENT_RPI_RESUME:
11003 		rpip = (RPIobj_t *)arg1;
11004 
11005 		if (!rpip) {
11006 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
11007 			    "rpi: %s arg=%p. Null RPI found. Terminated.",
11008 			    emlxs_fcf_event_xlate(evt), arg1);
11009 
11010 			return (1);
11011 		}
11012 
11013 		break;
11014 
11015 	default:
11016 		return (1);
11017 	}
11018 
11019 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
11020 	    "rpi:%d %s:%s arg=%p",
11021 	    rpip->RPI,
11022 	    emlxs_rpi_state_xlate(rpip->state),
11023 	    emlxs_fcf_event_xlate(evt), arg1);
11024 
11025 	rval = emlxs_rpi_action(port, rpip, evt, arg1);
11026 
11027 	return (rval);
11028 
11029 } /* emlxs_rpi_event() */
11030 
11031 
11032 /*ARGSUSED*/
11033 static uint32_t
11034 emlxs_rpi_state(emlxs_port_t *port, RPIobj_t *rpip, uint16_t state,
11035     uint16_t reason, uint32_t explain, void *arg1)
11036 {
11037 	uint32_t rval = 0;
11038 
11039 	if (state >= RPI_ACTION_STATES) {
11040 		return (1);
11041 	}
11042 
11043 	if ((rpip->state == state) &&
11044 	    (reason != FCF_REASON_REENTER)) {
11045 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11046 		    "rpi_state:%d %s:%s:0x%x arg=%p. State not changed. "
11047 		    "Terminated.",
11048 		    rpip->RPI,
11049 		    emlxs_rpi_state_xlate(rpip->state),
11050 		    emlxs_fcf_reason_xlate(reason),
11051 		    explain, arg1);
11052 
11053 		return (1);
11054 	}
11055 
11056 	if (!reason) {
11057 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11058 		    "rpi:%d %s-->%s arg=%p",
11059 		    rpip->RPI,
11060 		    emlxs_rpi_state_xlate(rpip->state),
11061 		    emlxs_rpi_state_xlate(state), arg1);
11062 	} else if (reason == FCF_REASON_EVENT) {
11063 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11064 		    "rpi:%d %s-->%s:%s:%s arg=%p",
11065 		    rpip->RPI,
11066 		    emlxs_rpi_state_xlate(rpip->state),
11067 		    emlxs_rpi_state_xlate(state),
11068 		    emlxs_fcf_reason_xlate(reason),
11069 		    emlxs_fcf_event_xlate(explain), arg1);
11070 	} else if (explain) {
11071 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11072 		    "rpi:%d %s-->%s:%s:0x%x arg=%p",
11073 		    rpip->RPI,
11074 		    emlxs_rpi_state_xlate(rpip->state),
11075 		    emlxs_rpi_state_xlate(state),
11076 		    emlxs_fcf_reason_xlate(reason),
11077 		    explain, arg1);
11078 	} else {
11079 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11080 		    "rpi:%d %s-->%s:%s arg=%p",
11081 		    rpip->RPI,
11082 		    emlxs_rpi_state_xlate(rpip->state),
11083 		    emlxs_rpi_state_xlate(state),
11084 		    emlxs_fcf_reason_xlate(reason), arg1);
11085 	}
11086 
11087 	rpip->prev_state = rpip->state;
11088 	rpip->prev_reason = rpip->reason;
11089 	rpip->state = state;
11090 	rpip->reason = reason;
11091 
11092 	rval = emlxs_rpi_action(port, rpip, FCF_EVENT_STATE_ENTER, arg1);
11093 
11094 	return (rval);
11095 
11096 } /* emlxs_rpi_state() */
11097 
11098 
11099 static RPIobj_t *
11100 emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did)
11101 {
11102 	emlxs_hba_t *hba = HBA;
11103 	uint16_t	i;
11104 	RPIobj_t	*rpip;
11105 
11106 	/* Special handling for Fabric RPI */
11107 	if (did == FABRIC_DID) {
11108 		/* Use the reserved RPI in the port */
11109 		rpip = &port->VPIobj.fcf_rpi;
11110 
11111 		bzero(rpip, sizeof (RPIobj_t));
11112 		rpip->index = 0xffff;
11113 		rpip->RPI = 0xffff;
11114 		rpip->did = FABRIC_DID;
11115 		rpip->vpip = &port->VPIobj;
11116 
11117 		(void) emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
11118 		    0, 0, 0);
11119 
11120 		return (rpip);
11121 	}
11122 
11123 	rpip = hba->sli.sli4.RPIp;
11124 	for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
11125 		/* To be consistent with SLI3, the RPI assignment */
11126 		/* starts with 1. ONLY one SLI4 HBA in the entire */
11127 		/* system will be sacrificed by one RPI and that  */
11128 		/* is the one having RPI base equal 0. */
11129 		if ((rpip->state == RPI_STATE_FREE) && (rpip->RPI != 0)) {
11130 
11131 			bzero(rpip, sizeof (RPIobj_t));
11132 			rpip->index = i;
11133 			rpip->RPI = hba->sli.sli4.RPIBase + i;
11134 			rpip->vpip = &port->VPIobj;
11135 			rpip->did = did;
11136 
11137 			(void) emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
11138 			    0, 0, 0);
11139 
11140 			return (rpip);
11141 		}
11142 	}
11143 
11144 	return (NULL);
11145 
11146 } /* emlxs_rpi_alloc() */
11147 
11148 
11149 static uint32_t
11150 emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip)
11151 {
11152 	uint32_t rval;
11153 
11154 	rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
11155 
11156 	return (rval);
11157 
11158 } /* emlxs_fcfi_free() */
11159 
11160 
11161 extern RPIobj_t *
11162 emlxs_rpi_find(emlxs_port_t *port, uint16_t rpi)
11163 {
11164 	emlxs_hba_t *hba = HBA;
11165 	RPIobj_t	*rpip;
11166 
11167 	/* Special handling for Fabric RPI */
11168 	if (rpi == 0xffff) {
11169 		return (port->VPIobj.rpip);
11170 	}
11171 
11172 	if ((rpi < hba->sli.sli4.RPIBase) ||
11173 	    (rpi >= hba->sli.sli4.RPIBase+hba->sli.sli4.RPICount)) {
11174 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11175 		    "rpi_find:%d. RPI out of range (%d,%d).",
11176 		    rpi,
11177 		    hba->sli.sli4.RPIBase,
11178 		    hba->sli.sli4.RPIBase+hba->sli.sli4.RPICount);
11179 
11180 		return (NULL);
11181 	}
11182 
11183 	rpip = &hba->sli.sli4.RPIp[(rpi - hba->sli.sli4.RPIBase)];
11184 
11185 	if (rpip->state == RPI_STATE_FREE) {
11186 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11187 		    "rpi_find:%d  RPI not active",
11188 		    rpi);
11189 
11190 		return (NULL);
11191 	}
11192 
11193 	return (rpip);
11194 
11195 } /* emlxs_rpi_find() */
11196 
11197 
11198 static RPIobj_t *
11199 emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did)
11200 {
11201 	emlxs_hba_t *hba = HBA;
11202 	RPIobj_t	*rpip;
11203 	RPIobj_t	*rpip1;
11204 	uint32_t	i;
11205 
11206 	/* Special handling for Fabric RPI */
11207 	if (did == FABRIC_DID) {
11208 		return (port->VPIobj.rpip);
11209 	}
11210 
11211 	rpip1 = NULL;
11212 	rpip = hba->sli.sli4.RPIp;
11213 	for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
11214 		if (rpip->state == RPI_STATE_FREE) {
11215 			continue;
11216 		}
11217 
11218 		if ((rpip->did == did) && (rpip->vpip == &port->VPIobj)) {
11219 			rpip1 = rpip;
11220 			break;
11221 		}
11222 	}
11223 
11224 	return (rpip1);
11225 
11226 } /* emlxs_rpi_find_did() */
11227 
11228 
11229 extern RPIobj_t *
11230 emlxs_rpi_alloc_notify(emlxs_port_t *port, uint32_t did)
11231 {
11232 	emlxs_hba_t *hba = HBA;
11233 	RPIobj_t	*rpip;
11234 
11235 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
11236 		return (NULL);
11237 	}
11238 
11239 	/* Fabric RPI will be handled automatically */
11240 	if (did == FABRIC_DID) {
11241 		return (NULL);
11242 	}
11243 
11244 	mutex_enter(&EMLXS_FCF_LOCK);
11245 
11246 	rpip = emlxs_rpi_alloc(port, did);
11247 
11248 	mutex_exit(&EMLXS_FCF_LOCK);
11249 
11250 	return (rpip);
11251 
11252 } /* emlxs_rpi_alloc_notify() */
11253 
11254 
11255 extern uint32_t
11256 emlxs_rpi_free_notify(emlxs_port_t *port, RPIobj_t *rpip)
11257 {
11258 	emlxs_hba_t	*hba = HBA;
11259 	uint32_t	rval;
11260 
11261 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
11262 		return (1);
11263 	}
11264 
11265 	if (!rpip) {
11266 		return (1);
11267 	}
11268 
11269 	/* Fabric RPI will be handled automatically */
11270 	if (rpip->did == FABRIC_DID) {
11271 		return (1);
11272 	}
11273 
11274 	mutex_enter(&EMLXS_FCF_LOCK);
11275 
11276 	rval =  emlxs_rpi_free(port, rpip);
11277 
11278 	mutex_exit(&EMLXS_FCF_LOCK);
11279 
11280 	return (rval);
11281 
11282 } /* emlxs_rpi_free_notify() */
11283 
11284 
11285 extern uint32_t
11286 emlxs_rpi_pause_notify(emlxs_port_t *port, RPIobj_t *rpip)
11287 {
11288 	emlxs_hba_t *hba = HBA;
11289 
11290 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
11291 		return (1);
11292 	}
11293 
11294 	if (!rpip) {
11295 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11296 		    "rpi_pause_notify: No RPI provided.");
11297 
11298 		return (1);
11299 	}
11300 
11301 	/* Fabric RPI will be handled automatically */
11302 	if (rpip->did == FABRIC_DID) {
11303 		return (1);
11304 	}
11305 
11306 	mutex_enter(&EMLXS_FCF_LOCK);
11307 
11308 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11309 	    "rpi_pause_notify:%d %s. Pausing.",
11310 	    rpip->RPI,
11311 	    emlxs_rpi_state_xlate(rpip->state));
11312 
11313 	(void) emlxs_rpi_event(port, FCF_EVENT_RPI_PAUSE, rpip);
11314 
11315 	mutex_exit(&EMLXS_FCF_LOCK);
11316 
11317 	return (0);
11318 
11319 } /* emlxs_rpi_pause_notify() */
11320 
11321 
11322 extern uint32_t
11323 emlxs_rpi_online_notify(emlxs_port_t *port, RPIobj_t *rpip, uint32_t did,
11324     SERV_PARM *sparam, void *arg1, void *arg2, void *arg3)
11325 {
11326 	emlxs_hba_t *hba = HBA;
11327 	emlxs_deferred_cmpl_t *cmpl;
11328 	uint32_t allocated = 0;
11329 
11330 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
11331 		return (1);
11332 	}
11333 
11334 	/* Fabric RPI will be handled automatically */
11335 	if (did == FABRIC_DID) {
11336 		return (1);
11337 	}
11338 
11339 	mutex_enter(&EMLXS_FCF_LOCK);
11340 
11341 	if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) {
11342 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11343 		    "rpi_online_notify: vpi=%d. Port disabled.",
11344 		    port->VPIobj.VPI);
11345 
11346 		mutex_exit(&EMLXS_FCF_LOCK);
11347 		return (1);
11348 	}
11349 
11350 	if (!rpip) {
11351 		rpip = emlxs_rpi_find_did(port, did);
11352 	}
11353 
11354 	if (!rpip) {
11355 		rpip = emlxs_rpi_alloc(port, did);
11356 		allocated = 1;
11357 	}
11358 
11359 	if (!rpip) {
11360 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11361 		    "rpi_online_notify: Unable to allocate an rpi. did=%x",
11362 		    did);
11363 
11364 		mutex_exit(&EMLXS_FCF_LOCK);
11365 		return (1);
11366 	}
11367 
11368 	/* Initialize RPI node info */
11369 	bcopy((void *)sparam, (void *)&rpip->sparam, sizeof (SERV_PARM));
11370 
11371 	if (arg1 || arg2 || arg3) {
11372 		cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
11373 		    sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
11374 
11375 		cmpl->port = port;
11376 		cmpl->arg1 = arg1;
11377 		cmpl->arg2 = arg2;
11378 		cmpl->arg3 = arg3;
11379 
11380 		rpip->cmpl = cmpl;
11381 	}
11382 
11383 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11384 	    "rpi_online_notify:%d %s. %s. Onlining.",
11385 	    rpip->RPI,
11386 	    emlxs_rpi_state_xlate(rpip->state),
11387 	    ((allocated)? "Allocated":"Updated"));
11388 
11389 	(void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE, rpip);
11390 
11391 	if (rpip->cmpl) {
11392 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11393 		    "rpi_online_notify:%d %s. Deferred args not completed.",
11394 		    rpip->RPI,
11395 		    emlxs_rpi_state_xlate(rpip->state));
11396 
11397 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
11398 		rpip->cmpl = 0;
11399 
11400 		mutex_exit(&EMLXS_FCF_LOCK);
11401 		return (1);
11402 	}
11403 
11404 	mutex_exit(&EMLXS_FCF_LOCK);
11405 
11406 	return (0);
11407 
11408 } /* emlxs_rpi_online_notify() */
11409 
11410 
11411 extern uint32_t
11412 emlxs_rpi_offline_notify(emlxs_port_t *port, RPIobj_t *rpip,
11413     void *arg1, void *arg2, void *arg3)
11414 {
11415 	emlxs_hba_t *hba = HBA;
11416 	emlxs_deferred_cmpl_t *cmpl;
11417 
11418 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
11419 		return (1);
11420 	}
11421 
11422 	if (!rpip) {
11423 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11424 		    "rpi_offline_notify: No RPI provided.");
11425 
11426 		return (1);
11427 	}
11428 
11429 	/* Fabric RPI will be handled automatically */
11430 	if (rpip->did == FABRIC_DID) {
11431 		return (1);
11432 	}
11433 
11434 	mutex_enter(&EMLXS_FCF_LOCK);
11435 
11436 	if (arg1 || arg2 || arg3) {
11437 		cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
11438 		    sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
11439 
11440 		cmpl->port = port;
11441 		cmpl->arg1 = arg1;
11442 		cmpl->arg2 = arg2;
11443 		cmpl->arg3 = arg3;
11444 
11445 		rpip->cmpl = cmpl;
11446 	}
11447 
11448 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11449 	    "rpi_offline_notify:%d %s. Offlining.",
11450 	    rpip->RPI,
11451 	    emlxs_rpi_state_xlate(rpip->state));
11452 
11453 	(void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip);
11454 
11455 	if (rpip->cmpl) {
11456 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11457 		    "rpi_offline_notify:%d %s. Deferred args not completed.",
11458 		    rpip->RPI,
11459 		    emlxs_rpi_state_xlate(rpip->state));
11460 
11461 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
11462 		rpip->cmpl = 0;
11463 
11464 		mutex_exit(&EMLXS_FCF_LOCK);
11465 		return (1);
11466 	}
11467 
11468 	mutex_exit(&EMLXS_FCF_LOCK);
11469 
11470 	return (0);
11471 
11472 } /* emlxs_rpi_offline_notify() */
11473 
11474 
11475 extern uint32_t
11476 emlxs_rpi_resume_notify(emlxs_port_t *port, RPIobj_t *rpip, emlxs_buf_t *sbp)
11477 {
11478 	emlxs_hba_t *hba = HBA;
11479 	emlxs_deferred_cmpl_t *cmpl;
11480 
11481 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
11482 		return (1);
11483 	}
11484 
11485 	if (!rpip) {
11486 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11487 		    "rpi_resume_notify: No RPI provided.");
11488 
11489 		return (1);
11490 	}
11491 
11492 	/* Fabric RPI will be handled automatically */
11493 	if (rpip->did == FABRIC_DID) {
11494 		return (1);
11495 	}
11496 
11497 	mutex_enter(&EMLXS_FCF_LOCK);
11498 
11499 	if (rpip->state != RPI_STATE_PAUSED) {
11500 		mutex_exit(&EMLXS_FCF_LOCK);
11501 		return (1);
11502 	}
11503 
11504 	if (sbp) {
11505 		cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
11506 		    sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
11507 
11508 		cmpl->port = port;
11509 		cmpl->arg1 = (void *)sbp;
11510 		cmpl->arg2 = 0;
11511 		cmpl->arg3 = 0;
11512 
11513 		rpip->cmpl = cmpl;
11514 	}
11515 
11516 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11517 	    "rpi_resume_notify:%d %s. Resuming.",
11518 	    rpip->RPI,
11519 	    emlxs_rpi_state_xlate(rpip->state));
11520 
11521 	(void) emlxs_rpi_event(port, FCF_EVENT_RPI_RESUME, rpip);
11522 
11523 	if (rpip->cmpl) {
11524 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11525 		    "rpi_resume_notify:%d %s. Deferred args not completed.",
11526 		    rpip->RPI,
11527 		    emlxs_rpi_state_xlate(rpip->state));
11528 
11529 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
11530 		rpip->cmpl = 0;
11531 
11532 		mutex_exit(&EMLXS_FCF_LOCK);
11533 		return (1);
11534 	}
11535 
11536 	mutex_exit(&EMLXS_FCF_LOCK);
11537 
11538 	return (0);
11539 
11540 } /* emlxs_rpi_resume_notify() */
11541 
11542 
11543 /*ARGSUSED*/
11544 static uint32_t
11545 emlxs_rpi_free_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
11546     void *arg1)
11547 {
11548 	emlxs_hba_t *hba = HBA;
11549 	XRIobj_t	*xrip;
11550 	XRIobj_t	*next_xrip;
11551 
11552 	if (rpip->state != RPI_STATE_FREE) {
11553 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11554 		    "rpi_free_action:%d %s:%s arg=%p. "
11555 		    "Invalid state. Terminated.",
11556 		    rpip->RPI,
11557 		    emlxs_rpi_state_xlate(rpip->state),
11558 		    emlxs_fcf_event_xlate(evt), arg1);
11559 		return (1);
11560 	}
11561 
11562 	if (rpip->did == FABRIC_DID) {
11563 		if (rpip->vpip->flogi_sbp) {
11564 			emlxs_vpi_flogi_cmpl(port, rpip->vpip, 1);
11565 		}
11566 	}
11567 
11568 	/* Break node/RPI binding */
11569 	rw_enter(&port->node_rwlock, RW_WRITER);
11570 	if (rpip->node) {
11571 		rpip->node->rpip = NULL;
11572 		rpip->node = NULL;
11573 	}
11574 	rw_exit(&port->node_rwlock);
11575 
11576 	/* Remove all XRIs under this RPI */
11577 	mutex_enter(&EMLXS_FCTAB_LOCK);
11578 	xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
11579 	while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
11580 		next_xrip = xrip->_f;
11581 		if (xrip->rpip == rpip) {
11582 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11583 			    "rpi_free_action:%d xri_count=%d. "
11584 			    "Removing XRI:%d iotag:%d.",
11585 			    rpip->RPI,
11586 			    rpip->xri_count,
11587 			    xrip->XRI, xrip->iotag);
11588 
11589 			xrip->rpip->xri_count--;
11590 			xrip->rpip = NULL;
11591 		}
11592 		xrip = next_xrip;
11593 	}
11594 	mutex_exit(&EMLXS_FCTAB_LOCK);
11595 
11596 	if (rpip->xri_count) {
11597 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11598 		    "rpi_free_action:%d. xri_count=%d",
11599 		    rpip->RPI,
11600 		    rpip->xri_count);
11601 	}
11602 
11603 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11604 	    "rpi_free_action:%d flag=%x. RPI freed.",
11605 	    rpip->RPI,
11606 	    rpip->flag);
11607 
11608 	rpip->flag = 0;
11609 
11610 	return (0);
11611 
11612 } /* emlxs_rpi_free_action() */
11613 
11614 
11615 /*ARGSUSED*/
11616 static uint32_t
11617 emlxs_rpi_online_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
11618     void *arg1)
11619 {
11620 	uint32_t rval = 1;
11621 
11622 	if (evt != FCF_EVENT_RPI_ONLINE) {
11623 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11624 		    "rpi_online_evt_action:%d %s:%s arg=%p. "
11625 		    "Invalid event type. Terminated.",
11626 		    rpip->RPI,
11627 		    emlxs_rpi_state_xlate(rpip->state),
11628 		    emlxs_fcf_event_xlate(evt), arg1);
11629 		return (1);
11630 	}
11631 
11632 	switch (rpip->state) {
11633 	case RPI_STATE_REG:
11634 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11635 		    "rpi_online_evt_action:%d flag=%x. Registering.",
11636 		    rpip->RPI,
11637 		    rpip->flag);
11638 
11639 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG,
11640 		    FCF_REASON_REENTER, evt, arg1);
11641 		break;
11642 
11643 	default:
11644 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11645 		    "rpi_online_evt_action:%d flag=%x. Registering.",
11646 		    rpip->RPI,
11647 		    rpip->flag);
11648 
11649 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG,
11650 		    FCF_REASON_EVENT, evt, arg1);
11651 		break;
11652 	}
11653 
11654 	return (rval);
11655 
11656 } /* emlxs_rpi_online_evt_action() */
11657 
11658 
11659 /*ARGSUSED*/
11660 static uint32_t
11661 emlxs_rpi_offline_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
11662     void *arg1)
11663 {
11664 	uint32_t rval = 1;
11665 
11666 	if (evt != FCF_EVENT_RPI_OFFLINE) {
11667 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11668 		    "rpi_offline_evt_action:%d %s:%s arg=%p. "
11669 		    "Invalid event type. Terminated.",
11670 		    rpip->RPI,
11671 		    emlxs_rpi_state_xlate(rpip->state),
11672 		    emlxs_fcf_event_xlate(evt), arg1);
11673 		return (1);
11674 	}
11675 
11676 	switch (rpip->state) {
11677 	case RPI_STATE_OFFLINE:
11678 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11679 		    "rpi_offline_evt_action:%d flag=%x. Offlining RPI.",
11680 		    rpip->RPI,
11681 		    rpip->flag);
11682 
11683 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
11684 		    FCF_REASON_REENTER, evt, arg1);
11685 		break;
11686 
11687 	case RPI_STATE_UNREG:
11688 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11689 		    "rpi_offline_evt_action:%d flag=%x. Already unregistering. "
11690 		    "Terminated.",
11691 		    rpip->RPI,
11692 		    rpip->flag);
11693 
11694 		break;
11695 
11696 	default:
11697 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11698 		    "rpi_offline_evt_action:%d flag=%x. Unregistering.",
11699 		    rpip->RPI,
11700 		    rpip->flag);
11701 
11702 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
11703 		    FCF_REASON_EVENT, evt, arg1);
11704 		break;
11705 
11706 	}
11707 
11708 	return (rval);
11709 
11710 } /* emlxs_rpi_offline_evt_action() */
11711 
11712 
11713 /*ARGSUSED*/
11714 static uint32_t
11715 emlxs_rpi_pause_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
11716     void *arg1)
11717 {
11718 	uint32_t rval = 1;
11719 
11720 	if (evt != FCF_EVENT_RPI_PAUSE) {
11721 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11722 		    "rpi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
11723 		    "Invalid event type. Terminated.",
11724 		    rpip->RPI,
11725 		    emlxs_rpi_state_xlate(rpip->state),
11726 		    emlxs_fcf_event_xlate(evt), arg1,
11727 		    rpip->flag);
11728 		return (1);
11729 	}
11730 
11731 	switch (rpip->state) {
11732 	case RPI_STATE_OFFLINE:
11733 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11734 		    "rpi_pause_evt_action:%d flag=%x. Offlining RPI.",
11735 		    rpip->RPI,
11736 		    rpip->flag);
11737 
11738 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
11739 		    FCF_REASON_REENTER, evt, arg1);
11740 		break;
11741 
11742 	case RPI_STATE_UNREG:
11743 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11744 		    "rpi_pause_evt_action:%d flag=%x. Not online. "
11745 		    "Terminated.",
11746 		    rpip->RPI,
11747 		    rpip->flag);
11748 
11749 		break;
11750 
11751 	case RPI_STATE_PAUSED:
11752 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11753 		    "rpi_pause_evt_action:%d flag=%x. Already paused. "
11754 		    "Terminated.",
11755 		    rpip->RPI,
11756 		    rpip->flag);
11757 
11758 		break;
11759 
11760 	case RPI_STATE_REG:
11761 	case RPI_STATE_ONLINE:
11762 	case RPI_STATE_RESUME:
11763 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11764 		    "rpi_pause_evt_action:%d flag=%x. Pausing.",
11765 		    rpip->RPI,
11766 		    rpip->flag);
11767 
11768 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_PAUSED,
11769 		    FCF_REASON_EVENT, evt, arg1);
11770 		break;
11771 
11772 	default:
11773 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11774 		    "rpi_pause_evt_action:%d flag=%x. Terminated.",
11775 		    rpip->RPI,
11776 		    rpip->flag);
11777 		break;
11778 	}
11779 
11780 	return (rval);
11781 
11782 } /* emlxs_rpi_pause_evt_action() */
11783 
11784 
11785 /*ARGSUSED*/
11786 static uint32_t
11787 emlxs_rpi_resume_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
11788     void *arg1)
11789 {
11790 	uint32_t rval = 1;
11791 
11792 	if (evt != FCF_EVENT_RPI_RESUME) {
11793 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11794 		    "rpi_resume_evt_action:%d %s:%s arg=%p flag=%x. "
11795 		    "Invalid event type. Terminated.",
11796 		    rpip->RPI,
11797 		    emlxs_rpi_state_xlate(rpip->state),
11798 		    emlxs_fcf_event_xlate(evt), arg1,
11799 		    rpip->flag);
11800 		return (1);
11801 	}
11802 
11803 	switch (rpip->state) {
11804 	case RPI_STATE_PAUSED:
11805 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11806 		    "rpi_resume_evt_action:%d flag=%x. Resuming.",
11807 		    rpip->RPI,
11808 		    rpip->flag);
11809 
11810 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME,
11811 		    FCF_REASON_EVENT, evt, arg1);
11812 		break;
11813 
11814 	default:
11815 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11816 		    "rpi_resume_evt_action:%d flag=%x. Not paused. Terminated.",
11817 		    rpip->RPI,
11818 		    rpip->flag);
11819 		break;
11820 	}
11821 
11822 	return (rval);
11823 
11824 } /* emlxs_rpi_resume_evt_action() */
11825 
11826 
11827 /*ARGSUSED*/
11828 static uint32_t
11829 emlxs_rpi_offline_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
11830     void *arg1)
11831 {
11832 	uint32_t rval;
11833 	VPIobj_t *vpip;
11834 
11835 	vpip = rpip->vpip;
11836 
11837 	if (rpip->state != RPI_STATE_OFFLINE) {
11838 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11839 		    "rpi_offline_action:%d %s:%s arg=%p. "
11840 		    "Invalid state. Terminated.",
11841 		    rpip->RPI,
11842 		    emlxs_rpi_state_xlate(rpip->state),
11843 		    emlxs_fcf_event_xlate(evt), arg1);
11844 		return (1);
11845 	}
11846 
11847 	if (rpip->prev_state == RPI_STATE_FREE) {
11848 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11849 		    "rpi_offline_action:%d rpi_online=%d,%d. Terminated.",
11850 		    rpip->RPI,
11851 		    vpip->rpi_online, vpip->rpi_paused);
11852 
11853 		return (0);
11854 	}
11855 
11856 	if (rpip->flag & EMLXS_RPI_PAUSED) {
11857 		rpip->flag &= ~EMLXS_RPI_PAUSED;
11858 
11859 		if (vpip->rpi_paused) {
11860 			vpip->rpi_paused--;
11861 		}
11862 	}
11863 
11864 	if (rpip->flag & EMLXS_RPI_VPI) {
11865 		rpip->flag &= ~EMLXS_RPI_VPI;
11866 
11867 		if (vpip->rpi_online) {
11868 			vpip->rpi_online--;
11869 		}
11870 
11871 		/* Added protection */
11872 		if (vpip->rpi_online < vpip->rpi_paused) {
11873 			vpip->rpi_paused = vpip->rpi_online;
11874 		}
11875 	}
11876 
11877 	if (rpip->did == FABRIC_DID) {
11878 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11879 		    "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. "
11880 		    "Fabric RPI offline. Freeing.",
11881 		    rpip->RPI,
11882 		    vpip->rpi_online, vpip->rpi_paused,
11883 		    rpip->xri_count);
11884 
11885 		/* Free RPI */
11886 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
11887 
11888 		return (rval);
11889 	}
11890 
11891 	if ((vpip->rpi_online == 0) ||
11892 	    (vpip->rpi_online == vpip->rpi_paused)) {
11893 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11894 		    "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. "
11895 		    "RPI offline. "
11896 		    "Notifying VPI:%d",
11897 		    rpip->RPI,
11898 		    vpip->rpi_online, vpip->rpi_paused,
11899 		    rpip->xri_count,
11900 		    vpip->VPI);
11901 
11902 		/* Notify VPI */
11903 		(void) emlxs_vpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip);
11904 
11905 	} else {
11906 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11907 		    "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. "
11908 		    "RPI offline. Freeing.",
11909 		    rpip->RPI,
11910 		    vpip->rpi_online, vpip->rpi_paused,
11911 		    rpip->xri_count);
11912 	}
11913 
11914 	/* Free RPI */
11915 	rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
11916 
11917 	return (rval);
11918 
11919 } /* emlxs_rpi_offline_action() */
11920 
11921 
11922 /*ARGSUSED*/
11923 static uint32_t
11924 emlxs_rpi_paused_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
11925     void *arg1)
11926 {
11927 	VPIobj_t *vpip;
11928 
11929 	vpip = rpip->vpip;
11930 
11931 	if (rpip->state != RPI_STATE_PAUSED) {
11932 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11933 		    "rpi_paused_action:%d %s:%s arg=%p. "
11934 		    "Invalid state. Terminated.",
11935 		    rpip->RPI,
11936 		    emlxs_rpi_state_xlate(rpip->state),
11937 		    emlxs_fcf_event_xlate(evt), arg1);
11938 		return (1);
11939 	}
11940 
11941 	if (!(rpip->flag & EMLXS_RPI_PAUSED)) {
11942 		rpip->flag |= EMLXS_RPI_PAUSED;
11943 		vpip->rpi_paused++;
11944 	}
11945 
11946 	/* Check if all RPI's have been paused for a VPI */
11947 	if (vpip->rpi_online == vpip->rpi_paused) {
11948 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11949 		    "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. "
11950 		    "RPI paused. "
11951 		    "Notifying VPI:%d",
11952 		    rpip->RPI,
11953 		    vpip->rpi_online, vpip->rpi_paused,
11954 		    rpip->xri_count,
11955 		    vpip->VPI);
11956 
11957 		/* Notify VPI */
11958 		(void) emlxs_vpi_event(port, FCF_EVENT_RPI_PAUSE, rpip);
11959 
11960 	} else {
11961 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11962 		    "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. "
11963 		    "RPI paused.",
11964 		    rpip->RPI,
11965 		    vpip->rpi_online, vpip->rpi_paused,
11966 		    rpip->xri_count);
11967 	}
11968 
11969 	return (0);
11970 
11971 } /* emlxs_rpi_paused_action() */
11972 
11973 
11974 /*ARGSUSED*/
11975 static uint32_t
11976 emlxs_rpi_unreg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
11977     void *arg1)
11978 {
11979 	uint32_t rval;
11980 
11981 	rpip->attempts++;
11982 
11983 	if (rpip->state != RPI_STATE_UNREG_FAILED) {
11984 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11985 		    "rpi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
11986 		    "Invalid state. Terminated.",
11987 		    rpip->RPI,
11988 		    emlxs_rpi_state_xlate(rpip->state),
11989 		    emlxs_fcf_event_xlate(evt), arg1,
11990 		    rpip->attempts);
11991 
11992 		return (1);
11993 	}
11994 
11995 	if ((rpip->reason == FCF_REASON_SEND_FAILED) ||
11996 	    !(rpip->flag & EMLXS_RPI_REG)) {
11997 
11998 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11999 		    "rpi_unreg_failed_action:%d reason=%x flag=%x. "
12000 		    "Going offline.",
12001 		    rpip->RPI,
12002 		    rpip->reason,
12003 		    rpip->flag);
12004 
12005 		rpip->flag &= ~EMLXS_RPI_REG;
12006 
12007 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
12008 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
12009 	} else {
12010 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12011 		    "rpi_unreg_failed_action:%d flag=%x. Going online.",
12012 		    rpip->RPI,
12013 		    rpip->flag);
12014 
12015 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
12016 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
12017 	}
12018 
12019 	return (rval);
12020 
12021 } /* emlxs_rpi_unreg_failed_action() */
12022 
12023 
12024 static void
12025 emlxs_rpi_unreg_handler(emlxs_port_t *port, RPIobj_t *rpip)
12026 {
12027 	emlxs_hba_t *hba = HBA;
12028 	VPIobj_t *vpip = rpip->vpip;
12029 	emlxs_node_t *node = rpip->node;
12030 	XRIobj_t *xrip;
12031 	XRIobj_t *next_xrip;
12032 
12033 	/* Special handling for Fabric RPI */
12034 	if (rpip->did == FABRIC_DID) {
12035 		if (node) {
12036 			(void) emlxs_tx_node_flush(port, node, 0, 0, 0);
12037 			(void) emlxs_chipq_node_flush(port, 0, node, 0);
12038 		}
12039 
12040 		/* Clear all reserved XRIs under this RPI */
12041 		mutex_enter(&EMLXS_FCTAB_LOCK);
12042 		xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
12043 		while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
12044 			next_xrip = xrip->_f;
12045 			if ((xrip->rpip == rpip) &&
12046 			    (xrip->flag & EMLXS_XRI_RESERVED)) {
12047 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12048 				    "rpi_unreg_action:%d xri_count=%d. "
12049 				    "Unreserving XRI:%d iotag:%d.",
12050 				    rpip->RPI,
12051 				    rpip->xri_count,
12052 				    xrip->XRI, xrip->iotag);
12053 
12054 				(void) emlxs_sli4_unreserve_xri(hba,
12055 				    xrip->XRI, 0);
12056 			}
12057 			xrip = next_xrip;
12058 		}
12059 		mutex_exit(&EMLXS_FCTAB_LOCK);
12060 	}
12061 
12062 	rpip->flag &= ~EMLXS_RPI_REG;
12063 
12064 	if (rpip->flag & EMLXS_RPI_PAUSED) {
12065 		rpip->flag &= ~EMLXS_RPI_PAUSED;
12066 
12067 		if (vpip->rpi_paused) {
12068 			vpip->rpi_paused--;
12069 		}
12070 	}
12071 
12072 	if (rpip->flag & EMLXS_RPI_VPI) {
12073 		rpip->flag &= ~EMLXS_RPI_VPI;
12074 
12075 		if (vpip->rpi_online) {
12076 			vpip->rpi_online--;
12077 		}
12078 
12079 		/* Added protection */
12080 		if (vpip->rpi_online < vpip->rpi_paused) {
12081 			vpip->rpi_paused = vpip->rpi_online;
12082 		}
12083 	}
12084 
12085 	rw_enter(&port->node_rwlock, RW_WRITER);
12086 	if (node) {
12087 		rpip->node = NULL;
12088 		node->rpip = NULL;
12089 	}
12090 	rw_exit(&port->node_rwlock);
12091 
12092 	if (node) {
12093 		emlxs_node_rm(port, node);
12094 	}
12095 
12096 	return;
12097 
12098 } /* emlxs_rpi_unreg_handler() */
12099 
12100 
12101 /*ARGSUSED*/
12102 static uint32_t
12103 emlxs_rpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
12104 {
12105 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
12106 	MAILBOX4 *mb4;
12107 	RPIobj_t *rpip;
12108 
12109 	mutex_enter(&EMLXS_FCF_LOCK);
12110 
12111 	rpip = (RPIobj_t *)mbq->context;
12112 
12113 	mb4 = (MAILBOX4 *)mbq;
12114 
12115 	if (rpip->state != RPI_STATE_UNREG) {
12116 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12117 		    "rpi_unreg_mbcmpl:%d state=%s. "
12118 		    "No longer in RPI_STATE_UNREG. Terminated.",
12119 		    rpip->RPI,
12120 		    emlxs_rpi_state_xlate(rpip->state));
12121 
12122 		mutex_exit(&EMLXS_FCF_LOCK);
12123 		return (0);
12124 	}
12125 
12126 	if (mb4->mbxStatus) {
12127 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12128 		    "rpi_unreg_mbcmpl:%d failed. status=%x",
12129 		    rpip->RPI,
12130 		    mb4->mbxStatus);
12131 
12132 		(void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
12133 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
12134 
12135 		mutex_exit(&EMLXS_FCF_LOCK);
12136 		return (0);
12137 	}
12138 
12139 	emlxs_rpi_unreg_handler(port, rpip);
12140 
12141 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12142 	    "rpi_unreg_mbcmpl:%d Unregistered. Unreg cmpl.",
12143 	    rpip->RPI);
12144 
12145 	(void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_CMPL,
12146 	    0, 0, 0);
12147 
12148 	mutex_exit(&EMLXS_FCF_LOCK);
12149 	return (0);
12150 
12151 } /* emlxs_rpi_unreg_mbcmpl() */
12152 
12153 
12154 /*ARGSUSED*/
12155 static uint32_t
12156 emlxs_rpi_unreg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
12157     void *arg1)
12158 {
12159 	emlxs_hba_t *hba = HBA;
12160 	MAILBOX4 *mb4;
12161 	MAILBOXQ *mbq;
12162 	uint32_t rval;
12163 	VPIobj_t *vpip = rpip->vpip;
12164 
12165 	if (rpip->state != RPI_STATE_UNREG) {
12166 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12167 		    "rpi_unreg_action:%d %s:%s arg=%p. "
12168 		    "Invalid state. Terminated.",
12169 		    rpip->RPI,
12170 		    emlxs_rpi_state_xlate(rpip->state),
12171 		    emlxs_fcf_event_xlate(evt), arg1);
12172 
12173 		return (1);
12174 	}
12175 
12176 	if (!(rpip->flag & EMLXS_RPI_REG)) {
12177 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12178 		    "rpi_unreg_action:%d. Not registered. Going offline.",
12179 		    rpip->RPI);
12180 
12181 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
12182 		    FCF_REASON_EVENT, evt, arg1);
12183 
12184 		return (rval);
12185 	}
12186 
12187 	if (rpip->prev_state != RPI_STATE_UNREG_FAILED) {
12188 		rpip->attempts = 0;
12189 	}
12190 
12191 	if (rpip->did == FABRIC_DID) {
12192 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12193 		    "rpi_unreg_action:%d did=%x vpi=%d. Fabric RPI. "
12194 		    "Going offline.",
12195 		    rpip->RPI,
12196 		    rpip->did,
12197 		    rpip->vpip->VPI);
12198 
12199 		/* Don't send UNREG_RPI, but process it as if we did */
12200 		emlxs_rpi_unreg_handler(port, rpip);
12201 
12202 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
12203 		    FCF_REASON_EVENT, evt, arg1);
12204 
12205 		return (rval);
12206 	}
12207 
12208 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12209 	    "rpi_unreg_action:%d attempts=%d. Sending UNREG_RPI.",
12210 	    rpip->RPI,
12211 	    rpip->attempts);
12212 
12213 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
12214 
12215 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
12216 		    FCF_REASON_NO_MBOX, 0, arg1);
12217 
12218 		return (rval);
12219 	}
12220 	mb4 = (MAILBOX4*)mbq;
12221 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
12222 
12223 	mbq->nonembed = NULL;
12224 	mbq->mbox_cmpl = emlxs_rpi_unreg_mbcmpl;
12225 	mbq->context = (void *)rpip;
12226 	mbq->port = (void *)port;
12227 
12228 	mb4->mbxCommand = MBX_UNREG_RPI;
12229 	mb4->mbxOwner = OWN_HOST;
12230 	mb4->un.varUnregLogin.rpi = rpip->RPI;
12231 	mb4->un.varUnregLogin.vpi = vpip->VPI;
12232 
12233 	if (rpip->cmpl) {
12234 		mbq->sbp = rpip->cmpl->arg1;
12235 		mbq->ubp = rpip->cmpl->arg2;
12236 		mbq->iocbq = rpip->cmpl->arg3;
12237 	}
12238 
12239 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
12240 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
12241 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
12242 
12243 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
12244 		    FCF_REASON_SEND_FAILED, rval, arg1);
12245 
12246 		return (rval);
12247 	}
12248 
12249 	if (rpip->cmpl) {
12250 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
12251 		rpip->cmpl = 0;
12252 	}
12253 
12254 	return (0);
12255 
12256 } /* emlxs_rpi_unreg_action() */
12257 
12258 
12259 /*ARGSUSED*/
12260 static uint32_t
12261 emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
12262     void *arg1)
12263 {
12264 	uint32_t rval;
12265 
12266 	if (rpip->state != RPI_STATE_UNREG_CMPL) {
12267 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12268 		    "rpi_unreg_cmpl_action:%d %s:%s arg=%p. "
12269 		    "Invalid state. Terminated.",
12270 		    rpip->RPI,
12271 		    emlxs_rpi_state_xlate(rpip->state),
12272 		    emlxs_fcf_event_xlate(evt), arg1);
12273 		return (1);
12274 	}
12275 
12276 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12277 	    "rpi_unreg_cmpl_action:%d flag=%x. Going offline.",
12278 	    rpip->RPI,
12279 	    rpip->flag);
12280 
12281 	rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
12282 	    FCF_REASON_EVENT, evt, arg1);
12283 
12284 	return (rval);
12285 
12286 } /* emlxs_rpi_unreg_cmpl_action() */
12287 
12288 
12289 /*ARGSUSED*/
12290 static uint32_t
12291 emlxs_rpi_reg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
12292     void *arg1)
12293 {
12294 	uint32_t rval;
12295 
12296 	rpip->attempts++;
12297 
12298 	if (rpip->state != RPI_STATE_REG_FAILED) {
12299 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12300 		    "rpi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
12301 		    "Invalid state. Terminated.",
12302 		    rpip->RPI,
12303 		    emlxs_rpi_state_xlate(rpip->state),
12304 		    emlxs_fcf_event_xlate(evt), arg1,
12305 		    rpip->attempts);
12306 
12307 		return (1);
12308 	}
12309 
12310 	if ((rpip->reason == FCF_REASON_SEND_FAILED) ||
12311 	    !(rpip->flag & EMLXS_RPI_REG)) {
12312 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12313 		    "rpi_reg_failed_action:%d reason=%x flag=%x. "
12314 		    "Going offline.",
12315 		    rpip->RPI,
12316 		    rpip->reason,
12317 		    rpip->flag);
12318 
12319 		rpip->flag &= ~EMLXS_RPI_REG;
12320 
12321 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
12322 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
12323 	} else {
12324 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12325 		    "rpi_reg_failed_action:%d flag=%x. Unregistering",
12326 		    rpip->RPI,
12327 		    rpip->flag);
12328 
12329 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
12330 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
12331 	}
12332 
12333 	return (rval);
12334 
12335 } /* emlxs_rpi_reg_failed_action() */
12336 
12337 
12338 static uint32_t
12339 emlxs_rpi_reg_handler(emlxs_port_t *port, RPIobj_t *rpip)
12340 {
12341 	VPIobj_t *vpip;
12342 	emlxs_node_t *node;
12343 
12344 	vpip = rpip->vpip;
12345 
12346 	rpip->flag |= EMLXS_RPI_REG;
12347 
12348 	if (rpip->flag & EMLXS_RPI_PAUSED) {
12349 		rpip->flag &= ~EMLXS_RPI_PAUSED;
12350 
12351 		if (vpip->rpi_paused) {
12352 			vpip->rpi_paused--;
12353 		}
12354 	}
12355 
12356 	if (!(rpip->flag & EMLXS_RPI_VPI) &&
12357 	    (rpip->did != FABRIC_DID)) {
12358 		rpip->flag |= EMLXS_RPI_VPI;
12359 		vpip->rpi_online++;
12360 	}
12361 
12362 	/* Create or update the node */
12363 	node = emlxs_node_create(port, rpip->did, rpip->RPI, &rpip->sparam);
12364 
12365 	if (!node) {
12366 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12367 		    "rpi_reg_handler:%d. Node create failed. Reg failed.",
12368 		    rpip->RPI);
12369 
12370 		return (FCF_REASON_NO_NODE);
12371 	}
12372 
12373 	return (0);
12374 
12375 } /* emlxs_rpi_reg_handler() */
12376 
12377 
12378 /*ARGSUSED*/
12379 static uint32_t
12380 emlxs_rpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
12381 {
12382 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
12383 	MAILBOX4 *mb4;
12384 	RPIobj_t *rpip;
12385 	emlxs_node_t *node;
12386 	uint32_t rval;
12387 
12388 	mutex_enter(&EMLXS_FCF_LOCK);
12389 
12390 	rpip = (RPIobj_t *)mbq->context;
12391 	mb4 = (MAILBOX4 *)mbq;
12392 
12393 	if (rpip->state != RPI_STATE_REG) {
12394 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12395 		    "rpi_reg_mbcmpl:%d state=%s. No longer in RPI_STATE_REG. "
12396 		    "Terminated.",
12397 		    rpip->RPI,
12398 		    emlxs_rpi_state_xlate(rpip->state));
12399 
12400 		mutex_exit(&EMLXS_FCF_LOCK);
12401 		return (0);
12402 	}
12403 
12404 	if (mb4->mbxStatus) {
12405 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12406 		    "rpi_reg_mbcmpl:%d failed. status=%x",
12407 		    rpip->RPI,
12408 		    mb4->mbxStatus);
12409 
12410 		(void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
12411 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
12412 
12413 		mutex_exit(&EMLXS_FCF_LOCK);
12414 		return (0);
12415 	}
12416 
12417 	rval = emlxs_rpi_reg_handler(port, rpip);
12418 
12419 	if (rval) {
12420 		mb4->mbxStatus = MBX_FAILURE;
12421 
12422 		(void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
12423 		    rval, 0, 0);
12424 
12425 		mutex_exit(&EMLXS_FCF_LOCK);
12426 		return (0);
12427 	}
12428 
12429 	node = rpip->node;
12430 
12431 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12432 	    "rpi_reg_mbcmpl:%d Registered. Reg cmpl.",
12433 	    rpip->RPI);
12434 
12435 	(void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_CMPL, 0, 0, 0);
12436 
12437 	mutex_exit(&EMLXS_FCF_LOCK);
12438 
12439 	/* Needed for FCT trigger in emlxs_mb_deferred_cmpl */
12440 	if (mbq->sbp) {
12441 		((emlxs_buf_t *)mbq->sbp)->node = node;
12442 	}
12443 
12444 #ifdef DHCHAP_SUPPORT
12445 	if (mbq->sbp || mbq->ubp) {
12446 		if (emlxs_dhc_auth_start(port, node, (uint8_t *)mbq->sbp,
12447 		    (uint8_t *)mbq->ubp) == 0) {
12448 			/* Auth started - auth completion will */
12449 			/* handle sbp and ubp now */
12450 			mbq->sbp = NULL;
12451 			mbq->ubp = NULL;
12452 		}
12453 	}
12454 #endif	/* DHCHAP_SUPPORT */
12455 
12456 	return (0);
12457 
12458 } /* emlxs_rpi_reg_mbcmpl() */
12459 
12460 
12461 /*ARGSUSED*/
12462 static uint32_t
12463 emlxs_rpi_reg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
12464     void *arg1)
12465 {
12466 	emlxs_hba_t *hba = HBA;
12467 	MAILBOX4 *mb4;
12468 	MAILBOXQ *mbq;
12469 	MATCHMAP *mp;
12470 	uint32_t rval;
12471 
12472 	if (rpip->state != RPI_STATE_REG) {
12473 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12474 		    "rpi_reg_action:%d %s:%s arg=%p. "
12475 		    "Invalid state. Terminated.",
12476 		    rpip->RPI,
12477 		    emlxs_rpi_state_xlate(rpip->state),
12478 		    emlxs_fcf_event_xlate(evt), arg1);
12479 
12480 		return (1);
12481 	}
12482 
12483 	if (rpip->did == FABRIC_DID) {
12484 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12485 		    "rpi_reg_action:%d did=%x vpi=%d. Fabric RPI. "
12486 		    "Going online.",
12487 		    rpip->RPI,
12488 		    rpip->did,
12489 		    rpip->vpip->VPI);
12490 
12491 		/* Don't send REG_RPI, but process it as if we did */
12492 		rval = emlxs_rpi_reg_handler(port, rpip);
12493 
12494 		if (rval) {
12495 			rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
12496 			    rval, 0, 0);
12497 
12498 			return (rval);
12499 		}
12500 
12501 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
12502 		    FCF_REASON_EVENT, evt, arg1);
12503 
12504 		return (rval);
12505 	}
12506 
12507 	if (!(rpip->vpip->flag & EMLXS_VPI_PORT_ENABLED)) {
12508 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12509 		    "rpi_reg_action:%d did=%x. vpi=%d. Port disabled. "
12510 		    "Offlining RPI.",
12511 		    rpip->RPI,
12512 		    rpip->did,
12513 		    rpip->vpip->VPI);
12514 
12515 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
12516 		    FCF_REASON_NOT_ALLOWED, evt, arg1);
12517 
12518 		return (rval);
12519 	}
12520 
12521 	if (rpip->prev_state != RPI_STATE_REG_FAILED) {
12522 		rpip->attempts = 0;
12523 	}
12524 
12525 	if (rpip->flag & EMLXS_RPI_REG) {
12526 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12527 		    "rpi_reg_action:%d flag=%x. Already registered. "
12528 		    "Updating registration.",
12529 		    rpip->RPI, rpip->flag);
12530 	}
12531 
12532 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12533 	    "rpi_reg_action:%d attempts=%d. Sending REG_RPI.",
12534 	    rpip->RPI,
12535 	    rpip->attempts);
12536 
12537 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
12538 
12539 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
12540 		    FCF_REASON_NO_MBOX, 0, arg1);
12541 
12542 		return (rval);
12543 	}
12544 
12545 	mb4 = (MAILBOX4*)mbq;
12546 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
12547 
12548 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
12549 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
12550 
12551 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
12552 		    FCF_REASON_NO_BUFFER, 0, arg1);
12553 
12554 		return (rval);
12555 	}
12556 
12557 	mbq->bp = (void *)mp;
12558 	mbq->nonembed = NULL;
12559 
12560 	mbq->mbox_cmpl = emlxs_rpi_reg_mbcmpl;
12561 	mbq->context = (void *)rpip;
12562 	mbq->port = (void *)port;
12563 
12564 	mb4->mbxCommand = MBX_REG_RPI;
12565 	mb4->mbxOwner = OWN_HOST;
12566 
12567 	mb4->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
12568 	mb4->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(mp->phys);
12569 	mb4->un.varRegLogin.un.sp64.addrLow = PADDR_LO(mp->phys);
12570 	mb4->un.varRegLogin.did = rpip->did;
12571 	mb4->un.varWords[30] = 0;	/* flags */
12572 
12573 	mb4->un.varRegLogin.vpi = rpip->vpip->VPI;
12574 	mb4->un.varRegLogin.rpi = rpip->RPI;
12575 
12576 	bcopy((void *)&rpip->sparam, (void *)mp->virt, sizeof (SERV_PARM));
12577 
12578 	if (rpip->cmpl) {
12579 		mbq->sbp = rpip->cmpl->arg1;
12580 		mbq->ubp = rpip->cmpl->arg2;
12581 		mbq->iocbq = rpip->cmpl->arg3;
12582 	}
12583 
12584 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
12585 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
12586 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
12587 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
12588 
12589 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
12590 		    FCF_REASON_SEND_FAILED, rval, arg1);
12591 
12592 		return (rval);
12593 	}
12594 
12595 	if (rpip->cmpl) {
12596 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
12597 		rpip->cmpl = 0;
12598 	}
12599 
12600 	return (0);
12601 
12602 } /* emlxs_rpi_reg_action() */
12603 
12604 
12605 /*ARGSUSED*/
12606 static uint32_t
12607 emlxs_rpi_reg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
12608     void *arg1)
12609 {
12610 	uint32_t rval;
12611 
12612 	if (rpip->state != RPI_STATE_REG_CMPL) {
12613 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12614 		    "rpi_reg_cmpl_action:%d %s:%s arg=%p. "
12615 		    "Invalid state. Terminated.",
12616 		    rpip->RPI,
12617 		    emlxs_rpi_state_xlate(rpip->state),
12618 		    emlxs_fcf_event_xlate(evt), arg1);
12619 		return (1);
12620 	}
12621 
12622 	if (rpip->flag & EMLXS_RPI_REG) {
12623 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12624 		    "rpi_reg_cmpl_action:%d flag=%x. Going online",
12625 		    rpip->RPI,
12626 		    rpip->flag);
12627 
12628 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
12629 		    FCF_REASON_EVENT, evt, arg1);
12630 	} else {
12631 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12632 		    "rpi_reg_cmpl_action:%d flag=%x. Going offline.",
12633 		    rpip->RPI,
12634 		    rpip->flag);
12635 
12636 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
12637 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
12638 	}
12639 
12640 	return (rval);
12641 
12642 } /* emlxs_rpi_reg_cmpl_action() */
12643 
12644 
12645 /*ARGSUSED*/
12646 static uint32_t
12647 emlxs_rpi_resume_failed_action(emlxs_port_t *port, RPIobj_t *rpip,
12648     uint32_t evt, void *arg1)
12649 {
12650 	uint32_t rval;
12651 
12652 	rpip->attempts++;
12653 
12654 	if (rpip->state != RPI_STATE_RESUME_FAILED) {
12655 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12656 		    "rpi_resume_failed_action:%d %s:%s arg=%p attempt=%d. "
12657 		    "Invalid state. Terminated.",
12658 		    rpip->RPI,
12659 		    emlxs_rpi_state_xlate(rpip->state),
12660 		    emlxs_fcf_event_xlate(evt), arg1,
12661 		    rpip->attempts);
12662 
12663 		return (1);
12664 	}
12665 
12666 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12667 	    "rpi_resume_failed_action:%d attempt=%d. Unregistering.",
12668 	    rpip->RPI,
12669 	    rpip->attempts);
12670 
12671 	rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
12672 	    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
12673 
12674 	return (rval);
12675 
12676 } /* emlxs_rpi_resume_failed_action() */
12677 
12678 
12679 /*ARGSUSED*/
12680 static void
12681 emlxs_rpi_resume_handler(emlxs_port_t *port, RPIobj_t *rpip)
12682 {
12683 	if (rpip->flag & EMLXS_RPI_PAUSED) {
12684 		rpip->flag &= ~EMLXS_RPI_PAUSED;
12685 
12686 		if (rpip->vpip->rpi_paused) {
12687 			rpip->vpip->rpi_paused--;
12688 		}
12689 	}
12690 
12691 	return;
12692 
12693 } /* emlxs_rpi_resume_handler() */
12694 
12695 
12696 /*ARGSUSED*/
12697 static uint32_t
12698 emlxs_rpi_resume_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
12699 {
12700 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
12701 	MAILBOX4 *mb4;
12702 	RPIobj_t *rpip;
12703 
12704 	mutex_enter(&EMLXS_FCF_LOCK);
12705 
12706 	rpip = (RPIobj_t *)mbq->context;
12707 	mb4 = (MAILBOX4 *)mbq;
12708 
12709 	if (rpip->state != RPI_STATE_RESUME) {
12710 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12711 		    "rpi_resume_mbcmpl:%d state=%s. "
12712 		    "No longer in RPI_STATE_RESUME. Terminated.",
12713 		    rpip->RPI,
12714 		    emlxs_rpi_state_xlate(rpip->state));
12715 
12716 		mutex_exit(&EMLXS_FCF_LOCK);
12717 		return (0);
12718 	}
12719 
12720 	if (mb4->mbxStatus) {
12721 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12722 		    "rpi_resume_mbcmpl:%d failed. status=%x",
12723 		    rpip->RPI,
12724 		    mb4->mbxStatus);
12725 
12726 		(void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
12727 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
12728 
12729 		mutex_exit(&EMLXS_FCF_LOCK);
12730 		return (0);
12731 	}
12732 
12733 	emlxs_rpi_resume_handler(port, rpip);
12734 
12735 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12736 	    "rpi_resume_mbcmpl:%d Resumed. Resume cmpl.",
12737 	    rpip->RPI);
12738 
12739 	(void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_CMPL, 0, 0, 0);
12740 
12741 	mutex_exit(&EMLXS_FCF_LOCK);
12742 
12743 	return (0);
12744 
12745 } /* emlxs_rpi_resume_mbcmpl() */
12746 
12747 
12748 /*ARGSUSED*/
12749 static uint32_t
12750 emlxs_rpi_resume_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
12751     void *arg1)
12752 {
12753 	emlxs_hba_t *hba = HBA;
12754 	MAILBOX4 *mb4;
12755 	MAILBOXQ *mbq;
12756 	uint32_t rval;
12757 
12758 	if (rpip->state != RPI_STATE_RESUME) {
12759 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12760 		    "rpi_resume_action:%d %s:%s arg=%p. "
12761 		    "Invalid state. Terminated.",
12762 		    rpip->RPI,
12763 		    emlxs_rpi_state_xlate(rpip->state),
12764 		    emlxs_fcf_event_xlate(evt), arg1);
12765 
12766 		return (1);
12767 	}
12768 
12769 	if (!(rpip->flag & EMLXS_RPI_PAUSED)) {
12770 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12771 		    "rpi_resume_action:%d flag=%x. Not Paused. Going online.",
12772 		    rpip->RPI, rpip->flag);
12773 
12774 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
12775 		    FCF_REASON_EVENT, evt, arg1);
12776 
12777 		return (rval);
12778 	}
12779 
12780 	if (rpip->did == FABRIC_DID) {
12781 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12782 		    "rpi_resume_action:%d. Fabric RPI. "
12783 		    "Going online.",
12784 		    rpip->RPI);
12785 
12786 		/* Don't send RESUME_RPI, but process it as if we did */
12787 		emlxs_rpi_resume_handler(port, rpip);
12788 
12789 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
12790 		    FCF_REASON_EVENT, evt, arg1);
12791 
12792 		return (rval);
12793 	}
12794 
12795 	if (rpip->prev_state != RPI_STATE_RESUME_FAILED) {
12796 		rpip->attempts = 0;
12797 	}
12798 
12799 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12800 	    "rpi_resume_action:%d attempts=%d. Sending RESUME_RPI.",
12801 	    rpip->RPI,
12802 	    rpip->attempts);
12803 
12804 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
12805 
12806 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
12807 		    FCF_REASON_NO_MBOX, 0, arg1);
12808 
12809 		return (rval);
12810 	}
12811 	mb4 = (MAILBOX4*)mbq;
12812 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
12813 
12814 	mbq->nonembed = NULL;
12815 	mbq->mbox_cmpl = emlxs_rpi_resume_mbcmpl;
12816 	mbq->context = (void *)rpip;
12817 	mbq->port = (void *)port;
12818 
12819 	mb4->mbxCommand = MBX_RESUME_RPI;
12820 	mb4->mbxOwner = OWN_HOST;
12821 
12822 	mb4->un.varResumeRPI.EventTag = hba->link_event_tag;
12823 	mb4->un.varResumeRPI.RPI = rpip->RPI;
12824 
12825 	if (rpip->cmpl) {
12826 		mbq->sbp = rpip->cmpl->arg1;
12827 		mbq->ubp = rpip->cmpl->arg2;
12828 		mbq->iocbq = rpip->cmpl->arg3;
12829 	}
12830 
12831 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
12832 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
12833 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
12834 
12835 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
12836 		    FCF_REASON_SEND_FAILED, rval, arg1);
12837 
12838 		return (rval);
12839 	}
12840 
12841 	if (rpip->cmpl) {
12842 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
12843 		rpip->cmpl = 0;
12844 	}
12845 
12846 	return (0);
12847 
12848 } /* emlxs_rpi_resume_action() */
12849 
12850 
12851 static uint32_t
12852 emlxs_rpi_resume_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
12853     void *arg1)
12854 {
12855 	uint32_t rval;
12856 
12857 	if (rpip->state != RPI_STATE_RESUME_CMPL) {
12858 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12859 		    "rpi_resume_cmpl_action:%d %s:%s arg=%p. "
12860 		    "Invalid state. Terminated.",
12861 		    rpip->RPI,
12862 		    emlxs_rpi_state_xlate(rpip->state),
12863 		    emlxs_fcf_event_xlate(evt), arg1);
12864 		return (1);
12865 	}
12866 
12867 	if (rpip->flag & EMLXS_RPI_PAUSED) {
12868 		if (rpip->flag & EMLXS_RPI_REG) {
12869 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12870 			    "rpi_reg_cmpl_action:%d flag=%x. Unregistering.",
12871 			    rpip->RPI,
12872 			    rpip->flag);
12873 
12874 			rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
12875 			    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
12876 		} else {
12877 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12878 			    "rpi_reg_cmpl_action:%d flag=%x. Going offline.",
12879 			    rpip->RPI,
12880 			    rpip->flag);
12881 
12882 			rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
12883 			    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
12884 		}
12885 	} else {
12886 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12887 		    "rpi_resume_cmpl_action:%d flag=%x. Going online.",
12888 		    rpip->RPI,
12889 		    rpip->flag);
12890 
12891 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
12892 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
12893 	}
12894 
12895 	return (rval);
12896 
12897 } /* emlxs_rpi_resume_cmpl_action() */
12898 
12899 
12900 /*ARGSUSED*/
12901 static uint32_t
12902 emlxs_rpi_online_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
12903     void *arg1)
12904 {
12905 	emlxs_hba_t *hba = HBA;
12906 	uint32_t rval;
12907 
12908 	if (rpip->state != RPI_STATE_ONLINE) {
12909 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12910 		    "rpi_online_action:%d %s:%s arg=%p. "
12911 		    "Invalid state. Terminated.",
12912 		    rpip->RPI,
12913 		    emlxs_rpi_state_xlate(rpip->state),
12914 		    emlxs_fcf_event_xlate(evt), arg1);
12915 		return (1);
12916 	}
12917 
12918 	if (rpip->did == FABRIC_DID) {
12919 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12920 		    "rpi_online_action:%d did=%x. Fabric RPI online. "
12921 		    "Terminated.",
12922 		    rpip->RPI,
12923 		    rpip->did,
12924 		    rpip->vpip->VPI);
12925 
12926 		EMLXS_STATE_CHANGE(hba, FC_READY);
12927 
12928 		if (rpip->vpip->flogi_sbp) {
12929 			emlxs_vpi_flogi_cmpl(port, rpip->vpip, 0);
12930 		}
12931 
12932 		return (0);
12933 	}
12934 
12935 	if (!(rpip->vpip->flag & EMLXS_VPI_PORT_ENABLED)) {
12936 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12937 		    "rpi_online_action:%d did=%x. vpi=%d. Port disabled. "
12938 		    "Offlining RPI.",
12939 		    rpip->RPI,
12940 		    rpip->did,
12941 		    rpip->vpip->VPI);
12942 
12943 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
12944 		    FCF_REASON_NOT_ALLOWED, evt, arg1);
12945 
12946 		return (rval);
12947 	}
12948 
12949 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12950 	    "rpi_online_action:%d did=%x. RPI online. Notifying VPI:%d.",
12951 	    rpip->RPI,
12952 	    rpip->did,
12953 	    rpip->vpip->VPI);
12954 
12955 	/* Notify VPI */
12956 	rval = emlxs_vpi_event(port, FCF_EVENT_RPI_ONLINE, rpip);
12957 
12958 	return (rval);
12959 
12960 } /* emlxs_rpi_online_action() */
12961