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