aacraid_debug.c revision 330897
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: stable/11/sys/dev/aacraid/aacraid_debug.c 330897 2018-03-14 03:19:51Z eadler $");
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 */
70void
71aacraid_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 */
85void
86aacraid_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 */
177void
178aacraid_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 */
457const 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 | 		*/
4740;
475
476int 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
521void 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
619void 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