xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dump.c (revision b6805bf78d2bbbeeaea8909a05623587b42d58b3)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #include <emlxs.h>
29 
30 #ifdef DUMP_SUPPORT
31 
32 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
33 EMLXS_MSG_DEF(EMLXS_DUMP_C);
34 
35 /* ************************************************************************* */
36 /* Utility functions */
37 /* ************************************************************************* */
38 
39 static uint32_t
40 emlxs_menlo_set_mode(
41 	emlxs_hba_t *hba,
42 	uint32_t mode)
43 {
44 	emlxs_port_t *port = &PPORT;
45 	uint32_t cmd_size;
46 	uint32_t rsp_size;
47 	menlo_cmd_t *cmd_buf = NULL;
48 	menlo_rsp_t *rsp_buf = NULL;
49 	uint32_t rval = 0;
50 
51 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
52 		return (DFC_INVALID_ADAPTER);
53 	}
54 
55 	cmd_size = sizeof (menlo_set_cmd_t);
56 	cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP);
57 
58 	rsp_size = 4;
59 	rsp_buf = (menlo_rsp_t *)kmem_zalloc(rsp_size, KM_SLEEP);
60 
61 	cmd_buf->code = MENLO_CMD_SET_MODE;
62 	cmd_buf->set.value1 = mode;
63 	cmd_buf->set.value2 = 0;
64 
65 #ifdef EMLXS_BIG_ENDIAN
66 	emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size);
67 #endif /* EMLXS_BIG_ENDIAN */
68 
69 	if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size,
70 	    (uint8_t *)rsp_buf, &rsp_size)) {
71 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
72 		    "emlxs_menlo_set_mode: Unable to send command.");
73 		goto done;
74 	}
75 #ifdef EMLXS_BIG_ENDIAN
76 	emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size);
77 #endif /* EMLXS_BIG_ENDIAN */
78 
79 	if (rsp_buf->code != 0) {
80 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
81 		    "emlxs_menlo_set_mode: Menlo command error. code=%d.\n",
82 		    rsp_buf->code);
83 	}
84 
85 	rval = rsp_buf->code;
86 
87 done:
88 
89 	if (cmd_buf) {
90 		kmem_free(cmd_buf, sizeof (menlo_set_cmd_t));
91 	}
92 
93 	if (rsp_buf) {
94 		kmem_free(rsp_buf, 4);
95 	}
96 
97 	return (rval);
98 
99 } /* emlxs_menlo_set_mode() */
100 
101 
102 static uint32_t
103 emlxs_menlo_reset(
104 	emlxs_hba_t *hba,
105 	uint32_t firmware)
106 {
107 	emlxs_port_t *port = &PPORT;
108 	uint32_t cmd_size;
109 	uint32_t rsp_size;
110 	menlo_cmd_t *cmd_buf = NULL;
111 	menlo_rsp_t *rsp_buf = NULL;
112 	uint32_t rval = 0;
113 
114 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
115 		return (DFC_INVALID_ADAPTER);
116 	}
117 
118 	cmd_size = sizeof (menlo_reset_cmd_t);
119 	cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP);
120 
121 	rsp_size = 4;
122 	rsp_buf = (menlo_rsp_t *)kmem_zalloc(rsp_size, KM_SLEEP);
123 
124 	cmd_buf->code = MENLO_CMD_RESET;
125 	cmd_buf->reset.firmware = firmware;
126 
127 #ifdef EMLXS_BIG_ENDIAN
128 	emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size);
129 #endif /* EMLXS_BIG_ENDIAN */
130 
131 	if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size,
132 	    (uint8_t *)rsp_buf, &rsp_size)) {
133 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
134 		    "emlxs_menlo_reset: Unable to send command.");
135 		goto done;
136 	}
137 #ifdef EMLXS_BIG_ENDIAN
138 	emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size);
139 #endif /* EMLXS_BIG_ENDIAN */
140 
141 	if (rsp_buf->code != 0) {
142 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
143 		    "emlxs_menlo_reset: Menlo command error. code=%d.\n",
144 		    rsp_buf->code);
145 	}
146 
147 	rval = rsp_buf->code;
148 
149 done:
150 
151 	if (cmd_buf) {
152 		kmem_free(cmd_buf, sizeof (menlo_reset_cmd_t));
153 	}
154 
155 	if (rsp_buf) {
156 		kmem_free(rsp_buf, 4);
157 	}
158 
159 	return (rval);
160 
161 } /* emlxs_menlo_reset() */
162 
163 
164 static uint32_t
165 emlxs_menlo_get_cfg(
166 	emlxs_hba_t *hba,
167 	menlo_get_config_rsp_t *rsp_buf,
168 	uint32_t rsp_size)
169 {
170 	emlxs_port_t *port = &PPORT;
171 	uint32_t cmd_size;
172 	menlo_cmd_t *cmd_buf = NULL;
173 	uint32_t rval = 0;
174 
175 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
176 		return (DFC_INVALID_ADAPTER);
177 	}
178 
179 	cmd_size = sizeof (menlo_get_cmd_t);
180 	cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP);
181 
182 	rsp_size = sizeof (menlo_get_config_rsp_t);
183 
184 	cmd_buf->code = MENLO_CMD_GET_CONFIG;
185 	cmd_buf->get.context = 0;
186 	cmd_buf->get.length = rsp_size;
187 
188 #ifdef EMLXS_BIG_ENDIAN
189 	emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size);
190 #endif /* EMLXS_BIG_ENDIAN */
191 
192 	if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size,
193 	    (uint8_t *)rsp_buf, &rsp_size)) {
194 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
195 		    "emlxs_menlo_get_cfg: Unable to send command.");
196 		goto done;
197 	}
198 #ifdef EMLXS_BIG_ENDIAN
199 	emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size);
200 #endif /* EMLXS_BIG_ENDIAN */
201 
202 	if (rsp_buf->code != 0) {
203 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
204 		    "emlxs_menlo_get_cfg: Menlo command error. code=%d.\n",
205 		    rsp_buf->code);
206 	}
207 
208 	rval = rsp_buf->code;
209 
210 done:
211 
212 	if (cmd_buf) {
213 		kmem_free(cmd_buf, sizeof (menlo_get_cmd_t));
214 	}
215 
216 	return (rval);
217 
218 } /* emlxs_menlo_get_cfg() */
219 
220 
221 
222 static uint32_t
223 emlxs_menlo_get_logcfg(
224 	emlxs_hba_t *hba,
225 	menlo_rsp_t *rsp_buf,
226 	uint32_t rsp_size)
227 {
228 	emlxs_port_t *port = &PPORT;
229 	uint32_t cmd_size;
230 	menlo_cmd_t *cmd_buf = NULL;
231 	uint32_t rval = 0;
232 
233 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
234 		return (DFC_INVALID_ADAPTER);
235 	}
236 
237 	cmd_size = sizeof (menlo_get_cmd_t);
238 	cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP);
239 
240 	cmd_buf->code = MENLO_CMD_GET_LOG_CONFIG;
241 	cmd_buf->get.context = 0;
242 	cmd_buf->get.length = rsp_size;
243 
244 #ifdef EMLXS_BIG_ENDIAN
245 	emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size);
246 #endif /* EMLXS_BIG_ENDIAN */
247 
248 	if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size,
249 	    (uint8_t *)rsp_buf, &rsp_size)) {
250 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
251 		    "emlxs_menlo_get_logcfg: Unable to send command.");
252 		goto done;
253 	}
254 #ifdef EMLXS_BIG_ENDIAN
255 	emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size);
256 #endif /* EMLXS_BIG_ENDIAN */
257 
258 	if (rsp_buf->code != 0) {
259 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
260 		    "emlxs_menlo_get_logcfg: Menlo command error. code=%d.\n",
261 		    rsp_buf->code);
262 	}
263 
264 	rval = rsp_buf->code;
265 
266 done:
267 
268 	if (cmd_buf) {
269 		kmem_free(cmd_buf, sizeof (menlo_get_cmd_t));
270 	}
271 
272 	return (rval);
273 
274 } /* emlxs_menlo_get_logcfg() */
275 
276 
277 static uint32_t
278 emlxs_menlo_get_log(
279 	emlxs_hba_t *hba,
280 	uint32_t id,
281 	menlo_rsp_t *rsp_buf,
282 	uint32_t rsp_size)
283 {
284 	emlxs_port_t *port = &PPORT;
285 	uint32_t cmd_size;
286 	menlo_cmd_t *cmd_buf = NULL;
287 	uint32_t rval = 0;
288 
289 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
290 		return (DFC_INVALID_ADAPTER);
291 	}
292 
293 	cmd_size = sizeof (menlo_get_cmd_t);
294 	cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP);
295 
296 	cmd_buf->code = MENLO_CMD_GET_LOG_DATA;
297 	cmd_buf->get.context = id;
298 	cmd_buf->get.length = rsp_size;
299 
300 #ifdef EMLXS_BIG_ENDIAN
301 	emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size);
302 #endif /* EMLXS_BIG_ENDIAN */
303 
304 	if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size,
305 	    (uint8_t *)rsp_buf, &rsp_size)) {
306 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
307 		    "emlxs_menlo_get_log: Unable to send command.");
308 		goto done;
309 	}
310 #ifdef EMLXS_BIG_ENDIAN
311 	emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size);
312 #endif /* EMLXS_BIG_ENDIAN */
313 
314 	if (rsp_buf->code != 0) {
315 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
316 		    "emlxs_menlo_get_log: Menlo command error. code=%d.\n",
317 		    rsp_buf->code);
318 	}
319 
320 	rval = rsp_buf->code;
321 
322 done:
323 
324 	if (cmd_buf) {
325 		kmem_free(cmd_buf, sizeof (menlo_get_cmd_t));
326 	}
327 
328 	return (rval);
329 
330 } /* emlxs_menlo_get_log() */
331 
332 
333 static uint32_t
334 emlxs_menlo_get_paniclog(
335 	emlxs_hba_t *hba,
336 	menlo_rsp_t *rsp_buf,
337 	uint32_t rsp_size)
338 {
339 	emlxs_port_t *port = &PPORT;
340 	uint32_t cmd_size;
341 	menlo_cmd_t *cmd_buf = NULL;
342 	uint32_t rval = 0;
343 
344 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
345 		return (DFC_INVALID_ADAPTER);
346 	}
347 
348 	cmd_size = sizeof (menlo_get_cmd_t);
349 	cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP);
350 
351 	cmd_buf->code = MENLO_CMD_GET_PANIC_LOG;
352 	cmd_buf->get.context = 0;
353 	cmd_buf->get.length = rsp_size;
354 
355 #ifdef EMLXS_BIG_ENDIAN
356 	emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size);
357 #endif /* EMLXS_BIG_ENDIAN */
358 
359 	if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size,
360 	    (uint8_t *)rsp_buf, &rsp_size)) {
361 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
362 		    "emlxs_menlo_get_paniclog: Unable to send command.");
363 		goto done;
364 	}
365 #ifdef EMLXS_BIG_ENDIAN
366 	emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size);
367 #endif /* EMLXS_BIG_ENDIAN */
368 
369 	if (rsp_buf->code != 0) {
370 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
371 		    "emlxs_menlo_get_paniclog: Menlo command error. code=%d.\n",
372 		    rsp_buf->code);
373 	}
374 
375 	rval = rsp_buf->code;
376 
377 done:
378 
379 	if (cmd_buf) {
380 		kmem_free(cmd_buf, sizeof (menlo_get_cmd_t));
381 	}
382 
383 	return (rval);
384 
385 } /* emlxs_menlo_get_paniclog() */
386 
387 
388 
389 
390 extern void
391 emlxs_fflush(
392 	emlxs_file_t *fp)
393 {
394 	uint32_t offset;
395 
396 	offset = (uint32_t)((uintptr_t)fp->ptr - (uintptr_t)fp->buffer);
397 
398 	if (offset > fp->size) {
399 		fp->ptr = fp->buffer + fp->size;
400 	}
401 
402 	return;
403 
404 } /* emlxs_fflush() */
405 
406 
407 extern uint32_t
408 emlxs_ftell(
409 	emlxs_file_t *fp)
410 {
411 	uint32_t offset;
412 
413 	offset = (uint32_t)((uintptr_t)fp->ptr - (uintptr_t)fp->buffer);
414 
415 	return (offset);
416 
417 } /* emlxs_ftell() */
418 
419 
420 static void
421 emlxs_fputc(
422 	uint8_t value,
423 	emlxs_file_t *fp)
424 {
425 	uint32_t offset;
426 
427 	offset = (uint32_t)((uintptr_t)fp->ptr - (uintptr_t)fp->buffer);
428 
429 	if ((offset + 1) <= fp->size) {
430 		*fp->ptr++ = value;
431 	}
432 
433 	return;
434 
435 } /* emlxs_fputc() */
436 
437 
438 static uint32_t
439 emlxs_fwrite(
440 	uint8_t *buffer,
441 	uint32_t size,
442 	uint32_t nitems,
443 	emlxs_file_t *fp)
444 {
445 	uint32_t offset;
446 	uint32_t length;
447 
448 	length = size * nitems;
449 
450 	if (length) {
451 		offset =
452 		    (uint32_t)((uintptr_t)fp->ptr - (uintptr_t)fp->buffer);
453 
454 		if ((offset + length) > fp->size) {
455 			length = fp->size - offset;
456 		}
457 
458 		if (length) {
459 			bcopy(buffer, fp->ptr, length);
460 			fp->ptr += length;
461 		}
462 	}
463 
464 	return (length);
465 
466 } /* emlxs_fwrite() */
467 
468 
469 static uint32_t
470 emlxs_fprintf(
471 	emlxs_file_t *fp,
472 	const char *fmt, ...)
473 {
474 	va_list valist;
475 	char va_str[1024];
476 	uint32_t length;
477 
478 	va_start(valist, fmt);
479 	(void) vsprintf(va_str, fmt, valist);
480 	va_end(valist);
481 
482 	length = emlxs_fwrite((uint8_t *)va_str, strlen(va_str), 1, fp);
483 
484 	return (length);
485 
486 } /* emlxs_fprintf() */
487 
488 
489 extern emlxs_file_t *
490 emlxs_fopen(
491 	emlxs_hba_t *hba,
492 	uint32_t file_type)
493 {
494 	emlxs_file_t *fp;
495 
496 	switch (file_type) {
497 	case EMLXS_TXT_FILE:
498 		fp = &hba->dump_txtfile;
499 		fp->size = EMLXS_TXT_FILE_SIZE;
500 		break;
501 
502 	case EMLXS_DMP_FILE:
503 		fp = &hba->dump_dmpfile;
504 		fp->size = EMLXS_DMP_FILE_SIZE;
505 		break;
506 
507 	case EMLXS_CEE_FILE:
508 		fp = &hba->dump_ceefile;
509 		fp->size = EMLXS_CEE_FILE_SIZE;
510 		break;
511 
512 	default:
513 		return (NULL);
514 	}
515 
516 	/* Make sure it is word aligned */
517 	fp->size &= 0xFFFFFFFC;
518 
519 	if (!fp->buffer) {
520 		fp->buffer =
521 		    (uint8_t *)kmem_zalloc(fp->size, KM_SLEEP);
522 
523 	} else {
524 		bzero(fp->buffer, fp->size);
525 	}
526 
527 	fp->ptr = fp->buffer;
528 
529 	return (fp);
530 
531 } /* emlxs_fopen() */
532 
533 
534 extern uint32_t
535 emlxs_fclose(
536 	emlxs_file_t *fp)
537 {
538 	uint32_t offset;
539 
540 	if (fp == NULL) {
541 		return (0);
542 	}
543 
544 	offset = (uint32_t)((uintptr_t)fp->ptr - (uintptr_t)fp->buffer);
545 	offset = offset % 4;
546 
547 	switch (offset) {
548 	case 0:
549 		break;
550 
551 	case 1:
552 		*fp->ptr++ = 0;
553 		*fp->ptr++ = 0;
554 		*fp->ptr++ = 0;
555 		break;
556 
557 	case 2:
558 		*fp->ptr++ = 0;
559 		*fp->ptr++ = 0;
560 		break;
561 
562 	case 3:
563 		*fp->ptr++ = 0;
564 		break;
565 	}
566 
567 	return (0);
568 
569 } /* emlxs_fclose() */
570 
571 
572 static void
573 emlxs_fdelete(
574 	emlxs_file_t *fp)
575 {
576 	if (fp == NULL) {
577 		return;
578 	}
579 
580 	if (fp->buffer && fp->size) {
581 		kmem_free(fp->buffer, fp->size);
582 	}
583 
584 	fp->buffer = NULL;
585 	fp->ptr = NULL;
586 	fp->size = 0;
587 
588 	return;
589 
590 } /* emlxs_fdelete() */
591 
592 
593 /* This builds a single core buffer for the IOCTL interface */
594 extern uint32_t
595 emlxs_get_dump(
596 	emlxs_hba_t *hba,
597 	uint8_t *buffer,
598 	uint32_t *buflen)
599 {
600 	emlxs_port_t *port = &PPORT;
601 	int32_t i;
602 	int32_t size;
603 	int32_t count;
604 	uint32_t size_dmp;
605 	uint32_t size_txt;
606 	uint32_t size_cee;
607 	emlxs_file_t *fp_txt;
608 	emlxs_file_t *fp_dmp;
609 	emlxs_file_t *fp_cee;
610 	uint32_t *wptr;
611 	uint8_t *bptr;
612 
613 	if (!buflen) {
614 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
615 		    "emlxs_get_dump: Buffer length = 0");
616 		return (1);
617 	}
618 
619 	fp_txt = &hba->dump_txtfile;
620 	fp_dmp = &hba->dump_dmpfile;
621 	fp_cee = &hba->dump_ceefile;
622 
623 	size_txt = emlxs_ftell(fp_txt);
624 	size_dmp = emlxs_ftell(fp_dmp);
625 	size_cee = emlxs_ftell(fp_cee);
626 
627 	size = 0;
628 	count = 0;
629 	if (size_txt) {
630 		count++;
631 		size += size_txt + 8;
632 	}
633 	if (size_dmp) {
634 		count++;
635 		size += size_dmp + 8;
636 	}
637 	if (size_cee) {
638 		count++;
639 		size += size_cee + 8;
640 	}
641 
642 	if (size) {
643 		size += 4;
644 	}
645 
646 	if (!buffer) {
647 		goto done;
648 	}
649 
650 	bzero(buffer, *buflen);
651 
652 	if (*buflen < size) {
653 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
654 		    "emlxs_get_dump: Buffer length too small. %d < %d",
655 		    *buflen, size);
656 
657 		*buflen = 0;
658 		return (1);
659 	}
660 
661 	wptr = (uint32_t *)buffer;
662 	wptr[0] = count;
663 	i = 1;
664 
665 	if (size_txt) {
666 		wptr[i++] = EMLXS_TXT_FILE_ID;
667 		wptr[i++] = size_txt;
668 	}
669 
670 	if (size_dmp) {
671 		wptr[i++] = EMLXS_DMP_FILE_ID;
672 		wptr[i++] = size_dmp;
673 	}
674 
675 	if (size_cee) {
676 		if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
677 		    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
678 			wptr[i++] = EMLXS_FAT_FILE_ID;
679 		} else {
680 			wptr[i++] = EMLXS_CEE_FILE_ID;
681 		}
682 
683 		wptr[i++] = size_cee;
684 	}
685 
686 	bptr = (uint8_t *)&wptr[i];
687 
688 	if (size_txt) {
689 		bcopy(fp_txt->buffer, bptr, size_txt);
690 		bptr += size_txt;
691 	}
692 
693 	if (size_dmp) {
694 		bcopy(fp_dmp->buffer, bptr, size_dmp);
695 		bptr += size_dmp;
696 	}
697 
698 	if (size_cee) {
699 		bcopy(fp_cee->buffer, bptr, size_cee);
700 		bptr += size_cee;
701 	}
702 
703 done:
704 
705 	*buflen = size;
706 
707 	/* printf("Done. buflen=%d \n", *buflen); */
708 
709 	return (0);
710 
711 } /* emlxs_get_dump() */
712 
713 
714 static uint32_t
715 emlxs_read_cfg_region(
716 	emlxs_hba_t *hba,
717 	uint32_t Identifier,
718 	uint32_t ByteCount,
719 	uint32_t *pRetByteCount,
720 	uint8_t *pBuffer)
721 {
722 	emlxs_port_t *port = &PPORT;
723 	MAILBOXQ *mbq;
724 	uint32_t ByteCountRem;	/* remaining portion of original byte count */
725 	uint32_t ByteCountReq;	/* requested byte count for a particular dump */
726 	uint32_t CopyCount;	/* bytes to copy after each successful dump */
727 	uint32_t Offset;	/* Offset into Config Region, for each dump */
728 	uint8_t *pLocalBuf;	/* ptr to buffer to receive each dump */
729 
730 	mbq =
731 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
732 
733 	pLocalBuf = pBuffer;	/* init local pointer to caller's buffer */
734 	Offset = 0;	/* start at offset 0 */
735 	*pRetByteCount = 0;	/* init returned byte count */
736 	CopyCount = 0;
737 
738 	for (ByteCountRem = ByteCount; ByteCountRem > 0;
739 	    ByteCountRem -= CopyCount) {
740 
741 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
742 			MAILBOX4 *mb = (MAILBOX4 *)mbq;
743 
744 			ByteCountReq =
745 			    (ByteCountRem < hba->sli.sli4.dump_region.size) ?
746 			    ByteCountRem : hba->sli.sli4.dump_region.size;
747 
748 			/* Clear the local dump_region */
749 			bzero(hba->sli.sli4.dump_region.virt,
750 			    hba->sli.sli4.dump_region.size);
751 
752 			bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
753 
754 			mb->mbxCommand = MBX_DUMP_MEMORY;
755 			mb->un.varDmp4.type = DMP_NV_PARAMS;
756 			mb->un.varDmp4.entry_index = Offset;
757 			mb->un.varDmp4.region_id = Identifier;
758 
759 			mb->un.varDmp4.available_cnt = ByteCountReq;
760 			mb->un.varDmp4.addrHigh =
761 			    PADDR_HI(hba->sli.sli4.dump_region.phys);
762 			mb->un.varDmp4.addrLow =
763 			    PADDR_LO(hba->sli.sli4.dump_region.phys);
764 			mb->un.varDmp4.rsp_cnt = 0;
765 
766 			mb->mbxOwner = OWN_HOST;
767 			mbq->mbox_cmpl = NULL;
768 
769 			if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
770 			    MBX_SUCCESS) {
771 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
772 				    "Unable to read config region. id=%x "\
773 				    "offset=%x status=%x",
774 				    Identifier, Offset, mb->mbxStatus);
775 
776 				kmem_free(mbq, sizeof (MAILBOXQ));
777 				return (1);
778 			}
779 
780 			CopyCount = mb->un.varDmp4.rsp_cnt;
781 
782 			/* if no more data returned */
783 			if (CopyCount == 0) {
784 				break;
785 			}
786 
787 			if (CopyCount > ByteCountReq) {
788 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
789 				    "emlxs_read_cfg_region: " \
790 				    "Byte count too big. %d > %d\n",
791 				    CopyCount, ByteCountReq);
792 
793 				CopyCount = ByteCountReq;
794 			}
795 
796 			bcopy((uint8_t *)hba->sli.sli4.dump_region.virt,
797 			    pLocalBuf, CopyCount);
798 
799 		} else {
800 			MAILBOX *mb = (MAILBOX *)mbq;
801 
802 			ByteCountReq =
803 			    (ByteCountRem < DUMP_BC_MAX) ? ByteCountRem :
804 			    DUMP_BC_MAX;
805 
806 			bzero((void *)mb, MAILBOX_CMD_BSIZE);
807 
808 			mb->mbxCommand = MBX_DUMP_MEMORY;
809 			mb->un.varDmp.type = DMP_NV_PARAMS;
810 			mb->un.varDmp.cv = 1;
811 			mb->un.varDmp.region_id = Identifier;
812 			mb->un.varDmp.entry_index = Offset;
813 			mb->un.varDmp.word_cnt = ByteCountReq / 4;
814 			mb->mbxOwner = OWN_HOST;
815 			mbq->mbox_cmpl = NULL;
816 
817 			if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
818 			    MBX_SUCCESS) {
819 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
820 				    "Unable to read config region. id=%x "\
821 				    "offset=%x status=%x",
822 				    Identifier, Offset, mb->mbxStatus);
823 
824 				kmem_free(mbq, sizeof (MAILBOXQ));
825 				return (1);
826 			}
827 
828 			/* Note: for Type 2/3 Dumps, varDmp.word_cnt is */
829 			/* actually a byte count. */
830 			CopyCount = mb->un.varDmp.word_cnt;
831 
832 			/* if no more data returned */
833 			if (CopyCount == 0) {
834 				break;
835 			}
836 
837 			if (CopyCount > ByteCountReq) {
838 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
839 				    "emlxs_read_cfg_region: " \
840 				    "Byte count too big. %d > %d\n",
841 				    CopyCount, ByteCountReq);
842 
843 				CopyCount = ByteCountReq;
844 			}
845 
846 			bcopy((uint8_t *)&mb->un.varDmp.resp_offset, pLocalBuf,
847 			    CopyCount);
848 		}
849 
850 		pLocalBuf += CopyCount;
851 		Offset += CopyCount;
852 		*pRetByteCount += CopyCount;
853 	}
854 
855 	return (0);
856 
857 } /* emlxs_read_cfg_region() */
858 
859 
860 
861 /* ************************************************************************* */
862 /* ************************************************************************* */
863 /* Dump Generators, Low-Level */
864 /* ************************************************************************* */
865 /* ************************************************************************* */
866 
867 static uint32_t
868 emlxs_dump_string_txtfile(
869 	emlxs_file_t *fpTxtFile,
870 	char *pString,
871 	char *pSidLegend,
872 	char *pLidLegend,
873 	uint32_t pure)
874 {
875 
876 	if (!fpTxtFile) {
877 		return (1);
878 	}
879 
880 	if (pSidLegend && pLidLegend) {
881 		(void) emlxs_fprintf(fpTxtFile, "%s: %s\n", pSidLegend,
882 		    pLidLegend);
883 
884 		if (pure == 0) {
885 			emlxs_fputc(' ', fpTxtFile);
886 		}
887 
888 		(void) emlxs_fwrite((uint8_t *)pString, strlen(pString), 1,
889 		    fpTxtFile);
890 
891 		if (pure == 0) {
892 			emlxs_fputc('\n', fpTxtFile);
893 			emlxs_fputc('\n', fpTxtFile);
894 		}
895 	} else {
896 		if (pure == 0) {
897 			emlxs_fputc(' ', fpTxtFile);
898 		}
899 		(void) emlxs_fwrite((uint8_t *)pString, strlen(pString), 1,
900 		    fpTxtFile);
901 	}
902 
903 	emlxs_fflush(fpTxtFile);
904 
905 	return (0);
906 
907 } /* emlxs_dump_string_txtfile() */
908 
909 
910 static uint32_t
911 emlxs_dump_word_txtfile(
912 	emlxs_file_t *fpTxtFile,
913 	uint32_t *pBuffer,
914 	uint32_t WordCount,
915 	char *pSidLegend,
916 	char *pLidLegend)
917 {
918 	char buf1[256];
919 	char buf2[256];
920 	uint32_t *ptr;
921 	uint32_t j;
922 
923 	if (!fpTxtFile) {
924 		return (1);
925 	}
926 
927 	/* Write Legend String to the TXT File */
928 	(void) emlxs_fprintf(fpTxtFile, "%s: %s\n", pSidLegend, pLidLegend);
929 
930 	/* Write the buffer to the TXT File */
931 	ptr = pBuffer;
932 
933 	for (j = 0; j < WordCount; j++) {
934 		buf1[0] = 0;
935 		buf2[0] = 0;
936 
937 		if ((j & 0x03) == 0) {
938 			(void) sprintf(buf1, "\n%04x:", j * 4);
939 			(void) strcat(buf2, buf1);
940 		}
941 		(void) sprintf(buf1, " %08x", ptr[j]);	/* print 1 word */
942 		(void) strcat(buf2, buf1);
943 		(void) emlxs_fwrite((uint8_t *)buf2, strlen(buf2), 1,
944 		    fpTxtFile);
945 	}
946 
947 	emlxs_fputc('\n', fpTxtFile);
948 	emlxs_fputc('\n', fpTxtFile);
949 	emlxs_fflush(fpTxtFile);
950 	return (0);
951 
952 } /* emlxs_dump_word_txtfile() */
953 
954 
955 
956 
957 static uint32_t
958 emlxs_dump_string_dmpfile(
959 	emlxs_file_t *fpDmpFile,
960 	char *pString,
961 	uint8_t sid,
962 	char *pSidLegend,
963 	char *pLidLegend)
964 {
965 	uint32_t length;
966 	uint8_t byte;
967 	uint32_t pos;
968 
969 	if (!fpDmpFile) {
970 		return (1);
971 	}
972 
973 	/* Write Legend SID to the DMP File */
974 	emlxs_fputc(SID_LEGEND, fpDmpFile);
975 
976 	/* Write Argument SID to the DMP File */
977 	emlxs_fputc(sid, fpDmpFile);
978 
979 	/* Write Legend String to the DMP File, including a Null Byte */
980 	(void) emlxs_fprintf(fpDmpFile, "%s: %s", pSidLegend, pLidLegend);
981 	emlxs_fputc(0, fpDmpFile);
982 
983 	/* Write Argument SID to the DMP File */
984 	emlxs_fputc(sid, fpDmpFile);
985 
986 	/* Write Buffer Length to the DMP File */
987 	length = (uint32_t)(strlen(pString) + 1);
988 #ifdef EMLXS_LITTLE_ENDIAN
989 	byte = (uint8_t)(length & 0x0000FF);
990 	emlxs_fputc(byte, fpDmpFile);
991 	byte = (uint8_t)((length & 0x00FF00) >> 8);
992 	emlxs_fputc(byte, fpDmpFile);
993 	byte = (uint8_t)((length & 0xFF0000) >> 16);
994 	emlxs_fputc(byte, fpDmpFile);
995 #endif /* EMLXS_LITTLE_ENDIAN */
996 
997 #ifdef EMLXS_BIG_ENDIAN
998 	byte = (uint8_t)((length & 0xFF0000) >> 16);
999 	emlxs_fputc(byte, fpDmpFile);
1000 	byte = (uint8_t)((length & 0x00FF00) >> 8);
1001 	emlxs_fputc(byte, fpDmpFile);
1002 	byte = (uint8_t)(length & 0x0000FF);
1003 	emlxs_fputc(byte, fpDmpFile);
1004 #endif /* EMLXS_BIG_ENDIAN */
1005 
1006 	/* Write Argument String to the DMP File, including a Null Byte */
1007 	(void) emlxs_fwrite((uint8_t *)pString, strlen(pString), 1, fpDmpFile);
1008 	emlxs_fputc(0, fpDmpFile);
1009 
1010 	emlxs_fflush(fpDmpFile);
1011 
1012 #if CC_DUMP_ENABLE_PAD
1013 	/* check file size.. pad as necessary */
1014 	pos = emlxs_ftell(fpDmpFile);
1015 	switch (pos & 0x03) {
1016 	case 0:
1017 		break;
1018 	case 1:
1019 		emlxs_fputc(0, fpDmpFile);
1020 		emlxs_fputc(0, fpDmpFile);
1021 		emlxs_fputc(0, fpDmpFile);
1022 		break;
1023 	case 2:
1024 		emlxs_fputc(0, fpDmpFile);
1025 		emlxs_fputc(0, fpDmpFile);
1026 		break;
1027 	case 3:
1028 		emlxs_fputc(0, fpDmpFile);
1029 		break;
1030 	}
1031 	emlxs_fflush(fpDmpFile);
1032 #endif
1033 
1034 	return (0);
1035 
1036 } /* emlxs_dump_string_dmpfile() */
1037 
1038 
1039 /* ************************************************************************** */
1040 /* emlxs_dump_word_dmpfile */
1041 /* If little endian, just write the buffer normally. */
1042 /* However, if Big Endian... Consider the following: */
1043 /* Automatic Dump, initiated by driver, Port Offline (FW WarmStart Mode), */
1044 /* Mailbox in SLIM. */
1045 /* On-Demand Dump, initiated by utility, Port Online (FW Normal Mode), */
1046 /* Mailbox in Host Memory. */
1047 /* We use the same IOCTL to get the DUMP Data, for both cases. */
1048 /* However, it normalizes the data before delivering it to us. */
1049 /* In the Dump File, we must always write the data in native mode. */
1050 /* So, if Big Endian, On-demand Dump, we must swap the words. */
1051 /* ************************************************************************* */
1052 /*ARGSUSED*/
1053 extern uint32_t
1054 emlxs_dump_word_dmpfile(
1055 	emlxs_file_t *fpDmpFile,
1056 	uint8_t *pBuffer,
1057 	uint32_t bufferLen,
1058 	int fSwap)
1059 {
1060 	uint32_t i;
1061 	uint32_t *wptr;
1062 
1063 	if (!fpDmpFile) {
1064 		return (1);
1065 	}
1066 
1067 	wptr = (uint32_t *)pBuffer;
1068 	for (i = 0; i < bufferLen / 4; i++, wptr++) {
1069 		if (fSwap) {
1070 			uint32_t w1;
1071 			w1 = *wptr;
1072 			*wptr = BE_SWAP32(w1);
1073 		}
1074 
1075 		(void) emlxs_fwrite((uint8_t *)wptr, 4, 1, fpDmpFile);
1076 	}
1077 
1078 	emlxs_fflush(fpDmpFile);
1079 
1080 	return (0);
1081 
1082 } /* emlxs_dump_word_dmpfile() */
1083 
1084 
1085 static uint32_t
1086 emlxs_dump_port_block(
1087 	emlxs_file_t *fpDmpFile,
1088 	uint8_t *pBuffer,
1089 	uint32_t bufferLen,
1090 	DUMP_TABLE_ENTRY entry,
1091 	int fSwap)
1092 {
1093 	uint32_t status;
1094 	uint32_t w;
1095 	uint8_t b;
1096 
1097 	if (!fpDmpFile) {
1098 		return (1);
1099 	}
1100 
1101 	/* Write Argument SID to the DMP File */
1102 	b = (uint8_t)entry.un.PortBlock.un.s.sid;
1103 	emlxs_fputc(b, fpDmpFile);
1104 
1105 #ifdef EMLXS_LITTLE_ENDIAN
1106 	/* Write Buffer Length to the DMP File */
1107 	w = entry.un.PortBlock.un.s.bc;
1108 	b = (uint8_t)(w & 0x000000FF);
1109 	emlxs_fputc(b, fpDmpFile);
1110 	b = (uint8_t)((w & 0x0000FF00) >> 8);
1111 	emlxs_fputc(b, fpDmpFile);
1112 	b = (uint8_t)((w & 0x00FF0000) >> 16);
1113 	emlxs_fputc(b, fpDmpFile);
1114 
1115 	/* Write address to the DMP File */
1116 	w = entry.un.PortBlock.un.s.addr;
1117 	b = (uint8_t)(w & 0x000000FF);
1118 	emlxs_fputc(b, fpDmpFile);
1119 	b = (uint8_t)((w & 0x0000FF00) >> 8);
1120 	emlxs_fputc(b, fpDmpFile);
1121 	b = (uint8_t)((w & 0x00FF0000) >> 16);
1122 	emlxs_fputc(b, fpDmpFile);
1123 	b = (uint8_t)((w & 0xFF000000) >> 24);
1124 	emlxs_fputc(b, fpDmpFile);
1125 #endif /* EMLXS_LITTLE_ENDIAN */
1126 
1127 #ifdef EMLXS_BIG_ENDIAN
1128 	/* Write Buffer Length to the DMP File */
1129 	w = entry.un.PortBlock.un.s.bc;
1130 	b = (uint8_t)((w & 0x00FF0000) >> 16);
1131 	emlxs_fputc(b, fpDmpFile);
1132 	b = (uint8_t)((w & 0x0000FF00) >> 8);
1133 	emlxs_fputc(b, fpDmpFile);
1134 	b = (uint8_t)(w & 0x000000FF);
1135 	emlxs_fputc(b, fpDmpFile);
1136 
1137 	/* Write address to the DMP File */
1138 	w = entry.un.PortBlock.un.s.addr;
1139 	b = (uint8_t)((w & 0xFF000000) >> 24);
1140 	emlxs_fputc(b, fpDmpFile);
1141 	b = (uint8_t)((w & 0x00FF0000) >> 16);
1142 	emlxs_fputc(b, fpDmpFile);
1143 	b = (uint8_t)((w & 0x0000FF00) >> 8);
1144 	emlxs_fputc(b, fpDmpFile);
1145 	b = (uint8_t)(w & 0x000000FF);
1146 	emlxs_fputc(b, fpDmpFile);
1147 #endif /* EMLXS_BIG_ENDIAN */
1148 
1149 	status =
1150 	    emlxs_dump_word_dmpfile(fpDmpFile, pBuffer, bufferLen, fSwap);
1151 
1152 	emlxs_fflush(fpDmpFile);
1153 
1154 	return (status);
1155 
1156 } /* emlxs_dump_port_block() */
1157 
1158 
1159 static uint32_t
1160 emlxs_dump_port_struct(
1161 	emlxs_file_t *fpDmpFile,
1162 	uint8_t *pBuffer,
1163 	uint32_t bufferLen,
1164 	DUMP_TABLE_ENTRY entry,
1165 	int fSwap)
1166 {
1167 	uint32_t status;
1168 	uint32_t w;
1169 	uint8_t b;
1170 
1171 	if (!fpDmpFile) {
1172 		return (1);
1173 	}
1174 
1175 	/* Write Argument SID to the DMP File */
1176 	b = (uint8_t)entry.un.PortStruct.un.s.sid;
1177 	emlxs_fputc(b, fpDmpFile);
1178 
1179 	/* Write Element Length to the DMP File */
1180 	b = (uint8_t)entry.un.PortStruct.un.s.length;
1181 	emlxs_fputc(b, fpDmpFile);
1182 
1183 #ifdef EMLXS_LITTLE_ENDIAN
1184 	/* Write Element Count to the DMP File */
1185 	w = entry.un.PortStruct.un.s.count;
1186 	b = (uint8_t)(w & 0x000000FF);
1187 	emlxs_fputc(b, fpDmpFile);
1188 	b = (uint8_t)((w & 0x0000FF00) >> 8);
1189 	emlxs_fputc(b, fpDmpFile);
1190 
1191 	/* Write Address to the DMP File */
1192 	w = entry.un.PortStruct.un.s.addr;
1193 	b = (uint8_t)(w & 0x000000FF);
1194 	emlxs_fputc(b, fpDmpFile);
1195 	b = (uint8_t)((w & 0x0000FF00) >> 8);
1196 	emlxs_fputc(b, fpDmpFile);
1197 	b = (uint8_t)((w & 0x00FF0000) >> 16);
1198 	emlxs_fputc(b, fpDmpFile);
1199 	b = (uint8_t)((w & 0xFF000000) >> 24);
1200 	emlxs_fputc(b, fpDmpFile);
1201 #endif /* EMLXS_LITTLE_ENDIAN */
1202 
1203 #ifdef EMLXS_BIG_ENDIAN
1204 	/* Write Element Count to the DMP File */
1205 	w = entry.un.PortStruct.un.s.count;
1206 	b = (uint8_t)((w & 0x0000FF00) >> 8);
1207 	emlxs_fputc(b, fpDmpFile);
1208 	b = (uint8_t)(w & 0x000000FF);
1209 	emlxs_fputc(b, fpDmpFile);
1210 
1211 	/* Write Address to the DMP File */
1212 	w = entry.un.PortStruct.un.s.addr;
1213 	b = (uint8_t)((w & 0xFF000000) >> 24);
1214 	emlxs_fputc(b, fpDmpFile);
1215 	b = (uint8_t)((w & 0x00FF0000) >> 16);
1216 	emlxs_fputc(b, fpDmpFile);
1217 	b = (uint8_t)((w & 0x0000FF00) >> 8);
1218 	emlxs_fputc(b, fpDmpFile);
1219 	b = (uint8_t)(w & 0x000000FF);
1220 	emlxs_fputc(b, fpDmpFile);
1221 #endif /* EMLXS_BIG_ENDIAN */
1222 
1223 	status =
1224 	    emlxs_dump_word_dmpfile(fpDmpFile, pBuffer, bufferLen, fSwap);
1225 
1226 	emlxs_fflush(fpDmpFile);
1227 
1228 	return (status);
1229 
1230 } /* emlxs_dump_port_struct() */
1231 
1232 
1233 static uint32_t
1234 emlxs_dump_host_block(
1235 	emlxs_file_t *fpDmpFile,
1236 	uint8_t *pBuffer,
1237 	uint32_t bufferLen,
1238 	uint8_t sid,
1239 	char *pSidLegend,
1240 	char *pLidLegend,
1241 	int fSwap)
1242 {
1243 	uint32_t status;
1244 	uint32_t length;
1245 	uint8_t byte;
1246 
1247 	if (!fpDmpFile) {
1248 		return (1);
1249 	}
1250 
1251 	/* Write Legend SID to the DMP File */
1252 	emlxs_fputc(SID_LEGEND, fpDmpFile);
1253 
1254 	/* Write Argument SID to the DMP File */
1255 	emlxs_fputc(sid, fpDmpFile);
1256 
1257 	/* Write Legend String to the DMP File, including a Null Byte */
1258 	(void) emlxs_fprintf(fpDmpFile, "%s: %s", pSidLegend, pLidLegend);
1259 	emlxs_fputc(0, fpDmpFile);
1260 
1261 	/* Write Argument SID to the DMP File */
1262 	emlxs_fputc(sid, fpDmpFile);
1263 
1264 	/* Write Buffer Length to the DMP File */
1265 	length = bufferLen;
1266 #ifdef EMLXS_LITTLE_ENDIAN
1267 	byte = (uint8_t)(length & 0x0000FF);
1268 	emlxs_fputc(byte, fpDmpFile);
1269 	byte = (uint8_t)((length & 0x00FF00) >> 8);
1270 	emlxs_fputc(byte, fpDmpFile);
1271 	byte = (uint8_t)((length & 0xFF0000) >> 16);
1272 	emlxs_fputc(byte, fpDmpFile);
1273 #endif /* EMLXS_LITTLE_ENDIAN */
1274 
1275 #ifdef EMLXS_BIG_ENDIAN
1276 	byte = (uint8_t)((length & 0xFF0000) >> 16);
1277 	emlxs_fputc(byte, fpDmpFile);
1278 	byte = (uint8_t)((length & 0x00FF00) >> 8);
1279 	emlxs_fputc(byte, fpDmpFile);
1280 	byte = (uint8_t)(length & 0x0000FF);
1281 	emlxs_fputc(byte, fpDmpFile);
1282 #endif /* EMLXS_BIG_ENDIAN */
1283 
1284 	status =
1285 	    emlxs_dump_word_dmpfile(fpDmpFile, pBuffer, bufferLen, fSwap);
1286 
1287 	emlxs_fflush(fpDmpFile);
1288 
1289 	return (status);
1290 
1291 } /* emlxs_dump_host_block() */
1292 
1293 
1294 static uint32_t
1295 emlxs_dump_host_struct(
1296 	emlxs_file_t *fpDmpFile,
1297 	uint8_t *pBuffer,
1298 	uint32_t bufferLen,
1299 	uint32_t elementLength,
1300 	uint32_t elementCount,
1301 	uint8_t sid,
1302 	char *pSidLegend,
1303 	char *pLidLegend,
1304 	int fSwap)
1305 {
1306 	uint32_t status;
1307 	uint32_t w;
1308 	uint8_t b;
1309 
1310 	if (!fpDmpFile) {
1311 		return (1);
1312 	}
1313 
1314 	/* Write Legend SID to the DMP File */
1315 	emlxs_fputc(SID_LEGEND, fpDmpFile);
1316 
1317 	/* Write Argument SID to the DMP File */
1318 	emlxs_fputc(sid, fpDmpFile);
1319 
1320 	/* Write Legend String to the DMP File, including a Null Byte */
1321 	(void) emlxs_fprintf(fpDmpFile, "%s: %s", pSidLegend, pLidLegend);
1322 	emlxs_fputc(0, fpDmpFile);
1323 
1324 	/* Write Argument SID to the DMP File */
1325 	emlxs_fputc(sid, fpDmpFile);
1326 
1327 	/* Write Element Length to the DMP File */
1328 	b = (uint8_t)elementLength;
1329 	emlxs_fputc(b, fpDmpFile);
1330 
1331 	/* Write Element Count to the DMP File */
1332 	w = elementCount;
1333 #ifdef EMLXS_LITTLE_ENDIAN
1334 	b = (uint8_t)(w & 0x000000FF);
1335 	emlxs_fputc(b, fpDmpFile);
1336 	b = (uint8_t)((w & 0x0000FF00) >> 8);
1337 	emlxs_fputc(b, fpDmpFile);
1338 #endif /* EMLXS_LITTLE_ENDIAN */
1339 
1340 #ifdef EMLXS_BIG_ENDIAN
1341 	b = (uint8_t)((w & 0x0000FF00) >> 8);
1342 	emlxs_fputc(b, fpDmpFile);
1343 	b = (uint8_t)(w & 0x000000FF);
1344 	emlxs_fputc(b, fpDmpFile);
1345 #endif /* EMLXS_BIG_ENDIAN */
1346 
1347 	status =
1348 	    emlxs_dump_word_dmpfile(fpDmpFile, pBuffer, bufferLen, fSwap);
1349 
1350 	emlxs_fflush(fpDmpFile);
1351 
1352 	return (status);
1353 
1354 } /* emlxs_dump_host_struct() */
1355 
1356 
1357 /* ************************************************************************* */
1358 /* ************************************************************************* */
1359 /* Dump Generators, Mid-Level */
1360 /* ************************************************************************* */
1361 /* ************************************************************************* */
1362 
1363 static uint32_t
1364 emlxs_dump_parm_table(
1365 	emlxs_hba_t *hba,
1366 	emlxs_file_t *fpTxtFile,
1367 	emlxs_file_t *fpDmpFile)
1368 {
1369 	emlxs_config_t *cfg = &CFG;
1370 	uint32_t status;
1371 	uint32_t i;
1372 
1373 	/* vars used to build the Dump String */
1374 	char *buf1;
1375 	char *buf2;
1376 
1377 	buf1 = (char *)kmem_zalloc(8192, KM_SLEEP);
1378 	buf2 = (char *)kmem_zalloc(8192, KM_SLEEP);
1379 
1380 	/* Driver Parameters Heading */
1381 	(void) sprintf(buf1,
1382 	    "IDX                     string      Low     "\
1383 	    "High      Def      Cur  Exp  Dyn");
1384 
1385 	/* Build the buffer containing all the Driver Params */
1386 	for (i = 0; i < NUM_CFG_PARAM; i++) {
1387 		(void) sprintf(buf2,
1388 		    "\n  %02x: %25s %8x %8x %8x %8x %4x %4x", i,
1389 		    cfg[i].string, cfg[i].low, cfg[i].hi, cfg[i].def,
1390 		    cfg[i].current, (cfg[i].flags & PARM_HIDDEN) ? 0 : 1,
1391 		    (cfg[i].flags & PARM_DYNAMIC) ? 1 : 0);
1392 
1393 		(void) strcat(buf1, buf2);
1394 	}
1395 
1396 	status =
1397 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_DP_TABLE,
1398 	    LEGEND_NULL, 0);
1399 
1400 	status =
1401 	    emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_DP_TABLE,
1402 	    LEGEND_DP_TABLE, LEGEND_NULL);
1403 
1404 	kmem_free(buf1, 8192);
1405 	kmem_free(buf2, 8192);
1406 
1407 	return (status);
1408 
1409 } /* emlxs_dump_parm_table() */
1410 
1411 
1412 static uint32_t
1413 emlxs_dump_model(
1414 	emlxs_hba_t *hba,
1415 	emlxs_file_t *fpTxtFile,
1416 	emlxs_file_t *fpDmpFile)
1417 {
1418 	emlxs_vpd_t *vpd = &VPD;
1419 	uint32_t status;
1420 
1421 	/* vars used to build the Dump String */
1422 	char buf1[512];
1423 	char buf2[512];
1424 
1425 	/* Write the Model into the buffer */
1426 	(void) sprintf(buf2, "%s", vpd->model);
1427 	(void) strcpy(buf1, "Model: ");
1428 	(void) strcat(buf1, buf2);
1429 
1430 	/* Write the Model Description into the buffer */
1431 	(void) sprintf(buf2, "%s", vpd->model_desc);
1432 	(void) strcat(buf1, "\n Description: ");
1433 	(void) strcat(buf1, buf2);
1434 
1435 	status =
1436 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_INFO,
1437 	    LEGEND_HBA_MODEL, 0);
1438 
1439 	status =
1440 	    emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_HBA_INFO,
1441 	    LEGEND_HBA_INFO, LEGEND_HBA_MODEL);
1442 
1443 	return (status);
1444 
1445 } /* emlxs_dump_model() */
1446 
1447 
1448 static uint32_t
1449 emlxs_dump_wwn(
1450 	emlxs_hba_t *hba,
1451 	emlxs_file_t *fpTxtFile,
1452 	emlxs_file_t *fpDmpFile)
1453 {
1454 	uint32_t status;
1455 
1456 	/* vars used to build the Dump String */
1457 	char buf1[512];
1458 	char buf2[512];
1459 	int i;
1460 	uint8_t *p;
1461 
1462 	/* Write the WWPN into the buffer */
1463 	(void) strcpy(buf1, "Port WWN: ");
1464 	p = (uint8_t *)&hba->wwpn;
1465 	for (i = 0; i < 7; i++) {
1466 		(void) sprintf(buf2, "%02x:", *p++);
1467 		(void) strcat(buf1, buf2);
1468 	}
1469 	(void) sprintf(buf2, "%02x", *p++);
1470 	(void) strcat(buf1, buf2);
1471 
1472 	/* Write the WWNN into the buffer */
1473 	(void) strcat(buf1, "\n Node WWN: ");
1474 	p = (uint8_t *)&hba->wwnn;
1475 	for (i = 0; i < 7; i++) {
1476 		(void) sprintf(buf2, "%02x:", *p++);
1477 		(void) strcat(buf1, buf2);
1478 	}
1479 	(void) sprintf(buf2, "%02x", *p++);
1480 	(void) strcat(buf1, buf2);
1481 
1482 	status =
1483 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_INFO,
1484 	    LEGEND_HBA_WWN, 0);
1485 
1486 	status =
1487 	    emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_HBA_INFO,
1488 	    LEGEND_HBA_INFO, LEGEND_HBA_WWN);
1489 
1490 	return (status);
1491 
1492 } /* emlxs_dump_wwn() */
1493 
1494 
1495 static uint32_t
1496 emlxs_dump_serial_number(
1497 	emlxs_hba_t *hba,
1498 	emlxs_file_t *fpTxtFile,
1499 	emlxs_file_t *fpDmpFile)
1500 {
1501 	emlxs_vpd_t *vpd = &VPD;
1502 	uint32_t status;
1503 
1504 	/* vars used to build the Dump String */
1505 	char buf1[512];
1506 	char buf2[512];
1507 
1508 	/* Write the Serial Number into the buffer */
1509 	(void) sprintf(buf2, "%s", vpd->serial_num);
1510 	(void) strcpy(buf1, LEGEND_HBA_SN);
1511 	(void) strcat(buf1, ": ");
1512 	(void) strcat(buf1, buf2);
1513 
1514 	status =
1515 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_INFO,
1516 	    LEGEND_HBA_SN, 0);
1517 
1518 	status =
1519 	    emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_HBA_INFO,
1520 	    LEGEND_HBA_INFO, LEGEND_HBA_SN);
1521 
1522 	return (status);
1523 
1524 } /* emlxs_dump_serial_number() */
1525 
1526 
1527 static uint32_t
1528 emlxs_dump_fw_version(
1529 	emlxs_hba_t *hba,
1530 	emlxs_file_t *fpTxtFile,
1531 	emlxs_file_t *fpDmpFile)
1532 {
1533 	emlxs_vpd_t *vpd = &VPD;
1534 	uint32_t status;
1535 
1536 	char *buf1;
1537 	char *buf2;
1538 	uint32_t buf1_size;
1539 	uint32_t buf2_size;
1540 
1541 	buf1_size = 1024;
1542 	buf2_size = 1024;
1543 
1544 	buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP);
1545 	buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP);
1546 
1547 	/* Write the Firmware Version into the buffer */
1548 	(void) sprintf(buf2, "%s", vpd->fw_version);
1549 	(void) strcpy(buf1, LEGEND_HBA_FW_VERSION);
1550 	(void) strcat(buf1, ": ");
1551 	(void) strcat(buf1, buf2);
1552 
1553 	/* Write the Operational FW Version into the buffer */
1554 	(void) sprintf(buf2, "%s", vpd->opFwName);
1555 	(void) strcat(buf1, "\n ");
1556 	(void) strcat(buf1, LEGEND_HBA_FW_OPVERSION);
1557 	(void) strcat(buf1, ": ");
1558 	(void) strcat(buf1, buf2);
1559 
1560 	/* Write the SLI-1 FW Version into the buffer */
1561 	(void) sprintf(buf2, "%s", vpd->sli1FwName);
1562 	(void) strcat(buf1, "\n ");
1563 	(void) strcat(buf1, LEGEND_HBA_FW_SLI1VERSION);
1564 	(void) strcat(buf1, ": ");
1565 	(void) strcat(buf1, buf2);
1566 
1567 	/* Write the SLI-2 FW Version into the buffer */
1568 	(void) sprintf(buf2, "%s", vpd->sli2FwName);
1569 	(void) strcat(buf1, "\n ");
1570 	(void) strcat(buf1, LEGEND_HBA_FW_SLI2VERSION);
1571 	(void) strcat(buf1, ": ");
1572 	(void) strcat(buf1, buf2);
1573 
1574 	/* Write the SLI-3 FW Version into the buffer */
1575 	(void) sprintf(buf2, "%s", vpd->sli3FwName);
1576 	(void) strcat(buf1, "\n ");
1577 	(void) strcat(buf1, LEGEND_HBA_FW_SLI3VERSION);
1578 	(void) strcat(buf1, ": ");
1579 	(void) strcat(buf1, buf2);
1580 
1581 	/* Write the Kernel FW Version into the buffer */
1582 	(void) sprintf(buf2, "%s", vpd->postKernName);
1583 	(void) strcat(buf1, "\n ");
1584 	(void) strcat(buf1, LEGEND_HBA_FW_KERNELVERSION);
1585 	(void) strcat(buf1, ": ");
1586 	(void) strcat(buf1, buf2);
1587 
1588 	status =
1589 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_INFO,
1590 	    LEGEND_HBA_FW_VERSION, 0);
1591 
1592 	status =
1593 	    emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_HBA_INFO,
1594 	    LEGEND_HBA_INFO, LEGEND_HBA_FW_VERSION);
1595 
1596 	kmem_free(buf1, buf1_size);
1597 	kmem_free(buf2, buf2_size);
1598 
1599 	return (status);
1600 
1601 } /* emlxs_dump_fw_version() */
1602 
1603 
1604 static uint32_t
1605 emlxs_dump_boot_version(
1606 	emlxs_hba_t *hba,
1607 	emlxs_file_t *fpTxtFile,
1608 	emlxs_file_t *fpDmpFile)
1609 {
1610 	emlxs_vpd_t *vpd = &VPD;
1611 	uint32_t status;
1612 	uint32_t state;
1613 
1614 	char *buf1;
1615 	char *buf2;
1616 	uint32_t buf1_size;
1617 	uint32_t buf2_size;
1618 
1619 	buf1_size = 1024;
1620 	buf2_size = 1024;
1621 
1622 	buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP);
1623 	buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP);
1624 
1625 #ifdef EMLXS_SPARC
1626 	if (strcmp(vpd->fcode_version, "none") == 0)
1627 #else
1628 	if (strcmp(vpd->boot_version, "none") == 0)
1629 #endif /* EMLXS_SPARC */
1630 	{
1631 		state = 2;	/* BOOT_BIOS_NOT_PRESENT */
1632 	} else {
1633 		state = emlxs_boot_code_state(hba);
1634 	}
1635 
1636 	/* Write the Boot Bios State into the buffer */
1637 	(void) sprintf(buf2, " %d", state);
1638 	(void) strcpy(buf1, LEGEND_HBA_BB_STATE);
1639 	(void) strcat(buf1, ": ");
1640 	(void) strcat(buf1, buf2);
1641 
1642 	/* Write the Boot Bios Version into the buffer */
1643 	if (state == 2) {
1644 		(void) sprintf(buf2, "%s", "unknown");
1645 	} else {
1646 #ifdef EMLXS_SPARC
1647 		(void) sprintf(buf2, "%s (FCode)", vpd->fcode_version);
1648 #else
1649 		(void) sprintf(buf2, "%s", vpd->boot_version);
1650 #endif /* EMLXS_SPARC */
1651 	}
1652 
1653 	(void) strcat(buf1, "\n ");
1654 	(void) strcat(buf1, LEGEND_HBA_BB_VERSION);
1655 	(void) strcat(buf1, ": ");
1656 	(void) strcat(buf1, buf2);
1657 
1658 	status =
1659 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_INFO,
1660 	    LEGEND_HBA_BB_VERSION, 0);
1661 
1662 	status =
1663 	    emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_HBA_INFO,
1664 	    LEGEND_HBA_INFO, LEGEND_HBA_BB_VERSION);
1665 
1666 	kmem_free(buf1, buf1_size);
1667 	kmem_free(buf2, buf2_size);
1668 
1669 	return (status);
1670 
1671 } /* emlxs_dump_boot_version() */
1672 
1673 
1674 /* ARGSUSED */
1675 static uint32_t
1676 emlxs_dump_cfg_region4_decoded(
1677 	emlxs_hba_t *hba,
1678 	emlxs_file_t *fpTxtFile,
1679 	char *pLidLegend,
1680 	DUMP_WAKE_UP_PARAMS *pBuffer,
1681 	uint32_t ByteCount)
1682 {
1683 	uint32_t status;
1684 	char *buf1;	/* text buffer */
1685 	char *buf2;	/* text buffer */
1686 	uint32_t buf1_size;
1687 	uint32_t buf2_size;
1688 
1689 	buf1_size = 1024;
1690 	buf2_size = 1024;
1691 
1692 	buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP);
1693 	buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP);
1694 
1695 	/* Write the Initial ID into the buffer */
1696 	(void) sprintf(buf2, "%s: %08x %08x", LEGEND_CR4_INITIAL_LOAD,
1697 	    pBuffer->InitialId[0], pBuffer->InitialId[1]);
1698 	(void) strcat(buf1, buf2);
1699 
1700 	/* Write the Flags Word into the buffer */
1701 	(void) sprintf(buf2, "\n %s: %08x", LEGEND_CR4_FLAGS, pBuffer->Flags);
1702 	(void) strcat(buf1, buf2);
1703 
1704 	/* Write the Boot Bios ID into the buffer */
1705 	(void) sprintf(buf2, "\n %s: %08x %08x", LEGEND_CR4_BOOT_BIOS_ID,
1706 	    pBuffer->BootBiosId[0], pBuffer->BootBiosId[1]);
1707 	(void) strcat(buf1, buf2);
1708 
1709 	/* Write the SLI1 ID into the buffer */
1710 	(void) sprintf(buf2, "\n %s: %08x %08x", LEGEND_CR4_SLI1_ID,
1711 	    pBuffer->Sli1Id[0], pBuffer->Sli1Id[1]);
1712 	(void) strcat(buf1, buf2);
1713 
1714 	/* Write the SLI2 ID into the buffer */
1715 	(void) sprintf(buf2, "\n %s: %08x %08x", LEGEND_CR4_SLI2_ID,
1716 	    pBuffer->Sli2Id[0], pBuffer->Sli2Id[1]);
1717 	(void) strcat(buf1, buf2);
1718 
1719 	/* Write the SLI3 ID into the buffer */
1720 	(void) sprintf(buf2, "\n %s: %08x %08x", LEGEND_CR4_SLI3_ID,
1721 	    pBuffer->Sli3Id[0], pBuffer->Sli3Id[1]);
1722 	(void) strcat(buf1, buf2);
1723 
1724 	/* Write the SLI4 ID into the buffer */
1725 	(void) sprintf(buf2, "\n %s: %08x %08x", LEGEND_CR4_SLI4_ID,
1726 	    pBuffer->Sli4Id[0], pBuffer->Sli4Id[1]);
1727 	(void) strcat(buf1, buf2);
1728 
1729 	/* Write the Erom ID into the buffer */
1730 	(void) sprintf(buf2, "\n %s: %08x %08x", LEGEND_CR4_EROM_ID,
1731 	    pBuffer->EromId[0], pBuffer->EromId[1]);
1732 	(void) strcat(buf1, buf2);
1733 
1734 	status =
1735 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_CONFIG_REGION,
1736 	    LEGEND_CONFIG_REGION_4, 0);
1737 
1738 	kmem_free(buf1, buf1_size);
1739 	kmem_free(buf2, buf2_size);
1740 
1741 	return (status);
1742 
1743 } /* emlxs_dump_cfg_region4_decoded() */
1744 
1745 
1746 /* ARGSUSED */
1747 uint32_t
1748 emlxs_dump_cfg_region14_decoded(
1749 	emlxs_hba_t *hba,
1750 	emlxs_file_t *fpTxtFile,
1751 	char *pLidLegend,
1752 	char *pBuffer,
1753 	uint32_t ByteCount)
1754 {
1755 	uint32_t status;
1756 	char *buf1;	/* text buffer */
1757 	char *buf2;	/* text buffer */
1758 	uint32_t buf1_size;
1759 	uint32_t buf2_size;
1760 	int i;
1761 	uint8_t tag;
1762 	uint16_t length;
1763 	uint16_t length2;
1764 	char mnemonic[4];
1765 	int fDone = FALSE;	/* flag to exit VPD loop */
1766 
1767 #ifdef EMLXS_BIG_ENDIAN
1768 	uint32_t *wptr;
1769 	uint32_t w1;
1770 #endif
1771 
1772 	buf1_size = 1024;
1773 	buf2_size = 1024;
1774 
1775 	buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP);
1776 	buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP);
1777 
1778 /* If Big Endian, swap the data in place, */
1779 /* because it's PCI Data (Little Endian) */
1780 #ifdef EMLXS_BIG_ENDIAN
1781 	wptr = (uint32_t *)pBuffer;
1782 	for (i = 0; i < (int)ByteCount / 4; i++, wptr++) {
1783 		w1 = *wptr;
1784 		*wptr = BE_SWAP32(w1);
1785 	}
1786 #endif /* EMLXS_BIG_ENDIAN */
1787 
1788 	/* Decode the VPD Data and write it into the buffer */
1789 
1790 	/* CR 26941 */
1791 	/* NOTE: The following code is correct, */
1792 	/* should work, and used to work. */
1793 	/* pBuffer points to char, and the symbol VPD_TAG_82 is 0x82. */
1794 	/* The test is an equality test, not a relational test. */
1795 	/* The compiler should generate an 8 bit test, and */
1796 	/* sign extension does not apply. */
1797 	/* I don't know when or why it stopped working, */
1798 	/* and don't have time to dig. */
1799 	/* The cast fixes it. */
1800 
1801 	if (((unsigned char)pBuffer[0]) != VPD_TAG_82) {
1802 		(void) sprintf(buf1, "Bad VPD Data: (w0=0x%08x)",
1803 		    *(uint32_t *)pBuffer);
1804 	} else {	/* begin good data */
1805 		i = 0;
1806 		while (!fDone) {
1807 			tag = pBuffer[i++];
1808 			length = pBuffer[i++];
1809 			length |= (pBuffer[i++] << 8);
1810 
1811 			switch (tag) {
1812 			case VPD_TAG_82:
1813 				(void) strncpy(buf2, &pBuffer[i],
1814 				    length > buf2_size ? buf2_size : length);
1815 				buf2[length >
1816 				    (buf2_size - 1) ? (buf2_size -
1817 				    1) : length] = 0;
1818 				(void) strcat(buf1, "Name: ");
1819 				(void) strcat(buf1, buf2);
1820 				i += length;
1821 				break;
1822 
1823 			case VPD_TAG_90:
1824 				for (;;) {
1825 					mnemonic[0] = pBuffer[i++];
1826 					mnemonic[1] = pBuffer[i++];
1827 					mnemonic[2] = 0;
1828 
1829 					if (strcmp(mnemonic, "RV") == 0) {
1830 						fDone = TRUE;
1831 						break;
1832 					}
1833 
1834 					if (mnemonic[0] == 0) {
1835 						fDone = TRUE;
1836 						break;
1837 					}
1838 
1839 					length2 = pBuffer[i++];
1840 					(void) sprintf(buf2, "\n %s: ",
1841 					    mnemonic);
1842 					(void) strcat(buf1, buf2);
1843 					(void) strncpy(buf2, &pBuffer[i],
1844 					    length2 >
1845 					    buf2_size ? buf2_size : length2);
1846 					buf2[length2 >
1847 					    (buf2_size - 1) ? (buf2_size -
1848 					    1) : length2] = 0;
1849 					(void) strcat(buf1, buf2);
1850 					i += length2;
1851 				}
1852 				break;
1853 
1854 			default:
1855 				break;
1856 
1857 			}	/* end switch */
1858 
1859 		}	/* end while */
1860 
1861 	}	/* good data */
1862 
1863 	status =
1864 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_CONFIG_REGION,
1865 	    LEGEND_CONFIG_REGION_14, 0);
1866 
1867 	kmem_free(buf1, buf1_size);
1868 	kmem_free(buf2, buf2_size);
1869 
1870 	return (status);
1871 
1872 } /* emlxs_dump_cfg_region14_decoded() */
1873 
1874 
1875 static uint32_t
1876 emlxs_dump_cfg_region(
1877 	emlxs_hba_t *hba,
1878 	emlxs_file_t *fpTxtFile,
1879 	emlxs_file_t *fpDmpFile,
1880 	uint8_t Region,
1881 	char *pLidLegend,
1882 	int fSwap)
1883 {
1884 	uint32_t status;
1885 	uint32_t RetByteCount = 0;	/* returned byte count */
1886 	char *buf1;	/* string ops buffer */
1887 	char *buf2;	/* string ops buffer */
1888 	uint32_t buf1_size;
1889 	uint32_t buf2_size;
1890 	uint32_t *buffer;
1891 	int i;
1892 
1893 #ifdef EMLXS_LITTLE_ENDIAN
1894 	fSwap = FALSE;
1895 #endif /* EMLXS_LITTLE_ENDIAN */
1896 
1897 	buf1_size = 4096;
1898 	buf2_size = 1024;
1899 
1900 	buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP);
1901 	buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP);
1902 
1903 	buffer =
1904 	    (uint32_t *)kmem_zalloc(DUMP_MAX_CONFIG_REGION_LENGTH, KM_SLEEP);
1905 
1906 	status =
1907 	    emlxs_read_cfg_region(hba, Region, DUMP_MAX_CONFIG_REGION_LENGTH,
1908 	    &RetByteCount, (uint8_t *)buffer);
1909 
1910 	if (status != 0) {
1911 		kmem_free(buffer, DUMP_MAX_CONFIG_REGION_LENGTH);
1912 		kmem_free(buf1, buf1_size);
1913 		kmem_free(buf2, buf2_size);
1914 		return (status);
1915 	}
1916 
1917 	/* Write the Data into the buffer */
1918 	for (i = 0; i < (int)RetByteCount / 4; i++) {
1919 		if ((i % 8 == 0) && (i != 0)) {
1920 			(void) strcat((char *)buf1, "\n ");
1921 		}
1922 
1923 		(void) sprintf(buf2, "%08x, ", buffer[i]);
1924 		(void) strcat((char *)buf1, buf2);
1925 	}
1926 
1927 	status =
1928 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_CONFIG_REGION,
1929 	    pLidLegend, 0);
1930 
1931 	status = emlxs_dump_host_block(fpDmpFile,
1932 	    (uint8_t *)buffer,
1933 	    RetByteCount,
1934 	    SID_CONFIG_REGION, LEGEND_CONFIG_REGION, pLidLegend, fSwap);
1935 
1936 	if (Region == 4) {
1937 		status =
1938 		    emlxs_dump_cfg_region4_decoded(hba, fpTxtFile, pLidLegend,
1939 		    (DUMP_WAKE_UP_PARAMS *)buffer, RetByteCount);
1940 	}
1941 
1942 	if (Region == 14) {
1943 		status =
1944 		    emlxs_dump_cfg_region14_decoded(hba, fpTxtFile,
1945 		    pLidLegend, (char *)buffer, RetByteCount);
1946 	}
1947 
1948 	kmem_free(buffer, DUMP_MAX_CONFIG_REGION_LENGTH);
1949 	kmem_free(buf1, buf1_size);
1950 	kmem_free(buf2, buf2_size);
1951 
1952 	return (status);
1953 
1954 } /* emlxs_dump_cfg_region() */
1955 
1956 
1957 static uint32_t
1958 emlxs_dump_cfg_regions(
1959 	emlxs_hba_t *hba,
1960 	emlxs_file_t *fpTxtFile,
1961 	emlxs_file_t *fpDmpFile)
1962 {
1963 	uint32_t status;
1964 
1965 	status =
1966 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 0,
1967 	    LEGEND_CONFIG_REGION_0, FALSE);
1968 
1969 	status =
1970 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 1,
1971 	    LEGEND_CONFIG_REGION_1, FALSE);
1972 
1973 	status =
1974 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 2,
1975 	    LEGEND_CONFIG_REGION_2, FALSE);
1976 
1977 	status =
1978 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 3,
1979 	    LEGEND_CONFIG_REGION_3, FALSE);
1980 
1981 	status =
1982 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 4,
1983 	    LEGEND_CONFIG_REGION_4, FALSE);
1984 
1985 	status =
1986 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 5,
1987 	    LEGEND_CONFIG_REGION_5, FALSE);
1988 
1989 	status =
1990 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 6,
1991 	    LEGEND_CONFIG_REGION_6, FALSE);
1992 
1993 	status =
1994 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 7,
1995 	    LEGEND_CONFIG_REGION_7, FALSE);
1996 
1997 	status =
1998 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 8,
1999 	    LEGEND_CONFIG_REGION_8, TRUE);
2000 
2001 	status =
2002 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 9,
2003 	    LEGEND_CONFIG_REGION_9, TRUE);
2004 
2005 	status =
2006 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 10,
2007 	    LEGEND_CONFIG_REGION_10, TRUE);
2008 
2009 	status =
2010 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 11,
2011 	    LEGEND_CONFIG_REGION_11, FALSE);
2012 
2013 	status =
2014 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 12,
2015 	    LEGEND_CONFIG_REGION_12, FALSE);
2016 
2017 	status =
2018 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 13,
2019 	    LEGEND_CONFIG_REGION_13, FALSE);
2020 
2021 	status =
2022 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 14,
2023 	    LEGEND_CONFIG_REGION_14, FALSE);
2024 
2025 	status =
2026 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 15,
2027 	    LEGEND_CONFIG_REGION_15, FALSE);
2028 
2029 	status =
2030 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 16,
2031 	    LEGEND_CONFIG_REGION_16, FALSE);
2032 
2033 	status =
2034 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 17,
2035 	    LEGEND_CONFIG_REGION_17, FALSE);
2036 
2037 	status =
2038 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 18,
2039 	    LEGEND_CONFIG_REGION_18, FALSE);
2040 
2041 	status =
2042 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 19,
2043 	    LEGEND_CONFIG_REGION_19, FALSE);
2044 
2045 	status =
2046 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 20,
2047 	    LEGEND_CONFIG_REGION_20, FALSE);
2048 
2049 	status =
2050 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 21,
2051 	    LEGEND_CONFIG_REGION_21, FALSE);
2052 
2053 	status =
2054 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 22,
2055 	    LEGEND_CONFIG_REGION_22, FALSE);
2056 
2057 	status =
2058 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 23,
2059 	    LEGEND_CONFIG_REGION_23, FALSE);
2060 
2061 	status =
2062 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 24,
2063 	    LEGEND_CONFIG_REGION_24, FALSE);
2064 
2065 	status =
2066 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 25,
2067 	    LEGEND_CONFIG_REGION_25, FALSE);
2068 
2069 	status =
2070 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 26,
2071 	    LEGEND_CONFIG_REGION_26, FALSE);
2072 
2073 	status =
2074 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 27,
2075 	    LEGEND_CONFIG_REGION_27, FALSE);
2076 
2077 	status =
2078 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 28,
2079 	    LEGEND_CONFIG_REGION_28, FALSE);
2080 
2081 	status =
2082 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 29,
2083 	    LEGEND_CONFIG_REGION_29, FALSE);
2084 
2085 	status =
2086 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 30,
2087 	    LEGEND_CONFIG_REGION_30, FALSE);
2088 
2089 	status =
2090 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 31,
2091 	    LEGEND_CONFIG_REGION_31, FALSE);
2092 
2093 	status =
2094 	    emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 32,
2095 	    LEGEND_CONFIG_REGION_32, FALSE);
2096 
2097 	return (status);
2098 
2099 } /* emlxs_dump_cfg_regions() */
2100 
2101 
2102 /*ARGSUSED*/
2103 static uint32_t
2104 emlxs_dump_os_version(
2105 	emlxs_hba_t *hba,
2106 	emlxs_file_t *fpTxtFile,
2107 	emlxs_file_t *fpDmpFile)
2108 {
2109 	uint32_t status;
2110 	char *buf1;
2111 	char *buf2;
2112 	uint32_t buf1_size;
2113 	uint32_t buf2_size;
2114 
2115 	buf1_size = 1024;
2116 	buf2_size = 1024;
2117 
2118 	buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP);
2119 	buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP);
2120 
2121 	/* First, write the OS Name string into the buffer */
2122 	(void) strcpy(buf1, utsname.sysname);
2123 
2124 	/* Second, write the Version Info into the buffer */
2125 	(void) sprintf(buf2, ", %s", utsname.release);
2126 	(void) strcat(buf1, buf2);
2127 
2128 	status =
2129 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_REV_INFO,
2130 	    LEGEND_REV_OS_VERSION, 0);
2131 
2132 	status =
2133 	    emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_REV_INFO,
2134 	    LEGEND_REV_INFO, LEGEND_REV_OS_VERSION);
2135 
2136 	kmem_free(buf1, buf1_size);
2137 	kmem_free(buf2, buf2_size);
2138 
2139 	return (status);
2140 
2141 } /* emlxs_dump_os_version() */
2142 
2143 
2144 /*ARGSUSED*/
2145 static uint32_t
2146 emlxs_dump_drv_version(
2147 	emlxs_hba_t *hba,
2148 	emlxs_file_t *fpTxtFile,
2149 	emlxs_file_t *fpDmpFile)
2150 {
2151 	uint32_t status;
2152 	char *buf1;
2153 	char *buf2;
2154 	uint32_t buf1_size;
2155 	uint32_t buf2_size;
2156 
2157 	buf1_size = 1024;
2158 	buf2_size = 1024;
2159 
2160 	buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP);
2161 	buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP);
2162 
2163 	/* Write the Driver Type into the buffer */
2164 	(void) strcpy(buf1, "Driver Type: ");
2165 	(void) strcat(buf1, DUMP_DRV_LEADVILLE);
2166 
2167 	/* Write the Driver Name into the buffer */
2168 	(void) sprintf(buf2, "%s", DRIVER_NAME);
2169 	(void) strcat(buf1, "\n Driver Name: ");
2170 	(void) strcat(buf1, buf2);
2171 
2172 	/* Write the Driver Version into the buffer */
2173 	(void) sprintf(buf2, "%s", emlxs_version);
2174 	(void) strcat(buf1, "\n Driver Version: ");
2175 	(void) strcat(buf1, buf2);
2176 
2177 	status =
2178 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_REV_INFO,
2179 	    LEGEND_REV_DRV_VERSION, 0);
2180 
2181 	status =
2182 	    emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_REV_INFO,
2183 	    LEGEND_REV_INFO, LEGEND_REV_DRV_VERSION);
2184 
2185 	kmem_free(buf1, buf1_size);
2186 	kmem_free(buf2, buf2_size);
2187 
2188 	return (status);
2189 
2190 } /* emlxs_dump_drv_version() */
2191 
2192 
2193 static uint32_t
2194 emlxs_dump_file_create(
2195 	emlxs_hba_t *hba,
2196 	emlxs_file_t ** fpTxtFile,
2197 	emlxs_file_t ** fpDmpFile,
2198 	emlxs_file_t ** fpCeeFile)
2199 {
2200 	if (fpTxtFile) {
2201 		/* Create the Dump Files */
2202 		if ((*fpTxtFile = emlxs_fopen(hba, EMLXS_TXT_FILE)) == NULL) {
2203 			return (1);
2204 		}
2205 	}
2206 
2207 	if (fpCeeFile) {
2208 		*fpCeeFile = NULL;
2209 
2210 		if ((hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) ||
2211 		    (hba->model_info.chip == EMLXS_BE2_CHIP) ||
2212 		    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
2213 			if ((*fpCeeFile =
2214 			    emlxs_fopen(hba, EMLXS_CEE_FILE)) == NULL) {
2215 				emlxs_fdelete(*fpTxtFile);
2216 				return (1);
2217 			}
2218 		}
2219 	}
2220 
2221 	if (fpDmpFile) {
2222 		if ((*fpDmpFile = emlxs_fopen(hba, EMLXS_DMP_FILE)) == NULL) {
2223 			emlxs_fdelete(*fpTxtFile);
2224 			emlxs_fdelete(*fpCeeFile);
2225 			return (1);
2226 		}
2227 
2228 		/* Initialize the DMP File */
2229 		/* Write the single-byte Dump Identification */
2230 		/* SID to the DMP File */
2231 #ifdef EMLXS_LITTLE_ENDIAN
2232 		emlxs_fputc(SID_DUMP_ID_LE, *fpDmpFile);
2233 #endif /* EMLXS_LITTLE_ENDIAN */
2234 
2235 #ifdef EMLXS_BIG_ENDIAN
2236 		emlxs_fputc(SID_DUMP_ID_BE, *fpDmpFile);
2237 #endif /* EMLXS_BIG_ENDIAN */
2238 
2239 		emlxs_fputc(SID_NULL, *fpDmpFile);
2240 		emlxs_fputc(SID_NULL, *fpDmpFile);
2241 		emlxs_fputc(SID_NULL, *fpDmpFile);
2242 		emlxs_fflush(*fpDmpFile);
2243 	}
2244 
2245 	return (0);
2246 
2247 } /* emlxs_dump_file_create() */
2248 
2249 
2250 static uint32_t
2251 emlxs_dump_file_terminate(
2252 	emlxs_hba_t *hba,
2253 	emlxs_file_t *fpTxtFile,
2254 	emlxs_file_t *fpDmpFile,
2255 	emlxs_file_t *fpCeeFile)
2256 {
2257 
2258 	if (fpTxtFile) {
2259 		/* Write a suitable string to the Dump TXT File */
2260 		(void) emlxs_fprintf(fpTxtFile, "Dump File End\n");
2261 		emlxs_fflush(fpTxtFile);
2262 	}
2263 
2264 	if (fpCeeFile) {
2265 		if (hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) {
2266 			(void) emlxs_fprintf(fpCeeFile, "Dump File End\n");
2267 		}
2268 
2269 		emlxs_fflush(fpCeeFile);
2270 	}
2271 
2272 	/* Write the single-byte Dump Termination SID to the DMP File */
2273 	if (fpDmpFile) {
2274 		emlxs_fputc(SID_DUMP_TERM, fpDmpFile);
2275 		emlxs_fflush(fpDmpFile);
2276 	}
2277 
2278 
2279 	return (0);
2280 
2281 } /* emlxs_dump_file_terminate() */
2282 
2283 
2284 static uint32_t
2285 emlxs_dump_file_close(
2286 	emlxs_file_t *fpTxtFile,
2287 	emlxs_file_t *fpDmpFile,
2288 	emlxs_file_t *fpCeeFile)
2289 {
2290 
2291 	if (fpTxtFile) {
2292 		(void) emlxs_fclose(fpTxtFile);
2293 	}
2294 
2295 	if (fpCeeFile) {
2296 		(void) emlxs_fclose(fpCeeFile);
2297 	}
2298 
2299 	if (fpDmpFile) {
2300 		(void) emlxs_fclose(fpDmpFile);
2301 	}
2302 
2303 	return (0);
2304 
2305 } /* emlxs_dump_file_close() */
2306 
2307 
2308 /* ************************************************************************* */
2309 /* ************************************************************************* */
2310 /* Dump Generators, High Level */
2311 /* ************************************************************************* */
2312 /* ************************************************************************* */
2313 
2314 
2315 static uint32_t
2316 emlxs_dump_rev_info(
2317 	emlxs_hba_t *hba,
2318 	emlxs_file_t *fpTxtFile,
2319 	emlxs_file_t *fpDmpFile)
2320 {
2321 	(void) emlxs_dump_os_version(hba, fpTxtFile, fpDmpFile);
2322 	(void) emlxs_dump_drv_version(hba, fpTxtFile, fpDmpFile);
2323 	return (0);
2324 
2325 } /* emlxs_dump_rev_info() */
2326 
2327 
2328 /* ARGSUSED */
2329 static uint32_t
2330 emlxs_dump_hba_info(
2331 	emlxs_hba_t *hba,
2332 	emlxs_file_t *fpTxtFile,
2333 	emlxs_file_t *fpDmpFile,
2334 	uint32_t dump_type)
2335 {
2336 	(void) emlxs_dump_model(hba, fpTxtFile, fpDmpFile);
2337 	(void) emlxs_dump_wwn(hba, fpTxtFile, fpDmpFile);
2338 	(void) emlxs_dump_serial_number(hba, fpTxtFile, fpDmpFile);
2339 	(void) emlxs_dump_fw_version(hba, fpTxtFile, fpDmpFile);
2340 	(void) emlxs_dump_boot_version(hba, fpTxtFile, fpDmpFile);
2341 
2342 
2343 	return (0);
2344 
2345 } /* emlxs_dump_hba_info() */
2346 
2347 
2348 /* ************************************************************************* */
2349 /* emlxs_dump_table_check */
2350 /* Examine Dump Table, and determine its size. */
2351 /* Count and include ID SIDs, and the TERM SID, */
2352 /* but not the Pointer at Addr 654. */
2353 /* See comments for CC_DUMP_USE_ALL_TABLES for additional description. */
2354 /* ************************************************************************* */
2355 static uint32_t
2356 emlxs_dump_table_check(
2357 	emlxs_hba_t *hba,
2358 	uint32_t *pSize)
2359 {
2360 	emlxs_port_t *port = &PPORT;
2361 	int fDone = FALSE;	/* loop control flag */
2362 	uint32_t tableSize = 0;	/* dump table size (word count) */
2363 	MAILBOX *mb;
2364 	MAILBOXQ *mbq;
2365 	uint32_t DumpTableAddr;
2366 	DUMP_TABLE_ENTRY entry;
2367 
2368 	*pSize = 0;
2369 
2370 	/* Read 1 word from low memory at address 654; */
2371 	/* save the returned Dump Table Base Address */
2372 
2373 	mbq =
2374 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
2375 	mb = (MAILBOX *) mbq;
2376 
2377 	/* Read the dump table address */
2378 	emlxs_mb_dump(hba, mbq, 0x654, 1);
2379 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2380 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2381 		    "Unable to read dump table address. "\
2382 		    "offset=0x654 status=%x",
2383 		    mb->mbxStatus);
2384 
2385 		kmem_free(mbq, sizeof (MAILBOXQ));
2386 		return (1);
2387 	}
2388 
2389 	DumpTableAddr = mb->un.varDmp.resp_offset;
2390 
2391 	if (DumpTableAddr == 0) {
2392 		kmem_free(mbq, sizeof (MAILBOXQ));
2393 		return (1);
2394 	}
2395 
2396 	/* Now loop reading Dump Table Entries.. */
2397 	/* break out when we see a Terminator SID */
2398 	while (!fDone) {
2399 		emlxs_mb_dump(hba, mbq, DumpTableAddr, 2);
2400 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
2401 		    MBX_SUCCESS) {
2402 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2403 			    "Unable to read dump table entry. "\
2404 			    "offset=%x status=%x",
2405 			    DumpTableAddr, mb->mbxStatus);
2406 
2407 			kmem_free(mbq, sizeof (MAILBOXQ));
2408 			return (1);
2409 		}
2410 
2411 		entry.un.PortBlock.un.w[0] = mb->un.varWords[4];
2412 
2413 		switch (entry.un.PortBlock.un.s.sid) {
2414 		/* New Dump Table */
2415 		case SID_ID01:
2416 			tableSize++;
2417 			DumpTableAddr += 4;
2418 			break;
2419 
2420 #ifdef CC_DUMP_USE_ALL_TABLES
2421 		/* New Dump Table */
2422 		case SID_ID02:
2423 		case SID_ID03:
2424 			tableSize++;
2425 			DumpTableAddr += 4;
2426 			break;
2427 #else
2428 		/* New Dump Table */
2429 		case SID_ID02:
2430 		case SID_ID03:
2431 			tableSize++;
2432 			fDone = TRUE;
2433 			break;
2434 #endif /* CC_DUMP_USE_ALL_TABLES */
2435 
2436 		/* Dump Table(s) Termination - all done */
2437 		case SID_TERM:
2438 			tableSize++;
2439 			fDone = TRUE;
2440 			break;
2441 
2442 			/* Dump Table Entry */
2443 		default:
2444 			tableSize += 2;
2445 			DumpTableAddr += 8;
2446 			break;
2447 		}
2448 
2449 	}	/* end while */
2450 
2451 	*pSize = (tableSize * 4); /* return the total Dump Table size */
2452 
2453 	kmem_free(mbq, sizeof (MAILBOXQ));
2454 	return (0);
2455 
2456 } /* emlxs_dump_table_check() */
2457 
2458 
2459 /* ************************************************************************ */
2460 /* emlxs_dump_table_read */
2461 /* Read the Dump Table and store it, for use */
2462 /* subsequently in emlxs_dump_hba_memory. */
2463 /* See comments for CC_DUMP_USE_ALL_TABLES for additional description. */
2464 /* ************************************************************************ */
2465 static uint32_t
2466 emlxs_dump_table_read(
2467 	emlxs_hba_t *hba,
2468 	emlxs_file_t *fpTxtFile,
2469 	uint32_t **ppDumpTable,
2470 	uint32_t *pDumpTableSize)
2471 {
2472 	emlxs_port_t *port = &PPORT;
2473 	uint32_t status = 0;
2474 	int fDone = FALSE;
2475 	MAILBOXQ *mbq;
2476 	MAILBOX *mb;
2477 	uint32_t *pDumpTableEntry;
2478 	uint32_t DumpTableAddr;
2479 	DUMP_TABLE_ENTRY entry;
2480 
2481 	char buf2[256];
2482 	char *buf1;
2483 	uint32_t size = (32 * 1024);
2484 
2485 	/* First, check the dump table and if valid, get its size */
2486 	status = emlxs_dump_table_check(hba, pDumpTableSize);
2487 	if (status != 0) {
2488 		return (status);
2489 	}
2490 
2491 	buf1 = (char *)kmem_zalloc(size, KM_SLEEP);
2492 
2493 	/* Allocate a buffer to hold the Dump Table */
2494 	*ppDumpTable = (uint32_t *)kmem_zalloc(*pDumpTableSize, KM_SLEEP);
2495 
2496 	pDumpTableEntry = *ppDumpTable;
2497 
2498 	/* Read 1 word from low memory at address 654; */
2499 	/* save the returned Dump Table Base Address */
2500 	mbq =
2501 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
2502 
2503 	mb = (MAILBOX *) mbq;
2504 
2505 	/* Read the dump table address */
2506 	emlxs_mb_dump(hba, mbq, 0x654, 1);
2507 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2508 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2509 		    "Unable to read dump table address. "\
2510 		    "offset=0x654 status=%x",
2511 		    mb->mbxStatus);
2512 
2513 		kmem_free(buf1, size);
2514 		kmem_free(mbq, sizeof (MAILBOXQ));
2515 
2516 		kmem_free(*ppDumpTable, *pDumpTableSize);
2517 		*pDumpTableSize = 0;
2518 		*ppDumpTable = NULL;
2519 
2520 		return (1);
2521 	}
2522 
2523 	DumpTableAddr = mb->un.varDmp.resp_offset;
2524 
2525 	if (DumpTableAddr == 0) {
2526 		kmem_free(buf1, size);
2527 		kmem_free(mbq, sizeof (MAILBOXQ));
2528 
2529 		kmem_free(*ppDumpTable, *pDumpTableSize);
2530 		*pDumpTableSize = 0;
2531 		*ppDumpTable = NULL;
2532 
2533 		return (1);
2534 	}
2535 
2536 
2537 	/* Now loop reading Dump Table Entries.. */
2538 	/* break out when we see a Terminator SID */
2539 	while (!fDone) {
2540 		emlxs_mb_dump(hba, mbq, DumpTableAddr, 2);
2541 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
2542 		    MBX_SUCCESS) {
2543 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2544 			    "Unable to read dump table entry. "\
2545 			    "offset=%x status=%x",
2546 			    DumpTableAddr, mb->mbxStatus);
2547 
2548 			kmem_free(buf1, size);
2549 			kmem_free(mbq, sizeof (MAILBOXQ));
2550 
2551 			kmem_free(*ppDumpTable, *pDumpTableSize);
2552 			*pDumpTableSize = 0;
2553 			*ppDumpTable = NULL;
2554 
2555 			return (1);
2556 		}
2557 
2558 		(void) sprintf(buf2, "\n Addr=%08x: ", mb->un.varDmp.base_adr);
2559 		(void) strcat(buf1, buf2);
2560 
2561 		entry.un.PortBlock.un.w[0] = mb->un.varWords[4];
2562 		*pDumpTableEntry++ = mb->un.varWords[4];
2563 
2564 		switch (entry.un.PortBlock.un.s.sid) {
2565 			/* New Dump Table */
2566 		case SID_ID01:
2567 			(void) sprintf(buf2, "w0=%08x",
2568 			    entry.un.PortBlock.un.w[0]);
2569 			(void) strcat(buf1, buf2);
2570 			DumpTableAddr += 4;
2571 			break;
2572 
2573 #ifdef CC_DUMP_USE_ALL_TABLES
2574 		/* New Dump Table */
2575 		case SID_ID02:
2576 		case SID_ID03:
2577 			(void) sprintf(buf2, "w0=%08x",
2578 			    entry.un.PortBlock.un.w[0]);
2579 			(void) strcat(buf1, buf2);
2580 			DumpTableAddr += 4;
2581 			break;
2582 #else
2583 			/* New Dump Table */
2584 		case SID_ID02:
2585 		case SID_ID03:
2586 			(void) sprintf(buf2, "w0=%08x",
2587 			    entry.un.PortBlock.un.w[0]);
2588 			(void) strcat(buf1, buf2);
2589 			fDone = TRUE;
2590 			break;
2591 #endif /* CC_DUMP_USE_ALL_TABLES */
2592 
2593 			/* Dump Table(s) Termination - all done */
2594 		case SID_TERM:
2595 			(void) sprintf(buf2, "w0=%08x",
2596 			    entry.un.PortBlock.un.w[0]);
2597 			(void) strcat(buf1, buf2);
2598 			fDone = TRUE;
2599 			break;
2600 
2601 			/* Dump Table Entry */
2602 		default:
2603 			entry.un.PortBlock.un.w[1] = mb->un.varWords[5];
2604 			*pDumpTableEntry++ = mb->un.varWords[5];
2605 
2606 			(void) sprintf(buf2, "w0=%08x, w1=%08x",
2607 			    entry.un.PortBlock.un.w[0],
2608 			    entry.un.PortBlock.un.w[1]);
2609 			(void) strcat(buf1, buf2);
2610 			DumpTableAddr += 8;
2611 			break;
2612 		}
2613 
2614 	}	/* end while */
2615 
2616 	status =
2617 	    emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_MEM_DUMP,
2618 	    LEGEND_HBA_MEM_DUMP_TABLE, 0);
2619 
2620 	kmem_free(buf1, size);
2621 	kmem_free(mbq, sizeof (MAILBOXQ));
2622 
2623 	if (status != 0) {
2624 		kmem_free(*ppDumpTable, *pDumpTableSize);
2625 		*pDumpTableSize = 0;
2626 		*ppDumpTable = NULL;
2627 
2628 		return (status);
2629 	}
2630 
2631 	return (0);
2632 
2633 } /* emlxs_dump_table_read() */
2634 
2635 
2636 /* ************************************************************************* */
2637 /* emlxs_dump_hba_memory */
2638 /* Guided by the Dump Table previously read in, */
2639 /* generate the Port Memory Dump. */
2640 /* See comments for CC_DUMP_USE_ALL_TABLES for additional description. */
2641 /* ************************************************************************* */
2642 static uint32_t
2643 emlxs_dump_hba_memory(
2644 	emlxs_hba_t *hba,
2645 	emlxs_file_t *fpDmpFile,
2646 	uint32_t *pDumpTable)
2647 {
2648 	emlxs_port_t *port = &PPORT;
2649 	uint32_t status = 0;
2650 	int fDone = FALSE;
2651 	DUMP_TABLE_ENTRY entry;
2652 	MAILBOXQ *mbq;
2653 	MAILBOX *mb;
2654 	uint32_t byteCount;
2655 	uint32_t byteCountRem;
2656 	uint8_t *pBuf;
2657 	uint8_t *p1;
2658 	uint32_t portAddr;
2659 	int fSwap = FALSE;
2660 	uint32_t offset;
2661 	uint32_t wcount;
2662 	uint32_t total = 0;
2663 
2664 #ifdef EMLXS_BIG_ENDIAN
2665 	fSwap = TRUE;
2666 #endif /* EMLXS_BIG_ENDIAN */
2667 
2668 	if (!fpDmpFile) {
2669 		return (1);
2670 	}
2671 
2672 	mbq =
2673 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
2674 
2675 	mb = (MAILBOX *) mbq;
2676 
2677 	/* loop reading Dump Table Entries.. break out when */
2678 	/* we see a Terminator SID */
2679 	while (!fDone) {
2680 		entry.un.PortBlock.un.w[0] = *pDumpTable++;
2681 
2682 		switch (entry.un.PortBlock.un.s.sid) {
2683 
2684 			/* New Dump Table */
2685 		case SID_ID01:
2686 			break;
2687 
2688 #ifdef CC_DUMP_USE_ALL_TABLES
2689 			/* New Dump Table */
2690 		case SID_ID02:
2691 		case SID_ID03:
2692 			break;
2693 #else
2694 			/* New Dump Table */
2695 		case SID_ID02:
2696 		case SID_ID03:
2697 			fDone = TRUE;
2698 			break;
2699 #endif /* CC_DUMP_USE_ALL_TABLES */
2700 
2701 			/* Dump Table(s) Termination - all done */
2702 		case SID_TERM:
2703 			fDone = TRUE;
2704 			break;
2705 
2706 		default:
2707 			/* Dump Table Entry */
2708 			entry.un.PortBlock.un.w[1] = *pDumpTable++;
2709 
2710 #ifdef CC_DUMP_FW_BUG_1
2711 			if (entry.un.PortBlock.un.w[1] == 0x3E0000) {
2712 				break;
2713 			}
2714 #endif /* CC_DUMP_FW_BUG_1 */
2715 
2716 			/* Check if indirect address, and */
2717 			/* obtain the new address if so */
2718 			if ((entry.un.PortBlock.un.s.addr & 0x80000000) != 0) {
2719 				offset =
2720 				    (entry.un.PortBlock.un.s.
2721 				    addr & 0x01FFFFFF);
2722 				emlxs_mb_dump(hba, mbq, offset, 1);
2723 				if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT,
2724 				    0) != MBX_SUCCESS) {
2725 					EMLXS_MSGF(EMLXS_CONTEXT,
2726 					    &emlxs_init_debug_msg,
2727 					    "Unable to read dump table entry. "\
2728 					    "offset=%x status=%x",
2729 					    offset, mb->mbxStatus);
2730 
2731 					kmem_free(mbq, sizeof (MAILBOXQ));
2732 					return (1);
2733 				}
2734 
2735 				/* replace the indirect address in the */
2736 				/* Dump Table */
2737 				entry.un.PortBlock.un.s.addr =
2738 				    mb->un.varWords[4];
2739 			}
2740 
2741 			/* determine byte count to dump */
2742 			byteCount = entry.un.PortBlock.un.s.bc;
2743 			if (entry.un.PortBlock.un.s.sid & SID_MULT_ELEM) {
2744 				if (entry.un.PortStruct.un.s.count == 0) {
2745 					byteCount =
2746 					    256 *
2747 					    entry.un.PortStruct.un.s.length;
2748 				} else {
2749 					byteCount =
2750 					    entry.un.PortStruct.un.s.count *
2751 					    entry.un.PortStruct.un.s.length;
2752 				}
2753 			}
2754 
2755 			total += byteCount;
2756 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2757 			    "Dump: addr=%x count=%d total=%d", offset,
2758 			    byteCount, total);
2759 
2760 			/* allocate a buffer to receive the dump data */
2761 			pBuf = (uint8_t *)kmem_zalloc(byteCount, KM_SLEEP);
2762 
2763 			/* loop issuing MBX commands, 18x measly words at */
2764 			/* a time */
2765 
2766 			/* init vars */
2767 			byteCountRem = byteCount;
2768 			p1 = pBuf;
2769 			portAddr = entry.un.PortBlock.un.s.addr;
2770 
2771 			for (;;) {
2772 				if (byteCountRem == 0) {
2773 					break;
2774 				}
2775 
2776 				wcount =
2777 				    (byteCountRem / 4 >=
2778 				    0x18) ? 0x18 : (byteCountRem / 4);
2779 				emlxs_mb_dump(hba, mbq, portAddr, wcount);
2780 				if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT,
2781 				    0) != MBX_SUCCESS) {
2782 					EMLXS_MSGF(EMLXS_CONTEXT,
2783 					    &emlxs_init_debug_msg,
2784 					    "Unable to read dump table entry."\
2785 					    " offset=%x wc=%d status=%x",
2786 					    portAddr, wcount, mb->mbxStatus);
2787 					break;
2788 				}
2789 
2790 				bcopy((uint8_t *)&mb->un.varWords[4], p1,
2791 				    (mb->un.varDmp.word_cnt * 4));
2792 
2793 				byteCountRem -= (mb->un.varDmp.word_cnt * 4);
2794 				p1 += (mb->un.varDmp.word_cnt * 4);
2795 				portAddr += (mb->un.varDmp.word_cnt * 4);
2796 
2797 			}	/* end for */
2798 
2799 			if (status == 0) {
2800 				if (entry.un.PortBlock.un.s.
2801 				    sid & SID_MULT_ELEM) {
2802 					status =
2803 					    emlxs_dump_port_struct(fpDmpFile,
2804 					    pBuf, byteCount, entry, fSwap);
2805 				} else {
2806 					status =
2807 					    emlxs_dump_port_block(fpDmpFile,
2808 					    pBuf, byteCount, entry, fSwap);
2809 				}
2810 			}
2811 
2812 			if (pBuf) {
2813 				kmem_free(pBuf, byteCount);
2814 			}
2815 
2816 			break;
2817 
2818 		}	/* end switch */
2819 
2820 	}	/* end while */
2821 
2822 	kmem_free(mbq, sizeof (MAILBOXQ));
2823 
2824 	return (status);
2825 
2826 } /* emlxs_dump_hba_memory() */
2827 
2828 
2829 static uint32_t
2830 emlxs_dump_hba(
2831 	emlxs_hba_t *hba,
2832 	emlxs_file_t *fpTxtFile,
2833 	emlxs_file_t *fpDmpFile)
2834 {
2835 	uint32_t status = 0;
2836 	uint32_t *pDumpTable = 0;
2837 	uint32_t DumpTableSize = 0;
2838 
2839 	if (hba->sli_mode >= EMLXS_HBA_SLI4_MODE) {
2840 		return (1);
2841 	}
2842 
2843 	/* HBA should be in WARM state here */
2844 	status =
2845 	    emlxs_dump_table_read(hba, fpTxtFile, &pDumpTable,
2846 	    &DumpTableSize);
2847 	if (status) {
2848 		return (status);
2849 	}
2850 
2851 	status = emlxs_dump_hba_memory(hba, fpDmpFile, pDumpTable);
2852 
2853 	if (pDumpTable != 0) {
2854 		kmem_free(pDumpTable, DumpTableSize);
2855 	}
2856 
2857 	return (status);
2858 
2859 } /* emlxs_dump_hba() */
2860 
2861 
2862 /* ************************************************************************* */
2863 /* emlxs_dump_drv_region */
2864 /* Common subroutine for all the Dump_Sli"Structures" Routines */
2865 /* NOTE: This routine does not free pBuf. This is by design. */
2866 /* The caller does it. */
2867 /* ************************************************************************* */
2868 static uint32_t
2869 emlxs_dump_drv_region(
2870 	emlxs_hba_t *hba,
2871 	uint32_t regionId,
2872 	uint8_t **pBuf,
2873 	uint32_t *pBufLen)
2874 {  /* ptr to length of buffer */
2875 	uint32_t status;
2876 	uint32_t size;
2877 
2878 	*pBuf = NULL;
2879 	*pBufLen = 0;
2880 
2881 	size = 0;
2882 	status = emlxs_get_dump_region(hba, regionId, NULL, &size);
2883 
2884 	if (status != 0) {
2885 		return (1);
2886 	}
2887 
2888 	/* Now that we know the required length, request the actual data */
2889 	*pBuf = (uint8_t *)kmem_zalloc(size, KM_SLEEP);
2890 
2891 	status = emlxs_get_dump_region(hba, regionId, *pBuf, &size);
2892 
2893 	if (status != 0) {
2894 		kmem_free(*pBuf, size);
2895 		*pBuf = NULL;
2896 
2897 		return (1);
2898 	}
2899 
2900 	*pBufLen = size;
2901 
2902 	return (status);
2903 
2904 } /* emlxs_dump_drv_region() */
2905 
2906 
2907 static uint32_t
2908 emlxs_dump_sli_regs(
2909 	emlxs_hba_t *hba,
2910 	emlxs_file_t *fpDmpFile)
2911 {
2912 	uint32_t status;
2913 	uint8_t *pBuf;	/* ptr to data buffer to receive Dump Region Data */
2914 	uint32_t bufLen = 0;	/* length of buffer */
2915 	int fSwap = FALSE;	/* flag to pass to emlxs_dump_word_dmpfile */
2916 
2917 #ifdef EMLXS_BIG_ENDIAN
2918 	fSwap = TRUE;
2919 #endif /* EMLXS_BIG_ENDIAN */
2920 
2921 	if (!fpDmpFile) {
2922 		return (1);
2923 	}
2924 
2925 	status = emlxs_dump_drv_region(hba, DR_SLI_REGS, &pBuf, &bufLen);
2926 
2927 	if (status != 0) {
2928 		return (status);
2929 	}
2930 
2931 	status =
2932 	    emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_SLI_REGS,
2933 	    LEGEND_SLI_STRUCTURES, LEGEND_SLI_REGS, fSwap);
2934 
2935 	kmem_free(pBuf, bufLen);
2936 
2937 	return (status);
2938 
2939 } /* emlxs_dump_sli_regs() */
2940 
2941 
2942 static uint32_t
2943 emlxs_dump_slim(
2944 	emlxs_hba_t *hba,
2945 	emlxs_file_t *fpTxtFile,
2946 	emlxs_file_t *fpDmpFile,
2947 	uint32_t dump_type)
2948 {
2949 	uint32_t status;
2950 	uint8_t *pBuf;	/* ptr to data buffer to receive Dump Region Data */
2951 	uint32_t bufLen = 0;	/* length of buffer */
2952 	int fSwap = FALSE;	/* flag to pass to emlxs_dump_word_dmpfile */
2953 
2954 #ifdef EMLXS_BIG_ENDIAN
2955 	fSwap = TRUE;
2956 #endif /* EMLXS_BIG_ENDIAN */
2957 
2958 	status = emlxs_dump_drv_region(hba, DR_SLIM, &pBuf, &bufLen);
2959 
2960 	if (status != 0) {
2961 		return (status);
2962 	}
2963 
2964 	/* The SLIM Dump is only useful if it's a */
2965 	/* Driver-Initiated dump, say, after a HW Error */
2966 	if (dump_type == DUMP_TYPE_DRIVER) {
2967 		status =
2968 		    emlxs_dump_word_txtfile(fpTxtFile, (uint32_t *)pBuf,
2969 		    0x40, LEGEND_SLI_STRUCTURES, LEGEND_SLIM);
2970 	}
2971 
2972 	status =
2973 	    emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_SLIM,
2974 	    LEGEND_SLI_STRUCTURES, LEGEND_SLIM, fSwap);
2975 
2976 	kmem_free(pBuf, bufLen);
2977 
2978 	return (status);
2979 
2980 } /* emlxs_dump_slim() */
2981 
2982 
2983 static uint32_t
2984 emlxs_dump_pcb(
2985 	emlxs_hba_t *hba,
2986 	emlxs_file_t *fpDmpFile)
2987 {
2988 	uint32_t status;
2989 	uint8_t *pBuf;	/* ptr to data buffer to receive Dump Region Data */
2990 	uint32_t bufLen = 0;	/* length of buffer */
2991 	int fSwap = FALSE;	/* flag to pass to emlxs_dump_word_dmpfile */
2992 
2993 #ifdef EMLXS_BIG_ENDIAN
2994 	fSwap = TRUE;
2995 #endif /* EMLXS_BIG_ENDIAN */
2996 
2997 	if (!fpDmpFile) {
2998 		return (1);
2999 	}
3000 
3001 	status = emlxs_dump_drv_region(hba, DR_PCB, &pBuf, &bufLen);
3002 	if (status != 0) {
3003 		return (status);
3004 	}
3005 
3006 	status =
3007 	    emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_PCB,
3008 	    LEGEND_SLI_STRUCTURES, LEGEND_PCB, fSwap);
3009 
3010 	kmem_free(pBuf, bufLen);
3011 
3012 	return (status);
3013 
3014 } /* emlxs_dump_pcb() */
3015 
3016 
3017 static uint32_t
3018 emlxs_dump_mbox(
3019 	emlxs_hba_t *hba,
3020 	emlxs_file_t *fpDmpFile)
3021 {
3022 	uint32_t status;
3023 	uint8_t *pBuf;	/* ptr to data buffer to receive Dump Region Data */
3024 	uint32_t bufLen = 0;	/* length of buffer */
3025 	int fSwap = FALSE;	/* flag to pass to emlxs_dump_word_dmpfile */
3026 
3027 #ifdef EMLXS_BIG_ENDIAN
3028 	fSwap = TRUE;
3029 #endif /* EMLXS_BIG_ENDIAN */
3030 
3031 	if (!fpDmpFile) {
3032 		return (1);
3033 	}
3034 
3035 	status = emlxs_dump_drv_region(hba, DR_MBX, &pBuf, &bufLen);
3036 	if (status != 0) {
3037 		return (status);
3038 	}
3039 
3040 	status =
3041 	    emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_MBX,
3042 	    LEGEND_SLI_STRUCTURES, LEGEND_MBX, fSwap);
3043 
3044 	kmem_free(pBuf, bufLen);
3045 
3046 	return (status);
3047 
3048 } /* emlxs_dump_mbox() */
3049 
3050 
3051 static uint32_t
3052 emlxs_dump_host_pointers(
3053 	emlxs_hba_t *hba,
3054 	emlxs_file_t *fpDmpFile)
3055 {
3056 	uint32_t status;
3057 	uint8_t *pBuf;	/* ptr to data buffer to receive Dump Region Data */
3058 	uint32_t bufLen = 0;	/* length of buffer */
3059 	int fSwap = FALSE;	/* flag to pass to emlxs_dump_word_dmpfile */
3060 
3061 #ifdef EMLXS_BIG_ENDIAN
3062 	fSwap = TRUE;
3063 #endif /* EMLXS_BIG_ENDIAN */
3064 
3065 	if (!fpDmpFile) {
3066 		return (1);
3067 	}
3068 
3069 	status = emlxs_dump_drv_region(hba, DR_HOST_PTRS, &pBuf, &bufLen);
3070 	if (status != 0) {
3071 		return (status);
3072 	}
3073 
3074 	status =
3075 	    emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_HOST_PTRS,
3076 	    LEGEND_SLI_STRUCTURES, LEGEND_HOST_PTRS, fSwap);
3077 
3078 	kmem_free(pBuf, bufLen);
3079 
3080 	return (status);
3081 
3082 } /* emlxs_dump_host_pointers() */
3083 
3084 
3085 static uint32_t
3086 emlxs_dump_port_pointers(
3087 	emlxs_hba_t *hba,
3088 	emlxs_file_t *fpDmpFile)
3089 {
3090 	uint32_t status;
3091 	uint8_t *pBuf;	/* ptr to data buffer to receive Dump Region Data */
3092 	uint32_t bufLen = 0;	/* length of buffer */
3093 	int fSwap = FALSE;	/* flag to pass to emlxs_dump_word_dmpfile */
3094 
3095 #ifdef EMLXS_BIG_ENDIAN
3096 	fSwap = TRUE;
3097 #endif /* EMLXS_BIG_ENDIAN */
3098 
3099 	if (!fpDmpFile) {
3100 		return (1);
3101 	}
3102 
3103 	status = emlxs_dump_drv_region(hba, DR_PORT_PTRS, &pBuf, &bufLen);
3104 	if (status != 0) {
3105 		return (status);
3106 	}
3107 
3108 	status =
3109 	    emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_PORT_PTRS,
3110 	    LEGEND_SLI_STRUCTURES, LEGEND_PORT_PTRS, fSwap);
3111 
3112 	kmem_free(pBuf, bufLen);
3113 
3114 	return (status);
3115 
3116 } /* emlxs_dump_port_pointers() */
3117 
3118 
3119 static uint32_t
3120 emlxs_dump_rings(
3121 	emlxs_hba_t *hba,
3122 	emlxs_file_t *fpDmpFile)
3123 {
3124 	uint32_t status;
3125 	uint8_t *pBuf;	/* ptr to data buffer to receive Dump Region Data */
3126 	uint32_t bufLen = 0;	/* length of buffer */
3127 	int fSwap = FALSE;	/* flag to pass to emlxs_dump_word_dmpfile */
3128 
3129 #ifdef EMLXS_BIG_ENDIAN
3130 	fSwap = TRUE;
3131 #endif /* EMLXS_BIG_ENDIAN */
3132 
3133 	if (!fpDmpFile) {
3134 		return (1);
3135 	}
3136 
3137 	status = emlxs_dump_drv_region(hba, DR_RINGS, &pBuf, &bufLen);
3138 	if (status != 0) {
3139 		return (status);
3140 	}
3141 
3142 	status =
3143 	    emlxs_dump_host_struct(fpDmpFile, pBuf, bufLen, sizeof (IOCB),
3144 	    bufLen / sizeof (IOCB), SID_RINGS, LEGEND_SLI_STRUCTURES,
3145 	    LEGEND_RINGS, fSwap);
3146 
3147 	kmem_free(pBuf, bufLen);
3148 
3149 	return (status);
3150 
3151 } /* emlxs_dump_rings() */
3152 
3153 
3154 static uint32_t
3155 emlxs_dump_drv_internals(
3156 	emlxs_hba_t *hba,
3157 	emlxs_file_t *fpDmpFile)
3158 {
3159 	uint32_t status;
3160 	uint8_t *pBuf;	/* ptr to data buffer to receive Dump Region Data */
3161 	uint32_t bufLen = 0;	/* length of buffer */
3162 	int fSwap = FALSE;	/* flag to pass to emlxs_dump_word_dmpfile */
3163 
3164 #ifdef EMLXS_BIG_ENDIAN
3165 	fSwap = TRUE;
3166 #endif /* EMLXS_BIG_ENDIAN */
3167 
3168 	if (!fpDmpFile) {
3169 		return (1);
3170 	}
3171 
3172 	status = emlxs_dump_drv_region(hba, DR_INTERNAL, &pBuf, &bufLen);
3173 	if (status != 0) {
3174 		return (status);
3175 	}
3176 
3177 	status =
3178 	    emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_INTERNAL_SOL,
3179 	    LEGEND_SLI_STRUCTURES, LEGEND_DRIVER_SPEC, fSwap);
3180 
3181 	kmem_free(pBuf, bufLen);
3182 
3183 	return (status);
3184 
3185 } /* emlxs_dump_drv_internals() */
3186 
3187 
3188 static uint32_t
3189 emlxs_dump_sli_interface(
3190 	emlxs_hba_t *hba,
3191 	emlxs_file_t *fpTxtFile,
3192 	emlxs_file_t *fpDmpFile,
3193 	uint32_t dump_type)
3194 {
3195 
3196 	if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
3197 		/* HBA should be in OFFLINE state here */
3198 
3199 		(void) emlxs_dump_sli_regs(hba, fpDmpFile);
3200 		(void) emlxs_dump_slim(hba, fpTxtFile, fpDmpFile, dump_type);
3201 		(void) emlxs_dump_pcb(hba, fpDmpFile);
3202 		(void) emlxs_dump_mbox(hba, fpDmpFile);
3203 		(void) emlxs_dump_host_pointers(hba, fpDmpFile);
3204 		(void) emlxs_dump_port_pointers(hba, fpDmpFile);
3205 		(void) emlxs_dump_rings(hba, fpDmpFile);
3206 	}
3207 
3208 	(void) emlxs_dump_drv_internals(hba, fpDmpFile);
3209 
3210 	return (0);
3211 
3212 } /* emlxs_dump_sli_interface() */
3213 
3214 
3215 static uint32_t
3216 emlxs_dump_menlo_log(
3217 	emlxs_hba_t *hba,
3218 	emlxs_file_t *fpCeeFile)
3219 {
3220 	uint32_t RmStatus;
3221 	int i, j;
3222 	int isWrapped = FALSE;
3223 	char buf1[2048] = { 0 };
3224 	char buf2[2048] = { 0 };
3225 
3226 	/* Get Config Command vars */
3227 	menlo_get_config_rsp_t GcBuf;
3228 	menlo_get_config_rsp_t *pGcBuf = &GcBuf;
3229 
3230 	/* Get Log Config Command vars */
3231 	uint32_t LcBufSize;
3232 	menlo_rsp_t *pLcBuf = NULL;
3233 	uint32_t NumLogs;
3234 	menlo_log_t *pLcEntry;
3235 
3236 	/* Get Log Data Command vars */
3237 	uint32_t LdBufSize;
3238 	menlo_rsp_t *pLdBuf = NULL;
3239 	uint16_t Head;
3240 	uint8_t *pLogEntry;
3241 	char *pLogString;
3242 
3243 	/* Get Panic Log Command vars */
3244 	uint32_t PlBufSize;
3245 	menlo_rsp_t *pPlBuf = NULL;
3246 	uint32_t PanicLogEntryCount;
3247 	uint32_t PanicLogEntrySize;
3248 
3249 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
3250 		return (DFC_INVALID_ADAPTER);
3251 	}
3252 
3253 	/* First, issue a GetConfig command, which gives us */
3254 	/* the Log Config and Panic Log sizes */
3255 
3256 	RmStatus =
3257 	    emlxs_menlo_get_cfg(hba, pGcBuf, sizeof (menlo_get_config_rsp_t));
3258 
3259 	if (RmStatus != 0) {
3260 		goto done;
3261 	}
3262 
3263 	LcBufSize = GcBuf.log_cfg_size + 8;
3264 	PlBufSize = GcBuf.panic_log_size;
3265 
3266 	pLcBuf = (menlo_rsp_t *)kmem_zalloc(LcBufSize, KM_SLEEP);
3267 
3268 	RmStatus = emlxs_menlo_get_logcfg(hba, pLcBuf, LcBufSize);
3269 
3270 	if (RmStatus != 0) {
3271 		goto done;
3272 	}
3273 
3274 	buf1[0] = 0;
3275 	RmStatus =
3276 	    emlxs_dump_string_txtfile(fpCeeFile, buf1,
3277 	    LEGEND_MENLO_LOG_CONFIG, LEGEND_NULL, 0);
3278 
3279 	NumLogs = pLcBuf->log_cfg.num_logs;
3280 	pLcEntry = (menlo_log_t *)&pLcBuf->log_cfg.data;
3281 
3282 	buf1[0] = 0;
3283 	(void) sprintf(buf2, "LogId   Entries   Size   Name");
3284 	(void) strcat(buf1, buf2);
3285 	(void) sprintf(buf2, "\n-----   -------   ----   ----");
3286 	(void) strcat(buf1, buf2);
3287 
3288 	RmStatus = emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1);
3289 
3290 	for (i = 0; i < (int)NumLogs; i++) {
3291 		buf1[0] = 0;
3292 		(void) sprintf(buf2, "\n %2d      %4d    %4d    %s",
3293 		    pLcEntry[i].id,
3294 		    pLcEntry[i].num_entries,
3295 		    pLcEntry[i].entry_size, pLcEntry[i].name);
3296 		(void) strcat(buf1, buf2);
3297 		RmStatus =
3298 		    emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1);
3299 	}
3300 
3301 	/* Now issue a series of GetLogData commands, */
3302 	/* which gives us the actual Logs */
3303 
3304 	for (i = 0; i < (int)NumLogs; i++) {
3305 		LdBufSize =
3306 		    (pLcEntry[i].num_entries *pLcEntry[i].entry_size) + 8;
3307 
3308 		pLdBuf = (menlo_rsp_t *)kmem_zalloc(LdBufSize, KM_SLEEP);
3309 
3310 		RmStatus = emlxs_menlo_get_log(hba, i, pLdBuf, LdBufSize);
3311 
3312 		if (RmStatus != 0) {
3313 			goto done;
3314 		}
3315 
3316 		/* print a caption for the current log */
3317 		buf1[0] = 0;
3318 		(void) sprintf(buf2, "\n\nLog %d:", i);
3319 		(void) strcat(buf1, buf2);
3320 		(void) sprintf(buf2, " %s", pLcEntry[i].name);
3321 		(void) strcat(buf1, buf2);
3322 		(void) sprintf(buf2, "\n");
3323 
3324 		for (j = 0; j < 75; j++) {
3325 			(void) strcat(buf2, "-");
3326 		}
3327 
3328 		(void) strcat(buf1, buf2);
3329 		RmStatus =
3330 		    emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1);
3331 
3332 		/* check the head entry to determine whether */
3333 		/* the log has wrapped or not */
3334 		Head = pLdBuf->log.head;
3335 		pLogEntry = (uint8_t *)&pLdBuf->log.data;
3336 		pLogString =
3337 		    (char *)&(pLogEntry[Head *pLcEntry[i].entry_size]);
3338 
3339 		isWrapped = FALSE;
3340 		if (strlen(pLogString) != 0) {
3341 			isWrapped = TRUE;
3342 		}
3343 
3344 		/* if log is wrapped, get entries from the */
3345 		/* Head through the End */
3346 		if (isWrapped) {
3347 			for (j = Head; j < (int)pLcEntry[i].num_entries; j++) {
3348 				pLogString =
3349 				    (char *)&(pLogEntry[j *
3350 				    pLcEntry[i].entry_size]);
3351 				buf1[0] = 0;
3352 				(void) sprintf(buf2, "\n%3d: %s", j,
3353 				    pLogString);
3354 				(void) strcat(buf1, buf2);
3355 				RmStatus =
3356 				    emlxs_dump_string_txtfile(fpCeeFile, buf1,
3357 				    0, 0, 1);
3358 			}
3359 		}
3360 
3361 		/* if wrapped or not, get entries from the Top */
3362 		/* through the Head */
3363 		for (j = 0; j < Head; j++) {
3364 			pLogString =
3365 			    (char *)&(pLogEntry[j * pLcEntry[i].entry_size]);
3366 			buf1[0] = 0;
3367 			(void) sprintf(buf2, "\n%3d: %s", j, pLogString);
3368 			(void) strcat(buf1, buf2);
3369 			RmStatus =
3370 			    emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0,
3371 			    1);
3372 		}
3373 	}	/* end for i */
3374 
3375 	/* Now issue a GetPanicLog command, which gives us the Panic Log */
3376 
3377 	/* print a caption for the current log */
3378 	(void) strcpy(buf1, LEGEND_MENLO_LOG_PANIC_REGS);
3379 	buf2[0] = 0;
3380 	for (j = 0; j < 75; j++) {
3381 		(void) strcat(buf2, "-");
3382 	}
3383 	(void) strcat(buf1, buf2);
3384 	RmStatus = emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1);
3385 
3386 	pPlBuf = (menlo_rsp_t *)kmem_zalloc(PlBufSize, KM_SLEEP);
3387 
3388 	RmStatus = emlxs_menlo_get_paniclog(hba, pPlBuf, PlBufSize);
3389 
3390 	if (RmStatus == 0) {
3391 		buf1[0] = 0;
3392 		(void) sprintf(buf2, "\nType         = %x",
3393 		    pPlBuf->panic_log.type);
3394 		(void) strcat(buf1, buf2);
3395 		(void) sprintf(buf2, "\nRegsEpc      = %08x",
3396 		    pPlBuf->panic_log.regs_epc);
3397 		(void) strcat(buf1, buf2);
3398 		(void) sprintf(buf2, "\nRegsCp0Cause = %08x",
3399 		    pPlBuf->panic_log.regs_cp0_cause);
3400 		(void) strcat(buf1, buf2);
3401 		(void) sprintf(buf2, "\nRegsCp0Stat  = %08x",
3402 		    pPlBuf->panic_log.regs_cp0_status);
3403 		(void) strcat(buf1, buf2);
3404 		RmStatus =
3405 		    emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1);
3406 
3407 		buf1[0] = 0;
3408 		for (i = 0; i < MENLO_NUM_GP_REGS; i++) {
3409 			(void) sprintf(buf2, "\nRegsGp[%02x]   = %08x", i,
3410 			    pPlBuf->panic_log.regs_gp[i]);
3411 			(void) strcat(buf1, buf2);
3412 		}
3413 		RmStatus =
3414 		    emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1);
3415 
3416 		buf1[0] = 0;
3417 		(void) sprintf(buf2, "\nLogPresent   = %08x",
3418 		    pPlBuf->panic_log.log_present);
3419 		(void) strcat(buf1, buf2);
3420 		PanicLogEntryCount = pPlBuf->panic_log.num_entries;
3421 		(void) sprintf(buf2, "\nNumEntries   = %08x",
3422 		    PanicLogEntryCount);
3423 		(void) strcat(buf1, buf2);
3424 		PanicLogEntrySize = pPlBuf->panic_log.entry_size;
3425 		(void) sprintf(buf2, "\nEntrySize    = %d.",
3426 		    PanicLogEntrySize);
3427 		(void) strcat(buf1, buf2);
3428 		(void) sprintf(buf2, "\nHead Entry   = %d.",
3429 		    pPlBuf->panic_log.head);
3430 		(void) strcat(buf1, buf2);
3431 		RmStatus =
3432 		    emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1);
3433 
3434 		/* print a caption for the current log */
3435 		(void) strcpy(buf1, LEGEND_MENLO_LOG_PANIC_LOGS);
3436 		buf2[0] = 0;
3437 		for (j = 0; j < 75; j++) {
3438 			(void) strcat(buf2, "-");
3439 		}
3440 		(void) strcat(buf1, buf2);
3441 		RmStatus =
3442 		    emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1);
3443 
3444 		/* check the head entry to determine whether the */
3445 		/* log has wrapped or not */
3446 		Head = pPlBuf->panic_log.head;
3447 		pLogEntry = (uint8_t *)&pPlBuf->panic_log.data;
3448 		pLogString = (char *)&(pLogEntry[Head * PanicLogEntrySize]);
3449 		isWrapped = FALSE;
3450 		if (strlen(pLogString) != 0) {
3451 			isWrapped = TRUE;
3452 		}
3453 
3454 		/* if log is wrapped, get entries from the */
3455 		/* Head through the End */
3456 		if (isWrapped) {
3457 			for (j = Head; j < (int)PanicLogEntryCount; j++) {
3458 				pLogString =
3459 				    (char *)&(pLogEntry[j *
3460 				    PanicLogEntrySize]);
3461 				buf1[0] = 0;
3462 				(void) sprintf(buf2, "\n%3d: %s", j,
3463 				    pLogString);
3464 				(void) strcat(buf1, buf2);
3465 				RmStatus =
3466 				    emlxs_dump_string_txtfile(fpCeeFile, buf1,
3467 				    0, 0, 1);
3468 			}
3469 		}
3470 		/* if wrapped or not, get entries from the Top */
3471 		/* through the Head */
3472 		for (j = 0; j < Head; j++) {
3473 			pLogString =
3474 			    (char *)&(pLogEntry[j * PanicLogEntrySize]);
3475 			buf1[0] = 0;
3476 			(void) sprintf(buf2, "\n%3d: %s", j, pLogString);
3477 			(void) strcat(buf1, buf2);
3478 			RmStatus =
3479 			    emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0,
3480 			    1);
3481 		}
3482 	}
3483 
3484 	RmStatus = emlxs_dump_string_txtfile(fpCeeFile, "\n\n", 0, 0, 1);
3485 
3486 done:
3487 
3488 	if (pLdBuf != 0) {
3489 		kmem_free(pLdBuf, LdBufSize);
3490 	}
3491 
3492 	if (pLcBuf != 0) {
3493 		kmem_free(pLcBuf, LcBufSize);
3494 	}
3495 
3496 	if (pPlBuf != 0) {
3497 		kmem_free(pPlBuf, PlBufSize);
3498 	}
3499 
3500 	return (RmStatus);
3501 
3502 } /* emlxs_dump_menlo_log() */
3503 
3504 
3505 static uint32_t
3506 emlxs_dump_saturn_log(
3507 	emlxs_hba_t *hba,
3508 	emlxs_file_t *fpTxtFile,
3509 	emlxs_file_t *fpDmpFile)
3510 {
3511 	emlxs_port_t *port = &PPORT;
3512 	MAILBOXQ *mbq;
3513 	MAILBOX *mb;
3514 	MATCHMAP *mp = NULL;
3515 	uint32_t status;
3516 	uint32_t logSize = 0;
3517 	uintptr_t tempAddress;
3518 	int fSwap = FALSE;
3519 	uint32_t i;
3520 	uint32_t block_size;
3521 	uint32_t offset;
3522 
3523 #ifdef EMLXS_BIG_ENDIAN
3524 	fSwap = TRUE;
3525 #endif /* EMLXS_BIG_ENDIAN */
3526 
3527 	if (hba->model_info.chip != EMLXS_SATURN_CHIP) {
3528 		return (1);
3529 	}
3530 
3531 	mbq =
3532 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
3533 
3534 	mb = (MAILBOX *) mbq;
3535 
3536 	/* Step 1: Call MBX_READ_EVENT_LOG_STATUS to get the log size. */
3537 	for (i = 0; i < 10; i++) {
3538 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
3539 		mb->mbxCommand = MBX_READ_EVENT_LOG_STATUS;
3540 		mbq->mbox_cmpl = NULL;
3541 
3542 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) ==
3543 		    MBX_SUCCESS) {
3544 			break;
3545 		}
3546 
3547 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3548 		    "Unable to read event log status. status=%x",
3549 		    mb->mbxStatus);
3550 
3551 		if ((mb->mbxStatus & 0xFFFF) == MBXERR_NOT_SUPPORTED ||
3552 		    (mb->mbxStatus & 0xFFFF) == MBX_DRVR_ERROR) {
3553 			(void) emlxs_dump_string_txtfile(fpTxtFile,
3554 			    NV_LOG_NOT_INCLUDED_IN_DMP,
3555 			    LEGEND_NON_VOLATILE_LOG,
3556 			    LEGEND_NV_LOG_DRIVER_NOT_SUPPORTED, 0);
3557 
3558 			kmem_free(mbq, sizeof (MAILBOXQ));
3559 			return (1);
3560 		}
3561 
3562 		/* The call to get the log size simply fails. */
3563 		/* Retry up to 10 times. */
3564 		if ((mb->mbxStatus & 0xFFFF) != MBX_BUSY) {
3565 			/* Mailbox fails for some unknown reason. */
3566 			/* Put something in the txt to indicate this case. */
3567 			(void) emlxs_dump_string_txtfile(fpTxtFile,
3568 			    NV_LOG_NOT_INCLUDED_IN_DMP,
3569 			    LEGEND_NON_VOLATILE_LOG,
3570 			    LEGEND_NV_LOG_STATUS_ERROR, 0);
3571 
3572 			kmem_free(mbq, sizeof (MAILBOXQ));
3573 			return (1);
3574 		}
3575 	}
3576 
3577 	if (i >= 10) {
3578 		(void) emlxs_dump_string_txtfile(fpTxtFile,
3579 		    NV_LOG_NOT_INCLUDED_IN_DMP, LEGEND_NON_VOLATILE_LOG,
3580 		    LEGEND_NV_LOG_STATUS_ERROR, 0);
3581 
3582 		kmem_free(mbq, sizeof (MAILBOXQ));
3583 		return (1);
3584 	}
3585 
3586 	/* Step 2: Use the log size from step 1 to call MBX_READ_EVENT_LOG */
3587 	logSize = mb->un.varLogStat.size;
3588 
3589 	if ((mp = emlxs_mem_buf_alloc(hba, logSize)) == 0) {
3590 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3591 		    "Unable to allocate receive buffer. "
3592 		    "size=%d",
3593 		    logSize);
3594 
3595 		kmem_free(mbq, sizeof (MAILBOXQ));
3596 		return (1);
3597 	}
3598 
3599 	for (offset = 0; offset < logSize; offset = offset + 1024) {
3600 		if (logSize - offset < 1024) {
3601 			block_size = logSize - offset;
3602 		} else {
3603 			block_size = 1024;
3604 		}
3605 
3606 		tempAddress = (uintptr_t)(mp->phys + offset);
3607 
3608 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
3609 		mb->mbxCommand = MBX_READ_EVENT_LOG;	/* 0x38 */
3610 		mb->un.varRdEvtLog.read_log = 1;	/* read log */
3611 		mb->un.varRdEvtLog.mbox_rsp = 0;	/* not using Mailbox */
3612 		mb->un.varRdEvtLog.offset = offset;
3613 		mb->un.varRdEvtLog.un.sp64.tus.f.bdeFlags = 0x0;
3614 		mb->un.varRdEvtLog.un.sp64.tus.f.bdeSize = block_size;
3615 		mb->un.varRdEvtLog.un.sp64.addrLow = PADDR_LO(tempAddress);
3616 		mb->un.varRdEvtLog.un.sp64.addrHigh = PADDR_HI(tempAddress);
3617 		mbq->mbox_cmpl = NULL;
3618 
3619 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
3620 		    MBX_SUCCESS) {
3621 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3622 			    "Unable to read event log. status=%x",
3623 			    mb->mbxStatus);
3624 
3625 			emlxs_mem_buf_free(hba, mp);
3626 			kmem_free(mbq, sizeof (MAILBOXQ));
3627 			return (1);
3628 		}
3629 	}
3630 
3631 	/* Step 3: Dump the log to the DMP file as raw data. */
3632 
3633 	/* Write a string to text file to direct the user to the DMP */
3634 	/* file for the actual log. */
3635 	status =
3636 	    emlxs_dump_string_txtfile(fpTxtFile, NV_LOG_INCLUDED_IN_DMP,
3637 	    LEGEND_NON_VOLATILE_LOG, LEGEND_NULL, 0);
3638 
3639 	/* Write the real log to the DMP file. */
3640 	EMLXS_MPDATA_SYNC(mp->dma_handle, 0, logSize, DDI_DMA_SYNC_FORKERNEL);
3641 
3642 	status =
3643 	    emlxs_dump_host_block(fpDmpFile, mp->virt, logSize,
3644 	    SID_NON_VOLATILE_LOG, LEGEND_NON_VOLATILE_LOG, LEGEND_NULL,
3645 	    fSwap);
3646 
3647 #ifdef FMA_SUPPORT
3648 	if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
3649 	    != DDI_FM_OK) {
3650 		EMLXS_MSGF(EMLXS_CONTEXT,
3651 		    &emlxs_invalid_dma_handle_msg,
3652 		    "emlxs_dump_saturn_log: hdl=%p",
3653 		    mp->dma_handle);
3654 		status = 1;
3655 	}
3656 #endif  /* FMA_SUPPORT */
3657 
3658 	emlxs_mem_buf_free(hba, mp);
3659 	kmem_free(mbq, sizeof (MAILBOXQ));
3660 	return (status);
3661 
3662 } /* emlxs_dump_saturn_log() */
3663 
3664 
3665 static uint32_t
3666 emlxs_dump_tigershark_log(
3667 	emlxs_hba_t *hba,
3668 	emlxs_file_t *fpTxtFile,
3669 	emlxs_file_t *fpCeeFile)
3670 {
3671 	emlxs_port_t *port = &PPORT;
3672 	uint32_t rval = 0;
3673 	uint32_t offset;
3674 	uint32_t log_size;
3675 	uint32_t xfer_size;
3676 	uint32_t buffer_size;
3677 	uint8_t *buffer = NULL;
3678 	uint8_t *bptr;
3679 	uint8_t *payload;
3680 	MAILBOXQ *mbq = NULL;
3681 	MAILBOX4 *mb = NULL;
3682 	MATCHMAP *mp = NULL;
3683 	IOCTL_COMMON_MANAGE_FAT *fat;
3684 	mbox_req_hdr_t *hdr_req;
3685 
3686 	if ((hba->model_info.chip != EMLXS_BE2_CHIP) &&
3687 	    (hba->model_info.chip != EMLXS_BE3_CHIP)) {
3688 		return (1);
3689 	}
3690 
3691 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3692 	    "Querying FAT...");
3693 
3694 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3695 	    KM_SLEEP);
3696 
3697 	mb = (MAILBOX4*)mbq;
3698 
3699 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
3700 	    sizeof (IOCTL_COMMON_MANAGE_FAT) + BE_MAX_XFER_SIZE))) == NULL) {
3701 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3702 		    "Unable to allocate FAT buffer.");
3703 
3704 		rval = 1;
3705 		goto done;
3706 	}
3707 
3708 	/* Query FAT */
3709 	mb->un.varSLIConfig.be.embedded = 0;
3710 	mbq->nonembed = (void *)mp;
3711 	mbq->mbox_cmpl = NULL;
3712 
3713 	mb->mbxCommand = MBX_SLI_CONFIG;
3714 	mb->mbxOwner = OWN_HOST;
3715 
3716 	hdr_req = (mbox_req_hdr_t *)mp->virt;
3717 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
3718 	hdr_req->opcode = COMMON_OPCODE_MANAGE_FAT;
3719 	hdr_req->timeout = 0;
3720 	hdr_req->req_length = sizeof (IOCTL_COMMON_MANAGE_FAT);
3721 
3722 	fat = (IOCTL_COMMON_MANAGE_FAT *)(hdr_req + 1);
3723 	fat->params.request.fat_operation = QUERY_FAT;
3724 	fat->params.request.read_log_offset = 0;
3725 	fat->params.request.read_log_length = 0;
3726 	fat->params.request.data_buffer_size = BE_MAX_XFER_SIZE;
3727 
3728 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
3729 	    MBX_SUCCESS) {
3730 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3731 		    "FAT Query failed. status=%x",
3732 		    mb->mbxStatus);
3733 
3734 		rval = 1;
3735 		goto done;
3736 	}
3737 
3738 	log_size = fat->params.response.log_size;
3739 	buffer_size = fat->params.response.log_size;
3740 
3741 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3742 	    "FAT: log_size=%d", log_size);
3743 
3744 	if (buffer_size == 0) {
3745 		goto done;
3746 	}
3747 
3748 	if ((buffer = (uint8_t *)kmem_alloc(
3749 	    buffer_size, KM_NOSLEEP)) == NULL) {
3750 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3751 		    "Unable to allocate log buffer.");
3752 
3753 		rval = 1;
3754 		goto done;
3755 	}
3756 	bzero(buffer, buffer_size);
3757 
3758 	/* Upload Log */
3759 	bptr = buffer;
3760 	offset = 0;
3761 
3762 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3763 	    "Uploading log... (%d bytes)", log_size);
3764 
3765 	while (log_size) {
3766 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
3767 		bzero((void *) mp->virt, mp->size);
3768 
3769 		xfer_size = min(BE_MAX_XFER_SIZE, log_size);
3770 
3771 		mb->un.varSLIConfig.be.embedded = 0;
3772 		mbq->nonembed = (void *)mp;
3773 		mbq->mbox_cmpl = NULL;
3774 
3775 		mb->mbxCommand = MBX_SLI_CONFIG;
3776 		mb->mbxOwner = OWN_HOST;
3777 
3778 		hdr_req = (mbox_req_hdr_t *)mp->virt;
3779 		hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
3780 		hdr_req->opcode = COMMON_OPCODE_MANAGE_FAT;
3781 		hdr_req->timeout = 0;
3782 		hdr_req->req_length =
3783 		    sizeof (IOCTL_COMMON_MANAGE_FAT) + xfer_size;
3784 
3785 		fat = (IOCTL_COMMON_MANAGE_FAT *)(hdr_req + 1);
3786 		fat->params.request.fat_operation = RETRIEVE_FAT;
3787 		fat->params.request.read_log_offset = offset;
3788 		fat->params.request.read_log_length = xfer_size;
3789 		fat->params.request.data_buffer_size = BE_MAX_XFER_SIZE;
3790 
3791 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
3792 		    MBX_SUCCESS) {
3793 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3794 			    "Failed to upload log. status=%x",
3795 			    mb->mbxStatus);
3796 
3797 			(void) emlxs_dump_string_txtfile(fpTxtFile,
3798 			    NV_LOG_NOT_INCLUDED_IN_FAT,
3799 			    LEGEND_NON_VOLATILE_LOG,
3800 			    LEGEND_NV_LOG_STATUS_ERROR, 0);
3801 
3802 			rval = 1;
3803 			goto done;
3804 		}
3805 
3806 		payload = (uint8_t *)(&fat->params.response.data_buffer);
3807 
3808 		BE_SWAP32_BCOPY(payload, bptr, xfer_size);
3809 
3810 		log_size -= xfer_size;
3811 		offset += xfer_size;
3812 		bptr += xfer_size;
3813 	}
3814 
3815 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3816 	    "Log upload complete.");
3817 
3818 	/* Write a string to text file to direct the user to the CEE */
3819 	/* file for the actual log. */
3820 	rval =
3821 	    emlxs_dump_string_txtfile(fpTxtFile, NV_LOG_INCLUDED_IN_FAT,
3822 	    LEGEND_NON_VOLATILE_LOG, LEGEND_NULL, 0);
3823 
3824 
3825 	/* Write the log to the CEE file. */
3826 	/* First word is the log size */
3827 	bptr = buffer + sizeof (uint32_t);
3828 	log_size = buffer_size - sizeof (uint32_t);
3829 	rval = emlxs_dump_word_dmpfile(fpCeeFile, (uint8_t *)bptr,
3830 	    log_size, 0);
3831 
3832 done:
3833 
3834 	if (mbq) {
3835 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3836 	}
3837 
3838 	if (mp) {
3839 		emlxs_mem_buf_free(hba, mp);
3840 	}
3841 
3842 	if (buffer) {
3843 		kmem_free(buffer, buffer_size);
3844 	}
3845 
3846 	if (rval == 0) {
3847 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3848 		    "Dump complete.");
3849 	}
3850 
3851 	return (rval);
3852 
3853 } /* emlxs_dump_tigershark_log() */
3854 
3855 
3856 extern uint32_t
3857 emlxs_dump_user_event(
3858 	emlxs_hba_t *hba)
3859 {
3860 	emlxs_port_t *port = &PPORT;
3861 	uint32_t status;
3862 	emlxs_file_t *fpTxtFile;
3863 	emlxs_file_t *fpDmpFile;
3864 	emlxs_file_t *fpCeeFile;
3865 
3866 	mutex_enter(&EMLXS_DUMP_LOCK);
3867 
3868 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3869 	    "User Event: Firmware core dump initiated...");
3870 
3871 	status =
3872 	    emlxs_dump_file_create(hba, &fpTxtFile, &fpDmpFile, &fpCeeFile);
3873 	if (status != 0) {
3874 		mutex_exit(&EMLXS_DUMP_LOCK);
3875 		return (1);
3876 	}
3877 
3878 	(void) emlxs_dump_rev_info(hba, fpTxtFile, fpDmpFile);
3879 	(void) emlxs_dump_hba_info(hba, fpTxtFile, fpDmpFile, DUMP_TYPE_USER);
3880 	(void) emlxs_dump_parm_table(hba, fpTxtFile, fpDmpFile);
3881 	(void) emlxs_dump_cfg_regions(hba, fpTxtFile, fpDmpFile);
3882 
3883 	if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
3884 		(void) emlxs_set_hba_mode(hba, DDI_ONDI);
3885 		(void) emlxs_dump_saturn_log(hba, fpTxtFile, fpDmpFile);
3886 	}
3887 
3888 	if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
3889 	    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
3890 		(void) emlxs_dump_tigershark_log(hba, fpTxtFile, fpCeeFile);
3891 	}
3892 
3893 	if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
3894 		(void) emlxs_set_hba_mode(hba, DDI_DIAGDI);
3895 	}
3896 
3897 	(void) emlxs_dump_sli_interface(hba, fpTxtFile, fpDmpFile,
3898 	    DUMP_TYPE_USER);
3899 
3900 	if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
3901 		(void) emlxs_set_hba_mode(hba, DDI_WARMDI);
3902 	}
3903 
3904 	(void) emlxs_dump_hba(hba, fpTxtFile, fpDmpFile);
3905 
3906 	(void) emlxs_set_hba_mode(hba, DDI_ONDI);
3907 
3908 	status = emlxs_menlo_set_mode(hba, MENLO_MAINTENANCE_MODE_ENABLE);
3909 	if (status == 0) {
3910 		(void) emlxs_dump_menlo_log(hba, fpCeeFile);
3911 		(void) emlxs_menlo_set_mode(hba,
3912 		    MENLO_MAINTENANCE_MODE_DISABLE);
3913 	}
3914 
3915 	(void) emlxs_dump_file_terminate(hba, fpTxtFile, fpDmpFile, fpCeeFile);
3916 	(void) emlxs_dump_file_close(fpTxtFile, fpDmpFile, fpCeeFile);
3917 
3918 	mutex_exit(&EMLXS_DUMP_LOCK);
3919 	return (0);
3920 
3921 } /* emlxs_dump_user_event() */
3922 
3923 
3924 extern uint32_t
3925 emlxs_dump_temp_event(
3926 	emlxs_hba_t *hba,
3927 	uint32_t tempType,
3928 	uint32_t temp)
3929 {
3930 	emlxs_port_t *port = &PPORT;
3931 	uint32_t status;
3932 	emlxs_file_t *fpTxtFile;
3933 
3934 	/* misc vars */
3935 	char sBuf1[512];	/* general purpose string buffer */
3936 	char sBuf2[256];	/* general purpose string buffer */
3937 	char sBuf3[256];	/* general purpose string buffer */
3938 
3939 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3940 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3941 		    "Temperature Event: type=%d temp=%d.  "\
3942 		    "Invalid SLI4 event.",
3943 		    tempType, temp);
3944 
3945 		return (1);
3946 	}
3947 
3948 	mutex_enter(&EMLXS_DUMP_LOCK);
3949 
3950 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
3951 	    "Temperature Event: type=%d temp=%d.  "\
3952 	    "Firmware core dump initiated...",
3953 	    tempType, temp);
3954 
3955 	status = emlxs_dump_file_create(hba, &fpTxtFile, 0, 0);
3956 	if (status != 0) {
3957 		mutex_exit(&EMLXS_DUMP_LOCK);
3958 		return (1);
3959 	}
3960 
3961 	/* Now generate the Dump */
3962 	/* Note: ignore return (status); if one part fails, */
3963 	/* keep trying to dump more stuff. */
3964 
3965 	/* Write a warning at the top of the file */
3966 	(void) strcpy(sBuf1, "WARNING: HBA Temperature Event:\n");
3967 	switch (tempType) {
3968 	case TEMP_TYPE_CRITICAL:
3969 		(void) sprintf(sBuf2, " Event Type  = %d (Critical)\n",
3970 		    tempType);
3971 		break;
3972 	case TEMP_TYPE_THRESHOLD:
3973 		(void) sprintf(sBuf2, " Event Type  = %d (Threshold)\n",
3974 		    tempType);
3975 		break;
3976 	case TEMP_TYPE_NORMAL:
3977 		(void) sprintf(sBuf2, " Event Type  = %d (Normal)\n",
3978 		    tempType);
3979 		break;
3980 	default:
3981 		(void) sprintf(sBuf2, " Unknown Event Type  = %d\n", tempType);
3982 		break;
3983 	}
3984 	(void) sprintf(sBuf3, " Temperature = %d\n\n", temp);
3985 	(void) strcat(sBuf1, sBuf2);
3986 	(void) strcat(sBuf1, sBuf3);
3987 
3988 	(void) emlxs_dump_string_txtfile(fpTxtFile, sBuf1, 0, 0, 0);
3989 
3990 	(void) emlxs_dump_rev_info(hba, fpTxtFile, NULL);
3991 	(void) emlxs_dump_hba_info(hba, fpTxtFile, NULL, DUMP_TYPE_TEMP);
3992 
3993 	(void) emlxs_dump_file_terminate(hba, fpTxtFile, NULL, NULL);
3994 	(void) emlxs_dump_file_close(fpTxtFile, NULL, NULL);
3995 
3996 	mutex_exit(&EMLXS_DUMP_LOCK);
3997 	return (0);
3998 
3999 } /* emlxs_dump_temp_event() */
4000 
4001 
4002 extern uint32_t
4003 emlxs_dump_drv_event(
4004 	emlxs_hba_t *hba)
4005 {
4006 	emlxs_port_t *port = &PPORT;
4007 	uint32_t status;
4008 	emlxs_file_t *fpTxtFile;
4009 	emlxs_file_t *fpDmpFile;
4010 	emlxs_file_t *fpCeeFile;
4011 
4012 	mutex_enter(&EMLXS_DUMP_LOCK);
4013 
4014 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
4015 	    "Dump Event: Firmware core dump initiated...");
4016 
4017 	status =
4018 	    emlxs_dump_file_create(hba, &fpTxtFile, &fpDmpFile, &fpCeeFile);
4019 	if (status != 0) {
4020 		mutex_exit(&EMLXS_DUMP_LOCK);
4021 		return (1);
4022 	}
4023 
4024 	if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
4025 		(void) emlxs_set_hba_mode(hba, DDI_ONDI);
4026 		(void) emlxs_dump_saturn_log(hba, fpTxtFile, fpDmpFile);
4027 	}
4028 
4029 	if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
4030 	    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
4031 		(void) emlxs_dump_tigershark_log(hba, fpTxtFile, fpCeeFile);
4032 	}
4033 
4034 	if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
4035 		(void) emlxs_set_hba_mode(hba, DDI_DIAGDI);
4036 	}
4037 
4038 	(void) emlxs_dump_sli_interface(hba, fpTxtFile, fpDmpFile,
4039 	    DUMP_TYPE_DRIVER);
4040 
4041 	if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
4042 		(void) emlxs_set_hba_mode(hba, DDI_WARMDI);
4043 	}
4044 
4045 	(void) emlxs_dump_hba(hba, fpTxtFile, fpDmpFile);
4046 
4047 	(void) emlxs_set_hba_mode(hba, DDI_ONDI);
4048 
4049 	status = emlxs_menlo_set_mode(hba, MENLO_MAINTENANCE_MODE_ENABLE);
4050 	if (status == 0) {
4051 		(void) emlxs_dump_menlo_log(hba, fpCeeFile);
4052 	}
4053 
4054 	/* Now generate the rest of the Dump */
4055 	(void) emlxs_dump_rev_info(hba, fpTxtFile, fpDmpFile);
4056 	(void) emlxs_dump_hba_info(hba, fpTxtFile, fpDmpFile, DUMP_TYPE_DRIVER);
4057 	(void) emlxs_dump_parm_table(hba, fpTxtFile, fpDmpFile);
4058 	(void) emlxs_dump_cfg_regions(hba, fpTxtFile, fpDmpFile);
4059 
4060 	(void) emlxs_dump_file_terminate(hba, fpTxtFile, fpDmpFile, fpCeeFile);
4061 	(void) emlxs_dump_file_close(fpTxtFile, fpDmpFile, fpCeeFile);
4062 
4063 	/* The last step of the Menlo Dump. */
4064 	(void) emlxs_menlo_reset(hba, MENLO_FW_OPERATIONAL);
4065 
4066 	(void) emlxs_set_hba_mode(hba, DDI_WARMDI);
4067 
4068 	mutex_exit(&EMLXS_DUMP_LOCK);
4069 
4070 
4071 	return (0);
4072 
4073 } /* emlxs_dump_drv_event() */
4074 
4075 
4076 /* ARGSUSED */
4077 extern void
4078 emlxs_dump_drv_thread(emlxs_hba_t *hba,
4079 	void *arg1, void *arg2)
4080 {
4081 	(void) emlxs_dump_drv_event(hba);
4082 
4083 	/* Clear the Dump flag */
4084 	mutex_enter(&EMLXS_PORT_LOCK);
4085 	hba->flag &= ~FC_DUMP_ACTIVE;
4086 	mutex_exit(&EMLXS_PORT_LOCK);
4087 
4088 	return;
4089 
4090 } /* emlxs_dump_drv_thread() */
4091 
4092 
4093 /* ARGSUSED */
4094 extern void
4095 emlxs_dump_user_thread(emlxs_hba_t *hba,
4096 	void *arg1, void *arg2)
4097 {
4098 	(void) emlxs_dump_user_event(hba);
4099 
4100 	/* Clear the Dump flag */
4101 	mutex_enter(&EMLXS_PORT_LOCK);
4102 	hba->flag &= ~FC_DUMP_ACTIVE;
4103 	mutex_exit(&EMLXS_PORT_LOCK);
4104 
4105 	return;
4106 
4107 } /* emlxs_dump_user_thread() */
4108 
4109 
4110 /* ARGSUSED */
4111 extern void
4112 emlxs_dump_temp_thread(emlxs_hba_t *hba,
4113 	void *arg1, void *arg2)
4114 {
4115 	dump_temp_event_t *temp_event = (dump_temp_event_t *)arg1;
4116 
4117 	(void) emlxs_dump_temp_event(temp_event->hba, temp_event->type,
4118 	    temp_event->temp);
4119 
4120 	/* Free the temp event object */
4121 	kmem_free(temp_event, sizeof (dump_temp_event_t));
4122 
4123 	/* Clear the Dump flag */
4124 	mutex_enter(&EMLXS_PORT_LOCK);
4125 	hba->flag &= ~FC_DUMP_ACTIVE;
4126 	mutex_exit(&EMLXS_PORT_LOCK);
4127 
4128 	return;
4129 
4130 } /* emlxs_dump_temp_thread() */
4131 
4132 
4133 /* Schedules a dump thread */
4134 /* temp_type and temp are only valid for type=EMLXS_TEMP_DUMP */
4135 extern void
4136 emlxs_dump(emlxs_hba_t *hba, uint32_t type, uint32_t temp_type, uint32_t temp)
4137 {
4138 	emlxs_port_t *port = &PPORT;
4139 	dump_temp_event_t *temp_event = NULL;
4140 
4141 	mutex_enter(&EMLXS_PORT_LOCK);
4142 
4143 	/* Check if it is safe to dump */
4144 	if (!(hba->flag & FC_DUMP_SAFE)) {
4145 		mutex_exit(&EMLXS_PORT_LOCK);
4146 
4147 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
4148 		    "emlxs_dump: Dump disabled.");
4149 
4150 		return;
4151 	}
4152 
4153 	/* Check if a dump is already in progess */
4154 	if (hba->flag & FC_DUMP_ACTIVE) {
4155 		mutex_exit(&EMLXS_PORT_LOCK);
4156 
4157 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
4158 		    "emlxs_dump: Dump already in progress.");
4159 
4160 		return;
4161 	}
4162 
4163 	/* Prepare to schedule dump */
4164 	switch (type) {
4165 	case EMLXS_DRV_DUMP:
4166 	case EMLXS_USER_DUMP:
4167 		break;
4168 
4169 	case EMLXS_TEMP_DUMP:
4170 		temp_event = (dump_temp_event_t *)kmem_alloc(
4171 		    sizeof (dump_temp_event_t), KM_NOSLEEP);
4172 
4173 		if (temp_event == NULL) {
4174 			mutex_exit(&EMLXS_PORT_LOCK);
4175 
4176 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
4177 			    "emlxs_dump: Unable to allocate temp object.");
4178 
4179 			return;
4180 		}
4181 
4182 		temp_event->hba  = hba;
4183 		temp_event->type = temp_type;
4184 		temp_event->temp = temp;
4185 		break;
4186 
4187 	default:
4188 		mutex_exit(&EMLXS_PORT_LOCK);
4189 
4190 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg,
4191 		    "emlxs_dump: Error: Unknown dump type. (%x)",
4192 		    type);
4193 
4194 		return;
4195 	}
4196 
4197 	/* Set the Dump-in-progess flag */
4198 	hba->flag |= FC_DUMP_ACTIVE;
4199 	mutex_exit(&EMLXS_PORT_LOCK);
4200 
4201 	/* Create a separate thread to run the dump event */
4202 	switch (type) {
4203 	case EMLXS_DRV_DUMP:
4204 		emlxs_thread_spawn(hba, emlxs_dump_drv_thread, NULL, NULL);
4205 		break;
4206 
4207 	case EMLXS_TEMP_DUMP:
4208 		emlxs_thread_spawn(hba, emlxs_dump_temp_thread,
4209 		    (void *)temp_event, NULL);
4210 		break;
4211 
4212 	case EMLXS_USER_DUMP:
4213 		emlxs_thread_spawn(hba, emlxs_dump_user_thread, NULL, NULL);
4214 		break;
4215 	}
4216 
4217 	return;
4218 
4219 } /* emlxs_dump() */
4220 
4221 extern void
4222 emlxs_dump_wait(emlxs_hba_t *hba)
4223 {
4224 	/* Wait for the Dump flag to clear */
4225 	while ((hba->flag & FC_DUMP_ACTIVE)) {
4226 		DELAYMS(1000);
4227 	}
4228 
4229 } /* emlxs_dump_wait() */
4230 
4231 
4232 #endif /* DUMP_SUPPORT */
4233