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