1 2 /*- 3 * Copyright (c) 2006-2010 Adaptec, Inc. 4 * Copyright (c) 2010-2012 PMC-Sierra, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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. 15 * 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 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 /* 34 * Debugging support. 35 */ 36 #include "opt_aacraid.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/conf.h> 42 43 #include <sys/bus.h> 44 45 #include <machine/resource.h> 46 #include <machine/bus.h> 47 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> 54 #include <sys/conf.h> 55 56 #include <sys/bus.h> 57 #include <sys/rman.h> 58 59 #include <machine/resource.h> 60 #include <machine/bus.h> 61 #include <machine/stdarg.h> 62 63 #include <dev/aacraid/aacraid_debug.h> 64 65 #ifdef AACRAID_DEBUG 66 /* 67 * Dump the command queue indices 68 */ 69 void 70 aacraid_print_queues(struct aac_softc *sc) 71 { 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); 79 } 80 81 /* 82 * Print a FIB 83 */ 84 void 85 aacraid_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller) 86 { 87 if (fib == NULL) { 88 device_printf(sc->aac_dev, 89 "aac_print_fib called with NULL fib\n"); 90 return; 91 } 92 device_printf(sc->aac_dev, "%s: FIB @ %p\n", caller, fib); 93 device_printf(sc->aac_dev, " XferState %b\n", fib->Header.XferState, 94 "\20" 95 "\1HOSTOWNED" 96 "\2ADAPTEROWNED" 97 "\3INITIALISED" 98 "\4EMPTY" 99 "\5FROMPOOL" 100 "\6FROMHOST" 101 "\7FROMADAP" 102 "\10REXPECTED" 103 "\11RNOTEXPECTED" 104 "\12DONEADAP" 105 "\13DONEHOST" 106 "\14HIGH" 107 "\15NORM" 108 "\16ASYNC" 109 "\17PAGEFILEIO" 110 "\20SHUTDOWN" 111 "\21LAZYWRITE" 112 "\22ADAPMICROFIB" 113 "\23BIOSFIB" 114 "\24FAST_RESPONSE" 115 "\25APIFIB\n"); 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", 127 fib->Header.Handle); 128 switch(fib->Header.Command) { 129 case ContainerCommand: 130 { 131 struct aac_blockread *br; 132 struct aac_blockwrite *bw; 133 struct aac_sg_table *sg; 134 int i; 135 136 br = (struct aac_blockread*)fib->data; 137 bw = (struct aac_blockwrite*)fib->data; 138 sg = NULL; 139 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, 144 br->ByteCount); 145 sg = &br->SgMap; 146 } 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" : 153 "unstable"); 154 sg = &bw->SgMap; 155 } 156 if (sg != NULL) { 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); 163 } 164 break; 165 } 166 default: 167 device_printf(sc->aac_dev, " %16D\n", fib->data, " "); 168 device_printf(sc->aac_dev, " %16D\n", fib->data + 16, " "); 169 break; 170 } 171 } 172 173 /* 174 * Describe an AIF we have received. 175 */ 176 void 177 aacraid_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) 178 { 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); 187 break; 188 case AifEnTaskComplete: /* Task has completed */ 189 device_printf(sc->aac_dev, "(TaskComplete)\n"); 190 break; 191 case AifEnConfigChange: /* Adapter configuration change 192 * occurred */ 193 device_printf(sc->aac_dev, "(ConfigChange)\n"); 194 break; 195 case AifEnContainerChange: /* Adapter specific container 196 * configuration change */ 197 device_printf(sc->aac_dev, "(ContainerChange) " 198 "container %d,%d\n", 199 aif->data.EN.data.ECC.container[0], 200 aif->data.EN.data.ECC.container[1]); 201 break; 202 case AifEnDeviceFailure: /* SCSI device failed */ 203 device_printf(sc->aac_dev, "(DeviceFailure) " 204 "handle %d\n", 205 aif->data.EN.data.EDF.deviceHandle); 206 break; 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); 214 break; 215 case AifEnContainerEvent: /* Significant container 216 * event */ 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); 221 break; 222 case AifEnFileSystemChange: /* File system changed */ 223 device_printf(sc->aac_dev, "(FileSystemChange)\n"); 224 break; 225 case AifEnConfigPause: /* Container pause event */ 226 device_printf(sc->aac_dev, "(ConfigPause)\n"); 227 break; 228 case AifEnConfigResume: /* Container resume event */ 229 device_printf(sc->aac_dev, "(ConfigResume)\n"); 230 break; 231 case AifEnFailoverChange: /* Failover space assignment 232 * changed */ 233 device_printf(sc->aac_dev, "(FailoverChange)\n"); 234 break; 235 case AifEnRAID5RebuildDone: /* RAID5 rebuild finished */ 236 device_printf(sc->aac_dev, "(RAID5RebuildDone)\n"); 237 break; 238 case AifEnEnclosureManagement: /* Enclosure management event */ 239 device_printf(sc->aac_dev, "(EnclosureManagement) " 240 "EMPID %d unit %d " 241 "event %d\n", aif->data.EN.data.EEE.empID, 242 aif->data.EN.data.EEE.unitID, 243 aif->data.EN.data.EEE.eventType); 244 break; 245 case AifEnBatteryEvent: /* Significant NV battery 246 * event */ 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); 252 break; 253 case AifEnAddContainer: /* A new container was 254 * created. */ 255 device_printf(sc->aac_dev, "(AddContainer)\n"); 256 break; 257 case AifEnDeleteContainer: /* A container was deleted. */ 258 device_printf(sc->aac_dev, "(DeleteContainer)\n"); 259 break; 260 case AifEnBatteryNeedsRecond: /* The battery needs 261 * reconditioning */ 262 device_printf(sc->aac_dev, "(BatteryNeedsRecond)\n"); 263 break; 264 case AifEnClusterEvent: /* Some cluster event */ 265 device_printf(sc->aac_dev, "(ClusterEvent) event %d\n", 266 aif->data.EN.data.ECLE.eventType); 267 break; 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); 274 break; 275 case AifDenMorphComplete: /* A morph operation 276 * completed */ 277 device_printf(sc->aac_dev, "(MorphComplete)\n"); 278 break; 279 case AifDenVolumeExtendComplete: /* A volume expand operation 280 * completed */ 281 device_printf(sc->aac_dev, "(VolumeExtendComplete)\n"); 282 break; 283 default: 284 device_printf(sc->aac_dev, "(%d)\n", aif->data.EN.type); 285 break; 286 } 287 break; 288 case AifCmdJobProgress: 289 { 290 char *status; 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; 304 default: 305 status = "unknown status"; break; 306 } 307 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); 316 break; 317 case AifJobScsiVerify: /* SCSI device Verify operation 318 * NO REPAIR */ 319 device_printf(sc->aac_dev, "(ScsiVerify) handle %d\n", 320 aif->data.PR[0].jd.client.scsi_dh); 321 break; 322 case AifJobScsiExercise: /* SCSI device Exercise 323 * operation */ 324 device_printf(sc->aac_dev, "(ScsiExercise) handle %d\n", 325 aif->data.PR[0].jd.client.scsi_dh); 326 break; 327 case AifJobScsiVerifyRepair: /* SCSI device Verify operation 328 * WITH repair */ 329 device_printf(sc->aac_dev, 330 "(ScsiVerifyRepair) handle %d\n", 331 aif->data.PR[0].jd.client.scsi_dh); 332 break; 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); 337 break; 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); 343 break; 344 case AifJobCtrCreateMirror: /* Container Create Mirror 345 * operation */ 346 device_printf(sc->aac_dev, 347 "(ContainerCreateMirror) container %d\n", 348 aif->data.PR[0].jd.client.container.src); 349 /* XXX two containers? */ 350 break; 351 case AifJobCtrMergeMirror: /* Container Merge Mirror 352 * operation */ 353 device_printf(sc->aac_dev, 354 "(ContainerMergeMirror) container %d\n", 355 aif->data.PR[0].jd.client.container.src); 356 /* XXX two containers? */ 357 break; 358 case AifJobCtrScrubMirror: /* Container Scrub Mirror 359 * operation */ 360 device_printf(sc->aac_dev, 361 "(ContainerScrubMirror) container %d\n", 362 aif->data.PR[0].jd.client.container.src); 363 break; 364 case AifJobCtrRebuildRaid5: /* Container Rebuild Raid5 365 * operation */ 366 device_printf(sc->aac_dev, 367 "(ContainerRebuildRaid5) container %d\n", 368 aif->data.PR[0].jd.client.container.src); 369 break; 370 case AifJobCtrScrubRaid5: /* Container Scrub Raid5 371 * operation */ 372 device_printf(sc->aac_dev, 373 "(ContainerScrubRaid5) container %d\n", 374 aif->data.PR[0].jd.client.container.src); 375 break; 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? */ 381 break; 382 case AifJobCtrPartCopy: /* Container Partition copy 383 * operation */ 384 device_printf(sc->aac_dev, 385 "(ContainerPartCopy) container %d to " 386 "%d\n", 387 aif->data.PR[0].jd.client.container.src, 388 aif->data.PR[0].jd.client.container.dst); 389 break; 390 case AifJobCtrRebuildMirror: /* Container Rebuild Mirror 391 * operation */ 392 device_printf(sc->aac_dev, 393 "(ContainerRebuildMirror) container " 394 "%d\n", 395 aif->data.PR[0].jd.client.container.src); 396 break; 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? */ 402 break; 403 case AifJobFsCreate: /* File System Create 404 * operation */ 405 device_printf(sc->aac_dev, "(FsCreate)\n"); 406 break; 407 case AifJobFsVerify: /* File System Verify 408 * operation */ 409 device_printf(sc->aac_dev, "(FsVerivy)\n"); 410 break; 411 case AifJobFsExtend: /* File System Extend 412 * operation */ 413 device_printf(sc->aac_dev, "(FsExtend)\n"); 414 break; 415 case AifJobApiFormatNTFS: /* Format a drive to NTFS */ 416 device_printf(sc->aac_dev, "(FormatNTFS)\n"); 417 break; 418 case AifJobApiFormatFAT: /* Format a drive to FAT */ 419 device_printf(sc->aac_dev, "(FormatFAT)\n"); 420 break; 421 case AifJobApiUpdateSnapshot: /* update the read/write half 422 * of a snapshot */ 423 device_printf(sc->aac_dev, "(UpdateSnapshot)\n"); 424 break; 425 case AifJobApiFormatFAT32: /* Format a drive to FAT32 */ 426 device_printf(sc->aac_dev, "(FormatFAT32)\n"); 427 break; 428 case AifJobCtlContinuousCtrVerify: /* Adapter operation */ 429 device_printf(sc->aac_dev, "(ContinuousCtrVerify)\n"); 430 break; 431 default: 432 device_printf(sc->aac_dev, "(%d)\n", 433 aif->data.PR[0].jd.type); 434 break; 435 } 436 break; 437 } 438 case AifCmdAPIReport: 439 device_printf(sc->aac_dev, "APIReport (%d)\n", aif->seqNumber); 440 break; 441 case AifCmdDriverNotify: 442 device_printf(sc->aac_dev, "DriverNotify (%d)\n", 443 aif->seqNumber); 444 break; 445 default: 446 device_printf(sc->aac_dev, "AIF %d (%d)\n", aif->command, 447 aif->seqNumber); 448 break; 449 } 450 } 451 #endif /* AACRAID_DEBUG */ 452 453 /* 454 * Debug flags to be put into the HBA flags field when initialized 455 */ 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 | */ 473 0; 474 475 int aacraid_get_fw_debug_buffer(struct aac_softc *sc) 476 { 477 u_int32_t MonDriverBufferPhysAddrLow = 0; 478 u_int32_t MonDriverBufferPhysAddrHigh = 0; 479 u_int32_t MonDriverBufferSize = 0; 480 u_int32_t MonDriverHeaderSize = 0; 481 482 /* 483 * Get the firmware print buffer parameters from the firmware 484 * If the command was successful map in the address. 485 */ 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); 494 495 /* 496 * See if the address is already mapped in and if so set it up 497 * from the base address 498 */ 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; 507 return 1; 508 } 509 } 510 } 511 512 /* 513 * The GET_DRIVER_BUFFER_PROPERTIES command failed 514 */ 515 return 0; 516 } 517 518 #define PRINT_TIMEOUT 250000 /* 1/4 second */ 519 520 void aacraid_fw_printf(struct aac_softc *sc, unsigned long PrintFlags, const char * fmt, ...) 521 { 522 va_list args; 523 u_int32_t Count, i; 524 char PrintBuffer_P[PRINT_BUFFER_SIZE]; 525 unsigned long PrintType; 526 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)) 532 return; 533 534 /* 535 * Set up parameters and call sprintf function to format the data 536 */ 537 va_start(args, fmt); 538 vsprintf(PrintBuffer_P, fmt, args); 539 va_end(args); 540 541 /* 542 * Make sure the HBA structure has been passed in for this section 543 */ 544 if ((sc != NULL) && (sc->FwDebugBufferSize)) { 545 /* 546 * If we are set up for a Firmware print 547 */ 548 if ((sc->DebugFlags & HBA_FLAGS_DBG_FW_PRINT_B) 549 && ((PrintFlags 550 & (HBA_FLAGS_DBG_KERNEL_PRINT_B|HBA_FLAGS_DBG_FW_PRINT_B)) 551 != HBA_FLAGS_DBG_KERNEL_PRINT_B)) { 552 /* 553 * Make sure the string size is within boundaries 554 */ 555 Count = strlen(PrintBuffer_P); 556 if (Count > sc->FwDebugBufferSize) 557 Count = (u_int16_t)sc->FwDebugBufferSize; 558 559 /* 560 * Wait for no more than PRINT_TIMEOUT for the previous 561 * message length to clear (the handshake). 562 */ 563 for (i = 0; i < PRINT_TIMEOUT; ++i) { 564 if (!AAC_MEM1_GETREG4(sc, 565 sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET)) { 566 break; 567 } 568 DELAY(1); 569 } 570 571 /* 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 575 * pick it up. 576 */ 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, 581 PrintBuffer_P[i]); 582 } 583 AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_FLAGS_OFFSET, 584 sc->FwDebugFlags); 585 AAC_MEM1_SETREG4(sc, sc->DebugOffset + FW_DEBUG_STR_LENGTH_OFFSET, 586 Count); 587 } else 588 sc->DebugFlags &= ~HBA_FLAGS_DBG_FW_PRINT_B; 589 } 590 591 /* 592 * If the Kernel Debug Print flag is set, send it off to the 593 * Kernel debugger 594 */ 595 if ((sc->DebugFlags & HBA_FLAGS_DBG_KERNEL_PRINT_B) 596 && ((PrintFlags 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); 601 else 602 device_printf (sc->aac_dev, "%s\n", PrintBuffer_P); 603 } 604 605 } else { 606 /* 607 * No HBA structure passed in so it has to be for the Kernel Debugger 608 */ 609 if ((sc != NULL) && (sc->FwDebugFlags & FW_DEBUG_FLAGS_NO_HEADERS_B)) 610 printf ("%s\n", PrintBuffer_P); 611 else if (sc != NULL) 612 device_printf (sc->aac_dev, "%s\n", PrintBuffer_P); 613 else 614 printf("%s\n", PrintBuffer_P); 615 } 616 } 617 618 void aacraid_fw_print_mem(struct aac_softc *sc, unsigned long PrintFlags, u_int8_t *Addr, int Count) 619 { 620 int Offset, i; 621 u_int32_t DebugFlags = 0; 622 char Buffer[100]; 623 char *LineBuffer_P; 624 625 /* 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 628 */ 629 if (sc != NULL) { 630 DebugFlags = sc->FwDebugFlags; 631 sc->FwDebugFlags |= FW_DEBUG_FLAGS_NO_HEADERS_B; 632 } 633 634 Offset = 0; 635 636 /* 637 * Loop through all the data 638 */ 639 while (Offset < Count) { 640 /* 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 643 * buffer 644 */ 645 LineBuffer_P = Buffer; 646 647 /* 648 * Set up the address in HEX 649 */ 650 sprintf(LineBuffer_P, "\n%04x ", Offset); 651 LineBuffer_P += 6; 652 653 /* 654 * Set up 16 bytes in HEX format 655 */ 656 for (i = 0; i < 16; ++i) { 657 /* 658 * If we are past the count of data bytes to output, 659 * pad with blanks 660 */ 661 if ((Offset + i) >= Count) 662 sprintf (LineBuffer_P, " "); 663 else 664 sprintf (LineBuffer_P, "%02x ", Addr[Offset+i]); 665 LineBuffer_P += 3; 666 667 /* 668 * At the mid point we will put in a divider 669 */ 670 if (i == 7) { 671 sprintf (LineBuffer_P, "- "); 672 LineBuffer_P += 2; 673 } 674 } 675 /* 676 * Now do the same 16 bytes at the end of the line in ASCII 677 * format 678 */ 679 sprintf (LineBuffer_P, " "); 680 LineBuffer_P += 2; 681 for (i = 0; i < 16; ++i) { 682 /* 683 * If all data processed, OUT-O-HERE 684 */ 685 if ((Offset + i) >= Count) 686 break; 687 688 /* 689 * If this is a printable ASCII character, convert it 690 */ 691 if ((Addr[Offset+i] > 0x1F) && (Addr[Offset+i] < 0x7F)) 692 sprintf (LineBuffer_P, "%c", Addr[Offset+i]); 693 else 694 sprintf (LineBuffer_P, "."); 695 ++LineBuffer_P; 696 } 697 /* 698 * The line is now formatted, so print it out 699 */ 700 aacraid_fw_printf(sc, PrintFlags, "%s", Buffer); 701 702 /* 703 * Bump the offset by 16 for the next line 704 */ 705 Offset += 16; 706 707 } 708 709 /* 710 * Restore the saved off flags 711 */ 712 if (sc != NULL) 713 sc->FwDebugFlags = DebugFlags; 714 } 715 716