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