]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/aacraid/aacraid_debug.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / aacraid / aacraid_debug.c
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 occured. */
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