1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte 
22*fcf3ce44SJohn Forte /*
23*fcf3ce44SJohn Forte  * Copyright 2008 Emulex.  All rights reserved.
24*fcf3ce44SJohn Forte  * Use is subject to License terms.
25*fcf3ce44SJohn Forte  */
26*fcf3ce44SJohn Forte 
27*fcf3ce44SJohn Forte 
28*fcf3ce44SJohn Forte #include "emlxs.h"
29*fcf3ce44SJohn Forte 
30*fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31*fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_MBOX_C);
32*fcf3ce44SJohn Forte 
33*fcf3ce44SJohn Forte static void emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOX *mb,
34*fcf3ce44SJohn Forte     uint32_t hbainit);
35*fcf3ce44SJohn Forte static void emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mask,
36*fcf3ce44SJohn Forte     uint32_t ringno);
37*fcf3ce44SJohn Forte static void emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOX *mb, uint32_t word0,
38*fcf3ce44SJohn Forte     uint32_t word1, uint32_t word2);
39*fcf3ce44SJohn Forte static int32_t emlxs_mb_handle_cmd(emlxs_hba_t *hba, MAILBOX *mb);
40*fcf3ce44SJohn Forte static void emlxs_mb_write_nv(emlxs_hba_t *hba, MAILBOX *mb);
41*fcf3ce44SJohn Forte 
42*fcf3ce44SJohn Forte static void emlxs_mb_init(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t flag,
43*fcf3ce44SJohn Forte     uint32_t tmo);
44*fcf3ce44SJohn Forte static void emlxs_mb_retry(emlxs_hba_t *hba, MAILBOX *mb);
45*fcf3ce44SJohn Forte 
46*fcf3ce44SJohn Forte 
47*fcf3ce44SJohn Forte emlxs_table_t emlxs_mb_cmd_table[] =
48*fcf3ce44SJohn Forte {
49*fcf3ce44SJohn Forte 	{MBX_SHUTDOWN, "SHUTDOWN"},
50*fcf3ce44SJohn Forte 	{MBX_LOAD_SM, "LOAD_SM"},
51*fcf3ce44SJohn Forte 	{MBX_READ_NV, "READ_NV"},
52*fcf3ce44SJohn Forte 	{MBX_WRITE_NV, "WRITE_NV"},
53*fcf3ce44SJohn Forte 	{MBX_RUN_BIU_DIAG, "RUN_BIU_DIAG"},
54*fcf3ce44SJohn Forte 	{MBX_INIT_LINK, "INIT_LINK"},
55*fcf3ce44SJohn Forte 	{MBX_DOWN_LINK, "DOWN_LINK"},
56*fcf3ce44SJohn Forte 	{MBX_CONFIG_LINK, "CONFIG_LINK"},
57*fcf3ce44SJohn Forte 	{MBX_PART_SLIM, "PART_SLIM"},
58*fcf3ce44SJohn Forte 	{MBX_CONFIG_RING, "CONFIG_RING"},
59*fcf3ce44SJohn Forte 	{MBX_RESET_RING, "RESET_RING"},
60*fcf3ce44SJohn Forte 	{MBX_READ_CONFIG, "READ_CONFIG"},
61*fcf3ce44SJohn Forte 	{MBX_READ_RCONFIG, "READ_RCONFIG"},
62*fcf3ce44SJohn Forte 	{MBX_READ_SPARM, "READ_SPARM"},
63*fcf3ce44SJohn Forte 	{MBX_READ_STATUS, "READ_STATUS"},
64*fcf3ce44SJohn Forte 	{MBX_READ_RPI, "READ_RPI"},
65*fcf3ce44SJohn Forte 	{MBX_READ_XRI, "READ_XRI"},
66*fcf3ce44SJohn Forte 	{MBX_READ_REV, "READ_REV"},
67*fcf3ce44SJohn Forte 	{MBX_READ_LNK_STAT, "READ_LNK_STAT"},
68*fcf3ce44SJohn Forte 	{MBX_REG_LOGIN, "REG_LOGIN"},
69*fcf3ce44SJohn Forte 	{MBX_UNREG_LOGIN, "UNREG_LOGIN"},
70*fcf3ce44SJohn Forte 	{MBX_READ_LA, "READ_LA"},
71*fcf3ce44SJohn Forte 	{MBX_CLEAR_LA, "CLEAR_LA"},
72*fcf3ce44SJohn Forte 	{MBX_DUMP_MEMORY, "DUMP_MEMORY"},
73*fcf3ce44SJohn Forte 	{MBX_DUMP_CONTEXT, "DUMP_CONTEXT"},
74*fcf3ce44SJohn Forte 	{MBX_RUN_DIAGS, "RUN_DIAGS"},
75*fcf3ce44SJohn Forte 	{MBX_RESTART, "RESTART"},
76*fcf3ce44SJohn Forte 	{MBX_UPDATE_CFG, "UPDATE_CFG"},
77*fcf3ce44SJohn Forte 	{MBX_DOWN_LOAD, "DOWN_LOAD"},
78*fcf3ce44SJohn Forte 	{MBX_DEL_LD_ENTRY, "DEL_LD_ENTRY"},
79*fcf3ce44SJohn Forte 	{MBX_RUN_PROGRAM, "RUN_PROGRAM"},
80*fcf3ce44SJohn Forte 	{MBX_SET_MASK, "SET_MASK"},
81*fcf3ce44SJohn Forte 	{MBX_SET_VARIABLE, "SET_VARIABLE"},
82*fcf3ce44SJohn Forte 	{MBX_UNREG_D_ID, "UNREG_D_ID"},
83*fcf3ce44SJohn Forte 	{MBX_KILL_BOARD, "KILL_BOARD"},
84*fcf3ce44SJohn Forte 	{MBX_CONFIG_FARP, "CONFIG_FARP"},
85*fcf3ce44SJohn Forte 	{MBX_LOAD_AREA, "LOAD_AREA"},
86*fcf3ce44SJohn Forte 	{MBX_RUN_BIU_DIAG64, "RUN_BIU_DIAG64"},
87*fcf3ce44SJohn Forte 	{MBX_CONFIG_PORT, "CONFIG_PORT"},
88*fcf3ce44SJohn Forte 	{MBX_READ_SPARM64, "READ_SPARM64"},
89*fcf3ce44SJohn Forte 	{MBX_READ_RPI64, "READ_RPI64"},
90*fcf3ce44SJohn Forte 	{MBX_CONFIG_MSI, "CONFIG_MSI"},
91*fcf3ce44SJohn Forte 	{MBX_CONFIG_MSIX, "CONFIG_MSIX"},
92*fcf3ce44SJohn Forte 	{MBX_REG_LOGIN64, "REG_LOGIN64"},
93*fcf3ce44SJohn Forte 	{MBX_READ_LA64, "READ_LA64"},
94*fcf3ce44SJohn Forte 	{MBX_FLASH_WR_ULA, "FLASH_WR_ULA"},
95*fcf3ce44SJohn Forte 	{MBX_SET_DEBUG, "SET_DEBUG"},
96*fcf3ce44SJohn Forte 	{MBX_GET_DEBUG, "GET_DEBUG"},
97*fcf3ce44SJohn Forte 	{MBX_LOAD_EXP_ROM, "LOAD_EXP_ROM"},
98*fcf3ce44SJohn Forte 	{MBX_BEACON, "BEACON"},
99*fcf3ce44SJohn Forte 	{MBX_CONFIG_HBQ, "CONFIG_HBQ"},	/* SLI3 */
100*fcf3ce44SJohn Forte 	{MBX_REG_VPI, "REG_VPI"},	/* NPIV */
101*fcf3ce44SJohn Forte 	{MBX_ASYNC_EVENT, "ASYNC_EVENT"},
102*fcf3ce44SJohn Forte 	{MBX_HEARTBEAT, "HEARTBEAT"},
103*fcf3ce44SJohn Forte 	{MBX_READ_EVENT_LOG_STATUS, "READ_EVENT_LOG_STATUS"},
104*fcf3ce44SJohn Forte 	{MBX_READ_EVENT_LOG, "READ_EVENT_LOG"},
105*fcf3ce44SJohn Forte 	{MBX_WRITE_EVENT_LOG, "WRITE_EVENT_LOG"},
106*fcf3ce44SJohn Forte 	{MBX_NV_LOG, "NV_LOG"}
107*fcf3ce44SJohn Forte 
108*fcf3ce44SJohn Forte };	/* emlxs_mb_cmd_table */
109*fcf3ce44SJohn Forte 
110*fcf3ce44SJohn Forte 
111*fcf3ce44SJohn Forte /* ARGSUSED */
112*fcf3ce44SJohn Forte extern void
113*fcf3ce44SJohn Forte emlxs_mb_async_event(emlxs_hba_t *hba, MAILBOX *mb)
114*fcf3ce44SJohn Forte {
115*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
116*fcf3ce44SJohn Forte 
117*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_ASYNC_EVENT;
118*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
119*fcf3ce44SJohn Forte 	mb->un.varWords[0] = FC_ELS_RING;
120*fcf3ce44SJohn Forte 
121*fcf3ce44SJohn Forte 	return;
122*fcf3ce44SJohn Forte 
123*fcf3ce44SJohn Forte } /* emlxs_mb_async_event() */
124*fcf3ce44SJohn Forte 
125*fcf3ce44SJohn Forte 
126*fcf3ce44SJohn Forte /* ARGSUSED */
127*fcf3ce44SJohn Forte extern void
128*fcf3ce44SJohn Forte emlxs_mb_heartbeat(emlxs_hba_t *hba, MAILBOX *mb)
129*fcf3ce44SJohn Forte {
130*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
131*fcf3ce44SJohn Forte 
132*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_HEARTBEAT;
133*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
134*fcf3ce44SJohn Forte 
135*fcf3ce44SJohn Forte 	return;
136*fcf3ce44SJohn Forte 
137*fcf3ce44SJohn Forte } /* emlxs_mb_heartbeat() */
138*fcf3ce44SJohn Forte 
139*fcf3ce44SJohn Forte 
140*fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
141*fcf3ce44SJohn Forte 
142*fcf3ce44SJohn Forte /* ARGSUSED */
143*fcf3ce44SJohn Forte extern void
144*fcf3ce44SJohn Forte emlxs_mb_config_msi(emlxs_hba_t *hba, MAILBOX *mb, uint32_t *intr_map,
145*fcf3ce44SJohn Forte     uint32_t intr_count)
146*fcf3ce44SJohn Forte {
147*fcf3ce44SJohn Forte 	uint32_t i;
148*fcf3ce44SJohn Forte 	uint32_t mask;
149*fcf3ce44SJohn Forte 
150*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
151*fcf3ce44SJohn Forte 
152*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_CONFIG_MSI;
153*fcf3ce44SJohn Forte 
154*fcf3ce44SJohn Forte 	/* Set the default message id to zero */
155*fcf3ce44SJohn Forte 	mb->un.varCfgMSI.defaultPresent = 1;
156*fcf3ce44SJohn Forte 	mb->un.varCfgMSI.defaultMessageNumber = 0;
157*fcf3ce44SJohn Forte 
158*fcf3ce44SJohn Forte 	for (i = 1; i < intr_count; i++) {
159*fcf3ce44SJohn Forte 		mask = intr_map[i];
160*fcf3ce44SJohn Forte 
161*fcf3ce44SJohn Forte 		mb->un.varCfgMSI.attConditions |= mask;
162*fcf3ce44SJohn Forte 
163*fcf3ce44SJohn Forte #ifdef EMLXS_BIG_ENDIAN
164*fcf3ce44SJohn Forte 		if (mask & HA_R0ATT) {
165*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[3] = i;
166*fcf3ce44SJohn Forte 		}
167*fcf3ce44SJohn Forte 		if (mask & HA_R1ATT) {
168*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[7] = i;
169*fcf3ce44SJohn Forte 		}
170*fcf3ce44SJohn Forte 		if (mask & HA_R2ATT) {
171*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[11] = i;
172*fcf3ce44SJohn Forte 		}
173*fcf3ce44SJohn Forte 		if (mask & HA_R3ATT) {
174*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[15] = i;
175*fcf3ce44SJohn Forte 		}
176*fcf3ce44SJohn Forte 		if (mask & HA_LATT) {
177*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[29] = i;
178*fcf3ce44SJohn Forte 		}
179*fcf3ce44SJohn Forte 		if (mask & HA_MBATT) {
180*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[30] = i;
181*fcf3ce44SJohn Forte 		}
182*fcf3ce44SJohn Forte 		if (mask & HA_ERATT) {
183*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[31] = i;
184*fcf3ce44SJohn Forte 		}
185*fcf3ce44SJohn Forte #endif	/* EMLXS_BIG_ENDIAN */
186*fcf3ce44SJohn Forte 
187*fcf3ce44SJohn Forte #ifdef EMLXS_LITTLE_ENDIAN
188*fcf3ce44SJohn Forte 		/* Accounts for half word swap of LE architecture */
189*fcf3ce44SJohn Forte 		if (mask & HA_R0ATT) {
190*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[2] = i;
191*fcf3ce44SJohn Forte 		}
192*fcf3ce44SJohn Forte 		if (mask & HA_R1ATT) {
193*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[6] = i;
194*fcf3ce44SJohn Forte 		}
195*fcf3ce44SJohn Forte 		if (mask & HA_R2ATT) {
196*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[10] = i;
197*fcf3ce44SJohn Forte 		}
198*fcf3ce44SJohn Forte 		if (mask & HA_R3ATT) {
199*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[14] = i;
200*fcf3ce44SJohn Forte 		}
201*fcf3ce44SJohn Forte 		if (mask & HA_LATT) {
202*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[28] = i;
203*fcf3ce44SJohn Forte 		}
204*fcf3ce44SJohn Forte 		if (mask & HA_MBATT) {
205*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[31] = i;
206*fcf3ce44SJohn Forte 		}
207*fcf3ce44SJohn Forte 		if (mask & HA_ERATT) {
208*fcf3ce44SJohn Forte 			mb->un.varCfgMSI.messageNumberByHA[30] = i;
209*fcf3ce44SJohn Forte 		}
210*fcf3ce44SJohn Forte #endif	/* EMLXS_LITTLE_ENDIAN */
211*fcf3ce44SJohn Forte 	}
212*fcf3ce44SJohn Forte 
213*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
214*fcf3ce44SJohn Forte 
215*fcf3ce44SJohn Forte 	return;
216*fcf3ce44SJohn Forte 
217*fcf3ce44SJohn Forte } /* emlxs_mb_config_msi() */
218*fcf3ce44SJohn Forte 
219*fcf3ce44SJohn Forte 
220*fcf3ce44SJohn Forte /* ARGSUSED */
221*fcf3ce44SJohn Forte extern void
222*fcf3ce44SJohn Forte emlxs_mb_config_msix(emlxs_hba_t *hba, MAILBOX *mb, uint32_t *intr_map,
223*fcf3ce44SJohn Forte     uint32_t intr_count)
224*fcf3ce44SJohn Forte {
225*fcf3ce44SJohn Forte 	uint32_t i;
226*fcf3ce44SJohn Forte 	uint32_t mask;
227*fcf3ce44SJohn Forte 
228*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
229*fcf3ce44SJohn Forte 
230*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_CONFIG_MSIX;
231*fcf3ce44SJohn Forte 
232*fcf3ce44SJohn Forte 	/* Set the default message id to zero */
233*fcf3ce44SJohn Forte 	mb->un.varCfgMSIX.defaultPresent = 1;
234*fcf3ce44SJohn Forte 	mb->un.varCfgMSIX.defaultMessageNumber = 0;
235*fcf3ce44SJohn Forte 
236*fcf3ce44SJohn Forte 	for (i = 1; i < intr_count; i++) {
237*fcf3ce44SJohn Forte 		mask = intr_map[i];
238*fcf3ce44SJohn Forte 
239*fcf3ce44SJohn Forte 		mb->un.varCfgMSIX.attConditions1 |= mask;
240*fcf3ce44SJohn Forte 
241*fcf3ce44SJohn Forte #ifdef EMLXS_BIG_ENDIAN
242*fcf3ce44SJohn Forte 		if (mask & HA_R0ATT) {
243*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[3] = i;
244*fcf3ce44SJohn Forte 		}
245*fcf3ce44SJohn Forte 		if (mask & HA_R1ATT) {
246*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[7] = i;
247*fcf3ce44SJohn Forte 		}
248*fcf3ce44SJohn Forte 		if (mask & HA_R2ATT) {
249*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[11] = i;
250*fcf3ce44SJohn Forte 		}
251*fcf3ce44SJohn Forte 		if (mask & HA_R3ATT) {
252*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[15] = i;
253*fcf3ce44SJohn Forte 		}
254*fcf3ce44SJohn Forte 		if (mask & HA_LATT) {
255*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[29] = i;
256*fcf3ce44SJohn Forte 		}
257*fcf3ce44SJohn Forte 		if (mask & HA_MBATT) {
258*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[30] = i;
259*fcf3ce44SJohn Forte 		}
260*fcf3ce44SJohn Forte 		if (mask & HA_ERATT) {
261*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[31] = i;
262*fcf3ce44SJohn Forte 		}
263*fcf3ce44SJohn Forte #endif	/* EMLXS_BIG_ENDIAN */
264*fcf3ce44SJohn Forte 
265*fcf3ce44SJohn Forte #ifdef EMLXS_LITTLE_ENDIAN
266*fcf3ce44SJohn Forte 		/* Accounts for word swap of LE architecture */
267*fcf3ce44SJohn Forte 		if (mask & HA_R0ATT) {
268*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[0] = i;
269*fcf3ce44SJohn Forte 		}
270*fcf3ce44SJohn Forte 		if (mask & HA_R1ATT) {
271*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[4] = i;
272*fcf3ce44SJohn Forte 		}
273*fcf3ce44SJohn Forte 		if (mask & HA_R2ATT) {
274*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[8] = i;
275*fcf3ce44SJohn Forte 		}
276*fcf3ce44SJohn Forte 		if (mask & HA_R3ATT) {
277*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[12] = i;
278*fcf3ce44SJohn Forte 		}
279*fcf3ce44SJohn Forte 		if (mask & HA_LATT) {
280*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[30] = i;
281*fcf3ce44SJohn Forte 		}
282*fcf3ce44SJohn Forte 		if (mask & HA_MBATT) {
283*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[29] = i;
284*fcf3ce44SJohn Forte 		}
285*fcf3ce44SJohn Forte 		if (mask & HA_ERATT) {
286*fcf3ce44SJohn Forte 			mb->un.varCfgMSIX.messageNumberByHA[28] = i;
287*fcf3ce44SJohn Forte 		}
288*fcf3ce44SJohn Forte #endif	/* EMLXS_LITTLE_ENDIAN */
289*fcf3ce44SJohn Forte 	}
290*fcf3ce44SJohn Forte 
291*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
292*fcf3ce44SJohn Forte 
293*fcf3ce44SJohn Forte 	return;
294*fcf3ce44SJohn Forte 
295*fcf3ce44SJohn Forte } /* emlxs_mb_config_msix() */
296*fcf3ce44SJohn Forte 
297*fcf3ce44SJohn Forte 
298*fcf3ce44SJohn Forte #endif	/* MSI_SUPPORT */
299*fcf3ce44SJohn Forte 
300*fcf3ce44SJohn Forte /* ARGSUSED */
301*fcf3ce44SJohn Forte extern void
302*fcf3ce44SJohn Forte emlxs_mb_reset_ring(emlxs_hba_t *hba, MAILBOX *mb, uint32_t ringno)
303*fcf3ce44SJohn Forte {
304*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
305*fcf3ce44SJohn Forte 
306*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_RESET_RING;
307*fcf3ce44SJohn Forte 	mb->un.varRstRing.ring_no = ringno;
308*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
309*fcf3ce44SJohn Forte 
310*fcf3ce44SJohn Forte 	return;
311*fcf3ce44SJohn Forte 
312*fcf3ce44SJohn Forte } /* emlxs_mb_reset_ring() */
313*fcf3ce44SJohn Forte 
314*fcf3ce44SJohn Forte 
315*fcf3ce44SJohn Forte 
316*fcf3ce44SJohn Forte /*
317*fcf3ce44SJohn Forte  *  emlxs_mb_dump_vpd  Issue a DUMP MEMORY
318*fcf3ce44SJohn Forte  *                     mailbox command
319*fcf3ce44SJohn Forte  */
320*fcf3ce44SJohn Forte /* ARGSUSED */
321*fcf3ce44SJohn Forte extern void
322*fcf3ce44SJohn Forte emlxs_mb_dump_vpd(emlxs_hba_t *hba, MAILBOX *mb, uint32_t offset)
323*fcf3ce44SJohn Forte {
324*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
325*fcf3ce44SJohn Forte 
326*fcf3ce44SJohn Forte 	/*
327*fcf3ce44SJohn Forte 	 * Setup to dump VPD region
328*fcf3ce44SJohn Forte 	 */
329*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_DUMP_MEMORY;
330*fcf3ce44SJohn Forte 	mb->un.varDmp.cv = 1;
331*fcf3ce44SJohn Forte 	mb->un.varDmp.type = DMP_NV_PARAMS;
332*fcf3ce44SJohn Forte 	mb->un.varDmp.entry_index = offset;
333*fcf3ce44SJohn Forte 	mb->un.varDmp.region_id = DMP_VPD_REGION;
334*fcf3ce44SJohn Forte 	mb->un.varDmp.word_cnt = DMP_VPD_DUMP_WCOUNT;	/* limited by */
335*fcf3ce44SJohn Forte 							/*   mailbox size */
336*fcf3ce44SJohn Forte 
337*fcf3ce44SJohn Forte 	mb->un.varDmp.co = 0;
338*fcf3ce44SJohn Forte 	mb->un.varDmp.resp_offset = 0;
339*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
340*fcf3ce44SJohn Forte } /* emlxs_mb_dump_vpd() */
341*fcf3ce44SJohn Forte 
342*fcf3ce44SJohn Forte 
343*fcf3ce44SJohn Forte /*
344*fcf3ce44SJohn Forte  *  emlxs_mb_read_nv  Issue a READ NVPARAM
345*fcf3ce44SJohn Forte  *                  mailbox command
346*fcf3ce44SJohn Forte  */
347*fcf3ce44SJohn Forte /* ARGSUSED */
348*fcf3ce44SJohn Forte extern void
349*fcf3ce44SJohn Forte emlxs_mb_read_nv(emlxs_hba_t *hba, MAILBOX *mb)
350*fcf3ce44SJohn Forte {
351*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
352*fcf3ce44SJohn Forte 
353*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_READ_NV;
354*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
355*fcf3ce44SJohn Forte 
356*fcf3ce44SJohn Forte } /* End emlxs_mb_read_nv */
357*fcf3ce44SJohn Forte 
358*fcf3ce44SJohn Forte 
359*fcf3ce44SJohn Forte /*
360*fcf3ce44SJohn Forte  *  emlxs_mb_read_rev  Issue a READ REV
361*fcf3ce44SJohn Forte  *                   mailbox command
362*fcf3ce44SJohn Forte  */
363*fcf3ce44SJohn Forte /* ARGSUSED */
364*fcf3ce44SJohn Forte extern void
365*fcf3ce44SJohn Forte emlxs_mb_read_rev(emlxs_hba_t *hba, MAILBOX *mb, uint32_t v3)
366*fcf3ce44SJohn Forte {
367*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
368*fcf3ce44SJohn Forte 
369*fcf3ce44SJohn Forte 	mb->un.varRdRev.cv = 1;
370*fcf3ce44SJohn Forte 
371*fcf3ce44SJohn Forte 	if (v3) {
372*fcf3ce44SJohn Forte 		mb->un.varRdRev.cv3 = 1;
373*fcf3ce44SJohn Forte 	}
374*fcf3ce44SJohn Forte 
375*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_READ_REV;
376*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
377*fcf3ce44SJohn Forte 
378*fcf3ce44SJohn Forte } /* End emlxs_mb_read_rev */
379*fcf3ce44SJohn Forte 
380*fcf3ce44SJohn Forte 
381*fcf3ce44SJohn Forte /*
382*fcf3ce44SJohn Forte  *  emlxs_mb_run_biu_diag  Issue a RUN_BIU_DIAG
383*fcf3ce44SJohn Forte  *                     mailbox command
384*fcf3ce44SJohn Forte  */
385*fcf3ce44SJohn Forte /* ARGSUSED */
386*fcf3ce44SJohn Forte extern uint32_t
387*fcf3ce44SJohn Forte emlxs_mb_run_biu_diag(emlxs_hba_t *hba, MAILBOX *mb, uint64_t out,
388*fcf3ce44SJohn Forte     uint64_t in)
389*fcf3ce44SJohn Forte {
390*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
391*fcf3ce44SJohn Forte 
392*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_RUN_BIU_DIAG64;
393*fcf3ce44SJohn Forte 	mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE;
394*fcf3ce44SJohn Forte 	mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
395*fcf3ce44SJohn Forte 	    (uint32_t)putPaddrHigh(out);
396*fcf3ce44SJohn Forte 	mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow =
397*fcf3ce44SJohn Forte 	    (uint32_t)putPaddrLow(out);
398*fcf3ce44SJohn Forte 	mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE;
399*fcf3ce44SJohn Forte 	mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =
400*fcf3ce44SJohn Forte 	    (uint32_t)putPaddrHigh(in);
401*fcf3ce44SJohn Forte 	mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = (uint32_t)putPaddrLow(in);
402*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
403*fcf3ce44SJohn Forte 
404*fcf3ce44SJohn Forte 	return (0);
405*fcf3ce44SJohn Forte 
406*fcf3ce44SJohn Forte } /* End emlxs_mb_run_biu_diag */
407*fcf3ce44SJohn Forte 
408*fcf3ce44SJohn Forte 
409*fcf3ce44SJohn Forte /*
410*fcf3ce44SJohn Forte  *  emlxs_mb_read_la  Issue a READ LA
411*fcf3ce44SJohn Forte  *                  mailbox command
412*fcf3ce44SJohn Forte  */
413*fcf3ce44SJohn Forte extern uint32_t
414*fcf3ce44SJohn Forte emlxs_mb_read_la(emlxs_hba_t *hba, MAILBOX *mb)
415*fcf3ce44SJohn Forte {
416*fcf3ce44SJohn Forte 	MATCHMAP *mp;
417*fcf3ce44SJohn Forte 
418*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
419*fcf3ce44SJohn Forte 
420*fcf3ce44SJohn Forte 	if ((mp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BUF)) == 0) {
421*fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_READ_LA64;
422*fcf3ce44SJohn Forte 
423*fcf3ce44SJohn Forte 		return (1);
424*fcf3ce44SJohn Forte 	}
425*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_READ_LA64;
426*fcf3ce44SJohn Forte 	mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
427*fcf3ce44SJohn Forte 	mb->un.varReadLA.un.lilpBde64.addrHigh =
428*fcf3ce44SJohn Forte 	    (uint32_t)putPaddrHigh(mp->phys);
429*fcf3ce44SJohn Forte 	mb->un.varReadLA.un.lilpBde64.addrLow =
430*fcf3ce44SJohn Forte 	    (uint32_t)putPaddrLow(mp->phys);
431*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
432*fcf3ce44SJohn Forte 
433*fcf3ce44SJohn Forte 	/*
434*fcf3ce44SJohn Forte 	 * save address for completion
435*fcf3ce44SJohn Forte 	 */
436*fcf3ce44SJohn Forte 	((MAILBOXQ *)mb)->bp = (uint8_t *)mp;
437*fcf3ce44SJohn Forte 
438*fcf3ce44SJohn Forte 	return (0);
439*fcf3ce44SJohn Forte 
440*fcf3ce44SJohn Forte } /* emlxs_mb_read_la() */
441*fcf3ce44SJohn Forte 
442*fcf3ce44SJohn Forte 
443*fcf3ce44SJohn Forte /*
444*fcf3ce44SJohn Forte  *  emlxs_mb_clear_la  Issue a CLEAR LA
445*fcf3ce44SJohn Forte  *                   mailbox command
446*fcf3ce44SJohn Forte  */
447*fcf3ce44SJohn Forte extern void
448*fcf3ce44SJohn Forte emlxs_mb_clear_la(emlxs_hba_t *hba, MAILBOX *mb)
449*fcf3ce44SJohn Forte {
450*fcf3ce44SJohn Forte #ifdef FC_RPI_CHECK
451*fcf3ce44SJohn Forte 	emlxs_rpi_check(hba);
452*fcf3ce44SJohn Forte #endif	/* FC_RPI_CHECK */
453*fcf3ce44SJohn Forte 
454*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
455*fcf3ce44SJohn Forte 
456*fcf3ce44SJohn Forte 	mb->un.varClearLA.eventTag = hba->link_event_tag;
457*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_CLEAR_LA;
458*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
459*fcf3ce44SJohn Forte 
460*fcf3ce44SJohn Forte 	return;
461*fcf3ce44SJohn Forte 
462*fcf3ce44SJohn Forte } /* End emlxs_mb_clear_la */
463*fcf3ce44SJohn Forte 
464*fcf3ce44SJohn Forte 
465*fcf3ce44SJohn Forte /*
466*fcf3ce44SJohn Forte  *  emlxs_mb_read_status  Issue a READ STATUS
467*fcf3ce44SJohn Forte  *                      mailbox command
468*fcf3ce44SJohn Forte  */
469*fcf3ce44SJohn Forte /* ARGSUSED */
470*fcf3ce44SJohn Forte extern void
471*fcf3ce44SJohn Forte emlxs_mb_read_status(emlxs_hba_t *hba, MAILBOX *mb)
472*fcf3ce44SJohn Forte {
473*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
474*fcf3ce44SJohn Forte 
475*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_READ_STATUS;
476*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
477*fcf3ce44SJohn Forte 
478*fcf3ce44SJohn Forte } /* End fc_read_status */
479*fcf3ce44SJohn Forte 
480*fcf3ce44SJohn Forte 
481*fcf3ce44SJohn Forte /*
482*fcf3ce44SJohn Forte  *  emlxs_mb_read_lnk_stat  Issue a LINK STATUS
483*fcf3ce44SJohn Forte  *                        mailbox command
484*fcf3ce44SJohn Forte  */
485*fcf3ce44SJohn Forte /* ARGSUSED */
486*fcf3ce44SJohn Forte extern void
487*fcf3ce44SJohn Forte emlxs_mb_read_lnk_stat(emlxs_hba_t *hba, MAILBOX *mb)
488*fcf3ce44SJohn Forte {
489*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
490*fcf3ce44SJohn Forte 
491*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_READ_LNK_STAT;
492*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
493*fcf3ce44SJohn Forte 
494*fcf3ce44SJohn Forte } /* End emlxs_mb_read_lnk_stat */
495*fcf3ce44SJohn Forte 
496*fcf3ce44SJohn Forte 
497*fcf3ce44SJohn Forte /*
498*fcf3ce44SJohn Forte  *  emlxs_mb_write_nv  Issue a WRITE NVPARAM
499*fcf3ce44SJohn Forte  *                   mailbox command
500*fcf3ce44SJohn Forte  */
501*fcf3ce44SJohn Forte static void
502*fcf3ce44SJohn Forte emlxs_emb_mb_write_nv(emlxs_hba_t *hba, MAILBOX *mb)
503*fcf3ce44SJohn Forte {
504*fcf3ce44SJohn Forte 	int32_t i;
505*fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
506*fcf3ce44SJohn Forte 
507*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
508*fcf3ce44SJohn Forte 
509*fcf3ce44SJohn Forte 	bcopy((void *) &hba->wwnn,
510*fcf3ce44SJohn Forte 	    (void *) mb->un.varWTnvp.nodename,
511*fcf3ce44SJohn Forte 	    sizeof (NAME_TYPE));
512*fcf3ce44SJohn Forte 
513*fcf3ce44SJohn Forte 	bcopy((void *) &hba->wwpn,
514*fcf3ce44SJohn Forte 	    (void *) mb->un.varWTnvp.portname,
515*fcf3ce44SJohn Forte 	    sizeof (NAME_TYPE));
516*fcf3ce44SJohn Forte 
517*fcf3ce44SJohn Forte 	mb->un.varWTnvp.pref_DID = 0;
518*fcf3ce44SJohn Forte 	mb->un.varWTnvp.hardAL_PA = (uint8_t)cfg[CFG_ASSIGN_ALPA].current;
519*fcf3ce44SJohn Forte 	mb->un.varWTnvp.rsvd1[0] = 0xffffffff;
520*fcf3ce44SJohn Forte 	mb->un.varWTnvp.rsvd1[1] = 0xffffffff;
521*fcf3ce44SJohn Forte 	mb->un.varWTnvp.rsvd1[2] = 0xffffffff;
522*fcf3ce44SJohn Forte 	for (i = 0; i < 21; i++) {
523*fcf3ce44SJohn Forte 		mb->un.varWTnvp.rsvd3[i] = 0xffffffff;
524*fcf3ce44SJohn Forte 	}
525*fcf3ce44SJohn Forte 
526*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_WRITE_NV;
527*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
528*fcf3ce44SJohn Forte } /* End emlxs_mb_write_nv */
529*fcf3ce44SJohn Forte 
530*fcf3ce44SJohn Forte 
531*fcf3ce44SJohn Forte /*
532*fcf3ce44SJohn Forte  *  emlxs_mb_part_slim  Issue a PARTITION SLIM
533*fcf3ce44SJohn Forte  *                    mailbox command
534*fcf3ce44SJohn Forte  */
535*fcf3ce44SJohn Forte static void
536*fcf3ce44SJohn Forte emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOX *mb, uint32_t hbainit)
537*fcf3ce44SJohn Forte {
538*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
539*fcf3ce44SJohn Forte 
540*fcf3ce44SJohn Forte 
541*fcf3ce44SJohn Forte 	mb->un.varSlim.numRing = hba->ring_count;
542*fcf3ce44SJohn Forte 	mb->un.varSlim.hbainit = hbainit;
543*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_PART_SLIM;
544*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
545*fcf3ce44SJohn Forte 
546*fcf3ce44SJohn Forte } /* End emlxs_mb_part_slim */
547*fcf3ce44SJohn Forte 
548*fcf3ce44SJohn Forte 
549*fcf3ce44SJohn Forte /*
550*fcf3ce44SJohn Forte  *  emlxs_mb_config_ring  Issue a CONFIG RING
551*fcf3ce44SJohn Forte  *                      mailbox command
552*fcf3ce44SJohn Forte  */
553*fcf3ce44SJohn Forte extern void
554*fcf3ce44SJohn Forte emlxs_mb_config_ring(emlxs_hba_t *hba, int32_t ring, MAILBOX *mb)
555*fcf3ce44SJohn Forte {
556*fcf3ce44SJohn Forte 	int32_t i;
557*fcf3ce44SJohn Forte 	int32_t j;
558*fcf3ce44SJohn Forte 
559*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
560*fcf3ce44SJohn Forte 
561*fcf3ce44SJohn Forte 	j = 0;
562*fcf3ce44SJohn Forte 	for (i = 0; i < ring; i++) {
563*fcf3ce44SJohn Forte 		j += hba->ring_masks[i];
564*fcf3ce44SJohn Forte 	}
565*fcf3ce44SJohn Forte 
566*fcf3ce44SJohn Forte 	for (i = 0; i < hba->ring_masks[ring]; i++) {
567*fcf3ce44SJohn Forte 		if ((j + i) >= 6) {
568*fcf3ce44SJohn Forte 			break;
569*fcf3ce44SJohn Forte 		}
570*fcf3ce44SJohn Forte 		mb->un.varCfgRing.rrRegs[i].rval = hba->ring_rval[j + i];
571*fcf3ce44SJohn Forte 		mb->un.varCfgRing.rrRegs[i].rmask = hba->ring_rmask[j + i];
572*fcf3ce44SJohn Forte 
573*fcf3ce44SJohn Forte 		mb->un.varCfgRing.rrRegs[i].tval = hba->ring_tval[j + i];
574*fcf3ce44SJohn Forte 		mb->un.varCfgRing.rrRegs[i].tmask = hba->ring_tmask[j + i];
575*fcf3ce44SJohn Forte 	}
576*fcf3ce44SJohn Forte 
577*fcf3ce44SJohn Forte 	mb->un.varCfgRing.ring = ring;
578*fcf3ce44SJohn Forte 	mb->un.varCfgRing.profile = 0;
579*fcf3ce44SJohn Forte 	mb->un.varCfgRing.maxOrigXchg = 0;
580*fcf3ce44SJohn Forte 	mb->un.varCfgRing.maxRespXchg = 0;
581*fcf3ce44SJohn Forte 	mb->un.varCfgRing.recvNotify = 1;
582*fcf3ce44SJohn Forte 	mb->un.varCfgRing.numMask = hba->ring_masks[ring];
583*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_CONFIG_RING;
584*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
585*fcf3ce44SJohn Forte 
586*fcf3ce44SJohn Forte 	return;
587*fcf3ce44SJohn Forte 
588*fcf3ce44SJohn Forte } /* End emlxs_mb_config_ring */
589*fcf3ce44SJohn Forte 
590*fcf3ce44SJohn Forte 
591*fcf3ce44SJohn Forte /*
592*fcf3ce44SJohn Forte  *  emlxs_mb_config_link  Issue a CONFIG LINK
593*fcf3ce44SJohn Forte  *                      mailbox command
594*fcf3ce44SJohn Forte  */
595*fcf3ce44SJohn Forte extern void
596*fcf3ce44SJohn Forte emlxs_mb_config_link(emlxs_hba_t *hba, MAILBOX *mb)
597*fcf3ce44SJohn Forte {
598*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
599*fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
600*fcf3ce44SJohn Forte 
601*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
602*fcf3ce44SJohn Forte 
603*fcf3ce44SJohn Forte 	/*
604*fcf3ce44SJohn Forte 	 * NEW_FEATURE SLI-2, Coalescing Response Feature.
605*fcf3ce44SJohn Forte 	 */
606*fcf3ce44SJohn Forte 	if (cfg[CFG_CR_DELAY].current) {
607*fcf3ce44SJohn Forte 		mb->un.varCfgLnk.cr = 1;
608*fcf3ce44SJohn Forte 		mb->un.varCfgLnk.ci = 1;
609*fcf3ce44SJohn Forte 		mb->un.varCfgLnk.cr_delay = cfg[CFG_CR_DELAY].current;
610*fcf3ce44SJohn Forte 		mb->un.varCfgLnk.cr_count = cfg[CFG_CR_COUNT].current;
611*fcf3ce44SJohn Forte 	}
612*fcf3ce44SJohn Forte 	if (cfg[CFG_ACK0].current)
613*fcf3ce44SJohn Forte 		mb->un.varCfgLnk.ack0_enable = 1;
614*fcf3ce44SJohn Forte 
615*fcf3ce44SJohn Forte 	mb->un.varCfgLnk.myId = port->did;
616*fcf3ce44SJohn Forte 	mb->un.varCfgLnk.edtov = hba->fc_edtov;
617*fcf3ce44SJohn Forte 	mb->un.varCfgLnk.arbtov = hba->fc_arbtov;
618*fcf3ce44SJohn Forte 	mb->un.varCfgLnk.ratov = hba->fc_ratov;
619*fcf3ce44SJohn Forte 	mb->un.varCfgLnk.rttov = hba->fc_rttov;
620*fcf3ce44SJohn Forte 	mb->un.varCfgLnk.altov = hba->fc_altov;
621*fcf3ce44SJohn Forte 	mb->un.varCfgLnk.crtov = hba->fc_crtov;
622*fcf3ce44SJohn Forte 	mb->un.varCfgLnk.citov = hba->fc_citov;
623*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_CONFIG_LINK;
624*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
625*fcf3ce44SJohn Forte 
626*fcf3ce44SJohn Forte 	return;
627*fcf3ce44SJohn Forte 
628*fcf3ce44SJohn Forte } /* emlxs_mb_config_link() */
629*fcf3ce44SJohn Forte 
630*fcf3ce44SJohn Forte 
631*fcf3ce44SJohn Forte /*
632*fcf3ce44SJohn Forte  *  emlxs_mb_init_link  Issue an INIT LINK
633*fcf3ce44SJohn Forte  *                    mailbox command
634*fcf3ce44SJohn Forte  */
635*fcf3ce44SJohn Forte extern void
636*fcf3ce44SJohn Forte emlxs_mb_init_link(emlxs_hba_t *hba, MAILBOX *mb, uint32_t topology,
637*fcf3ce44SJohn Forte     uint32_t linkspeed)
638*fcf3ce44SJohn Forte {
639*fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd = &VPD;
640*fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
641*fcf3ce44SJohn Forte 
642*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
643*fcf3ce44SJohn Forte 
644*fcf3ce44SJohn Forte 	switch (topology) {
645*fcf3ce44SJohn Forte 	case FLAGS_LOCAL_LB:
646*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
647*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_flags |= FLAGS_LOCAL_LB;
648*fcf3ce44SJohn Forte 		break;
649*fcf3ce44SJohn Forte 	case FLAGS_TOPOLOGY_MODE_LOOP_PT:
650*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
651*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
652*fcf3ce44SJohn Forte 		break;
653*fcf3ce44SJohn Forte 	case FLAGS_TOPOLOGY_MODE_PT_PT:
654*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
655*fcf3ce44SJohn Forte 		break;
656*fcf3ce44SJohn Forte 	case FLAGS_TOPOLOGY_MODE_LOOP:
657*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
658*fcf3ce44SJohn Forte 		break;
659*fcf3ce44SJohn Forte 	case FLAGS_TOPOLOGY_MODE_PT_LOOP:
660*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
661*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
662*fcf3ce44SJohn Forte 		break;
663*fcf3ce44SJohn Forte 	}
664*fcf3ce44SJohn Forte 
665*fcf3ce44SJohn Forte 	if (cfg[CFG_LILP_ENABLE].current == 0) {
666*fcf3ce44SJohn Forte 		/* Disable LIRP/LILP support */
667*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_flags |= FLAGS_LIRP_LILP;
668*fcf3ce44SJohn Forte 	}
669*fcf3ce44SJohn Forte 	/*
670*fcf3ce44SJohn Forte 	 * Setting up the link speed
671*fcf3ce44SJohn Forte 	 */
672*fcf3ce44SJohn Forte 	switch (linkspeed) {
673*fcf3ce44SJohn Forte 	case 0:
674*fcf3ce44SJohn Forte 		break;
675*fcf3ce44SJohn Forte 
676*fcf3ce44SJohn Forte 	case 1:
677*fcf3ce44SJohn Forte 		if (!(vpd->link_speed & LMT_1GB_CAPABLE)) {
678*fcf3ce44SJohn Forte 			linkspeed = 0;
679*fcf3ce44SJohn Forte 		}
680*fcf3ce44SJohn Forte 		break;
681*fcf3ce44SJohn Forte 
682*fcf3ce44SJohn Forte 	case 2:
683*fcf3ce44SJohn Forte 		if (!(vpd->link_speed & LMT_2GB_CAPABLE)) {
684*fcf3ce44SJohn Forte 			linkspeed = 0;
685*fcf3ce44SJohn Forte 		}
686*fcf3ce44SJohn Forte 		break;
687*fcf3ce44SJohn Forte 
688*fcf3ce44SJohn Forte 	case 4:
689*fcf3ce44SJohn Forte 		if (!(vpd->link_speed & LMT_4GB_CAPABLE)) {
690*fcf3ce44SJohn Forte 			linkspeed = 0;
691*fcf3ce44SJohn Forte 		}
692*fcf3ce44SJohn Forte 		break;
693*fcf3ce44SJohn Forte 
694*fcf3ce44SJohn Forte 	case 8:
695*fcf3ce44SJohn Forte 		if (!(vpd->link_speed & LMT_8GB_CAPABLE)) {
696*fcf3ce44SJohn Forte 			linkspeed = 0;
697*fcf3ce44SJohn Forte 		}
698*fcf3ce44SJohn Forte 		break;
699*fcf3ce44SJohn Forte 
700*fcf3ce44SJohn Forte 	case 10:
701*fcf3ce44SJohn Forte 		if (!(vpd->link_speed & LMT_10GB_CAPABLE)) {
702*fcf3ce44SJohn Forte 			linkspeed = 0;
703*fcf3ce44SJohn Forte 		}
704*fcf3ce44SJohn Forte 		break;
705*fcf3ce44SJohn Forte 
706*fcf3ce44SJohn Forte 	default:
707*fcf3ce44SJohn Forte 		linkspeed = 0;
708*fcf3ce44SJohn Forte 		break;
709*fcf3ce44SJohn Forte 
710*fcf3ce44SJohn Forte 	}
711*fcf3ce44SJohn Forte 
712*fcf3ce44SJohn Forte 	if ((linkspeed > 0) && (vpd->feaLevelHigh >= 0x02)) {
713*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
714*fcf3ce44SJohn Forte 		mb->un.varInitLnk.link_speed = linkspeed;
715*fcf3ce44SJohn Forte 	}
716*fcf3ce44SJohn Forte 	mb->un.varInitLnk.link_flags |= FLAGS_PREABORT_RETURN;
717*fcf3ce44SJohn Forte 
718*fcf3ce44SJohn Forte 	mb->un.varInitLnk.fabric_AL_PA = (uint8_t)cfg[CFG_ASSIGN_ALPA].current;
719*fcf3ce44SJohn Forte 	mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK;
720*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
721*fcf3ce44SJohn Forte 
722*fcf3ce44SJohn Forte 
723*fcf3ce44SJohn Forte 	return;
724*fcf3ce44SJohn Forte 
725*fcf3ce44SJohn Forte } /* emlxs_mb_init_link() */
726*fcf3ce44SJohn Forte 
727*fcf3ce44SJohn Forte 
728*fcf3ce44SJohn Forte /*
729*fcf3ce44SJohn Forte  *  emlxs_mb_down_link  Issue a DOWN LINK
730*fcf3ce44SJohn Forte  *                    mailbox command
731*fcf3ce44SJohn Forte  */
732*fcf3ce44SJohn Forte /* ARGSUSED */
733*fcf3ce44SJohn Forte extern void
734*fcf3ce44SJohn Forte emlxs_mb_down_link(emlxs_hba_t *hba, MAILBOX *mb)
735*fcf3ce44SJohn Forte {
736*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
737*fcf3ce44SJohn Forte 
738*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_DOWN_LINK;
739*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
740*fcf3ce44SJohn Forte 
741*fcf3ce44SJohn Forte 	return;
742*fcf3ce44SJohn Forte 
743*fcf3ce44SJohn Forte } /* emlxs_mb_down_link() */
744*fcf3ce44SJohn Forte 
745*fcf3ce44SJohn Forte 
746*fcf3ce44SJohn Forte /*
747*fcf3ce44SJohn Forte  *  emlxs_mb_read_sparam  Issue a READ SPARAM
748*fcf3ce44SJohn Forte  *                      mailbox command
749*fcf3ce44SJohn Forte  */
750*fcf3ce44SJohn Forte extern uint32_t
751*fcf3ce44SJohn Forte emlxs_mb_read_sparam(emlxs_hba_t *hba, MAILBOX *mb)
752*fcf3ce44SJohn Forte {
753*fcf3ce44SJohn Forte 	MATCHMAP *mp;
754*fcf3ce44SJohn Forte 
755*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
756*fcf3ce44SJohn Forte 
757*fcf3ce44SJohn Forte 	if ((mp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BUF)) == 0) {
758*fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_READ_SPARM64;
759*fcf3ce44SJohn Forte 
760*fcf3ce44SJohn Forte 		return (1);
761*fcf3ce44SJohn Forte 	}
762*fcf3ce44SJohn Forte 	mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
763*fcf3ce44SJohn Forte 	mb->un.varRdSparm.un.sp64.addrHigh = (uint32_t)putPaddrHigh(mp->phys);
764*fcf3ce44SJohn Forte 	mb->un.varRdSparm.un.sp64.addrLow = (uint32_t)putPaddrLow(mp->phys);
765*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_READ_SPARM64;
766*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
767*fcf3ce44SJohn Forte 
768*fcf3ce44SJohn Forte 	/*
769*fcf3ce44SJohn Forte 	 * save address for completion
770*fcf3ce44SJohn Forte 	 */
771*fcf3ce44SJohn Forte 	((MAILBOXQ *)mb)->bp = (uint8_t *)mp;
772*fcf3ce44SJohn Forte 
773*fcf3ce44SJohn Forte 	return (0);
774*fcf3ce44SJohn Forte 
775*fcf3ce44SJohn Forte } /* emlxs_mb_read_sparam() */
776*fcf3ce44SJohn Forte 
777*fcf3ce44SJohn Forte 
778*fcf3ce44SJohn Forte /*
779*fcf3ce44SJohn Forte  *  emlxs_mb_read_rpi    Issue a READ RPI
780*fcf3ce44SJohn Forte  *                     mailbox command
781*fcf3ce44SJohn Forte  */
782*fcf3ce44SJohn Forte /* ARGSUSED */
783*fcf3ce44SJohn Forte extern uint32_t
784*fcf3ce44SJohn Forte emlxs_mb_read_rpi(emlxs_hba_t *hba, uint32_t rpi, MAILBOX *mb, uint32_t flag)
785*fcf3ce44SJohn Forte {
786*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
787*fcf3ce44SJohn Forte 
788*fcf3ce44SJohn Forte 	/*
789*fcf3ce44SJohn Forte 	 * Set flag to issue action on cmpl
790*fcf3ce44SJohn Forte 	 */
791*fcf3ce44SJohn Forte 	mb->un.varWords[30] = flag;
792*fcf3ce44SJohn Forte 	mb->un.varRdRPI.reqRpi = (volatile uint16_t) rpi;
793*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_READ_RPI64;
794*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
795*fcf3ce44SJohn Forte 
796*fcf3ce44SJohn Forte 	return (0);
797*fcf3ce44SJohn Forte 
798*fcf3ce44SJohn Forte } /* End emlxs_mb_read_rpi */
799*fcf3ce44SJohn Forte 
800*fcf3ce44SJohn Forte 
801*fcf3ce44SJohn Forte /*
802*fcf3ce44SJohn Forte  *  emlxs_mb_read_xri    Issue a READ XRI
803*fcf3ce44SJohn Forte  *                     mailbox command
804*fcf3ce44SJohn Forte  */
805*fcf3ce44SJohn Forte /* ARGSUSED */
806*fcf3ce44SJohn Forte extern uint32_t
807*fcf3ce44SJohn Forte emlxs_mb_read_xri(emlxs_hba_t *hba, uint32_t xri, MAILBOX *mb, uint32_t flag)
808*fcf3ce44SJohn Forte {
809*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
810*fcf3ce44SJohn Forte 
811*fcf3ce44SJohn Forte 	/*
812*fcf3ce44SJohn Forte 	 * Set flag to issue action on cmpl
813*fcf3ce44SJohn Forte 	 */
814*fcf3ce44SJohn Forte 	mb->un.varWords[30] = flag;
815*fcf3ce44SJohn Forte 	mb->un.varRdXRI.reqXri = (volatile uint16_t) xri;
816*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_READ_XRI;
817*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
818*fcf3ce44SJohn Forte 
819*fcf3ce44SJohn Forte 	return (0);
820*fcf3ce44SJohn Forte 
821*fcf3ce44SJohn Forte } /* End emlxs_mb_read_xri */
822*fcf3ce44SJohn Forte 
823*fcf3ce44SJohn Forte 
824*fcf3ce44SJohn Forte /* ARGSUSED */
825*fcf3ce44SJohn Forte extern int32_t
826*fcf3ce44SJohn Forte emlxs_mb_check_sparm(emlxs_hba_t *hba, SERV_PARM *nsp)
827*fcf3ce44SJohn Forte {
828*fcf3ce44SJohn Forte 	uint32_t nsp_value;
829*fcf3ce44SJohn Forte 	uint32_t *iptr;
830*fcf3ce44SJohn Forte 
831*fcf3ce44SJohn Forte 	if (nsp->cmn.fPort) {
832*fcf3ce44SJohn Forte 		return (0);
833*fcf3ce44SJohn Forte 	}
834*fcf3ce44SJohn Forte 	/* Validate the service parameters */
835*fcf3ce44SJohn Forte 	iptr = (uint32_t *)& nsp->portName;
836*fcf3ce44SJohn Forte 	if (iptr[0] == 0 && iptr[1] == 0) {
837*fcf3ce44SJohn Forte 		return (1);
838*fcf3ce44SJohn Forte 	}
839*fcf3ce44SJohn Forte 	iptr = (uint32_t *)& nsp->nodeName;
840*fcf3ce44SJohn Forte 	if (iptr[0] == 0 && iptr[1] == 0) {
841*fcf3ce44SJohn Forte 		return (2);
842*fcf3ce44SJohn Forte 	}
843*fcf3ce44SJohn Forte 	if (nsp->cls2.classValid) {
844*fcf3ce44SJohn Forte 		nsp_value = ((nsp->cls2.rcvDataSizeMsb & 0x0f) << 8) |
845*fcf3ce44SJohn Forte 		    nsp->cls2.rcvDataSizeLsb;
846*fcf3ce44SJohn Forte 
847*fcf3ce44SJohn Forte 		/*
848*fcf3ce44SJohn Forte 		 * If the receive data length is zero then set it to the CSP
849*fcf3ce44SJohn Forte 		 * value
850*fcf3ce44SJohn Forte 		 */
851*fcf3ce44SJohn Forte 		if (!nsp_value) {
852*fcf3ce44SJohn Forte 			nsp->cls2.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb;
853*fcf3ce44SJohn Forte 			nsp->cls2.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb;
854*fcf3ce44SJohn Forte 			return (0);
855*fcf3ce44SJohn Forte 		}
856*fcf3ce44SJohn Forte 	}
857*fcf3ce44SJohn Forte 	if (nsp->cls3.classValid) {
858*fcf3ce44SJohn Forte 		nsp_value = ((nsp->cls3.rcvDataSizeMsb & 0x0f) << 8) |
859*fcf3ce44SJohn Forte 		    nsp->cls3.rcvDataSizeLsb;
860*fcf3ce44SJohn Forte 
861*fcf3ce44SJohn Forte 		/*
862*fcf3ce44SJohn Forte 		 * If the receive data length is zero then set it to the CSP
863*fcf3ce44SJohn Forte 		 * value
864*fcf3ce44SJohn Forte 		 */
865*fcf3ce44SJohn Forte 		/* This prevents a Emulex adapter bug from occurring */
866*fcf3ce44SJohn Forte 		if (!nsp_value) {
867*fcf3ce44SJohn Forte 			nsp->cls3.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb;
868*fcf3ce44SJohn Forte 			nsp->cls3.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb;
869*fcf3ce44SJohn Forte 			return (0);
870*fcf3ce44SJohn Forte 		}
871*fcf3ce44SJohn Forte 	}
872*fcf3ce44SJohn Forte 	return (0);
873*fcf3ce44SJohn Forte 
874*fcf3ce44SJohn Forte } /* emlxs_mb_check_sparm() */
875*fcf3ce44SJohn Forte 
876*fcf3ce44SJohn Forte 
877*fcf3ce44SJohn Forte /*
878*fcf3ce44SJohn Forte  *  emlxs_mb_reg_did  Issue a REG_LOGIN
879*fcf3ce44SJohn Forte  *                    mailbox command
880*fcf3ce44SJohn Forte  */
881*fcf3ce44SJohn Forte extern uint32_t
882*fcf3ce44SJohn Forte emlxs_mb_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param,
883*fcf3ce44SJohn Forte     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
884*fcf3ce44SJohn Forte {
885*fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
886*fcf3ce44SJohn Forte 	MATCHMAP *mp;
887*fcf3ce44SJohn Forte 	MAILBOXQ *mbq;
888*fcf3ce44SJohn Forte 	MAILBOX *mb;
889*fcf3ce44SJohn Forte 	uint32_t rval;
890*fcf3ce44SJohn Forte 
891*fcf3ce44SJohn Forte 	/* Check for invalid node ids to register */
892*fcf3ce44SJohn Forte 	if (did == 0 || (did & 0xff000000)) {
893*fcf3ce44SJohn Forte 		return (1);
894*fcf3ce44SJohn Forte 	}
895*fcf3ce44SJohn Forte 	if ((rval = emlxs_mb_check_sparm(hba, param))) {
896*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
897*fcf3ce44SJohn Forte 		    "Invalid service parameters. did=%06x rval=%d", did, rval);
898*fcf3ce44SJohn Forte 
899*fcf3ce44SJohn Forte 		return (1);
900*fcf3ce44SJohn Forte 	}
901*fcf3ce44SJohn Forte 	/* Check if the node limit has been reached */
902*fcf3ce44SJohn Forte 	if (port->node_count >= hba->max_nodes) {
903*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
904*fcf3ce44SJohn Forte 		    "Limit reached. did=%06x count=%d", did, port->node_count);
905*fcf3ce44SJohn Forte 
906*fcf3ce44SJohn Forte 		return (1);
907*fcf3ce44SJohn Forte 	}
908*fcf3ce44SJohn Forte 	if (!(mbq = (MAILBOXQ *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
909*fcf3ce44SJohn Forte 		return (1);
910*fcf3ce44SJohn Forte 	}
911*fcf3ce44SJohn Forte 	/* Build login request */
912*fcf3ce44SJohn Forte 	if ((mp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0) {
913*fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
914*fcf3ce44SJohn Forte 		return (1);
915*fcf3ce44SJohn Forte 	}
916*fcf3ce44SJohn Forte 	bcopy((void *) param, (void *) mp->virt, sizeof (SERV_PARM));
917*fcf3ce44SJohn Forte 
918*fcf3ce44SJohn Forte 	mb = (MAILBOX *) mbq->mbox;
919*fcf3ce44SJohn Forte 	mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
920*fcf3ce44SJohn Forte 	mb->un.varRegLogin.un.sp64.addrHigh = (uint32_t)putPaddrHigh(mp->phys);
921*fcf3ce44SJohn Forte 	mb->un.varRegLogin.un.sp64.addrLow = (uint32_t)putPaddrLow(mp->phys);
922*fcf3ce44SJohn Forte 	mb->un.varRegLogin.rpi = 0;
923*fcf3ce44SJohn Forte 	mb->un.varRegLogin.did = did;
924*fcf3ce44SJohn Forte 	mb->un.varWords[30] = 0;	/* flags */
925*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_REG_LOGIN64;
926*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
927*fcf3ce44SJohn Forte 
928*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
929*fcf3ce44SJohn Forte 	mb->un.varRegLogin.vpi =
930*fcf3ce44SJohn Forte 	    port->vpi;
931*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
932*fcf3ce44SJohn Forte 
933*fcf3ce44SJohn Forte 	mbq->sbp = (uint8_t *)sbp;
934*fcf3ce44SJohn Forte 	mbq->ubp = (uint8_t *)ubp;
935*fcf3ce44SJohn Forte 	mbq->iocbq = (uint8_t *)iocbq;
936*fcf3ce44SJohn Forte 	mbq->bp = (uint8_t *)mp;
937*fcf3ce44SJohn Forte 
938*fcf3ce44SJohn Forte 	if (emlxs_mb_issue_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
939*fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
940*fcf3ce44SJohn Forte 	}
941*fcf3ce44SJohn Forte 	return (0);
942*fcf3ce44SJohn Forte 
943*fcf3ce44SJohn Forte } /* emlxs_mb_reg_did() */
944*fcf3ce44SJohn Forte 
945*fcf3ce44SJohn Forte /*
946*fcf3ce44SJohn Forte  *  emlxs_mb_unreg_rpi  Issue a UNREG_LOGIN
947*fcf3ce44SJohn Forte  *                      mailbox command
948*fcf3ce44SJohn Forte  */
949*fcf3ce44SJohn Forte extern uint32_t
950*fcf3ce44SJohn Forte emlxs_mb_unreg_rpi(emlxs_port_t *port, uint32_t rpi, emlxs_buf_t *sbp,
951*fcf3ce44SJohn Forte     fc_unsol_buf_t *ubp, IOCBQ *iocbq)
952*fcf3ce44SJohn Forte {
953*fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
954*fcf3ce44SJohn Forte 	MAILBOXQ *mbq;
955*fcf3ce44SJohn Forte 	MAILBOX *mb;
956*fcf3ce44SJohn Forte 	NODELIST *ndlp;
957*fcf3ce44SJohn Forte 
958*fcf3ce44SJohn Forte 	if (rpi != 0xffff) {
959*fcf3ce44SJohn Forte 		/* Make sure the node does already exist */
960*fcf3ce44SJohn Forte 		ndlp = emlxs_node_find_rpi(port, rpi);
961*fcf3ce44SJohn Forte 
962*fcf3ce44SJohn Forte 
963*fcf3ce44SJohn Forte 		if (ndlp) {
964*fcf3ce44SJohn Forte 			/*
965*fcf3ce44SJohn Forte 			 * If we just unregistered the host node then clear
966*fcf3ce44SJohn Forte 			 * the host DID
967*fcf3ce44SJohn Forte 			 */
968*fcf3ce44SJohn Forte 			if (ndlp->nlp_DID == port->did) {
969*fcf3ce44SJohn Forte 				port->did = 0;
970*fcf3ce44SJohn Forte 			}
971*fcf3ce44SJohn Forte 			/* remove it */
972*fcf3ce44SJohn Forte 			emlxs_node_rm(port, ndlp);
973*fcf3ce44SJohn Forte 
974*fcf3ce44SJohn Forte 		} else {
975*fcf3ce44SJohn Forte 			return (1);
976*fcf3ce44SJohn Forte 		}
977*fcf3ce44SJohn Forte 	} else {	/* Unreg all */
978*fcf3ce44SJohn Forte 		emlxs_node_destroy_all(port);
979*fcf3ce44SJohn Forte 	}
980*fcf3ce44SJohn Forte 
981*fcf3ce44SJohn Forte 	if (!(mbq = (MAILBOXQ *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
982*fcf3ce44SJohn Forte 		return (1);
983*fcf3ce44SJohn Forte 	}
984*fcf3ce44SJohn Forte 	mb = (MAILBOX *) mbq->mbox;
985*fcf3ce44SJohn Forte 	mb->un.varUnregLogin.rpi = (uint16_t)rpi;
986*fcf3ce44SJohn Forte 
987*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
988*fcf3ce44SJohn Forte 	mb->un.varUnregLogin.vpi = port->vpi;
989*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
990*fcf3ce44SJohn Forte 
991*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_UNREG_LOGIN;
992*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
993*fcf3ce44SJohn Forte 	mbq->sbp = (uint8_t *)sbp;
994*fcf3ce44SJohn Forte 	mbq->ubp = (uint8_t *)ubp;
995*fcf3ce44SJohn Forte 	mbq->iocbq = (uint8_t *)iocbq;
996*fcf3ce44SJohn Forte 
997*fcf3ce44SJohn Forte 	if (emlxs_mb_issue_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
998*fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
999*fcf3ce44SJohn Forte 	}
1000*fcf3ce44SJohn Forte 	return (0);
1001*fcf3ce44SJohn Forte } /* emlxs_mb_unreg_rpi() */
1002*fcf3ce44SJohn Forte 
1003*fcf3ce44SJohn Forte /*
1004*fcf3ce44SJohn Forte  *  emlxs_mb_unreg_did  Issue a UNREG_DID
1005*fcf3ce44SJohn Forte  *                      mailbox command
1006*fcf3ce44SJohn Forte  */
1007*fcf3ce44SJohn Forte extern uint32_t
1008*fcf3ce44SJohn Forte emlxs_mb_unreg_did(emlxs_port_t *port, uint32_t did, emlxs_buf_t *sbp,
1009*fcf3ce44SJohn Forte     fc_unsol_buf_t *ubp, IOCBQ *iocbq)
1010*fcf3ce44SJohn Forte {
1011*fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1012*fcf3ce44SJohn Forte 	NODELIST *ndlp;
1013*fcf3ce44SJohn Forte 	MAILBOXQ *mbq;
1014*fcf3ce44SJohn Forte 	MAILBOX *mb;
1015*fcf3ce44SJohn Forte 
1016*fcf3ce44SJohn Forte 	/*
1017*fcf3ce44SJohn Forte 	 * Unregister all default RPIs if did == 0xffffffff
1018*fcf3ce44SJohn Forte 	 */
1019*fcf3ce44SJohn Forte 	if (did != 0xffffffff) {
1020*fcf3ce44SJohn Forte 		/* Check for base node */
1021*fcf3ce44SJohn Forte 		if (did == Bcast_DID) {
1022*fcf3ce44SJohn Forte 			/* just flush base node */
1023*fcf3ce44SJohn Forte 			(void) emlxs_tx_node_flush(port, &port->node_base,
1024*fcf3ce44SJohn Forte 			    0, 0, 0);
1025*fcf3ce44SJohn Forte 			(void) emlxs_chipq_node_flush(port, 0, &port->node_base,
1026*fcf3ce44SJohn Forte 			    0);
1027*fcf3ce44SJohn Forte 
1028*fcf3ce44SJohn Forte 			/* Return now */
1029*fcf3ce44SJohn Forte 			return (1);
1030*fcf3ce44SJohn Forte 		}
1031*fcf3ce44SJohn Forte 		/*
1032*fcf3ce44SJohn Forte 		 * A zero DID means that we are trying to unreg the host node
1033*fcf3ce44SJohn Forte 		 * after a link bounce
1034*fcf3ce44SJohn Forte 		 */
1035*fcf3ce44SJohn Forte 
1036*fcf3ce44SJohn Forte 		/*
1037*fcf3ce44SJohn Forte 		 * If the prev_did == 0 then the adapter has been reset and
1038*fcf3ce44SJohn Forte 		 * there is no need in unregistering
1039*fcf3ce44SJohn Forte 		 */
1040*fcf3ce44SJohn Forte 
1041*fcf3ce44SJohn Forte 		/*
1042*fcf3ce44SJohn Forte 		 * If the prev_did != 0 then we can look for the hosts last
1043*fcf3ce44SJohn Forte 		 * known DID node
1044*fcf3ce44SJohn Forte 		 */
1045*fcf3ce44SJohn Forte 
1046*fcf3ce44SJohn Forte 		if (did == 0) {
1047*fcf3ce44SJohn Forte 			if (port->prev_did == 0) {
1048*fcf3ce44SJohn Forte 				return (1);
1049*fcf3ce44SJohn Forte 			}
1050*fcf3ce44SJohn Forte 			did = port->prev_did;
1051*fcf3ce44SJohn Forte 		}
1052*fcf3ce44SJohn Forte 		/* Make sure the node does already exist */
1053*fcf3ce44SJohn Forte 		ndlp = emlxs_node_find_did(port, did);
1054*fcf3ce44SJohn Forte 
1055*fcf3ce44SJohn Forte 
1056*fcf3ce44SJohn Forte 		if (ndlp) {
1057*fcf3ce44SJohn Forte 			/* remove it */
1058*fcf3ce44SJohn Forte 			emlxs_node_rm(port, ndlp);
1059*fcf3ce44SJohn Forte 
1060*fcf3ce44SJohn Forte 			/*
1061*fcf3ce44SJohn Forte 			 * If we just unregistered the host node then clear
1062*fcf3ce44SJohn Forte 			 * the host DID
1063*fcf3ce44SJohn Forte 			 */
1064*fcf3ce44SJohn Forte 			if (did == port->did) {
1065*fcf3ce44SJohn Forte 				port->did = 0;
1066*fcf3ce44SJohn Forte 			}
1067*fcf3ce44SJohn Forte 		} else {
1068*fcf3ce44SJohn Forte 			return (1);
1069*fcf3ce44SJohn Forte 		}
1070*fcf3ce44SJohn Forte 	}
1071*fcf3ce44SJohn Forte 	if (!(mbq = (MAILBOXQ *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
1072*fcf3ce44SJohn Forte 		return (1);
1073*fcf3ce44SJohn Forte 	}
1074*fcf3ce44SJohn Forte 	mb = (MAILBOX *) mbq->mbox;
1075*fcf3ce44SJohn Forte 	mb->un.varUnregDID.did = did;
1076*fcf3ce44SJohn Forte 
1077*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
1078*fcf3ce44SJohn Forte 	mb->un.varUnregDID.vpi = port->vpi;
1079*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
1080*fcf3ce44SJohn Forte 
1081*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_UNREG_D_ID;
1082*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1083*fcf3ce44SJohn Forte 	mbq->sbp = (uint8_t *)sbp;
1084*fcf3ce44SJohn Forte 	mbq->ubp = (uint8_t *)ubp;
1085*fcf3ce44SJohn Forte 	mbq->iocbq = (uint8_t *)iocbq;
1086*fcf3ce44SJohn Forte 
1087*fcf3ce44SJohn Forte 	if (emlxs_mb_issue_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
1088*fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
1089*fcf3ce44SJohn Forte 	}
1090*fcf3ce44SJohn Forte 	return (0);
1091*fcf3ce44SJohn Forte 
1092*fcf3ce44SJohn Forte } /* End emlxs_mb_unreg_did */
1093*fcf3ce44SJohn Forte 
1094*fcf3ce44SJohn Forte 
1095*fcf3ce44SJohn Forte /*
1096*fcf3ce44SJohn Forte  *  emlxs_mb_set_mask   Issue a SET MASK
1097*fcf3ce44SJohn Forte  *                    mailbox command
1098*fcf3ce44SJohn Forte  */
1099*fcf3ce44SJohn Forte /* ARGSUSED */
1100*fcf3ce44SJohn Forte static void
1101*fcf3ce44SJohn Forte emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mask,
1102*fcf3ce44SJohn Forte     uint32_t ringno)
1103*fcf3ce44SJohn Forte {
1104*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1105*fcf3ce44SJohn Forte 
1106*fcf3ce44SJohn Forte 	mb->un.varWords[0] = 0x11223344;	/* set passwd */
1107*fcf3ce44SJohn Forte 	mb->un.varWords[1] = mask;	/* set mask */
1108*fcf3ce44SJohn Forte 	mb->un.varWords[2] = ringno;	/* set ringno */
1109*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_SET_MASK;
1110*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1111*fcf3ce44SJohn Forte 
1112*fcf3ce44SJohn Forte } /* End emlxs_mb_set_mask */
1113*fcf3ce44SJohn Forte 
1114*fcf3ce44SJohn Forte 
1115*fcf3ce44SJohn Forte /*
1116*fcf3ce44SJohn Forte  *  emlxs_mb_set_debug  Issue a special debug
1117*fcf3ce44SJohn Forte  *                    mailbox command
1118*fcf3ce44SJohn Forte  */
1119*fcf3ce44SJohn Forte /* ARGSUSED */
1120*fcf3ce44SJohn Forte static void
1121*fcf3ce44SJohn Forte emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOX *mb, uint32_t word0,
1122*fcf3ce44SJohn Forte     uint32_t word1, uint32_t word2)
1123*fcf3ce44SJohn Forte {
1124*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1125*fcf3ce44SJohn Forte 
1126*fcf3ce44SJohn Forte 	mb->un.varWords[0] = word0;
1127*fcf3ce44SJohn Forte 	mb->un.varWords[1] = word1;
1128*fcf3ce44SJohn Forte 	mb->un.varWords[2] = word2;
1129*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_SET_DEBUG;
1130*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1131*fcf3ce44SJohn Forte 
1132*fcf3ce44SJohn Forte } /* End emlxs_mb_set_debug */
1133*fcf3ce44SJohn Forte 
1134*fcf3ce44SJohn Forte 
1135*fcf3ce44SJohn Forte /*
1136*fcf3ce44SJohn Forte  *  emlxs_mb_set_var   Issue a special debug mbox
1137*fcf3ce44SJohn Forte  *                    command to write slim
1138*fcf3ce44SJohn Forte  */
1139*fcf3ce44SJohn Forte /* ARGSUSED */
1140*fcf3ce44SJohn Forte extern void
1141*fcf3ce44SJohn Forte emlxs_mb_set_var(emlxs_hba_t *hba, MAILBOX *mb, uint32_t addr, uint32_t value)
1142*fcf3ce44SJohn Forte {
1143*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1144*fcf3ce44SJohn Forte 
1145*fcf3ce44SJohn Forte 	/* addr = 0x090597 is AUTO ABTS disable for ELS commands */
1146*fcf3ce44SJohn Forte 	/* addr = 0x052198 is DELAYED ABTS enable for ELS commands */
1147*fcf3ce44SJohn Forte 	/* addr = 0x100506 is for setting PCI MAX READ value */
1148*fcf3ce44SJohn Forte 
1149*fcf3ce44SJohn Forte 	/*
1150*fcf3ce44SJohn Forte 	 * Always turn on DELAYED ABTS for ELS timeouts
1151*fcf3ce44SJohn Forte 	 */
1152*fcf3ce44SJohn Forte 	if ((addr == 0x052198) && (value == 0)) {
1153*fcf3ce44SJohn Forte 		value = 1;
1154*fcf3ce44SJohn Forte 	}
1155*fcf3ce44SJohn Forte 	mb->un.varWords[0] = addr;
1156*fcf3ce44SJohn Forte 	mb->un.varWords[1] = value;
1157*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_SET_VARIABLE;
1158*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1159*fcf3ce44SJohn Forte 
1160*fcf3ce44SJohn Forte } /* End emlxs_mb_set_var */
1161*fcf3ce44SJohn Forte 
1162*fcf3ce44SJohn Forte 
1163*fcf3ce44SJohn Forte /*
1164*fcf3ce44SJohn Forte  * Disable Traffic Cop
1165*fcf3ce44SJohn Forte  */
1166*fcf3ce44SJohn Forte /* ARGSUSED */
1167*fcf3ce44SJohn Forte extern void
1168*fcf3ce44SJohn Forte emlxs_disable_tc(emlxs_hba_t *hba, MAILBOX *mb)
1169*fcf3ce44SJohn Forte {
1170*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1171*fcf3ce44SJohn Forte 
1172*fcf3ce44SJohn Forte 	mb->un.varWords[0] = 0x50797;
1173*fcf3ce44SJohn Forte 	mb->un.varWords[1] = 0;
1174*fcf3ce44SJohn Forte 	mb->un.varWords[2] = 0xfffffffe;
1175*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_SET_VARIABLE;
1176*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1177*fcf3ce44SJohn Forte 
1178*fcf3ce44SJohn Forte } /* End emlxs_disable_tc */
1179*fcf3ce44SJohn Forte 
1180*fcf3ce44SJohn Forte 
1181*fcf3ce44SJohn Forte /*
1182*fcf3ce44SJohn Forte  *  emlxs_mb_config_port  Issue a CONFIG_PORT
1183*fcf3ce44SJohn Forte  *                      mailbox command
1184*fcf3ce44SJohn Forte  */
1185*fcf3ce44SJohn Forte extern uint32_t
1186*fcf3ce44SJohn Forte emlxs_mb_config_port(emlxs_hba_t *hba, MAILBOX *mb, uint32_t sli_mode,
1187*fcf3ce44SJohn Forte     uint32_t hbainit)
1188*fcf3ce44SJohn Forte {
1189*fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd = &VPD;
1190*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1191*fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
1192*fcf3ce44SJohn Forte 	RING *rp;
1193*fcf3ce44SJohn Forte 	uint64_t pcb;
1194*fcf3ce44SJohn Forte 	uint64_t mbx;
1195*fcf3ce44SJohn Forte 	uint64_t hgp;
1196*fcf3ce44SJohn Forte 	uint64_t pgp;
1197*fcf3ce44SJohn Forte 	uint64_t rgp;
1198*fcf3ce44SJohn Forte 	MAILBOX *mbox;
1199*fcf3ce44SJohn Forte 	SLIM2 *slim;
1200*fcf3ce44SJohn Forte 	SLI2_RDSC *rdsc;
1201*fcf3ce44SJohn Forte 	uint64_t offset;
1202*fcf3ce44SJohn Forte 	uint32_t Laddr;
1203*fcf3ce44SJohn Forte 	uint32_t i;
1204*fcf3ce44SJohn Forte 
1205*fcf3ce44SJohn Forte 	cfg = &CFG;
1206*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1207*fcf3ce44SJohn Forte 	mbox = NULL;
1208*fcf3ce44SJohn Forte 	slim = NULL;
1209*fcf3ce44SJohn Forte 
1210*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_CONFIG_PORT;
1211*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1212*fcf3ce44SJohn Forte 
1213*fcf3ce44SJohn Forte 	mb->un.varCfgPort.pcbLen = sizeof (PCB);
1214*fcf3ce44SJohn Forte 
1215*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
1216*fcf3ce44SJohn Forte 	mb->un.varCfgPort.hbainit[0] = hbainit;
1217*fcf3ce44SJohn Forte #else	/* SLI3_SUPPORT */
1218*fcf3ce44SJohn Forte 	mb->un.varCfgPort.hbainit = hbainit;
1219*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
1220*fcf3ce44SJohn Forte 
1221*fcf3ce44SJohn Forte 	pcb = hba->slim2.phys + (uint64_t)(unsigned long)& (slim->pcb);
1222*fcf3ce44SJohn Forte 	mb->un.varCfgPort.pcbLow = (uint32_t)putPaddrLow(pcb);
1223*fcf3ce44SJohn Forte 	mb->un.varCfgPort.pcbHigh = (uint32_t)putPaddrHigh(pcb);
1224*fcf3ce44SJohn Forte 
1225*fcf3ce44SJohn Forte 	/* Set Host pointers in SLIM flag */
1226*fcf3ce44SJohn Forte 	mb->un.varCfgPort.hps = 1;
1227*fcf3ce44SJohn Forte 
1228*fcf3ce44SJohn Forte 	/* Initialize hba structure for assumed default SLI2 mode */
1229*fcf3ce44SJohn Forte 	/* If config port succeeds, then we will update it then   */
1230*fcf3ce44SJohn Forte 	hba->sli_mode = 2;
1231*fcf3ce44SJohn Forte 	hba->vpi_max = 1;
1232*fcf3ce44SJohn Forte 	hba->flag &= ~FC_NPIV_ENABLED;
1233*fcf3ce44SJohn Forte 
1234*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
1235*fcf3ce44SJohn Forte 	if (sli_mode >= 3) {
1236*fcf3ce44SJohn Forte 		mb->un.varCfgPort.sli_mode = 3;
1237*fcf3ce44SJohn Forte 		mb->un.varCfgPort.cerbm = 1;
1238*fcf3ce44SJohn Forte 		mb->un.varCfgPort.max_hbq = EMLXS_NUM_HBQ;
1239*fcf3ce44SJohn Forte 
1240*fcf3ce44SJohn Forte #ifdef NPIV_SUPPORT
1241*fcf3ce44SJohn Forte 		if (cfg[CFG_NPIV_ENABLE].current) {
1242*fcf3ce44SJohn Forte 			if (vpd->feaLevelHigh >= 0x09) {
1243*fcf3ce44SJohn Forte 				if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
1244*fcf3ce44SJohn Forte 					mb->un.varCfgPort.vpi_max =
1245*fcf3ce44SJohn Forte 					    MAX_VPORTS - 1;
1246*fcf3ce44SJohn Forte 				} else {
1247*fcf3ce44SJohn Forte 					mb->un.varCfgPort.vpi_max =
1248*fcf3ce44SJohn Forte 					    MAX_VPORTS_LIMITED - 1;
1249*fcf3ce44SJohn Forte 				}
1250*fcf3ce44SJohn Forte 
1251*fcf3ce44SJohn Forte 				mb->un.varCfgPort.cmv = 1;
1252*fcf3ce44SJohn Forte 			} else {
1253*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1254*fcf3ce44SJohn Forte 				    "CFGPORT: Firmware does not support NPIV. "
1255*fcf3ce44SJohn Forte 				    "level=%d", vpd->feaLevelHigh);
1256*fcf3ce44SJohn Forte 			}
1257*fcf3ce44SJohn Forte 
1258*fcf3ce44SJohn Forte 		}
1259*fcf3ce44SJohn Forte #endif	/* NPIV_SUPPORT */
1260*fcf3ce44SJohn Forte 	}
1261*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
1262*fcf3ce44SJohn Forte 
1263*fcf3ce44SJohn Forte 	/*
1264*fcf3ce44SJohn Forte 	 * Now setup pcb
1265*fcf3ce44SJohn Forte 	 */
1266*fcf3ce44SJohn Forte 	((SLIM2 *) hba->slim2.virt)->pcb.type = TYPE_NATIVE_SLI2;
1267*fcf3ce44SJohn Forte 	((SLIM2 *) hba->slim2.virt)->pcb.feature = FEATURE_INITIAL_SLI2;
1268*fcf3ce44SJohn Forte 	((SLIM2 *) hba->slim2.virt)->pcb.maxRing = (hba->ring_count - 1);
1269*fcf3ce44SJohn Forte 	((SLIM2 *) hba->slim2.virt)->pcb.mailBoxSize = sizeof (MAILBOX) +
1270*fcf3ce44SJohn Forte 	    MBOX_EXTENSION_SIZE;
1271*fcf3ce44SJohn Forte 
1272*fcf3ce44SJohn Forte 	mbx = hba->slim2.phys + (uint64_t)(unsigned long)& (slim->mbx);
1273*fcf3ce44SJohn Forte 	((SLIM2 *)hba->slim2.virt)->pcb.mbAddrHigh =
1274*fcf3ce44SJohn Forte 	    (uint32_t)putPaddrHigh(mbx);
1275*fcf3ce44SJohn Forte 	((SLIM2 *)hba->slim2.virt)->pcb.mbAddrLow = (uint32_t)putPaddrLow(mbx);
1276*fcf3ce44SJohn Forte 
1277*fcf3ce44SJohn Forte 
1278*fcf3ce44SJohn Forte 	/*
1279*fcf3ce44SJohn Forte 	 * Set up HGP - Port Memory
1280*fcf3ce44SJohn Forte 	 *
1281*fcf3ce44SJohn Forte 	 * CR0Put    - SLI2(no HBQs) = 0xc0, With HBQs = 0x80
1282*fcf3ce44SJohn Forte 	 * RR0Get 0xc4 0x84
1283*fcf3ce44SJohn Forte 	 * CR1Put 0xc8 0x88
1284*fcf3ce44SJohn Forte 	 * RR1Get 0xcc 0x8c
1285*fcf3ce44SJohn Forte 	 * CR2Put 0xd0 0x90
1286*fcf3ce44SJohn Forte 	 * RR2Get 0xd4 0x94
1287*fcf3ce44SJohn Forte 	 * CR3Put 0xd8 0x98
1288*fcf3ce44SJohn Forte 	 * RR3Get 0xdc 0x9c
1289*fcf3ce44SJohn Forte 	 *
1290*fcf3ce44SJohn Forte 	 * Reserved 0xa0-0xbf
1291*fcf3ce44SJohn Forte 	 *
1292*fcf3ce44SJohn Forte 	 * If HBQs configured:
1293*fcf3ce44SJohn Forte 	 * HBQ 0 Put ptr  0xc0
1294*fcf3ce44SJohn Forte 	 * HBQ 1 Put ptr  0xc4
1295*fcf3ce44SJohn Forte 	 * HBQ 2 Put ptr  0xc8
1296*fcf3ce44SJohn Forte 	 * ......
1297*fcf3ce44SJohn Forte 	 * HBQ(M-1)Put Pointer 0xc0+(M-1)*4
1298*fcf3ce44SJohn Forte 	 */
1299*fcf3ce44SJohn Forte 
1300*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
1301*fcf3ce44SJohn Forte 	if (sli_mode >= 3) {
1302*fcf3ce44SJohn Forte 		/* ERBM is enabled */
1303*fcf3ce44SJohn Forte 		hba->hgp_ring_offset = 0x80;
1304*fcf3ce44SJohn Forte 		hba->hgp_hbq_offset = 0xC0;
1305*fcf3ce44SJohn Forte 
1306*fcf3ce44SJohn Forte 		hba->iocb_cmd_size = SLI3_IOCB_CMD_SIZE;
1307*fcf3ce44SJohn Forte 		hba->iocb_rsp_size = SLI3_IOCB_RSP_SIZE;
1308*fcf3ce44SJohn Forte 
1309*fcf3ce44SJohn Forte 	} else	/* SLI2 */
1310*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
1311*fcf3ce44SJohn Forte 	{
1312*fcf3ce44SJohn Forte 		/* ERBM is disabled */
1313*fcf3ce44SJohn Forte 		hba->hgp_ring_offset = 0xC0;
1314*fcf3ce44SJohn Forte 		hba->hgp_hbq_offset = 0;
1315*fcf3ce44SJohn Forte 
1316*fcf3ce44SJohn Forte 		hba->iocb_cmd_size = SLI2_IOCB_CMD_SIZE;
1317*fcf3ce44SJohn Forte 		hba->iocb_rsp_size = SLI2_IOCB_RSP_SIZE;
1318*fcf3ce44SJohn Forte 	}
1319*fcf3ce44SJohn Forte 
1320*fcf3ce44SJohn Forte 	/* The Sbus card uses Host Memory. The PCI card uses SLIM POINTER */
1321*fcf3ce44SJohn Forte 	if (hba->bus_type == SBUS_FC) {
1322*fcf3ce44SJohn Forte 		hgp = hba->slim2.phys +
1323*fcf3ce44SJohn Forte 		    (uint64_t)(unsigned long)& (mbox->us.s2.host);
1324*fcf3ce44SJohn Forte 		((SLIM2 *)hba->slim2.virt)->pcb.hgpAddrHigh =
1325*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrHigh(hgp);
1326*fcf3ce44SJohn Forte 		((SLIM2 *)hba->slim2.virt)->pcb.hgpAddrLow =
1327*fcf3ce44SJohn Forte 		    (uint32_t)putPaddrLow(hgp);
1328*fcf3ce44SJohn Forte 	} else {
1329*fcf3ce44SJohn Forte 		((SLIM2 *)hba->slim2.virt)->pcb.hgpAddrHigh =
1330*fcf3ce44SJohn Forte 		    (uint32_t)ddi_get32(hba->pci_acc_handle,
1331*fcf3ce44SJohn Forte 		    (uint32_t *)(hba->pci_addr + PCI_BAR_1_REGISTER));
1332*fcf3ce44SJohn Forte 
1333*fcf3ce44SJohn Forte 		Laddr = ddi_get32(hba->pci_acc_handle,
1334*fcf3ce44SJohn Forte 		    (uint32_t *)(hba->pci_addr + PCI_BAR_0_REGISTER));
1335*fcf3ce44SJohn Forte 		Laddr &= ~0x4;
1336*fcf3ce44SJohn Forte 		((SLIM2 *)hba->slim2.virt)->pcb.hgpAddrLow =
1337*fcf3ce44SJohn Forte 		    (uint32_t)(Laddr + hba->hgp_ring_offset);
1338*fcf3ce44SJohn Forte 
1339*fcf3ce44SJohn Forte 	}
1340*fcf3ce44SJohn Forte 
1341*fcf3ce44SJohn Forte 	pgp = hba->slim2.phys + (uint64_t)(unsigned long)& (mbox->us.s2.port);
1342*fcf3ce44SJohn Forte 	((SLIM2 *)hba->slim2.virt)->pcb.pgpAddrHigh =
1343*fcf3ce44SJohn Forte 	    (uint32_t)putPaddrHigh(pgp);
1344*fcf3ce44SJohn Forte 	((SLIM2 *)hba->slim2.virt)->pcb.pgpAddrLow = (uint32_t)putPaddrLow(pgp);
1345*fcf3ce44SJohn Forte 
1346*fcf3ce44SJohn Forte 	offset = 0;
1347*fcf3ce44SJohn Forte 	for (i = 0; i < 4; i++) {
1348*fcf3ce44SJohn Forte 		rp = &hba->ring[i];
1349*fcf3ce44SJohn Forte 		rdsc = &((SLIM2 *) hba->slim2.virt)->pcb.rdsc[i];
1350*fcf3ce44SJohn Forte 
1351*fcf3ce44SJohn Forte 		/* Setup command ring */
1352*fcf3ce44SJohn Forte 		rgp = hba->slim2.phys +
1353*fcf3ce44SJohn Forte 		    (uint64_t)(unsigned long)& (slim->IOCBs[offset]);
1354*fcf3ce44SJohn Forte 		rdsc->cmdAddrHigh = (uint32_t)putPaddrHigh(rgp);
1355*fcf3ce44SJohn Forte 		rdsc->cmdAddrLow = (uint32_t)putPaddrLow(rgp);
1356*fcf3ce44SJohn Forte 		rdsc->cmdEntries = rp->fc_numCiocb;
1357*fcf3ce44SJohn Forte 
1358*fcf3ce44SJohn Forte 		rp->fc_cmdringaddr = (void *) &((SLIM2 *) hba->slim2.virt)->
1359*fcf3ce44SJohn Forte 		    IOCBs[offset];
1360*fcf3ce44SJohn Forte 		offset += rdsc->cmdEntries * hba->iocb_cmd_size;
1361*fcf3ce44SJohn Forte 
1362*fcf3ce44SJohn Forte 		/* Setup response ring */
1363*fcf3ce44SJohn Forte 		rgp = hba->slim2.phys +
1364*fcf3ce44SJohn Forte 		    (uint64_t)(unsigned long)& (slim->IOCBs[offset]);
1365*fcf3ce44SJohn Forte 		rdsc->rspAddrHigh = (uint32_t)putPaddrHigh(rgp);
1366*fcf3ce44SJohn Forte 		rdsc->rspAddrLow = (uint32_t)putPaddrLow(rgp);
1367*fcf3ce44SJohn Forte 		rdsc->rspEntries = rp->fc_numRiocb;
1368*fcf3ce44SJohn Forte 
1369*fcf3ce44SJohn Forte 		rp->fc_rspringaddr = (void *) &((SLIM2 *) hba->slim2.virt)->
1370*fcf3ce44SJohn Forte 		    IOCBs[offset];
1371*fcf3ce44SJohn Forte 		offset += rdsc->rspEntries * hba->iocb_rsp_size;
1372*fcf3ce44SJohn Forte 	}
1373*fcf3ce44SJohn Forte 
1374*fcf3ce44SJohn Forte 	emlxs_pcimem_bcopy((uint32_t *)(&((SLIM2 *) hba->slim2.virt)->pcb),
1375*fcf3ce44SJohn Forte 	    (uint32_t *)(&((SLIM2 *) hba->slim2.virt)->pcb), sizeof (PCB));
1376*fcf3ce44SJohn Forte 
1377*fcf3ce44SJohn Forte 	offset =
1378*fcf3ce44SJohn Forte 	    ((uint64_t)(unsigned long)& (((SLIM2 *) hba->slim2.virt)->pcb) -
1379*fcf3ce44SJohn Forte 	    (uint64_t)(unsigned long)hba->slim2.virt);
1380*fcf3ce44SJohn Forte 	emlxs_mpdata_sync(hba->slim2.dma_handle, (off_t)offset, sizeof (PCB),
1381*fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORDEV);
1382*fcf3ce44SJohn Forte 
1383*fcf3ce44SJohn Forte 	return (0);
1384*fcf3ce44SJohn Forte 
1385*fcf3ce44SJohn Forte } /* emlxs_mb_config_port() */
1386*fcf3ce44SJohn Forte 
1387*fcf3ce44SJohn Forte 
1388*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
1389*fcf3ce44SJohn Forte extern void
1390*fcf3ce44SJohn Forte emlxs_mb_config_hbq(emlxs_hba_t *hba, MAILBOX *mb, int hbq_id)
1391*fcf3ce44SJohn Forte {
1392*fcf3ce44SJohn Forte 	HBQ_INIT_t *hbq;
1393*fcf3ce44SJohn Forte 	int i;
1394*fcf3ce44SJohn Forte 
1395*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1396*fcf3ce44SJohn Forte 
1397*fcf3ce44SJohn Forte 	hbq = &hba->hbq_table[hbq_id];
1398*fcf3ce44SJohn Forte 
1399*fcf3ce44SJohn Forte 	mb->un.varCfgHbq.hbqId = hbq_id;
1400*fcf3ce44SJohn Forte 	mb->un.varCfgHbq.numEntries = hbq->HBQ_numEntries;
1401*fcf3ce44SJohn Forte 	mb->un.varCfgHbq.recvNotify = hbq->HBQ_recvNotify;
1402*fcf3ce44SJohn Forte 	mb->un.varCfgHbq.numMask = hbq->HBQ_num_mask;
1403*fcf3ce44SJohn Forte 	mb->un.varCfgHbq.profile = hbq->HBQ_profile;
1404*fcf3ce44SJohn Forte 	mb->un.varCfgHbq.ringMask = hbq->HBQ_ringMask;
1405*fcf3ce44SJohn Forte 	mb->un.varCfgHbq.headerLen = hbq->HBQ_headerLen;
1406*fcf3ce44SJohn Forte 	mb->un.varCfgHbq.logEntry = hbq->HBQ_logEntry;
1407*fcf3ce44SJohn Forte 	mb->un.varCfgHbq.hbqaddrLow = putPaddrLow(hbq->HBQ_host_buf.phys);
1408*fcf3ce44SJohn Forte 	mb->un.varCfgHbq.hbqaddrHigh = putPaddrHigh(hbq->HBQ_host_buf.phys);
1409*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_CONFIG_HBQ;
1410*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1411*fcf3ce44SJohn Forte 
1412*fcf3ce44SJohn Forte 	/* Copy info for profiles 2,3,5. Other profiles this area is reserved */
1413*fcf3ce44SJohn Forte 	if ((hbq->HBQ_profile == 2) || (hbq->HBQ_profile == 3) ||
1414*fcf3ce44SJohn Forte 	    (hbq->HBQ_profile == 5)) {
1415*fcf3ce44SJohn Forte 		bcopy(&hbq->profiles.allprofiles,
1416*fcf3ce44SJohn Forte 		    &mb->un.varCfgHbq.profiles.allprofiles,
1417*fcf3ce44SJohn Forte 		    sizeof (hbq->profiles));
1418*fcf3ce44SJohn Forte 	}
1419*fcf3ce44SJohn Forte 	/* Return if no rctl / type masks for this HBQ */
1420*fcf3ce44SJohn Forte 	if (!hbq->HBQ_num_mask) {
1421*fcf3ce44SJohn Forte 		return;
1422*fcf3ce44SJohn Forte 	}
1423*fcf3ce44SJohn Forte 	/* Otherwise we setup specific rctl / type masks for this HBQ */
1424*fcf3ce44SJohn Forte 	for (i = 0; i < hbq->HBQ_num_mask; i++) {
1425*fcf3ce44SJohn Forte 		mb->un.varCfgHbq.hbqMasks[i].tmatch = hbq->HBQ_Masks[i].tmatch;
1426*fcf3ce44SJohn Forte 		mb->un.varCfgHbq.hbqMasks[i].tmask = hbq->HBQ_Masks[i].tmask;
1427*fcf3ce44SJohn Forte 		mb->un.varCfgHbq.hbqMasks[i].rctlmatch =
1428*fcf3ce44SJohn Forte 		    hbq->HBQ_Masks[i].rctlmatch;
1429*fcf3ce44SJohn Forte 		mb->un.varCfgHbq.hbqMasks[i].rctlmask =
1430*fcf3ce44SJohn Forte 		    hbq->HBQ_Masks[i].rctlmask;
1431*fcf3ce44SJohn Forte 	}
1432*fcf3ce44SJohn Forte 
1433*fcf3ce44SJohn Forte 	return;
1434*fcf3ce44SJohn Forte 
1435*fcf3ce44SJohn Forte } /* emlxs_mb_config_hbq() */
1436*fcf3ce44SJohn Forte 
1437*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
1438*fcf3ce44SJohn Forte 
1439*fcf3ce44SJohn Forte 
1440*fcf3ce44SJohn Forte extern uint32_t
1441*fcf3ce44SJohn Forte emlxs_mb_reg_vpi(emlxs_port_t *port)
1442*fcf3ce44SJohn Forte {
1443*fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1444*fcf3ce44SJohn Forte 	MAILBOXQ *mbq;
1445*fcf3ce44SJohn Forte 	MAILBOX *mb;
1446*fcf3ce44SJohn Forte 
1447*fcf3ce44SJohn Forte 	if (!(hba->flag & FC_NPIV_ENABLED)) {
1448*fcf3ce44SJohn Forte 		return (0);
1449*fcf3ce44SJohn Forte 	}
1450*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
1451*fcf3ce44SJohn Forte 
1452*fcf3ce44SJohn Forte 	/* Can't reg vpi until ClearLA is sent */
1453*fcf3ce44SJohn Forte 	if (hba->state != FC_READY) {
1454*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1455*fcf3ce44SJohn Forte 
1456*fcf3ce44SJohn Forte 		return (1);
1457*fcf3ce44SJohn Forte 	}
1458*fcf3ce44SJohn Forte 	/* Must have port id */
1459*fcf3ce44SJohn Forte 	if (!port->did) {
1460*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1461*fcf3ce44SJohn Forte 
1462*fcf3ce44SJohn Forte 		return (1);
1463*fcf3ce44SJohn Forte 	}
1464*fcf3ce44SJohn Forte 	if (!(mbq = (MAILBOXQ *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
1465*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1466*fcf3ce44SJohn Forte 
1467*fcf3ce44SJohn Forte 		return (1);
1468*fcf3ce44SJohn Forte 	}
1469*fcf3ce44SJohn Forte 	port->flag |= EMLXS_PORT_REGISTERED;
1470*fcf3ce44SJohn Forte 
1471*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1472*fcf3ce44SJohn Forte 
1473*fcf3ce44SJohn Forte 	mb = (MAILBOX *) mbq->mbox;
1474*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1475*fcf3ce44SJohn Forte 	mb->un.varRegVpi.vpi = port->vpi;
1476*fcf3ce44SJohn Forte 	mb->un.varRegVpi.sid = port->did;
1477*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_REG_VPI;
1478*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1479*fcf3ce44SJohn Forte 
1480*fcf3ce44SJohn Forte 	if (emlxs_mb_issue_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
1481*fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
1482*fcf3ce44SJohn Forte 	}
1483*fcf3ce44SJohn Forte 	return (0);
1484*fcf3ce44SJohn Forte 
1485*fcf3ce44SJohn Forte } /* emlxs_mb_reg_vpi() */
1486*fcf3ce44SJohn Forte 
1487*fcf3ce44SJohn Forte 
1488*fcf3ce44SJohn Forte extern uint32_t
1489*fcf3ce44SJohn Forte emlxs_mb_unreg_vpi(emlxs_port_t *port)
1490*fcf3ce44SJohn Forte {
1491*fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1492*fcf3ce44SJohn Forte 	MAILBOXQ *mbq;
1493*fcf3ce44SJohn Forte 	MAILBOX *mb;
1494*fcf3ce44SJohn Forte 
1495*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
1496*fcf3ce44SJohn Forte 
1497*fcf3ce44SJohn Forte 	if (!(port->flag & EMLXS_PORT_REGISTERED)) {
1498*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1499*fcf3ce44SJohn Forte 
1500*fcf3ce44SJohn Forte 		return (0);
1501*fcf3ce44SJohn Forte 	}
1502*fcf3ce44SJohn Forte 	if (!(mbq = (MAILBOXQ *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
1503*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
1504*fcf3ce44SJohn Forte 
1505*fcf3ce44SJohn Forte 		return (1);
1506*fcf3ce44SJohn Forte 	}
1507*fcf3ce44SJohn Forte 	port->flag &= ~EMLXS_PORT_REGISTERED;
1508*fcf3ce44SJohn Forte 
1509*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1510*fcf3ce44SJohn Forte 
1511*fcf3ce44SJohn Forte 	mb = (MAILBOX *) mbq->mbox;
1512*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1513*fcf3ce44SJohn Forte 	mb->un.varUnregVpi.vpi = port->vpi;
1514*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_UNREG_VPI;
1515*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1516*fcf3ce44SJohn Forte 
1517*fcf3ce44SJohn Forte 	if (emlxs_mb_issue_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
1518*fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
1519*fcf3ce44SJohn Forte 	}
1520*fcf3ce44SJohn Forte 	return (0);
1521*fcf3ce44SJohn Forte 
1522*fcf3ce44SJohn Forte } /* emlxs_mb_unreg_vpi() */
1523*fcf3ce44SJohn Forte 
1524*fcf3ce44SJohn Forte 
1525*fcf3ce44SJohn Forte /*
1526*fcf3ce44SJohn Forte  *  emlxs_mb_config_farp  Issue a CONFIG FARP
1527*fcf3ce44SJohn Forte  *                      mailbox command
1528*fcf3ce44SJohn Forte  */
1529*fcf3ce44SJohn Forte extern void
1530*fcf3ce44SJohn Forte emlxs_mb_config_farp(emlxs_hba_t *hba, MAILBOX *mb)
1531*fcf3ce44SJohn Forte {
1532*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1533*fcf3ce44SJohn Forte 
1534*fcf3ce44SJohn Forte 	bcopy((uint8_t *)& hba->wwpn,
1535*fcf3ce44SJohn Forte 	    (uint8_t *)& mb->un.varCfgFarp.portname,
1536*fcf3ce44SJohn Forte 	    sizeof (NAME_TYPE));
1537*fcf3ce44SJohn Forte 
1538*fcf3ce44SJohn Forte 	bcopy((uint8_t *)& hba->wwpn,
1539*fcf3ce44SJohn Forte 	    (uint8_t *)& mb->un.varCfgFarp.nodename,
1540*fcf3ce44SJohn Forte 	    sizeof (NAME_TYPE));
1541*fcf3ce44SJohn Forte 
1542*fcf3ce44SJohn Forte 	mb->un.varCfgFarp.filterEnable = 1;
1543*fcf3ce44SJohn Forte 	mb->un.varCfgFarp.portName = 1;
1544*fcf3ce44SJohn Forte 	mb->un.varCfgFarp.nodeName = 1;
1545*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_CONFIG_FARP;
1546*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1547*fcf3ce44SJohn Forte } /* emlxs_mb_config_farp() */
1548*fcf3ce44SJohn Forte 
1549*fcf3ce44SJohn Forte 
1550*fcf3ce44SJohn Forte /*
1551*fcf3ce44SJohn Forte  *  emlxs_mb_read_nv  Issue a READ CONFIG
1552*fcf3ce44SJohn Forte  *                  mailbox command
1553*fcf3ce44SJohn Forte  */
1554*fcf3ce44SJohn Forte /* ARGSUSED */
1555*fcf3ce44SJohn Forte extern void
1556*fcf3ce44SJohn Forte emlxs_mb_read_config(emlxs_hba_t *hba, MAILBOX *mb)
1557*fcf3ce44SJohn Forte {
1558*fcf3ce44SJohn Forte 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1559*fcf3ce44SJohn Forte 
1560*fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_READ_CONFIG;
1561*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1562*fcf3ce44SJohn Forte 
1563*fcf3ce44SJohn Forte } /* emlxs_mb_read_config() */
1564*fcf3ce44SJohn Forte 
1565*fcf3ce44SJohn Forte 
1566*fcf3ce44SJohn Forte 
1567*fcf3ce44SJohn Forte /*
1568*fcf3ce44SJohn Forte  * NAME:     emlxs_mb_put
1569*fcf3ce44SJohn Forte  *
1570*fcf3ce44SJohn Forte  * FUNCTION: put mailbox cmd onto the mailbox queue.
1571*fcf3ce44SJohn Forte  *
1572*fcf3ce44SJohn Forte  * EXECUTION ENVIRONMENT: process and interrupt level.
1573*fcf3ce44SJohn Forte  *
1574*fcf3ce44SJohn Forte  * NOTES:
1575*fcf3ce44SJohn Forte  *
1576*fcf3ce44SJohn Forte  * CALLED FROM: emlxs_mb_issue_cmd
1577*fcf3ce44SJohn Forte  *
1578*fcf3ce44SJohn Forte  * INPUT: hba           - pointer to the device info area mbp
1579*fcf3ce44SJohn Forte  *                      - pointer to mailbox queue entry of mailbox cmd
1580*fcf3ce44SJohn Forte  *
1581*fcf3ce44SJohn Forte  * RETURNS: NULL - command queued
1582*fcf3ce44SJohn Forte  */
1583*fcf3ce44SJohn Forte extern void
1584*fcf3ce44SJohn Forte emlxs_mb_put(emlxs_hba_t *hba, MAILBOXQ *mbq)
1585*fcf3ce44SJohn Forte {
1586*fcf3ce44SJohn Forte 
1587*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_MBOX_LOCK);
1588*fcf3ce44SJohn Forte 
1589*fcf3ce44SJohn Forte 	if (hba->mbox_queue.q_first) {
1590*fcf3ce44SJohn Forte 
1591*fcf3ce44SJohn Forte 		/*
1592*fcf3ce44SJohn Forte 		 * queue command to end of list
1593*fcf3ce44SJohn Forte 		 */
1594*fcf3ce44SJohn Forte 		((MAILBOXQ *) hba->mbox_queue.q_last)->next = mbq;
1595*fcf3ce44SJohn Forte 		hba->mbox_queue.q_last = (uint8_t *)mbq;
1596*fcf3ce44SJohn Forte 		hba->mbox_queue.q_cnt++;
1597*fcf3ce44SJohn Forte 	} else {
1598*fcf3ce44SJohn Forte 
1599*fcf3ce44SJohn Forte 		/*
1600*fcf3ce44SJohn Forte 		 * add command to empty list
1601*fcf3ce44SJohn Forte 		 */
1602*fcf3ce44SJohn Forte 		hba->mbox_queue.q_first = (uint8_t *)mbq;
1603*fcf3ce44SJohn Forte 		hba->mbox_queue.q_last = (uint8_t *)mbq;
1604*fcf3ce44SJohn Forte 		hba->mbox_queue.q_cnt = 1;
1605*fcf3ce44SJohn Forte 	}
1606*fcf3ce44SJohn Forte 
1607*fcf3ce44SJohn Forte 	mbq->next = NULL;
1608*fcf3ce44SJohn Forte 
1609*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_MBOX_LOCK);
1610*fcf3ce44SJohn Forte } /* emlxs_mb_put() */
1611*fcf3ce44SJohn Forte 
1612*fcf3ce44SJohn Forte 
1613*fcf3ce44SJohn Forte /*
1614*fcf3ce44SJohn Forte  * NAME:     emlxs_mb_get
1615*fcf3ce44SJohn Forte  *
1616*fcf3ce44SJohn Forte  * FUNCTION: get a mailbox command from mailbox command queue
1617*fcf3ce44SJohn Forte  *
1618*fcf3ce44SJohn Forte  * EXECUTION ENVIRONMENT: interrupt level.
1619*fcf3ce44SJohn Forte  *
1620*fcf3ce44SJohn Forte  * NOTES:
1621*fcf3ce44SJohn Forte  *
1622*fcf3ce44SJohn Forte  * CALLED FROM: emlxs_handle_mb_event
1623*fcf3ce44SJohn Forte  *
1624*fcf3ce44SJohn Forte  * INPUT: hba       - pointer to the device info area
1625*fcf3ce44SJohn Forte  *
1626*fcf3ce44SJohn Forte  * RETURNS: NULL - no match found mb pointer - pointer to a mailbox command
1627*fcf3ce44SJohn Forte  */
1628*fcf3ce44SJohn Forte extern MAILBOXQ *
1629*fcf3ce44SJohn Forte emlxs_mb_get(emlxs_hba_t *hba)
1630*fcf3ce44SJohn Forte {
1631*fcf3ce44SJohn Forte 	MAILBOXQ *p_first = NULL;
1632*fcf3ce44SJohn Forte 
1633*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_MBOX_LOCK);
1634*fcf3ce44SJohn Forte 
1635*fcf3ce44SJohn Forte 	if (hba->mbox_queue.q_first) {
1636*fcf3ce44SJohn Forte 		p_first = (MAILBOXQ *) hba->mbox_queue.q_first;
1637*fcf3ce44SJohn Forte 		hba->mbox_queue.q_first = (uint8_t *)p_first->next;
1638*fcf3ce44SJohn Forte 
1639*fcf3ce44SJohn Forte 		if (hba->mbox_queue.q_first == NULL) {
1640*fcf3ce44SJohn Forte 			hba->mbox_queue.q_last = NULL;
1641*fcf3ce44SJohn Forte 			hba->mbox_queue.q_cnt = 0;
1642*fcf3ce44SJohn Forte 		} else {
1643*fcf3ce44SJohn Forte 			hba->mbox_queue.q_cnt--;
1644*fcf3ce44SJohn Forte 		}
1645*fcf3ce44SJohn Forte 
1646*fcf3ce44SJohn Forte 		p_first->next = NULL;
1647*fcf3ce44SJohn Forte 	}
1648*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_MBOX_LOCK);
1649*fcf3ce44SJohn Forte 
1650*fcf3ce44SJohn Forte 	return (p_first);
1651*fcf3ce44SJohn Forte 
1652*fcf3ce44SJohn Forte } /* emlxs_mb_get() */
1653*fcf3ce44SJohn Forte 
1654*fcf3ce44SJohn Forte 
1655*fcf3ce44SJohn Forte 
1656*fcf3ce44SJohn Forte /* EMLXS_PORT_LOCK must be held when calling this */
1657*fcf3ce44SJohn Forte static void
1658*fcf3ce44SJohn Forte emlxs_mb_init(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t flag, uint32_t tmo)
1659*fcf3ce44SJohn Forte {
1660*fcf3ce44SJohn Forte 	MATCHMAP *mp;
1661*fcf3ce44SJohn Forte 
1662*fcf3ce44SJohn Forte 	HBASTATS.MboxIssued++;
1663*fcf3ce44SJohn Forte 	hba->mbox_queue_flag = flag;
1664*fcf3ce44SJohn Forte 
1665*fcf3ce44SJohn Forte 	/* Set the Mailbox timer */
1666*fcf3ce44SJohn Forte 	hba->mbox_timer = hba->timer_tics + tmo;
1667*fcf3ce44SJohn Forte 
1668*fcf3ce44SJohn Forte 	/* Initialize mailbox */
1669*fcf3ce44SJohn Forte 	mbq->flag &= MBQ_INIT_MASK;
1670*fcf3ce44SJohn Forte 	hba->mbox_mbqflag = mbq->flag;
1671*fcf3ce44SJohn Forte 
1672*fcf3ce44SJohn Forte 	mbq->next = 0;
1673*fcf3ce44SJohn Forte 
1674*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_MBOX_LOCK);
1675*fcf3ce44SJohn Forte 	if (flag == MBX_NOWAIT) {
1676*fcf3ce44SJohn Forte 		hba->mbox_mbq = 0;
1677*fcf3ce44SJohn Forte 	} else {
1678*fcf3ce44SJohn Forte 		hba->mbox_mbq = (uint8_t *)mbq;
1679*fcf3ce44SJohn Forte 	}
1680*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_MBOX_LOCK);
1681*fcf3ce44SJohn Forte 
1682*fcf3ce44SJohn Forte 	if (mbq->bp) {
1683*fcf3ce44SJohn Forte 		mp = (MATCHMAP *) mbq->bp;
1684*fcf3ce44SJohn Forte 		emlxs_mpdata_sync(mp->dma_handle, 0, mp->size,
1685*fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORDEV);
1686*fcf3ce44SJohn Forte 
1687*fcf3ce44SJohn Forte 		hba->mbox_bp = mbq->bp;
1688*fcf3ce44SJohn Forte 		mbq->bp = 0;
1689*fcf3ce44SJohn Forte 	}
1690*fcf3ce44SJohn Forte 	if (mbq->sbp) {
1691*fcf3ce44SJohn Forte 		hba->mbox_sbp = mbq->sbp;
1692*fcf3ce44SJohn Forte 		mbq->sbp = 0;
1693*fcf3ce44SJohn Forte 	}
1694*fcf3ce44SJohn Forte 	if (mbq->ubp) {
1695*fcf3ce44SJohn Forte 		hba->mbox_ubp = mbq->ubp;
1696*fcf3ce44SJohn Forte 		mbq->ubp = 0;
1697*fcf3ce44SJohn Forte 	}
1698*fcf3ce44SJohn Forte 	if (mbq->iocbq) {
1699*fcf3ce44SJohn Forte 		hba->mbox_iocbq = mbq->iocbq;
1700*fcf3ce44SJohn Forte 		mbq->iocbq = 0;
1701*fcf3ce44SJohn Forte 	}
1702*fcf3ce44SJohn Forte #ifdef MBOX_EXT_SUPPORT
1703*fcf3ce44SJohn Forte 	if (mbq->extbuf && mbq->extsize) {
1704*fcf3ce44SJohn Forte 		hba->mbox_ext = mbq->extbuf;
1705*fcf3ce44SJohn Forte 		hba->mbox_ext_size = mbq->extsize;
1706*fcf3ce44SJohn Forte 	}
1707*fcf3ce44SJohn Forte #endif	/* MBOX_EXT_SUPPORT */
1708*fcf3ce44SJohn Forte 
1709*fcf3ce44SJohn Forte 	return;
1710*fcf3ce44SJohn Forte 
1711*fcf3ce44SJohn Forte } /* emlxs_mb_init() */
1712*fcf3ce44SJohn Forte 
1713*fcf3ce44SJohn Forte 
1714*fcf3ce44SJohn Forte extern void
1715*fcf3ce44SJohn Forte emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus)
1716*fcf3ce44SJohn Forte {
1717*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1718*fcf3ce44SJohn Forte 	MATCHMAP *mbox_bp;
1719*fcf3ce44SJohn Forte 	emlxs_buf_t *mbox_sbp;
1720*fcf3ce44SJohn Forte 	fc_unsol_buf_t *mbox_ubp;
1721*fcf3ce44SJohn Forte 	IOCBQ *mbox_iocbq;
1722*fcf3ce44SJohn Forte 	MAILBOXQ *mbox_mbq;
1723*fcf3ce44SJohn Forte 	MAILBOX *mbox;
1724*fcf3ce44SJohn Forte 	uint32_t mbox_queue_flag;
1725*fcf3ce44SJohn Forte 	emlxs_ub_priv_t *ub_priv;
1726*fcf3ce44SJohn Forte 
1727*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
1728*fcf3ce44SJohn Forte 
1729*fcf3ce44SJohn Forte 	if (hba->mbox_queue_flag) {
1730*fcf3ce44SJohn Forte 		HBASTATS.MboxCompleted++;
1731*fcf3ce44SJohn Forte 
1732*fcf3ce44SJohn Forte 		if (mbxStatus != MBX_SUCCESS) {
1733*fcf3ce44SJohn Forte 			HBASTATS.MboxError++;
1734*fcf3ce44SJohn Forte 		} else {
1735*fcf3ce44SJohn Forte 			HBASTATS.MboxGood++;
1736*fcf3ce44SJohn Forte 		}
1737*fcf3ce44SJohn Forte 	}
1738*fcf3ce44SJohn Forte 	mbox_bp = (MATCHMAP *) hba->mbox_bp;
1739*fcf3ce44SJohn Forte 	mbox_sbp = (emlxs_buf_t *)hba->mbox_sbp;
1740*fcf3ce44SJohn Forte 	mbox_ubp = (fc_unsol_buf_t *)hba->mbox_ubp;
1741*fcf3ce44SJohn Forte 	mbox_iocbq = (IOCBQ *) hba->mbox_iocbq;
1742*fcf3ce44SJohn Forte 	mbox_mbq = (MAILBOXQ *) hba->mbox_mbq;
1743*fcf3ce44SJohn Forte 	mbox_queue_flag = hba->mbox_queue_flag;
1744*fcf3ce44SJohn Forte 
1745*fcf3ce44SJohn Forte #ifdef MBOX_EXT_SUPPORT
1746*fcf3ce44SJohn Forte 	hba->mbox_ext = 0;
1747*fcf3ce44SJohn Forte 	hba->mbox_ext_size = 0;
1748*fcf3ce44SJohn Forte #endif	/* MBOX_EXT_SUPPORT */
1749*fcf3ce44SJohn Forte 
1750*fcf3ce44SJohn Forte 	hba->mbox_bp = 0;
1751*fcf3ce44SJohn Forte 	hba->mbox_sbp = 0;
1752*fcf3ce44SJohn Forte 	hba->mbox_ubp = 0;
1753*fcf3ce44SJohn Forte 	hba->mbox_iocbq = 0;
1754*fcf3ce44SJohn Forte 	hba->mbox_mbqflag = 0;
1755*fcf3ce44SJohn Forte 	hba->mbox_mbq = 0;
1756*fcf3ce44SJohn Forte 	hba->mbox_timer = 0;
1757*fcf3ce44SJohn Forte 	hba->mbox_queue_flag = 0;
1758*fcf3ce44SJohn Forte 
1759*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1760*fcf3ce44SJohn Forte 
1761*fcf3ce44SJohn Forte 	if (mbox_mbq) {
1762*fcf3ce44SJohn Forte 		if (mb) {
1763*fcf3ce44SJohn Forte 			/*
1764*fcf3ce44SJohn Forte 			 * Copy the local mailbox provided back into the
1765*fcf3ce44SJohn Forte 			 * original mailbox
1766*fcf3ce44SJohn Forte 			 */
1767*fcf3ce44SJohn Forte 			bcopy((uint32_t *)mb, (uint32_t *)mbox_mbq,
1768*fcf3ce44SJohn Forte 			    MAILBOX_CMD_BSIZE);
1769*fcf3ce44SJohn Forte 		}
1770*fcf3ce44SJohn Forte 		mbox = (MAILBOX *) mbox_mbq;
1771*fcf3ce44SJohn Forte 		mbox->mbxStatus = mbxStatus;
1772*fcf3ce44SJohn Forte 
1773*fcf3ce44SJohn Forte 		/* Mark mailbox complete */
1774*fcf3ce44SJohn Forte 		mbox_mbq->flag |= MBQ_COMPLETED;
1775*fcf3ce44SJohn Forte 
1776*fcf3ce44SJohn Forte 		/* Wake up the sleeping thread */
1777*fcf3ce44SJohn Forte 		if (mbox_queue_flag == MBX_SLEEP) {
1778*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_MBOX_LOCK);
1779*fcf3ce44SJohn Forte 			cv_broadcast(&EMLXS_MBOX_CV);
1780*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_MBOX_LOCK);
1781*fcf3ce44SJohn Forte 		}
1782*fcf3ce44SJohn Forte 	}
1783*fcf3ce44SJohn Forte 	/* Check for deferred MBUF cleanup */
1784*fcf3ce44SJohn Forte 	if (mbox_bp && (mbox_queue_flag == MBX_NOWAIT)) {
1785*fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mbox_bp);
1786*fcf3ce44SJohn Forte 	}
1787*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
1788*fcf3ce44SJohn Forte 	if (mbox_sbp && mbox_sbp->fct_cmd) {
1789*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1790*fcf3ce44SJohn Forte 		    "FCT mailbox: %s: status=%x",
1791*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
1792*fcf3ce44SJohn Forte 		    (uint32_t)mb->mbxStatus);
1793*fcf3ce44SJohn Forte 	}
1794*fcf3ce44SJohn Forte #endif	/* SFCT_SUPPORT */
1795*fcf3ce44SJohn Forte 
1796*fcf3ce44SJohn Forte 	/* Check for deferred pkt completion */
1797*fcf3ce44SJohn Forte 	if (mbox_sbp) {
1798*fcf3ce44SJohn Forte 		if (mbxStatus != MBX_SUCCESS) {
1799*fcf3ce44SJohn Forte 			/* Set error status */
1800*fcf3ce44SJohn Forte 			mbox_sbp->pkt_flags &= ~PACKET_STATE_VALID;
1801*fcf3ce44SJohn Forte 			emlxs_set_pkt_state(mbox_sbp, IOSTAT_LOCAL_REJECT,
1802*fcf3ce44SJohn Forte 			    IOERR_NO_RESOURCES, 1);
1803*fcf3ce44SJohn Forte 		}
1804*fcf3ce44SJohn Forte 		emlxs_pkt_complete(mbox_sbp, -1, 0, 1);
1805*fcf3ce44SJohn Forte 	}
1806*fcf3ce44SJohn Forte 	/* Check for deferred ub completion */
1807*fcf3ce44SJohn Forte 	if (mbox_ubp) {
1808*fcf3ce44SJohn Forte 		ub_priv = mbox_ubp->ub_fca_private;
1809*fcf3ce44SJohn Forte 		port = ub_priv->port;
1810*fcf3ce44SJohn Forte 
1811*fcf3ce44SJohn Forte 		emlxs_ub_callback(port, mbox_ubp);
1812*fcf3ce44SJohn Forte 	}
1813*fcf3ce44SJohn Forte 	/* Check for deferred iocb tx */
1814*fcf3ce44SJohn Forte 	if (mbox_iocbq) {
1815*fcf3ce44SJohn Forte 		emlxs_issue_iocb_cmd(hba, mbox_iocbq->ring, mbox_iocbq);
1816*fcf3ce44SJohn Forte 	}
1817*fcf3ce44SJohn Forte 	return;
1818*fcf3ce44SJohn Forte 
1819*fcf3ce44SJohn Forte } /* emlxs_mb_fini() */
1820*fcf3ce44SJohn Forte 
1821*fcf3ce44SJohn Forte 
1822*fcf3ce44SJohn Forte 
1823*fcf3ce44SJohn Forte /* This should only be called with active MBX_NOWAIT mailboxes */
1824*fcf3ce44SJohn Forte static void
1825*fcf3ce44SJohn Forte emlxs_mb_retry(emlxs_hba_t *hba, MAILBOX *mb)
1826*fcf3ce44SJohn Forte {
1827*fcf3ce44SJohn Forte 	MAILBOXQ *mbq;
1828*fcf3ce44SJohn Forte 
1829*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
1830*fcf3ce44SJohn Forte 
1831*fcf3ce44SJohn Forte 	HBASTATS.MboxCompleted++;
1832*fcf3ce44SJohn Forte 
1833*fcf3ce44SJohn Forte 	if (mb->mbxStatus != 0) {
1834*fcf3ce44SJohn Forte 		HBASTATS.MboxError++;
1835*fcf3ce44SJohn Forte 	} else {
1836*fcf3ce44SJohn Forte 		HBASTATS.MboxGood++;
1837*fcf3ce44SJohn Forte 	}
1838*fcf3ce44SJohn Forte 
1839*fcf3ce44SJohn Forte 	mbq = (MAILBOXQ *) mb;
1840*fcf3ce44SJohn Forte 	mbq->bp = (uint8_t *)hba->mbox_bp;
1841*fcf3ce44SJohn Forte 	mbq->sbp = (uint8_t *)hba->mbox_sbp;
1842*fcf3ce44SJohn Forte 	mbq->ubp = (uint8_t *)hba->mbox_ubp;
1843*fcf3ce44SJohn Forte 	mbq->iocbq = (uint8_t *)hba->mbox_iocbq;
1844*fcf3ce44SJohn Forte 
1845*fcf3ce44SJohn Forte 	hba->mbox_bp = 0;
1846*fcf3ce44SJohn Forte 	hba->mbox_sbp = 0;
1847*fcf3ce44SJohn Forte 	hba->mbox_ubp = 0;
1848*fcf3ce44SJohn Forte 	hba->mbox_iocbq = 0;
1849*fcf3ce44SJohn Forte 	hba->mbox_mbq = 0;
1850*fcf3ce44SJohn Forte 	hba->mbox_mbqflag = 0;
1851*fcf3ce44SJohn Forte 	hba->mbox_queue_flag = 0;
1852*fcf3ce44SJohn Forte 
1853*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
1854*fcf3ce44SJohn Forte 
1855*fcf3ce44SJohn Forte 	return;
1856*fcf3ce44SJohn Forte 
1857*fcf3ce44SJohn Forte } /* emlxs_mb_retry() */
1858*fcf3ce44SJohn Forte 
1859*fcf3ce44SJohn Forte 
1860*fcf3ce44SJohn Forte 
1861*fcf3ce44SJohn Forte /*
1862*fcf3ce44SJohn Forte  *  emlxs_handle_mb_event
1863*fcf3ce44SJohn Forte  *
1864*fcf3ce44SJohn Forte  *  Description: Process a Mailbox Attention.
1865*fcf3ce44SJohn Forte  *  Called from host_interrupt to process MBATT
1866*fcf3ce44SJohn Forte  *
1867*fcf3ce44SJohn Forte  *    Returns:
1868*fcf3ce44SJohn Forte  *
1869*fcf3ce44SJohn Forte  */
1870*fcf3ce44SJohn Forte extern uint32_t
1871*fcf3ce44SJohn Forte emlxs_handle_mb_event(emlxs_hba_t *hba)
1872*fcf3ce44SJohn Forte {
1873*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1874*fcf3ce44SJohn Forte 	MAILBOX *mb;
1875*fcf3ce44SJohn Forte 	MAILBOX *swpmb;
1876*fcf3ce44SJohn Forte 	MAILBOX *mbox;
1877*fcf3ce44SJohn Forte 	MAILBOXQ *mbq;
1878*fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
1879*fcf3ce44SJohn Forte 	uint32_t control;
1880*fcf3ce44SJohn Forte 	volatile uint32_t word0;
1881*fcf3ce44SJohn Forte 	MATCHMAP *mbox_bp;
1882*fcf3ce44SJohn Forte 	uint32_t la_enable;
1883*fcf3ce44SJohn Forte 	off_t offset;
1884*fcf3ce44SJohn Forte 	uint32_t i;
1885*fcf3ce44SJohn Forte 	MAILBOXQ mailbox;
1886*fcf3ce44SJohn Forte 
1887*fcf3ce44SJohn Forte 	cfg = &CFG;
1888*fcf3ce44SJohn Forte 	swpmb = (MAILBOX *) & word0;
1889*fcf3ce44SJohn Forte 	mb = (MAILBOX *) & mailbox;
1890*fcf3ce44SJohn Forte 
1891*fcf3ce44SJohn Forte 	switch (hba->mbox_queue_flag) {
1892*fcf3ce44SJohn Forte 	case 0:
1893*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
1894*fcf3ce44SJohn Forte 		    "No mailbox active.");
1895*fcf3ce44SJohn Forte 		return (0);
1896*fcf3ce44SJohn Forte 
1897*fcf3ce44SJohn Forte 	case MBX_POLL:
1898*fcf3ce44SJohn Forte 
1899*fcf3ce44SJohn Forte 		/*
1900*fcf3ce44SJohn Forte 		 * Mark mailbox complete, this should wake up any polling
1901*fcf3ce44SJohn Forte 		 * threads
1902*fcf3ce44SJohn Forte 		 */
1903*fcf3ce44SJohn Forte 		/*
1904*fcf3ce44SJohn Forte 		 * This can happen if interrupts are enabled while a polled
1905*fcf3ce44SJohn Forte 		 * mailbox command is outstanding
1906*fcf3ce44SJohn Forte 		 */
1907*fcf3ce44SJohn Forte 		/*
1908*fcf3ce44SJohn Forte 		 * If we don't set MBQ_COMPLETED here, the polling thread may
1909*fcf3ce44SJohn Forte 		 * wait until timeout error occurs
1910*fcf3ce44SJohn Forte 		 */
1911*fcf3ce44SJohn Forte 
1912*fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_MBOX_LOCK);
1913*fcf3ce44SJohn Forte 		mbq = (MAILBOXQ *) hba->mbox_mbq;
1914*fcf3ce44SJohn Forte 		if (mbq) {
1915*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
1916*fcf3ce44SJohn Forte 			    "Mailbox event. Completing Polled command.");
1917*fcf3ce44SJohn Forte 			mbq->flag |= MBQ_COMPLETED;
1918*fcf3ce44SJohn Forte 		}
1919*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_MBOX_LOCK);
1920*fcf3ce44SJohn Forte 
1921*fcf3ce44SJohn Forte 		return (0);
1922*fcf3ce44SJohn Forte 
1923*fcf3ce44SJohn Forte 	case MBX_SLEEP:
1924*fcf3ce44SJohn Forte 	case MBX_NOWAIT:
1925*fcf3ce44SJohn Forte 		break;
1926*fcf3ce44SJohn Forte 
1927*fcf3ce44SJohn Forte 	default:
1928*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
1929*fcf3ce44SJohn Forte 		    "Invalid Mailbox flag (%x).");
1930*fcf3ce44SJohn Forte 		return (0);
1931*fcf3ce44SJohn Forte 	}
1932*fcf3ce44SJohn Forte 
1933*fcf3ce44SJohn Forte 	/* Get first word of mailbox */
1934*fcf3ce44SJohn Forte 	if (hba->flag & FC_SLIM2_MODE) {
1935*fcf3ce44SJohn Forte 		mbox = FC_SLIM2_MAILBOX(hba);
1936*fcf3ce44SJohn Forte 		offset = (off_t)((uint64_t)(unsigned long)mbox -
1937*fcf3ce44SJohn Forte 		    (uint64_t)(unsigned long)hba->slim2.virt);
1938*fcf3ce44SJohn Forte 
1939*fcf3ce44SJohn Forte 		emlxs_mpdata_sync(hba->slim2.dma_handle, offset,
1940*fcf3ce44SJohn Forte 		    sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
1941*fcf3ce44SJohn Forte 		word0 = *((volatile uint32_t *) mbox);
1942*fcf3ce44SJohn Forte 		word0 = PCIMEM_LONG(word0);
1943*fcf3ce44SJohn Forte 	} else {
1944*fcf3ce44SJohn Forte 		mbox = FC_SLIM1_MAILBOX(hba);
1945*fcf3ce44SJohn Forte 		word0 = READ_SLIM_ADDR(hba, ((volatile uint32_t *) mbox));
1946*fcf3ce44SJohn Forte 	}
1947*fcf3ce44SJohn Forte 
1948*fcf3ce44SJohn Forte 	i = 0;
1949*fcf3ce44SJohn Forte 	while (swpmb->mbxOwner == OWN_CHIP) {
1950*fcf3ce44SJohn Forte 		if (i++ > 10000) {
1951*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
1952*fcf3ce44SJohn Forte 			    "OWN_CHIP: %s: status=%x",
1953*fcf3ce44SJohn Forte 			    emlxs_mb_cmd_xlate(swpmb->mbxCommand),
1954*fcf3ce44SJohn Forte 			    swpmb->mbxStatus);
1955*fcf3ce44SJohn Forte 
1956*fcf3ce44SJohn Forte 			return (1);
1957*fcf3ce44SJohn Forte 		}
1958*fcf3ce44SJohn Forte 		/* Get first word of mailbox */
1959*fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1960*fcf3ce44SJohn Forte 			emlxs_mpdata_sync(hba->slim2.dma_handle, offset,
1961*fcf3ce44SJohn Forte 			    sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
1962*fcf3ce44SJohn Forte 			word0 = *((volatile uint32_t *) mbox);
1963*fcf3ce44SJohn Forte 			word0 = PCIMEM_LONG(word0);
1964*fcf3ce44SJohn Forte 		} else {
1965*fcf3ce44SJohn Forte 			word0 = READ_SLIM_ADDR(hba,
1966*fcf3ce44SJohn Forte 			    ((volatile uint32_t *) mbox));
1967*fcf3ce44SJohn Forte 		}
1968*fcf3ce44SJohn Forte 	}
1969*fcf3ce44SJohn Forte 
1970*fcf3ce44SJohn Forte 	/* Now that we are the owner, DMA Sync entire mailbox if needed */
1971*fcf3ce44SJohn Forte 	if (hba->flag & FC_SLIM2_MODE) {
1972*fcf3ce44SJohn Forte 		emlxs_mpdata_sync(hba->slim2.dma_handle, offset,
1973*fcf3ce44SJohn Forte 		    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
1974*fcf3ce44SJohn Forte 		emlxs_pcimem_bcopy((uint32_t *)mbox, (uint32_t *)mb,
1975*fcf3ce44SJohn Forte 		    MAILBOX_CMD_BSIZE);
1976*fcf3ce44SJohn Forte 	} else {
1977*fcf3ce44SJohn Forte 		READ_SLIM_COPY(hba, (uint32_t *)mb, (uint32_t *)mbox,
1978*fcf3ce44SJohn Forte 		    MAILBOX_CMD_WSIZE);
1979*fcf3ce44SJohn Forte 	}
1980*fcf3ce44SJohn Forte 
1981*fcf3ce44SJohn Forte #ifdef MBOX_EXT_SUPPORT
1982*fcf3ce44SJohn Forte 	if (hba->mbox_ext) {
1983*fcf3ce44SJohn Forte 		uint32_t *mbox_ext = (uint32_t *)((uint8_t *)mbox +
1984*fcf3ce44SJohn Forte 		    MBOX_EXTENSION_OFFSET);
1985*fcf3ce44SJohn Forte 		off_t offset_ext = offset + MBOX_EXTENSION_OFFSET;
1986*fcf3ce44SJohn Forte 
1987*fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
1988*fcf3ce44SJohn Forte 			emlxs_mpdata_sync(hba->slim2.dma_handle, offset_ext,
1989*fcf3ce44SJohn Forte 			    hba->mbox_ext_size, DDI_DMA_SYNC_FORKERNEL);
1990*fcf3ce44SJohn Forte 			emlxs_pcimem_bcopy(mbox_ext, (uint32_t *)hba->mbox_ext,
1991*fcf3ce44SJohn Forte 			    hba->mbox_ext_size);
1992*fcf3ce44SJohn Forte 		} else {
1993*fcf3ce44SJohn Forte 			READ_SLIM_COPY(hba, (uint32_t *)hba->mbox_ext, mbox_ext,
1994*fcf3ce44SJohn Forte 			    (hba->mbox_ext_size / 4));
1995*fcf3ce44SJohn Forte 		}
1996*fcf3ce44SJohn Forte 	}
1997*fcf3ce44SJohn Forte #endif	/* MBOX_EXT_SUPPORT */
1998*fcf3ce44SJohn Forte 
1999*fcf3ce44SJohn Forte 	/* Now sync the memory buffer if one was used */
2000*fcf3ce44SJohn Forte 	if (hba->mbox_bp) {
2001*fcf3ce44SJohn Forte 		mbox_bp = (MATCHMAP *) hba->mbox_bp;
2002*fcf3ce44SJohn Forte 		emlxs_mpdata_sync(mbox_bp->dma_handle, 0, mbox_bp->size,
2003*fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORKERNEL);
2004*fcf3ce44SJohn Forte 	}
2005*fcf3ce44SJohn Forte 	/* Mailbox has been completely received at this point */
2006*fcf3ce44SJohn Forte 
2007*fcf3ce44SJohn Forte 	if (mb->mbxCommand == MBX_HEARTBEAT) {
2008*fcf3ce44SJohn Forte 		hba->heartbeat_active = 0;
2009*fcf3ce44SJohn Forte 		goto done;
2010*fcf3ce44SJohn Forte 	}
2011*fcf3ce44SJohn Forte 	if (hba->mbox_queue_flag == MBX_SLEEP) {
2012*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2013*fcf3ce44SJohn Forte 		    "Received.  %s: status=%x Sleep.",
2014*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(swpmb->mbxCommand), swpmb->mbxStatus);
2015*fcf3ce44SJohn Forte 	} else {
2016*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2017*fcf3ce44SJohn Forte 		    "Completed. %s: status=%x",
2018*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(swpmb->mbxCommand), swpmb->mbxStatus);
2019*fcf3ce44SJohn Forte 	}
2020*fcf3ce44SJohn Forte 
2021*fcf3ce44SJohn Forte 	/* Filter out passthru mailbox */
2022*fcf3ce44SJohn Forte 	if (hba->mbox_mbqflag & MBQ_PASSTHRU) {
2023*fcf3ce44SJohn Forte 		goto done;
2024*fcf3ce44SJohn Forte 	}
2025*fcf3ce44SJohn Forte 	/* If succesful, process the result */
2026*fcf3ce44SJohn Forte 	if (mb->mbxStatus == 0) {
2027*fcf3ce44SJohn Forte 		(void) emlxs_mb_handle_cmd(hba, mb);
2028*fcf3ce44SJohn Forte 		goto done;
2029*fcf3ce44SJohn Forte 	}
2030*fcf3ce44SJohn Forte 	/* ERROR RETURNED */
2031*fcf3ce44SJohn Forte 
2032*fcf3ce44SJohn Forte 	/* Check for no resources */
2033*fcf3ce44SJohn Forte 	if ((mb->mbxStatus == MBXERR_NO_RESOURCES) &&
2034*fcf3ce44SJohn Forte 	    (hba->mbox_queue_flag == MBX_NOWAIT)) {
2035*fcf3ce44SJohn Forte 		/* Retry only MBX_NOWAIT requests */
2036*fcf3ce44SJohn Forte 
2037*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
2038*fcf3ce44SJohn Forte 		    "Retrying.  %s: status=%x",
2039*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
2040*fcf3ce44SJohn Forte 		    (uint32_t)mb->mbxStatus);
2041*fcf3ce44SJohn Forte 
2042*fcf3ce44SJohn Forte 		if ((mbox = (MAILBOX *) emlxs_mem_get(hba, MEM_MBOX))) {
2043*fcf3ce44SJohn Forte 			bcopy((uint8_t *)mb, (uint8_t *)mbox,
2044*fcf3ce44SJohn Forte 			    MAILBOX_CMD_BSIZE);
2045*fcf3ce44SJohn Forte 
2046*fcf3ce44SJohn Forte 			switch (mbox->mbxCommand) {
2047*fcf3ce44SJohn Forte 			case MBX_READ_SPARM:
2048*fcf3ce44SJohn Forte 				control = mbox->un.varRdSparm.un.sp.bdeSize;
2049*fcf3ce44SJohn Forte 				if (control == 0) {
2050*fcf3ce44SJohn Forte 					(void) emlxs_mb_read_sparam(hba, mbox);
2051*fcf3ce44SJohn Forte 				}
2052*fcf3ce44SJohn Forte 				break;
2053*fcf3ce44SJohn Forte 
2054*fcf3ce44SJohn Forte 			case MBX_READ_SPARM64:
2055*fcf3ce44SJohn Forte 				control = mbox->un.varRdSparm.un.sp64.tus.f.
2056*fcf3ce44SJohn Forte 				    bdeSize;
2057*fcf3ce44SJohn Forte 				if (control == 0) {
2058*fcf3ce44SJohn Forte 					(void) emlxs_mb_read_sparam(hba, mbox);
2059*fcf3ce44SJohn Forte 				}
2060*fcf3ce44SJohn Forte 				break;
2061*fcf3ce44SJohn Forte 
2062*fcf3ce44SJohn Forte 			case MBX_REG_LOGIN:
2063*fcf3ce44SJohn Forte 				control = mbox->un.varRegLogin.un.sp.bdeSize;
2064*fcf3ce44SJohn Forte 				if (control == 0) {
2065*fcf3ce44SJohn Forte 					goto done;
2066*fcf3ce44SJohn Forte 				}
2067*fcf3ce44SJohn Forte 				break;
2068*fcf3ce44SJohn Forte 
2069*fcf3ce44SJohn Forte 			case MBX_REG_LOGIN64:
2070*fcf3ce44SJohn Forte 				control = mbox->un.varRegLogin.un.sp64.tus.f.
2071*fcf3ce44SJohn Forte 				    bdeSize;
2072*fcf3ce44SJohn Forte 				if (control == 0) {
2073*fcf3ce44SJohn Forte 					goto done;
2074*fcf3ce44SJohn Forte 				}
2075*fcf3ce44SJohn Forte 				break;
2076*fcf3ce44SJohn Forte 
2077*fcf3ce44SJohn Forte 			case MBX_READ_LA:
2078*fcf3ce44SJohn Forte 				control = mbox->un.varReadLA.un.lilpBde.bdeSize;
2079*fcf3ce44SJohn Forte 				if (control == 0) {
2080*fcf3ce44SJohn Forte 					(void) emlxs_mb_read_la(hba, mbox);
2081*fcf3ce44SJohn Forte 				}
2082*fcf3ce44SJohn Forte 				break;
2083*fcf3ce44SJohn Forte 
2084*fcf3ce44SJohn Forte 			case MBX_READ_LA64:
2085*fcf3ce44SJohn Forte 				control = mbox->un.varReadLA.un.lilpBde64.tus.f.
2086*fcf3ce44SJohn Forte 				    bdeSize;
2087*fcf3ce44SJohn Forte 				if (control == 0) {
2088*fcf3ce44SJohn Forte 					(void) emlxs_mb_read_la(hba, mbox);
2089*fcf3ce44SJohn Forte 				}
2090*fcf3ce44SJohn Forte 				break;
2091*fcf3ce44SJohn Forte 			}
2092*fcf3ce44SJohn Forte 
2093*fcf3ce44SJohn Forte 			mbox->mbxOwner = OWN_HOST;
2094*fcf3ce44SJohn Forte 			mbox->mbxStatus = 0;
2095*fcf3ce44SJohn Forte 
2096*fcf3ce44SJohn Forte 			/* Refresh the mailbox area */
2097*fcf3ce44SJohn Forte 			emlxs_mb_retry(hba, mbox);
2098*fcf3ce44SJohn Forte 
2099*fcf3ce44SJohn Forte 			if (emlxs_mb_issue_cmd(hba, mbox, MBX_NOWAIT, 0) !=
2100*fcf3ce44SJohn Forte 			    MBX_BUSY) {
2101*fcf3ce44SJohn Forte 				(void) emlxs_mem_put(hba, MEM_MBOX,
2102*fcf3ce44SJohn Forte 				    (uint8_t *)mbox);
2103*fcf3ce44SJohn Forte 			}
2104*fcf3ce44SJohn Forte 			return (0);
2105*fcf3ce44SJohn Forte 		}
2106*fcf3ce44SJohn Forte 	}
2107*fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
2108*fcf3ce44SJohn Forte 	    "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
2109*fcf3ce44SJohn Forte 	    (uint32_t)mb->mbxStatus);
2110*fcf3ce44SJohn Forte 
2111*fcf3ce44SJohn Forte 	/*
2112*fcf3ce44SJohn Forte 	 * ERROR: process mailbox command error
2113*fcf3ce44SJohn Forte 	 */
2114*fcf3ce44SJohn Forte 	switch (mb->mbxCommand) {
2115*fcf3ce44SJohn Forte 	case MBX_REG_LOGIN:
2116*fcf3ce44SJohn Forte 	case MBX_REG_LOGIN64:
2117*fcf3ce44SJohn Forte 
2118*fcf3ce44SJohn Forte 		if (mb->mbxStatus == MBXERR_RPI_FULL) {
2119*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
2120*fcf3ce44SJohn Forte 			port = &VPORT(mb->un.varRegLogin.vpi);
2121*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
2122*fcf3ce44SJohn Forte 
2123*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
2124*fcf3ce44SJohn Forte 			    "Limit reached. count=%d", port->node_count);
2125*fcf3ce44SJohn Forte 		}
2126*fcf3ce44SJohn Forte 		break;
2127*fcf3ce44SJohn Forte 
2128*fcf3ce44SJohn Forte 	case MBX_READ_LA:
2129*fcf3ce44SJohn Forte 	case MBX_READ_LA64:
2130*fcf3ce44SJohn Forte 
2131*fcf3ce44SJohn Forte 		/* Enable Link Attention interrupts */
2132*fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
2133*fcf3ce44SJohn Forte 
2134*fcf3ce44SJohn Forte 		if (!(hba->hc_copy & HC_LAINT_ENA)) {
2135*fcf3ce44SJohn Forte 			/*
2136*fcf3ce44SJohn Forte 			 * hba->hc_copy  = READ_CSR_REG(hba, FC_HC_REG(hba,
2137*fcf3ce44SJohn Forte 			 * hba->csr_addr));
2138*fcf3ce44SJohn Forte 			 */
2139*fcf3ce44SJohn Forte 			hba->hc_copy |= HC_LAINT_ENA;
2140*fcf3ce44SJohn Forte 			WRITE_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr),
2141*fcf3ce44SJohn Forte 			    hba->hc_copy);
2142*fcf3ce44SJohn Forte 		}
2143*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
2144*fcf3ce44SJohn Forte 
2145*fcf3ce44SJohn Forte 		break;
2146*fcf3ce44SJohn Forte 
2147*fcf3ce44SJohn Forte 
2148*fcf3ce44SJohn Forte 	case MBX_CLEAR_LA:
2149*fcf3ce44SJohn Forte 
2150*fcf3ce44SJohn Forte 		la_enable = 1;
2151*fcf3ce44SJohn Forte 
2152*fcf3ce44SJohn Forte 		if (mb->mbxStatus == 0x1601) {
2153*fcf3ce44SJohn Forte 			/*
2154*fcf3ce44SJohn Forte 			 * Get a buffer which will be used for mailbox
2155*fcf3ce44SJohn Forte 			 * commands
2156*fcf3ce44SJohn Forte 			 */
2157*fcf3ce44SJohn Forte 			if ((mbox = (MAILBOX *) emlxs_mem_get(hba, MEM_MBOX |
2158*fcf3ce44SJohn Forte 			    MEM_PRI))) {
2159*fcf3ce44SJohn Forte 				/* Get link attention message */
2160*fcf3ce44SJohn Forte 				if (emlxs_mb_read_la(hba, mbox) == 0) {
2161*fcf3ce44SJohn Forte 					if (emlxs_mb_issue_cmd(hba, mbox,
2162*fcf3ce44SJohn Forte 					    MBX_NOWAIT, 0) != MBX_BUSY) {
2163*fcf3ce44SJohn Forte 						(void) emlxs_mem_put(hba,
2164*fcf3ce44SJohn Forte 						    MEM_MBOX, (uint8_t *)mbox);
2165*fcf3ce44SJohn Forte 					}
2166*fcf3ce44SJohn Forte 					la_enable = 0;
2167*fcf3ce44SJohn Forte 				} else {
2168*fcf3ce44SJohn Forte 					(void) emlxs_mem_put(hba, MEM_MBOX,
2169*fcf3ce44SJohn Forte 					    (uint8_t *)mbox);
2170*fcf3ce44SJohn Forte 				}
2171*fcf3ce44SJohn Forte 			}
2172*fcf3ce44SJohn Forte 		}
2173*fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
2174*fcf3ce44SJohn Forte 		if (la_enable) {
2175*fcf3ce44SJohn Forte 			if (!(hba->hc_copy & HC_LAINT_ENA)) {
2176*fcf3ce44SJohn Forte 				/* Enable Link Attention interrupts */
2177*fcf3ce44SJohn Forte 				/*
2178*fcf3ce44SJohn Forte 				 * hba->hc_copy  = READ_CSR_REG(hba,
2179*fcf3ce44SJohn Forte 				 * FC_HC_REG(hba, hba->csr_addr));
2180*fcf3ce44SJohn Forte 				 */
2181*fcf3ce44SJohn Forte 				hba->hc_copy |= HC_LAINT_ENA;
2182*fcf3ce44SJohn Forte 				WRITE_CSR_REG(hba,
2183*fcf3ce44SJohn Forte 				    FC_HC_REG(hba, hba->csr_addr),
2184*fcf3ce44SJohn Forte 				    hba->hc_copy);
2185*fcf3ce44SJohn Forte 			}
2186*fcf3ce44SJohn Forte 		} else {
2187*fcf3ce44SJohn Forte 			if (hba->hc_copy & HC_LAINT_ENA) {
2188*fcf3ce44SJohn Forte 				/* Disable Link Attention interrupts */
2189*fcf3ce44SJohn Forte 				/*
2190*fcf3ce44SJohn Forte 				 * hba->hc_copy  = READ_CSR_REG(hba,
2191*fcf3ce44SJohn Forte 				 * FC_HC_REG(hba, hba->csr_addr));
2192*fcf3ce44SJohn Forte 				 */
2193*fcf3ce44SJohn Forte 				hba->hc_copy &= ~HC_LAINT_ENA;
2194*fcf3ce44SJohn Forte 				WRITE_CSR_REG(hba,
2195*fcf3ce44SJohn Forte 				    FC_HC_REG(hba, hba->csr_addr),
2196*fcf3ce44SJohn Forte 				    hba->hc_copy);
2197*fcf3ce44SJohn Forte 			}
2198*fcf3ce44SJohn Forte 		}
2199*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
2200*fcf3ce44SJohn Forte 
2201*fcf3ce44SJohn Forte 		break;
2202*fcf3ce44SJohn Forte 
2203*fcf3ce44SJohn Forte 	case MBX_INIT_LINK:
2204*fcf3ce44SJohn Forte 		if ((hba->flag & FC_SLIM2_MODE) &&
2205*fcf3ce44SJohn Forte 		    (hba->mbox_queue_flag == MBX_NOWAIT)) {
2206*fcf3ce44SJohn Forte 			/* Retry only MBX_NOWAIT requests */
2207*fcf3ce44SJohn Forte 
2208*fcf3ce44SJohn Forte 			if ((cfg[CFG_LINK_SPEED].current > 0) &&
2209*fcf3ce44SJohn Forte 			    ((mb->mbxStatus == 0x0011) ||
2210*fcf3ce44SJohn Forte 			    (mb->mbxStatus == 0x0500))) {
2211*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
2212*fcf3ce44SJohn Forte 				    "Retrying.  %s: status=%x. Auto-speed set.",
2213*fcf3ce44SJohn Forte 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
2214*fcf3ce44SJohn Forte 				    (uint32_t)mb->mbxStatus);
2215*fcf3ce44SJohn Forte 
2216*fcf3ce44SJohn Forte 				if ((mbox = (MAILBOX *) emlxs_mem_get(hba,
2217*fcf3ce44SJohn Forte 				    MEM_MBOX))) {
2218*fcf3ce44SJohn Forte 					bcopy((uint8_t *)mb, (uint8_t *)mbox,
2219*fcf3ce44SJohn Forte 					    MAILBOX_CMD_BSIZE);
2220*fcf3ce44SJohn Forte 
2221*fcf3ce44SJohn Forte 					mbox->un.varInitLnk.link_flags &=
2222*fcf3ce44SJohn Forte 					    ~FLAGS_LINK_SPEED;
2223*fcf3ce44SJohn Forte 					mbox->un.varInitLnk.link_speed = 0;
2224*fcf3ce44SJohn Forte 					mbox->mbxOwner = OWN_HOST;
2225*fcf3ce44SJohn Forte 					mbox->mbxStatus = 0;
2226*fcf3ce44SJohn Forte 
2227*fcf3ce44SJohn Forte 					/* Refresh the mailbox area */
2228*fcf3ce44SJohn Forte 					emlxs_mb_retry(hba, mbox);
2229*fcf3ce44SJohn Forte 
2230*fcf3ce44SJohn Forte 					if (emlxs_mb_issue_cmd(hba, mbox,
2231*fcf3ce44SJohn Forte 					    MBX_NOWAIT, 0) != MBX_BUSY) {
2232*fcf3ce44SJohn Forte 						(void) emlxs_mem_put(hba,
2233*fcf3ce44SJohn Forte 						    MEM_MBOX, (uint8_t *)mbox);
2234*fcf3ce44SJohn Forte 					}
2235*fcf3ce44SJohn Forte 					return (0);
2236*fcf3ce44SJohn Forte 				}
2237*fcf3ce44SJohn Forte 			}
2238*fcf3ce44SJohn Forte 		}
2239*fcf3ce44SJohn Forte 		break;
2240*fcf3ce44SJohn Forte 	}
2241*fcf3ce44SJohn Forte 
2242*fcf3ce44SJohn Forte done:
2243*fcf3ce44SJohn Forte 
2244*fcf3ce44SJohn Forte 	/* Clean up the mailbox area */
2245*fcf3ce44SJohn Forte 	emlxs_mb_fini(hba, mb, mb->mbxStatus);
2246*fcf3ce44SJohn Forte 
2247*fcf3ce44SJohn Forte 	/* Attempt to send pending mailboxes */
2248*fcf3ce44SJohn Forte 	if ((mbox = (MAILBOX *) emlxs_mb_get(hba))) {
2249*fcf3ce44SJohn Forte 		if (emlxs_mb_issue_cmd(hba, mbox, MBX_NOWAIT, 0) != MBX_BUSY) {
2250*fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox);
2251*fcf3ce44SJohn Forte 		}
2252*fcf3ce44SJohn Forte 	}
2253*fcf3ce44SJohn Forte 	return (0);
2254*fcf3ce44SJohn Forte 
2255*fcf3ce44SJohn Forte } /* emlxs_handle_mb_event() */
2256*fcf3ce44SJohn Forte 
2257*fcf3ce44SJohn Forte 
2258*fcf3ce44SJohn Forte 
2259*fcf3ce44SJohn Forte /*
2260*fcf3ce44SJohn Forte  *  emlxs_mb_handle_cmd
2261*fcf3ce44SJohn Forte  *
2262*fcf3ce44SJohn Forte  *  Description: Process a Mailbox Command.
2263*fcf3ce44SJohn Forte  *  Called from host_interrupt to process MBATT
2264*fcf3ce44SJohn Forte  *
2265*fcf3ce44SJohn Forte  *    Returns:
2266*fcf3ce44SJohn Forte  *
2267*fcf3ce44SJohn Forte  */
2268*fcf3ce44SJohn Forte static int
2269*fcf3ce44SJohn Forte emlxs_mb_handle_cmd(emlxs_hba_t *hba, MAILBOX *mb)
2270*fcf3ce44SJohn Forte {
2271*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2272*fcf3ce44SJohn Forte 	emlxs_port_t *vport;
2273*fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2274*fcf3ce44SJohn Forte 	NODELIST *ndlp;
2275*fcf3ce44SJohn Forte 	volatile SERV_PARM *sp;
2276*fcf3ce44SJohn Forte 	int32_t i;
2277*fcf3ce44SJohn Forte 	uint32_t ldata;
2278*fcf3ce44SJohn Forte 	uint32_t ldid;
2279*fcf3ce44SJohn Forte 	uint16_t lrpi;
2280*fcf3ce44SJohn Forte 	uint16_t lvpi;
2281*fcf3ce44SJohn Forte 	MATCHMAP *mp;
2282*fcf3ce44SJohn Forte 	uint8_t *wwn;
2283*fcf3ce44SJohn Forte 	READ_LA_VAR la;
2284*fcf3ce44SJohn Forte 
2285*fcf3ce44SJohn Forte 	if (mb->mbxStatus != 0) {
2286*fcf3ce44SJohn Forte 		return (1);
2287*fcf3ce44SJohn Forte 	}
2288*fcf3ce44SJohn Forte 	mp = (MATCHMAP *) hba->mbox_bp;
2289*fcf3ce44SJohn Forte 
2290*fcf3ce44SJohn Forte 	/*
2291*fcf3ce44SJohn Forte 	 * Mailbox command completed successfully, process completion
2292*fcf3ce44SJohn Forte 	 */
2293*fcf3ce44SJohn Forte 	switch (mb->mbxCommand) {
2294*fcf3ce44SJohn Forte 	case MBX_SHUTDOWN:
2295*fcf3ce44SJohn Forte 	case MBX_LOAD_SM:
2296*fcf3ce44SJohn Forte 	case MBX_READ_NV:
2297*fcf3ce44SJohn Forte 	case MBX_WRITE_NV:
2298*fcf3ce44SJohn Forte 	case MBX_RUN_BIU_DIAG:
2299*fcf3ce44SJohn Forte 	case MBX_RUN_BIU_DIAG64:
2300*fcf3ce44SJohn Forte 	case MBX_INIT_LINK:
2301*fcf3ce44SJohn Forte 	case MBX_DOWN_LINK:
2302*fcf3ce44SJohn Forte 	case MBX_CONFIG_LINK:
2303*fcf3ce44SJohn Forte 	case MBX_PART_SLIM:
2304*fcf3ce44SJohn Forte 	case MBX_CONFIG_RING:
2305*fcf3ce44SJohn Forte 	case MBX_RESET_RING:
2306*fcf3ce44SJohn Forte 	case MBX_READ_CONFIG:
2307*fcf3ce44SJohn Forte 	case MBX_READ_RCONFIG:
2308*fcf3ce44SJohn Forte 	case MBX_READ_STATUS:
2309*fcf3ce44SJohn Forte 	case MBX_READ_XRI:
2310*fcf3ce44SJohn Forte 	case MBX_READ_REV:
2311*fcf3ce44SJohn Forte 	case MBX_READ_LNK_STAT:
2312*fcf3ce44SJohn Forte 	case MBX_UNREG_LOGIN:
2313*fcf3ce44SJohn Forte 	case MBX_DUMP_MEMORY:
2314*fcf3ce44SJohn Forte 	case MBX_DUMP_CONTEXT:
2315*fcf3ce44SJohn Forte 	case MBX_RUN_DIAGS:
2316*fcf3ce44SJohn Forte 	case MBX_RESTART:
2317*fcf3ce44SJohn Forte 	case MBX_UPDATE_CFG:
2318*fcf3ce44SJohn Forte 	case MBX_DOWN_LOAD:
2319*fcf3ce44SJohn Forte 	case MBX_DEL_LD_ENTRY:
2320*fcf3ce44SJohn Forte 	case MBX_RUN_PROGRAM:
2321*fcf3ce44SJohn Forte 	case MBX_SET_MASK:
2322*fcf3ce44SJohn Forte 	case MBX_SET_VARIABLE:
2323*fcf3ce44SJohn Forte 	case MBX_UNREG_D_ID:
2324*fcf3ce44SJohn Forte 	case MBX_KILL_BOARD:
2325*fcf3ce44SJohn Forte 	case MBX_CONFIG_FARP:
2326*fcf3ce44SJohn Forte 	case MBX_LOAD_AREA:
2327*fcf3ce44SJohn Forte 	case MBX_CONFIG_PORT:
2328*fcf3ce44SJohn Forte 	case MBX_CONFIG_MSI:
2329*fcf3ce44SJohn Forte 	case MBX_FLASH_WR_ULA:
2330*fcf3ce44SJohn Forte 	case MBX_SET_DEBUG:
2331*fcf3ce44SJohn Forte 	case MBX_GET_DEBUG:
2332*fcf3ce44SJohn Forte 	case MBX_LOAD_EXP_ROM:
2333*fcf3ce44SJohn Forte 	case MBX_BEACON:
2334*fcf3ce44SJohn Forte 	case MBX_READ_RPI:
2335*fcf3ce44SJohn Forte 	case MBX_READ_RPI64:
2336*fcf3ce44SJohn Forte 	case MBX_REG_VPI:
2337*fcf3ce44SJohn Forte 	case MBX_UNREG_VPI:
2338*fcf3ce44SJohn Forte 	case MBX_CONFIG_HBQ:
2339*fcf3ce44SJohn Forte 	case MBX_ASYNC_EVENT:
2340*fcf3ce44SJohn Forte 	case MBX_HEARTBEAT:
2341*fcf3ce44SJohn Forte 		break;
2342*fcf3ce44SJohn Forte 
2343*fcf3ce44SJohn Forte 	case MBX_CONFIG_MSIX:
2344*fcf3ce44SJohn Forte 		break;
2345*fcf3ce44SJohn Forte 
2346*fcf3ce44SJohn Forte 	case MBX_READ_SPARM:	/* a READ SPARAM command completed */
2347*fcf3ce44SJohn Forte 	case MBX_READ_SPARM64:	/* a READ SPARAM command completed */
2348*fcf3ce44SJohn Forte 		{
2349*fcf3ce44SJohn Forte 			if (mp) {
2350*fcf3ce44SJohn Forte 				bcopy((caddr_t)mp->virt, (caddr_t)& hba->sparam,
2351*fcf3ce44SJohn Forte 				    sizeof (SERV_PARM));
2352*fcf3ce44SJohn Forte 
2353*fcf3ce44SJohn Forte 				bcopy((caddr_t)& hba->sparam.nodeName,
2354*fcf3ce44SJohn Forte 				    (caddr_t)& hba->wwnn,
2355*fcf3ce44SJohn Forte 				    sizeof (NAME_TYPE));
2356*fcf3ce44SJohn Forte 
2357*fcf3ce44SJohn Forte 				bcopy((caddr_t)& hba->sparam.portName,
2358*fcf3ce44SJohn Forte 				    (caddr_t)& hba->wwpn,
2359*fcf3ce44SJohn Forte 				    sizeof (NAME_TYPE));
2360*fcf3ce44SJohn Forte 
2361*fcf3ce44SJohn Forte 				/* Initialize the physical port */
2362*fcf3ce44SJohn Forte 				bcopy((caddr_t)& hba->sparam,
2363*fcf3ce44SJohn Forte 				    (caddr_t)& port->sparam,
2364*fcf3ce44SJohn Forte 				    sizeof (SERV_PARM));
2365*fcf3ce44SJohn Forte 				bcopy((caddr_t)& hba->wwpn,
2366*fcf3ce44SJohn Forte 				    (caddr_t)& port->wwpn, sizeof (NAME_TYPE));
2367*fcf3ce44SJohn Forte 				bcopy((caddr_t)& hba->wwnn,
2368*fcf3ce44SJohn Forte 				    (caddr_t)& port->wwnn, sizeof (NAME_TYPE));
2369*fcf3ce44SJohn Forte 
2370*fcf3ce44SJohn Forte 				/* Initialize the virtual ports */
2371*fcf3ce44SJohn Forte 				for (i = 1; i < MAX_VPORTS; i++) {
2372*fcf3ce44SJohn Forte 					vport = &VPORT(i);
2373*fcf3ce44SJohn Forte 					if (vport->flag & EMLXS_PORT_BOUND) {
2374*fcf3ce44SJohn Forte 						continue;
2375*fcf3ce44SJohn Forte 					}
2376*fcf3ce44SJohn Forte 					bcopy((caddr_t)& hba->sparam,
2377*fcf3ce44SJohn Forte 					    (caddr_t)& vport->sparam,
2378*fcf3ce44SJohn Forte 					    sizeof (SERV_PARM));
2379*fcf3ce44SJohn Forte 
2380*fcf3ce44SJohn Forte 					bcopy((caddr_t)& vport->wwnn,
2381*fcf3ce44SJohn Forte 					    (caddr_t)& vport->sparam.nodeName,
2382*fcf3ce44SJohn Forte 					    sizeof (NAME_TYPE));
2383*fcf3ce44SJohn Forte 
2384*fcf3ce44SJohn Forte 					bcopy((caddr_t)& vport->wwpn,
2385*fcf3ce44SJohn Forte 					    (caddr_t)& vport->sparam.portName,
2386*fcf3ce44SJohn Forte 					    sizeof (NAME_TYPE));
2387*fcf3ce44SJohn Forte 				}
2388*fcf3ce44SJohn Forte 
2389*fcf3ce44SJohn Forte 			}
2390*fcf3ce44SJohn Forte 			break;
2391*fcf3ce44SJohn Forte 		}
2392*fcf3ce44SJohn Forte 
2393*fcf3ce44SJohn Forte 
2394*fcf3ce44SJohn Forte 	case MBX_REG_LOGIN:
2395*fcf3ce44SJohn Forte 	case MBX_REG_LOGIN64:
2396*fcf3ce44SJohn Forte 
2397*fcf3ce44SJohn Forte 		if (!mp) {
2398*fcf3ce44SJohn Forte 			break;
2399*fcf3ce44SJohn Forte 		}
2400*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
2401*fcf3ce44SJohn Forte 		ldata = mb->un.varWords[5];
2402*fcf3ce44SJohn Forte 		lvpi = ldata & 0xffff;
2403*fcf3ce44SJohn Forte 		port = &VPORT(lvpi);
2404*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
2405*fcf3ce44SJohn Forte 
2406*fcf3ce44SJohn Forte 		/* First copy command data */
2407*fcf3ce44SJohn Forte 		ldata = mb->un.varWords[0];	/* get rpi */
2408*fcf3ce44SJohn Forte 		lrpi = ldata & 0xffff;
2409*fcf3ce44SJohn Forte 
2410*fcf3ce44SJohn Forte 		ldata = mb->un.varWords[1];	/* get did */
2411*fcf3ce44SJohn Forte 		ldid = ldata & Mask_DID;
2412*fcf3ce44SJohn Forte 
2413*fcf3ce44SJohn Forte 		sp = (volatile SERV_PARM *) mp->virt;
2414*fcf3ce44SJohn Forte 		ndlp = emlxs_node_find_did(port, ldid);
2415*fcf3ce44SJohn Forte 
2416*fcf3ce44SJohn Forte 		if (!ndlp) {
2417*fcf3ce44SJohn Forte 			/* Attempt to create a node */
2418*fcf3ce44SJohn Forte 			if ((ndlp = (NODELIST *) emlxs_mem_get(hba, MEM_NLP))) {
2419*fcf3ce44SJohn Forte 				ndlp->nlp_Rpi = lrpi;
2420*fcf3ce44SJohn Forte 				ndlp->nlp_DID = ldid;
2421*fcf3ce44SJohn Forte 
2422*fcf3ce44SJohn Forte 				bcopy((uint8_t *)sp,
2423*fcf3ce44SJohn Forte 				    (uint8_t *)& ndlp->sparm,
2424*fcf3ce44SJohn Forte 				    sizeof (SERV_PARM));
2425*fcf3ce44SJohn Forte 
2426*fcf3ce44SJohn Forte 				bcopy((uint8_t *)& sp->nodeName,
2427*fcf3ce44SJohn Forte 				    (uint8_t *)& ndlp->nlp_nodename,
2428*fcf3ce44SJohn Forte 				    sizeof (NAME_TYPE));
2429*fcf3ce44SJohn Forte 
2430*fcf3ce44SJohn Forte 				bcopy((uint8_t *)& sp->portName,
2431*fcf3ce44SJohn Forte 				    (uint8_t *)& ndlp->nlp_portname,
2432*fcf3ce44SJohn Forte 				    sizeof (NAME_TYPE));
2433*fcf3ce44SJohn Forte 
2434*fcf3ce44SJohn Forte 				ndlp->nlp_active = 1;
2435*fcf3ce44SJohn Forte 				ndlp->nlp_flag[FC_CT_RING] |= NLP_CLOSED;
2436*fcf3ce44SJohn Forte 				ndlp->nlp_flag[FC_ELS_RING] |= NLP_CLOSED;
2437*fcf3ce44SJohn Forte 				ndlp->nlp_flag[FC_FCP_RING] |= NLP_CLOSED;
2438*fcf3ce44SJohn Forte 				ndlp->nlp_flag[FC_IP_RING] |= NLP_CLOSED;
2439*fcf3ce44SJohn Forte 
2440*fcf3ce44SJohn Forte 				/* Add the node */
2441*fcf3ce44SJohn Forte 				emlxs_node_add(port, ndlp);
2442*fcf3ce44SJohn Forte 
2443*fcf3ce44SJohn Forte 				/* Open the node */
2444*fcf3ce44SJohn Forte 				emlxs_node_open(port, ndlp, FC_CT_RING);
2445*fcf3ce44SJohn Forte 				emlxs_node_open(port, ndlp, FC_ELS_RING);
2446*fcf3ce44SJohn Forte 				emlxs_node_open(port, ndlp, FC_IP_RING);
2447*fcf3ce44SJohn Forte 				emlxs_node_open(port, ndlp, FC_FCP_RING);
2448*fcf3ce44SJohn Forte 			} else {
2449*fcf3ce44SJohn Forte 				wwn = (uint8_t *)& sp->portName;
2450*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
2451*fcf3ce44SJohn Forte 				    &emlxs_node_create_failed_msg,
2452*fcf3ce44SJohn Forte 				    "Unable to allocate node. did=%06x rpi=%x "
2453*fcf3ce44SJohn Forte 				    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
2454*fcf3ce44SJohn Forte 				    ldid, lrpi, wwn[0], wwn[1], wwn[2], wwn[3],
2455*fcf3ce44SJohn Forte 				    wwn[4], wwn[5], wwn[6], wwn[7]);
2456*fcf3ce44SJohn Forte 
2457*fcf3ce44SJohn Forte 				break;
2458*fcf3ce44SJohn Forte 			}
2459*fcf3ce44SJohn Forte 		} else {
2460*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_PORT_LOCK);
2461*fcf3ce44SJohn Forte 
2462*fcf3ce44SJohn Forte 			ndlp->nlp_Rpi = lrpi;
2463*fcf3ce44SJohn Forte 			ndlp->nlp_DID = ldid;
2464*fcf3ce44SJohn Forte 
2465*fcf3ce44SJohn Forte 			bcopy((uint8_t *)sp,
2466*fcf3ce44SJohn Forte 			    (uint8_t *)& ndlp->sparm,
2467*fcf3ce44SJohn Forte 			    sizeof (SERV_PARM));
2468*fcf3ce44SJohn Forte 
2469*fcf3ce44SJohn Forte 			bcopy((uint8_t *)& sp->nodeName,
2470*fcf3ce44SJohn Forte 			    (uint8_t *)& ndlp->nlp_nodename,
2471*fcf3ce44SJohn Forte 			    sizeof (NAME_TYPE));
2472*fcf3ce44SJohn Forte 
2473*fcf3ce44SJohn Forte 			bcopy((uint8_t *)& sp->portName,
2474*fcf3ce44SJohn Forte 			    (uint8_t *)& ndlp->nlp_portname,
2475*fcf3ce44SJohn Forte 			    sizeof (NAME_TYPE));
2476*fcf3ce44SJohn Forte 
2477*fcf3ce44SJohn Forte 			wwn = (uint8_t *)& ndlp->nlp_portname;
2478*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg,
2479*fcf3ce44SJohn Forte 			    "node=%p did=%06x rpi=%x wwpn="
2480*fcf3ce44SJohn Forte 			    "%02x%02x%02x%02x%02x%02x%02x%02x",
2481*fcf3ce44SJohn Forte 			    ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], wwn[1],
2482*fcf3ce44SJohn Forte 			    wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
2483*fcf3ce44SJohn Forte 
2484*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
2485*fcf3ce44SJohn Forte 
2486*fcf3ce44SJohn Forte 			/* Open the node */
2487*fcf3ce44SJohn Forte 			emlxs_node_open(port, ndlp, FC_CT_RING);
2488*fcf3ce44SJohn Forte 			emlxs_node_open(port, ndlp, FC_ELS_RING);
2489*fcf3ce44SJohn Forte 			emlxs_node_open(port, ndlp, FC_IP_RING);
2490*fcf3ce44SJohn Forte 			emlxs_node_open(port, ndlp, FC_FCP_RING);
2491*fcf3ce44SJohn Forte 		}
2492*fcf3ce44SJohn Forte 
2493*fcf3ce44SJohn Forte 		/* If this was a fabric login */
2494*fcf3ce44SJohn Forte 		if (ndlp->nlp_DID == Fabric_DID) {
2495*fcf3ce44SJohn Forte 			/*
2496*fcf3ce44SJohn Forte 			 * If CLEAR_LA has been sent, then attempt to
2497*fcf3ce44SJohn Forte 			 * register the vpi now
2498*fcf3ce44SJohn Forte 			 */
2499*fcf3ce44SJohn Forte 			if (hba->state == FC_READY) {
2500*fcf3ce44SJohn Forte 				(void) emlxs_mb_reg_vpi(port);
2501*fcf3ce44SJohn Forte 			}
2502*fcf3ce44SJohn Forte #ifdef SLI3_SUPPORT
2503*fcf3ce44SJohn Forte 			/*
2504*fcf3ce44SJohn Forte 			 * If NPIV Fabric support has just been established
2505*fcf3ce44SJohn Forte 			 * on the physical port, then notify the vports of
2506*fcf3ce44SJohn Forte 			 * the link up
2507*fcf3ce44SJohn Forte 			 */
2508*fcf3ce44SJohn Forte 			if ((lvpi == 0) &&
2509*fcf3ce44SJohn Forte 			    (hba->flag & FC_NPIV_ENABLED) &&
2510*fcf3ce44SJohn Forte 			    (hba->flag & FC_NPIV_SUPPORTED)) {
2511*fcf3ce44SJohn Forte 				/* Skip the physical port */
2512*fcf3ce44SJohn Forte 				for (i = 1; i < MAX_VPORTS; i++) {
2513*fcf3ce44SJohn Forte 					vport = &VPORT(i);
2514*fcf3ce44SJohn Forte 
2515*fcf3ce44SJohn Forte 					if (!(vport->flag & EMLXS_PORT_BOUND) ||
2516*fcf3ce44SJohn Forte 					    !(vport->flag &
2517*fcf3ce44SJohn Forte 					    EMLXS_PORT_ENABLE)) {
2518*fcf3ce44SJohn Forte 						continue;
2519*fcf3ce44SJohn Forte 					}
2520*fcf3ce44SJohn Forte 					emlxs_port_online(vport);
2521*fcf3ce44SJohn Forte 				}
2522*fcf3ce44SJohn Forte 			}
2523*fcf3ce44SJohn Forte #endif	/* SLI3_SUPPORT */
2524*fcf3ce44SJohn Forte 
2525*fcf3ce44SJohn Forte 		}
2526*fcf3ce44SJohn Forte #ifdef NPIV_SUPPORT
2527*fcf3ce44SJohn Forte 		if (hba->mbox_iocbq == (uint8_t *)1) {
2528*fcf3ce44SJohn Forte 			hba->mbox_iocbq = NULL;
2529*fcf3ce44SJohn Forte 			(void) emlxs_mb_unreg_did(port, ldid, NULL, NULL, NULL);
2530*fcf3ce44SJohn Forte 		}
2531*fcf3ce44SJohn Forte #endif	/* NPIV_SUPPORT */
2532*fcf3ce44SJohn Forte 
2533*fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
2534*fcf3ce44SJohn Forte 		if (hba->mbox_sbp || hba->mbox_ubp) {
2535*fcf3ce44SJohn Forte 			if (emlxs_dhc_auth_start(port, ndlp, hba->mbox_sbp,
2536*fcf3ce44SJohn Forte 			    hba->mbox_ubp) == 0) {
2537*fcf3ce44SJohn Forte 				/*
2538*fcf3ce44SJohn Forte 				 * Auth started - auth completion will handle
2539*fcf3ce44SJohn Forte 				 * sbp and ubp now
2540*fcf3ce44SJohn Forte 				 */
2541*fcf3ce44SJohn Forte 				hba->mbox_sbp = NULL;
2542*fcf3ce44SJohn Forte 				hba->mbox_ubp = NULL;
2543*fcf3ce44SJohn Forte 			}
2544*fcf3ce44SJohn Forte 		}
2545*fcf3ce44SJohn Forte #endif	/* DHCHAP_SUPPORT */
2546*fcf3ce44SJohn Forte 
2547*fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
2548*fcf3ce44SJohn Forte 		if (hba->mbox_sbp && ((emlxs_buf_t *)hba->mbox_sbp)->fct_cmd) {
2549*fcf3ce44SJohn Forte 			emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)hba->mbox_sbp;
2550*fcf3ce44SJohn Forte 
2551*fcf3ce44SJohn Forte 			if (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) {
2552*fcf3ce44SJohn Forte 				hba->mbox_sbp = NULL;
2553*fcf3ce44SJohn Forte 
2554*fcf3ce44SJohn Forte 				mutex_enter(&EMLXS_PKT_LOCK);
2555*fcf3ce44SJohn Forte 				cmd_sbp->node = ndlp;
2556*fcf3ce44SJohn Forte 				cmd_sbp->fct_state = EMLXS_FCT_REG_COMPLETE;
2557*fcf3ce44SJohn Forte 				cv_broadcast(&EMLXS_PKT_CV);
2558*fcf3ce44SJohn Forte 				mutex_exit(&EMLXS_PKT_LOCK);
2559*fcf3ce44SJohn Forte 			}
2560*fcf3ce44SJohn Forte 		}
2561*fcf3ce44SJohn Forte #endif	/* SFCT_SUPPORT */
2562*fcf3ce44SJohn Forte 
2563*fcf3ce44SJohn Forte 		break;
2564*fcf3ce44SJohn Forte 
2565*fcf3ce44SJohn Forte 	case MBX_READ_LA:
2566*fcf3ce44SJohn Forte 	case MBX_READ_LA64:
2567*fcf3ce44SJohn Forte 		bcopy((uint32_t *)((char *)mb + sizeof (uint32_t)),
2568*fcf3ce44SJohn Forte 		    (uint32_t *)& la, sizeof (READ_LA_VAR));
2569*fcf3ce44SJohn Forte 
2570*fcf3ce44SJohn Forte 		if (mp) {
2571*fcf3ce44SJohn Forte 			bcopy((caddr_t)mp->virt,
2572*fcf3ce44SJohn Forte 			    (caddr_t)port->alpa_map, 128);
2573*fcf3ce44SJohn Forte 		} else {
2574*fcf3ce44SJohn Forte 			bzero((caddr_t)port->alpa_map, 128);
2575*fcf3ce44SJohn Forte 		}
2576*fcf3ce44SJohn Forte 
2577*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_atten_msg,
2578*fcf3ce44SJohn Forte 		    "type=%s tag=%d -> %d  ALPA=%x",
2579*fcf3ce44SJohn Forte 		    ((la.attType == AT_LINK_UP) ?
2580*fcf3ce44SJohn Forte 		    "LinkUp" : "LinkDown"),
2581*fcf3ce44SJohn Forte 		    (uint32_t)hba->link_event_tag,
2582*fcf3ce44SJohn Forte 		    (uint32_t)la.eventTag, (uint32_t)la.granted_AL_PA);
2583*fcf3ce44SJohn Forte 
2584*fcf3ce44SJohn Forte 		if (la.pb) {
2585*fcf3ce44SJohn Forte 			hba->flag |= FC_BYPASSED_MODE;
2586*fcf3ce44SJohn Forte 		} else {
2587*fcf3ce44SJohn Forte 			hba->flag &= ~FC_BYPASSED_MODE;
2588*fcf3ce44SJohn Forte 		}
2589*fcf3ce44SJohn Forte 
2590*fcf3ce44SJohn Forte 		if (hba->link_event_tag == la.eventTag) {
2591*fcf3ce44SJohn Forte 			HBASTATS.LinkMultiEvent++;
2592*fcf3ce44SJohn Forte 		} else if (hba->link_event_tag + 1 < la.eventTag) {
2593*fcf3ce44SJohn Forte 			HBASTATS.LinkMultiEvent++;
2594*fcf3ce44SJohn Forte 
2595*fcf3ce44SJohn Forte 			if (hba->state > FC_LINK_DOWN) {
2596*fcf3ce44SJohn Forte 				/* Declare link down here */
2597*fcf3ce44SJohn Forte 				emlxs_linkdown(hba);
2598*fcf3ce44SJohn Forte 			}
2599*fcf3ce44SJohn Forte 		}
2600*fcf3ce44SJohn Forte 		hba->link_event_tag = la.eventTag;
2601*fcf3ce44SJohn Forte 		port->lip_type = 0;
2602*fcf3ce44SJohn Forte 
2603*fcf3ce44SJohn Forte 		/* If link not already up then declare it up now */
2604*fcf3ce44SJohn Forte 		if ((la.attType == AT_LINK_UP) &&
2605*fcf3ce44SJohn Forte 		    (hba->state < FC_LINK_UP)) {
2606*fcf3ce44SJohn Forte 
2607*fcf3ce44SJohn Forte 			/* Save the linkspeed */
2608*fcf3ce44SJohn Forte 			hba->linkspeed = la.UlnkSpeed;
2609*fcf3ce44SJohn Forte 
2610*fcf3ce44SJohn Forte 			/*
2611*fcf3ce44SJohn Forte 			 * Check for old model adapters that only
2612*fcf3ce44SJohn Forte 			 * supported 1Gb
2613*fcf3ce44SJohn Forte 			 */
2614*fcf3ce44SJohn Forte 			if ((hba->linkspeed == 0) &&
2615*fcf3ce44SJohn Forte 			    (hba->model_info.chip &
2616*fcf3ce44SJohn Forte 			    EMLXS_DRAGONFLY_CHIP)) {
2617*fcf3ce44SJohn Forte 				hba->linkspeed = LA_1GHZ_LINK;
2618*fcf3ce44SJohn Forte 			}
2619*fcf3ce44SJohn Forte 			if ((hba->topology = la.topology) ==
2620*fcf3ce44SJohn Forte 			    TOPOLOGY_LOOP) {
2621*fcf3ce44SJohn Forte 				port->did = la.granted_AL_PA;
2622*fcf3ce44SJohn Forte 				port->lip_type = la.lipType;
2623*fcf3ce44SJohn Forte 
2624*fcf3ce44SJohn Forte 				if (hba->flag & FC_SLIM2_MODE) {
2625*fcf3ce44SJohn Forte 					i = la.un.lilpBde64.tus.f.
2626*fcf3ce44SJohn Forte 					    bdeSize;
2627*fcf3ce44SJohn Forte 				} else {
2628*fcf3ce44SJohn Forte 					i = la.un.lilpBde.bdeSize;
2629*fcf3ce44SJohn Forte 				}
2630*fcf3ce44SJohn Forte 
2631*fcf3ce44SJohn Forte 				if (i == 0) {
2632*fcf3ce44SJohn Forte 					port->alpa_map[0] = 0;
2633*fcf3ce44SJohn Forte 				} else {
2634*fcf3ce44SJohn Forte 					uint8_t *alpa_map;
2635*fcf3ce44SJohn Forte 					uint32_t j;
2636*fcf3ce44SJohn Forte 
2637*fcf3ce44SJohn Forte 					/*
2638*fcf3ce44SJohn Forte 					 * Check number of devices in
2639*fcf3ce44SJohn Forte 					 * map
2640*fcf3ce44SJohn Forte 					 */
2641*fcf3ce44SJohn Forte 					if (port->alpa_map[0] > 127) {
2642*fcf3ce44SJohn Forte 						port->alpa_map[0] = 127;
2643*fcf3ce44SJohn Forte 					}
2644*fcf3ce44SJohn Forte 					alpa_map = (uint8_t *)port->alpa_map;
2645*fcf3ce44SJohn Forte 
2646*fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2647*fcf3ce44SJohn Forte 					    &emlxs_link_atten_msg,
2648*fcf3ce44SJohn Forte 					    "alpa_map: %d device(s):  %02x "
2649*fcf3ce44SJohn Forte 					    "%02x %02x %02x %02x %02x %02x",
2650*fcf3ce44SJohn Forte 					    alpa_map[0], alpa_map[1],
2651*fcf3ce44SJohn Forte 					    alpa_map[2], alpa_map[3],
2652*fcf3ce44SJohn Forte 					    alpa_map[4], alpa_map[5],
2653*fcf3ce44SJohn Forte 					    alpa_map[6], alpa_map[7]);
2654*fcf3ce44SJohn Forte 
2655*fcf3ce44SJohn Forte 					for (j = 8; j <= alpa_map[0]; j += 8) {
2656*fcf3ce44SJohn Forte 						EMLXS_MSGF(EMLXS_CONTEXT,
2657*fcf3ce44SJohn Forte 						    &emlxs_link_atten_msg,
2658*fcf3ce44SJohn Forte 						    "alpa_map: %02x %02x %02x "
2659*fcf3ce44SJohn Forte 						    "%02x %02x %02x %02x %02x",
2660*fcf3ce44SJohn Forte 						    alpa_map[j],
2661*fcf3ce44SJohn Forte 						    alpa_map[j + 1],
2662*fcf3ce44SJohn Forte 						    alpa_map[j + 2],
2663*fcf3ce44SJohn Forte 						    alpa_map[j + 3],
2664*fcf3ce44SJohn Forte 						    alpa_map[j + 4],
2665*fcf3ce44SJohn Forte 						    alpa_map[j + 5],
2666*fcf3ce44SJohn Forte 						    alpa_map[j + 6],
2667*fcf3ce44SJohn Forte 						    alpa_map[j + 7]);
2668*fcf3ce44SJohn Forte 					}
2669*fcf3ce44SJohn Forte 				}
2670*fcf3ce44SJohn Forte 			}
2671*fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
2672*fcf3ce44SJohn Forte 			/* Check if Menlo maintenance mode is enabled */
2673*fcf3ce44SJohn Forte 			if (hba->model_info.device_id ==
2674*fcf3ce44SJohn Forte 			    PCI_DEVICE_ID_LP21000_M) {
2675*fcf3ce44SJohn Forte 				if (la.mm == 1) {
2676*fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2677*fcf3ce44SJohn Forte 					    &emlxs_link_atten_msg,
2678*fcf3ce44SJohn Forte 					    "Maintenance Mode enabled.");
2679*fcf3ce44SJohn Forte 
2680*fcf3ce44SJohn Forte 					mutex_enter(&EMLXS_PORT_LOCK);
2681*fcf3ce44SJohn Forte 					hba->flag |= FC_MENLO_MODE;
2682*fcf3ce44SJohn Forte 					mutex_exit(&EMLXS_PORT_LOCK);
2683*fcf3ce44SJohn Forte 
2684*fcf3ce44SJohn Forte 					mutex_enter(&EMLXS_LINKUP_LOCK);
2685*fcf3ce44SJohn Forte 					cv_broadcast(&EMLXS_LINKUP_CV);
2686*fcf3ce44SJohn Forte 					mutex_exit(&EMLXS_LINKUP_LOCK);
2687*fcf3ce44SJohn Forte 				} else {
2688*fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2689*fcf3ce44SJohn Forte 					    &emlxs_link_atten_msg,
2690*fcf3ce44SJohn Forte 					    "Maintenance Mode disabled.");
2691*fcf3ce44SJohn Forte 				}
2692*fcf3ce44SJohn Forte 
2693*fcf3ce44SJohn Forte 				/* Check FCoE attention bit */
2694*fcf3ce44SJohn Forte 				if (la.fa == 1) {
2695*fcf3ce44SJohn Forte 					(void) thread_create(NULL, 0,
2696*fcf3ce44SJohn Forte 					    emlxs_fcoe_attention_thread,
2697*fcf3ce44SJohn Forte 					    (char *)hba, 0,
2698*fcf3ce44SJohn Forte 					    &p0, TS_RUN,
2699*fcf3ce44SJohn Forte 					    v.v_maxsyspri - 2);
2700*fcf3ce44SJohn Forte 				}
2701*fcf3ce44SJohn Forte 			}
2702*fcf3ce44SJohn Forte #endif	/* MENLO_SUPPORT */
2703*fcf3ce44SJohn Forte 
2704*fcf3ce44SJohn Forte 			if ((mbox = (MAILBOXQ *) emlxs_mem_get(hba,
2705*fcf3ce44SJohn Forte 			    MEM_MBOX | MEM_PRI))) {
2706*fcf3ce44SJohn Forte 				/*
2707*fcf3ce44SJohn Forte 				 * This should turn on DELAYED ABTS
2708*fcf3ce44SJohn Forte 				 * for ELS timeouts
2709*fcf3ce44SJohn Forte 				 */
2710*fcf3ce44SJohn Forte 				emlxs_mb_set_var(hba, (MAILBOX *) mbox,
2711*fcf3ce44SJohn Forte 				    0x00052198, 0x1);
2712*fcf3ce44SJohn Forte 
2713*fcf3ce44SJohn Forte 				emlxs_mb_put(hba, mbox);
2714*fcf3ce44SJohn Forte 			}
2715*fcf3ce44SJohn Forte 			if ((mbox = (MAILBOXQ *) emlxs_mem_get(hba,
2716*fcf3ce44SJohn Forte 			    MEM_MBOX | MEM_PRI))) {
2717*fcf3ce44SJohn Forte 				/*
2718*fcf3ce44SJohn Forte 				 * If link not already down then
2719*fcf3ce44SJohn Forte 				 * declare it down now
2720*fcf3ce44SJohn Forte 				 */
2721*fcf3ce44SJohn Forte 				if (emlxs_mb_read_sparam(hba,
2722*fcf3ce44SJohn Forte 				    (MAILBOX *) mbox) == 0) {
2723*fcf3ce44SJohn Forte 					emlxs_mb_put(hba, mbox);
2724*fcf3ce44SJohn Forte 				} else {
2725*fcf3ce44SJohn Forte 					(void) emlxs_mem_put(hba, MEM_MBOX,
2726*fcf3ce44SJohn Forte 					    (uint8_t *)mbox);
2727*fcf3ce44SJohn Forte 				}
2728*fcf3ce44SJohn Forte 			}
2729*fcf3ce44SJohn Forte 			if ((mbox = (MAILBOXQ *) emlxs_mem_get(hba,
2730*fcf3ce44SJohn Forte 			    MEM_MBOX | MEM_PRI))) {
2731*fcf3ce44SJohn Forte 				emlxs_mb_config_link(hba,
2732*fcf3ce44SJohn Forte 				    (MAILBOX *) mbox);
2733*fcf3ce44SJohn Forte 
2734*fcf3ce44SJohn Forte 				emlxs_mb_put(hba, mbox);
2735*fcf3ce44SJohn Forte 			}
2736*fcf3ce44SJohn Forte 			/* Declare the linkup here */
2737*fcf3ce44SJohn Forte 			emlxs_linkup(hba);
2738*fcf3ce44SJohn Forte 		}
2739*fcf3ce44SJohn Forte 		/* If link not already down then declare it down now */
2740*fcf3ce44SJohn Forte 		else if ((la.attType == AT_LINK_DOWN) &&
2741*fcf3ce44SJohn Forte 		    (hba->state > FC_LINK_DOWN)) {
2742*fcf3ce44SJohn Forte 			/* Declare link down here */
2743*fcf3ce44SJohn Forte 			emlxs_linkdown(hba);
2744*fcf3ce44SJohn Forte 		}
2745*fcf3ce44SJohn Forte 		/* Enable Link attention interrupt */
2746*fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
2747*fcf3ce44SJohn Forte 
2748*fcf3ce44SJohn Forte 		if (!(hba->hc_copy & HC_LAINT_ENA)) {
2749*fcf3ce44SJohn Forte 			/*
2750*fcf3ce44SJohn Forte 			 * hba->hc_copy  = READ_CSR_REG(hba,
2751*fcf3ce44SJohn Forte 			 * FC_HC_REG(hba, hba->csr_addr));
2752*fcf3ce44SJohn Forte 			 */
2753*fcf3ce44SJohn Forte 			hba->hc_copy |= HC_LAINT_ENA;
2754*fcf3ce44SJohn Forte 			WRITE_CSR_REG(hba, FC_HC_REG(hba,
2755*fcf3ce44SJohn Forte 			    hba->csr_addr), hba->hc_copy);
2756*fcf3ce44SJohn Forte 		}
2757*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
2758*fcf3ce44SJohn Forte 
2759*fcf3ce44SJohn Forte 		/* Log the link event */
2760*fcf3ce44SJohn Forte 		emlxs_log_link_event(port);
2761*fcf3ce44SJohn Forte 
2762*fcf3ce44SJohn Forte 		break;
2763*fcf3ce44SJohn Forte 
2764*fcf3ce44SJohn Forte 	case MBX_CLEAR_LA:
2765*fcf3ce44SJohn Forte 		/* Enable on Link Attention interrupts */
2766*fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
2767*fcf3ce44SJohn Forte 
2768*fcf3ce44SJohn Forte 		if (!(hba->hc_copy & HC_LAINT_ENA)) {
2769*fcf3ce44SJohn Forte 			/*
2770*fcf3ce44SJohn Forte 			 * hba->hc_copy  = READ_CSR_REG(hba, FC_HC_REG(hba,
2771*fcf3ce44SJohn Forte 			 * hba->csr_addr));
2772*fcf3ce44SJohn Forte 			 */
2773*fcf3ce44SJohn Forte 			hba->hc_copy |= HC_LAINT_ENA;
2774*fcf3ce44SJohn Forte 			WRITE_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr),
2775*fcf3ce44SJohn Forte 			    hba->hc_copy);
2776*fcf3ce44SJohn Forte 		}
2777*fcf3ce44SJohn Forte 		if (hba->state >= FC_LINK_UP) {
2778*fcf3ce44SJohn Forte 			emlxs_ffstate_change_locked(hba, FC_READY);
2779*fcf3ce44SJohn Forte 		}
2780*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
2781*fcf3ce44SJohn Forte 
2782*fcf3ce44SJohn Forte 		/* Adapter is now ready for FCP traffic */
2783*fcf3ce44SJohn Forte 		if (hba->state == FC_READY) {
2784*fcf3ce44SJohn Forte 			/* Register vpi's for all ports that have did's */
2785*fcf3ce44SJohn Forte 			for (i = 0; i < MAX_VPORTS; i++) {
2786*fcf3ce44SJohn Forte 				vport = &VPORT(i);
2787*fcf3ce44SJohn Forte 
2788*fcf3ce44SJohn Forte 				if (!(vport->flag & EMLXS_PORT_BOUND) ||
2789*fcf3ce44SJohn Forte 				    !(vport->did)) {
2790*fcf3ce44SJohn Forte 					continue;
2791*fcf3ce44SJohn Forte 				}
2792*fcf3ce44SJohn Forte 				(void) emlxs_mb_reg_vpi(vport);
2793*fcf3ce44SJohn Forte 			}
2794*fcf3ce44SJohn Forte 
2795*fcf3ce44SJohn Forte 			/* Attempt to send any pending IO */
2796*fcf3ce44SJohn Forte 			emlxs_issue_iocb_cmd(hba, &hba->ring[FC_FCP_RING], 0);
2797*fcf3ce44SJohn Forte 		}
2798*fcf3ce44SJohn Forte 		break;
2799*fcf3ce44SJohn Forte 
2800*fcf3ce44SJohn Forte 	default:
2801*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
2802*fcf3ce44SJohn Forte 		    "Unknown mailbox cmd: 0x%x", mb->mbxCommand);
2803*fcf3ce44SJohn Forte 		HBASTATS.MboxInvalid++;
2804*fcf3ce44SJohn Forte 		break;
2805*fcf3ce44SJohn Forte 	}
2806*fcf3ce44SJohn Forte 
2807*fcf3ce44SJohn Forte 	return (0);
2808*fcf3ce44SJohn Forte 
2809*fcf3ce44SJohn Forte } /* emlxs_mb_handle_cmd() */
2810*fcf3ce44SJohn Forte 
2811*fcf3ce44SJohn Forte 
2812*fcf3ce44SJohn Forte /* MBX_NOWAIT - returns MBX_BUSY or MBX_SUCCESS or MBX_HARDWARE_ERROR */
2813*fcf3ce44SJohn Forte /* MBX_WAIT   - returns MBX_TIMEOUT or mailbox_status */
2814*fcf3ce44SJohn Forte /* MBX_SLEEP  - returns MBX_TIMEOUT or mailbox_status */
2815*fcf3ce44SJohn Forte /* MBX_POLL   - returns MBX_TIMEOUT or mailbox_status */
2816*fcf3ce44SJohn Forte 
2817*fcf3ce44SJohn Forte extern uint32_t
2818*fcf3ce44SJohn Forte emlxs_mb_issue_cmd(emlxs_hba_t *hba, MAILBOX *mb, int32_t flag, uint32_t tmo)
2819*fcf3ce44SJohn Forte {
2820*fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2821*fcf3ce44SJohn Forte 	MAILBOX *mbox;
2822*fcf3ce44SJohn Forte 	MAILBOXQ *mbq;
2823*fcf3ce44SJohn Forte 	volatile uint32_t word0;
2824*fcf3ce44SJohn Forte 	volatile uint32_t ldata;
2825*fcf3ce44SJohn Forte 	uint32_t ha_copy;
2826*fcf3ce44SJohn Forte 	off_t offset;
2827*fcf3ce44SJohn Forte 	MATCHMAP *mbox_bp;
2828*fcf3ce44SJohn Forte 	uint32_t tmo_local;
2829*fcf3ce44SJohn Forte 	MAILBOX *swpmb;
2830*fcf3ce44SJohn Forte 
2831*fcf3ce44SJohn Forte 	mbq = (MAILBOXQ *) mb;
2832*fcf3ce44SJohn Forte 	swpmb = (MAILBOX *) & word0;
2833*fcf3ce44SJohn Forte 
2834*fcf3ce44SJohn Forte 	mb->mbxStatus = MBX_SUCCESS;
2835*fcf3ce44SJohn Forte 
2836*fcf3ce44SJohn Forte 	/* Check for minimum timeouts */
2837*fcf3ce44SJohn Forte 	switch (mb->mbxCommand) {
2838*fcf3ce44SJohn Forte 		/* Mailbox commands that erase/write flash */
2839*fcf3ce44SJohn Forte 	case MBX_DOWN_LOAD:
2840*fcf3ce44SJohn Forte 	case MBX_UPDATE_CFG:
2841*fcf3ce44SJohn Forte 	case MBX_LOAD_AREA:
2842*fcf3ce44SJohn Forte 	case MBX_LOAD_EXP_ROM:
2843*fcf3ce44SJohn Forte 	case MBX_WRITE_NV:
2844*fcf3ce44SJohn Forte 	case MBX_FLASH_WR_ULA:
2845*fcf3ce44SJohn Forte 	case MBX_DEL_LD_ENTRY:
2846*fcf3ce44SJohn Forte 	case MBX_LOAD_SM:
2847*fcf3ce44SJohn Forte 		if (tmo < 300) {
2848*fcf3ce44SJohn Forte 			tmo = 300;
2849*fcf3ce44SJohn Forte 		}
2850*fcf3ce44SJohn Forte 		break;
2851*fcf3ce44SJohn Forte 
2852*fcf3ce44SJohn Forte 	default:
2853*fcf3ce44SJohn Forte 		if (tmo < 30) {
2854*fcf3ce44SJohn Forte 			tmo = 30;
2855*fcf3ce44SJohn Forte 		}
2856*fcf3ce44SJohn Forte 		break;
2857*fcf3ce44SJohn Forte 	}
2858*fcf3ce44SJohn Forte 
2859*fcf3ce44SJohn Forte 	/* Adjust wait flag */
2860*fcf3ce44SJohn Forte 	if (flag != MBX_NOWAIT) {
2861*fcf3ce44SJohn Forte 		/* If interrupt is enabled, use sleep, otherwise poll */
2862*fcf3ce44SJohn Forte 		if (hba->hc_copy & HC_MBINT_ENA) {
2863*fcf3ce44SJohn Forte 			flag = MBX_SLEEP;
2864*fcf3ce44SJohn Forte 		} else {
2865*fcf3ce44SJohn Forte 			flag = MBX_POLL;
2866*fcf3ce44SJohn Forte 		}
2867*fcf3ce44SJohn Forte 	}
2868*fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
2869*fcf3ce44SJohn Forte 
2870*fcf3ce44SJohn Forte 	/* Check for hardware error */
2871*fcf3ce44SJohn Forte 	if (hba->flag & FC_HARDWARE_ERROR) {
2872*fcf3ce44SJohn Forte 		mb->mbxStatus = (hba->flag & FC_OVERTEMP_EVENT) ?
2873*fcf3ce44SJohn Forte 		    MBX_OVERTEMP_ERROR : MBX_HARDWARE_ERROR;
2874*fcf3ce44SJohn Forte 
2875*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
2876*fcf3ce44SJohn Forte 
2877*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2878*fcf3ce44SJohn Forte 		    "Hardware error reported. %s failed. status=%x mb=%p",
2879*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mb->mbxStatus, mb);
2880*fcf3ce44SJohn Forte 
2881*fcf3ce44SJohn Forte 		return (MBX_HARDWARE_ERROR);
2882*fcf3ce44SJohn Forte 	}
2883*fcf3ce44SJohn Forte 	if (hba->mbox_queue_flag) {
2884*fcf3ce44SJohn Forte 		/* If we are not polling, then queue it for later */
2885*fcf3ce44SJohn Forte 		if (flag == MBX_NOWAIT) {
2886*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2887*fcf3ce44SJohn Forte 			    "Busy.      %s: mb=%p NoWait.",
2888*fcf3ce44SJohn Forte 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
2889*fcf3ce44SJohn Forte 
2890*fcf3ce44SJohn Forte 			emlxs_mb_put(hba, mbq);
2891*fcf3ce44SJohn Forte 
2892*fcf3ce44SJohn Forte 			HBASTATS.MboxBusy++;
2893*fcf3ce44SJohn Forte 
2894*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
2895*fcf3ce44SJohn Forte 
2896*fcf3ce44SJohn Forte 			return (MBX_BUSY);
2897*fcf3ce44SJohn Forte 		}
2898*fcf3ce44SJohn Forte 		tmo_local = tmo * 20;	/* Convert tmo seconds to 50 */
2899*fcf3ce44SJohn Forte 					/*   millisecond tics */
2900*fcf3ce44SJohn Forte 		while (hba->mbox_queue_flag) {
2901*fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
2902*fcf3ce44SJohn Forte 
2903*fcf3ce44SJohn Forte 			if (tmo_local-- == 0) {
2904*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
2905*fcf3ce44SJohn Forte 				    "Timeout.   %s: mb=%p tmo=%d Waiting.",
2906*fcf3ce44SJohn Forte 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
2907*fcf3ce44SJohn Forte 				    tmo);
2908*fcf3ce44SJohn Forte 
2909*fcf3ce44SJohn Forte 				/* Non-lethalStatus mailbox timeout */
2910*fcf3ce44SJohn Forte 				/* Does not indicate a hardware error */
2911*fcf3ce44SJohn Forte 				mb->mbxStatus = MBX_TIMEOUT;
2912*fcf3ce44SJohn Forte 				return (MBX_TIMEOUT);
2913*fcf3ce44SJohn Forte 			}
2914*fcf3ce44SJohn Forte 			DELAYMS(50);
2915*fcf3ce44SJohn Forte 			mutex_enter(&EMLXS_PORT_LOCK);
2916*fcf3ce44SJohn Forte 		}
2917*fcf3ce44SJohn Forte 	}
2918*fcf3ce44SJohn Forte 	/* Initialize mailbox area */
2919*fcf3ce44SJohn Forte 	emlxs_mb_init(hba, mbq, flag, tmo);
2920*fcf3ce44SJohn Forte 
2921*fcf3ce44SJohn Forte 	switch (flag) {
2922*fcf3ce44SJohn Forte 	case MBX_NOWAIT:
2923*fcf3ce44SJohn Forte 
2924*fcf3ce44SJohn Forte 		if (mb->mbxCommand != MBX_HEARTBEAT) {
2925*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2926*fcf3ce44SJohn Forte 			    "Sending.   %s: mb=%p NoWait.",
2927*fcf3ce44SJohn Forte 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
2928*fcf3ce44SJohn Forte 		}
2929*fcf3ce44SJohn Forte 		break;
2930*fcf3ce44SJohn Forte 
2931*fcf3ce44SJohn Forte 	case MBX_SLEEP:
2932*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2933*fcf3ce44SJohn Forte 		    "Sending.   %s: mb=%p Sleep.",
2934*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
2935*fcf3ce44SJohn Forte 
2936*fcf3ce44SJohn Forte 		break;
2937*fcf3ce44SJohn Forte 
2938*fcf3ce44SJohn Forte 	case MBX_POLL:
2939*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
2940*fcf3ce44SJohn Forte 		    "Sending.   %s: mb=%p Polled.",
2941*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
2942*fcf3ce44SJohn Forte 		break;
2943*fcf3ce44SJohn Forte 	}
2944*fcf3ce44SJohn Forte 
2945*fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_CHIP;
2946*fcf3ce44SJohn Forte 
2947*fcf3ce44SJohn Forte 	/* Clear the attention bit */
2948*fcf3ce44SJohn Forte 	WRITE_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr), HA_MBATT);
2949*fcf3ce44SJohn Forte 
2950*fcf3ce44SJohn Forte 	if (hba->flag & FC_SLIM2_MODE) {
2951*fcf3ce44SJohn Forte 		/* First copy command data */
2952*fcf3ce44SJohn Forte 		mbox = FC_SLIM2_MAILBOX(hba);
2953*fcf3ce44SJohn Forte 		offset = (off_t)((uint64_t)(unsigned long)mbox -
2954*fcf3ce44SJohn Forte 		    (uint64_t)(unsigned long)hba->slim2.virt);
2955*fcf3ce44SJohn Forte 
2956*fcf3ce44SJohn Forte #ifdef MBOX_EXT_SUPPORT
2957*fcf3ce44SJohn Forte 		if (hba->mbox_ext) {
2958*fcf3ce44SJohn Forte 			uint32_t *mbox_ext = (uint32_t *)((uint8_t *)mbox +
2959*fcf3ce44SJohn Forte 			    MBOX_EXTENSION_OFFSET);
2960*fcf3ce44SJohn Forte 			off_t offset_ext = offset + MBOX_EXTENSION_OFFSET;
2961*fcf3ce44SJohn Forte 
2962*fcf3ce44SJohn Forte 			emlxs_pcimem_bcopy((uint32_t *)hba->mbox_ext, mbox_ext,
2963*fcf3ce44SJohn Forte 			    hba->mbox_ext_size);
2964*fcf3ce44SJohn Forte 			emlxs_mpdata_sync(hba->slim2.dma_handle, offset_ext,
2965*fcf3ce44SJohn Forte 			    hba->mbox_ext_size, DDI_DMA_SYNC_FORDEV);
2966*fcf3ce44SJohn Forte 		}
2967*fcf3ce44SJohn Forte #endif	/* MBOX_EXT_SUPPORT */
2968*fcf3ce44SJohn Forte 
2969*fcf3ce44SJohn Forte 		emlxs_pcimem_bcopy((uint32_t *)mb, (uint32_t *)mbox,
2970*fcf3ce44SJohn Forte 		    MAILBOX_CMD_BSIZE);
2971*fcf3ce44SJohn Forte 		emlxs_mpdata_sync(hba->slim2.dma_handle, offset,
2972*fcf3ce44SJohn Forte 		    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
2973*fcf3ce44SJohn Forte 	}
2974*fcf3ce44SJohn Forte 	/* Check for config port command */
2975*fcf3ce44SJohn Forte 	else if (mb->mbxCommand == MBX_CONFIG_PORT) {
2976*fcf3ce44SJohn Forte 		/* copy command data into host mbox for cmpl */
2977*fcf3ce44SJohn Forte 		mbox = FC_SLIM2_MAILBOX(hba);
2978*fcf3ce44SJohn Forte 		offset = (off_t)((uint64_t)(unsigned long)mbox -
2979*fcf3ce44SJohn Forte 		    (uint64_t)(unsigned long)hba->slim2.virt);
2980*fcf3ce44SJohn Forte 
2981*fcf3ce44SJohn Forte 		emlxs_pcimem_bcopy((uint32_t *)mb, (uint32_t *)mbox,
2982*fcf3ce44SJohn Forte 		    MAILBOX_CMD_BSIZE);
2983*fcf3ce44SJohn Forte 		emlxs_mpdata_sync(hba->slim2.dma_handle, offset,
2984*fcf3ce44SJohn Forte 		    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
2985*fcf3ce44SJohn Forte 
2986*fcf3ce44SJohn Forte 		/* First copy command data */
2987*fcf3ce44SJohn Forte 		mbox = FC_SLIM1_MAILBOX(hba);
2988*fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords,
2989*fcf3ce44SJohn Forte 		    (MAILBOX_CMD_WSIZE - 1));
2990*fcf3ce44SJohn Forte 
2991*fcf3ce44SJohn Forte 		/* copy over last word, with mbxOwner set */
2992*fcf3ce44SJohn Forte 		ldata = *((volatile uint32_t *) mb);
2993*fcf3ce44SJohn Forte 		WRITE_SLIM_ADDR(hba, ((volatile uint32_t *) mbox), ldata);
2994*fcf3ce44SJohn Forte 
2995*fcf3ce44SJohn Forte 		/* switch over to host mailbox */
2996*fcf3ce44SJohn Forte 		/*
2997*fcf3ce44SJohn Forte 		 * hba->mbox_queueaddr = (uint32_t *)&((SLIM2 *)
2998*fcf3ce44SJohn Forte 		 * hba->slim2.virt)->mbx;
2999*fcf3ce44SJohn Forte 		 */
3000*fcf3ce44SJohn Forte 		hba->flag |= FC_SLIM2_MODE;
3001*fcf3ce44SJohn Forte 	} else {	/* SLIM 1 */
3002*fcf3ce44SJohn Forte 		mbox = FC_SLIM1_MAILBOX(hba);
3003*fcf3ce44SJohn Forte 
3004*fcf3ce44SJohn Forte #ifdef MBOX_EXT_SUPPORT
3005*fcf3ce44SJohn Forte 		if (hba->mbox_ext) {
3006*fcf3ce44SJohn Forte 			uint32_t *mbox_ext = (uint32_t *)((uint8_t *)mbox +
3007*fcf3ce44SJohn Forte 			    MBOX_EXTENSION_OFFSET);
3008*fcf3ce44SJohn Forte 			WRITE_SLIM_COPY(hba, (uint32_t *)hba->mbox_ext,
3009*fcf3ce44SJohn Forte 			    mbox_ext, (hba->mbox_ext_size / 4));
3010*fcf3ce44SJohn Forte 		}
3011*fcf3ce44SJohn Forte #endif	/* MBOX_EXT_SUPPORT */
3012*fcf3ce44SJohn Forte 
3013*fcf3ce44SJohn Forte 		/* First copy command data */
3014*fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords,
3015*fcf3ce44SJohn Forte 		    (MAILBOX_CMD_WSIZE - 1));
3016*fcf3ce44SJohn Forte 
3017*fcf3ce44SJohn Forte 		/* copy over last word, with mbxOwner set */
3018*fcf3ce44SJohn Forte 		ldata = *((volatile uint32_t *) mb);
3019*fcf3ce44SJohn Forte 		WRITE_SLIM_ADDR(hba, ((volatile uint32_t *) mbox), ldata);
3020*fcf3ce44SJohn Forte 	}
3021*fcf3ce44SJohn Forte 
3022*fcf3ce44SJohn Forte 	/* Interrupt board to do it right away */
3023*fcf3ce44SJohn Forte 	WRITE_CSR_REG(hba, FC_CA_REG(hba, hba->csr_addr), CA_MBATT);
3024*fcf3ce44SJohn Forte 
3025*fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
3026*fcf3ce44SJohn Forte 
3027*fcf3ce44SJohn Forte 	switch (flag) {
3028*fcf3ce44SJohn Forte 	case MBX_NOWAIT:
3029*fcf3ce44SJohn Forte 		return (MBX_SUCCESS);
3030*fcf3ce44SJohn Forte 
3031*fcf3ce44SJohn Forte 	case MBX_SLEEP:
3032*fcf3ce44SJohn Forte 
3033*fcf3ce44SJohn Forte 		/* Wait for completion */
3034*fcf3ce44SJohn Forte 		/* The driver clock is timing the mailbox. */
3035*fcf3ce44SJohn Forte 		/* emlxs_mb_fini() will be called externally. */
3036*fcf3ce44SJohn Forte 
3037*fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_MBOX_LOCK);
3038*fcf3ce44SJohn Forte 		while (!(mbq->flag & MBQ_COMPLETED)) {
3039*fcf3ce44SJohn Forte 			cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK);
3040*fcf3ce44SJohn Forte 		}
3041*fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_MBOX_LOCK);
3042*fcf3ce44SJohn Forte 
3043*fcf3ce44SJohn Forte 		if (mb->mbxStatus == MBX_TIMEOUT) {
3044*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
3045*fcf3ce44SJohn Forte 			    "Timeout.   %s: mb=%p tmo=%d. Sleep.",
3046*fcf3ce44SJohn Forte 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo);
3047*fcf3ce44SJohn Forte 		} else {
3048*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3049*fcf3ce44SJohn Forte 			    "Completed. %s: mb=%p status=%x Sleep.",
3050*fcf3ce44SJohn Forte 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3051*fcf3ce44SJohn Forte 			    mb->mbxStatus);
3052*fcf3ce44SJohn Forte 		}
3053*fcf3ce44SJohn Forte 
3054*fcf3ce44SJohn Forte 		break;
3055*fcf3ce44SJohn Forte 
3056*fcf3ce44SJohn Forte 	case MBX_POLL:
3057*fcf3ce44SJohn Forte 
3058*fcf3ce44SJohn Forte 		tmo_local = tmo * 2000;	/* Convert tmo seconds to 500 usec */
3059*fcf3ce44SJohn Forte 					/*   tics */
3060*fcf3ce44SJohn Forte 
3061*fcf3ce44SJohn Forte 		if (hba->state >= FC_INIT_START) {
3062*fcf3ce44SJohn Forte 			ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba,
3063*fcf3ce44SJohn Forte 			    hba->csr_addr));
3064*fcf3ce44SJohn Forte 
3065*fcf3ce44SJohn Forte 			/* Wait for command to complete */
3066*fcf3ce44SJohn Forte 			while (!(ha_copy & HA_MBATT) &&
3067*fcf3ce44SJohn Forte 			    !(mbq->flag & MBQ_COMPLETED)) {
3068*fcf3ce44SJohn Forte 				if (!hba->timer_id && (tmo_local-- == 0)) {
3069*fcf3ce44SJohn Forte 					/* self time */
3070*fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
3071*fcf3ce44SJohn Forte 					    &emlxs_hardware_error_msg,
3072*fcf3ce44SJohn Forte 					    "Mailbox Timeout: %s: mb=%p Polled",
3073*fcf3ce44SJohn Forte 					    emlxs_mb_cmd_xlate(mb->mbxCommand),
3074*fcf3ce44SJohn Forte 					    mb);
3075*fcf3ce44SJohn Forte 
3076*fcf3ce44SJohn Forte 					hba->flag |= FC_MBOX_TIMEOUT;
3077*fcf3ce44SJohn Forte 					emlxs_ffstate_change(hba, FC_ERROR);
3078*fcf3ce44SJohn Forte 					emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
3079*fcf3ce44SJohn Forte 
3080*fcf3ce44SJohn Forte 					break;
3081*fcf3ce44SJohn Forte 				}
3082*fcf3ce44SJohn Forte 				DELAYUS(500);
3083*fcf3ce44SJohn Forte 				ha_copy = READ_CSR_REG(hba,
3084*fcf3ce44SJohn Forte 				    FC_HA_REG(hba, hba->csr_addr));
3085*fcf3ce44SJohn Forte 			}
3086*fcf3ce44SJohn Forte 
3087*fcf3ce44SJohn Forte 			if (mb->mbxStatus == MBX_TIMEOUT) {
3088*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
3089*fcf3ce44SJohn Forte 				    "Timeout.   %s: mb=%p tmo=%d. Polled.",
3090*fcf3ce44SJohn Forte 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3091*fcf3ce44SJohn Forte 				    tmo);
3092*fcf3ce44SJohn Forte 
3093*fcf3ce44SJohn Forte 				break;
3094*fcf3ce44SJohn Forte 			}
3095*fcf3ce44SJohn Forte 		}
3096*fcf3ce44SJohn Forte 		/* Get first word of mailbox */
3097*fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
3098*fcf3ce44SJohn Forte 			mbox = FC_SLIM2_MAILBOX(hba);
3099*fcf3ce44SJohn Forte 			offset = (off_t)((uint64_t)(unsigned long)mbox -
3100*fcf3ce44SJohn Forte 			    (uint64_t)(unsigned long)hba->slim2.virt);
3101*fcf3ce44SJohn Forte 
3102*fcf3ce44SJohn Forte 			emlxs_mpdata_sync(hba->slim2.dma_handle, offset,
3103*fcf3ce44SJohn Forte 			    sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
3104*fcf3ce44SJohn Forte 			word0 = *((volatile uint32_t *) mbox);
3105*fcf3ce44SJohn Forte 			word0 = PCIMEM_LONG(word0);
3106*fcf3ce44SJohn Forte 		} else {
3107*fcf3ce44SJohn Forte 			mbox = FC_SLIM1_MAILBOX(hba);
3108*fcf3ce44SJohn Forte 			word0 = READ_SLIM_ADDR(hba,
3109*fcf3ce44SJohn Forte 			    ((volatile uint32_t *) mbox));
3110*fcf3ce44SJohn Forte 		}
3111*fcf3ce44SJohn Forte 
3112*fcf3ce44SJohn Forte 		/* Wait for command to complete */
3113*fcf3ce44SJohn Forte 		while ((swpmb->mbxOwner == OWN_CHIP) &&
3114*fcf3ce44SJohn Forte 		    !(mbq->flag & MBQ_COMPLETED)) {
3115*fcf3ce44SJohn Forte 			if (!hba->timer_id && (tmo_local-- == 0)) {
3116*fcf3ce44SJohn Forte 				/* self time */
3117*fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
3118*fcf3ce44SJohn Forte 				    &emlxs_hardware_error_msg,
3119*fcf3ce44SJohn Forte 				    "Mailbox Timeout: %s: mb=%p Polled.",
3120*fcf3ce44SJohn Forte 				    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3121*fcf3ce44SJohn Forte 
3122*fcf3ce44SJohn Forte 				hba->flag |= FC_MBOX_TIMEOUT;
3123*fcf3ce44SJohn Forte 				emlxs_ffstate_change(hba, FC_ERROR);
3124*fcf3ce44SJohn Forte 				emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
3125*fcf3ce44SJohn Forte 
3126*fcf3ce44SJohn Forte 				break;
3127*fcf3ce44SJohn Forte 			}
3128*fcf3ce44SJohn Forte 			DELAYUS(500);
3129*fcf3ce44SJohn Forte 
3130*fcf3ce44SJohn Forte 			/* Get first word of mailbox */
3131*fcf3ce44SJohn Forte 			if (hba->flag & FC_SLIM2_MODE) {
3132*fcf3ce44SJohn Forte 				emlxs_mpdata_sync(hba->slim2.dma_handle, offset,
3133*fcf3ce44SJohn Forte 				    sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
3134*fcf3ce44SJohn Forte 				word0 = *((volatile uint32_t *) mbox);
3135*fcf3ce44SJohn Forte 				word0 = PCIMEM_LONG(word0);
3136*fcf3ce44SJohn Forte 			} else {
3137*fcf3ce44SJohn Forte 				word0 = READ_SLIM_ADDR(hba,
3138*fcf3ce44SJohn Forte 				    ((volatile uint32_t *) mbox));
3139*fcf3ce44SJohn Forte 			}
3140*fcf3ce44SJohn Forte 
3141*fcf3ce44SJohn Forte 		}	/* while */
3142*fcf3ce44SJohn Forte 
3143*fcf3ce44SJohn Forte 		if (mb->mbxStatus == MBX_TIMEOUT) {
3144*fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
3145*fcf3ce44SJohn Forte 			    "Timeout.   %s: mb=%p tmo=%d. Polled.",
3146*fcf3ce44SJohn Forte 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo);
3147*fcf3ce44SJohn Forte 
3148*fcf3ce44SJohn Forte 			break;
3149*fcf3ce44SJohn Forte 		}
3150*fcf3ce44SJohn Forte 		/* copy results back to user */
3151*fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
3152*fcf3ce44SJohn Forte 			emlxs_mpdata_sync(hba->slim2.dma_handle, offset,
3153*fcf3ce44SJohn Forte 			    MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
3154*fcf3ce44SJohn Forte 			emlxs_pcimem_bcopy((uint32_t *)mbox, (uint32_t *)mb,
3155*fcf3ce44SJohn Forte 			    MAILBOX_CMD_BSIZE);
3156*fcf3ce44SJohn Forte 		} else {
3157*fcf3ce44SJohn Forte 			READ_SLIM_COPY(hba, (uint32_t *)mb, (uint32_t *)mbox,
3158*fcf3ce44SJohn Forte 			    MAILBOX_CMD_WSIZE);
3159*fcf3ce44SJohn Forte 		}
3160*fcf3ce44SJohn Forte 
3161*fcf3ce44SJohn Forte #ifdef MBOX_EXT_SUPPORT
3162*fcf3ce44SJohn Forte 		if (hba->mbox_ext) {
3163*fcf3ce44SJohn Forte 			uint32_t *mbox_ext = (uint32_t *)((uint8_t *)mbox +
3164*fcf3ce44SJohn Forte 			    MBOX_EXTENSION_OFFSET);
3165*fcf3ce44SJohn Forte 			off_t offset_ext = offset + MBOX_EXTENSION_OFFSET;
3166*fcf3ce44SJohn Forte 
3167*fcf3ce44SJohn Forte 			if (hba->flag & FC_SLIM2_MODE) {
3168*fcf3ce44SJohn Forte 				emlxs_mpdata_sync(hba->slim2.dma_handle,
3169*fcf3ce44SJohn Forte 				    offset_ext, hba->mbox_ext_size,
3170*fcf3ce44SJohn Forte 				    DDI_DMA_SYNC_FORKERNEL);
3171*fcf3ce44SJohn Forte 				emlxs_pcimem_bcopy(mbox_ext,
3172*fcf3ce44SJohn Forte 				    (uint32_t *)hba->mbox_ext,
3173*fcf3ce44SJohn Forte 				    hba->mbox_ext_size);
3174*fcf3ce44SJohn Forte 			} else {
3175*fcf3ce44SJohn Forte 				READ_SLIM_COPY(hba, (uint32_t *)hba->mbox_ext,
3176*fcf3ce44SJohn Forte 				    mbox_ext, (hba->mbox_ext_size / 4));
3177*fcf3ce44SJohn Forte 			}
3178*fcf3ce44SJohn Forte 		}
3179*fcf3ce44SJohn Forte #endif	/* MBOX_EXT_SUPPORT */
3180*fcf3ce44SJohn Forte 
3181*fcf3ce44SJohn Forte 		/* Sync the memory buffer */
3182*fcf3ce44SJohn Forte 		if (hba->mbox_bp) {
3183*fcf3ce44SJohn Forte 			mbox_bp = (MATCHMAP *) hba->mbox_bp;
3184*fcf3ce44SJohn Forte 			emlxs_mpdata_sync(mbox_bp->dma_handle, 0, mbox_bp->size,
3185*fcf3ce44SJohn Forte 			    DDI_DMA_SYNC_FORKERNEL);
3186*fcf3ce44SJohn Forte 		}
3187*fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3188*fcf3ce44SJohn Forte 		    "Completed. %s: mb=%p status=%x Polled.",
3189*fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mb, mb->mbxStatus);
3190*fcf3ce44SJohn Forte 
3191*fcf3ce44SJohn Forte 		/* Process the result */
3192*fcf3ce44SJohn Forte 		if (!(mbq->flag & MBQ_PASSTHRU)) {
3193*fcf3ce44SJohn Forte 			(void) emlxs_mb_handle_cmd(hba, mb);
3194*fcf3ce44SJohn Forte 		}
3195*fcf3ce44SJohn Forte 		/* Clear the attention bit */
3196*fcf3ce44SJohn Forte 		WRITE_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr), HA_MBATT);
3197*fcf3ce44SJohn Forte 
3198*fcf3ce44SJohn Forte 		/* Clean up the mailbox area */
3199*fcf3ce44SJohn Forte 		emlxs_mb_fini(hba, NULL, mb->mbxStatus);
3200*fcf3ce44SJohn Forte 
3201*fcf3ce44SJohn Forte 		break;
3202*fcf3ce44SJohn Forte 
3203*fcf3ce44SJohn Forte 	}	/* switch (flag) */
3204*fcf3ce44SJohn Forte 
3205*fcf3ce44SJohn Forte 	return (mb->mbxStatus);
3206*fcf3ce44SJohn Forte 
3207*fcf3ce44SJohn Forte } /* emlxs_mb_issue_cmd() */
3208*fcf3ce44SJohn Forte 
3209*fcf3ce44SJohn Forte 
3210*fcf3ce44SJohn Forte 
3211*fcf3ce44SJohn Forte extern char *
3212*fcf3ce44SJohn Forte emlxs_mb_cmd_xlate(uint8_t cmd)
3213*fcf3ce44SJohn Forte {
3214*fcf3ce44SJohn Forte 	static char buffer[32];
3215*fcf3ce44SJohn Forte 	uint32_t i;
3216*fcf3ce44SJohn Forte 	uint32_t count;
3217*fcf3ce44SJohn Forte 
3218*fcf3ce44SJohn Forte 	count = sizeof (emlxs_mb_cmd_table) / sizeof (emlxs_table_t);
3219*fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
3220*fcf3ce44SJohn Forte 		if (cmd == emlxs_mb_cmd_table[i].code) {
3221*fcf3ce44SJohn Forte 			return (emlxs_mb_cmd_table[i].string);
3222*fcf3ce44SJohn Forte 		}
3223*fcf3ce44SJohn Forte 	}
3224*fcf3ce44SJohn Forte 
3225*fcf3ce44SJohn Forte 	(void) sprintf(buffer, "Cmd=0x%x", cmd);
3226*fcf3ce44SJohn Forte 	return (buffer);
3227*fcf3ce44SJohn Forte 
3228*fcf3ce44SJohn Forte } /* emlxs_mb_cmd_xlate() */
3229