1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 /* 33 * Debugging support. 34 */ 35 #include "opt_aacraid.h" 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/conf.h> 41 42 #include <sys/bus.h> 43 44 #include <machine/resource.h> 45 #include <machine/bus.h> 46 47 #include <dev/aacraid/aacraid_reg.h> 48 #include <sys/aac_ioctl.h> 49 #include <dev/aacraid/aacraid_var.h> 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/kernel.h> 53 #include <sys/conf.h> 54 #include <sys/bus.h> 55 #include <sys/rman.h> 56 #include <sys/stdarg.h> 57 58 #include <machine/resource.h> 59 #include <machine/bus.h> 60 61 #include <dev/aacraid/aacraid_debug.h> 62 63 #ifdef AACRAID_DEBUG 64 /* 65 * Dump the command queue indices 66 */ 67 void 68 aacraid_print_queues(struct aac_softc *sc) 69 { 70 device_printf(sc->aac_dev, "AACQ_FREE %d/%d\n", 71 sc->aac_qstat[AACQ_FREE].q_length, sc->aac_qstat[AACQ_FREE].q_max); 72 device_printf(sc->aac_dev, "AACQ_READY %d/%d\n", 73 sc->aac_qstat[AACQ_READY].q_length, 74 sc->aac_qstat[AACQ_READY].q_max); 75 device_printf(sc->aac_dev, "AACQ_BUSY %d/%d\n", 76 sc->aac_qstat[AACQ_BUSY].q_length, sc->aac_qstat[AACQ_BUSY].q_max); 77 } 78 79 /* 80 * Print a FIB 81 */ 82 void 83 aacraid_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller) 84 { 85 if (fib == NULL) { 86 device_printf(sc->aac_dev, 87 "aac_print_fib called with NULL fib\n"); 88 return; 89 } 90 device_printf(sc->aac_dev, "%s: FIB @ %p\n", caller, fib); 91 device_printf(sc->aac_dev, " XferState %b\n", fib->Header.XferState, 92 "\20" 93 "\1HOSTOWNED" 94 "\2ADAPTEROWNED" 95 "\3INITIALISED" 96 "\4EMPTY" 97 "\5FROMPOOL" 98 "\6FROMHOST" 99 "\7FROMADAP" 100 "\10REXPECTED" 101 "\11RNOTEXPECTED" 102 "\12DONEADAP" 103 "\13DONEHOST" 104 "\14HIGH" 105 "\15NORM" 106 "\16ASYNC" 107 "\17PAGEFILEIO" 108 "\20SHUTDOWN" 109 "\21LAZYWRITE" 110 "\22ADAPMICROFIB" 111 "\23BIOSFIB" 112 "\24FAST_RESPONSE" 113 "\25APIFIB\n"); 114 device_printf(sc->aac_dev, " Command %d\n", fib->Header.Command); 115 device_printf(sc->aac_dev, " StructType %d\n", 116 fib->Header.StructType); 117 device_printf(sc->aac_dev, " Size %d\n", fib->Header.Size); 118 device_printf(sc->aac_dev, " SenderSize %d\n", 119 fib->Header.SenderSize); 120 device_printf(sc->aac_dev, " SenderAddress 0x%x\n", 121 fib->Header.SenderFibAddress); 122 device_printf(sc->aac_dev, " RcvrAddress 0x%x\n", 123 fib->Header.u.ReceiverFibAddress); 124 device_printf(sc->aac_dev, " Handle 0x%x\n", 125 fib->Header.Handle); 126 switch(fib->Header.Command) { 127 case ContainerCommand: 128 { 129 struct aac_blockread *br; 130 struct aac_blockwrite *bw; 131 struct aac_sg_table *sg; 132 int i; 133 134 br = (struct aac_blockread*)fib->data; 135 bw = (struct aac_blockwrite*)fib->data; 136 sg = NULL; 137 138 if (br->Command == VM_CtBlockRead) { 139 device_printf(sc->aac_dev, 140 " BlockRead: container %d 0x%x/%d\n", 141 br->ContainerId, br->BlockNumber, 142 br->ByteCount); 143 sg = &br->SgMap; 144 } 145 if (bw->Command == VM_CtBlockWrite) { 146 device_printf(sc->aac_dev, 147 " BlockWrite: container %d 0x%x/%d " 148 "(%s)\n", bw->ContainerId, 149 bw->BlockNumber, bw->ByteCount, 150 bw->Stable == CSTABLE ? "stable" : 151 "unstable"); 152 sg = &bw->SgMap; 153 } 154 if (sg != NULL) { 155 device_printf(sc->aac_dev, 156 " %d s/g entries\n", sg->SgCount); 157 for (i = 0; i < sg->SgCount; i++) 158 device_printf(sc->aac_dev, " 0x%08x/%d\n", 159 sg->SgEntry[i].SgAddress, 160 sg->SgEntry[i].SgByteCount); 161 } 162 break; 163 } 164 default: 165 device_printf(sc->aac_dev, " %16D\n", fib->data, " "); 166 device_printf(sc->aac_dev, " %16D\n", fib->data + 16, " "); 167 break; 168 } 169 } 170 171 /* 172 * Describe an AIF we have received. 173 */ 174 void 175 aacraid_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) 176 { 177 switch(aif->command) { 178 case AifCmdEventNotify: 179 device_printf(sc->aac_dev, "EventNotify(%d)\n", aif->seqNumber); 180 switch(aif->data.EN.type) { 181 case AifEnGeneric: /* Generic notification */ 182 device_printf(sc->aac_dev, "(Generic) %.*s\n", 183 (int)sizeof(aif->data.EN.data.EG), 184 aif->data.EN.data.EG.text); 185 break; 186 case AifEnTaskComplete: /* Task has completed */ 187 device_printf(sc->aac_dev, "(TaskComplete)\n"); 188 break; 189 case AifEnConfigChange: /* Adapter configuration change 190 * occurred */ 191 device_printf(sc->aac_dev, "(ConfigChange)\n"); 192 break; 193 case AifEnContainerChange: /* Adapter specific container 194 * configuration change */ 195 device_printf(sc->aac_dev, "(ContainerChange) " 196 "container %d,%d\n", 197 aif->data.EN.data.ECC.container[0], 198 aif->data.EN.data.ECC.container[1]); 199 break; 200 case AifEnDeviceFailure: /* SCSI device failed */ 201 device_printf(sc->aac_dev, "(DeviceFailure) " 202 "handle %d\n", 203 aif->data.EN.data.EDF.deviceHandle); 204 break; 205 case AifEnMirrorFailover: /* Mirror failover started */ 206 device_printf(sc->aac_dev, "(MirrorFailover) " 207 "container %d failed, " 208 "migrating from slice %d to %d\n", 209 aif->data.EN.data.EMF.container, 210 aif->data.EN.data.EMF.failedSlice, 211 aif->data.EN.data.EMF.creatingSlice); 212 break; 213 case AifEnContainerEvent: /* Significant container 214 * event */ 215 device_printf(sc->aac_dev, "(ContainerEvent) " 216 "container %d event " 217 "%d\n", aif->data.EN.data.ECE.container, 218 aif->data.EN.data.ECE.eventType); 219 break; 220 case AifEnFileSystemChange: /* File system changed */ 221 device_printf(sc->aac_dev, "(FileSystemChange)\n"); 222 break; 223 case AifEnConfigPause: /* Container pause event */ 224 device_printf(sc->aac_dev, "(ConfigPause)\n"); 225 break; 226 case AifEnConfigResume: /* Container resume event */ 227 device_printf(sc->aac_dev, "(ConfigResume)\n"); 228 break; 229 case AifEnFailoverChange: /* Failover space assignment 230 * changed */ 231 device_printf(sc->aac_dev, "(FailoverChange)\n"); 232 break; 233 case AifEnRAID5RebuildDone: /* RAID5 rebuild finished */ 234 device_printf(sc->aac_dev, "(RAID5RebuildDone)\n"); 235 break; 236 case AifEnEnclosureManagement: /* Enclosure management event */ 237 device_printf(sc->aac_dev, "(EnclosureManagement) " 238 "EMPID %d unit %d " 239 "event %d\n", aif->data.EN.data.EEE.empID, 240 aif->data.EN.data.EEE.unitID, 241 aif->data.EN.data.EEE.eventType); 242 break; 243 case AifEnBatteryEvent: /* Significant NV battery 244 * event */ 245 device_printf(sc->aac_dev, "(BatteryEvent) %d " 246 "(state was %d, is %d\n", 247 aif->data.EN.data.EBE.transition_type, 248 aif->data.EN.data.EBE.current_state, 249 aif->data.EN.data.EBE.prior_state); 250 break; 251 case AifEnAddContainer: /* A new container was 252 * created. */ 253 device_printf(sc->aac_dev, "(AddContainer)\n"); 254 break; 255 case AifEnDeleteContainer: /* A container was deleted. */ 256 device_printf(sc->aac_dev, "(DeleteContainer)\n"); 257 break; 258 case AifEnBatteryNeedsRecond: /* The battery needs 259 * reconditioning */ 260 device_printf(sc->aac_dev, "(BatteryNeedsRecond)\n"); 261 break; 262 case AifEnClusterEvent: /* Some cluster event */ 263 device_printf(sc->aac_dev, "(ClusterEvent) event %d\n", 264 aif->data.EN.data.ECLE.eventType); 265 break; 266 case AifEnDiskSetEvent: /* A disk set event occurred. */ 267 device_printf(sc->aac_dev, "(DiskSetEvent) event %d " 268 "diskset %jd creator %jd\n", 269 aif->data.EN.data.EDS.eventType, 270 (intmax_t)aif->data.EN.data.EDS.DsNum, 271 (intmax_t)aif->data.EN.data.EDS.CreatorId); 272 break; 273 case AifDenMorphComplete: /* A morph operation 274 * completed */ 275 device_printf(sc->aac_dev, "(MorphComplete)\n"); 276 break; 277 case AifDenVolumeExtendComplete: /* A volume expand operation 278 * completed */ 279 device_printf(sc->aac_dev, "(VolumeExtendComplete)\n"); 280 break; 281 default: 282 device_printf(sc->aac_dev, "(%d)\n", aif->data.EN.type); 283 break; 284 } 285 break; 286 case AifCmdJobProgress: 287 { 288 char *status; 289 switch(aif->data.PR[0].status) { 290 case AifJobStsSuccess: 291 status = "success"; break; 292 case AifJobStsFinished: 293 status = "finished"; break; 294 case AifJobStsAborted: 295 status = "aborted"; break; 296 case AifJobStsFailed: 297 status = "failed"; break; 298 case AifJobStsSuspended: 299 status = "suspended"; break; 300 case AifJobStsRunning: 301 status = "running"; break; 302 default: 303 status = "unknown status"; break; 304 } 305 306 device_printf(sc->aac_dev, "JobProgress (%d) - %s (%d, %d)\n", 307 aif->seqNumber, status, 308 aif->data.PR[0].currentTick, 309 aif->data.PR[0].finalTick); 310 switch(aif->data.PR[0].jd.type) { 311 case AifJobScsiZero: /* SCSI dev clear operation */ 312 device_printf(sc->aac_dev, "(ScsiZero) handle %d\n", 313 aif->data.PR[0].jd.client.scsi_dh); 314 break; 315 case AifJobScsiVerify: /* SCSI device Verify operation 316 * NO REPAIR */ 317 device_printf(sc->aac_dev, "(ScsiVerify) handle %d\n", 318 aif->data.PR[0].jd.client.scsi_dh); 319 break; 320 case AifJobScsiExercise: /* SCSI device Exercise 321 * operation */ 322 device_printf(sc->aac_dev, "(ScsiExercise) handle %d\n", 323 aif->data.PR[0].jd.client.scsi_dh); 324 break; 325 case AifJobScsiVerifyRepair: /* SCSI device Verify operation 326 * WITH repair */ 327 device_printf(sc->aac_dev, 328 "(ScsiVerifyRepair) handle %d\n", 329 aif->data.PR[0].jd.client.scsi_dh); 330 break; 331 case AifJobCtrZero: /* Container clear operation */ 332 device_printf(sc->aac_dev, 333 "(ContainerZero) container %d\n", 334 aif->data.PR[0].jd.client.container.src); 335 break; 336 case AifJobCtrCopy: /* Container copy operation */ 337 device_printf(sc->aac_dev, 338 "(ContainerCopy) container %d to %d\n", 339 aif->data.PR[0].jd.client.container.src, 340 aif->data.PR[0].jd.client.container.dst); 341 break; 342 case AifJobCtrCreateMirror: /* Container Create Mirror 343 * operation */ 344 device_printf(sc->aac_dev, 345 "(ContainerCreateMirror) container %d\n", 346 aif->data.PR[0].jd.client.container.src); 347 /* XXX two containers? */ 348 break; 349 case AifJobCtrMergeMirror: /* Container Merge Mirror 350 * operation */ 351 device_printf(sc->aac_dev, 352 "(ContainerMergeMirror) container %d\n", 353 aif->data.PR[0].jd.client.container.src); 354 /* XXX two containers? */ 355 break; 356 case AifJobCtrScrubMirror: /* Container Scrub Mirror 357 * operation */ 358 device_printf(sc->aac_dev, 359 "(ContainerScrubMirror) container %d\n", 360 aif->data.PR[0].jd.client.container.src); 361 break; 362 case AifJobCtrRebuildRaid5: /* Container Rebuild Raid5 363 * operation */ 364 device_printf(sc->aac_dev, 365 "(ContainerRebuildRaid5) container %d\n", 366 aif->data.PR[0].jd.client.container.src); 367 break; 368 case AifJobCtrScrubRaid5: /* Container Scrub Raid5 369 * operation */ 370 device_printf(sc->aac_dev, 371 "(ContainerScrubRaid5) container %d\n", 372 aif->data.PR[0].jd.client.container.src); 373 break; 374 case AifJobCtrMorph: /* Container morph operation */ 375 device_printf(sc->aac_dev, 376 "(ContainerMorph) container %d\n", 377 aif->data.PR[0].jd.client.container.src); 378 /* XXX two containers? */ 379 break; 380 case AifJobCtrPartCopy: /* Container Partition copy 381 * operation */ 382 device_printf(sc->aac_dev, 383 "(ContainerPartCopy) container %d to " 384 "%d\n", 385 aif->data.PR[0].jd.client.container.src, 386 aif->data.PR[0].jd.client.container.dst); 387 break; 388 case AifJobCtrRebuildMirror: /* Container Rebuild Mirror 389 * operation */ 390 device_printf(sc->aac_dev, 391 "(ContainerRebuildMirror) container " 392 "%d\n", 393 aif->data.PR[0].jd.client.container.src); 394 break; 395 case AifJobCtrCrazyCache: /* crazy cache */ 396 device_printf(sc->aac_dev, 397 "(ContainerCrazyCache) container %d\n", 398 aif->data.PR[0].jd.client.container.src); 399 /* XXX two containers? */ 400 break; 401 case AifJobFsCreate: /* File System Create 402 * operation */ 403 device_printf(sc->aac_dev, "(FsCreate)\n"); 404 break; 405 case AifJobFsVerify: /* File System Verify 406 * operation */ 407 device_printf(sc->aac_dev, "(FsVerivy)\n"); 408 break; 409 case AifJobFsExtend: /* File System Extend 410 * operation */ 411 device_printf(sc->aac_dev, "(FsExtend)\n"); 412 break; 413 case AifJobApiFormatNTFS: /* Format a drive to NTFS */ 414 device_printf(sc->aac_dev, "(FormatNTFS)\n"); 415 break; 416 case AifJobApiFormatFAT: /* Format a drive to FAT */ 417 device_printf(sc->aac_dev, "(FormatFAT)\n"); 418 break; 419 case AifJobApiUpdateSnapshot: /* update the read/write half 420 * of a snapshot */ 421 device_printf(sc->aac_dev, "(UpdateSnapshot)\n"); 422 break; 423 case AifJobApiFormatFAT32: /* Format a drive to FAT32 */ 424 device_printf(sc->aac_dev, "(FormatFAT32)\n"); 425 break; 426 case AifJobCtlContinuousCtrVerify: /* Adapter operation */ 427 device_printf(sc->aac_dev, "(ContinuousCtrVerify)\n"); 428 break; 429 default: 430 device_printf(sc->aac_dev, "(%d)\n", 431 aif->data.PR[0].jd.type); 432 break; 433 } 434 break; 435 } 436 case AifCmdAPIReport: 437 device_printf(sc->aac_dev, "APIReport (%d)\n", aif->seqNumber); 438 break; 439 case AifCmdDriverNotify: 440 device_printf(sc->aac_dev, "DriverNotify (%d)\n", 441 aif->seqNumber); 442 break; 443 default: 444 device_printf(sc->aac_dev, "AIF %d (%d)\n", aif->command, 445 aif->seqNumber); 446 break; 447 } 448 } 449 #endif /* AACRAID_DEBUG */ 450 451 /* 452 * Debug flags to be put into the HBA flags field when initialized 453 */ 454 const unsigned long aacraid_debug_flags = /* Variable to setup with above flags. */ 455 /* HBA_FLAGS_DBG_KERNEL_PRINT_B | */ 456 HBA_FLAGS_DBG_FW_PRINT_B | 457 /* HBA_FLAGS_DBG_FUNCTION_ENTRY_B | */ 458 HBA_FLAGS_DBG_FUNCTION_EXIT_B | 459 HBA_FLAGS_DBG_ERROR_B | 460 HBA_FLAGS_DBG_INIT_B | 461 /* HBA_FLAGS_DBG_OS_COMMANDS_B | */ 462 /* HBA_FLAGS_DBG_SCAN_B | */ 463 /* HBA_FLAGS_DBG_COALESCE_B | */ 464 /* HBA_FLAGS_DBG_IOCTL_COMMANDS_B | */ 465 /* HBA_FLAGS_DBG_SYNC_COMMANDS_B | */ 466 HBA_FLAGS_DBG_COMM_B | 467 /* HBA_FLAGS_DBG_AIF_B | */ 468 /* HBA_FLAGS_DBG_CSMI_COMMANDS_B | */ 469 HBA_FLAGS_DBG_DEBUG_B | 470 /* HBA_FLAGS_DBG_FLAGS_MASK | */ 471 0; 472 473 int aacraid_get_fw_debug_buffer(struct aac_softc *sc) 474 { 475 u_int32_t MonDriverBufferPhysAddrLow = 0; 476 u_int32_t MonDriverBufferPhysAddrHigh = 0; 477 u_int32_t MonDriverBufferSize = 0; 478 u_int32_t MonDriverHeaderSize = 0; 479 480 /* 481 * Get the firmware print buffer parameters from the firmware 482 * If the command was successful map in the address. 483 */ 484 if (!aacraid_sync_command(sc, AAC_MONKER_GETDRVPROP, 0, 0, 0, 0, NULL, NULL)) { 485 MonDriverBufferPhysAddrLow = AAC_GET_MAILBOX(sc, 1); 486 MonDriverBufferPhysAddrHigh = AAC_GET_MAILBOX(sc, 2); 487 MonDriverBufferSize = AAC_GET_MAILBOX(sc, 3); 488 MonDriverHeaderSize = AAC_GET_MAILBOX(sc, 4); 489 if (MonDriverBufferSize) { 490 unsigned long Offset = MonDriverBufferPhysAddrLow 491 - rman_get_start(sc->aac_regs_res1); 492 493 /* 494 * See if the address is already mapped in and if so set it up 495 * from the base address 496 */ 497 if ((MonDriverBufferPhysAddrHigh == 0) && 498 (Offset + MonDriverBufferSize < 499 rman_get_size(sc->aac_regs_res1))) { 500 sc->DebugOffset = Offset; 501 sc->DebugHeaderSize = MonDriverHeaderSize; 502 sc->FwDebugBufferSize = MonDriverBufferSize; 503 sc->FwDebugFlags = 0; 504 sc->DebugFlags = aacraid_debug_flags; 505 return 1; 506 } 507 } 508 } 509 510 /* 511 * The GET_DRIVER_BUFFER_PROPERTIES command failed 512 */ 513 return 0; 514 } 515 516 #define PRINT_TIMEOUT 250000 /* 1/4 second */ 517 518 void aacraid_fw_printf(struct aac_softc *sc, unsigned long PrintFlags, const char * fmt, ...) 519 { 520 va_list args; 521 u_int32_t Count, i; 522 char PrintBuffer_P[PRINT_BUFFER_SIZE]; 523 unsigned long PrintType; 524 525 PrintType = PrintFlags & 526 ~(HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B); 527 if (((PrintType!=0) && (sc!=NULL) && ((sc->DebugFlags & PrintType)==0)) 528 || ((sc!=NULL) && (sc->DebugFlags 529 & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B)) == 0)) 530 return; 531 532 /* 533 * Set up parameters and call sprintf function to format the data 534 */ 535 va_start(args, fmt); 536 vsprintf(PrintBuffer_P, fmt, args); 537 va_end(args); 538 539 /* 540 * Make sure the HBA structure has been passed in for this section 541 */ 542 if ((sc != NULL) && (sc->FwDebugBufferSize)) { 543 /* 544 * If we are set up for a Firmware print 545 */ 546 if ((sc->DebugFlags & HBA_FLAGS_DBG_FW_PRINT_B) 547 && ((PrintFlags 548 & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B)) 549 != HBA_FLAGS_DBG_KERNEL_PRINT_B)) { 550 /* 551 * Make sure the string size is within boundaries 552 */ 553 Count = strlen(PrintBuffer_P); 554 if (Count > sc->FwDebugBufferSize) 555 Count = (u_int16_t)sc->FwDebugBufferSize; 556 557 /* 558 * Wait for no more than PRINT_TIMEOUT for the previous 559 * message length to clear (the handshake). 560 */ 561 for (i = 0; i < PRINT_TIMEOUT; ++i) { 562 if (!AAC_MEM1_GETREG4(sc, 563 sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET)) { 564 break; 565 } 566 DELAY(1); 567 } 568 569 /* 570 * If the Length is clear, copy over the message, the 571 * flags, and the length. Make sure the length is the 572 * last because that is the signal for the Firmware to 573 * pick it up. 574 */ 575 if (!AAC_MEM1_GETREG4(sc, 576 sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET)) { 577 for (i = 0; i < Count; ++i) { 578 AAC_MEM1_SETREG1(sc, sc->DebugOffset + sc->DebugHeaderSize + i, 579 PrintBuffer_P[i]); 580 } 581 AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_FLAGS_OFFSET, 582 sc->FwDebugFlags); 583 AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET, 584 Count); 585 } else 586 sc->DebugFlags &= ~HBA_FLAGS_DBG_FW_PRINT_B; 587 } 588 589 /* 590 * If the Kernel Debug Print flag is set, send it off to the 591 * Kernel debugger 592 */ 593 if ((sc->DebugFlags & HBA_FLAGS_DBG_KERNEL_PRINT_B) 594 && ((PrintFlags 595 & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B)) 596 != HBA_FLAGS_DBG_FW_PRINT_B)) { 597 if (sc->FwDebugFlags & FW_DEBUG_FLAGS_NO_HEADERS_B) 598 printf ("%s\n", PrintBuffer_P); 599 else 600 device_printf (sc->aac_dev, "%s\n", PrintBuffer_P); 601 } 602 603 } else { 604 /* 605 * No HBA structure passed in so it has to be for the Kernel Debugger 606 */ 607 if ((sc != NULL) && (sc->FwDebugFlags & FW_DEBUG_FLAGS_NO_HEADERS_B)) 608 printf ("%s\n", PrintBuffer_P); 609 else if (sc != NULL) 610 device_printf (sc->aac_dev, "%s\n", PrintBuffer_P); 611 else 612 printf("%s\n", PrintBuffer_P); 613 } 614 } 615 616 void aacraid_fw_print_mem(struct aac_softc *sc, unsigned long PrintFlags, u_int8_t *Addr, int Count) 617 { 618 int Offset, i; 619 u_int32_t DebugFlags = 0; 620 char Buffer[100]; 621 char *LineBuffer_P; 622 623 /* 624 * If we have an HBA structure, save off the flags and set the no 625 * headers flag so we don't have garbage between our lines of data 626 */ 627 if (sc != NULL) { 628 DebugFlags = sc->FwDebugFlags; 629 sc->FwDebugFlags |= FW_DEBUG_FLAGS_NO_HEADERS_B; 630 } 631 632 Offset = 0; 633 634 /* 635 * Loop through all the data 636 */ 637 while (Offset < Count) { 638 /* 639 * We will format each line into a buffer and then print out 640 * the entire line so set the pointer to the beginning of the 641 * buffer 642 */ 643 LineBuffer_P = Buffer; 644 645 /* 646 * Set up the address in HEX 647 */ 648 sprintf(LineBuffer_P, "\n%04x ", Offset); 649 LineBuffer_P += 6; 650 651 /* 652 * Set up 16 bytes in HEX format 653 */ 654 for (i = 0; i < 16; ++i) { 655 /* 656 * If we are past the count of data bytes to output, 657 * pad with blanks 658 */ 659 if ((Offset + i) >= Count) 660 sprintf (LineBuffer_P, " "); 661 else 662 sprintf (LineBuffer_P, "%02x ", Addr[Offset+i]); 663 LineBuffer_P += 3; 664 665 /* 666 * At the mid point we will put in a divider 667 */ 668 if (i == 7) { 669 sprintf (LineBuffer_P, "- "); 670 LineBuffer_P += 2; 671 } 672 } 673 /* 674 * Now do the same 16 bytes at the end of the line in ASCII 675 * format 676 */ 677 sprintf (LineBuffer_P, " "); 678 LineBuffer_P += 2; 679 for (i = 0; i < 16; ++i) { 680 /* 681 * If all data processed, OUT-O-HERE 682 */ 683 if ((Offset + i) >= Count) 684 break; 685 686 /* 687 * If this is a printable ASCII character, convert it 688 */ 689 if ((Addr[Offset+i] > 0x1F) && (Addr[Offset+i] < 0x7F)) 690 sprintf (LineBuffer_P, "%c", Addr[Offset+i]); 691 else 692 sprintf (LineBuffer_P, "."); 693 ++LineBuffer_P; 694 } 695 /* 696 * The line is now formatted, so print it out 697 */ 698 aacraid_fw_printf(sc, PrintFlags, "%s", Buffer); 699 700 /* 701 * Bump the offset by 16 for the next line 702 */ 703 Offset += 16; 704 } 705 706 /* 707 * Restore the saved off flags 708 */ 709 if (sc != NULL) 710 sc->FwDebugFlags = DebugFlags; 711 } 712