diff options
Diffstat (limited to 'sys/dev/aac/aac_debug.c')
-rw-r--r-- | sys/dev/aac/aac_debug.c | 426 |
1 files changed, 426 insertions, 0 deletions
diff --git a/sys/dev/aac/aac_debug.c b/sys/dev/aac/aac_debug.c new file mode 100644 index 0000000..09293ad --- /dev/null +++ b/sys/dev/aac/aac_debug.c @@ -0,0 +1,426 @@ +/*- + * Copyright (c) 2000 Michael Smith + * Copyright (c) 2000 BSDi + * 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. + * + * $FreeBSD$ + */ + +/* + * Debugging support. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> + +#include <dev/aac/aac_compat.h> +#include <sys/bus.h> +#include <sys/devicestat.h> +#include <sys/disk.h> + +#include <machine/resource.h> +#include <machine/bus.h> + +#include <dev/aac/aacreg.h> +#include <dev/aac/aacvar.h> + +void aac_printstate0(void); +void aac_intr0(void); + +/******************************************************************************** + * Dump the command queue indices + */ +void +aac_print_queues(struct aac_softc *sc) +{ + device_printf(sc->aac_dev, "FIB queue header at %p queues at %p\n", + &sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][0], + &sc->aac_queues->qt_HostNormCmdQueue[0]); + device_printf(sc->aac_dev, "HOST_NORM_CMD %d/%d (%d)\n", + sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX], + sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX], + AAC_HOST_NORM_CMD_ENTRIES); + device_printf(sc->aac_dev, "HOST_HIGH_CMD %d/%d (%d)\n", + sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX], + sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX], + AAC_HOST_HIGH_CMD_ENTRIES); + device_printf(sc->aac_dev, "ADAP_NORM_CMD %d/%d (%d)\n", + sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX], + sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX], + AAC_ADAP_NORM_CMD_ENTRIES); + device_printf(sc->aac_dev, "ADAP_HIGH_CMD %d/%d (%d)\n", + sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX], + sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX], + AAC_ADAP_HIGH_CMD_ENTRIES); + device_printf(sc->aac_dev, "HOST_NORM_RESP %d/%d (%d)\n", + sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX], + sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX], + AAC_HOST_NORM_RESP_ENTRIES); + device_printf(sc->aac_dev, "HOST_HIGH_RESP %d/%d (%d)\n", + sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX], + sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX], + AAC_HOST_HIGH_RESP_ENTRIES); + device_printf(sc->aac_dev, "ADAP_NORM_RESP %d/%d (%d)\n", + sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX], + sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX], + AAC_ADAP_NORM_RESP_ENTRIES); + device_printf(sc->aac_dev, "ADAP_HIGH_RESP %d/%d (%d)\n", + sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX], + sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX], + AAC_ADAP_HIGH_RESP_ENTRIES); + +} + +/******************************************************************************** + * Print the command queue states for controller 0 (callable from DDB) + */ +void +aac_printstate0(void) +{ + struct aac_softc *sc = devclass_get_softc(aac_devclass, 0); + + aac_print_queues(sc); + switch (sc->aac_hwif) { + case AAC_HWIF_I960RX: + device_printf(sc->aac_dev, "IDBR 0x%08x IIMR 0x%08x IISR 0x%08x\n", + AAC_GETREG4(sc, AAC_RX_IDBR), AAC_GETREG4(sc, AAC_RX_IIMR), AAC_GETREG4(sc, AAC_RX_IISR)); + device_printf(sc->aac_dev, "ODBR 0x%08x OIMR 0x%08x OISR 0x%08x\n", + AAC_GETREG4(sc, AAC_RX_ODBR), AAC_GETREG4(sc, AAC_RX_OIMR), AAC_GETREG4(sc, AAC_RX_OISR)); + AAC_SETREG4(sc, AAC_RX_OIMR, 0/*~(AAC_DB_COMMAND_READY | AAC_DB_RESPONSE_READY | AAC_DB_PRINTF)*/); + device_printf(sc->aac_dev, "ODBR 0x%08x OIMR 0x%08x OISR 0x%08x\n", + AAC_GETREG4(sc, AAC_RX_ODBR), AAC_GETREG4(sc, AAC_RX_OIMR), AAC_GETREG4(sc, AAC_RX_OISR)); + break; + case AAC_HWIF_STRONGARM: + /* XXX implement */ + } +} + +/******************************************************************************** + * simulate an interrupt for controller 0 + */ +void +aac_intr0(void) +{ + struct aac_softc *sc = devclass_get_softc(aac_devclass, 0); + + aac_intr(sc); +} + +/******************************************************************************** + * Panic in a slightly informative fashion + */ +void +aac_panic(struct aac_softc *sc, char *reason) +{ + aac_print_queues(sc); + panic(reason); +} + +/******************************************************************************** + * Print a FIB + */ +void +aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller) +{ + 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, " Flags 0x%x\n", fib->Header.Flags); + 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, " ReceiverAddress 0x%x\n", fib->Header.ReceiverFibAddress); + device_printf(sc->aac_dev, " SenderData 0x%x\n", fib->Header.SenderData); + switch(fib->Header.Command) { + case ContainerCommand: + { + struct aac_blockread *br = (struct aac_blockread *)fib->data; + struct aac_blockwrite *bw = (struct aac_blockwrite *)fib->data; + struct aac_sg_table *sg = NULL; + int i; + 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 +aac_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); /* XXX interpret */ + 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); /* XXX interpret? */ + 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, /* XXX interpret */ + 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 %lld creator %lld\n", + aif->data.EN.data.EDS.eventType, + aif->data.EN.data.EDS.DsNum, + 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 device 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, "(ConatainerZero) container %d\n", + aif->data.PR[0].jd.client.container.src); + break; + case AifJobCtrCopy: /* Container copy operation */ + device_printf(sc->aac_dev, "(ConatainerCopy) 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, "(ConatainerCreateMirror) 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, "(ConatainerMergeMirror) 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, "(ConatainerScrubMirror) container %d\n", + aif->data.PR[0].jd.client.container.src); + break; + case AifJobCtrRebuildRaid5: /* Container Rebuild Raid5 operation */ + device_printf(sc->aac_dev, "(ConatainerRebuildRaid5) container %d\n", + aif->data.PR[0].jd.client.container.src); + break; + case AifJobCtrScrubRaid5: /* Container Scrub Raid5 operation */ + device_printf(sc->aac_dev, "(ConatainerScrubRaid5) container %d\n", + aif->data.PR[0].jd.client.container.src); + break; + case AifJobCtrMorph: /* Container morph operation */ + device_printf(sc->aac_dev, "(ConatainerMorph) 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, "(ConatainerPartCopy) 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, "(ConatainerRebuildMirror) container %d\n", + aif->data.PR[0].jd.client.container.src); + break; + case AifJobCtrCrazyCache: /* crazy cache */ + device_printf(sc->aac_dev, "(ConatainerCrazyCache) 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; + } +} |