2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2006-2010 Adaptec, Inc.
5 * Copyright (c) 2010-2012 PMC-Sierra, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
37 #include "opt_aacraid.h"
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
46 #include <machine/resource.h>
47 #include <machine/bus.h>
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>
60 #include <machine/resource.h>
61 #include <machine/bus.h>
62 #include <machine/stdarg.h>
64 #include <dev/aacraid/aacraid_debug.h>
68 * Dump the command queue indices
71 aacraid_print_queues(struct aac_softc *sc)
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);
86 aacraid_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller)
89 device_printf(sc->aac_dev,
90 "aac_print_fib called with NULL fib\n");
93 device_printf(sc->aac_dev, "%s: FIB @ %p\n", caller, fib);
94 device_printf(sc->aac_dev, " XferState %b\n", fib->Header.XferState,
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",
129 switch(fib->Header.Command) {
130 case ContainerCommand:
132 struct aac_blockread *br;
133 struct aac_blockwrite *bw;
134 struct aac_sg_table *sg;
137 br = (struct aac_blockread*)fib->data;
138 bw = (struct aac_blockwrite*)fib->data;
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,
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" :
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);
168 device_printf(sc->aac_dev, " %16D\n", fib->data, " ");
169 device_printf(sc->aac_dev, " %16D\n", fib->data + 16, " ");
175 * Describe an AIF we have received.
178 aacraid_print_aif(struct aac_softc *sc, struct aac_aif_command *aif)
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);
189 case AifEnTaskComplete: /* Task has completed */
190 device_printf(sc->aac_dev, "(TaskComplete)\n");
192 case AifEnConfigChange: /* Adapter configuration change
194 device_printf(sc->aac_dev, "(ConfigChange)\n");
196 case AifEnContainerChange: /* Adapter specific container
197 * configuration change */
198 device_printf(sc->aac_dev, "(ContainerChange) "
200 aif->data.EN.data.ECC.container[0],
201 aif->data.EN.data.ECC.container[1]);
203 case AifEnDeviceFailure: /* SCSI device failed */
204 device_printf(sc->aac_dev, "(DeviceFailure) "
206 aif->data.EN.data.EDF.deviceHandle);
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);
216 case AifEnContainerEvent: /* Significant container
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);
223 case AifEnFileSystemChange: /* File system changed */
224 device_printf(sc->aac_dev, "(FileSystemChange)\n");
226 case AifEnConfigPause: /* Container pause event */
227 device_printf(sc->aac_dev, "(ConfigPause)\n");
229 case AifEnConfigResume: /* Container resume event */
230 device_printf(sc->aac_dev, "(ConfigResume)\n");
232 case AifEnFailoverChange: /* Failover space assignment
234 device_printf(sc->aac_dev, "(FailoverChange)\n");
236 case AifEnRAID5RebuildDone: /* RAID5 rebuild finished */
237 device_printf(sc->aac_dev, "(RAID5RebuildDone)\n");
239 case AifEnEnclosureManagement: /* Enclosure management event */
240 device_printf(sc->aac_dev, "(EnclosureManagement) "
242 "event %d\n", aif->data.EN.data.EEE.empID,
243 aif->data.EN.data.EEE.unitID,
244 aif->data.EN.data.EEE.eventType);
246 case AifEnBatteryEvent: /* Significant NV battery
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);
254 case AifEnAddContainer: /* A new container was
256 device_printf(sc->aac_dev, "(AddContainer)\n");
258 case AifEnDeleteContainer: /* A container was deleted. */
259 device_printf(sc->aac_dev, "(DeleteContainer)\n");
261 case AifEnBatteryNeedsRecond: /* The battery needs
263 device_printf(sc->aac_dev, "(BatteryNeedsRecond)\n");
265 case AifEnClusterEvent: /* Some cluster event */
266 device_printf(sc->aac_dev, "(ClusterEvent) event %d\n",
267 aif->data.EN.data.ECLE.eventType);
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);
276 case AifDenMorphComplete: /* A morph operation
278 device_printf(sc->aac_dev, "(MorphComplete)\n");
280 case AifDenVolumeExtendComplete: /* A volume expand operation
282 device_printf(sc->aac_dev, "(VolumeExtendComplete)\n");
285 device_printf(sc->aac_dev, "(%d)\n", aif->data.EN.type);
289 case AifCmdJobProgress:
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;
306 status = "unknown status"; break;
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);
318 case AifJobScsiVerify: /* SCSI device Verify operation
320 device_printf(sc->aac_dev, "(ScsiVerify) handle %d\n",
321 aif->data.PR[0].jd.client.scsi_dh);
323 case AifJobScsiExercise: /* SCSI device Exercise
325 device_printf(sc->aac_dev, "(ScsiExercise) handle %d\n",
326 aif->data.PR[0].jd.client.scsi_dh);
328 case AifJobScsiVerifyRepair: /* SCSI device Verify operation
330 device_printf(sc->aac_dev,
331 "(ScsiVerifyRepair) handle %d\n",
332 aif->data.PR[0].jd.client.scsi_dh);
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);
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);
345 case AifJobCtrCreateMirror: /* Container Create Mirror
347 device_printf(sc->aac_dev,
348 "(ContainerCreateMirror) container %d\n",
349 aif->data.PR[0].jd.client.container.src);
350 /* XXX two containers? */
352 case AifJobCtrMergeMirror: /* Container Merge Mirror
354 device_printf(sc->aac_dev,
355 "(ContainerMergeMirror) container %d\n",
356 aif->data.PR[0].jd.client.container.src);
357 /* XXX two containers? */
359 case AifJobCtrScrubMirror: /* Container Scrub Mirror
361 device_printf(sc->aac_dev,
362 "(ContainerScrubMirror) container %d\n",
363 aif->data.PR[0].jd.client.container.src);
365 case AifJobCtrRebuildRaid5: /* Container Rebuild Raid5
367 device_printf(sc->aac_dev,
368 "(ContainerRebuildRaid5) container %d\n",
369 aif->data.PR[0].jd.client.container.src);
371 case AifJobCtrScrubRaid5: /* Container Scrub Raid5
373 device_printf(sc->aac_dev,
374 "(ContainerScrubRaid5) container %d\n",
375 aif->data.PR[0].jd.client.container.src);
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? */
383 case AifJobCtrPartCopy: /* Container Partition copy
385 device_printf(sc->aac_dev,
386 "(ContainerPartCopy) container %d to "
388 aif->data.PR[0].jd.client.container.src,
389 aif->data.PR[0].jd.client.container.dst);
391 case AifJobCtrRebuildMirror: /* Container Rebuild Mirror
393 device_printf(sc->aac_dev,
394 "(ContainerRebuildMirror) container "
396 aif->data.PR[0].jd.client.container.src);
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? */
404 case AifJobFsCreate: /* File System Create
406 device_printf(sc->aac_dev, "(FsCreate)\n");
408 case AifJobFsVerify: /* File System Verify
410 device_printf(sc->aac_dev, "(FsVerivy)\n");
412 case AifJobFsExtend: /* File System Extend
414 device_printf(sc->aac_dev, "(FsExtend)\n");
416 case AifJobApiFormatNTFS: /* Format a drive to NTFS */
417 device_printf(sc->aac_dev, "(FormatNTFS)\n");
419 case AifJobApiFormatFAT: /* Format a drive to FAT */
420 device_printf(sc->aac_dev, "(FormatFAT)\n");
422 case AifJobApiUpdateSnapshot: /* update the read/write half
424 device_printf(sc->aac_dev, "(UpdateSnapshot)\n");
426 case AifJobApiFormatFAT32: /* Format a drive to FAT32 */
427 device_printf(sc->aac_dev, "(FormatFAT32)\n");
429 case AifJobCtlContinuousCtrVerify: /* Adapter operation */
430 device_printf(sc->aac_dev, "(ContinuousCtrVerify)\n");
433 device_printf(sc->aac_dev, "(%d)\n",
434 aif->data.PR[0].jd.type);
439 case AifCmdAPIReport:
440 device_printf(sc->aac_dev, "APIReport (%d)\n", aif->seqNumber);
442 case AifCmdDriverNotify:
443 device_printf(sc->aac_dev, "DriverNotify (%d)\n",
447 device_printf(sc->aac_dev, "AIF %d (%d)\n", aif->command,
452 #endif /* AACRAID_DEBUG */
455 * Debug flags to be put into the HBA flags field when initialized
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 | */
476 int aacraid_get_fw_debug_buffer(struct aac_softc *sc)
478 u_int32_t MonDriverBufferPhysAddrLow = 0;
479 u_int32_t MonDriverBufferPhysAddrHigh = 0;
480 u_int32_t MonDriverBufferSize = 0;
481 u_int32_t MonDriverHeaderSize = 0;
484 * Get the firmware print buffer parameters from the firmware
485 * If the command was successful map in the address.
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);
497 * See if the address is already mapped in and if so set it up
498 * from the base address
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;
514 * The GET_DRIVER_BUFFER_PROPERTIES command failed
519 #define PRINT_TIMEOUT 250000 /* 1/4 second */
521 void aacraid_fw_printf(struct aac_softc *sc, unsigned long PrintFlags, const char * fmt, ...)
525 char PrintBuffer_P[PRINT_BUFFER_SIZE];
526 unsigned long PrintType;
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))
536 * Set up parameters and call sprintf function to format the data
539 vsprintf(PrintBuffer_P, fmt, args);
543 * Make sure the HBA structure has been passed in for this section
545 if ((sc != NULL) && (sc->FwDebugBufferSize)) {
547 * If we are set up for a Firmware print
549 if ((sc->DebugFlags & HBA_FLAGS_DBG_FW_PRINT_B)
551 & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B))
552 != HBA_FLAGS_DBG_KERNEL_PRINT_B)) {
554 * Make sure the string size is within boundaries
556 Count = strlen(PrintBuffer_P);
557 if (Count > sc->FwDebugBufferSize)
558 Count = (u_int16_t)sc->FwDebugBufferSize;
561 * Wait for no more than PRINT_TIMEOUT for the previous
562 * message length to clear (the handshake).
564 for (i = 0; i < PRINT_TIMEOUT; ++i) {
565 if (!AAC_MEM1_GETREG4(sc,
566 sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET)) {
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
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,
584 AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_FLAGS_OFFSET,
586 AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET,
589 sc->DebugFlags &= ~HBA_FLAGS_DBG_FW_PRINT_B;
593 * If the Kernel Debug Print flag is set, send it off to the
596 if ((sc->DebugFlags & HBA_FLAGS_DBG_KERNEL_PRINT_B)
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);
603 device_printf (sc->aac_dev, "%s\n", PrintBuffer_P);
608 * No HBA structure passed in so it has to be for the Kernel Debugger
610 if ((sc != NULL) && (sc->FwDebugFlags & FW_DEBUG_FLAGS_NO_HEADERS_B))
611 printf ("%s\n", PrintBuffer_P);
613 device_printf (sc->aac_dev, "%s\n", PrintBuffer_P);
615 printf("%s\n", PrintBuffer_P);
619 void aacraid_fw_print_mem(struct aac_softc *sc, unsigned long PrintFlags, u_int8_t *Addr, int Count)
622 u_int32_t DebugFlags = 0;
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
631 DebugFlags = sc->FwDebugFlags;
632 sc->FwDebugFlags |= FW_DEBUG_FLAGS_NO_HEADERS_B;
638 * Loop through all the data
640 while (Offset < Count) {
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
646 LineBuffer_P = Buffer;
649 * Set up the address in HEX
651 sprintf(LineBuffer_P, "\n%04x ", Offset);
655 * Set up 16 bytes in HEX format
657 for (i = 0; i < 16; ++i) {
659 * If we are past the count of data bytes to output,
662 if ((Offset + i) >= Count)
663 sprintf (LineBuffer_P, " ");
665 sprintf (LineBuffer_P, "%02x ", Addr[Offset+i]);
669 * At the mid point we will put in a divider
672 sprintf (LineBuffer_P, "- ");
677 * Now do the same 16 bytes at the end of the line in ASCII
680 sprintf (LineBuffer_P, " ");
682 for (i = 0; i < 16; ++i) {
684 * If all data processed, OUT-O-HERE
686 if ((Offset + i) >= Count)
690 * If this is a printable ASCII character, convert it
692 if ((Addr[Offset+i] > 0x1F) && (Addr[Offset+i] < 0x7F))
693 sprintf (LineBuffer_P, "%c", Addr[Offset+i]);
695 sprintf (LineBuffer_P, ".");
699 * The line is now formatted, so print it out
701 aacraid_fw_printf(sc, PrintFlags, "%s", Buffer);
704 * Bump the offset by 16 for the next line
710 * Restore the saved off flags
713 sc->FwDebugFlags = DebugFlags;