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