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