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