3 * Copyright (c) 2006-2010 Adaptec, Inc.
4 * Copyright (c) 2010-2012 PMC-Sierra, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
36 #include "opt_aacraid.h"
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
45 #include <machine/resource.h>
46 #include <machine/bus.h>
48 #include <dev/aacraid/aacraid_reg.h>
49 #include <sys/aac_ioctl.h>
50 #include <dev/aacraid/aacraid_var.h>
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/kernel.h>
59 #include <machine/resource.h>
60 #include <machine/bus.h>
61 #include <machine/stdarg.h>
63 #include <dev/aacraid/aacraid_debug.h>
67 * Dump the command queue indices
70 aacraid_print_queues(struct aac_softc *sc)
72 device_printf(sc->aac_dev, "AACQ_FREE %d/%d\n",
73 sc->aac_qstat[AACQ_FREE].q_length, sc->aac_qstat[AACQ_FREE].q_max);
74 device_printf(sc->aac_dev, "AACQ_READY %d/%d\n",
75 sc->aac_qstat[AACQ_READY].q_length,
76 sc->aac_qstat[AACQ_READY].q_max);
77 device_printf(sc->aac_dev, "AACQ_BUSY %d/%d\n",
78 sc->aac_qstat[AACQ_BUSY].q_length, sc->aac_qstat[AACQ_BUSY].q_max);
85 aacraid_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller)
88 device_printf(sc->aac_dev,
89 "aac_print_fib called with NULL fib\n");
92 device_printf(sc->aac_dev, "%s: FIB @ %p\n", caller, fib);
93 device_printf(sc->aac_dev, " XferState %b\n", fib->Header.XferState,
116 device_printf(sc->aac_dev, " Command %d\n", fib->Header.Command);
117 device_printf(sc->aac_dev, " StructType %d\n",
118 fib->Header.StructType);
119 device_printf(sc->aac_dev, " Size %d\n", fib->Header.Size);
120 device_printf(sc->aac_dev, " SenderSize %d\n",
121 fib->Header.SenderSize);
122 device_printf(sc->aac_dev, " SenderAddress 0x%x\n",
123 fib->Header.SenderFibAddress);
124 device_printf(sc->aac_dev, " RcvrAddress 0x%x\n",
125 fib->Header.u.ReceiverFibAddress);
126 device_printf(sc->aac_dev, " Handle 0x%x\n",
128 switch(fib->Header.Command) {
129 case ContainerCommand:
131 struct aac_blockread *br;
132 struct aac_blockwrite *bw;
133 struct aac_sg_table *sg;
136 br = (struct aac_blockread*)fib->data;
137 bw = (struct aac_blockwrite*)fib->data;
140 if (br->Command == VM_CtBlockRead) {
141 device_printf(sc->aac_dev,
142 " BlockRead: container %d 0x%x/%d\n",
143 br->ContainerId, br->BlockNumber,
147 if (bw->Command == VM_CtBlockWrite) {
148 device_printf(sc->aac_dev,
149 " BlockWrite: container %d 0x%x/%d "
150 "(%s)\n", bw->ContainerId,
151 bw->BlockNumber, bw->ByteCount,
152 bw->Stable == CSTABLE ? "stable" :
157 device_printf(sc->aac_dev,
158 " %d s/g entries\n", sg->SgCount);
159 for (i = 0; i < sg->SgCount; i++)
160 device_printf(sc->aac_dev, " 0x%08x/%d\n",
161 sg->SgEntry[i].SgAddress,
162 sg->SgEntry[i].SgByteCount);
167 device_printf(sc->aac_dev, " %16D\n", fib->data, " ");
168 device_printf(sc->aac_dev, " %16D\n", fib->data + 16, " ");
174 * Describe an AIF we have received.
177 aacraid_print_aif(struct aac_softc *sc, struct aac_aif_command *aif)
179 switch(aif->command) {
180 case AifCmdEventNotify:
181 device_printf(sc->aac_dev, "EventNotify(%d)\n", aif->seqNumber);
182 switch(aif->data.EN.type) {
183 case AifEnGeneric: /* Generic notification */
184 device_printf(sc->aac_dev, "(Generic) %.*s\n",
185 (int)sizeof(aif->data.EN.data.EG),
186 aif->data.EN.data.EG.text);
188 case AifEnTaskComplete: /* Task has completed */
189 device_printf(sc->aac_dev, "(TaskComplete)\n");
191 case AifEnConfigChange: /* Adapter configuration change
193 device_printf(sc->aac_dev, "(ConfigChange)\n");
195 case AifEnContainerChange: /* Adapter specific container
196 * configuration change */
197 device_printf(sc->aac_dev, "(ContainerChange) "
199 aif->data.EN.data.ECC.container[0],
200 aif->data.EN.data.ECC.container[1]);
202 case AifEnDeviceFailure: /* SCSI device failed */
203 device_printf(sc->aac_dev, "(DeviceFailure) "
205 aif->data.EN.data.EDF.deviceHandle);
207 case AifEnMirrorFailover: /* Mirror failover started */
208 device_printf(sc->aac_dev, "(MirrorFailover) "
209 "container %d failed, "
210 "migrating from slice %d to %d\n",
211 aif->data.EN.data.EMF.container,
212 aif->data.EN.data.EMF.failedSlice,
213 aif->data.EN.data.EMF.creatingSlice);
215 case AifEnContainerEvent: /* Significant container
217 device_printf(sc->aac_dev, "(ContainerEvent) "
218 "container %d event "
219 "%d\n", aif->data.EN.data.ECE.container,
220 aif->data.EN.data.ECE.eventType);
222 case AifEnFileSystemChange: /* File system changed */
223 device_printf(sc->aac_dev, "(FileSystemChange)\n");
225 case AifEnConfigPause: /* Container pause event */
226 device_printf(sc->aac_dev, "(ConfigPause)\n");
228 case AifEnConfigResume: /* Container resume event */
229 device_printf(sc->aac_dev, "(ConfigResume)\n");
231 case AifEnFailoverChange: /* Failover space assignment
233 device_printf(sc->aac_dev, "(FailoverChange)\n");
235 case AifEnRAID5RebuildDone: /* RAID5 rebuild finished */
236 device_printf(sc->aac_dev, "(RAID5RebuildDone)\n");
238 case AifEnEnclosureManagement: /* Enclosure management event */
239 device_printf(sc->aac_dev, "(EnclosureManagement) "
241 "event %d\n", aif->data.EN.data.EEE.empID,
242 aif->data.EN.data.EEE.unitID,
243 aif->data.EN.data.EEE.eventType);
245 case AifEnBatteryEvent: /* Significant NV battery
247 device_printf(sc->aac_dev, "(BatteryEvent) %d "
248 "(state was %d, is %d\n",
249 aif->data.EN.data.EBE.transition_type,
250 aif->data.EN.data.EBE.current_state,
251 aif->data.EN.data.EBE.prior_state);
253 case AifEnAddContainer: /* A new container was
255 device_printf(sc->aac_dev, "(AddContainer)\n");
257 case AifEnDeleteContainer: /* A container was deleted. */
258 device_printf(sc->aac_dev, "(DeleteContainer)\n");
260 case AifEnBatteryNeedsRecond: /* The battery needs
262 device_printf(sc->aac_dev, "(BatteryNeedsRecond)\n");
264 case AifEnClusterEvent: /* Some cluster event */
265 device_printf(sc->aac_dev, "(ClusterEvent) event %d\n",
266 aif->data.EN.data.ECLE.eventType);
268 case AifEnDiskSetEvent: /* A disk set event occurred. */
269 device_printf(sc->aac_dev, "(DiskSetEvent) event %d "
270 "diskset %jd creator %jd\n",
271 aif->data.EN.data.EDS.eventType,
272 (intmax_t)aif->data.EN.data.EDS.DsNum,
273 (intmax_t)aif->data.EN.data.EDS.CreatorId);
275 case AifDenMorphComplete: /* A morph operation
277 device_printf(sc->aac_dev, "(MorphComplete)\n");
279 case AifDenVolumeExtendComplete: /* A volume expand operation
281 device_printf(sc->aac_dev, "(VolumeExtendComplete)\n");
284 device_printf(sc->aac_dev, "(%d)\n", aif->data.EN.type);
288 case AifCmdJobProgress:
291 switch(aif->data.PR[0].status) {
292 case AifJobStsSuccess:
293 status = "success"; break;
294 case AifJobStsFinished:
295 status = "finished"; break;
296 case AifJobStsAborted:
297 status = "aborted"; break;
298 case AifJobStsFailed:
299 status = "failed"; break;
300 case AifJobStsSuspended:
301 status = "suspended"; break;
302 case AifJobStsRunning:
303 status = "running"; break;
305 status = "unknown status"; break;
308 device_printf(sc->aac_dev, "JobProgress (%d) - %s (%d, %d)\n",
309 aif->seqNumber, status,
310 aif->data.PR[0].currentTick,
311 aif->data.PR[0].finalTick);
312 switch(aif->data.PR[0].jd.type) {
313 case AifJobScsiZero: /* SCSI dev clear operation */
314 device_printf(sc->aac_dev, "(ScsiZero) handle %d\n",
315 aif->data.PR[0].jd.client.scsi_dh);
317 case AifJobScsiVerify: /* SCSI device Verify operation
319 device_printf(sc->aac_dev, "(ScsiVerify) handle %d\n",
320 aif->data.PR[0].jd.client.scsi_dh);
322 case AifJobScsiExercise: /* SCSI device Exercise
324 device_printf(sc->aac_dev, "(ScsiExercise) handle %d\n",
325 aif->data.PR[0].jd.client.scsi_dh);
327 case AifJobScsiVerifyRepair: /* SCSI device Verify operation
329 device_printf(sc->aac_dev,
330 "(ScsiVerifyRepair) handle %d\n",
331 aif->data.PR[0].jd.client.scsi_dh);
333 case AifJobCtrZero: /* Container clear operation */
334 device_printf(sc->aac_dev,
335 "(ContainerZero) container %d\n",
336 aif->data.PR[0].jd.client.container.src);
338 case AifJobCtrCopy: /* Container copy operation */
339 device_printf(sc->aac_dev,
340 "(ContainerCopy) container %d to %d\n",
341 aif->data.PR[0].jd.client.container.src,
342 aif->data.PR[0].jd.client.container.dst);
344 case AifJobCtrCreateMirror: /* Container Create Mirror
346 device_printf(sc->aac_dev,
347 "(ContainerCreateMirror) container %d\n",
348 aif->data.PR[0].jd.client.container.src);
349 /* XXX two containers? */
351 case AifJobCtrMergeMirror: /* Container Merge Mirror
353 device_printf(sc->aac_dev,
354 "(ContainerMergeMirror) container %d\n",
355 aif->data.PR[0].jd.client.container.src);
356 /* XXX two containers? */
358 case AifJobCtrScrubMirror: /* Container Scrub Mirror
360 device_printf(sc->aac_dev,
361 "(ContainerScrubMirror) container %d\n",
362 aif->data.PR[0].jd.client.container.src);
364 case AifJobCtrRebuildRaid5: /* Container Rebuild Raid5
366 device_printf(sc->aac_dev,
367 "(ContainerRebuildRaid5) container %d\n",
368 aif->data.PR[0].jd.client.container.src);
370 case AifJobCtrScrubRaid5: /* Container Scrub Raid5
372 device_printf(sc->aac_dev,
373 "(ContainerScrubRaid5) container %d\n",
374 aif->data.PR[0].jd.client.container.src);
376 case AifJobCtrMorph: /* Container morph operation */
377 device_printf(sc->aac_dev,
378 "(ContainerMorph) container %d\n",
379 aif->data.PR[0].jd.client.container.src);
380 /* XXX two containers? */
382 case AifJobCtrPartCopy: /* Container Partition copy
384 device_printf(sc->aac_dev,
385 "(ContainerPartCopy) container %d to "
387 aif->data.PR[0].jd.client.container.src,
388 aif->data.PR[0].jd.client.container.dst);
390 case AifJobCtrRebuildMirror: /* Container Rebuild Mirror
392 device_printf(sc->aac_dev,
393 "(ContainerRebuildMirror) container "
395 aif->data.PR[0].jd.client.container.src);
397 case AifJobCtrCrazyCache: /* crazy cache */
398 device_printf(sc->aac_dev,
399 "(ContainerCrazyCache) container %d\n",
400 aif->data.PR[0].jd.client.container.src);
401 /* XXX two containers? */
403 case AifJobFsCreate: /* File System Create
405 device_printf(sc->aac_dev, "(FsCreate)\n");
407 case AifJobFsVerify: /* File System Verify
409 device_printf(sc->aac_dev, "(FsVerivy)\n");
411 case AifJobFsExtend: /* File System Extend
413 device_printf(sc->aac_dev, "(FsExtend)\n");
415 case AifJobApiFormatNTFS: /* Format a drive to NTFS */
416 device_printf(sc->aac_dev, "(FormatNTFS)\n");
418 case AifJobApiFormatFAT: /* Format a drive to FAT */
419 device_printf(sc->aac_dev, "(FormatFAT)\n");
421 case AifJobApiUpdateSnapshot: /* update the read/write half
423 device_printf(sc->aac_dev, "(UpdateSnapshot)\n");
425 case AifJobApiFormatFAT32: /* Format a drive to FAT32 */
426 device_printf(sc->aac_dev, "(FormatFAT32)\n");
428 case AifJobCtlContinuousCtrVerify: /* Adapter operation */
429 device_printf(sc->aac_dev, "(ContinuousCtrVerify)\n");
432 device_printf(sc->aac_dev, "(%d)\n",
433 aif->data.PR[0].jd.type);
438 case AifCmdAPIReport:
439 device_printf(sc->aac_dev, "APIReport (%d)\n", aif->seqNumber);
441 case AifCmdDriverNotify:
442 device_printf(sc->aac_dev, "DriverNotify (%d)\n",
446 device_printf(sc->aac_dev, "AIF %d (%d)\n", aif->command,
451 #endif /* AACRAID_DEBUG */
454 * Debug flags to be put into the HBA flags field when initialized
456 const unsigned long aacraid_debug_flags = /* Variable to setup with above flags. */
457 /* HBA_FLAGS_DBG_KERNEL_PRINT_B | */
458 HBA_FLAGS_DBG_FW_PRINT_B |
459 /* HBA_FLAGS_DBG_FUNCTION_ENTRY_B | */
460 HBA_FLAGS_DBG_FUNCTION_EXIT_B |
461 HBA_FLAGS_DBG_ERROR_B |
462 HBA_FLAGS_DBG_INIT_B |
463 /* HBA_FLAGS_DBG_OS_COMMANDS_B | */
464 /* HBA_FLAGS_DBG_SCAN_B | */
465 /* HBA_FLAGS_DBG_COALESCE_B | */
466 /* HBA_FLAGS_DBG_IOCTL_COMMANDS_B | */
467 /* HBA_FLAGS_DBG_SYNC_COMMANDS_B | */
468 HBA_FLAGS_DBG_COMM_B |
469 /* HBA_FLAGS_DBG_AIF_B | */
470 /* HBA_FLAGS_DBG_CSMI_COMMANDS_B | */
471 HBA_FLAGS_DBG_DEBUG_B |
472 /* HBA_FLAGS_DBG_FLAGS_MASK | */
475 int aacraid_get_fw_debug_buffer(struct aac_softc *sc)
477 u_int32_t MonDriverBufferPhysAddrLow = 0;
478 u_int32_t MonDriverBufferPhysAddrHigh = 0;
479 u_int32_t MonDriverBufferSize = 0;
480 u_int32_t MonDriverHeaderSize = 0;
483 * Get the firmware print buffer parameters from the firmware
484 * If the command was successful map in the address.
486 if (!aacraid_sync_command(sc, AAC_MONKER_GETDRVPROP, 0, 0, 0, 0, NULL, NULL)) {
487 MonDriverBufferPhysAddrLow = AAC_GET_MAILBOX(sc, 1);
488 MonDriverBufferPhysAddrHigh = AAC_GET_MAILBOX(sc, 2);
489 MonDriverBufferSize = AAC_GET_MAILBOX(sc, 3);
490 MonDriverHeaderSize = AAC_GET_MAILBOX(sc, 4);
491 if (MonDriverBufferSize) {
492 unsigned long Offset = MonDriverBufferPhysAddrLow
493 - rman_get_start(sc->aac_regs_res1);
496 * See if the address is already mapped in and if so set it up
497 * from the base address
499 if ((MonDriverBufferPhysAddrHigh == 0) &&
500 (Offset + MonDriverBufferSize <
501 rman_get_size(sc->aac_regs_res1))) {
502 sc->DebugOffset = Offset;
503 sc->DebugHeaderSize = MonDriverHeaderSize;
504 sc->FwDebugBufferSize = MonDriverBufferSize;
505 sc->FwDebugFlags = 0;
506 sc->DebugFlags = aacraid_debug_flags;
513 * The GET_DRIVER_BUFFER_PROPERTIES command failed
518 #define PRINT_TIMEOUT 250000 /* 1/4 second */
520 void aacraid_fw_printf(struct aac_softc *sc, unsigned long PrintFlags, const char * fmt, ...)
524 char PrintBuffer_P[PRINT_BUFFER_SIZE];
525 unsigned long PrintType;
527 PrintType = PrintFlags &
528 ~(HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B);
529 if (((PrintType!=0) && (sc!=NULL) && ((sc->DebugFlags & PrintType)==0))
530 || ((sc!=NULL) && (sc->DebugFlags
531 & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B)) == 0))
535 * Set up parameters and call sprintf function to format the data
538 vsprintf(PrintBuffer_P, fmt, args);
542 * Make sure the HBA structure has been passed in for this section
544 if ((sc != NULL) && (sc->FwDebugBufferSize)) {
546 * If we are set up for a Firmware print
548 if ((sc->DebugFlags & HBA_FLAGS_DBG_FW_PRINT_B)
550 & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B))
551 != HBA_FLAGS_DBG_KERNEL_PRINT_B)) {
553 * Make sure the string size is within boundaries
555 Count = strlen(PrintBuffer_P);
556 if (Count > sc->FwDebugBufferSize)
557 Count = (u_int16_t)sc->FwDebugBufferSize;
560 * Wait for no more than PRINT_TIMEOUT for the previous
561 * message length to clear (the handshake).
563 for (i = 0; i < PRINT_TIMEOUT; ++i) {
564 if (!AAC_MEM1_GETREG4(sc,
565 sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET)) {
572 * If the Length is clear, copy over the message, the
573 * flags, and the length. Make sure the length is the
574 * last because that is the signal for the Firmware to
577 if (!AAC_MEM1_GETREG4(sc,
578 sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET)) {
579 for (i = 0; i < Count; ++i) {
580 AAC_MEM1_SETREG1(sc, sc->DebugOffset + sc->DebugHeaderSize + i,
583 AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_FLAGS_OFFSET,
585 AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET,
588 sc->DebugFlags &= ~HBA_FLAGS_DBG_FW_PRINT_B;
592 * If the Kernel Debug Print flag is set, send it off to the
595 if ((sc->DebugFlags & HBA_FLAGS_DBG_KERNEL_PRINT_B)
597 & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B))
598 != HBA_FLAGS_DBG_FW_PRINT_B)) {
599 if (sc->FwDebugFlags & FW_DEBUG_FLAGS_NO_HEADERS_B)
600 printf ("%s\n", PrintBuffer_P);
602 device_printf (sc->aac_dev, "%s\n", PrintBuffer_P);
607 * No HBA structure passed in so it has to be for the Kernel Debugger
609 if ((sc != NULL) && (sc->FwDebugFlags & FW_DEBUG_FLAGS_NO_HEADERS_B))
610 printf ("%s\n", PrintBuffer_P);
612 device_printf (sc->aac_dev, "%s\n", PrintBuffer_P);
614 printf("%s\n", PrintBuffer_P);
618 void aacraid_fw_print_mem(struct aac_softc *sc, unsigned long PrintFlags, u_int8_t *Addr, int Count)
621 u_int32_t DebugFlags = 0;
626 * If we have an HBA structure, save off the flags and set the no
627 * headers flag so we don't have garbage between our lines of data
630 DebugFlags = sc->FwDebugFlags;
631 sc->FwDebugFlags |= FW_DEBUG_FLAGS_NO_HEADERS_B;
637 * Loop through all the data
639 while (Offset < Count) {
641 * We will format each line into a buffer and then print out
642 * the entire line so set the pointer to the beginning of the
645 LineBuffer_P = Buffer;
648 * Set up the address in HEX
650 sprintf(LineBuffer_P, "\n%04x ", Offset);
654 * Set up 16 bytes in HEX format
656 for (i = 0; i < 16; ++i) {
658 * If we are past the count of data bytes to output,
661 if ((Offset + i) >= Count)
662 sprintf (LineBuffer_P, " ");
664 sprintf (LineBuffer_P, "%02x ", Addr[Offset+i]);
668 * At the mid point we will put in a divider
671 sprintf (LineBuffer_P, "- ");
676 * Now do the same 16 bytes at the end of the line in ASCII
679 sprintf (LineBuffer_P, " ");
681 for (i = 0; i < 16; ++i) {
683 * If all data processed, OUT-O-HERE
685 if ((Offset + i) >= Count)
689 * If this is a printable ASCII character, convert it
691 if ((Addr[Offset+i] > 0x1F) && (Addr[Offset+i] < 0x7F))
692 sprintf (LineBuffer_P, "%c", Addr[Offset+i]);
694 sprintf (LineBuffer_P, ".");
698 * The line is now formatted, so print it out
700 aacraid_fw_printf(sc, PrintFlags, "%s", Buffer);
703 * Bump the offset by 16 for the next line
710 * Restore the saved off flags
713 sc->FwDebugFlags = DebugFlags;