xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mbox.c (revision 5bbb4db2c3f208d12bf0fd11769728f9e5ba66a2)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Emulex.  All rights reserved.
24  * Use is subject to License terms.
25  */
26 
27 #include <emlxs.h>
28 
29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
30 EMLXS_MSG_DEF(EMLXS_MBOX_C);
31 
32 static void	emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOX *mb,
33 			uint32_t hbainit);
34 static void	emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mask,
35 			uint32_t ringno);
36 static void	emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOX *mb,
37 			uint32_t word0, uint32_t word1, uint32_t word2);
38 static int32_t	emlxs_mb_handle_cmd(emlxs_hba_t *hba, MAILBOX *mb);
39 static void	emlxs_mb_write_nv(emlxs_hba_t *hba, MAILBOX *mb);
40 
41 
42 emlxs_table_t emlxs_mb_cmd_table[] = {
43 	{MBX_SHUTDOWN, "SHUTDOWN"},
44 	{MBX_LOAD_SM, "LOAD_SM"},
45 	{MBX_READ_NV, "READ_NV"},
46 	{MBX_WRITE_NV, "WRITE_NV"},
47 	{MBX_RUN_BIU_DIAG, "RUN_BIU_DIAG"},
48 	{MBX_INIT_LINK, "INIT_LINK"},
49 	{MBX_DOWN_LINK, "DOWN_LINK"},
50 	{MBX_CONFIG_LINK, "CONFIG_LINK"},
51 	{MBX_PART_SLIM, "PART_SLIM"},
52 	{MBX_CONFIG_RING, "CONFIG_RING"},
53 	{MBX_RESET_RING, "RESET_RING"},
54 	{MBX_READ_CONFIG, "READ_CONFIG"},
55 	{MBX_READ_RCONFIG, "READ_RCONFIG"},
56 	{MBX_READ_SPARM, "READ_SPARM"},
57 	{MBX_READ_STATUS, "READ_STATUS"},
58 	{MBX_READ_RPI, "READ_RPI"},
59 	{MBX_READ_XRI, "READ_XRI"},
60 	{MBX_READ_REV, "READ_REV"},
61 	{MBX_READ_LNK_STAT, "READ_LNK_STAT"},
62 	{MBX_REG_LOGIN, "REG_LOGIN"},
63 	{MBX_UNREG_LOGIN, "UNREG_LOGIN"},
64 	{MBX_READ_LA, "READ_LA"},
65 	{MBX_CLEAR_LA, "CLEAR_LA"},
66 	{MBX_DUMP_MEMORY, "DUMP_MEMORY"},
67 	{MBX_DUMP_CONTEXT, "DUMP_CONTEXT"},
68 	{MBX_RUN_DIAGS, "RUN_DIAGS"},
69 	{MBX_RESTART, "RESTART"},
70 	{MBX_UPDATE_CFG, "UPDATE_CFG"},
71 	{MBX_DOWN_LOAD, "DOWN_LOAD"},
72 	{MBX_DEL_LD_ENTRY, "DEL_LD_ENTRY"},
73 	{MBX_RUN_PROGRAM, "RUN_PROGRAM"},
74 	{MBX_SET_MASK, "SET_MASK"},
75 	{MBX_SET_VARIABLE, "SET_VARIABLE"},
76 	{MBX_UNREG_D_ID, "UNREG_D_ID"},
77 	{MBX_KILL_BOARD, "KILL_BOARD"},
78 	{MBX_CONFIG_FARP, "CONFIG_FARP"},
79 	{MBX_LOAD_AREA, "LOAD_AREA"},
80 	{MBX_RUN_BIU_DIAG64, "RUN_BIU_DIAG64"},
81 	{MBX_CONFIG_PORT, "CONFIG_PORT"},
82 	{MBX_READ_SPARM64, "READ_SPARM64"},
83 	{MBX_READ_RPI64, "READ_RPI64"},
84 	{MBX_CONFIG_MSI, "CONFIG_MSI"},
85 	{MBX_CONFIG_MSIX, "CONFIG_MSIX"},
86 	{MBX_REG_LOGIN64, "REG_LOGIN64"},
87 	{MBX_READ_LA64, "READ_LA64"},
88 	{MBX_FLASH_WR_ULA, "FLASH_WR_ULA"},
89 	{MBX_SET_DEBUG, "SET_DEBUG"},
90 	{MBX_GET_DEBUG, "GET_DEBUG"},
91 	{MBX_LOAD_EXP_ROM, "LOAD_EXP_ROM"},
92 	{MBX_BEACON, "BEACON"},
93 	{MBX_CONFIG_HBQ, "CONFIG_HBQ"},	/* SLI3 */
94 	{MBX_REG_VPI, "REG_VPI"},	/* NPIV */
95 	{MBX_ASYNC_EVENT, "ASYNC_EVENT"},
96 	{MBX_HEARTBEAT, "HEARTBEAT"},
97 	{MBX_READ_EVENT_LOG_STATUS, "READ_EVENT_LOG_STATUS"},
98 	{MBX_READ_EVENT_LOG, "READ_EVENT_LOG"},
99 	{MBX_WRITE_EVENT_LOG, "WRITE_EVENT_LOG"},
100 	{MBX_NV_LOG, "NV_LOG"},
101 	{MBX_PORT_CAPABILITIES, "PORT_CAPABILITIES"},
102 	{MBX_IOV_CONTROL, "IOV_CONTROL"},
103 	{MBX_IOV_MBX, "IOV_MBX"}
104 };	/* emlxs_mb_cmd_table */
105 
106 
107 /*ARGSUSED*/
108 extern void
109 emlxs_mb_async_event(emlxs_hba_t *hba, MAILBOX *mb)
110 {
111 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
112 
113 	mb->mbxCommand = MBX_ASYNC_EVENT;
114 	mb->mbxOwner = OWN_HOST;
115 	mb->un.varWords[0] = FC_ELS_RING;
116 
117 	return;
118 
119 } /* emlxs_mb_async_event() */
120 
121 
122 /*ARGSUSED*/
123 extern void
124 emlxs_mb_heartbeat(emlxs_hba_t *hba, MAILBOX *mb)
125 {
126 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
127 
128 	mb->mbxCommand = MBX_HEARTBEAT;
129 	mb->mbxOwner = OWN_HOST;
130 
131 	return;
132 
133 } /* emlxs_mb_heartbeat() */
134 
135 
136 #ifdef MSI_SUPPORT
137 
138 /*ARGSUSED*/
139 extern void
140 emlxs_mb_config_msi(emlxs_hba_t *hba, MAILBOX *mb, uint32_t *intr_map,
141     uint32_t intr_count)
142 {
143 	uint32_t i;
144 	uint32_t mask;
145 
146 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
147 
148 	mb->mbxCommand = MBX_CONFIG_MSI;
149 
150 	/* Set the default message id to zero */
151 	mb->un.varCfgMSI.defaultPresent = 1;
152 	mb->un.varCfgMSI.defaultMessageNumber = 0;
153 
154 	for (i = 1; i < intr_count; i++) {
155 		mask = intr_map[i];
156 
157 		mb->un.varCfgMSI.attConditions |= mask;
158 
159 #ifdef EMLXS_BIG_ENDIAN
160 		if (mask & HA_R0ATT) {
161 			mb->un.varCfgMSI.messageNumberByHA[3] = i;
162 		}
163 		if (mask & HA_R1ATT) {
164 			mb->un.varCfgMSI.messageNumberByHA[7] = i;
165 		}
166 		if (mask & HA_R2ATT) {
167 			mb->un.varCfgMSI.messageNumberByHA[11] = i;
168 		}
169 		if (mask & HA_R3ATT) {
170 			mb->un.varCfgMSI.messageNumberByHA[15] = i;
171 		}
172 		if (mask & HA_LATT) {
173 			mb->un.varCfgMSI.messageNumberByHA[29] = i;
174 		}
175 		if (mask & HA_MBATT) {
176 			mb->un.varCfgMSI.messageNumberByHA[30] = i;
177 		}
178 		if (mask & HA_ERATT) {
179 			mb->un.varCfgMSI.messageNumberByHA[31] = i;
180 		}
181 #endif	/* EMLXS_BIG_ENDIAN */
182 
183 #ifdef EMLXS_LITTLE_ENDIAN
184 		/* Accounts for half word swap of LE architecture */
185 		if (mask & HA_R0ATT) {
186 			mb->un.varCfgMSI.messageNumberByHA[2] = i;
187 		}
188 		if (mask & HA_R1ATT) {
189 			mb->un.varCfgMSI.messageNumberByHA[6] = i;
190 		}
191 		if (mask & HA_R2ATT) {
192 			mb->un.varCfgMSI.messageNumberByHA[10] = i;
193 		}
194 		if (mask & HA_R3ATT) {
195 			mb->un.varCfgMSI.messageNumberByHA[14] = i;
196 		}
197 		if (mask & HA_LATT) {
198 			mb->un.varCfgMSI.messageNumberByHA[28] = i;
199 		}
200 		if (mask & HA_MBATT) {
201 			mb->un.varCfgMSI.messageNumberByHA[31] = i;
202 		}
203 		if (mask & HA_ERATT) {
204 			mb->un.varCfgMSI.messageNumberByHA[30] = i;
205 		}
206 #endif	/* EMLXS_LITTLE_ENDIAN */
207 	}
208 
209 	mb->mbxOwner = OWN_HOST;
210 
211 	return;
212 
213 } /* emlxs_mb_config_msi() */
214 
215 
216 /*ARGSUSED*/
217 extern void
218 emlxs_mb_config_msix(emlxs_hba_t *hba, MAILBOX *mb, uint32_t *intr_map,
219     uint32_t intr_count)
220 {
221 	uint32_t i;
222 	uint32_t mask;
223 
224 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
225 
226 	mb->mbxCommand = MBX_CONFIG_MSIX;
227 
228 	/* Set the default message id to zero */
229 	mb->un.varCfgMSIX.defaultPresent = 1;
230 	mb->un.varCfgMSIX.defaultMessageNumber = 0;
231 
232 	for (i = 1; i < intr_count; i++) {
233 		mask = intr_map[i];
234 
235 		mb->un.varCfgMSIX.attConditions1 |= mask;
236 
237 #ifdef EMLXS_BIG_ENDIAN
238 		if (mask & HA_R0ATT) {
239 			mb->un.varCfgMSIX.messageNumberByHA[3] = i;
240 		}
241 		if (mask & HA_R1ATT) {
242 			mb->un.varCfgMSIX.messageNumberByHA[7] = i;
243 		}
244 		if (mask & HA_R2ATT) {
245 			mb->un.varCfgMSIX.messageNumberByHA[11] = i;
246 		}
247 		if (mask & HA_R3ATT) {
248 			mb->un.varCfgMSIX.messageNumberByHA[15] = i;
249 		}
250 		if (mask & HA_LATT) {
251 			mb->un.varCfgMSIX.messageNumberByHA[29] = i;
252 		}
253 		if (mask & HA_MBATT) {
254 			mb->un.varCfgMSIX.messageNumberByHA[30] = i;
255 		}
256 		if (mask & HA_ERATT) {
257 			mb->un.varCfgMSIX.messageNumberByHA[31] = i;
258 		}
259 #endif	/* EMLXS_BIG_ENDIAN */
260 
261 #ifdef EMLXS_LITTLE_ENDIAN
262 		/* Accounts for word swap of LE architecture */
263 		if (mask & HA_R0ATT) {
264 			mb->un.varCfgMSIX.messageNumberByHA[0] = i;
265 		}
266 		if (mask & HA_R1ATT) {
267 			mb->un.varCfgMSIX.messageNumberByHA[4] = i;
268 		}
269 		if (mask & HA_R2ATT) {
270 			mb->un.varCfgMSIX.messageNumberByHA[8] = i;
271 		}
272 		if (mask & HA_R3ATT) {
273 			mb->un.varCfgMSIX.messageNumberByHA[12] = i;
274 		}
275 		if (mask & HA_LATT) {
276 			mb->un.varCfgMSIX.messageNumberByHA[30] = i;
277 		}
278 		if (mask & HA_MBATT) {
279 			mb->un.varCfgMSIX.messageNumberByHA[29] = i;
280 		}
281 		if (mask & HA_ERATT) {
282 			mb->un.varCfgMSIX.messageNumberByHA[28] = i;
283 		}
284 #endif	/* EMLXS_LITTLE_ENDIAN */
285 	}
286 
287 	mb->mbxOwner = OWN_HOST;
288 
289 	return;
290 
291 } /* emlxs_mb_config_msix() */
292 
293 
294 #endif	/* MSI_SUPPORT */
295 
296 
297 /*ARGSUSED*/
298 extern void
299 emlxs_mb_reset_ring(emlxs_hba_t *hba, MAILBOX *mb, uint32_t ringno)
300 {
301 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
302 
303 	mb->mbxCommand = MBX_RESET_RING;
304 	mb->un.varRstRing.ring_no = ringno;
305 	mb->mbxOwner = OWN_HOST;
306 
307 	return;
308 
309 } /* emlxs_mb_reset_ring() */
310 
311 
312 
313 /*
314  * emlxs_mb_dump_vpd  Issue a DUMP MEMORY mailbox command
315  */
316 /*ARGSUSED*/
317 extern void
318 emlxs_mb_dump_vpd(emlxs_hba_t *hba, MAILBOX *mb, uint32_t offset)
319 {
320 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
321 
322 	/*
323 	 * Setup to dump VPD region
324 	 */
325 	mb->mbxCommand = MBX_DUMP_MEMORY;
326 	mb->un.varDmp.cv = 1;
327 	mb->un.varDmp.type = DMP_NV_PARAMS;
328 	mb->un.varDmp.entry_index = offset;
329 	mb->un.varDmp.region_id = DMP_VPD_REGION;
330 
331 	/* limited by mailbox size */
332 	mb->un.varDmp.word_cnt = DMP_VPD_DUMP_WCOUNT;
333 
334 	mb->un.varDmp.co = 0;
335 	mb->un.varDmp.resp_offset = 0;
336 	mb->mbxOwner = OWN_HOST;
337 
338 } /* emlxs_mb_dump_vpd() */
339 
340 
341 /*ARGSUSED*/
342 extern void
343 emlxs_mb_dump(emlxs_hba_t *hba, MAILBOX *mb, uint32_t offset, uint32_t words)
344 {
345 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
346 
347 	mb->mbxCommand = MBX_DUMP_MEMORY;
348 	mb->un.varDmp.type = DMP_MEM_REG;
349 	mb->un.varDmp.word_cnt = words;
350 	mb->un.varDmp.base_adr = offset;
351 
352 	mb->un.varDmp.co = 0;
353 	mb->un.varDmp.resp_offset = 0;
354 	mb->mbxOwner = OWN_HOST;
355 
356 	return;
357 
358 } /* emlxs_mb_dump() */
359 
360 
361 
362 /*
363  *  emlxs_mb_read_nv  Issue a READ NVPARAM mailbox command
364  */
365 /*ARGSUSED*/
366 extern void
367 emlxs_mb_read_nv(emlxs_hba_t *hba, MAILBOX *mb)
368 {
369 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
370 
371 	mb->mbxCommand = MBX_READ_NV;
372 	mb->mbxOwner = OWN_HOST;
373 } /* End emlxs_mb_read_nv */
374 
375 
376 /*
377  * emlxs_mb_read_rev  Issue a READ REV mailbox command
378  */
379 /*ARGSUSED*/
380 extern void
381 emlxs_mb_read_rev(emlxs_hba_t *hba, MAILBOX *mb, uint32_t v3)
382 {
383 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
384 
385 	mb->un.varRdRev.cv = 1;
386 
387 	if (v3) {
388 		mb->un.varRdRev.cv3 = 1;
389 	}
390 
391 	mb->mbxCommand = MBX_READ_REV;
392 	mb->mbxOwner = OWN_HOST;
393 } /* End emlxs_mb_read_rev */
394 
395 
396 /*
397  * emlxs_mb_run_biu_diag  Issue a RUN_BIU_DIAG mailbox command
398  */
399 /*ARGSUSED*/
400 extern uint32_t
401 emlxs_mb_run_biu_diag(emlxs_hba_t *hba, MAILBOX *mb, uint64_t out,
402     uint64_t in)
403 {
404 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
405 
406 	mb->mbxCommand = MBX_RUN_BIU_DIAG64;
407 	mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE;
408 	mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = putPaddrHigh(out);
409 	mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = putPaddrLow(out);
410 	mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE;
411 	mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = putPaddrHigh(in);
412 	mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = putPaddrLow(in);
413 	mb->mbxOwner = OWN_HOST;
414 
415 	return (0);
416 } /* End emlxs_mb_run_biu_diag */
417 
418 
419 /*
420  *  emlxs_mb_read_la  Issue a READ LA mailbox command
421  */
422 extern uint32_t
423 emlxs_mb_read_la(emlxs_hba_t *hba, MAILBOX *mb)
424 {
425 	MATCHMAP *mp;
426 
427 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
428 
429 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
430 		mb->mbxCommand = MBX_READ_LA64;
431 
432 		return (1);
433 	}
434 
435 	mb->mbxCommand = MBX_READ_LA64;
436 	mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
437 	mb->un.varReadLA.un.lilpBde64.addrHigh = putPaddrHigh(mp->phys);
438 	mb->un.varReadLA.un.lilpBde64.addrLow = putPaddrLow(mp->phys);
439 	mb->mbxOwner = OWN_HOST;
440 
441 	/*
442 	 * save address for completion
443 	 */
444 	((MAILBOXQ *)mb)->bp = (uint8_t *)mp;
445 
446 	return (0);
447 
448 } /* emlxs_mb_read_la() */
449 
450 
451 /*
452  *  emlxs_mb_clear_la  Issue a CLEAR LA mailbox command
453  */
454 extern void
455 emlxs_mb_clear_la(emlxs_hba_t *hba, MAILBOX *mb)
456 {
457 #ifdef FC_RPI_CHECK
458 	emlxs_rpi_check(hba);
459 #endif	/* FC_RPI_CHECK */
460 
461 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
462 
463 	mb->un.varClearLA.eventTag = hba->link_event_tag;
464 	mb->mbxCommand = MBX_CLEAR_LA;
465 	mb->mbxOwner = OWN_HOST;
466 
467 	return;
468 
469 } /* End emlxs_mb_clear_la */
470 
471 
472 /*
473  * emlxs_mb_read_status  Issue a READ STATUS mailbox command
474  */
475 /*ARGSUSED*/
476 extern void
477 emlxs_mb_read_status(emlxs_hba_t *hba, MAILBOX *mb)
478 {
479 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
480 
481 	mb->mbxCommand = MBX_READ_STATUS;
482 	mb->mbxOwner = OWN_HOST;
483 } /* End fc_read_status */
484 
485 /*
486  * emlxs_mb_read_lnk_stat  Issue a LINK STATUS mailbox command
487  */
488 /*ARGSUSED*/
489 extern void
490 emlxs_mb_read_lnk_stat(emlxs_hba_t *hba, MAILBOX *mb)
491 {
492 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
493 
494 	mb->mbxCommand = MBX_READ_LNK_STAT;
495 	mb->mbxOwner = OWN_HOST;
496 } /* End emlxs_mb_read_lnk_stat */
497 
498 
499 /*
500  * emlxs_mb_write_nv  Issue a WRITE NVPARAM mailbox command
501  */
502 static void
503 emlxs_emb_mb_write_nv(emlxs_hba_t *hba, MAILBOX *mb)
504 {
505 	int32_t		i;
506 	emlxs_config_t	*cfg = &CFG;
507 
508 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
509 
510 	bcopy((void *)&hba->wwnn,
511 	    (void *)mb->un.varWTnvp.nodename, sizeof (NAME_TYPE));
512 
513 	bcopy((void *)&hba->wwpn,
514 	    (void *)mb->un.varWTnvp.portname, sizeof (NAME_TYPE));
515 
516 	mb->un.varWTnvp.pref_DID = 0;
517 	mb->un.varWTnvp.hardAL_PA = (uint8_t)cfg[CFG_ASSIGN_ALPA].current;
518 	mb->un.varWTnvp.rsvd1[0] = 0xffffffff;
519 	mb->un.varWTnvp.rsvd1[1] = 0xffffffff;
520 	mb->un.varWTnvp.rsvd1[2] = 0xffffffff;
521 	for (i = 0; i < 21; i++) {
522 		mb->un.varWTnvp.rsvd3[i] = 0xffffffff;
523 	}
524 
525 	mb->mbxCommand = MBX_WRITE_NV;
526 	mb->mbxOwner = OWN_HOST;
527 } /* End emlxs_mb_write_nv */
528 
529 
530 /*
531  * emlxs_mb_part_slim  Issue a PARTITION SLIM mailbox command
532  */
533 static void
534 emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOX *mb, uint32_t hbainit)
535 {
536 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
537 
538 
539 	mb->un.varSlim.numRing = hba->ring_count;
540 	mb->un.varSlim.hbainit = hbainit;
541 	mb->mbxCommand = MBX_PART_SLIM;
542 	mb->mbxOwner = OWN_HOST;
543 } /* End emlxs_mb_part_slim */
544 
545 
546 /*
547  * emlxs_mb_config_ring  Issue a CONFIG RING mailbox command
548  */
549 extern void
550 emlxs_mb_config_ring(emlxs_hba_t *hba, int32_t ring, MAILBOX *mb)
551 {
552 	int32_t i;
553 	int32_t j;
554 
555 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
556 
557 	j = 0;
558 	for (i = 0; i < ring; i++) {
559 		j += hba->ring_masks[i];
560 	}
561 
562 	for (i = 0; i < hba->ring_masks[ring]; i++) {
563 		if ((j + i) >= 6) {
564 			break;
565 		}
566 
567 		mb->un.varCfgRing.rrRegs[i].rval  = hba->ring_rval[j + i];
568 		mb->un.varCfgRing.rrRegs[i].rmask = hba->ring_rmask[j + i];
569 
570 		mb->un.varCfgRing.rrRegs[i].tval  = hba->ring_tval[j + i];
571 		mb->un.varCfgRing.rrRegs[i].tmask = hba->ring_tmask[j + i];
572 	}
573 
574 	mb->un.varCfgRing.ring = ring;
575 	mb->un.varCfgRing.profile = 0;
576 	mb->un.varCfgRing.maxOrigXchg = 0;
577 	mb->un.varCfgRing.maxRespXchg = 0;
578 	mb->un.varCfgRing.recvNotify = 1;
579 	mb->un.varCfgRing.numMask = hba->ring_masks[ring];
580 	mb->mbxCommand = MBX_CONFIG_RING;
581 	mb->mbxOwner = OWN_HOST;
582 
583 	return;
584 
585 } /* End emlxs_mb_config_ring */
586 
587 
588 /*
589  *  emlxs_mb_config_link  Issue a CONFIG LINK mailbox command
590  */
591 extern void
592 emlxs_mb_config_link(emlxs_hba_t *hba, MAILBOX *mb)
593 {
594 	emlxs_port_t   *port = &PPORT;
595 	emlxs_config_t *cfg = &CFG;
596 
597 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
598 
599 	/*
600 	 * NEW_FEATURE SLI-2, Coalescing Response Feature.
601 	 */
602 	if (cfg[CFG_CR_DELAY].current) {
603 		mb->un.varCfgLnk.cr = 1;
604 		mb->un.varCfgLnk.ci = 1;
605 		mb->un.varCfgLnk.cr_delay = cfg[CFG_CR_DELAY].current;
606 		mb->un.varCfgLnk.cr_count = cfg[CFG_CR_COUNT].current;
607 	}
608 
609 	if (cfg[CFG_ACK0].current)
610 		mb->un.varCfgLnk.ack0_enable = 1;
611 
612 	mb->un.varCfgLnk.myId = port->did;
613 	mb->un.varCfgLnk.edtov = hba->fc_edtov;
614 	mb->un.varCfgLnk.arbtov = hba->fc_arbtov;
615 	mb->un.varCfgLnk.ratov = hba->fc_ratov;
616 	mb->un.varCfgLnk.rttov = hba->fc_rttov;
617 	mb->un.varCfgLnk.altov = hba->fc_altov;
618 	mb->un.varCfgLnk.crtov = hba->fc_crtov;
619 	mb->un.varCfgLnk.citov = hba->fc_citov;
620 	mb->mbxCommand = MBX_CONFIG_LINK;
621 	mb->mbxOwner = OWN_HOST;
622 
623 	return;
624 
625 } /* emlxs_mb_config_link() */
626 
627 
628 /*
629  *  emlxs_mb_init_link  Issue an INIT LINK mailbox command
630  */
631 extern void
632 emlxs_mb_init_link(emlxs_hba_t *hba, MAILBOX *mb, uint32_t topology,
633     uint32_t linkspeed)
634 {
635 	emlxs_vpd_t	*vpd = &VPD;
636 	emlxs_config_t	*cfg = &CFG;
637 
638 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
639 
640 	switch (topology) {
641 	case FLAGS_LOCAL_LB:
642 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
643 		mb->un.varInitLnk.link_flags |= FLAGS_LOCAL_LB;
644 		break;
645 	case FLAGS_TOPOLOGY_MODE_LOOP_PT:
646 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
647 		mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
648 		break;
649 	case FLAGS_TOPOLOGY_MODE_PT_PT:
650 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
651 		break;
652 	case FLAGS_TOPOLOGY_MODE_LOOP:
653 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
654 		break;
655 	case FLAGS_TOPOLOGY_MODE_PT_LOOP:
656 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
657 		mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
658 		break;
659 	}
660 
661 	if (cfg[CFG_LILP_ENABLE].current == 0) {
662 		/* Disable LIRP/LILP support */
663 		mb->un.varInitLnk.link_flags |= FLAGS_LIRP_LILP;
664 	}
665 
666 	/*
667 	 * Setting up the link speed
668 	 */
669 	switch (linkspeed) {
670 	case 0:
671 		break;
672 
673 	case 1:
674 		if (!(vpd->link_speed & LMT_1GB_CAPABLE)) {
675 			linkspeed = 0;
676 		}
677 		break;
678 
679 	case 2:
680 		if (!(vpd->link_speed & LMT_2GB_CAPABLE)) {
681 			linkspeed = 0;
682 		}
683 		break;
684 
685 	case 4:
686 		if (!(vpd->link_speed & LMT_4GB_CAPABLE)) {
687 			linkspeed = 0;
688 		}
689 		break;
690 
691 	case 8:
692 		if (!(vpd->link_speed & LMT_8GB_CAPABLE)) {
693 			linkspeed = 0;
694 		}
695 		break;
696 
697 	case 10:
698 		if (!(vpd->link_speed & LMT_10GB_CAPABLE)) {
699 			linkspeed = 0;
700 		}
701 		break;
702 
703 	default:
704 		linkspeed = 0;
705 		break;
706 
707 	}
708 
709 	if ((linkspeed > 0) && (vpd->feaLevelHigh >= 0x02)) {
710 		mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
711 		mb->un.varInitLnk.link_speed = linkspeed;
712 	}
713 
714 	mb->un.varInitLnk.link_flags |= FLAGS_PREABORT_RETURN;
715 
716 	mb->un.varInitLnk.fabric_AL_PA =
717 	    (uint8_t)cfg[CFG_ASSIGN_ALPA].current;
718 	mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK;
719 	mb->mbxOwner = OWN_HOST;
720 
721 
722 	return;
723 
724 } /* emlxs_mb_init_link() */
725 
726 
727 /*
728  *  emlxs_mb_down_link  Issue a DOWN LINK mailbox command
729  */
730 /*ARGSUSED*/
731 extern void
732 emlxs_mb_down_link(emlxs_hba_t *hba, MAILBOX *mb)
733 {
734 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
735 
736 	mb->mbxCommand = MBX_DOWN_LINK;
737 	mb->mbxOwner = OWN_HOST;
738 
739 	return;
740 
741 } /* emlxs_mb_down_link() */
742 
743 
744 /*
745  * emlxs_mb_read_sparam  Issue a READ SPARAM mailbox command
746  */
747 extern uint32_t
748 emlxs_mb_read_sparam(emlxs_hba_t *hba, MAILBOX *mb)
749 {
750 	MATCHMAP *mp;
751 
752 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
753 
754 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
755 		mb->mbxCommand = MBX_READ_SPARM64;
756 
757 		return (1);
758 	}
759 
760 	mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
761 	mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys);
762 	mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys);
763 	mb->mbxCommand = MBX_READ_SPARM64;
764 	mb->mbxOwner = OWN_HOST;
765 
766 	/*
767 	 * save address for completion
768 	 */
769 	((MAILBOXQ *)mb)->bp = (uint8_t *)mp;
770 
771 	return (0);
772 
773 } /* emlxs_mb_read_sparam() */
774 
775 
776 /*
777  * emlxs_mb_read_rpi    Issue a READ RPI mailbox command
778  */
779 /*ARGSUSED*/
780 extern uint32_t
781 emlxs_mb_read_rpi(emlxs_hba_t *hba, uint32_t rpi, MAILBOX *mb,
782     uint32_t flag)
783 {
784 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
785 
786 	/*
787 	 * Set flag to issue action on cmpl
788 	 */
789 	mb->un.varWords[30] = flag;
790 	mb->un.varRdRPI.reqRpi = (volatile uint16_t) rpi;
791 	mb->mbxCommand = MBX_READ_RPI64;
792 	mb->mbxOwner = OWN_HOST;
793 
794 	return (0);
795 } /* End emlxs_mb_read_rpi */
796 
797 
798 /*
799  * emlxs_mb_read_xri    Issue a READ XRI mailbox command
800  */
801 /*ARGSUSED*/
802 extern uint32_t
803 emlxs_mb_read_xri(emlxs_hba_t *hba, uint32_t xri, MAILBOX *mb,
804     uint32_t flag)
805 {
806 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
807 
808 	/*
809 	 * Set flag to issue action on cmpl
810 	 */
811 	mb->un.varWords[30] = flag;
812 	mb->un.varRdXRI.reqXri = (volatile uint16_t)xri;
813 	mb->mbxCommand = MBX_READ_XRI;
814 	mb->mbxOwner = OWN_HOST;
815 
816 	return (0);
817 } /* End emlxs_mb_read_xri */
818 
819 
820 /*ARGSUSED*/
821 extern int32_t
822 emlxs_mb_check_sparm(emlxs_hba_t *hba, SERV_PARM *nsp)
823 {
824 	uint32_t nsp_value;
825 	uint32_t *iptr;
826 
827 	if (nsp->cmn.fPort) {
828 		return (0);
829 	}
830 
831 	/* Validate the service parameters */
832 	iptr = (uint32_t *)&nsp->portName;
833 	if (iptr[0] == 0 && iptr[1] == 0) {
834 		return (1);
835 	}
836 
837 	iptr = (uint32_t *)&nsp->nodeName;
838 	if (iptr[0] == 0 && iptr[1] == 0) {
839 		return (2);
840 	}
841 
842 	if (nsp->cls2.classValid) {
843 		nsp_value =
844 		    ((nsp->cls2.rcvDataSizeMsb & 0x0f) << 8) | nsp->cls2.
845 		    rcvDataSizeLsb;
846 
847 		/* If the receive data length is zero then set it to */
848 		/* the CSP value */
849 		if (!nsp_value) {
850 			nsp->cls2.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb;
851 			nsp->cls2.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb;
852 			return (0);
853 		}
854 	}
855 
856 	if (nsp->cls3.classValid) {
857 		nsp_value =
858 		    ((nsp->cls3.rcvDataSizeMsb & 0x0f) << 8) | nsp->cls3.
859 		    rcvDataSizeLsb;
860 
861 		/* If the receive data length is zero then set it to */
862 		/* the CSP value */
863 		if (!nsp_value) {
864 			nsp->cls3.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb;
865 			nsp->cls3.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb;
866 			return (0);
867 		}
868 	}
869 
870 	return (0);
871 
872 } /* emlxs_mb_check_sparm() */
873 
874 
875 /*
876  * emlxs_mb_reg_did  Issue a REG_LOGIN mailbox command
877  */
878 extern uint32_t
879 emlxs_mb_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param,
880     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
881 {
882 	emlxs_hba_t	*hba = HBA;
883 	MATCHMAP	*mp;
884 	MAILBOXQ	*mbq;
885 	MAILBOX		*mb;
886 	uint32_t	rval;
887 
888 	/* Check for invalid node ids to register */
889 	if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
890 		return (1);
891 	}
892 
893 	if (did & 0xff000000) {
894 		return (1);
895 	}
896 
897 	if ((rval = emlxs_mb_check_sparm(hba, param))) {
898 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
899 		    "Invalid service parameters. did=%06x rval=%d", did,
900 		    rval);
901 
902 		return (1);
903 	}
904 
905 	/* Check if the node limit has been reached */
906 	if (port->node_count >= hba->max_nodes) {
907 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
908 		    "Limit reached. did=%06x count=%d", did,
909 		    port->node_count);
910 
911 		return (1);
912 	}
913 
914 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
915 		return (1);
916 	}
917 
918 	/* Build login request */
919 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0) {
920 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
921 		return (1);
922 	}
923 
924 	bcopy((void *)param, (void *)mp->virt, sizeof (SERV_PARM));
925 
926 	mb = (MAILBOX *)mbq->mbox;
927 	mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
928 	mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys);
929 	mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys);
930 	mb->un.varRegLogin.rpi = 0;
931 	mb->un.varRegLogin.did = did;
932 	mb->un.varWords[30] = 0;	/* flags */
933 	mb->mbxCommand = MBX_REG_LOGIN64;
934 	mb->mbxOwner = OWN_HOST;
935 
936 #ifdef SLI3_SUPPORT
937 	mb->un.varRegLogin.vpi = port->vpi;
938 #endif	/* SLI3_SUPPORT */
939 
940 	mbq->sbp = (uint8_t *)sbp;
941 	mbq->ubp = (uint8_t *)ubp;
942 	mbq->iocbq = (uint8_t *)iocbq;
943 	mbq->bp = (uint8_t *)mp;
944 
945 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
946 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
947 	}
948 
949 	return (0);
950 
951 } /* emlxs_mb_reg_did() */
952 
953 /*
954  * emlxs_mb_unreg_rpi  Issue a UNREG_LOGIN mailbox command
955  */
956 extern uint32_t
957 emlxs_mb_unreg_rpi(emlxs_port_t *port, uint32_t rpi, emlxs_buf_t *sbp,
958     fc_unsol_buf_t *ubp, IOCBQ *iocbq)
959 {
960 	emlxs_hba_t	*hba = HBA;
961 	MAILBOXQ	*mbq;
962 	MAILBOX		*mb;
963 	NODELIST	*ndlp;
964 
965 	if (rpi != 0xffff) {
966 		/* Make sure the node does already exist */
967 		ndlp = emlxs_node_find_rpi(port, rpi);
968 
969 
970 		if (ndlp) {
971 			/*
972 			 * If we just unregistered the host node then
973 			 * clear the host DID
974 			 */
975 			if (ndlp->nlp_DID == port->did) {
976 				port->did = 0;
977 			}
978 
979 			/* remove it */
980 			emlxs_node_rm(port, ndlp);
981 
982 		} else {
983 			return (1);
984 		}
985 	} else {	/* Unreg all */
986 
987 		emlxs_node_destroy_all(port);
988 	}
989 
990 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
991 		return (1);
992 	}
993 
994 	mb = (MAILBOX *)mbq->mbox;
995 	mb->un.varUnregLogin.rpi = (uint16_t)rpi;
996 
997 #ifdef SLI3_SUPPORT
998 	mb->un.varUnregLogin.vpi = port->vpi;
999 #endif  /* SLI3_SUPPORT */
1000 
1001 	mb->mbxCommand = MBX_UNREG_LOGIN;
1002 	mb->mbxOwner = OWN_HOST;
1003 	mbq->sbp = (uint8_t *)sbp;
1004 	mbq->ubp = (uint8_t *)ubp;
1005 	mbq->iocbq = (uint8_t *)iocbq;
1006 
1007 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
1008 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
1009 	}
1010 
1011 	return (0);
1012 } /* emlxs_mb_unreg_rpi() */
1013 
1014 /*
1015  * emlxs_mb_unreg_did  Issue a UNREG_DID mailbox command
1016  */
1017 extern uint32_t
1018 emlxs_mb_unreg_did(emlxs_port_t *port, uint32_t did, emlxs_buf_t *sbp,
1019     fc_unsol_buf_t *ubp, IOCBQ *iocbq)
1020 {
1021 	emlxs_hba_t	*hba = HBA;
1022 	NODELIST	*ndlp;
1023 	MAILBOXQ	*mbq;
1024 	MAILBOX		*mb;
1025 
1026 	/*
1027 	 * Unregister all default RPIs if did == 0xffffffff
1028 	 */
1029 	if (did != 0xffffffff) {
1030 		/* Check for base node */
1031 		if (did == Bcast_DID) {
1032 			/* just flush base node */
1033 			(void) emlxs_tx_node_flush(port, &port->node_base,
1034 			    0, 0, 0);
1035 			(void) emlxs_chipq_node_flush(port, 0,
1036 			    &port->node_base, 0);
1037 
1038 			/* Return now */
1039 			return (1);
1040 		}
1041 
1042 
1043 		/*
1044 		 * A zero DID means that we are trying to unreg the host node
1045 		 * after a link bounce
1046 		 */
1047 
1048 		/*
1049 		 * If the prev_did == 0 then the adapter has been reset and
1050 		 * there is no need in unregistering
1051 		 */
1052 
1053 		/*
1054 		 * If the prev_did != 0 then we can look for the hosts
1055 		 * last known DID node
1056 		 */
1057 
1058 		if (did == 0) {
1059 			if (port->prev_did == 0) {
1060 				return (1);
1061 			}
1062 
1063 			did = port->prev_did;
1064 		}
1065 
1066 		/* Make sure the node does already exist */
1067 		ndlp = emlxs_node_find_did(port, did);
1068 
1069 
1070 		if (ndlp) {
1071 			/* remove it */
1072 			emlxs_node_rm(port, ndlp);
1073 
1074 			/*
1075 			 * If we just unregistered the host node then
1076 			 * clear the host DID
1077 			 */
1078 			if (did == port->did) {
1079 				port->did = 0;
1080 			}
1081 
1082 		} else {
1083 			return (1);
1084 		}
1085 	}
1086 
1087 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
1088 		return (1);
1089 	}
1090 
1091 	mb = (MAILBOX *)mbq->mbox;
1092 	mb->un.varUnregDID.did = did;
1093 
1094 #ifdef SLI3_SUPPORT
1095 	mb->un.varUnregDID.vpi = port->vpi;
1096 #endif	/* SLI3_SUPPORT */
1097 
1098 	mb->mbxCommand = MBX_UNREG_D_ID;
1099 	mb->mbxOwner = OWN_HOST;
1100 	mbq->sbp = (uint8_t *)sbp;
1101 	mbq->ubp = (uint8_t *)ubp;
1102 	mbq->iocbq = (uint8_t *)iocbq;
1103 
1104 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
1105 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
1106 	}
1107 
1108 	return (0);
1109 
1110 } /* End emlxs_mb_unreg_did */
1111 
1112 
1113 /*
1114  * emlxs_mb_set_mask   Issue a SET MASK mailbox command
1115  */
1116 /*ARGSUSED*/
1117 static void
1118 emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mask,
1119     uint32_t ringno)
1120 {
1121 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1122 
1123 	mb->un.varWords[0] = 0x11223344;	/* set passwd */
1124 	mb->un.varWords[1] = mask;	/* set mask */
1125 	mb->un.varWords[2] = ringno;	/* set ringno */
1126 	mb->mbxCommand = MBX_SET_MASK;
1127 	mb->mbxOwner = OWN_HOST;
1128 } /* End emlxs_mb_set_mask */
1129 
1130 
1131 /*
1132  * emlxs_mb_set_debug  Issue a special debug mailbox command
1133  */
1134 /*ARGSUSED*/
1135 static void
1136 emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOX *mb, uint32_t word0,
1137     uint32_t word1, uint32_t word2)
1138 {
1139 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1140 
1141 	mb->un.varWords[0] = word0;
1142 	mb->un.varWords[1] = word1;
1143 	mb->un.varWords[2] = word2;
1144 	mb->mbxCommand = MBX_SET_DEBUG;
1145 	mb->mbxOwner = OWN_HOST;
1146 } /* End emlxs_mb_set_debug */
1147 
1148 
1149 /*
1150  * emlxs_mb_set_var   Issue a special debug mbox command to write slim
1151  */
1152 /*ARGSUSED*/
1153 extern void
1154 emlxs_mb_set_var(emlxs_hba_t *hba, MAILBOX *mb, uint32_t addr,
1155     uint32_t value)
1156 {
1157 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1158 
1159 	/* addr = 0x090597 is AUTO ABTS disable for ELS commands */
1160 	/* addr = 0x052198 is DELAYED ABTS enable for ELS commands */
1161 	/* addr = 0x100506 is for setting PCI MAX READ value */
1162 
1163 	/*
1164 	 * Always turn on DELAYED ABTS for ELS timeouts
1165 	 */
1166 	if ((addr == 0x052198) && (value == 0)) {
1167 		value = 1;
1168 	}
1169 
1170 	mb->un.varWords[0] = addr;
1171 	mb->un.varWords[1] = value;
1172 	mb->mbxCommand = MBX_SET_VARIABLE;
1173 	mb->mbxOwner = OWN_HOST;
1174 } /* End emlxs_mb_set_var */
1175 
1176 
1177 /*
1178  * Disable Traffic Cop
1179  */
1180 /*ARGSUSED*/
1181 extern void
1182 emlxs_disable_tc(emlxs_hba_t *hba, MAILBOX *mb)
1183 {
1184 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1185 
1186 	mb->un.varWords[0] = 0x50797;
1187 	mb->un.varWords[1] = 0;
1188 	mb->un.varWords[2] = 0xfffffffe;
1189 	mb->mbxCommand = MBX_SET_VARIABLE;
1190 	mb->mbxOwner = OWN_HOST;
1191 
1192 } /* End emlxs_disable_tc */
1193 
1194 
1195 
1196 #ifdef SLI3_SUPPORT
1197 extern void
1198 emlxs_mb_config_hbq(emlxs_hba_t *hba, MAILBOX *mb, int hbq_id)
1199 {
1200 	HBQ_INIT_t	*hbq;
1201 	int		i;
1202 
1203 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1204 
1205 	hbq = &hba->hbq_table[hbq_id];
1206 
1207 	mb->un.varCfgHbq.hbqId = hbq_id;
1208 	mb->un.varCfgHbq.numEntries = hbq->HBQ_numEntries;
1209 	mb->un.varCfgHbq.recvNotify = hbq->HBQ_recvNotify;
1210 	mb->un.varCfgHbq.numMask = hbq->HBQ_num_mask;
1211 	mb->un.varCfgHbq.profile = hbq->HBQ_profile;
1212 	mb->un.varCfgHbq.ringMask = hbq->HBQ_ringMask;
1213 	mb->un.varCfgHbq.headerLen = hbq->HBQ_headerLen;
1214 	mb->un.varCfgHbq.logEntry = hbq->HBQ_logEntry;
1215 	mb->un.varCfgHbq.hbqaddrLow = putPaddrLow(hbq->HBQ_host_buf.phys);
1216 	mb->un.varCfgHbq.hbqaddrHigh = putPaddrHigh(hbq->HBQ_host_buf.phys);
1217 	mb->mbxCommand = MBX_CONFIG_HBQ;
1218 	mb->mbxOwner = OWN_HOST;
1219 
1220 	/* Copy info for profiles 2,3,5. Other profiles this area is reserved */
1221 	if ((hbq->HBQ_profile == 2) || (hbq->HBQ_profile == 3) ||
1222 	    (hbq->HBQ_profile == 5)) {
1223 		bcopy(&hbq->profiles.allprofiles,
1224 		    &mb->un.varCfgHbq.profiles.allprofiles,
1225 		    sizeof (hbq->profiles));
1226 	}
1227 
1228 	/* Return if no rctl / type masks for this HBQ */
1229 	if (!hbq->HBQ_num_mask) {
1230 		return;
1231 	}
1232 
1233 	/* Otherwise we setup specific rctl / type masks for this HBQ */
1234 	for (i = 0; i < hbq->HBQ_num_mask; i++) {
1235 		mb->un.varCfgHbq.hbqMasks[i].tmatch =
1236 		    hbq->HBQ_Masks[i].tmatch;
1237 		mb->un.varCfgHbq.hbqMasks[i].tmask = hbq->HBQ_Masks[i].tmask;
1238 		mb->un.varCfgHbq.hbqMasks[i].rctlmatch =
1239 		    hbq->HBQ_Masks[i].rctlmatch;
1240 		mb->un.varCfgHbq.hbqMasks[i].rctlmask =
1241 		    hbq->HBQ_Masks[i].rctlmask;
1242 	}
1243 
1244 	return;
1245 
1246 } /* emlxs_mb_config_hbq() */
1247 
1248 #endif	/* SLI3_SUPPORT */
1249 
1250 
1251 extern uint32_t
1252 emlxs_mb_reg_vpi(emlxs_port_t *port)
1253 {
1254 	emlxs_hba_t	*hba = HBA;
1255 	MAILBOXQ	*mbq;
1256 	MAILBOX		*mb;
1257 
1258 	if (!(hba->flag & FC_NPIV_ENABLED)) {
1259 		return (0);
1260 	}
1261 
1262 	mutex_enter(&EMLXS_PORT_LOCK);
1263 
1264 	/* Can't reg vpi until ClearLA is sent */
1265 	if (hba->state != FC_READY) {
1266 		mutex_exit(&EMLXS_PORT_LOCK);
1267 
1268 		return (1);
1269 	}
1270 
1271 	/* Must have port id */
1272 	if (!port->did) {
1273 		mutex_exit(&EMLXS_PORT_LOCK);
1274 
1275 		return (1);
1276 	}
1277 
1278 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
1279 		mutex_exit(&EMLXS_PORT_LOCK);
1280 
1281 		return (1);
1282 	}
1283 
1284 	port->flag |= EMLXS_PORT_REGISTERED;
1285 
1286 	mutex_exit(&EMLXS_PORT_LOCK);
1287 
1288 	mb = (MAILBOX *)mbq->mbox;
1289 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1290 	mb->un.varRegVpi.vpi = port->vpi;
1291 	mb->un.varRegVpi.sid = port->did;
1292 	mb->mbxCommand = MBX_REG_VPI;
1293 	mb->mbxOwner = OWN_HOST;
1294 
1295 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
1296 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
1297 	}
1298 
1299 	return (0);
1300 
1301 } /* emlxs_mb_reg_vpi() */
1302 
1303 
1304 extern uint32_t
1305 emlxs_mb_unreg_vpi(emlxs_port_t *port)
1306 {
1307 	emlxs_hba_t	*hba = HBA;
1308 	MAILBOXQ	*mbq;
1309 	MAILBOX		*mb;
1310 
1311 	mutex_enter(&EMLXS_PORT_LOCK);
1312 
1313 	if (!(port->flag & EMLXS_PORT_REGISTERED)) {
1314 		mutex_exit(&EMLXS_PORT_LOCK);
1315 
1316 		return (0);
1317 	}
1318 
1319 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
1320 		mutex_exit(&EMLXS_PORT_LOCK);
1321 
1322 		return (1);
1323 	}
1324 
1325 	port->flag &= ~EMLXS_PORT_REGISTERED;
1326 
1327 	mutex_exit(&EMLXS_PORT_LOCK);
1328 
1329 	mb = (MAILBOX *)mbq->mbox;
1330 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1331 	mb->un.varUnregVpi.vpi = port->vpi;
1332 	mb->mbxCommand = MBX_UNREG_VPI;
1333 	mb->mbxOwner = OWN_HOST;
1334 
1335 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
1336 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
1337 	}
1338 
1339 	return (0);
1340 
1341 } /* emlxs_mb_unreg_vpi() */
1342 
1343 
1344 /*
1345  * emlxs_mb_config_farp  Issue a CONFIG FARP mailbox command
1346  */
1347 extern void
1348 emlxs_mb_config_farp(emlxs_hba_t *hba, MAILBOX *mb)
1349 {
1350 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1351 
1352 	bcopy((uint8_t *)&hba->wwpn,
1353 	    (uint8_t *)&mb->un.varCfgFarp.portname, sizeof (NAME_TYPE));
1354 
1355 	bcopy((uint8_t *)&hba->wwpn,
1356 	    (uint8_t *)&mb->un.varCfgFarp.nodename, sizeof (NAME_TYPE));
1357 
1358 	mb->un.varCfgFarp.filterEnable = 1;
1359 	mb->un.varCfgFarp.portName = 1;
1360 	mb->un.varCfgFarp.nodeName = 1;
1361 	mb->mbxCommand = MBX_CONFIG_FARP;
1362 	mb->mbxOwner = OWN_HOST;
1363 } /* emlxs_mb_config_farp() */
1364 
1365 
1366 /*
1367  * emlxs_mb_read_nv  Issue a READ CONFIG mailbox command
1368  */
1369 /*ARGSUSED*/
1370 extern void
1371 emlxs_mb_read_config(emlxs_hba_t *hba, MAILBOX *mb)
1372 {
1373 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1374 
1375 	mb->mbxCommand = MBX_READ_CONFIG;
1376 	mb->mbxOwner = OWN_HOST;
1377 } /* emlxs_mb_read_config() */
1378 
1379 
1380 
1381 /*
1382  * NAME:     emlxs_mb_put
1383  *
1384  * FUNCTION: put mailbox cmd onto the mailbox queue.
1385  *
1386  * EXECUTION ENVIRONMENT: process and interrupt level.
1387  *
1388  * NOTES:
1389  *
1390  * CALLED FROM: emlxs_sli_issue_mbox_cmd
1391  *
1392  * INPUT: hba           - pointer to the device info area
1393  *      mbp             - pointer to mailbox queue entry of mailbox cmd
1394  *
1395  * RETURNS: NULL - command queued
1396  */
1397 extern void
1398 emlxs_mb_put(emlxs_hba_t *hba, MAILBOXQ *mbq)
1399 {
1400 
1401 	mutex_enter(&EMLXS_MBOX_LOCK);
1402 
1403 	if (hba->mbox_queue.q_first) {
1404 
1405 		/*
1406 		 * queue command to end of list
1407 		 */
1408 		((MAILBOXQ *)hba->mbox_queue.q_last)->next = mbq;
1409 		hba->mbox_queue.q_last = (uint8_t *)mbq;
1410 		hba->mbox_queue.q_cnt++;
1411 	} else {
1412 
1413 		/*
1414 		 * add command to empty list
1415 		 */
1416 		hba->mbox_queue.q_first = (uint8_t *)mbq;
1417 		hba->mbox_queue.q_last = (uint8_t *)mbq;
1418 		hba->mbox_queue.q_cnt = 1;
1419 	}
1420 
1421 	mbq->next = NULL;
1422 
1423 	mutex_exit(&EMLXS_MBOX_LOCK);
1424 } /* emlxs_mb_put() */
1425 
1426 
1427 /*
1428  * NAME:     emlxs_mb_get
1429  *
1430  * FUNCTION: get a mailbox command from mailbox command queue
1431  *
1432  * EXECUTION ENVIRONMENT: interrupt level.
1433  *
1434  * NOTES:
1435  *
1436  * CALLED FROM: emlxs_handle_mb_event
1437  *
1438  * INPUT: hba       - pointer to the device info area
1439  *
1440  * RETURNS: NULL - no match found mb pointer - pointer to a mailbox command
1441  */
1442 extern MAILBOXQ *
1443 emlxs_mb_get(emlxs_hba_t *hba)
1444 {
1445 	MAILBOXQ	*p_first = NULL;
1446 
1447 	mutex_enter(&EMLXS_MBOX_LOCK);
1448 
1449 	if (hba->mbox_queue.q_first) {
1450 		p_first = (MAILBOXQ *)hba->mbox_queue.q_first;
1451 		hba->mbox_queue.q_first = (uint8_t *)p_first->next;
1452 
1453 		if (hba->mbox_queue.q_first == NULL) {
1454 			hba->mbox_queue.q_last = NULL;
1455 			hba->mbox_queue.q_cnt = 0;
1456 		} else {
1457 			hba->mbox_queue.q_cnt--;
1458 		}
1459 
1460 		p_first->next = NULL;
1461 	}
1462 
1463 	mutex_exit(&EMLXS_MBOX_LOCK);
1464 
1465 	return (p_first);
1466 
1467 } /* emlxs_mb_get() */
1468 
1469 
1470 
1471 /* EMLXS_PORT_LOCK must be held when calling this */
1472 void
1473 emlxs_mb_init(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t flag, uint32_t tmo)
1474 {
1475 #ifdef FMA_SUPPORT
1476 	emlxs_port_t *port = &PPORT;
1477 #endif	/* FMA_SUPPORT */
1478 	MATCHMAP	*mp;
1479 
1480 	HBASTATS.MboxIssued++;
1481 	hba->mbox_queue_flag = flag;
1482 
1483 	/* Set the Mailbox timer */
1484 	hba->mbox_timer = hba->timer_tics + tmo;
1485 
1486 	/* Initialize mailbox */
1487 	mbq->flag &= MBQ_INIT_MASK;
1488 	hba->mbox_mbqflag = mbq->flag;
1489 
1490 	mbq->next = 0;
1491 
1492 	mutex_enter(&EMLXS_MBOX_LOCK);
1493 	if (flag == MBX_NOWAIT) {
1494 		hba->mbox_mbq = 0;
1495 	} else {
1496 		hba->mbox_mbq = (uint8_t *)mbq;
1497 	}
1498 	mutex_exit(&EMLXS_MBOX_LOCK);
1499 
1500 	if (mbq->bp) {
1501 		mp = (MATCHMAP *) mbq->bp;
1502 		emlxs_mpdata_sync(mp->dma_handle, 0, mp->size,
1503 		    DDI_DMA_SYNC_FORDEV);
1504 
1505 		hba->mbox_bp = mbq->bp;
1506 		mbq->bp = 0;
1507 	}
1508 
1509 	if (mbq->sbp) {
1510 		hba->mbox_sbp = mbq->sbp;
1511 		mbq->sbp = 0;
1512 	}
1513 
1514 	if (mbq->ubp) {
1515 		hba->mbox_ubp = mbq->ubp;
1516 		mbq->ubp = 0;
1517 	}
1518 
1519 	if (mbq->iocbq) {
1520 		hba->mbox_iocbq = mbq->iocbq;
1521 		mbq->iocbq = 0;
1522 	}
1523 #ifdef MBOX_EXT_SUPPORT
1524 	if (mbq->extbuf && mbq->extsize) {
1525 		hba->mbox_ext = mbq->extbuf;
1526 		hba->mbox_ext_size = mbq->extsize;
1527 	}
1528 #endif /* MBOX_EXT_SUPPORT */
1529 
1530 	return;
1531 
1532 } /* emlxs_mb_init() */
1533 
1534 
1535 extern void
1536 emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus)
1537 {
1538 	emlxs_port_t	*port = &PPORT;
1539 	MATCHMAP	*mbox_bp;
1540 	emlxs_buf_t	*mbox_sbp;
1541 	fc_unsol_buf_t	*mbox_ubp;
1542 	IOCBQ		*mbox_iocbq;
1543 	MAILBOXQ	*mbox_mbq;
1544 	MAILBOX		*mbox;
1545 	uint32_t	mbox_queue_flag;
1546 	emlxs_ub_priv_t	*ub_priv;
1547 
1548 	mutex_enter(&EMLXS_PORT_LOCK);
1549 
1550 	if (hba->mbox_queue_flag) {
1551 		HBASTATS.MboxCompleted++;
1552 
1553 		if (mbxStatus != MBX_SUCCESS) {
1554 			HBASTATS.MboxError++;
1555 		} else {
1556 			HBASTATS.MboxGood++;
1557 		}
1558 	}
1559 
1560 	mbox_bp = (MATCHMAP *)hba->mbox_bp;
1561 	mbox_sbp = (emlxs_buf_t *)hba->mbox_sbp;
1562 	mbox_ubp = (fc_unsol_buf_t *)hba->mbox_ubp;
1563 	mbox_iocbq = (IOCBQ *)hba->mbox_iocbq;
1564 	mbox_mbq = (MAILBOXQ *)hba->mbox_mbq;
1565 	mbox_queue_flag = hba->mbox_queue_flag;
1566 
1567 #ifdef MBOX_EXT_SUPPORT
1568 	hba->mbox_ext = 0;
1569 	hba->mbox_ext_size = 0;
1570 #endif /* MBOX_EXT_SUPPORT */
1571 
1572 	hba->mbox_bp = 0;
1573 	hba->mbox_sbp = 0;
1574 	hba->mbox_ubp = 0;
1575 	hba->mbox_iocbq = 0;
1576 	hba->mbox_mbqflag = 0;
1577 	hba->mbox_mbq = 0;
1578 	hba->mbox_timer = 0;
1579 	hba->mbox_queue_flag = 0;
1580 
1581 	mutex_exit(&EMLXS_PORT_LOCK);
1582 
1583 	if (mbox_mbq) {
1584 		if (mb) {
1585 			/* Copy the local mailbox provided back into */
1586 			/* the original mailbox */
1587 			bcopy((uint32_t *)mb, (uint32_t *)mbox_mbq,
1588 			    MAILBOX_CMD_BSIZE);
1589 		}
1590 
1591 		mbox = (MAILBOX *)mbox_mbq;
1592 		mbox->mbxStatus = mbxStatus;
1593 
1594 		/* Mark mailbox complete */
1595 		mbox_mbq->flag |= MBQ_COMPLETED;
1596 
1597 		/* Wake up the sleeping thread */
1598 		if (mbox_queue_flag == MBX_SLEEP) {
1599 			mutex_enter(&EMLXS_MBOX_LOCK);
1600 			cv_broadcast(&EMLXS_MBOX_CV);
1601 			mutex_exit(&EMLXS_MBOX_LOCK);
1602 		}
1603 	}
1604 
1605 	/* Check for deferred MBUF cleanup */
1606 	if (mbox_bp && (mbox_queue_flag == MBX_NOWAIT)) {
1607 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mbox_bp);
1608 	}
1609 #ifdef SFCT_SUPPORT
1610 	if (mbox_sbp && mbox_sbp->fct_cmd) {
1611 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1612 		    "FCT mailbox: %s: status=%x",
1613 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
1614 		    (uint32_t)mb->mbxStatus);
1615 	}
1616 #endif /* SFCT_SUPPORT */
1617 
1618 	/* Check for deferred pkt completion */
1619 	if (mbox_sbp) {
1620 		if (mbxStatus != MBX_SUCCESS) {
1621 			/* Set error status */
1622 			mbox_sbp->pkt_flags &= ~PACKET_STATE_VALID;
1623 			emlxs_set_pkt_state(mbox_sbp, IOSTAT_LOCAL_REJECT,
1624 			    IOERR_NO_RESOURCES, 1);
1625 		}
1626 
1627 		emlxs_pkt_complete(mbox_sbp, -1, 0, 1);
1628 	}
1629 
1630 	/* Check for deferred ub completion */
1631 	if (mbox_ubp) {
1632 		ub_priv = mbox_ubp->ub_fca_private;
1633 		port = ub_priv->port;
1634 
1635 		emlxs_ub_callback(port, mbox_ubp);
1636 	}
1637 
1638 	/* Check for deferred iocb tx */
1639 	if (mbox_iocbq) {
1640 		emlxs_sli_issue_iocb_cmd(hba, mbox_iocbq->ring, mbox_iocbq);
1641 	}
1642 
1643 	return;
1644 
1645 } /* emlxs_mb_fini() */
1646 
1647 
1648 
1649 /* This should only be called with active MBX_NOWAIT mailboxes */
1650 void
1651 emlxs_mb_retry(emlxs_hba_t *hba, MAILBOX *mb)
1652 {
1653 	MAILBOXQ	*mbq;
1654 
1655 	mutex_enter(&EMLXS_PORT_LOCK);
1656 
1657 	HBASTATS.MboxCompleted++;
1658 
1659 	if (mb->mbxStatus != 0) {
1660 		HBASTATS.MboxError++;
1661 	} else {
1662 		HBASTATS.MboxGood++;
1663 	}
1664 
1665 	mbq = (MAILBOXQ *)mb;
1666 	mbq->bp = (uint8_t *)hba->mbox_bp;
1667 	mbq->sbp = (uint8_t *)hba->mbox_sbp;
1668 	mbq->ubp = (uint8_t *)hba->mbox_ubp;
1669 	mbq->iocbq = (uint8_t *)hba->mbox_iocbq;
1670 
1671 	hba->mbox_bp = 0;
1672 	hba->mbox_sbp = 0;
1673 	hba->mbox_ubp = 0;
1674 	hba->mbox_iocbq = 0;
1675 	hba->mbox_mbq = 0;
1676 	hba->mbox_mbqflag = 0;
1677 	hba->mbox_queue_flag = 0;
1678 
1679 	mutex_exit(&EMLXS_PORT_LOCK);
1680 
1681 	return;
1682 
1683 } /* emlxs_mb_retry() */
1684 
1685 
1686 extern char *
1687 emlxs_mb_cmd_xlate(uint8_t cmd)
1688 {
1689 	static char	buffer[32];
1690 	uint32_t	i;
1691 	uint32_t	count;
1692 
1693 	count = sizeof (emlxs_mb_cmd_table) / sizeof (emlxs_table_t);
1694 	for (i = 0; i < count; i++) {
1695 		if (cmd == emlxs_mb_cmd_table[i].code) {
1696 			return (emlxs_mb_cmd_table[i].string);
1697 		}
1698 	}
1699 
1700 	(void) sprintf(buffer, "Cmd=0x%x", cmd);
1701 	return (buffer);
1702 
1703 } /* emlxs_mb_cmd_xlate() */
1704