xref: /freebsd/sys/dev/aacraid/aacraid_debug.c (revision 8ef24a0d4b28fe230e20637f56869cc4148cd2ca)
1 
2 /*-
3  * Copyright (c) 2006-2010 Adaptec, Inc.
4  * Copyright (c) 2010-2012 PMC-Sierra, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 /*
34  * Debugging support.
35  */
36 #include "opt_aacraid.h"
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/conf.h>
42 
43 #include <sys/bus.h>
44 
45 #include <machine/resource.h>
46 #include <machine/bus.h>
47 
48 #include <dev/aacraid/aacraid_reg.h>
49 #include <sys/aac_ioctl.h>
50 #include <dev/aacraid/aacraid_var.h>
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/kernel.h>
54 #include <sys/conf.h>
55 
56 #include <sys/bus.h>
57 #include <sys/rman.h>
58 
59 #include <machine/resource.h>
60 #include <machine/bus.h>
61 #include <machine/stdarg.h>
62 
63 #include <dev/aacraid/aacraid_debug.h>
64 
65 #ifdef AACRAID_DEBUG
66 /*
67  * Dump the command queue indices
68  */
69 void
70 aacraid_print_queues(struct aac_softc *sc)
71 {
72 	device_printf(sc->aac_dev, "AACQ_FREE      %d/%d\n",
73 	    sc->aac_qstat[AACQ_FREE].q_length, sc->aac_qstat[AACQ_FREE].q_max);
74 	device_printf(sc->aac_dev, "AACQ_READY     %d/%d\n",
75 	    sc->aac_qstat[AACQ_READY].q_length,
76 	    sc->aac_qstat[AACQ_READY].q_max);
77 	device_printf(sc->aac_dev, "AACQ_BUSY      %d/%d\n",
78 	    sc->aac_qstat[AACQ_BUSY].q_length, sc->aac_qstat[AACQ_BUSY].q_max);
79 }
80 
81 /*
82  * Print a FIB
83  */
84 void
85 aacraid_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller)
86 {
87 	if (fib == NULL) {
88 		device_printf(sc->aac_dev,
89 			      "aac_print_fib called with NULL fib\n");
90 		return;
91 	}
92 	device_printf(sc->aac_dev, "%s: FIB @ %p\n", caller, fib);
93 	device_printf(sc->aac_dev, "  XferState %b\n", fib->Header.XferState,
94 		      "\20"
95 		      "\1HOSTOWNED"
96 		      "\2ADAPTEROWNED"
97 		      "\3INITIALISED"
98 		      "\4EMPTY"
99 		      "\5FROMPOOL"
100 		      "\6FROMHOST"
101 		      "\7FROMADAP"
102 		      "\10REXPECTED"
103 		      "\11RNOTEXPECTED"
104 		      "\12DONEADAP"
105 		      "\13DONEHOST"
106 		      "\14HIGH"
107 		      "\15NORM"
108 		      "\16ASYNC"
109 		      "\17PAGEFILEIO"
110 		      "\20SHUTDOWN"
111 		      "\21LAZYWRITE"
112 		      "\22ADAPMICROFIB"
113 		      "\23BIOSFIB"
114 		      "\24FAST_RESPONSE"
115 		      "\25APIFIB\n");
116 	device_printf(sc->aac_dev, "  Command       %d\n", fib->Header.Command);
117 	device_printf(sc->aac_dev, "  StructType    %d\n",
118 		      fib->Header.StructType);
119 	device_printf(sc->aac_dev, "  Size          %d\n", fib->Header.Size);
120 	device_printf(sc->aac_dev, "  SenderSize    %d\n",
121 		      fib->Header.SenderSize);
122 	device_printf(sc->aac_dev, "  SenderAddress 0x%x\n",
123 		      fib->Header.SenderFibAddress);
124 	device_printf(sc->aac_dev, "  RcvrAddress   0x%x\n",
125 		      fib->Header.u.ReceiverFibAddress);
126 	device_printf(sc->aac_dev, "  Handle    0x%x\n",
127 		      fib->Header.Handle);
128 	switch(fib->Header.Command) {
129 	case ContainerCommand:
130 	{
131 		struct aac_blockread *br;
132 		struct aac_blockwrite *bw;
133 		struct aac_sg_table *sg;
134 		int i;
135 
136 		br = (struct aac_blockread*)fib->data;
137 		bw = (struct aac_blockwrite*)fib->data;
138 		sg = NULL;
139 
140 		if (br->Command == VM_CtBlockRead) {
141 			device_printf(sc->aac_dev,
142 				      "  BlockRead: container %d  0x%x/%d\n",
143 				      br->ContainerId, br->BlockNumber,
144 				      br->ByteCount);
145 			sg = &br->SgMap;
146 		}
147 		if (bw->Command == VM_CtBlockWrite) {
148 			device_printf(sc->aac_dev,
149 				      "  BlockWrite: container %d  0x%x/%d "
150 				      "(%s)\n", bw->ContainerId,
151 				      bw->BlockNumber, bw->ByteCount,
152 				      bw->Stable == CSTABLE ? "stable" :
153 				      "unstable");
154 			sg = &bw->SgMap;
155 		}
156 		if (sg != NULL) {
157 			device_printf(sc->aac_dev,
158 				      "  %d s/g entries\n", sg->SgCount);
159 			for (i = 0; i < sg->SgCount; i++)
160 				device_printf(sc->aac_dev, "  0x%08x/%d\n",
161 					      sg->SgEntry[i].SgAddress,
162 					      sg->SgEntry[i].SgByteCount);
163 		}
164 		break;
165 	}
166 	default:
167 		device_printf(sc->aac_dev, "   %16D\n", fib->data, " ");
168 		device_printf(sc->aac_dev, "   %16D\n", fib->data + 16, " ");
169 		break;
170 	}
171 }
172 
173 /*
174  * Describe an AIF we have received.
175  */
176 void
177 aacraid_print_aif(struct aac_softc *sc, struct aac_aif_command *aif)
178 {
179 	switch(aif->command) {
180 	case AifCmdEventNotify:
181 		device_printf(sc->aac_dev, "EventNotify(%d)\n", aif->seqNumber);
182 		switch(aif->data.EN.type) {
183 		case AifEnGeneric:		/* Generic notification */
184 			device_printf(sc->aac_dev, "(Generic) %.*s\n",
185 				  (int)sizeof(aif->data.EN.data.EG),
186 				  aif->data.EN.data.EG.text);
187 			break;
188 		case AifEnTaskComplete:		/* Task has completed */
189 			device_printf(sc->aac_dev, "(TaskComplete)\n");
190 			break;
191 		case AifEnConfigChange:		/* Adapter configuration change
192 						 * occurred */
193 			device_printf(sc->aac_dev, "(ConfigChange)\n");
194 			break;
195 		case AifEnContainerChange:	/* Adapter specific container
196 						 * configuration change */
197 			device_printf(sc->aac_dev, "(ContainerChange) "
198 				      "container %d,%d\n",
199 				      aif->data.EN.data.ECC.container[0],
200 				      aif->data.EN.data.ECC.container[1]);
201 			break;
202 		case AifEnDeviceFailure:	/* SCSI device failed */
203 			device_printf(sc->aac_dev, "(DeviceFailure) "
204 				      "handle %d\n",
205 				      aif->data.EN.data.EDF.deviceHandle);
206 			break;
207 		case AifEnMirrorFailover:	/* Mirror failover started */
208 			device_printf(sc->aac_dev, "(MirrorFailover) "
209 				      "container %d failed, "
210 				      "migrating from slice %d to %d\n",
211 				      aif->data.EN.data.EMF.container,
212 				      aif->data.EN.data.EMF.failedSlice,
213 				      aif->data.EN.data.EMF.creatingSlice);
214 			break;
215 		case AifEnContainerEvent:	/* Significant container
216 						 * event */
217 			device_printf(sc->aac_dev, "(ContainerEvent) "
218 				      "container %d event "
219 				      "%d\n", aif->data.EN.data.ECE.container,
220 				      aif->data.EN.data.ECE.eventType);
221 			break;
222 		case AifEnFileSystemChange:	/* File system changed */
223 			device_printf(sc->aac_dev, "(FileSystemChange)\n");
224 			break;
225 		case AifEnConfigPause:		/* Container pause event */
226 			device_printf(sc->aac_dev, "(ConfigPause)\n");
227 			break;
228 		case AifEnConfigResume:		/* Container resume event */
229 			device_printf(sc->aac_dev, "(ConfigResume)\n");
230 			break;
231 		case AifEnFailoverChange:	/* Failover space assignment
232 						 * changed */
233 			device_printf(sc->aac_dev, "(FailoverChange)\n");
234 			break;
235 		case AifEnRAID5RebuildDone:	/* RAID5 rebuild finished */
236 			device_printf(sc->aac_dev, "(RAID5RebuildDone)\n");
237 			break;
238 		case AifEnEnclosureManagement:	/* Enclosure management event */
239 			device_printf(sc->aac_dev, "(EnclosureManagement) "
240 				      "EMPID %d unit %d "
241 				      "event %d\n", aif->data.EN.data.EEE.empID,
242 				      aif->data.EN.data.EEE.unitID,
243 				      aif->data.EN.data.EEE.eventType);
244 			break;
245 		case AifEnBatteryEvent:		/* Significant NV battery
246 						 * event */
247 			device_printf(sc->aac_dev, "(BatteryEvent) %d "
248 				      "(state was %d, is %d\n",
249 				      aif->data.EN.data.EBE.transition_type,
250 				      aif->data.EN.data.EBE.current_state,
251 				      aif->data.EN.data.EBE.prior_state);
252 			break;
253 		case AifEnAddContainer:		/* A new container was
254 						 * created. */
255 			device_printf(sc->aac_dev, "(AddContainer)\n");
256 			break;
257 		case AifEnDeleteContainer:	/* A container was deleted. */
258 			device_printf(sc->aac_dev, "(DeleteContainer)\n");
259 			break;
260 		case AifEnBatteryNeedsRecond:	/* The battery needs
261 						 * reconditioning */
262 			device_printf(sc->aac_dev, "(BatteryNeedsRecond)\n");
263 			break;
264 		case AifEnClusterEvent:		/* Some cluster event */
265 			device_printf(sc->aac_dev, "(ClusterEvent) event %d\n",
266 				      aif->data.EN.data.ECLE.eventType);
267 			break;
268 		case AifEnDiskSetEvent:		/* A disk set event occurred. */
269 			device_printf(sc->aac_dev, "(DiskSetEvent) event %d "
270 				      "diskset %jd creator %jd\n",
271 				      aif->data.EN.data.EDS.eventType,
272 				      (intmax_t)aif->data.EN.data.EDS.DsNum,
273 				      (intmax_t)aif->data.EN.data.EDS.CreatorId);
274 			break;
275 		case AifDenMorphComplete: 	/* A morph operation
276 						 * completed */
277 			device_printf(sc->aac_dev, "(MorphComplete)\n");
278 			break;
279 		case AifDenVolumeExtendComplete: /* A volume expand operation
280 						  * completed */
281 			device_printf(sc->aac_dev, "(VolumeExtendComplete)\n");
282 			break;
283 		default:
284 			device_printf(sc->aac_dev, "(%d)\n", aif->data.EN.type);
285 			break;
286 		}
287 		break;
288 	case AifCmdJobProgress:
289 	{
290 		char	*status;
291 		switch(aif->data.PR[0].status) {
292 		case AifJobStsSuccess:
293 			status = "success"; break;
294 		case AifJobStsFinished:
295 			status = "finished"; break;
296 		case AifJobStsAborted:
297 			status = "aborted"; break;
298 		case AifJobStsFailed:
299 			status = "failed"; break;
300 		case AifJobStsSuspended:
301 			status = "suspended"; break;
302 		case AifJobStsRunning:
303 			status = "running"; break;
304 		default:
305 			status = "unknown status"; break;
306 		}
307 
308 		device_printf(sc->aac_dev, "JobProgress (%d) - %s (%d, %d)\n",
309 			      aif->seqNumber, status,
310 			      aif->data.PR[0].currentTick,
311 			      aif->data.PR[0].finalTick);
312 		switch(aif->data.PR[0].jd.type) {
313 		case AifJobScsiZero:		/* SCSI dev clear operation */
314 			device_printf(sc->aac_dev, "(ScsiZero) handle %d\n",
315 				      aif->data.PR[0].jd.client.scsi_dh);
316 			break;
317 		case AifJobScsiVerify:		/* SCSI device Verify operation
318 						 * NO REPAIR */
319 			device_printf(sc->aac_dev, "(ScsiVerify) handle %d\n",
320 				      aif->data.PR[0].jd.client.scsi_dh);
321 			break;
322 		case AifJobScsiExercise:	/* SCSI device Exercise
323 						 * operation */
324 			device_printf(sc->aac_dev, "(ScsiExercise) handle %d\n",
325 				      aif->data.PR[0].jd.client.scsi_dh);
326 			break;
327 		case AifJobScsiVerifyRepair:	/* SCSI device Verify operation
328 						 * WITH repair */
329 			device_printf(sc->aac_dev,
330 				      "(ScsiVerifyRepair) handle %d\n",
331 				      aif->data.PR[0].jd.client.scsi_dh);
332 			break;
333 		case AifJobCtrZero:		/* Container clear operation */
334 			device_printf(sc->aac_dev,
335 				      "(ContainerZero) container %d\n",
336 				      aif->data.PR[0].jd.client.container.src);
337 			break;
338 		case AifJobCtrCopy:		/* Container copy operation */
339 			device_printf(sc->aac_dev,
340 				      "(ContainerCopy) container %d to %d\n",
341 				      aif->data.PR[0].jd.client.container.src,
342 				      aif->data.PR[0].jd.client.container.dst);
343 			break;
344 		case AifJobCtrCreateMirror:	/* Container Create Mirror
345 						 * operation */
346 			device_printf(sc->aac_dev,
347 				      "(ContainerCreateMirror) container %d\n",
348 				      aif->data.PR[0].jd.client.container.src);
349 				      /* XXX two containers? */
350 			break;
351 		case AifJobCtrMergeMirror:	/* Container Merge Mirror
352 						 * operation */
353 			device_printf(sc->aac_dev,
354 				      "(ContainerMergeMirror) container %d\n",
355 				      aif->data.PR[0].jd.client.container.src);
356 				      /* XXX two containers? */
357 			break;
358 		case AifJobCtrScrubMirror:	/* Container Scrub Mirror
359 						 * operation */
360 			device_printf(sc->aac_dev,
361 				      "(ContainerScrubMirror) container %d\n",
362 				      aif->data.PR[0].jd.client.container.src);
363 			break;
364 		case AifJobCtrRebuildRaid5:	/* Container Rebuild Raid5
365 						 * operation */
366 			device_printf(sc->aac_dev,
367 				      "(ContainerRebuildRaid5) container %d\n",
368 				      aif->data.PR[0].jd.client.container.src);
369 			break;
370 		case AifJobCtrScrubRaid5:	/* Container Scrub Raid5
371 						 * operation */
372 			device_printf(sc->aac_dev,
373 				      "(ContainerScrubRaid5) container %d\n",
374 				      aif->data.PR[0].jd.client.container.src);
375 			break;
376 		case AifJobCtrMorph:		/* Container morph operation */
377 			device_printf(sc->aac_dev,
378 				      "(ContainerMorph) container %d\n",
379 				      aif->data.PR[0].jd.client.container.src);
380 				      /* XXX two containers? */
381 			break;
382 		case AifJobCtrPartCopy:		/* Container Partition copy
383 						 * operation */
384 			device_printf(sc->aac_dev,
385 				      "(ContainerPartCopy) container %d to "
386 				      "%d\n",
387 				      aif->data.PR[0].jd.client.container.src,
388 				      aif->data.PR[0].jd.client.container.dst);
389 			break;
390 		case AifJobCtrRebuildMirror:	/* Container Rebuild Mirror
391 						 * operation */
392 			device_printf(sc->aac_dev,
393 				      "(ContainerRebuildMirror) container "
394 				      "%d\n",
395 				      aif->data.PR[0].jd.client.container.src);
396 			break;
397 		case AifJobCtrCrazyCache:	/* crazy cache */
398 			device_printf(sc->aac_dev,
399 				      "(ContainerCrazyCache) container %d\n",
400 				      aif->data.PR[0].jd.client.container.src);
401 				      /* XXX two containers? */
402 			break;
403 		case AifJobFsCreate:		/* File System Create
404 						 * operation */
405 			device_printf(sc->aac_dev, "(FsCreate)\n");
406 			break;
407 		case AifJobFsVerify:		/* File System Verify
408 						 * operation */
409 			device_printf(sc->aac_dev, "(FsVerivy)\n");
410 			break;
411 		case AifJobFsExtend:		/* File System Extend
412 						 * operation */
413 			device_printf(sc->aac_dev, "(FsExtend)\n");
414 			break;
415 		case AifJobApiFormatNTFS:	/* Format a drive to NTFS */
416 			device_printf(sc->aac_dev, "(FormatNTFS)\n");
417 			break;
418 		case AifJobApiFormatFAT:	/* Format a drive to FAT */
419 			device_printf(sc->aac_dev, "(FormatFAT)\n");
420 			break;
421 		case AifJobApiUpdateSnapshot:	/* update the read/write half
422 						 * of a snapshot */
423 			device_printf(sc->aac_dev, "(UpdateSnapshot)\n");
424 			break;
425 		case AifJobApiFormatFAT32:	/* Format a drive to FAT32 */
426 			device_printf(sc->aac_dev, "(FormatFAT32)\n");
427 			break;
428 		case AifJobCtlContinuousCtrVerify: /* Adapter operation */
429 			device_printf(sc->aac_dev, "(ContinuousCtrVerify)\n");
430 			break;
431 		default:
432 			device_printf(sc->aac_dev, "(%d)\n",
433 				      aif->data.PR[0].jd.type);
434 			break;
435 		}
436 		break;
437 	}
438 	case AifCmdAPIReport:
439 		device_printf(sc->aac_dev, "APIReport (%d)\n", aif->seqNumber);
440 		break;
441 	case AifCmdDriverNotify:
442 		device_printf(sc->aac_dev, "DriverNotify (%d)\n",
443 			      aif->seqNumber);
444 		break;
445 	default:
446 		device_printf(sc->aac_dev, "AIF %d (%d)\n", aif->command,
447 			      aif->seqNumber);
448 		break;
449 	}
450 }
451 #endif /* AACRAID_DEBUG */
452 
453 /*
454  * Debug flags to be put into the HBA flags field when initialized
455  */
456 const unsigned long aacraid_debug_flags = /* Variable to setup with above flags. */
457 /*			HBA_FLAGS_DBG_KERNEL_PRINT_B |		*/
458 			HBA_FLAGS_DBG_FW_PRINT_B |
459 /*			HBA_FLAGS_DBG_FUNCTION_ENTRY_B |	*/
460 			HBA_FLAGS_DBG_FUNCTION_EXIT_B |
461 			HBA_FLAGS_DBG_ERROR_B |
462 			HBA_FLAGS_DBG_INIT_B |
463 /*			HBA_FLAGS_DBG_OS_COMMANDS_B |		*/
464 /*			HBA_FLAGS_DBG_SCAN_B |			*/
465 /*			HBA_FLAGS_DBG_COALESCE_B |		*/
466 /*			HBA_FLAGS_DBG_IOCTL_COMMANDS_B |	*/
467 /*			HBA_FLAGS_DBG_SYNC_COMMANDS_B |		*/
468 			HBA_FLAGS_DBG_COMM_B |
469 /*			HBA_FLAGS_DBG_AIF_B |			*/
470 /*			HBA_FLAGS_DBG_CSMI_COMMANDS_B | 	*/
471 			HBA_FLAGS_DBG_DEBUG_B |
472 /*			HBA_FLAGS_DBG_FLAGS_MASK | 		*/
473 0;
474 
475 int aacraid_get_fw_debug_buffer(struct aac_softc *sc)
476 {
477 	u_int32_t MonDriverBufferPhysAddrLow = 0;
478 	u_int32_t MonDriverBufferPhysAddrHigh = 0;
479 	u_int32_t MonDriverBufferSize = 0;
480 	u_int32_t MonDriverHeaderSize = 0;
481 
482 	/*
483 	 * Get the firmware print buffer parameters from the firmware
484 	 * If the command was successful map in the address.
485 	 */
486 	if (!aacraid_sync_command(sc, AAC_MONKER_GETDRVPROP, 0, 0, 0, 0, NULL, NULL)) {
487 		MonDriverBufferPhysAddrLow = AAC_GET_MAILBOX(sc, 1);
488 		MonDriverBufferPhysAddrHigh = AAC_GET_MAILBOX(sc, 2);
489 		MonDriverBufferSize = AAC_GET_MAILBOX(sc, 3);
490 		MonDriverHeaderSize = AAC_GET_MAILBOX(sc, 4);
491 		if (MonDriverBufferSize) {
492 			unsigned long Offset = MonDriverBufferPhysAddrLow
493 				- rman_get_start(sc->aac_regs_res1);
494 
495 			/*
496 			 * See if the address is already mapped in and if so set it up
497 			 * from the base address
498 			 */
499 			if ((MonDriverBufferPhysAddrHigh == 0) &&
500 				(Offset + MonDriverBufferSize <
501 				rman_get_size(sc->aac_regs_res1))) {
502 				sc->DebugOffset = Offset;
503 				sc->DebugHeaderSize = MonDriverHeaderSize;
504 				sc->FwDebugBufferSize = MonDriverBufferSize;
505 				sc->FwDebugFlags = 0;
506 				sc->DebugFlags = aacraid_debug_flags;
507 				return 1;
508 			}
509 		}
510 	}
511 
512 	/*
513 	 * The GET_DRIVER_BUFFER_PROPERTIES command failed
514 	 */
515 	return 0;
516 }
517 
518 #define PRINT_TIMEOUT 250000 /* 1/4 second */
519 
520 void aacraid_fw_printf(struct aac_softc *sc, unsigned long PrintFlags, const char * fmt, ...)
521 {
522 	va_list args;
523 	u_int32_t Count, i;
524 	char PrintBuffer_P[PRINT_BUFFER_SIZE];
525 	unsigned long PrintType;
526 
527 	PrintType = PrintFlags &
528 		~(HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B);
529 	if (((PrintType!=0) && (sc!=NULL) && ((sc->DebugFlags & PrintType)==0))
530 		|| ((sc!=NULL) && (sc->DebugFlags
531 		& (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B)) == 0))
532 		return;
533 
534 	/*
535 	 * Set up parameters and call sprintf function to format the data
536 	 */
537 	va_start(args, fmt);
538 	vsprintf(PrintBuffer_P, fmt, args);
539 	va_end(args);
540 
541 	/*
542 	 * Make sure the HBA structure has been passed in for this section
543 	 */
544 	if ((sc != NULL) && (sc->FwDebugBufferSize)) {
545 		/*
546 		 * If we are set up for a Firmware print
547 		 */
548 		if ((sc->DebugFlags & HBA_FLAGS_DBG_FW_PRINT_B)
549 			&& ((PrintFlags
550 			& (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B))
551 			!= HBA_FLAGS_DBG_KERNEL_PRINT_B)) {
552 			/*
553 			 * Make sure the string size is within boundaries
554 			 */
555 			Count = strlen(PrintBuffer_P);
556 			if (Count > sc->FwDebugBufferSize)
557 				Count = (u_int16_t)sc->FwDebugBufferSize;
558 
559 			/*
560 			 * Wait for no more than PRINT_TIMEOUT for the previous
561 			 * message length to clear (the handshake).
562 			 */
563 			for (i = 0; i < PRINT_TIMEOUT; ++i) {
564 				if (!AAC_MEM1_GETREG4(sc,
565 					sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET)) {
566 					break;
567 				}
568 				DELAY(1);
569             }
570 
571 			/*
572 			 * If the Length is clear, copy over the message, the
573 			 * flags, and the length. Make sure the length is the
574 			 * last because that is the signal for the Firmware to
575 			 * pick it up.
576 			 */
577 			if (!AAC_MEM1_GETREG4(sc,
578 				sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET)) {
579 				for (i = 0; i < Count; ++i) {
580 					AAC_MEM1_SETREG1(sc, sc->DebugOffset + sc->DebugHeaderSize + i,
581 								PrintBuffer_P[i]);
582 				}
583 				AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_FLAGS_OFFSET,
584 							sc->FwDebugFlags);
585 				AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET,
586                             Count);
587 			} else
588 				sc->DebugFlags &= ~HBA_FLAGS_DBG_FW_PRINT_B;
589 		}
590 
591 		/*
592 		 * If the Kernel Debug Print flag is set, send it off to the
593 		 * Kernel debugger
594 		 */
595 		if ((sc->DebugFlags & HBA_FLAGS_DBG_KERNEL_PRINT_B)
596 			&& ((PrintFlags
597 			& (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B))
598 			!= HBA_FLAGS_DBG_FW_PRINT_B)) {
599 			if (sc->FwDebugFlags & FW_DEBUG_FLAGS_NO_HEADERS_B)
600 				printf ("%s\n", PrintBuffer_P);
601 			else
602 				device_printf (sc->aac_dev, "%s\n", PrintBuffer_P);
603 		}
604 
605 	} else {
606 		/*
607 		 * No HBA structure passed in so it has to be for the Kernel Debugger
608 		 */
609 		if ((sc != NULL) && (sc->FwDebugFlags & FW_DEBUG_FLAGS_NO_HEADERS_B))
610 			printf ("%s\n", PrintBuffer_P);
611 		else if (sc != NULL)
612 			device_printf (sc->aac_dev, "%s\n", PrintBuffer_P);
613 		else
614 			printf("%s\n", PrintBuffer_P);
615 	}
616 }
617 
618 void aacraid_fw_print_mem(struct aac_softc *sc, unsigned long PrintFlags, u_int8_t *Addr, int Count)
619 {
620 	int Offset, i;
621 	u_int32_t DebugFlags = 0;
622 	char Buffer[100];
623 	char *LineBuffer_P;
624 
625 	/*
626 	 * If we have an HBA structure, save off the flags and set the no
627 	 * headers flag so we don't have garbage between our lines of data
628 	 */
629 	if (sc != NULL) {
630 		DebugFlags = sc->FwDebugFlags;
631 		sc->FwDebugFlags |= FW_DEBUG_FLAGS_NO_HEADERS_B;
632 	}
633 
634 	Offset = 0;
635 
636 	/*
637 	 * Loop through all the data
638 	 */
639 	while (Offset < Count) {
640 		/*
641 		 * We will format each line into a buffer and then print out
642 		 * the entire line so set the pointer to the beginning of the
643 		 * buffer
644 		 */
645 		LineBuffer_P = Buffer;
646 
647 		/*
648 		 * Set up the address in HEX
649 		 */
650 		sprintf(LineBuffer_P, "\n%04x  ", Offset);
651 		LineBuffer_P += 6;
652 
653 		/*
654 		 * Set up 16 bytes in HEX format
655 		 */
656 		for (i = 0; i < 16; ++i) {
657 			/*
658 			 * If we are past the count of data bytes to output,
659 			 * pad with blanks
660 			 */
661 			if ((Offset + i) >= Count)
662 				sprintf (LineBuffer_P, "   ");
663 			else
664 			  	sprintf (LineBuffer_P, "%02x ", Addr[Offset+i]);
665 			LineBuffer_P += 3;
666 
667 			/*
668 			 * At the mid point we will put in a divider
669 			 */
670 			if (i == 7) {
671 				sprintf (LineBuffer_P, "- ");
672 				LineBuffer_P += 2;
673 			}
674 		}
675 		/*
676 		 * Now do the same 16 bytes at the end of the line in ASCII
677 		 * format
678 		 */
679 		sprintf (LineBuffer_P, "  ");
680 		LineBuffer_P += 2;
681 		for (i = 0; i < 16; ++i) {
682 			/*
683 			 * If all data processed, OUT-O-HERE
684 			 */
685 			if ((Offset + i) >= Count)
686 				break;
687 
688 			/*
689 			 * If this is a printable ASCII character, convert it
690 			 */
691 			if ((Addr[Offset+i] > 0x1F) && (Addr[Offset+i] < 0x7F))
692 				sprintf (LineBuffer_P, "%c", Addr[Offset+i]);
693 			else
694 				sprintf (LineBuffer_P, ".");
695 			++LineBuffer_P;
696 		}
697 		/*
698 		 * The line is now formatted, so print it out
699 		 */
700 		aacraid_fw_printf(sc, PrintFlags, "%s", Buffer);
701 
702 		/*
703 		 * Bump the offset by 16 for the next line
704 		 */
705 		Offset += 16;
706 
707 	}
708 
709 	/*
710 	 * Restore the saved off flags
711 	 */
712 	if (sc != NULL)
713 		sc->FwDebugFlags = DebugFlags;
714 }
715 
716