aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/aacraid/aacraid_debug.c
diff options
context:
space:
mode:
authorAchim Leubner <achim@FreeBSD.org>2013-05-24 09:22:43 +0000
committerAchim Leubner <achim@FreeBSD.org>2013-05-24 09:22:43 +0000
commitdce93cd06d04c24cc142989c1adcb1929b0a2f26 (patch)
tree8bf15f63d33c02d7e556aa6725fc410c0f737892 /sys/dev/aacraid/aacraid_debug.c
parent3f61f926ea32a375604c12805119cb444354676e (diff)
Notes
Diffstat (limited to 'sys/dev/aacraid/aacraid_debug.c')
-rw-r--r--sys/dev/aacraid/aacraid_debug.c715
1 files changed, 715 insertions, 0 deletions
diff --git a/sys/dev/aacraid/aacraid_debug.c b/sys/dev/aacraid/aacraid_debug.c
new file mode 100644
index 0000000000000..6062d72d005da
--- /dev/null
+++ b/sys/dev/aacraid/aacraid_debug.c
@@ -0,0 +1,715 @@
+
+/*-
+ * Copyright (c) 2006-2010 Adaptec, Inc.
+ * Copyright (c) 2010-2012 PMC-Sierra, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Debugging support.
+ */
+#include "opt_aacraid.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+
+#include <sys/bus.h>
+
+#include <machine/resource.h>
+#include <machine/bus.h>
+
+#include <dev/aacraid/aacraid_reg.h>
+#include <sys/aac_ioctl.h>
+#include <dev/aacraid/aacraid_var.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <machine/stdarg.h>
+
+#include <dev/aacraid/aacraid_debug.h>
+
+#ifdef AACRAID_DEBUG
+/*
+ * Dump the command queue indices
+ */
+void
+aacraid_print_queues(struct aac_softc *sc)
+{
+ device_printf(sc->aac_dev, "AACQ_FREE %d/%d\n",
+ sc->aac_qstat[AACQ_FREE].q_length, sc->aac_qstat[AACQ_FREE].q_max);
+ device_printf(sc->aac_dev, "AACQ_READY %d/%d\n",
+ sc->aac_qstat[AACQ_READY].q_length,
+ sc->aac_qstat[AACQ_READY].q_max);
+ device_printf(sc->aac_dev, "AACQ_BUSY %d/%d\n",
+ sc->aac_qstat[AACQ_BUSY].q_length, sc->aac_qstat[AACQ_BUSY].q_max);
+}
+
+/*
+ * Print a FIB
+ */
+void
+aacraid_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller)
+{
+ if (fib == NULL) {
+ device_printf(sc->aac_dev,
+ "aac_print_fib called with NULL fib\n");
+ return;
+ }
+ device_printf(sc->aac_dev, "%s: FIB @ %p\n", caller, fib);
+ device_printf(sc->aac_dev, " XferState %b\n", fib->Header.XferState,
+ "\20"
+ "\1HOSTOWNED"
+ "\2ADAPTEROWNED"
+ "\3INITIALISED"
+ "\4EMPTY"
+ "\5FROMPOOL"
+ "\6FROMHOST"
+ "\7FROMADAP"
+ "\10REXPECTED"
+ "\11RNOTEXPECTED"
+ "\12DONEADAP"
+ "\13DONEHOST"
+ "\14HIGH"
+ "\15NORM"
+ "\16ASYNC"
+ "\17PAGEFILEIO"
+ "\20SHUTDOWN"
+ "\21LAZYWRITE"
+ "\22ADAPMICROFIB"
+ "\23BIOSFIB"
+ "\24FAST_RESPONSE"
+ "\25APIFIB\n");
+ device_printf(sc->aac_dev, " Command %d\n", fib->Header.Command);
+ device_printf(sc->aac_dev, " StructType %d\n",
+ fib->Header.StructType);
+ device_printf(sc->aac_dev, " Size %d\n", fib->Header.Size);
+ device_printf(sc->aac_dev, " SenderSize %d\n",
+ fib->Header.SenderSize);
+ device_printf(sc->aac_dev, " SenderAddress 0x%x\n",
+ fib->Header.SenderFibAddress);
+ device_printf(sc->aac_dev, " RcvrAddress 0x%x\n",
+ fib->Header.u.ReceiverFibAddress);
+ device_printf(sc->aac_dev, " Handle 0x%x\n",
+ fib->Header.Handle);
+ switch(fib->Header.Command) {
+ case ContainerCommand:
+ {
+ struct aac_blockread *br;
+ struct aac_blockwrite *bw;
+ struct aac_sg_table *sg;
+ int i;
+
+ br = (struct aac_blockread*)fib->data;
+ bw = (struct aac_blockwrite*)fib->data;
+ sg = NULL;
+
+ if (br->Command == VM_CtBlockRead) {
+ device_printf(sc->aac_dev,
+ " BlockRead: container %d 0x%x/%d\n",
+ br->ContainerId, br->BlockNumber,
+ br->ByteCount);
+ sg = &br->SgMap;
+ }
+ if (bw->Command == VM_CtBlockWrite) {
+ device_printf(sc->aac_dev,
+ " BlockWrite: container %d 0x%x/%d "
+ "(%s)\n", bw->ContainerId,
+ bw->BlockNumber, bw->ByteCount,
+ bw->Stable == CSTABLE ? "stable" :
+ "unstable");
+ sg = &bw->SgMap;
+ }
+ if (sg != NULL) {
+ device_printf(sc->aac_dev,
+ " %d s/g entries\n", sg->SgCount);
+ for (i = 0; i < sg->SgCount; i++)
+ device_printf(sc->aac_dev, " 0x%08x/%d\n",
+ sg->SgEntry[i].SgAddress,
+ sg->SgEntry[i].SgByteCount);
+ }
+ break;
+ }
+ default:
+ device_printf(sc->aac_dev, " %16D\n", fib->data, " ");
+ device_printf(sc->aac_dev, " %16D\n", fib->data + 16, " ");
+ break;
+ }
+}
+
+/*
+ * Describe an AIF we have received.
+ */
+void
+aacraid_print_aif(struct aac_softc *sc, struct aac_aif_command *aif)
+{
+ switch(aif->command) {
+ case AifCmdEventNotify:
+ device_printf(sc->aac_dev, "EventNotify(%d)\n", aif->seqNumber);
+ switch(aif->data.EN.type) {
+ case AifEnGeneric: /* Generic notification */
+ device_printf(sc->aac_dev, "(Generic) %.*s\n",
+ (int)sizeof(aif->data.EN.data.EG),
+ aif->data.EN.data.EG.text);
+ break;
+ case AifEnTaskComplete: /* Task has completed */
+ device_printf(sc->aac_dev, "(TaskComplete)\n");
+ break;
+ case AifEnConfigChange: /* Adapter configuration change
+ * occurred */
+ device_printf(sc->aac_dev, "(ConfigChange)\n");
+ break;
+ case AifEnContainerChange: /* Adapter specific container
+ * configuration change */
+ device_printf(sc->aac_dev, "(ContainerChange) "
+ "container %d,%d\n",
+ aif->data.EN.data.ECC.container[0],
+ aif->data.EN.data.ECC.container[1]);
+ break;
+ case AifEnDeviceFailure: /* SCSI device failed */
+ device_printf(sc->aac_dev, "(DeviceFailure) "
+ "handle %d\n",
+ aif->data.EN.data.EDF.deviceHandle);
+ break;
+ case AifEnMirrorFailover: /* Mirror failover started */
+ device_printf(sc->aac_dev, "(MirrorFailover) "
+ "container %d failed, "
+ "migrating from slice %d to %d\n",
+ aif->data.EN.data.EMF.container,
+ aif->data.EN.data.EMF.failedSlice,
+ aif->data.EN.data.EMF.creatingSlice);
+ break;
+ case AifEnContainerEvent: /* Significant container
+ * event */
+ device_printf(sc->aac_dev, "(ContainerEvent) "
+ "container %d event "
+ "%d\n", aif->data.EN.data.ECE.container,
+ aif->data.EN.data.ECE.eventType);
+ break;
+ case AifEnFileSystemChange: /* File system changed */
+ device_printf(sc->aac_dev, "(FileSystemChange)\n");
+ break;
+ case AifEnConfigPause: /* Container pause event */
+ device_printf(sc->aac_dev, "(ConfigPause)\n");
+ break;
+ case AifEnConfigResume: /* Container resume event */
+ device_printf(sc->aac_dev, "(ConfigResume)\n");
+ break;
+ case AifEnFailoverChange: /* Failover space assignment
+ * changed */
+ device_printf(sc->aac_dev, "(FailoverChange)\n");
+ break;
+ case AifEnRAID5RebuildDone: /* RAID5 rebuild finished */
+ device_printf(sc->aac_dev, "(RAID5RebuildDone)\n");
+ break;
+ case AifEnEnclosureManagement: /* Enclosure management event */
+ device_printf(sc->aac_dev, "(EnclosureManagement) "
+ "EMPID %d unit %d "
+ "event %d\n", aif->data.EN.data.EEE.empID,
+ aif->data.EN.data.EEE.unitID,
+ aif->data.EN.data.EEE.eventType);
+ break;
+ case AifEnBatteryEvent: /* Significant NV battery
+ * event */
+ device_printf(sc->aac_dev, "(BatteryEvent) %d "
+ "(state was %d, is %d\n",
+ aif->data.EN.data.EBE.transition_type,
+ aif->data.EN.data.EBE.current_state,
+ aif->data.EN.data.EBE.prior_state);
+ break;
+ case AifEnAddContainer: /* A new container was
+ * created. */
+ device_printf(sc->aac_dev, "(AddContainer)\n");
+ break;
+ case AifEnDeleteContainer: /* A container was deleted. */
+ device_printf(sc->aac_dev, "(DeleteContainer)\n");
+ break;
+ case AifEnBatteryNeedsRecond: /* The battery needs
+ * reconditioning */
+ device_printf(sc->aac_dev, "(BatteryNeedsRecond)\n");
+ break;
+ case AifEnClusterEvent: /* Some cluster event */
+ device_printf(sc->aac_dev, "(ClusterEvent) event %d\n",
+ aif->data.EN.data.ECLE.eventType);
+ break;
+ case AifEnDiskSetEvent: /* A disk set event occured. */
+ device_printf(sc->aac_dev, "(DiskSetEvent) event %d "
+ "diskset %jd creator %jd\n",
+ aif->data.EN.data.EDS.eventType,
+ (intmax_t)aif->data.EN.data.EDS.DsNum,
+ (intmax_t)aif->data.EN.data.EDS.CreatorId);
+ break;
+ case AifDenMorphComplete: /* A morph operation
+ * completed */
+ device_printf(sc->aac_dev, "(MorphComplete)\n");
+ break;
+ case AifDenVolumeExtendComplete: /* A volume expand operation
+ * completed */
+ device_printf(sc->aac_dev, "(VolumeExtendComplete)\n");
+ break;
+ default:
+ device_printf(sc->aac_dev, "(%d)\n", aif->data.EN.type);
+ break;
+ }
+ break;
+ case AifCmdJobProgress:
+ {
+ char *status;
+ switch(aif->data.PR[0].status) {
+ case AifJobStsSuccess:
+ status = "success"; break;
+ case AifJobStsFinished:
+ status = "finished"; break;
+ case AifJobStsAborted:
+ status = "aborted"; break;
+ case AifJobStsFailed:
+ status = "failed"; break;
+ case AifJobStsSuspended:
+ status = "suspended"; break;
+ case AifJobStsRunning:
+ status = "running"; break;
+ default:
+ status = "unknown status"; break;
+ }
+
+ device_printf(sc->aac_dev, "JobProgress (%d) - %s (%d, %d)\n",
+ aif->seqNumber, status,
+ aif->data.PR[0].currentTick,
+ aif->data.PR[0].finalTick);
+ switch(aif->data.PR[0].jd.type) {
+ case AifJobScsiZero: /* SCSI dev clear operation */
+ device_printf(sc->aac_dev, "(ScsiZero) handle %d\n",
+ aif->data.PR[0].jd.client.scsi_dh);
+ break;
+ case AifJobScsiVerify: /* SCSI device Verify operation
+ * NO REPAIR */
+ device_printf(sc->aac_dev, "(ScsiVerify) handle %d\n",
+ aif->data.PR[0].jd.client.scsi_dh);
+ break;
+ case AifJobScsiExercise: /* SCSI device Exercise
+ * operation */
+ device_printf(sc->aac_dev, "(ScsiExercise) handle %d\n",
+ aif->data.PR[0].jd.client.scsi_dh);
+ break;
+ case AifJobScsiVerifyRepair: /* SCSI device Verify operation
+ * WITH repair */
+ device_printf(sc->aac_dev,
+ "(ScsiVerifyRepair) handle %d\n",
+ aif->data.PR[0].jd.client.scsi_dh);
+ break;
+ case AifJobCtrZero: /* Container clear operation */
+ device_printf(sc->aac_dev,
+ "(ContainerZero) container %d\n",
+ aif->data.PR[0].jd.client.container.src);
+ break;
+ case AifJobCtrCopy: /* Container copy operation */
+ device_printf(sc->aac_dev,
+ "(ContainerCopy) container %d to %d\n",
+ aif->data.PR[0].jd.client.container.src,
+ aif->data.PR[0].jd.client.container.dst);
+ break;
+ case AifJobCtrCreateMirror: /* Container Create Mirror
+ * operation */
+ device_printf(sc->aac_dev,
+ "(ContainerCreateMirror) container %d\n",
+ aif->data.PR[0].jd.client.container.src);
+ /* XXX two containers? */
+ break;
+ case AifJobCtrMergeMirror: /* Container Merge Mirror
+ * operation */
+ device_printf(sc->aac_dev,
+ "(ContainerMergeMirror) container %d\n",
+ aif->data.PR[0].jd.client.container.src);
+ /* XXX two containers? */
+ break;
+ case AifJobCtrScrubMirror: /* Container Scrub Mirror
+ * operation */
+ device_printf(sc->aac_dev,
+ "(ContainerScrubMirror) container %d\n",
+ aif->data.PR[0].jd.client.container.src);
+ break;
+ case AifJobCtrRebuildRaid5: /* Container Rebuild Raid5
+ * operation */
+ device_printf(sc->aac_dev,
+ "(ContainerRebuildRaid5) container %d\n",
+ aif->data.PR[0].jd.client.container.src);
+ break;
+ case AifJobCtrScrubRaid5: /* Container Scrub Raid5
+ * operation */
+ device_printf(sc->aac_dev,
+ "(ContainerScrubRaid5) container %d\n",
+ aif->data.PR[0].jd.client.container.src);
+ break;
+ case AifJobCtrMorph: /* Container morph operation */
+ device_printf(sc->aac_dev,
+ "(ContainerMorph) container %d\n",
+ aif->data.PR[0].jd.client.container.src);
+ /* XXX two containers? */
+ break;
+ case AifJobCtrPartCopy: /* Container Partition copy
+ * operation */
+ device_printf(sc->aac_dev,
+ "(ContainerPartCopy) container %d to "
+ "%d\n",
+ aif->data.PR[0].jd.client.container.src,
+ aif->data.PR[0].jd.client.container.dst);
+ break;
+ case AifJobCtrRebuildMirror: /* Container Rebuild Mirror
+ * operation */
+ device_printf(sc->aac_dev,
+ "(ContainerRebuildMirror) container "
+ "%d\n",
+ aif->data.PR[0].jd.client.container.src);
+ break;
+ case AifJobCtrCrazyCache: /* crazy cache */
+ device_printf(sc->aac_dev,
+ "(ContainerCrazyCache) container %d\n",
+ aif->data.PR[0].jd.client.container.src);
+ /* XXX two containers? */
+ break;
+ case AifJobFsCreate: /* File System Create
+ * operation */
+ device_printf(sc->aac_dev, "(FsCreate)\n");
+ break;
+ case AifJobFsVerify: /* File System Verify
+ * operation */
+ device_printf(sc->aac_dev, "(FsVerivy)\n");
+ break;
+ case AifJobFsExtend: /* File System Extend
+ * operation */
+ device_printf(sc->aac_dev, "(FsExtend)\n");
+ break;
+ case AifJobApiFormatNTFS: /* Format a drive to NTFS */
+ device_printf(sc->aac_dev, "(FormatNTFS)\n");
+ break;
+ case AifJobApiFormatFAT: /* Format a drive to FAT */
+ device_printf(sc->aac_dev, "(FormatFAT)\n");
+ break;
+ case AifJobApiUpdateSnapshot: /* update the read/write half
+ * of a snapshot */
+ device_printf(sc->aac_dev, "(UpdateSnapshot)\n");
+ break;
+ case AifJobApiFormatFAT32: /* Format a drive to FAT32 */
+ device_printf(sc->aac_dev, "(FormatFAT32)\n");
+ break;
+ case AifJobCtlContinuousCtrVerify: /* Adapter operation */
+ device_printf(sc->aac_dev, "(ContinuousCtrVerify)\n");
+ break;
+ default:
+ device_printf(sc->aac_dev, "(%d)\n",
+ aif->data.PR[0].jd.type);
+ break;
+ }
+ break;
+ }
+ case AifCmdAPIReport:
+ device_printf(sc->aac_dev, "APIReport (%d)\n", aif->seqNumber);
+ break;
+ case AifCmdDriverNotify:
+ device_printf(sc->aac_dev, "DriverNotify (%d)\n",
+ aif->seqNumber);
+ break;
+ default:
+ device_printf(sc->aac_dev, "AIF %d (%d)\n", aif->command,
+ aif->seqNumber);
+ break;
+ }
+}
+#endif /* AACRAID_DEBUG */
+
+/*
+ * Debug flags to be put into the HBA flags field when initialized
+ */
+const unsigned long aacraid_debug_flags = /* Variable to setup with above flags. */
+/* HBA_FLAGS_DBG_KERNEL_PRINT_B | */
+ HBA_FLAGS_DBG_FW_PRINT_B |
+/* HBA_FLAGS_DBG_FUNCTION_ENTRY_B | */
+ HBA_FLAGS_DBG_FUNCTION_EXIT_B |
+ HBA_FLAGS_DBG_ERROR_B |
+ HBA_FLAGS_DBG_INIT_B |
+/* HBA_FLAGS_DBG_OS_COMMANDS_B | */
+/* HBA_FLAGS_DBG_SCAN_B | */
+/* HBA_FLAGS_DBG_COALESCE_B | */
+/* HBA_FLAGS_DBG_IOCTL_COMMANDS_B | */
+/* HBA_FLAGS_DBG_SYNC_COMMANDS_B | */
+ HBA_FLAGS_DBG_COMM_B |
+/* HBA_FLAGS_DBG_AIF_B | */
+/* HBA_FLAGS_DBG_CSMI_COMMANDS_B | */
+ HBA_FLAGS_DBG_DEBUG_B |
+/* HBA_FLAGS_DBG_FLAGS_MASK | */
+0;
+
+int aacraid_get_fw_debug_buffer(struct aac_softc *sc)
+{
+ u_int32_t MonDriverBufferPhysAddrLow = 0;
+ u_int32_t MonDriverBufferPhysAddrHigh = 0;
+ u_int32_t MonDriverBufferSize = 0;
+ u_int32_t MonDriverHeaderSize = 0;
+
+ /*
+ * Get the firmware print buffer parameters from the firmware
+ * If the command was successful map in the address.
+ */
+ if (!aacraid_sync_command(sc, AAC_MONKER_GETDRVPROP, 0, 0, 0, 0, NULL, NULL)) {
+ MonDriverBufferPhysAddrLow = AAC_GET_MAILBOX(sc, 1);
+ MonDriverBufferPhysAddrHigh = AAC_GET_MAILBOX(sc, 2);
+ MonDriverBufferSize = AAC_GET_MAILBOX(sc, 3);
+ MonDriverHeaderSize = AAC_GET_MAILBOX(sc, 4);
+ if (MonDriverBufferSize) {
+ unsigned long Offset = MonDriverBufferPhysAddrLow
+ - rman_get_start(sc->aac_regs_res1);
+
+ /*
+ * See if the address is already mapped in and if so set it up
+ * from the base address
+ */
+ if ((MonDriverBufferPhysAddrHigh == 0) &&
+ (Offset + MonDriverBufferSize <
+ rman_get_size(sc->aac_regs_res1))) {
+ sc->DebugOffset = Offset;
+ sc->DebugHeaderSize = MonDriverHeaderSize;
+ sc->FwDebugBufferSize = MonDriverBufferSize;
+ sc->FwDebugFlags = 0;
+ sc->DebugFlags = aacraid_debug_flags;
+ return 1;
+ }
+ }
+ }
+
+ /*
+ * The GET_DRIVER_BUFFER_PROPERTIES command failed
+ */
+ return 0;
+}
+
+#define PRINT_TIMEOUT 250000 /* 1/4 second */
+
+void aacraid_fw_printf(struct aac_softc *sc, unsigned long PrintFlags, const char * fmt, ...)
+{
+ va_list args;
+ u_int32_t Count, i;
+ char PrintBuffer_P[PRINT_BUFFER_SIZE];
+ unsigned long PrintType;
+
+ PrintType = PrintFlags &
+ ~(HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B);
+ if (((PrintType!=0) && (sc!=NULL) && ((sc->DebugFlags & PrintType)==0))
+ || ((sc!=NULL) && (sc->DebugFlags
+ & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B)) == 0))
+ return;
+
+ /*
+ * Set up parameters and call sprintf function to format the data
+ */
+ va_start(args, fmt);
+ vsprintf(PrintBuffer_P, fmt, args);
+ va_end(args);
+
+ /*
+ * Make sure the HBA structure has been passed in for this section
+ */
+ if ((sc != NULL) && (sc->FwDebugBufferSize)) {
+ /*
+ * If we are set up for a Firmware print
+ */
+ if ((sc->DebugFlags & HBA_FLAGS_DBG_FW_PRINT_B)
+ && ((PrintFlags
+ & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B))
+ != HBA_FLAGS_DBG_KERNEL_PRINT_B)) {
+ /*
+ * Make sure the string size is within boundaries
+ */
+ Count = strlen(PrintBuffer_P);
+ if (Count > sc->FwDebugBufferSize)
+ Count = (u_int16_t)sc->FwDebugBufferSize;
+
+ /*
+ * Wait for no more than PRINT_TIMEOUT for the previous
+ * message length to clear (the handshake).
+ */
+ for (i = 0; i < PRINT_TIMEOUT; ++i) {
+ if (!AAC_MEM1_GETREG4(sc,
+ sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET)) {
+ break;
+ }
+ DELAY(1);
+ }
+
+ /*
+ * If the Length is clear, copy over the message, the
+ * flags, and the length. Make sure the length is the
+ * last because that is the signal for the Firmware to
+ * pick it up.
+ */
+ if (!AAC_MEM1_GETREG4(sc,
+ sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET)) {
+ for (i = 0; i < Count; ++i) {
+ AAC_MEM1_SETREG1(sc, sc->DebugOffset + sc->DebugHeaderSize + i,
+ PrintBuffer_P[i]);
+ }
+ AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_FLAGS_OFFSET,
+ sc->FwDebugFlags);
+ AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET,
+ Count);
+ } else
+ sc->DebugFlags &= ~HBA_FLAGS_DBG_FW_PRINT_B;
+ }
+
+ /*
+ * If the Kernel Debug Print flag is set, send it off to the
+ * Kernel debugger
+ */
+ if ((sc->DebugFlags & HBA_FLAGS_DBG_KERNEL_PRINT_B)
+ && ((PrintFlags
+ & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B))
+ != HBA_FLAGS_DBG_FW_PRINT_B)) {
+ if (sc->FwDebugFlags & FW_DEBUG_FLAGS_NO_HEADERS_B)
+ printf ("%s\n", PrintBuffer_P);
+ else
+ device_printf (sc->aac_dev, "%s\n", PrintBuffer_P);
+ }
+
+ } else {
+ /*
+ * No HBA structure passed in so it has to be for the Kernel Debugger
+ */
+ if ((sc != NULL) && (sc->FwDebugFlags & FW_DEBUG_FLAGS_NO_HEADERS_B))
+ printf ("%s\n", PrintBuffer_P);
+ else if (sc != NULL)
+ device_printf (sc->aac_dev, "%s\n", PrintBuffer_P);
+ else
+ printf("%s\n", PrintBuffer_P);
+ }
+}
+
+void aacraid_fw_print_mem(struct aac_softc *sc, unsigned long PrintFlags, u_int8_t *Addr, int Count)
+{
+ int Offset, i;
+ u_int32_t DebugFlags = 0;
+ char Buffer[100];
+ char *LineBuffer_P;
+
+ /*
+ * If we have an HBA structure, save off the flags and set the no
+ * headers flag so we don't have garbage between our lines of data
+ */
+ if (sc != NULL) {
+ DebugFlags = sc->FwDebugFlags;
+ sc->FwDebugFlags |= FW_DEBUG_FLAGS_NO_HEADERS_B;
+ }
+
+ Offset = 0;
+
+ /*
+ * Loop through all the data
+ */
+ while (Offset < Count) {
+ /*
+ * We will format each line into a buffer and then print out
+ * the entire line so set the pointer to the beginning of the
+ * buffer
+ */
+ LineBuffer_P = Buffer;
+
+ /*
+ * Set up the address in HEX
+ */
+ sprintf(LineBuffer_P, "\n%04x ", Offset);
+ LineBuffer_P += 6;
+
+ /*
+ * Set up 16 bytes in HEX format
+ */
+ for (i = 0; i < 16; ++i) {
+ /*
+ * If we are past the count of data bytes to output,
+ * pad with blanks
+ */
+ if ((Offset + i) >= Count)
+ sprintf (LineBuffer_P, " ");
+ else
+ sprintf (LineBuffer_P, "%02x ", Addr[Offset+i]);
+ LineBuffer_P += 3;
+
+ /*
+ * At the mid point we will put in a divider
+ */
+ if (i == 7) {
+ sprintf (LineBuffer_P, "- ");
+ LineBuffer_P += 2;
+ }
+ }
+ /*
+ * Now do the same 16 bytes at the end of the line in ASCII
+ * format
+ */
+ sprintf (LineBuffer_P, " ");
+ LineBuffer_P += 2;
+ for (i = 0; i < 16; ++i) {
+ /*
+ * If all data processed, OUT-O-HERE
+ */
+ if ((Offset + i) >= Count)
+ break;
+
+ /*
+ * If this is a printable ASCII character, convert it
+ */
+ if ((Addr[Offset+i] > 0x1F) && (Addr[Offset+i] < 0x7F))
+ sprintf (LineBuffer_P, "%c", Addr[Offset+i]);
+ else
+ sprintf (LineBuffer_P, ".");
+ ++LineBuffer_P;
+ }
+ /*
+ * The line is now formatted, so print it out
+ */
+ aacraid_fw_printf(sc, PrintFlags, "%s", Buffer);
+
+ /*
+ * Bump the offset by 16 for the next line
+ */
+ Offset += 16;
+
+ }
+
+ /*
+ * Restore the saved off flags
+ */
+ if (sc != NULL)
+ sc->FwDebugFlags = DebugFlags;
+}
+