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
aacraid_print_queues(struct aac_softc * sc)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
aacraid_print_fib(struct aac_softc * sc,struct aac_fib * fib,const char * caller)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
aacraid_print_aif(struct aac_softc * sc,struct aac_aif_command * aif)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
aacraid_get_fw_debug_buffer(struct aac_softc * sc)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
aacraid_fw_printf(struct aac_softc * sc,unsigned long PrintFlags,const char * fmt,...)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
aacraid_fw_print_mem(struct aac_softc * sc,unsigned long PrintFlags,u_int8_t * Addr,int Count)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