xref: /freebsd/sys/dev/pms/RefTisa/sallsdk/spc/saioctlcmd.c (revision dd41de95a84d979615a2ef11df6850622bf6184e)
1 /*******************************************************************************
2 *Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
3 *
4 *Redistribution and use in source and binary forms, with or without modification, are permitted provided
5 *that the following conditions are met:
6 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7 *following disclaimer.
8 *2. Redistributions in binary form must reproduce the above copyright notice,
9 *this list of conditions and the following disclaimer in the documentation and/or other materials provided
10 *with the distribution.
11 *
12 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20 
21 ********************************************************************************/
22 /*******************************************************************************/
23 /*! \file saioctlcmd.c
24  *  \brief The file implements the functions of IOCTL MPI Command/Response to/from SPC
25  *
26  */
27 /******************************************************************************/
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 #include <dev/pms/config.h>
31 
32 #include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
33 #ifdef SA_ENABLE_TRACE_FUNCTIONS
34 #ifdef siTraceFileID
35 #undef siTraceFileID
36 #endif
37 #define siTraceFileID 'H'
38 #endif
39 
40 extern bit32 gFPGA_TEST;
41 
42 extern bit32 gWait_3;
43 extern bit32 gWait_2;
44 
45 
46 
47 LOCAL bit32 siGSMDump(
48                       agsaRoot_t     *agRoot,
49                       bit32          gsmDumpOffset,
50                       bit32          length,
51                       void           *directData);
52 
53 #ifdef SPC_ENABLE_PROFILE
54 /******************************************************************************/
55 /*! \brief SPC FW Profile Command
56  *
57  *  This command sends FW Flash Update Command to SPC.
58  *
59  *  \param agRoot          Handles for this instance of SAS/SATA LL
60  *  \param agContext       Context of SPC FW Flash Update Command
61  *  \param queueNum        Inbound/outbound queue number
62  *  \param flashUpdateInfo Pointer of flash update information
63  *
64  *  \return If the MPI command is sent to SPC successfully
65  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
66  *          - \e AGSA_RC_FAILURE the MPI command is failure
67  *
68  */
69 /*******************************************************************************/
70 GLOBAL bit32 saFwProfile(
71   agsaRoot_t                *agRoot,
72   agsaContext_t             *agContext,
73   bit32                     queueNum,
74   agsaFwProfile_t         *fwProfileInfo
75   )
76 {
77   bit32 ret           = AGSA_RC_SUCCESS, retVal;
78   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
79   agsaIORequestDesc_t *pRequest;
80   mpiICQueue_t        *circularQ;
81   void                *pMessage;
82   agsaFwProfileIOMB_t *pPayload;
83   bit8                inq, outq;
84   bit32               i, tcid_processor_cmd = 0;
85 
86 
87   /* sanity check */
88   SA_ASSERT((agNULL != agRoot), "");
89 
90   /* Get request from free IORequests */
91   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
92   pRequest = (agsaIORequestDesc_t *)saLlistGetHead(&(saRoot->freeIORequests));
93 
94   /* If no LL Control request entry avaliable */
95   if ( agNULL == pRequest )
96   {
97     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
98     SA_DBG1(("saFwProfile, No request from free list\n" ));
99      return AGSA_RC_BUSY;
100   }
101   /* If LL Control request entry avaliable */
102   else
103   {
104     /* Assign inbound and outbound Ring Buffer */
105     inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
106     outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
107     SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
108 
109     /* Remove the request from free list */
110     saLlistRemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
111     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
112     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
113     saRoot->IOMap[pRequest->HTag].agContext = agContext;
114     pRequest->valid = agTRUE;
115     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
116 
117 #ifdef SA_LL_IBQ_PROTECT
118     ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
119 #endif /* SA_LL_IBQ_PROTECT */
120     /* Get a free inbound queue entry */
121     circularQ = &saRoot->inboundQueue[inq];
122     retVal    = mpiMsgFreeGet(circularQ, IOMB_SIZE64, &pMessage);
123 
124     /* if message size is too large return failure */
125     if (AGSA_RC_FAILURE == retVal)
126     {
127 #ifdef SA_LL_IBQ_PROTECT
128       ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
129 #endif  /* SA_LL_IBQ_PROTECT */
130       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
131       /* remove the request from IOMap */
132       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
133       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
134       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
135       pRequest->valid = agFALSE;
136       /* return the request to free pool */
137       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
138       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
139 
140       SA_DBG1(("saFwProfile, error when get free IOMB\n"));
141       return AGSA_RC_FAILURE;
142     }
143 
144     /* return busy if inbound queue is full */
145     if (AGSA_RC_BUSY == retVal)
146     {
147 #ifdef SA_LL_IBQ_PROTECT
148       ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
149 #endif /* SA_LL_IBQ_PROTECT */
150 
151       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
152       /* remove the request from IOMap */
153       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
154       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
155       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
156       pRequest->valid = agFALSE;
157       /* return the request to free pool */
158       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
159       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
160       SA_DBG1(("saFwProfile, no more IOMB\n"));
161       return AGSA_RC_BUSY;
162     }
163 
164     pPayload = (agsaFwProfileIOMB_t *)pMessage;
165     tcid_processor_cmd = (((fwProfileInfo->tcid)<< 16) | ((fwProfileInfo->processor)<< 8) | fwProfileInfo->cmd);
166   /* Prepare the FW_FLASH_UPDATE IOMB payload */
167     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwProfileIOMB_t, tag), pRequest->HTag);
168     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwProfileIOMB_t, tcid_processor_cmd), tcid_processor_cmd);
169     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwProfileIOMB_t, codeStartAdd), fwProfileInfo->codeStartAdd);
170     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwProfileIOMB_t, codeEndAdd), fwProfileInfo->codeEndAdd);
171 
172     pPayload->SGLAL = fwProfileInfo->agSgl.sgLower;
173     pPayload->SGLAH = fwProfileInfo->agSgl.sgUpper;
174     pPayload->Len = fwProfileInfo->agSgl.len;
175     pPayload->extReserved = fwProfileInfo->agSgl.extReserved;
176 
177     /* fill up the reserved bytes with zero */
178     for (i = 0; i < FWPROFILE_IOMB_RESERVED_LEN; i ++)
179     {
180       pPayload->reserved0[i] = 0;
181     }
182 
183     /* post the IOMB to SPC */
184     ret = mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_FW_PROFILE, outq, (bit8)circularQ->priority);
185 
186 #ifdef SA_LL_IBQ_PROTECT
187     ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
188 #endif /* SA_LL_IBQ_PROTECT */
189 
190     if (AGSA_RC_FAILURE == ret)
191     {
192       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
193       /* remove the request from IOMap */
194       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
195       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
196       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
197       pRequest->valid = agFALSE;
198       /* return the request to free pool */
199       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
200       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
201       SA_DBG1(("saFwProfile, error when post FW_PROFILE IOMB\n"));
202     }
203   }
204   return ret;
205 }
206 #endif
207 /******************************************************************************/
208 /*! \brief SPC FW Flash Update Command
209  *
210  *  This command sends FW Flash Update Command to SPC.
211  *
212  *  \param agRoot          Handles for this instance of SAS/SATA LL
213  *  \param agContext       Context of SPC FW Flash Update Command
214  *  \param queueNum        Inbound/outbound queue number
215  *  \param flashUpdateInfo Pointer of flash update information
216  *
217  *  \return If the MPI command is sent to SPC successfully
218  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
219  *          - \e AGSA_RC_FAILURE the MPI command is failure
220  *
221  */
222 /*******************************************************************************/
223 GLOBAL bit32 saFwFlashUpdate(
224   agsaRoot_t                *agRoot,
225   agsaContext_t             *agContext,
226   bit32                     queueNum,
227   agsaUpdateFwFlash_t       *flashUpdateInfo
228   )
229 {
230   bit32 ret = AGSA_RC_SUCCESS, retVal;
231   agsaLLRoot_t        *saRoot;
232   agsaIORequestDesc_t *pRequest;
233   mpiICQueue_t        *circularQ;
234   void                *pMessage;
235   agsaFwFlashUpdate_t *pPayload;
236   bit8                inq, outq;
237   bit32               i;
238 
239   SA_ASSERT((agNULL != agRoot), "");
240   if (agRoot == agNULL)
241   {
242     SA_DBG1(("saFwFlashUpdate: agRoot == agNULL\n"));
243     return AGSA_RC_FAILURE;
244   }
245   saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
246   SA_ASSERT((agNULL != saRoot), "");
247   if (saRoot == agNULL)
248   {
249     SA_DBG1(("saFwFlashUpdate: saRoot == agNULL\n"));
250     return AGSA_RC_FAILURE;
251   }
252 
253 
254   smTraceFuncEnter(hpDBG_VERY_LOUD, "6a");
255   /* sanity check */
256   SA_ASSERT((agNULL != agRoot), "");
257   /* Get request from free IORequests */
258   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
259   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
260   /* If no LL Control request entry available */
261   if ( agNULL == pRequest ) {
262     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
263     SA_DBG1(("saFwFlashUpdate, No request from free list\n" ));
264     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6a");
265     return AGSA_RC_BUSY;
266   }
267   /* If LL Control request entry avaliable */
268   else
269   {
270     /* Assign inbound and outbound Ring Buffer */
271     inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
272     outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
273     SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
274     /* Remove the request from free list */
275     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
276     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
277     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
278     saRoot->IOMap[pRequest->HTag].agContext = agContext;
279     pRequest->valid = agTRUE;
280     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
281 #ifdef SA_LL_IBQ_PROTECT
282     ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
283 #endif /* SA_LL_IBQ_PROTECT */
284     /* Get a free inbound queue entry */
285     circularQ = &saRoot->inboundQueue[inq];
286     retVal    = mpiMsgFreeGet(circularQ, IOMB_SIZE64, &pMessage);
287     /* if message size is too large return failure */
288     if (AGSA_RC_FAILURE == retVal)
289     {
290 #ifdef SA_LL_IBQ_PROTECT
291       ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
292 #endif /* SA_LL_IBQ_PROTECT */
293       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
294       /* remove the request from IOMap */
295       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
296       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
297       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
298       pRequest->valid = agFALSE;
299       /* return the request to free pool */
300       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
301       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
302       SA_DBG1(("saFwFlashUpdate, error when get free IOMB\n"));
303       smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6a");
304       return AGSA_RC_FAILURE;
305     }
306     /* return busy if inbound queue is full */
307     if (AGSA_RC_BUSY == retVal)
308     {
309 #ifdef SA_LL_IBQ_PROTECT
310       ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
311 #endif /* SA_LL_IBQ_PROTECT */
312       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
313       /* remove the request from IOMap */
314       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
315       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
316       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
317       pRequest->valid = agFALSE;
318       /* return the request to free pool */
319       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
320       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
321       SA_DBG1(("saFwFlashUpdate, no more IOMB\n"));
322       smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "6a");
323       return AGSA_RC_BUSY;
324     }
325     pPayload = (agsaFwFlashUpdate_t *)pMessage;
326     /* Prepare the FW_FLASH_UPDATE IOMB payload */
327     OSSA_WRITE_LE_32( agRoot, pPayload,
328                       OSSA_OFFSET_OF(agsaFwFlashUpdate_t, tag), pRequest->HTag);
329     OSSA_WRITE_LE_32( agRoot, pPayload,
330                       OSSA_OFFSET_OF(agsaFwFlashUpdate_t, curImageOffset),
331                       flashUpdateInfo->currentImageOffset);
332     OSSA_WRITE_LE_32( agRoot, pPayload,
333                       OSSA_OFFSET_OF(agsaFwFlashUpdate_t, curImageLen),
334                       flashUpdateInfo->currentImageLen);
335     OSSA_WRITE_LE_32( agRoot, pPayload,
336                       OSSA_OFFSET_OF(agsaFwFlashUpdate_t, totalImageLen),
337                       flashUpdateInfo->totalImageLen);
338     pPayload->SGLAL = flashUpdateInfo->agSgl.sgLower;
339     pPayload->SGLAH = flashUpdateInfo->agSgl.sgUpper;
340     pPayload->Len   = flashUpdateInfo->agSgl.len;
341     pPayload->extReserved = flashUpdateInfo->agSgl.extReserved;
342     /* fill up the reserved bytes with zero */
343     for (i = 0; i < FWFLASH_IOMB_RESERVED_LEN; i ++) {
344       pPayload->reserved0[i] = 0;
345     }
346     /* post the IOMB to SPC */
347     ret = mpiMsgProduce( circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA,
348                          OPC_INB_FW_FLASH_UPDATE, outq, (bit8)circularQ->priority);
349 #ifdef SA_LL_IBQ_PROTECT
350     ossaSingleThreadedLeave( agRoot, LL_IOREQ_IBQ0_LOCK + inq );
351 #endif /* SA_LL_IBQ_PROTECT */
352     if (AGSA_RC_FAILURE == ret) {
353       ossaSingleThreadedEnter( agRoot, LL_IOREQ_LOCKEQ_LOCK );
354       /* remove the request from IOMap */
355       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
356       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
357       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
358       pRequest->valid = agFALSE;
359       /* return the request to free pool */
360       saLlistIOAdd( &(saRoot->freeIORequests), &(pRequest->linkNode) );
361       ossaSingleThreadedLeave( agRoot, LL_IOREQ_LOCKEQ_LOCK );
362       SA_DBG1( ("saFwFlashUpdate, error when post FW_FLASH_UPDATE IOMB\n") );
363     }
364   }
365   smTraceFuncExit( hpDBG_VERY_LOUD, 'd', "6a" );
366   return ret;
367 }
368 
369 
370 GLOBAL bit32 saFlashExtExecute (
371                   agsaRoot_t            *agRoot,
372                   agsaContext_t         *agContext,
373                   bit32                 queueNum,
374                   agsaFlashExtExecute_t *agFlashExtExe)
375 {
376 
377   bit32 ret           = AGSA_RC_SUCCESS, retVal;
378   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
379   agsaIORequestDesc_t *pRequest;
380   mpiICQueue_t        *circularQ;
381   void                *pMessage;
382   agsaFwFlashOpExt_t *pPayload;
383   bit8                inq, outq;
384 
385   smTraceFuncEnter(hpDBG_VERY_LOUD,"2R");
386 
387   /* sanity check */
388   SA_ASSERT((agNULL != agRoot), "");
389 
390   /* Get request from free IORequests */
391   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
392   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
393 
394   /* If no LL Control request entry available */
395   if ( agNULL == pRequest )
396   {
397     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
398     SA_DBG1(("saFlashExtExecute, No request from free list\n" ));
399     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2R");
400     return AGSA_RC_BUSY;
401   }
402   /* If LL Control request entry avaliable */
403   else
404   {
405     /* Assign inbound and outbound Ring Buffer */
406     inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
407     outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
408     SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
409 
410     /* Remove the request from free list */
411     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
412     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
413     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
414     saRoot->IOMap[pRequest->HTag].agContext = agContext;
415     pRequest->valid = agTRUE;
416     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
417 
418 #ifdef SA_LL_IBQ_PROTECT
419     ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
420 #endif /* SA_LL_IBQ_PROTECT */
421     /* Get a free inbound queue entry */
422     circularQ = &saRoot->inboundQueue[inq];
423     retVal    = mpiMsgFreeGet(circularQ, IOMB_SIZE64, &pMessage);
424 
425     /* if message size is too large return failure */
426     if (AGSA_RC_FAILURE == retVal)
427     {
428 #ifdef SA_LL_IBQ_PROTECT
429       ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
430 #endif   /* SA_LL_IBQ_PROTECT */
431       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
432       /* remove the request from IOMap */
433       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
434       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
435       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
436       pRequest->valid = agFALSE;
437       /* return the request to free pool */
438       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
439       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
440 
441       SA_DBG1(("saFlashExtExecute, error when get free IOMB\n"));
442       smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2R");
443       return AGSA_RC_FAILURE;
444     }
445 
446     /* return busy if inbound queue is full */
447     if (AGSA_RC_BUSY == retVal)
448     {
449 #ifdef SA_LL_IBQ_PROTECT
450       ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
451 #endif /* SA_LL_IBQ_PROTECT */
452       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
453       /* remove the request from IOMap */
454       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
455       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
456       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
457 
458       pRequest->valid = agFALSE;
459       /* return the request to free pool */
460       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
461       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
462 
463       SA_DBG3(("saFlashExtExecute, no more IOMB\n"));
464       smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2R");
465       return AGSA_RC_BUSY;
466     }
467 
468     pPayload = (agsaFwFlashOpExt_t *)pMessage;
469 
470     si_memset(pPayload, 0, sizeof(agsaFwFlashOpExt_t));
471 
472 
473     /* Prepare the FW_FLASH_UPDATE IOMB payload */
474     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwFlashOpExt_t, tag), pRequest->HTag);
475     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwFlashOpExt_t,Command ), agFlashExtExe->command);
476     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwFlashOpExt_t,PartOffset ), agFlashExtExe->partOffset);
477     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwFlashOpExt_t,DataLength ), agFlashExtExe->dataLen);
478     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwFlashOpExt_t,SGLAL ), agFlashExtExe->agSgl->sgLower);
479     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwFlashOpExt_t,SGLAH ), agFlashExtExe->agSgl->sgUpper);
480     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwFlashOpExt_t,Len ), agFlashExtExe->agSgl->len);
481     OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaFwFlashOpExt_t,E_sgl ), agFlashExtExe->agSgl->extReserved);
482 
483     /* post the IOMB to SPC */
484     ret = mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_FLASH_OP_EXT, outq, (bit8)circularQ->priority);
485 
486 #ifdef SA_LL_IBQ_PROTECT
487     ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
488 #endif /* SA_LL_IBQ_PROTECT */
489 
490 
491     if (AGSA_RC_FAILURE == ret)
492     {
493       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
494       /* remove the request from IOMap */
495       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
496       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
497       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
498       pRequest->valid = agFALSE;
499       /* return the request to free pool */
500       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
501       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
502       SA_DBG1(("saFlashExtExecute, error when post FW_FLASH_UPDATE IOMB\n"));
503     }
504   }
505   smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "2R");
506 
507   return ret;
508 
509 }
510 
511 
512 #ifdef SPC_ENABLE_PROFILE
513 /******************************************************************************/
514 /*! \brief SPC FW_PROFILE Respond
515  *
516  *  This command sends FW Profile Status to TD layer.
517  *
518  *  \param agRoot       Handles for this instance of SAS/SATA LL
519  *  \param payload      FW download response payload
520  *
521  *  \return If the MPI command is sent to SPC successfully
522  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
523  *          - \e AGSA_RC_FAILURE the MPI command is failure
524  *
525  */
526 /*******************************************************************************/
527 GLOBAL bit32 mpiFwProfileRsp(
528   agsaRoot_t             *agRoot,
529   agsaFwProfileRsp_t *payload
530   )
531 {
532   bit32               ret = AGSA_RC_SUCCESS;
533   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
534   agsaIORequestDesc_t *pRequest;
535   agsaContext_t       *agContext;
536 
537   bit32     status, tag, len;
538 
539   /* get request from IOMap */
540   OSSA_READ_LE_32(AGROOT, &tag, payload, OSSA_OFFSET_OF(agsaFwProfileRsp_t, tag));
541   OSSA_READ_LE_32(AGROOT, &status, payload, OSSA_OFFSET_OF(agsaFwProfileRsp_t, status));
542   OSSA_READ_LE_32(AGROOT, &len, payload, OSSA_OFFSET_OF(agsaFwProfileRsp_t, len));
543   pRequest = saRoot->IOMap[tag].IORequest;
544   if (agNULL == pRequest)
545   {
546     /* remove the request from IOMap */
547     saRoot->IOMap[tag].Tag = MARK_OFF;
548     saRoot->IOMap[tag].IORequest = agNULL;
549     SA_DBG1(("mpiFwProfileRsp: the request is NULL. Tag=%x\n", tag));
550     return AGSA_RC_FAILURE;
551   }
552   agContext = saRoot->IOMap[tag].agContext;
553   /* remove the request from IOMap */
554   saRoot->IOMap[tag].Tag = MARK_OFF;
555   saRoot->IOMap[tag].IORequest = agNULL;
556   saRoot->IOMap[tag].agContext = agNULL;
557   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
558 
559 
560   if(!pRequest->valid)
561   {
562     SA_DBG1(("mpiPortControlRsp: pRequest->valid %d not set\n", pRequest->valid));
563   }
564 
565   SA_ASSERT((pRequest->valid), "pRequest->valid");
566 
567   pRequest->valid = agFALSE;
568   /* return the request to free pool */
569   saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
570   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
571 
572   ossaFwProfileCB(agRoot, agContext, status, len);
573 
574  return ret;
575 }
576 #endif
577 /******************************************************************************/
578 /*! \brief SPC FW_FLASH_UPDATE Respond
579  *
580  *  This command sends FW Flash Update Status to TD layer.
581  *
582  *  \param agRoot       Handles for this instance of SAS/SATA LL
583  *  \param payload      FW download response payload
584  *
585  *  \return If the MPI command is sent to SPC successfully
586  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
587  *          - \e AGSA_RC_FAILURE the MPI command is failure
588  *
589  */
590 /*******************************************************************************/
591 GLOBAL bit32 mpiFwFlashUpdateRsp(
592   agsaRoot_t             *agRoot,
593   agsaFwFlashUpdateRsp_t *payload
594   )
595 {
596   bit32               ret = AGSA_RC_SUCCESS;
597   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
598   agsaIORequestDesc_t *pRequest;
599   agsaContext_t       *agContext;
600 
601   bit32     status, tag;
602   smTraceFuncEnter(hpDBG_VERY_LOUD,"6b");
603 
604   /* get request from IOMap */
605   OSSA_READ_LE_32(AGROOT, &tag, payload, OSSA_OFFSET_OF(agsaFwFlashUpdateRsp_t, tag));
606   OSSA_READ_LE_32(AGROOT, &status, payload, OSSA_OFFSET_OF(agsaFwFlashUpdateRsp_t, status));
607   pRequest = saRoot->IOMap[tag].IORequest;
608   agContext = saRoot->IOMap[tag].agContext;
609   /* remove the request from IOMap */
610   saRoot->IOMap[tag].Tag = MARK_OFF;
611   saRoot->IOMap[tag].IORequest = agNULL;
612   saRoot->IOMap[tag].agContext = agNULL;
613   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
614   SA_ASSERT((pRequest->valid), "pRequest->valid");
615   pRequest->valid = agFALSE;
616   /* return the request to free pool */
617   if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
618   {
619     SA_DBG1(("mpiFwFlashUpdateRsp: saving pRequest (%p) for later use\n", pRequest));
620     saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
621   }
622   else
623   {
624     /* return the request to free pool */
625     saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
626   }
627   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
628 
629   if(status > 1)
630   {
631     SA_DBG1(("mpiFwFlashUpdateRsp: status = 0x%x\n",status));
632   }
633 
634   ossaFwFlashUpdateCB(agRoot, agContext, status);
635 
636   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6b");
637 
638   return ret;
639 }
640 
641 GLOBAL bit32 mpiFwExtFlashUpdateRsp(
642   agsaRoot_t             *agRoot,
643   agsaFwFlashOpExtRsp_t *payload
644   )
645 {
646   bit32               ret = AGSA_RC_SUCCESS;
647   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
648   agsaIORequestDesc_t *pRequest;
649   agsaContext_t       *agContext;
650 
651   agsaFlashExtResponse_t FlashExtRsp;
652 
653   bit32     Command,Status, tag;
654   smTraceFuncEnter(hpDBG_VERY_LOUD,"2T");
655 
656   /* get request from IOMap */
657   OSSA_READ_LE_32(AGROOT, &tag, payload, OSSA_OFFSET_OF(agsaFwFlashOpExtRsp_t, tag));
658   OSSA_READ_LE_32(AGROOT, &Command, payload, OSSA_OFFSET_OF(agsaFwFlashOpExtRsp_t,Command ));
659   OSSA_READ_LE_32(AGROOT, &Status, payload, OSSA_OFFSET_OF(agsaFwFlashOpExtRsp_t,Status ));
660   OSSA_READ_LE_32(AGROOT, &FlashExtRsp.epart_sect_size, payload, OSSA_OFFSET_OF(agsaFwFlashOpExtRsp_t,Epart_Size ));
661   OSSA_READ_LE_32(AGROOT, &FlashExtRsp.epart_size, payload, OSSA_OFFSET_OF(agsaFwFlashOpExtRsp_t,EpartSectSize ));
662 
663   pRequest = saRoot->IOMap[tag].IORequest;
664   agContext = saRoot->IOMap[tag].agContext;
665   /* remove the request from IOMap */
666   saRoot->IOMap[tag].Tag = MARK_OFF;
667   saRoot->IOMap[tag].IORequest = agNULL;
668   saRoot->IOMap[tag].agContext = agNULL;
669   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
670   SA_ASSERT((pRequest->valid), "pRequest->valid");
671   pRequest->valid = agFALSE;
672   /* return the request to free pool */
673   if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
674   {
675     SA_DBG1(("mpiFwExtFlashUpdateRsp: saving pRequest (%p) for later use\n", pRequest));
676     saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
677   }
678   else
679   {
680     /* return the request to free pool */
681     saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
682   }
683   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
684 
685   if(Status > 1)
686   {
687     SA_DBG1(("mpiFwExtFlashUpdateRsp: status = 0x%x\n",Status));
688   }
689 
690   ossaFlashExtExecuteCB(agRoot, agContext, Status,Command,&FlashExtRsp);
691 
692   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2T");
693 
694   return ret;
695 
696 }
697 
698 
699 /******************************************************************************/
700 /*! \brief SPC Get Controller Information Command
701  *
702  *  This command sends Get Controller Information Command to SPC.
703  *
704  *  \param agRoot         Handles for this instance of SAS/SATA LL
705  *  \param controllerInfo Controller Information
706  *
707  *  \return If the MPI command is sent to SPC successfully
708  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
709  *          - \e AGSA_RC_FAILURE the MPI command is failure
710  *
711  */
712 /*******************************************************************************/
713 
714 GLOBAL bit32 saGetControllerInfo(
715                         agsaRoot_t                *agRoot,
716                         agsaControllerInfo_t      *controllerInfo
717                         )
718 {
719 
720   bit32     ret = AGSA_RC_SUCCESS;
721   bit32     max_wait_time;
722   bit32     max_wait_count;
723   bit32     ContrlCapFlag, MSGUCfgTblBase, CfgTblDWIdx;
724   bit32     value = 0, value1 = 0;
725   bit8      pcibar;
726 
727   if (agNULL != agRoot->sdkData)
728   {
729     smTraceFuncEnter(hpDBG_VERY_LOUD,"6e");
730   }
731   /* clean the structure */
732   si_memset(controllerInfo, 0, sizeof(agsaControllerInfo_t));
733 
734   if(smIS_SPC6V(agRoot))
735   {
736     controllerInfo->sdkInterfaceRev = STSDK_LL_INTERFACE_VERSION;
737     controllerInfo->sdkRevision     = STSDK_LL_VERSION;
738     controllerInfo->hwRevision = (ossaHwRegReadConfig32(agRoot,8) & 0xFF);
739   }else  if(smIS_SPC12V(agRoot))
740   {
741     controllerInfo->sdkInterfaceRev = STSDK_LL_12G_INTERFACE_VERSION;
742     controllerInfo->sdkRevision     = STSDK_LL_12G_VERSION;
743     controllerInfo->hwRevision = (ossaHwRegReadConfig32(agRoot,8) & 0xFF);
744   } else if(smIS_SPC(agRoot))
745   {
746     controllerInfo->hwRevision = SPC_READ_DEV_REV;
747     controllerInfo->sdkInterfaceRev = MATCHING_SPC_FW_VERSION;
748     controllerInfo->sdkRevision     = STSDK_LL_SPC_VERSION;
749   }
750   else
751   {
752     controllerInfo->hwRevision = (ossaHwRegReadConfig32(agRoot,8) & 0xFF);
753   }
754 
755   SA_DBG1(("saGetControllerInfo: SCRATCH_PAD0 value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_0,  MSGU_SCRATCH_PAD_0)));
756   SA_DBG1(("saGetControllerInfo: SCRATCH_PAD1 value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1)));
757   SA_DBG1(("saGetControllerInfo: SCRATCH_PAD2 value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_2,  MSGU_SCRATCH_PAD_2)));
758   SA_DBG1(("saGetControllerInfo: SCRATCH_PAD3 value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_3,  MSGU_SCRATCH_PAD_3)));
759   SA_DBG1(("saGetControllerInfo: SCRATCH_PAD3 value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_3,  MSGU_SCRATCH_PAD_3)));
760 
761   if(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_0,  MSGU_SCRATCH_PAD_0) == 0xFFFFFFFF)
762   {
763     SA_DBG1(("saGetControllerInfo:AGSA_RC_FAILURE SCRATCH_PAD0 value = 0x%x\n",
764             siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_0,  MSGU_SCRATCH_PAD_0) ) );
765     return AGSA_RC_FAILURE;
766   }
767 
768   if(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_0,  MSGU_SCRATCH_PAD_0) == 0xFFFFFFFF)
769   {
770     SA_DBG1(("saGetControllerInfo:AGSA_RC_FAILURE SCRATCH_PAD0 value = 0x%x\n",
771             siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_0,  MSGU_SCRATCH_PAD_0) ) );
772     return AGSA_RC_FAILURE;
773   }
774 
775   if( SCRATCH_PAD1_V_ERROR_STATE(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1)) )
776   {
777     SA_DBG1(("saGetControllerInfo: SCRATCH_PAD1 (0x%x) in error state ila %d raae %d Iop0 %d Iop1 %d\n",
778       siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1),
779     ( SCRATCH_PAD1_V_ILA_ERROR_STATE(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1, MSGU_SCRATCH_PAD_1)) ? 1 : 0),
780     ( SCRATCH_PAD1_V_RAAE_ERROR_STATE(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,MSGU_SCRATCH_PAD_1)) ? 1 : 0),
781     ( SCRATCH_PAD1_V_IOP0_ERROR_STATE(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,MSGU_SCRATCH_PAD_1)) ? 1 : 0),
782     ( SCRATCH_PAD1_V_IOP1_ERROR_STATE(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,MSGU_SCRATCH_PAD_1)) ? 1 : 0) ));
783 
784   }
785 
786   if(smIS_SPC(agRoot))
787   {
788     /* check HDA mode */
789     value = ossaHwRegReadExt(agRoot, PCIBAR3, HDA_RSP_OFFSET1MB+HDA_CMD_CODE_OFFSET) & HDA_STATUS_BITS;
790 
791     if (value == BOOTTLOADERHDA_IDLE)
792     {
793       /* HDA mode */
794       SA_DBG1(("saGetControllerInfo: HDA mode, value = 0x%x\n", value));
795       return AGSA_RC_HDA_NO_FW_RUNNING;
796     }
797   }
798   else
799   {
800     if(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1) &   SCRATCH_PAD1_V_RESERVED )
801     {
802       SA_DBG1(("saGetControllerInfo: Warning SCRATCH_PAD1 reserved bits set value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1)));
803     }
804     if( si_check_V_HDA(agRoot))
805     {
806       /*  Check HDA */
807       SA_DBG1(("saGetControllerInfo: HDA mode AGSA_RC_HDA_NO_FW_RUNNING\n" ));
808       return AGSA_RC_HDA_NO_FW_RUNNING;
809     }
810 
811 
812   }
813 
814   /* checking the fw AAP and IOP in ready state */
815   max_wait_time = WAIT_SECONDS(gWait_2);  /* 2 sec timeout */
816   max_wait_count = MAKE_MODULO(max_wait_time,WAIT_INCREMENT);
817   /* wait until scratch pad 1 and 2 registers in ready state  */
818   if(smIS_SPCV(agRoot))
819   {
820     do
821     {
822       ossaStallThread(agRoot, WAIT_INCREMENT);
823       value = siHalRegReadExt(agRoot, GEN_MSGU_SCRATCH_PAD_1, MSGU_SCRATCH_PAD_1);
824       value1 =siHalRegReadExt(agRoot, GEN_MSGU_SCRATCH_PAD_2, MSGU_SCRATCH_PAD_2);
825       if(smIS_SPCV(agRoot))
826       {
827         if((value & SCRATCH_PAD1_V_RESERVED) )
828         {
829           SA_DBG1(("saGetControllerInfo: V reserved SCRATCH_PAD1 value = 0x%x (0x%x)\n", value, SCRATCH_PAD1_V_RESERVED));
830           ret = AGSA_RC_FW_NOT_IN_READY_STATE;
831           break;
832         }
833       }
834 
835       if ((max_wait_count -= WAIT_INCREMENT) == 0)
836       {
837         SA_DBG1(("saGetControllerInfo:  timeout SCRATCH_PAD1_V_READY !! SCRATCH_PAD1/2 value = 0x%x 0x%x\n", value, value1));
838         break;
839       }
840 
841     } while (((value & SCRATCH_PAD1_V_READY) != SCRATCH_PAD1_V_READY) || (value == 0xffffffff));
842 
843   }
844   else
845   {
846     do
847     {
848       ossaStallThread(agRoot, WAIT_INCREMENT);
849       value = siHalRegReadExt(agRoot, GEN_MSGU_SCRATCH_PAD_1, MSGU_SCRATCH_PAD_1);
850       /* checking bit 4 to 7 for reserved in case we get 0xFFFFFFFF */
851       if (value & SCRATCH_PAD1_RESERVED)
852       {
853         SA_DBG1(("saGetControllerInfo: SCRATCH_PAD1 value = 0x%x\n", value));
854         ret = AGSA_RC_FW_NOT_IN_READY_STATE;
855         break;
856       }
857       value1 =siHalRegReadExt(agRoot, GEN_MSGU_SCRATCH_PAD_2,MSGU_SCRATCH_PAD_2);
858       /* checking bit 4 to 7 for reserved in case we get 0xFFFFFFFF */
859       if (value1 & SCRATCH_PAD2_RESERVED)
860       {
861         SA_DBG1(("saGetControllerInfo: SCRATCH_PAD2 value = 0x%x\n", value1));
862         ret = AGSA_RC_FW_NOT_IN_READY_STATE;
863         break;
864       }
865       if ((max_wait_count -= WAIT_INCREMENT) == 0)
866       {
867         SA_DBG1(("saGetControllerInfo: Timeout!! SCRATCH_PAD1/2 value = 0x%x 0x%x\n", value, value1));
868         break;
869       }
870     } while (((value & SCRATCH_PAD_STATE_MASK) != SCRATCH_PAD1_RDY) || ((value1 & SCRATCH_PAD_STATE_MASK) != SCRATCH_PAD2_RDY));
871   }
872 
873   if (!max_wait_count)
874   {
875     SA_DBG1(("saGetControllerInfo: timeout failure\n"));
876     ret = AGSA_RC_FW_NOT_IN_READY_STATE;
877   }
878 
879   if (ret == AGSA_RC_SUCCESS)
880   {
881     SA_DBG1(("saGetControllerInfo: FW Ready, SCRATCH_PAD1/2 value = 0x%x 0x%x\n", value, value1));
882 
883     /* read scratch pad0 to get PCI BAR and offset of configuration table */
884      MSGUCfgTblBase = siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_0,  MSGU_SCRATCH_PAD_0);
885     /* get offset */
886     CfgTblDWIdx = MSGUCfgTblBase & SCRATCH_PAD0_OFFSET_MASK;
887     /* get PCI BAR */
888     MSGUCfgTblBase = (MSGUCfgTblBase & SCRATCH_PAD0_BAR_MASK) >> SHIFT26;
889 
890     /* convert the PCI BAR to logical bar number */
891     pcibar = (bit8)mpiGetPCIBarIndex(agRoot, MSGUCfgTblBase);
892 
893     /* get controller information */
894     controllerInfo->signature =         ossaHwRegReadExt(agRoot, pcibar, (bit32)CfgTblDWIdx);
895     controllerInfo->fwInterfaceRev =    ossaHwRegReadExt(agRoot, pcibar, (bit32)CfgTblDWIdx + MAIN_INTERFACE_REVISION);
896     controllerInfo->fwRevision =        ossaHwRegReadExt(agRoot, pcibar, (bit32)CfgTblDWIdx + MAIN_FW_REVISION);
897     controllerInfo->ilaRevision =       ossaHwRegReadExt(agRoot, pcibar, (bit32)CfgTblDWIdx + MAIN_ILAT_ILAV_ILASMRN_ILAMRN_ILAMJN);
898     controllerInfo->maxPendingIO =      ossaHwRegReadExt(agRoot, pcibar, (bit32)CfgTblDWIdx + MAIN_MAX_OUTSTANDING_IO_OFFSET);
899     controllerInfo->maxDevices =       (ossaHwRegReadExt(agRoot, pcibar, (bit32)CfgTblDWIdx + MAIN_MAX_SGL_OFFSET) & MAIN_MAX_DEV_BITS);
900     controllerInfo->maxDevices =        controllerInfo->maxDevices >> SHIFT16;
901     controllerInfo->maxSgElements =    (ossaHwRegReadExt(agRoot, pcibar, (bit32)CfgTblDWIdx + MAIN_MAX_SGL_OFFSET) & MAIN_MAX_SGL_BITS);
902 
903     if( smIS_SPC(agRoot))
904     {
905       SA_DBG2(("saGetControllerInfo: LINK_CTRL 0x%08x Speed 0x%X Lanes 0x%X \n", ossaHwRegReadConfig32(agRoot,128),
906         ((ossaHwRegReadConfig32(agRoot,128) & 0x000F0000) >> 16),
907         ((ossaHwRegReadConfig32(agRoot,128) & 0x0FF00000) >> 20) ));
908       controllerInfo->PCILinkRate =  ((ossaHwRegReadConfig32(agRoot,128) & 0x000F0000) >> 16);
909       controllerInfo->PCIWidth =   ((ossaHwRegReadConfig32(agRoot,128) & 0x0FF00000) >> 20);
910     }
911     else
912     {
913       SA_DBG2(("saGetControllerInfo: LINK_CTRL 0x%08x Speed 0x%X Lanes 0x%X \n", ossaHwRegReadConfig32(agRoot,208),
914         ((ossaHwRegReadConfig32(agRoot,208) & 0x000F0000) >> 16),
915         ((ossaHwRegReadConfig32(agRoot,208) & 0x0FF00000) >> 20) ));
916       controllerInfo->PCILinkRate =  ((ossaHwRegReadConfig32(agRoot,208) & 0x000F0000) >> 16);
917       controllerInfo->PCIWidth =   ((ossaHwRegReadConfig32(agRoot,208) & 0x0FF00000) >> 20);
918     }
919 
920 
921     ContrlCapFlag =                     ossaHwRegReadExt(agRoot, pcibar, (bit32)CfgTblDWIdx + MAIN_CNTRL_CAP_OFFSET);
922     controllerInfo->queueSupport =      ContrlCapFlag & MAIN_QSUPPORT_BITS;
923     controllerInfo->phyCount =         (bit8)((ContrlCapFlag & MAIN_PHY_COUNT_MASK) >> SHIFT19);
924 
925 
926     if(smIS_SPCV(agRoot))
927     {
928       controllerInfo->controllerSetting = (bit8)((siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1) & SCRATCH_PAD1_V_BOOTSTATE_MASK ) >> SHIFT4);
929     }
930     else
931     {
932       controllerInfo->controllerSetting = (bit8)(ossaHwRegReadExt(agRoot, pcibar, (bit32)CfgTblDWIdx + MAIN_HDA_FLAGS_OFFSET) & MAIN_HDA_FLAG_BITS);
933     }
934     controllerInfo->sasSpecsSupport =   (ContrlCapFlag & MAIN_SAS_SUPPORT_BITS) >> SHIFT25;
935   }
936 
937   SA_DBG1(("saGetControllerInfo: signature         0x%X\n", controllerInfo->signature));
938   SA_DBG1(("saGetControllerInfo: fwInterfaceRev    0x%X\n", controllerInfo->fwInterfaceRev));
939   SA_DBG1(("saGetControllerInfo: hwRevision        0x%X\n", controllerInfo->hwRevision));
940   SA_DBG1(("saGetControllerInfo: fwRevision        0x%X\n", controllerInfo->fwRevision));
941   SA_DBG1(("saGetControllerInfo: ilaRevision       0x%X\n", controllerInfo->ilaRevision));
942   SA_DBG1(("saGetControllerInfo: maxPendingIO      0x%X\n", controllerInfo->maxPendingIO));
943   SA_DBG1(("saGetControllerInfo: maxDevices        0x%X\n", controllerInfo->maxDevices));
944   SA_DBG1(("saGetControllerInfo: maxSgElements     0x%X\n", controllerInfo->maxSgElements));
945   SA_DBG1(("saGetControllerInfo: queueSupport      0x%X\n", controllerInfo->queueSupport));
946   SA_DBG1(("saGetControllerInfo: phyCount          0x%X\n", controllerInfo->phyCount));
947   SA_DBG1(("saGetControllerInfo: controllerSetting 0x%X\n", controllerInfo->controllerSetting));
948   SA_DBG1(("saGetControllerInfo: PCILinkRate       0x%X\n", controllerInfo->PCILinkRate));
949   SA_DBG1(("saGetControllerInfo: PCIWidth          0x%X\n", controllerInfo->PCIWidth));
950   SA_DBG1(("saGetControllerInfo: sasSpecsSupport   0x%X\n", controllerInfo->sasSpecsSupport));
951   SA_DBG1(("saGetControllerInfo: sdkInterfaceRev   0x%X\n", controllerInfo->sdkInterfaceRev));
952   SA_DBG1(("saGetControllerInfo: sdkRevision       0x%X\n", controllerInfo->sdkRevision));
953   if (agNULL != agRoot->sdkData)
954   {
955     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6e");
956   }
957   return ret;
958 }
959 
960 /******************************************************************************/
961 /*! \brief SPC Get Controller Status Command
962  *
963  *  This command sends Get Controller Status Command to SPC.
964  *
965  *  \param agRoot           Handles for this instance of SAS/SATA LL
966  *  \param controllerStatus controller status
967  *
968  *  \return If the MPI command is sent to SPC successfully
969  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
970  *          - \e AGSA_RC_FAILURE the MPI command is failure
971  *
972  */
973 /*******************************************************************************/
974 GLOBAL bit32 saGetControllerStatus(
975                         agsaRoot_t                *agRoot,
976                         agsaControllerStatus_t    *controllerStatus
977                         )
978 {
979   bit32 ret = AGSA_RC_SUCCESS;
980   agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
981   spc_GSTableDescriptor_t GSTable;
982   bit32 max_wait_time;
983   bit32 max_wait_count;
984   bit32 i, value, value1;
985 
986   if (agNULL != saRoot)
987   {
988     smTraceFuncEnter(hpDBG_VERY_LOUD,"6f");
989   }
990   /* clean the structure */
991   si_memset(controllerStatus, 0, sizeof(agsaControllerStatus_t));
992   si_memset(&GSTable, 0, sizeof(spc_GSTableDescriptor_t));
993   if(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_0,  MSGU_SCRATCH_PAD_0) == 0xFFFFFFFF)
994   {
995     SA_DBG1(("saGetControllerStatus:AGSA_RC_FAILURE SCRATCH_PAD0 value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_0,  MSGU_SCRATCH_PAD_0)));
996     return AGSA_RC_FAILURE;
997   }
998 
999   if(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_3)  & (OSSA_ENCRYPT_ENGINE_FAILURE_MASK | OSSA_DIF_ENGINE_FAILURE_MASK))
1000   {
1001     SA_DBG1(("saGetControllerStatus: BIST error in SCRATCHPAD 3 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_3,  MSGU_SCRATCH_PAD_3)));
1002   }
1003 
1004   if(smIS_SPC(agRoot))
1005   {
1006 
1007     /* read detail fatal errors */
1008     controllerStatus->fatalErrorInfo.errorInfo0 = ossaHwRegRead(agRoot, MSGU_SCRATCH_PAD_0);
1009     controllerStatus->fatalErrorInfo.errorInfo1 = ossaHwRegRead(agRoot, MSGU_SCRATCH_PAD_1);
1010     controllerStatus->fatalErrorInfo.errorInfo2 = ossaHwRegRead(agRoot, MSGU_SCRATCH_PAD_2);
1011     controllerStatus->fatalErrorInfo.errorInfo3 = ossaHwRegRead(agRoot, MSGU_SCRATCH_PAD_3);
1012 
1013 #if defined(SALLSDK_DEBUG)
1014     SA_DBG1(("saGetControllerStatus: SCRATCH_PAD0 value = 0x%x\n", controllerStatus->fatalErrorInfo.errorInfo0));
1015     SA_DBG1(("saGetControllerStatus: SCRATCH_PAD1 value = 0x%x\n", controllerStatus->fatalErrorInfo.errorInfo1));
1016     SA_DBG1(("saGetControllerStatus: SCRATCH_PAD2 value = 0x%x\n", controllerStatus->fatalErrorInfo.errorInfo2));
1017     SA_DBG1(("saGetControllerStatus: SCRATCH_PAD3 value = 0x%x\n", controllerStatus->fatalErrorInfo.errorInfo3));
1018 #endif
1019 
1020     /* check HDA mode */
1021     value = ossaHwRegReadExt(agRoot, PCIBAR3, HDA_RSP_OFFSET1MB+HDA_CMD_CODE_OFFSET) & HDA_STATUS_BITS;
1022 
1023     if (value == BOOTTLOADERHDA_IDLE)
1024     {
1025       /* HDA mode */
1026       SA_DBG1(("saGetControllerStatus: HDA mode, value = 0x%x\n", value));
1027       return AGSA_RC_HDA_NO_FW_RUNNING;
1028     }
1029 
1030     /* check error state */
1031     value = ossaHwRegRead(agRoot, MSGU_SCRATCH_PAD_1);
1032     value1 = ossaHwRegRead(agRoot, MSGU_SCRATCH_PAD_2);
1033 
1034     /* check AAP or IOP error */
1035     if ((SCRATCH_PAD1_ERR == (value & SCRATCH_PAD_STATE_MASK)) || (SCRATCH_PAD2_ERR == (value1 & SCRATCH_PAD_STATE_MASK)))
1036     {
1037       if (agNULL != saRoot)
1038       {
1039         controllerStatus->fatalErrorInfo.regDumpBusBaseNum0 = saRoot->mainConfigTable.regDumpPCIBAR;
1040         controllerStatus->fatalErrorInfo.regDumpOffset0 = saRoot->mainConfigTable.FatalErrorDumpOffset0;
1041         controllerStatus->fatalErrorInfo.regDumpLen0 = saRoot->mainConfigTable.FatalErrorDumpLength0;
1042         controllerStatus->fatalErrorInfo.regDumpBusBaseNum1 = saRoot->mainConfigTable.regDumpPCIBAR;
1043         controllerStatus->fatalErrorInfo.regDumpOffset1 = saRoot->mainConfigTable.FatalErrorDumpOffset1;
1044         controllerStatus->fatalErrorInfo.regDumpLen1 = saRoot->mainConfigTable.FatalErrorDumpLength1;
1045       }
1046       else
1047       {
1048         controllerStatus->fatalErrorInfo.regDumpBusBaseNum0 = 0;
1049         controllerStatus->fatalErrorInfo.regDumpOffset0 = 0;
1050         controllerStatus->fatalErrorInfo.regDumpLen0 = 0;
1051         controllerStatus->fatalErrorInfo.regDumpBusBaseNum1 = 0;
1052         controllerStatus->fatalErrorInfo.regDumpOffset1 = 0;
1053         controllerStatus->fatalErrorInfo.regDumpLen1 = 0;
1054       }
1055 
1056       if (agNULL != saRoot)
1057       {
1058         smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6f");
1059       }
1060       return AGSA_RC_FW_NOT_IN_READY_STATE;
1061     }
1062 
1063     /* checking the fw AAP and IOP in ready state */
1064     max_wait_time = WAIT_SECONDS(2);  /* 2 sec timeout */
1065     max_wait_count = MAKE_MODULO(max_wait_time,WAIT_INCREMENT);
1066     /* wait until scratch pad 1 and 2 registers in ready state  */
1067     do
1068     {
1069       ossaStallThread(agRoot, WAIT_INCREMENT);
1070       value = ossaHwRegRead(agRoot, MSGU_SCRATCH_PAD_1);
1071       /* checking bit 4 to 7 for reserved in case we get 0xFFFFFFFF */
1072       if (value & SCRATCH_PAD1_RESERVED)
1073       {
1074         SA_DBG1(("saGetControllerStatus: (Reserved bit not 0) SCRATCH_PAD1 value = 0x%x\n", value));
1075         ret = AGSA_RC_FAILURE;
1076         break;
1077       }
1078 
1079       value1 = ossaHwRegRead(agRoot, MSGU_SCRATCH_PAD_2);
1080       /* checking bit 4 to 7 for reserved in case we get 0xFFFFFFFF */
1081       if (value1 & SCRATCH_PAD2_RESERVED)
1082       {
1083         SA_DBG1(("saGetControllerStatus: (Reserved bit not 0) SCRATCH_PAD2 value = 0x%x\n", value1));
1084         ret = AGSA_RC_FAILURE;
1085         break;
1086       }
1087 
1088       if ((max_wait_count -=WAIT_INCREMENT) == 0)
1089       {
1090         SA_DBG1(("saGetControllerStatus: Timeout!! SCRATCH_PAD1/2 value = 0x%x 0x%x\n", value, value1));
1091         break;
1092       }
1093     } while (((value & SCRATCH_PAD_STATE_MASK) != SCRATCH_PAD1_RDY) || ((value1 & SCRATCH_PAD_STATE_MASK) != SCRATCH_PAD2_RDY));
1094 
1095     if (!max_wait_count)
1096     {
1097       SA_DBG1(("saGetControllerStatus: timeout failure\n"));
1098       ret = AGSA_RC_FAILURE;
1099     }
1100 
1101     if (ret == AGSA_RC_SUCCESS)
1102     {
1103       SA_DBG1(("saGetControllerStatus: FW Ready, SCRATCH_PAD1/2 value = 0x%x 0x%x\n", value, value1));
1104 
1105       /* read scratch pad0 to get PCI BAR and offset of configuration table */
1106       value = ossaHwRegRead(agRoot, MSGU_SCRATCH_PAD_0);
1107       /* get offset */
1108       value1 = value & SCRATCH_PAD0_OFFSET_MASK;
1109       /* get PCI BAR */
1110       value = (value & SCRATCH_PAD0_BAR_MASK) >> SHIFT26;
1111 
1112       /* read GST Table state */
1113       mpiReadGSTable(agRoot, &GSTable);
1114 
1115       /* read register dump information */
1116       controllerStatus->fatalErrorInfo.regDumpBusBaseNum0 = value;
1117       controllerStatus->fatalErrorInfo.regDumpBusBaseNum1 = value;
1118       /* convert the PCI BAR to logical bar number */
1119       value = (bit8)mpiGetPCIBarIndex(agRoot, value);
1120       controllerStatus->fatalErrorInfo.regDumpOffset0 = ossaHwRegReadExt(agRoot, value, value1 + MAIN_FATAL_ERROR_RDUMP0_OFFSET);
1121       controllerStatus->fatalErrorInfo.regDumpLen0    = ossaHwRegReadExt(agRoot, value, value1 + MAIN_FATAL_ERROR_RDUMP0_LENGTH);
1122       controllerStatus->fatalErrorInfo.regDumpOffset1 = ossaHwRegReadExt(agRoot, value, value1 + MAIN_FATAL_ERROR_RDUMP1_OFFSET);
1123       controllerStatus->fatalErrorInfo.regDumpLen1    = ossaHwRegReadExt(agRoot, value, value1 + MAIN_FATAL_ERROR_RDUMP1_LENGTH);
1124 
1125       /* AAP/IOP error state */
1126       SA_DBG2(("saGetControllerStatus: SCRATCH PAD0 0x%x\n", controllerStatus->fatalErrorInfo.errorInfo0));
1127       SA_DBG2(("saGetControllerStatus: SCRATCH PAD1 0x%x\n", controllerStatus->fatalErrorInfo.errorInfo1));
1128       SA_DBG2(("saGetControllerStatus: SCRATCH PAD2 0x%x\n", controllerStatus->fatalErrorInfo.errorInfo2));
1129       SA_DBG2(("saGetControllerStatus: SCRATCH PAD3 0x%x\n", controllerStatus->fatalErrorInfo.errorInfo3));
1130       /* Register Dump information */
1131       SA_DBG2(("saGetControllerStatus: RegDumpOffset0 0x%x\n", controllerStatus->fatalErrorInfo.regDumpOffset0));
1132       SA_DBG2(("saGetControllerStatus: RegDumpLen0    0x%x\n", controllerStatus->fatalErrorInfo.regDumpLen0));
1133       SA_DBG2(("saGetControllerStatus: RegDumpOffset1 0x%x\n", controllerStatus->fatalErrorInfo.regDumpOffset1));
1134       SA_DBG2(("saGetControllerStatus: RegDumpLen1    0x%x\n", controllerStatus->fatalErrorInfo.regDumpLen1));
1135 
1136       controllerStatus->interfaceState = GSTable.GSTLenMPIS & GST_INF_STATE_BITS;
1137       controllerStatus->iqFreezeState0 = GSTable.IQFreezeState0;
1138       controllerStatus->iqFreezeState1 = GSTable.IQFreezeState1;
1139       for (i = 0; i < 8; i++)
1140       {
1141         controllerStatus->phyStatus[i] = GSTable.PhyState[i];
1142         controllerStatus->recoverableErrorInfo[i] = GSTable.recoverErrInfo[i];
1143       }
1144       controllerStatus->tickCount0 = GSTable.MsguTcnt;
1145       controllerStatus->tickCount1 = GSTable.IopTcnt;
1146       controllerStatus->tickCount2 = GSTable.Iop1Tcnt;
1147     }
1148   }
1149   else
1150   {
1151 
1152     SA_DBG1(("saGetControllerStatus: SPCv\n" ));
1153 
1154 
1155     if(siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1) &   SCRATCH_PAD1_V_RESERVED )
1156     {
1157       SA_DBG1(("saGetControllerStatus: Warning SCRATCH_PAD1 reserved bits set value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1)));
1158     }
1159     if( si_check_V_HDA(agRoot))
1160     {
1161       /*  Check HDA */
1162 
1163       controllerStatus->fatalErrorInfo.errorInfo0 = ossaHwRegRead(agRoot,V_Scratchpad_0_Register );
1164       controllerStatus->fatalErrorInfo.errorInfo1 = ossaHwRegRead(agRoot,V_Scratchpad_1_Register );
1165       controllerStatus->fatalErrorInfo.errorInfo2 = ossaHwRegRead(agRoot,V_Scratchpad_2_Register );
1166       controllerStatus->fatalErrorInfo.errorInfo3 = ossaHwRegRead(agRoot,V_Scratchpad_3_Register );
1167       SA_DBG1(("saGetControllerStatus: HDA mode, AGSA_RC_HDA_NO_FW_RUNNING errorInfo1  = 0x%x\n",controllerStatus->fatalErrorInfo.errorInfo1 ));
1168       return AGSA_RC_HDA_NO_FW_RUNNING;
1169     }
1170 
1171     ret = si_check_V_Ready(agRoot);
1172     /* Check ready */
1173     if (ret == AGSA_RC_SUCCESS)
1174     {
1175       /* read GST Table state */
1176       mpiReadGSTable(agRoot, &GSTable);
1177       controllerStatus->interfaceState = GSTable.GSTLenMPIS & GST_INF_STATE_BITS;
1178       controllerStatus->iqFreezeState0 = GSTable.IQFreezeState0;
1179       controllerStatus->iqFreezeState1 = GSTable.IQFreezeState1;
1180       for (i = 0; i < 8; i++)
1181       {
1182         controllerStatus->phyStatus[i] = GSTable.PhyState[i];
1183         controllerStatus->recoverableErrorInfo[i] = GSTable.recoverErrInfo[i];
1184       }
1185       controllerStatus->tickCount0 = GSTable.MsguTcnt;
1186       controllerStatus->tickCount1 = GSTable.IopTcnt;
1187       controllerStatus->tickCount2 = GSTable.Iop1Tcnt;
1188 
1189       controllerStatus->interfaceState = GSTable.GSTLenMPIS & GST_INF_STATE_BITS;
1190       controllerStatus->iqFreezeState0 = GSTable.IQFreezeState0;
1191       controllerStatus->iqFreezeState1 = GSTable.IQFreezeState1;
1192       for (i = 0; i < 8; i++)
1193       {
1194         if( IS_SDKDATA(agRoot))
1195         {
1196           if (agNULL != saRoot)
1197           {
1198             controllerStatus->phyStatus[i] = ((saRoot->phys[i+8].linkstatus << SHIFT8) | saRoot->phys[i].linkstatus);
1199           }
1200         }
1201         else
1202         {
1203           controllerStatus->phyStatus[i] = 0;
1204         }
1205         controllerStatus->recoverableErrorInfo[i] = GSTable.recoverErrInfo[i];
1206       }
1207       controllerStatus->tickCount0 = GSTable.MsguTcnt;
1208       controllerStatus->tickCount1 = GSTable.IopTcnt;
1209       controllerStatus->tickCount2 = GSTable.Iop1Tcnt;
1210 
1211     }
1212 
1213     SA_DBG1(("saGetControllerStatus: SCRATCH_PAD0 value = 0x%x\n", ossaHwRegRead(agRoot, V_Scratchpad_0_Register)));
1214     SA_DBG1(("saGetControllerStatus: SCRATCH_PAD1 value = 0x%x\n", ossaHwRegRead(agRoot, V_Scratchpad_1_Register)));
1215     SA_DBG1(("saGetControllerStatus: SCRATCH_PAD2 value = 0x%x\n", ossaHwRegRead(agRoot, V_Scratchpad_2_Register)));
1216     SA_DBG1(("saGetControllerStatus: SCRATCH_PAD3 value = 0x%x\n", ossaHwRegRead(agRoot, V_Scratchpad_3_Register)));
1217 
1218     controllerStatus->fatalErrorInfo.errorInfo0 = ossaHwRegRead(agRoot,V_Scratchpad_0_Register );
1219     controllerStatus->fatalErrorInfo.errorInfo1 = ossaHwRegRead(agRoot,V_Scratchpad_1_Register );
1220     controllerStatus->fatalErrorInfo.errorInfo2 = ossaHwRegRead(agRoot,V_Scratchpad_2_Register );
1221     controllerStatus->fatalErrorInfo.errorInfo3 = ossaHwRegRead(agRoot,V_Scratchpad_3_Register );
1222 
1223     controllerStatus->bootStatus = ( (( controllerStatus->fatalErrorInfo.errorInfo1 >>  SHIFT9) & 1 )                | /* bit 1  */
1224                                      (( controllerStatus->fatalErrorInfo.errorInfo3 & 0x3)               << SHIFT16) | /* bit 16 17 */
1225                                     ((( controllerStatus->fatalErrorInfo.errorInfo3 >>  SHIFT14) & 0x7)  << SHIFT18) | /* bit 18 19 20 */
1226                                     ((( controllerStatus->fatalErrorInfo.errorInfo3 >>  SHIFT4 ) & 0x1)  << SHIFT23) | /* bit 23 */
1227                                     ((( controllerStatus->fatalErrorInfo.errorInfo3 >>  SHIFT16) & 0xFF) << SHIFT24) );/* bit 24 31 */
1228 
1229     controllerStatus->bootComponentState[0] = (bit16) (( controllerStatus->fatalErrorInfo.errorInfo1               & 3 ) | 0x8000); /* RAAE_STATE */
1230     controllerStatus->bootComponentState[1] = (bit16) ((( controllerStatus->fatalErrorInfo.errorInfo1 >>  SHIFT10) & 3 ) | 0x8000); /* IOP0_STATE */
1231     controllerStatus->bootComponentState[2] = (bit16) ((( controllerStatus->fatalErrorInfo.errorInfo1 >>  SHIFT12) & 3 ) | 0x8000); /* IOP1_STATE */
1232     controllerStatus->bootComponentState[3] = (bit16) ((( controllerStatus->fatalErrorInfo.errorInfo1 >>  SHIFT4)  & 7 ) | 0x8000); /* BOOTLDR_STATE  */
1233     controllerStatus->bootComponentState[4] = (bit16) ((( controllerStatus->fatalErrorInfo.errorInfo1 >>  SHIFT2)  & 3 ) | 0x8000); /* ILA State */
1234     controllerStatus->bootComponentState[5] = 0;
1235     controllerStatus->bootComponentState[6] = 0;
1236     controllerStatus->bootComponentState[7] = 0;
1237 
1238 
1239 
1240     if(controllerStatus->fatalErrorInfo.errorInfo0 == 0xFFFFFFFF)
1241     {
1242       ret = AGSA_RC_FAILURE;
1243     }
1244 
1245   }
1246 
1247   SA_DBG1(("saGetControllerStatus: fatalErrorInfo.errorInfo0          0x%x\n", controllerStatus->fatalErrorInfo.errorInfo0));
1248   SA_DBG1(("saGetControllerStatus: fatalErrorInfo.errorInfo1          0x%x\n", controllerStatus->fatalErrorInfo.errorInfo1));
1249   SA_DBG1(("saGetControllerStatus: fatalErrorInfo.errorInfo2          0x%x\n", controllerStatus->fatalErrorInfo.errorInfo2));
1250   SA_DBG1(("saGetControllerStatus: fatalErrorInfo.errorInfo3          0x%x\n", controllerStatus->fatalErrorInfo.errorInfo3));
1251   SA_DBG1(("saGetControllerStatus: fatalErrorInfo.regDumpBusBaseNum0  0x%x\n", controllerStatus->fatalErrorInfo.regDumpBusBaseNum0));
1252   SA_DBG1(("saGetControllerStatus: fatalErrorInfo.regDumpOffset0      0x%x\n", controllerStatus->fatalErrorInfo.regDumpOffset0));
1253   SA_DBG1(("saGetControllerStatus: fatalErrorInfo.regDumpLen0         0x%x\n", controllerStatus->fatalErrorInfo.regDumpLen0));
1254   SA_DBG1(("saGetControllerStatus: fatalErrorInfo.regDumpBusBaseNum1  0x%x\n", controllerStatus->fatalErrorInfo.regDumpBusBaseNum1));
1255   SA_DBG1(("saGetControllerStatus: fatalErrorInfo.regDumpOffset1      0x%x\n", controllerStatus->fatalErrorInfo.regDumpOffset1));
1256   SA_DBG1(("saGetControllerStatus: fatalErrorInfo.regDumpLen1         0x%x\n", controllerStatus->fatalErrorInfo.regDumpLen1));
1257 
1258   SA_DBG1(("saGetControllerStatus: interfaceState                     0x%x\n", controllerStatus->interfaceState));
1259   SA_DBG1(("saGetControllerStatus: iqFreezeState0                     0x%x\n", controllerStatus->iqFreezeState0));
1260   SA_DBG1(("saGetControllerStatus: iqFreezeState1                     0x%x\n", controllerStatus->iqFreezeState1));
1261   SA_DBG1(("saGetControllerStatus: tickCount0                         0x%x\n", controllerStatus->tickCount0));
1262   SA_DBG1(("saGetControllerStatus: tickCount1                         0x%x\n", controllerStatus->tickCount1));
1263   SA_DBG1(("saGetControllerStatus: tickCount2                         0x%x\n", controllerStatus->tickCount2));
1264 
1265   SA_DBG1(("saGetControllerStatus: phyStatus[0]                       0x%08x\n", controllerStatus->phyStatus[0]));
1266   SA_DBG1(("saGetControllerStatus: phyStatus[1]                       0x%08x\n", controllerStatus->phyStatus[1]));
1267   SA_DBG1(("saGetControllerStatus: phyStatus[2]                       0x%08x\n", controllerStatus->phyStatus[2]));
1268   SA_DBG1(("saGetControllerStatus: phyStatus[3]                       0x%08x\n", controllerStatus->phyStatus[3]));
1269   SA_DBG1(("saGetControllerStatus: phyStatus[4]                       0x%08x\n", controllerStatus->phyStatus[4]));
1270   SA_DBG1(("saGetControllerStatus: phyStatus[5]                       0x%08x\n", controllerStatus->phyStatus[5]));
1271   SA_DBG1(("saGetControllerStatus: phyStatus[6]                       0x%08x\n", controllerStatus->phyStatus[6]));
1272   SA_DBG1(("saGetControllerStatus: phyStatus[7]                       0x%08x\n", controllerStatus->phyStatus[7]));
1273 
1274   SA_DBG1(("saGetControllerStatus: recoverableErrorInfo[0]            0x%08x\n", controllerStatus->recoverableErrorInfo[0]));
1275   SA_DBG1(("saGetControllerStatus: recoverableErrorInfo[1]            0x%08x\n", controllerStatus->recoverableErrorInfo[1]));
1276   SA_DBG1(("saGetControllerStatus: recoverableErrorInfo[2]            0x%08x\n", controllerStatus->recoverableErrorInfo[2]));
1277   SA_DBG1(("saGetControllerStatus: recoverableErrorInfo[3]            0x%08x\n", controllerStatus->recoverableErrorInfo[3]));
1278   SA_DBG1(("saGetControllerStatus: recoverableErrorInfo[4]            0x%08x\n", controllerStatus->recoverableErrorInfo[4]));
1279   SA_DBG1(("saGetControllerStatus: recoverableErrorInfo[5]            0x%08x\n", controllerStatus->recoverableErrorInfo[5]));
1280   SA_DBG1(("saGetControllerStatus: recoverableErrorInfo[6]            0x%08x\n", controllerStatus->recoverableErrorInfo[6]));
1281   SA_DBG1(("saGetControllerStatus: recoverableErrorInfo[7]            0x%08x\n", controllerStatus->recoverableErrorInfo[7]));
1282 
1283   SA_DBG1(("saGetControllerStatus: bootStatus                         0x%08x\n", controllerStatus->bootStatus));
1284   SA_DBG1(("saGetControllerStatus: bootStatus  Active FW Image        %x\n", (controllerStatus->bootStatus & 1 ) ? 1 : 0 ));
1285   SA_DBG1(("saGetControllerStatus: bootStatus  Encryption Cap         %x\n", ((controllerStatus->bootStatus & 0x30000 ) >> SHIFT16) ));
1286   SA_DBG1(("saGetControllerStatus: bootStatus  Encryption Sec Mode    %x\n", ((controllerStatus->bootStatus & 0xC0000 ) >> SHIFT18) ));
1287   SA_DBG1(("saGetControllerStatus: bootStatus  Encryption AES XTS     %x\n", (controllerStatus->bootStatus & 0x800000 ) ? 1 : 0 ));
1288   SA_DBG1(("saGetControllerStatus: bootStatus  Encryption Engine Stat 0x%x\n", ((controllerStatus->bootStatus & 0xFF000000 ) >> SHIFT24)  ));
1289 
1290 /*
1291 
1292 Bit 0 : Active FW Image
1293 0b: Primary Image
1294 1b: Secondary Image
1295 
1296 Bit 16-17 :  Encryption Capability
1297 00: Not supported. Controller firmware version doesn't support encryption functionality.
1298 01: Disabled due to error. Controller firmware supports encryption however, the functionality is currently disabled due to an error. The actual cause of the error is indicated in the error code field (bits [23:16]).
1299 10: Enabled with Error. Encryption is currently enabled however, firmware encountered encryption-related error during initialization which might have caused the controller to enter SMF Security mode and/or disabled access to non-volatile memory for encryption-related information. The actual cause of the error is indicated in the error code field (bits [23:16]).
1300 11: Enabled. Encryption functionality is enabled and fully functional.
1301 Bit 18-21 : Encryption Current Security Mode
1302 0000: Security Mode Factory
1303 0001: Security Mode A
1304 0010: Security Mode B
1305 All other values are reserved.
1306 Bit22: Reserved
1307 Bit 23 : Encryption AES XTS Enabled
1308 0: AES XTS is disabled.
1309 1: AES XTS is enabled
1310 Bit 24-31 : Encryption Engine Status
1311 */
1312 
1313 
1314   SA_DBG1(("saGetControllerStatus: bootComponentState[0] RAAE_STATE   0x%x\n", controllerStatus->bootComponentState[0]));
1315   SA_DBG1(("saGetControllerStatus: bootComponentState[1] IOP0_STATE   0x%x\n", controllerStatus->bootComponentState[1]));
1316   SA_DBG1(("saGetControllerStatus: bootComponentState[2] IOP1_STATE   0x%x\n", controllerStatus->bootComponentState[2]));
1317   SA_DBG1(("saGetControllerStatus: bootComponentState[3] BOOTLDR_     0x%x\n", controllerStatus->bootComponentState[3]));
1318   SA_DBG1(("saGetControllerStatus: bootComponentState[4] ILA State    0x%x\n", controllerStatus->bootComponentState[4]));
1319   SA_DBG1(("saGetControllerStatus: bootComponentState[5]              0x%x\n", controllerStatus->bootComponentState[5]));
1320   SA_DBG1(("saGetControllerStatus: bootComponentState[6]              0x%x\n", controllerStatus->bootComponentState[6]));
1321   SA_DBG1(("saGetControllerStatus: bootComponentState[7]              0x%x\n", controllerStatus->bootComponentState[7]));
1322 
1323   if (agNULL != saRoot)
1324   {
1325     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6f");
1326   }
1327 
1328   return ret;
1329 }
1330 
1331 /******************************************************************************/
1332 /*! \brief SPC Get Controller Event Log Information Command
1333  *
1334  *  This command sends Get Controller Event Log Information Command to SPC.
1335  *
1336  *  \param agRoot       Handles for this instance of SAS/SATA LL
1337  *  \param eventLogInfo event log information
1338  *
1339  *  \return If the MPI command is sent to SPC successfully
1340  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1341  *          - \e AGSA_RC_FAILURE the MPI command is failure
1342  *
1343  */
1344 /*******************************************************************************/
1345 GLOBAL bit32 saGetControllerEventLogInfo(
1346                         agsaRoot_t                *agRoot,
1347                         agsaControllerEventLog_t  *eventLogInfo
1348                         )
1349 {
1350   bit32 ret           = AGSA_RC_SUCCESS;
1351   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1352 
1353   smTraceFuncEnter(hpDBG_VERY_LOUD,"6g");
1354 
1355   /* sanity check */
1356   SA_ASSERT((agNULL != agRoot), "");
1357 
1358   eventLogInfo->eventLog1 = saRoot->memoryAllocated.agMemory[MPI_MEM_INDEX + MPI_EVENTLOG_INDEX];
1359   eventLogInfo->eventLog1Option = saRoot->mainConfigTable.eventLogOption;
1360   eventLogInfo->eventLog2 = saRoot->memoryAllocated.agMemory[MPI_MEM_INDEX + MPI_IOP_EVENTLOG_INDEX];
1361   eventLogInfo->eventLog2Option = saRoot->mainConfigTable.IOPeventLogOption;
1362 
1363   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6g");
1364 
1365   return ret;
1366 }
1367 
1368 /******************************************************************************/
1369 /*! \brief SPC Set GPIO Event Setup Command
1370  *
1371  *  This command sends GPIO Event Setup Command to SPC.
1372  *
1373  *  \param agRoot             Handles for this instance of SAS/SATA LL
1374  *  \param agsaContext        Context of this command
1375  *  \param queueNum           Queue number of inbound/outbound queue
1376  *  \param gpioEventSetupInfo Pointer of Event Setup Information structure
1377  *
1378  *  \return If the MPI command is sent to SPC successfully
1379  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1380  *          - \e AGSA_RC_FAILURE the MPI command is failure
1381  *
1382  */
1383 /*******************************************************************************/
1384 GLOBAL bit32 saGpioEventSetup(
1385                         agsaRoot_t                *agRoot,
1386                         agsaContext_t             *agContext,
1387                         bit32                     queueNum,
1388                         agsaGpioEventSetupInfo_t  *gpioEventSetupInfo
1389                         )
1390 {
1391   bit32 ret           = AGSA_RC_SUCCESS;
1392   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1393   agsaIORequestDesc_t *pRequest;
1394   agsaGPIOCmd_t       payload;
1395 
1396   smTraceFuncEnter(hpDBG_VERY_LOUD,"6h");
1397 
1398   /* sanity check */
1399   SA_ASSERT((agNULL != agRoot), "");
1400 
1401   /* Get request from free IORequests */
1402   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1403   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1404 
1405   /* If no LL Control request entry available */
1406   if ( agNULL == pRequest )
1407   {
1408     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1409     SA_DBG1(("saGpioEventSetup, No request from free list\n" ));
1410     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6h");
1411     return AGSA_RC_BUSY;
1412   }
1413   /* If LL Control request entry avaliable */
1414   else
1415   {
1416     /* Remove the request from free list */
1417     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1418     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1419     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1420     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1421     pRequest->valid = agTRUE;
1422 
1423     /* set payload to zeros */
1424     si_memset(&payload, 0, sizeof(agsaGPIOCmd_t));
1425     /* build IOMB command and send to SPC */
1426     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, tag), pRequest->HTag);
1427     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, eOBIDGeGsGrGw), GPIO_GE_BIT);
1428     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, GPIEVChange), gpioEventSetupInfo->gpioEventLevel);
1429     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, GPIEVFall), gpioEventSetupInfo->gpioEventFallingEdge);
1430     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, GPIEVRise), gpioEventSetupInfo->gpioEventRisingEdge);
1431     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GPIO, IOMB_SIZE64, queueNum);
1432     if (AGSA_RC_SUCCESS != ret)
1433     {
1434       /* remove the request from IOMap */
1435       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1436       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1437       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1438       pRequest->valid = agFALSE;
1439 
1440       /* return the request to free pool */
1441       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1442       {
1443         SA_DBG1(("saGpioEventSetup: saving pRequest (%p) for later use\n", pRequest));
1444         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1445       }
1446       else
1447       {
1448         /* return the request to free pool */
1449         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1450       }
1451       SA_DBG1(("saGpioEventSetup, sending IOMB failed\n" ));
1452     }
1453   }
1454 
1455   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1456   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6h");
1457 
1458   return ret;
1459 }
1460 
1461 /******************************************************************************/
1462 /*! \brief SPC Set GPIO Pin Setup Command
1463  *
1464  *  This command sends GPIO Pin Setup Command to SPC.
1465  *
1466  *  \param agRoot             Handles for this instance of SAS/SATA LL
1467  *  \param agsaContext        Context of this command
1468  *  \param queueNum           Queue number of inbound/outbound queue
1469  *  \param gpioPinSetupInfo   Pointer of Event Setup Information structure
1470  *
1471  *  \return If the MPI command is sent to SPC successfully
1472  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1473  *          - \e AGSA_RC_FAILURE the MPI command is failure
1474  *
1475  */
1476 /*******************************************************************************/
1477 GLOBAL bit32 saGpioPinSetup(
1478                         agsaRoot_t                *agRoot,
1479                         agsaContext_t             *agContext,
1480                         bit32                     queueNum,
1481                         agsaGpioPinSetupInfo_t    *gpioPinSetupInfo
1482                         )
1483 {
1484   bit32 ret           = AGSA_RC_SUCCESS;
1485   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1486   agsaIORequestDesc_t *pRequest;
1487   agsaGPIOCmd_t       payload;
1488 
1489   smTraceFuncEnter(hpDBG_VERY_LOUD,"6i");
1490 
1491   /* sanity check */
1492   SA_ASSERT((agNULL != agRoot), "");
1493 
1494   /* Get request from free IORequests */
1495   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1496   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1497 
1498   /* If no LL Control request entry available */
1499   if ( agNULL == pRequest )
1500   {
1501     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1502     SA_DBG1(("saGpioPinSetup, No request from free list\n" ));
1503     return AGSA_RC_BUSY;
1504   }
1505   /* If LL Control request entry avaliable */
1506   else
1507   {
1508     /* Remove the request from free list */
1509     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1510     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1511     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1512     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1513     pRequest->valid = agTRUE;
1514 
1515     /* set payload to zeros */
1516     si_memset(&payload, 0, sizeof(agsaGPIOCmd_t));
1517     /* build IOMB command and send to SPC */
1518     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, tag), pRequest->HTag);
1519     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, eOBIDGeGsGrGw), GPIO_GS_BIT);
1520     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, GpioIe), gpioPinSetupInfo->gpioInputEnabled);
1521     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, OT11_0), gpioPinSetupInfo->gpioTypePart1);
1522     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, OT19_12), gpioPinSetupInfo->gpioTypePart2);
1523     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GPIO, IOMB_SIZE64, queueNum);
1524     if (AGSA_RC_SUCCESS != ret)
1525     {
1526       /* remove the request from IOMap */
1527       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1528       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1529       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1530       pRequest->valid = agFALSE;
1531       /* return the request to free pool */
1532       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1533       {
1534         SA_DBG1(("saGpioPinSetup: saving pRequest (%p) for later use\n", pRequest));
1535         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1536       }
1537       else
1538       {
1539         /* return the request to free pool */
1540         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1541       }
1542       SA_DBG1(("saGpioPinSetup, sending IOMB failed\n" ));
1543     }
1544   }
1545 
1546   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1547   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6i");
1548 
1549   return ret;
1550 }
1551 
1552 /******************************************************************************/
1553 /*! \brief SPC GPIO Read Command
1554  *
1555  *  This command sends GPIO Read Command to SPC.
1556  *
1557  *  \param agRoot       Handles for this instance of SAS/SATA LL
1558  *  \param agsaContext  Context of this command
1559  *  \param queueNum     Queue number of inbound/outbound queue
1560  *
1561  *  \return If the MPI command is sent to SPC successfully
1562  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1563  *          - \e AGSA_RC_FAILURE the MPI command is failure
1564  *
1565  */
1566 /*******************************************************************************/
1567 GLOBAL bit32 saGpioRead(
1568                         agsaRoot_t                *agRoot,
1569                         agsaContext_t             *agContext,
1570                         bit32                     queueNum
1571                         )
1572 {
1573   bit32 ret           = AGSA_RC_SUCCESS;
1574   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1575   agsaIORequestDesc_t *pRequest;
1576   agsaGPIOCmd_t       payload;
1577 
1578   smTraceFuncEnter(hpDBG_VERY_LOUD,"6j");
1579 
1580   /* sanity check */
1581   SA_ASSERT((agNULL != agRoot), "");
1582 
1583   /* Get request from free IORequests */
1584   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1585   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1586 
1587   /* If no LL Control request entry available */
1588   if ( agNULL == pRequest )
1589   {
1590     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1591     SA_DBG1(("saGpioRead, No request from free list\n" ));
1592     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6j");
1593     return AGSA_RC_BUSY;
1594   }
1595   /* If LL Control request entry avaliable */
1596   else
1597   {
1598     /* Remove the request from free list */
1599     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1600     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1601     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1602     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1603     pRequest->valid = agTRUE;
1604 
1605     /* set payload to zeros */
1606     si_memset(&payload, 0, sizeof(agsaGPIOCmd_t));
1607     /* build IOMB command and send to SPC */
1608     /* set GR bit */
1609     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, tag), pRequest->HTag);
1610     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, eOBIDGeGsGrGw), GPIO_GR_BIT);
1611     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GPIO, IOMB_SIZE64, queueNum);
1612     if (AGSA_RC_SUCCESS != ret)
1613     {
1614       /* remove the request from IOMap */
1615       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1616       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1617       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1618       pRequest->valid = agFALSE;
1619       /* return the request to free pool */
1620       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1621       {
1622         SA_DBG1(("saGpioRead: saving pRequest (%p) for later use\n", pRequest));
1623         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1624       }
1625       else
1626       {
1627         /* return the request to free pool */
1628         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1629       }
1630       SA_DBG1(("saGpioRead, sending IOMB failed\n" ));
1631     }
1632   }
1633   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1634 
1635   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6j");
1636 
1637   return ret;
1638 }
1639 
1640 /******************************************************************************/
1641 /*! \brief SPC GPIO Write Command
1642  *
1643  *  This command sends GPIO Write Command to SPC.
1644  *
1645  *  \param agRoot         Handles for this instance of SAS/SATA LL
1646  *  \param agsaContext    Context of this command
1647  *  \param queueNum       Queue number of inbound/outbound queue
1648  *  \param gpioWriteMask  GPIO Write Mask
1649  *  \param gpioWriteValue GPIO Write Value
1650  *
1651  *  \return If the MPI command is sent to SPC successfully
1652  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1653  *          - \e AGSA_RC_FAILURE the MPI command is failure
1654  *
1655  */
1656 /*******************************************************************************/
1657 GLOBAL bit32 saGpioWrite(
1658                         agsaRoot_t                *agRoot,
1659                         agsaContext_t             *agContext,
1660                         bit32                     queueNum,
1661                         bit32                     gpioWriteMask,
1662                         bit32                     gpioWriteValue
1663                         )
1664 {
1665   bit32 ret           = AGSA_RC_SUCCESS;
1666   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1667   agsaIORequestDesc_t *pRequest;
1668   agsaGPIOCmd_t       payload;
1669 
1670   smTraceFuncEnter(hpDBG_VERY_LOUD,"6k");
1671 
1672   /* sanity check */
1673   SA_ASSERT((agNULL != agRoot), "");
1674 
1675   /* Get request from free IORequests */
1676   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1677   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1678 
1679   /* If no LL Control request entry available */
1680   if ( agNULL == pRequest )
1681   {
1682     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1683     SA_DBG1(("saGpioWrite, No request from free list\n" ));
1684     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6k");
1685     return AGSA_RC_BUSY;
1686   }
1687   /* If LL Control request entry avaliable */
1688   else
1689   {
1690     /* Remove the request from free list */
1691     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1692     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1693     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1694     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1695     pRequest->valid = agTRUE;
1696 
1697     /* set payload to zeros */
1698     si_memset(&payload, 0, sizeof(agsaGPIOCmd_t));
1699     /* build IOMB command and send to SPC */
1700     /* set GW bit */
1701     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, tag), pRequest->HTag);
1702     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, eOBIDGeGsGrGw), GPIO_GW_BIT);
1703     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, GpioWrMsk), gpioWriteMask);
1704     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGPIOCmd_t, GpioWrVal), gpioWriteValue);
1705     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GPIO, IOMB_SIZE64, queueNum);
1706     if (AGSA_RC_SUCCESS != ret)
1707     {
1708       /* remove the request from IOMap */
1709       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1710       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1711       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1712       pRequest->valid = agFALSE;
1713 
1714       /* return the request to free pool */
1715       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1716       {
1717         SA_DBG1(("saGpioWrite: saving pRequest (%p) for later use\n", pRequest));
1718         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1719       }
1720       else
1721       {
1722         /* return the request to free pool */
1723         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1724       }
1725       SA_DBG1(("saGpioWrite, sending IOMB failed\n" ));
1726     }
1727   }
1728 
1729   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1730   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6k");
1731 
1732   return ret;
1733 }
1734 
1735 /******************************************************************************/
1736 /*! \brief SPC SAS Diagnostic Execute Command
1737  *
1738  *  This command sends SAS Diagnostic Execute Command to SPC.
1739  *
1740  *  \param agRoot         Handles for this instance of SAS/SATA LL
1741  *  \param agsaContext    Context of this command
1742  *  \param queueNum       Queue number of inbound/outbound queue
1743  *  \param diag           Pointer of SAS Diag Execute Structure
1744  *
1745  *  \return If the MPI command is sent to SPC successfully
1746  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1747  *          - \e AGSA_RC_FAILURE the MPI command is failure
1748  *
1749  */
1750 /*******************************************************************************/
1751 GLOBAL bit32 saSASDiagExecute(
1752                         agsaRoot_t              *agRoot,
1753                         agsaContext_t           *agContext,
1754                         bit32                    queueNum,
1755                         agsaSASDiagExecute_t    *diag
1756                         )
1757 {
1758   bit32                     ret = AGSA_RC_SUCCESS;
1759   agsaLLRoot_t             *saRoot = agNULL;
1760   agsaIORequestDesc_t      *pRequest = agNULL;
1761   bit32  payload[32];
1762   /* sanity check */
1763   SA_ASSERT((agNULL != agRoot), "");
1764 
1765   saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1766   /* sanity check */
1767   SA_ASSERT((agNULL != saRoot), "");
1768 
1769   smTraceFuncEnter(hpDBG_VERY_LOUD,"6m");
1770 
1771   SA_DBG2(("saSASDiagExecute,command 0x%X\n", diag->command ));
1772   SA_DBG2(("saSASDiagExecute,param0 0x%X\n", diag->param0 ));
1773   SA_DBG2(("saSASDiagExecute,param2 0x%X\n", diag->param2 ));
1774   SA_DBG2(("saSASDiagExecute,param3 0x%X\n", diag->param3 ));
1775   SA_DBG2(("saSASDiagExecute,param4 0x%X\n", diag->param4 ));
1776   SA_DBG2(("saSASDiagExecute,param5 0x%X\n", diag->param5 ));
1777 
1778   /* Get request from free IORequests */
1779   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1780   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1781 
1782   /* If no LL Control request entry available */
1783   if ( agNULL == pRequest )
1784   {
1785     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1786     SA_DBG1(("saSASDiagExecute, No request from free list\n" ));
1787     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6m");
1788     return AGSA_RC_BUSY;
1789   }
1790   /* If LL Control request entry avaliable */
1791   else
1792   {
1793     /* Remove the request from free list */
1794     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1795     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1796     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1797     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1798     pRequest->valid = agTRUE;
1799     if(smIS_SPC(agRoot))
1800     {
1801       diag->param5 = 0; /* Reserved for SPC */
1802     }
1803 
1804     /* set payload to zeros */
1805     si_memset(&payload, 0, sizeof(payload));
1806     /* set payload to zeros */
1807     if(smIS_SPCV(agRoot))
1808     {
1809       /* build IOMB command and send to SPC */
1810       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASDiagExecuteCmd_t, tag),             pRequest->HTag);
1811       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASDiagExecuteCmd_t, CmdTypeDescPhyId),diag->command );
1812       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASDiagExecuteCmd_t, Pat1Pat2),        diag->param0 );
1813       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASDiagExecuteCmd_t, Threshold),       diag->param1 );
1814       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASDiagExecuteCmd_t, CodePatErrMsk),   diag->param2 );
1815       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASDiagExecuteCmd_t, Pmon),            diag->param3 );
1816       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASDiagExecuteCmd_t, PERF1CTL),        diag->param4 );
1817       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASDiagExecuteCmd_t, THRSHLD1),        diag->param5 );
1818       ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SAS_DIAG_EXECUTE, IOMB_SIZE128, queueNum);
1819     }
1820     else
1821     {
1822       /* build IOMB command and send to SPC */
1823       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_SASDiagExecuteCmd_t, tag),             pRequest->HTag);
1824       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_SASDiagExecuteCmd_t, CmdTypeDescPhyId),diag->command );
1825       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_SASDiagExecuteCmd_t, Pat1Pat2),        diag->param0 );
1826       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_SASDiagExecuteCmd_t, Threshold),       diag->param1 );
1827       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_SASDiagExecuteCmd_t, CodePatErrMsk),   diag->param2 );
1828       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_SASDiagExecuteCmd_t, Pmon),            diag->param3 );
1829       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_SASDiagExecuteCmd_t, PERF1CTL),        diag->param4 );
1830       ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SAS_DIAG_EXECUTE, IOMB_SIZE64, queueNum);
1831     }
1832     if (AGSA_RC_SUCCESS != ret)
1833     {
1834       /* remove the request from IOMap */
1835       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1836       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1837       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1838       pRequest->valid = agFALSE;
1839 
1840       /* return the request to free pool */
1841       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1842       {
1843         SA_DBG1(("saSASDiagExecute: saving pRequest (%p) for later use\n", pRequest));
1844         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1845       }
1846       else
1847       {
1848         /* return the request to free pool */
1849         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1850       }
1851       SA_DBG1(("saSASDiagExecute, sending IOMB failed\n" ));
1852       smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6m");
1853       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1854       return ret;
1855     }
1856   }
1857 
1858   smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "6m");
1859   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1860   return ret;
1861 }
1862 
1863 /******************************************************************************/
1864 /*! \brief SPC SAS Diagnostic Start/End Command
1865  *
1866  *  This command sends SAS Diagnostic Start/End Command to SPC.
1867  *
1868  *  \param agRoot         Handles for this instance of SAS/SATA LL
1869  *  \param agsaContext    Context of this command
1870  *  \param queueNum       Queue number of inbound/outbound queue
1871  *  \param phyId          Phy ID
1872  *  \param operation      Operation of SAS Diagnostic
1873  *
1874  *  \return If the MPI command is sent to SPC successfully
1875  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1876  *          - \e AGSA_RC_FAILURE the MPI command is failure
1877  *
1878  */
1879 /*******************************************************************************/
1880 GLOBAL bit32 saSASDiagStartEnd(
1881                         agsaRoot_t                *agRoot,
1882                         agsaContext_t             *agContext,
1883                         bit32                     queueNum,
1884                         bit32                     phyId,
1885                         bit32                     operation
1886                         )
1887 {
1888   bit32 ret                = AGSA_RC_SUCCESS;
1889   agsaLLRoot_t             *saRoot;
1890   agsaIORequestDesc_t      *pRequest;
1891   agsaSASDiagStartEndCmd_t payload;
1892 
1893   /* sanity check */
1894   SA_ASSERT((agNULL != agRoot), "");
1895   if (agRoot == agNULL)
1896   {
1897     SA_DBG1(("saSASDiagStartEnd: agRoot == agNULL\n"));
1898     return AGSA_RC_FAILURE;
1899   }
1900   saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
1901   SA_ASSERT((agNULL != saRoot), "");
1902   if (saRoot == agNULL)
1903   {
1904     SA_DBG1(("saSASDiagStartEnd: saRoot == agNULL\n"));
1905     return AGSA_RC_FAILURE;
1906   }
1907 
1908   smTraceFuncEnter(hpDBG_VERY_LOUD,"6n");
1909 
1910   SA_DBG3(("saSASDiagStartEnd, phyId 0x%x operation 0x%x\n",phyId,operation ));
1911 
1912   /* Get request from free IORequests */
1913   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1914   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1915 
1916   /* If no LL Control request entry available */
1917   if ( agNULL == pRequest )
1918   {
1919     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1920     SA_DBG1(("saSASDiagStartEnd, No request from free list\n" ));
1921     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6n");
1922     return AGSA_RC_BUSY;
1923   }
1924   /* If LL Control request entry avaliable */
1925   else
1926   {
1927     /* Remove the request from free list */
1928     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1929     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1930     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1931     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1932     pRequest->valid = agTRUE;
1933 
1934     /* set payload to zeros */
1935     si_memset(&payload, 0, sizeof(agsaSASDiagStartEndCmd_t));
1936     /* build IOMB command and send to SPC */
1937     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASDiagStartEndCmd_t, tag), pRequest->HTag);
1938     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASDiagStartEndCmd_t, OperationPhyId), ((phyId & SM_PHYID_MASK) | (operation << SHIFT8)));
1939     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SAS_DIAG_MODE_START_END, IOMB_SIZE64, queueNum);
1940     if (AGSA_RC_SUCCESS != ret)
1941     {
1942       /* remove the request from IOMap */
1943       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1944       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1945       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1946       pRequest->valid = agFALSE;
1947 
1948       /* return the request to free pool */
1949       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1950       {
1951         SA_DBG1(("saSASDiagStartEnd: saving pRequest (%p) for later use\n", pRequest));
1952         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1953       }
1954       else
1955       {
1956         /* return the request to free pool */
1957         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1958       }
1959       SA_DBG1(("saSASDiagStartEnd, sending IOMB failed\n" ));
1960     }
1961   }
1962 
1963   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6n");
1964   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1965   return ret;
1966 }
1967 
1968 /******************************************************************************/
1969 /*! \brief Initiate a GET TIME STAMP command
1970  *
1971  *  This function is called to initiate a Get Time Stamp command to the SPC.
1972  *  The completion of this function is reported in ossaGetTimeStampCB().
1973  *
1974  *  \param agRoot      handles for this instance of SAS/SATA hardware
1975  *  \param agContext   the context of this API
1976  *  \param queueNum    queue number
1977  *
1978  *  \return
1979  *          - SUCCESS or FAILURE
1980  */
1981 /*******************************************************************************/
1982 GLOBAL bit32 saGetTimeStamp(
1983                       agsaRoot_t        *agRoot,
1984                       agsaContext_t     *agContext,
1985                       bit32             queueNum
1986                       )
1987 {
1988   agsaIORequestDesc_t   *pRequest;
1989   agsaGetTimeStampCmd_t payload;
1990   bit32                 ret = AGSA_RC_SUCCESS;
1991   agsaLLRoot_t          *saRoot;
1992   SA_ASSERT((agNULL != agRoot), "");
1993   if (agRoot == agNULL)
1994   {
1995     SA_DBG1(("saGetTimeStamp: agRoot == agNULL\n"));
1996     return AGSA_RC_FAILURE;
1997   }
1998   saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
1999   SA_ASSERT((agNULL != saRoot), "");
2000   if (saRoot == agNULL)
2001   {
2002     SA_DBG1(("saGetTimeStamp: saRoot == agNULL\n"));
2003     return AGSA_RC_FAILURE;
2004   }
2005 
2006   smTraceFuncEnter(hpDBG_VERY_LOUD,"6o");
2007 
2008   /* sanity check */
2009   SA_ASSERT((agNULL != agRoot), "");
2010 
2011   SA_DBG3(("saGetTimeStamp: agContext %p\n", agContext));
2012 
2013   /* Get request from free IORequests */
2014   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2015   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2016 
2017   /* If no LL Control request entry available */
2018   if ( agNULL == pRequest )
2019   {
2020     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2021     SA_DBG1(("saGetTimeStamp, No request from free list\n" ));
2022     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6o");
2023     return AGSA_RC_BUSY;
2024   }
2025   /* If LL Control request entry avaliable */
2026   else
2027   {
2028     /* Remove the request from free list */
2029     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2030     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2031     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2032     saRoot->IOMap[pRequest->HTag].agContext = agContext;
2033     pRequest->valid = agTRUE;
2034 
2035     /* build IOMB command and send to SPC */
2036     /* set payload to zeros */
2037     si_memset(&payload, 0, sizeof(agsaGetTimeStampCmd_t));
2038 
2039     /* set tag */
2040     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetTimeStampCmd_t, tag), pRequest->HTag);
2041 
2042     /* build IOMB command and send to SPC */
2043     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_TIME_STAMP, IOMB_SIZE64, queueNum);
2044     if (AGSA_RC_SUCCESS != ret)
2045     {
2046       /* remove the request from IOMap */
2047       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2048       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2049       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2050       pRequest->valid = agFALSE;
2051 
2052       /* return the request to free pool */
2053       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
2054       {
2055         SA_DBG1(("saGetTimeStamp: saving pRequest (%p) for later use\n", pRequest));
2056         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
2057       }
2058       else
2059       {
2060         /* return the request to free pool */
2061         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2062       }
2063       SA_DBG1(("saGetTimeStamp, sending IOMB failed\n" ));
2064     }
2065   }
2066 
2067   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2068   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6o");
2069 
2070   return ret;
2071 }
2072 
2073 /******************************************************************************/
2074 /*! \brief Update IOMap Entry
2075  *
2076  *  This function is called to update certain fields of IOMap Entry
2077  *
2078  *  \param pIOMap       IOMap Entry
2079  *  \param HTag         Host Tag
2080  *  \param pRequest     Request
2081  *  \parma agContext    Context of this API
2082  *
2083  *  \return             NA
2084  */
2085 /*******************************************************************************/
2086 static void saUpdateIOMap(
2087                         agsaIOMap_t         *pIOMap,
2088                         bit32               HTag,
2089                         agsaIORequestDesc_t *pRequest,
2090                         agsaContext_t       *agContext
2091                         )
2092 {
2093   pIOMap->Tag = HTag;
2094   pIOMap->IORequest = (void *)pRequest;
2095   pIOMap->agContext = agContext;
2096 }
2097 
2098 /******************************************************************************/
2099 /*! \brief Get a request from free pool
2100  *
2101  *  This function gets a request from free pool
2102  *
2103  *  \param agRoot       Handles for this instance of SAS/SATA LL
2104  *  \param agsaContext  Context of this command
2105  *
2106  *  \return
2107  *          - \e Pointer to request, in case of success
2108  *          - \e NULL, in case of failure
2109  *
2110  */
2111 /*******************************************************************************/
2112 agsaIORequestDesc_t* saGetRequestFromFreePool(
2113                                             agsaRoot_t      *agRoot,
2114                                             agsaContext_t   *agContext
2115                                             )
2116 {
2117   agsaLLRoot_t          *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
2118   agsaIORequestDesc_t   *pRequest = agNULL;
2119 
2120   /* Acquire LL_IOREQ_LOCKEQ_LOCK */
2121   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2122 
2123   /* Get request from free IORequests */
2124   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2125   if (pRequest != agNULL)
2126   {
2127     /* Remove the request from free list */
2128     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2129 
2130     /* Release LL_IOREQ_LOCKEQ_LOCK */
2131     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2132 
2133     /* Add the request to IOMap */
2134     saUpdateIOMap(&saRoot->IOMap[pRequest->HTag], pRequest->HTag, pRequest, agContext);
2135     pRequest->valid = agTRUE;
2136   }
2137   else
2138   {
2139     /* Release LL_IOREQ_LOCKEQ_LOCK */
2140     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2141   }
2142 
2143   return pRequest;
2144 }
2145 
2146 /******************************************************************************/
2147 /*! \brief Return request to free pool
2148  *
2149  *  This function returns the request to free pool
2150  *
2151  *  \param agRoot       Handles for this instance of SAS/SATA LL
2152  *  \param pRequest     Request to be returned
2153  *
2154  *  \return             NA
2155  *
2156  */
2157 /*******************************************************************************/
2158 void saReturnRequestToFreePool(
2159                             agsaRoot_t          *agRoot,
2160                             agsaIORequestDesc_t *pRequest
2161                             )
2162 {
2163   agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
2164 
2165   SA_ASSERT((pRequest->valid), "pRequest->valid");
2166 
2167   /* Remove the request from IOMap */
2168   saUpdateIOMap(&saRoot->IOMap[pRequest->HTag], MARK_OFF, agNULL, agNULL);
2169   pRequest->valid = agFALSE;
2170 
2171   /* Acquire LL_IOREQ_LOCKEQ_LOCK */
2172   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2173 
2174   if (saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
2175   {
2176     SA_DBG1(("saReturnRequestToFreePool: saving pRequest (%p) for later use\n", pRequest));
2177     saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
2178   }
2179   else
2180   {
2181     /* Return the request to free pool */
2182     saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2183   }
2184 
2185   /* Release LL_IOREQ_LOCKEQ_LOCK */
2186   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2187 }
2188 /******************************************************************************/
2189 /*! \brief Initiate a serial GPIO command
2190  *
2191  *  This function is called to initiate a serial GPIO command to the SPC.
2192  *  The completion of this function is reported in ossaSgpioCB().
2193  *
2194  *  \param agRoot      handles for this instance of SAS/SATA hardware
2195  *  \param agContext   the context of this API
2196  *  \param queueNum    queue number
2197  *  \param pSGpioReq   Pointer to the serial GPIO fields
2198  *
2199  *  \return
2200  *          - SUCCESS or FAILURE
2201  */
2202 /*******************************************************************************/
2203 GLOBAL bit32 saSgpio(
2204                 agsaRoot_t              *agRoot,
2205                 agsaContext_t           *agContext,
2206                 bit32                   queueNum,
2207                 agsaSGpioReqResponse_t  *pSGpioReq
2208                 )
2209 {
2210   bit32                 i;
2211   agsaIORequestDesc_t   *pRequest = agNULL;
2212   agsaSGpioCmd_t        payload = {0};
2213   bit32                 ret = AGSA_RC_BUSY;
2214 
2215   smTraceFuncEnter(hpDBG_VERY_LOUD,"6t");
2216 
2217   /* Sanity check */
2218   SA_ASSERT((agNULL != agRoot), "");
2219 
2220   SA_DBG3(("saSgpio: agContext %p\n", agContext));
2221 
2222   /* Get request from free pool */
2223   pRequest = saGetRequestFromFreePool(agRoot, agContext);
2224   if (agNULL == pRequest)
2225   {
2226     SA_DBG1(("saSgpio, No request from free list\n" ));
2227     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6t");
2228   }
2229   else
2230   {
2231     /* Set payload to zeros */
2232     si_memset(&payload, 0, sizeof(agsaSGpioCmd_t));
2233 
2234     /* set tag */
2235     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSGpioCmd_t, tag), pRequest->HTag);
2236     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSGpioCmd_t, regIndexRegTypeFunctionFrameType),
2237                         (pSGpioReq->smpFrameType |
2238                         ((bit32)pSGpioReq->function << 8)  |
2239                         ((bit32)pSGpioReq->registerType << 16) |
2240                         ((bit32)pSGpioReq->registerIndex << 24)));
2241     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSGpioCmd_t, regCount), pSGpioReq->registerCount);
2242 
2243     if (SA_SAS_SMP_WRITE_GPIO_REGISTER == pSGpioReq->function)
2244     {
2245       for (i = 0; i < pSGpioReq->registerCount; i++)
2246       {
2247         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSGpioCmd_t, writeData) + (i * 4), pSGpioReq->readWriteData[i]);
2248       }
2249     }
2250 
2251     /* Build IOMB command and send to SPC */
2252     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SGPIO, IOMB_SIZE64, queueNum);
2253     if (AGSA_RC_SUCCESS != ret)
2254     {
2255       /* Return the request to free pool */
2256       saReturnRequestToFreePool(agRoot, pRequest);
2257       SA_DBG1(("saSgpio, sending IOMB failed\n" ));
2258     }
2259 
2260     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6t");
2261   }
2262 
2263   return ret;
2264 }
2265 
2266 /******************************************************************************/
2267 /*! \brief for spc card read Error Registers to memory if error occur
2268  *
2269  *  This function is called to get erorr registers content to memory if error occur.
2270  *
2271  *  \param agRoot      handles for this instance of SAS/SATA hardware
2272  *
2273  *  \return
2274  */
2275 /*******************************************************************************/
2276 LOCAL void siSpcGetErrorContent(
2277                                 agsaRoot_t *agRoot
2278                                )
2279 {
2280 
2281   agsaLLRoot_t          *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
2282   bit32       value, value1;
2283 
2284   value = siHalRegReadExt(agRoot, GEN_MSGU_SCRATCH_PAD_1, MSGU_SCRATCH_PAD_1) & SCRATCH_PAD_STATE_MASK;
2285   value1 = siHalRegReadExt(agRoot, GEN_MSGU_SCRATCH_PAD_2, MSGU_SCRATCH_PAD_2) & SCRATCH_PAD_STATE_MASK;
2286       /* check AAP error */
2287   if ((SCRATCH_PAD1_ERR == value) || (SCRATCH_PAD2_ERR == value1))
2288   {
2289         /* fatal error */
2290         /* get register dump from GSM and save it to LL local memory */
2291       siGetRegisterDumpGSM(agRoot, (void *)&saRoot->registerDump0[0],
2292            REG_DUMP_NUM0, 0, saRoot->mainConfigTable.FatalErrorDumpLength0);
2293       siGetRegisterDumpGSM(agRoot, (void *)&saRoot->registerDump1[0],
2294            REG_DUMP_NUM1, 0, saRoot->mainConfigTable.FatalErrorDumpLength1);
2295   }
2296 }
2297 
2298 
2299 /******************************************************************************/
2300 /*! \brief for spcv card read Error Registers to memory if error occur
2301  *
2302  *  This function is called to get erorr registers content to memory if error occur.
2303  *
2304  *  \param agRoot      handles for this instance of SAS/SATA hardware
2305  *
2306  *  \return
2307  */
2308 /*******************************************************************************/
2309 LOCAL void siSpcvGetErrorContent(
2310                                  agsaRoot_t *agRoot
2311                                  )
2312 {
2313 
2314   agsaLLRoot_t          *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
2315   bit32                 value;
2316 
2317   smTraceFuncEnter(hpDBG_VERY_LOUD,"2d");
2318   value = siHalRegReadExt(agRoot, GEN_MSGU_SCRATCH_PAD_1, MSGU_SCRATCH_PAD_1);
2319 
2320   if(((value & SPCV_RAAE_STATE_MASK) == SPCV_ERROR_VALUE) ||
2321      ((value & SPCV_IOP0_STATE_MASK) == SPCV_ERROR_VALUE) ||
2322      ((value & SPCV_IOP1_STATE_MASK) == SPCV_ERROR_VALUE)
2323     )
2324   {
2325         /* fatal error */
2326         /* get register dump from GSM and save it to LL local memory */
2327     siGetRegisterDumpGSM(agRoot, (void *)&saRoot->registerDump0[0],
2328        REG_DUMP_NUM0, 0, saRoot->mainConfigTable.FatalErrorDumpLength0);
2329     siGetRegisterDumpGSM(agRoot, (void *)&saRoot->registerDump1[0],
2330        REG_DUMP_NUM1, 0, saRoot->mainConfigTable.FatalErrorDumpLength1);
2331   }
2332   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2d");
2333 }
2334 
2335 #define LEFT_BYTE_FAIL(x, v)   \
2336      do {if( (x) < (v) ) return AGSA_RC_FAILURE; } while(0);
2337 
2338 LOCAL bit32 siDumpInboundQueue(
2339           void *  buffer,
2340           bit32   length,
2341           mpiICQueue_t  *q
2342           )
2343 {
2344   bit8  * _buf = buffer;
2345   si_memcpy( _buf, (bit8*)(q->memoryRegion.virtPtr) + length, 128*256);
2346   return AGSA_RC_SUCCESS;
2347 }
2348 
2349 LOCAL bit32 siDumpOutboundQueue(
2350           void *  buffer,
2351           bit32   length,
2352           mpiOCQueue_t  *q)
2353 {
2354   bit8  * _buf   = buffer;
2355   si_memcpy( _buf, (bit8*)(q->memoryRegion.virtPtr) + length, 128*256);
2356   return AGSA_RC_SUCCESS;
2357 }
2358 
2359 
2360 LOCAL bit32 siWaitForNonFatalTransfer( agsaRoot_t *agRoot,bit32 pcibar)
2361 {
2362   bit32 status = AGSA_RC_SUCCESS;
2363   bit32 ready;
2364   bit32 max_wait_time;
2365   bit32 max_wait_count;
2366   smTraceFuncEnter(hpDBG_VERY_LOUD,"2c");
2367 
2368   SA_DBG4(("siWaitForNonFatalTransfer:0 IBDBS 0x%x\n",ossaHwRegReadExt(agRoot,0 ,V_Inbound_Doorbell_Set_Register ) ));
2369   /* Write FDDHSHK  */
2370 
2371 
2372   /* Write bit7 of inbound doorbell set register  step 3 */
2373   ossaHwRegWriteExt(agRoot, 0,V_Inbound_Doorbell_Set_Register, SPCV_MSGU_CFG_TABLE_TRANSFER_DEBUG_INFO );
2374   SA_DBG4(("siWaitForNonFatalTransfer:1 IBDBS 0x%x\n",ossaHwRegReadExt(agRoot,0 ,V_Inbound_Doorbell_Set_Register ) ));
2375 
2376   /* Poll bit7 of inbound doorbell set register until clear step 4 */
2377   max_wait_time = (2000 * 1000); /* wait 2 seconds */
2378   max_wait_count = MAKE_MODULO(max_wait_time,WAIT_INCREMENT) - WAIT_INCREMENT;
2379   do
2380   {
2381     ossaStallThread(agRoot, WAIT_INCREMENT);
2382     ready = ossaHwRegReadExt(agRoot,0 ,V_Inbound_Doorbell_Set_Register );
2383   } while ( (ready & SPCV_MSGU_CFG_TABLE_TRANSFER_DEBUG_INFO)  && (max_wait_count -= WAIT_INCREMENT));
2384   if(max_wait_count == 0)
2385   {
2386     SA_DBG1(("siWaitForNonFatalTransfer:Timeout IBDBS 0x%x\n",ossaHwRegReadExt(agRoot,0 ,V_Inbound_Doorbell_Set_Register ) ));
2387     status = AGSA_RC_FAILURE;
2388   }
2389 
2390   SA_DBG4(("siWaitForNonFatalTransfer:3 IBDBS 0x%x\n",ossaHwRegReadExt(agRoot,0 ,V_Inbound_Doorbell_Set_Register ) ));
2391 
2392   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2c");
2393   return(status);
2394 }
2395 
2396 LOCAL bit32 siWaitForFatalTransfer( agsaRoot_t *agRoot,bit32 pcibar)
2397 {
2398   bit32 status = AGSA_RC_SUCCESS;
2399   bit32 ready;
2400   bit32 ErrorTableOffset;
2401   bit32 max_wait_time;
2402   bit32 max_wait_count;
2403 
2404   smTraceFuncEnter(hpDBG_VERY_LOUD,"2o");
2405 
2406   ErrorTableOffset = siGetTableOffset( agRoot, MAIN_MERRDCTO_MERRDCES );
2407 
2408   SA_DBG4(("siWaitForFatalTransfer: MPI_FATAL_EDUMP_TABLE_STATUS    Offset 0x%x 0x%x\n",ErrorTableOffset+MPI_FATAL_EDUMP_TABLE_STATUS, ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+MPI_FATAL_EDUMP_TABLE_STATUS )));
2409   SA_DBG4(("siWaitForFatalTransfer: MPI_FATAL_EDUMP_TABLE_ACCUM_LEN Offset 0x%x 0x%x\n",ErrorTableOffset+MPI_FATAL_EDUMP_TABLE_ACCUM_LEN, ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN)));
2410   /*
2411   2. Write 0x1 to the Fatal Error Debug Dump Handshake control [FDDHSHK] field in Table 73 and
2412   read back the same field (by polling) until it is 0. This prompts the debug agent to copy the next
2413   part of the debug data into GSM shared memory. To check the completion of the copy process, the
2414   host must poll the Fatal/Non Fatal Debug Data Transfer Status [FDDTSTAT] field in the Table
2415   Table 73.
2416   */
2417 
2418   /* Write FDDHSHK  */
2419   ossaHwRegWriteExt(agRoot,pcibar ,ErrorTableOffset+MPI_FATAL_EDUMP_TABLE_HANDSHAKE, MPI_FATAL_EDUMP_HANDSHAKE_RDY );
2420   SA_DBG4(("siWaitForFatalTransfer:1 MPI_FATAL_EDUMP_TABLE_HANDSHAKE 0x%x\n",ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+MPI_FATAL_EDUMP_TABLE_HANDSHAKE ) ));
2421 
2422   /* Poll FDDHSHK  until clear  */
2423   max_wait_time = (2000 * 1000); /* wait 2 seconds */
2424   max_wait_count = MAKE_MODULO(max_wait_time,WAIT_INCREMENT) - WAIT_INCREMENT;
2425   do
2426   {
2427     ossaStallThread(agRoot, WAIT_INCREMENT);
2428     ready = ossaHwRegReadExt(agRoot,0 ,ErrorTableOffset+MPI_FATAL_EDUMP_TABLE_HANDSHAKE );
2429   } while (ready   && (max_wait_count -= WAIT_INCREMENT));
2430   if(max_wait_count == 0)
2431   {
2432     SA_DBG1(("siWaitForFatalTransfer : 1 Timeout\n"));
2433     status = AGSA_RC_FAILURE;
2434   }
2435 
2436   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2o");
2437   return(status);
2438 }
2439 
2440 
2441 
2442 LOCAL bit32 siFatalErrorBuffer(
2443                   agsaRoot_t *agRoot,
2444                   agsaForensicData_t *forensicData
2445                   )
2446 {
2447   bit32 status = AGSA_RC_FAILURE;
2448   bit32 pcibar;
2449   bit32 ErrorTableOffset;
2450   bit32 Accum_len = 0;
2451 
2452   agsaLLRoot_t      *saRoot;
2453   /* sanity check */
2454   SA_ASSERT( (agNULL != agRoot), "");
2455   saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
2456   SA_ASSERT( (agNULL != saRoot), "saRoot");
2457   if(agNULL == saRoot )
2458   {
2459     SA_DBG1(("siFatalErrorBuffer: agNULL  saRoot\n"));
2460     return(status);
2461   }
2462 
2463   if(saRoot->ResetFailed )
2464   {
2465     SA_DBG1(("siFatalErrorBuffer: saRoot->ResetFailed\n"));
2466     return(status);
2467   }
2468   smTraceFuncEnter(hpDBG_VERY_LOUD,"2a");
2469   SA_DBG2(("siFatalErrorBuffer:In %p Offset 0x%08x Len 0x%08x Totel len 0x%x\n",
2470                         forensicData->BufferType.dataBuf.directData,
2471                         forensicData->BufferType.dataBuf.directOffset,
2472                         forensicData->BufferType.dataBuf.directLen,
2473 			forensicData->BufferType.dataBuf.readLen ));
2474 
2475   pcibar = siGetPciBar(agRoot);
2476   ErrorTableOffset = siGetTableOffset( agRoot, MAIN_MERRDCTO_MERRDCES );
2477 
2478   SA_DBG3(("siFatalErrorBuffer: MPI_FATAL_EDUMP_TABLE_STATUS  0x%x LEN 0x%x\n",
2479       ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+MPI_FATAL_EDUMP_TABLE_STATUS),
2480       ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) ));
2481 
2482   /*
2483   This section describes sequence for the host to capture debug data under fatal error conditions.
2484   A fatal error is an error condition that stops the SPCv controller from normal operation and causes it
2485   to be unresponsive to host requests. Since the firmware is non-operational, the host needs to pull the
2486   debug dump information using PCIe MEMBASE II with the assistance of the debug agent which becomes
2487   active when the main controller firmware fails.
2488   */
2489   /*
2490   To capture the fatal error debug data, the host must:
2491   1. Upon detecting the fatal error condition through a fatal error interrupt or by the MSGU scratchpad
2492   registers, capture the first part of the fatal error debug data. Upon fatal error, the first part of the
2493   debug data is located GSM shared memory and its length is updated in the Accumulative Debug
2494   Data Length Transferred [ACCDDLEN] field in Table Table 82. To capture the first part:
2495   */
2496   if(forensicData->BufferType.dataBuf.directOffset == 0)
2497   {
2498     /* start to get data */
2499     /*
2500     a. Program the MEMBASE II Shifting Register with 0x00.
2501     */
2502     ossaHwRegWriteExt(agRoot, pcibar,V_MEMBASE_II_ShiftRegister, saRoot->FatalForensicShiftOffset); // set base to zero
2503 
2504     saRoot->ForensicLastOffset =0;
2505     saRoot->FatalForensicStep = 0;
2506     saRoot->FatalBarLoc = 0;
2507     saRoot->FatalForensicShiftOffset = 0;
2508 
2509     SA_DBG1(("siFatalErrorBuffer: directOffset zero SCRATCH_PAD1 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1) ));
2510   }
2511 
2512   /* Read until Accum_len is retrived */
2513   Accum_len = ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
2514 
2515   SA_DBG2(("siFatalErrorBuffer: Accum_len 0x%x\n", Accum_len));
2516   if(Accum_len == 0xFFFFFFFF)
2517   {
2518     SA_DBG1(("siFatalErrorBuffer: Possible PCI issue 0x%x not expected\n", Accum_len));
2519     return(status);
2520   }
2521 
2522   if( Accum_len == 0 || Accum_len >=0x100000 )
2523   {
2524     SA_DBG1(("siFatalErrorBuffer: Accum_len == saRoot->FatalCurrentLength 0x%x\n", Accum_len));
2525     return(IOCTL_ERROR_NO_FATAL_ERROR);
2526   }
2527 
2528   if(saRoot->FatalForensicStep == 0) /* PM Step 1a and 1b */
2529   {
2530     moreData:
2531 	  if(forensicData->BufferType.dataBuf.directData)
2532 	  {
2533       		  siPciCpyMem(agRoot,saRoot->FatalBarLoc ,forensicData->BufferType.dataBuf.directData,forensicData->BufferType.dataBuf.directLen ,1 );
2534 	  }
2535 	  saRoot->FatalBarLoc += forensicData->BufferType.dataBuf.directLen;
2536 	  forensicData->BufferType.dataBuf.directOffset += forensicData->BufferType.dataBuf.directLen;
2537 	  saRoot->ForensicLastOffset  += forensicData->BufferType.dataBuf.directLen;
2538 	  forensicData->BufferType.dataBuf.readLen = forensicData->BufferType.dataBuf.directLen;
2539 
2540 	  if(saRoot->ForensicLastOffset  >= Accum_len)
2541     {
2542       /*
2543       e. Repeat the above 2 steps until all debug data is retrieved as specified in the Accumulative Debug
2544       Data Length Transferred [ACCDDLEN] field.
2545       NOTE: The ACCDDLEN field is cumulative so the host needs to take the difference from the
2546       previous step.
2547       */
2548       /* This section data ends get next section */
2549       SA_DBG1(("siFatalErrorBuffer: Accum_len reached 0x%x directOffset 0x%x\n",Accum_len,forensicData->BufferType.dataBuf.directOffset ));
2550       saRoot->FatalBarLoc = 0;
2551       saRoot->FatalForensicStep = 1;
2552       saRoot->FatalForensicShiftOffset = 0;
2553 		  status = AGSA_RC_COMPLETE;
2554 		  return status;
2555     }
2556     if(saRoot->FatalBarLoc < (64*1024))
2557     {
2558       SA_DBG2(("siFatalErrorBuffer: In same 64k FatalBarLoc 0x%x\n",saRoot->FatalBarLoc ));
2559       status = AGSA_RC_SUCCESS;
2560 		  return status;
2561     }
2562     /*
2563     c. Increment the MEMBASE II Shifting Register value by 0x100.
2564     */
2565     saRoot->FatalForensicShiftOffset+= 0x100;
2566     	  ossaHwRegWriteExt(agRoot, pcibar,V_MEMBASE_II_ShiftRegister, saRoot->FatalForensicShiftOffset);
2567     saRoot->FatalBarLoc = 0;
2568 
2569 	  SA_DBG1(("siFatalErrorBuffer: Get next bar data 0x%x\n",saRoot->FatalForensicShiftOffset));
2570 
2571     status = AGSA_RC_SUCCESS;
2572 
2573 	  SA_DBG1(("siFatalErrorBuffer:Offset 0x%x BarLoc 0x%x\n",saRoot->FatalForensicShiftOffset,saRoot->FatalBarLoc  ));
2574 	  SA_DBG1(("siFatalErrorBuffer: step 0 status %d %p Offset 0x%x Len 0x%x total_len 0x%x\n",
2575                         status,
2576                         forensicData->BufferType.dataBuf.directData,
2577 				  forensicData->BufferType.dataBuf.directOffset,
2578                         forensicData->BufferType.dataBuf.directLen,
2579 				  forensicData->BufferType.dataBuf.readLen ));
2580 	  return(status);
2581   }
2582 
2583   if(saRoot->FatalForensicStep == 1)
2584   {
2585 
2586     /*
2587     3. If Fatal/Non Fatal Debug Data Transfer Status [FDDTSTAT] field indicates status value of
2588     0x00000002 or 0x00000003, read the next part of the fatal debug data by taking the difference
2589     between the preserved ACCDDLEN value from step 2 and the new ACCDDLEN value.To capture
2590     the second part:
2591     a. Program the MEMBASE II Shifting Register with 0x00.
2592     */
2593     SA_DBG1(("siFatalErrorBuffer: FatalForensicStep 1 Accum_len 0x%X MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x%x\n",
2594                 Accum_len,
2595                 ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN)));
2596 
2597     saRoot->FatalForensicShiftOffset = 0; /* location in 64k region */
2598     /*
2599     b. Read 64K of the debug data.
2600     */
2601     ossaHwRegWriteExt(agRoot, pcibar,V_MEMBASE_II_ShiftRegister  ,saRoot->FatalForensicShiftOffset);
2602     SA_DBG1(("siFatalErrorBuffer: FatalForensicStep 1\n" ));
2603     /*
2604     2.Write 0x1 to the Fatal Error Debug Dump Handshake control [FDDHSHK]
2605     field inTable 82 and read back the same field (by polling for 2 seconds) until it is 0. This prompts
2606     the debug agent to copy the next part of the debug data into GSM shared memory. To check the
2607     completion of the copy process, the host must poll the Fatal/Non Fatal Debug Data Transfer Status
2608     [FDDTSTAT] field for 2 secondsin the MPI Fatal and Non-Fatal Error Dump Capture Table Table 82.
2609     */
2610     siWaitForFatalTransfer( agRoot,pcibar);
2611 
2612     /*
2613     d. Read the next 64K of the debug data.
2614     */
2615     saRoot->FatalForensicStep = 0;
2616 
2617     if( ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+ MPI_FATAL_EDUMP_TABLE_STATUS) != MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE )
2618     {
2619 
2620       SA_DBG3(("siFatalErrorBuffer:Step 3\n" ));
2621       SA_DBG3(("siFatalErrorBuffer:Step 3 MPI_FATAL_EDUMP_TABLE_STATUS 0x%x\n", ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+ MPI_FATAL_EDUMP_TABLE_STATUS )));
2622       /*
2623       2. Write FDDSTAT to 0x00000000 but preserve the Accumulative Debug Data Length Transferred
2624       [ACCDDLEN] field.
2625       */
2626       ossaHwRegWriteExt(agRoot,pcibar ,ErrorTableOffset+MPI_FATAL_EDUMP_TABLE_STATUS, 0 );
2627       /*
2628       4. If FDDSTAT is 0x00000002, repeat steps 2 and 3 until you reach this step with FDDSTAT being
2629       equal to 0x00000003.
2630       */
2631       goto moreData;
2632     }
2633     else
2634     {
2635       /*
2636          When FDDSTAT equals 0x00000003 and ACCDDLEN is unchanged, then
2637       */
2638       /*
2639       the fatal error dump is complete. If ACCDDLEN increases, one more read step is required.
2640       The content and format of the debug data is opaque to the host and must be forwarded to PMC-Sierra
2641       Applications support for failure analysis. Debug data is retrieved in several iterations which enables
2642       the host to use a smaller buffer and store the captured debug data in secondary storage during the process.
2643       */
2644 
2645       SA_DBG3(("siFatalErrorBuffer:Step 4\n" ));
2646       SA_DBG1(("siFatalErrorBuffer:  Done  Read 0x%x accum 0x%x\n",
2647                 forensicData->BufferType.dataBuf.directOffset,
2648                 ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN)));
2649 
2650 #if defined(SALLSDK_DEBUG)
2651       SA_DBG1(("siFatalErrorBuffer: SCRATCH_PAD1_V_ERROR_STATE 0x%x\n",SCRATCH_PAD1_V_ERROR_STATE( siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1) )));
2652       SA_DBG1(("siFatalErrorBuffer: SCRATCH_PAD0 value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_0,  MSGU_SCRATCH_PAD_0)));
2653       SA_DBG1(("siFatalErrorBuffer: SCRATCH_PAD1 value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_1,  MSGU_SCRATCH_PAD_1)));
2654       SA_DBG1(("siFatalErrorBuffer: SCRATCH_PAD2 value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_2,  MSGU_SCRATCH_PAD_2)));
2655       SA_DBG1(("siFatalErrorBuffer: SCRATCH_PAD3 value = 0x%x\n", siHalRegReadExt(agRoot,GEN_MSGU_SCRATCH_PAD_3,  MSGU_SCRATCH_PAD_3)));
2656 #endif
2657       forensicData->BufferType.dataBuf.readLen = 0xFFFFFFFF;
2658       status = AGSA_RC_SUCCESS;
2659 
2660     }
2661   }
2662 
2663 
2664   SA_DBG3(("siFatalErrorBuffer:status 0x%x %p directOffset 0x%x directLen 0x%x readLen 0x%x\n",
2665                         status,
2666                         forensicData->BufferType.dataBuf.directData,
2667                         forensicData->BufferType.dataBuf.directOffset,
2668                         forensicData->BufferType.dataBuf.directLen,
2669                         forensicData->BufferType.dataBuf.readLen ));
2670 
2671       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2a");
2672   return(status);
2673 }
2674 
2675 LOCAL bit32 siNonFatalErrorBuffer(
2676               agsaRoot_t *agRoot,
2677               agsaForensicData_t *forensicData
2678               )
2679 {
2680   bit32 status = AGSA_RC_FAILURE;
2681   bit32 pcibar;
2682   bit32 ErrorTableOffset;
2683 
2684   //bit32 i;
2685   bit32 ready;
2686   bit32 biggest;
2687   bit32 max_wait_time;
2688   bit32 max_wait_count;
2689   agsaLLRoot_t      *saRoot;
2690   /* sanity check */
2691   SA_ASSERT( (agNULL != agRoot), "agRoot");
2692   saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
2693   SA_ASSERT( (agNULL != saRoot), "saRoot");
2694   if(agNULL == saRoot )
2695   {
2696     SA_DBG1(("siNonFatalErrorBuffer: agNULL  saRoot\n"));
2697     return(status);
2698   }
2699 
2700   smTraceFuncEnter(hpDBG_VERY_LOUD,"2b");
2701   pcibar = siGetPciBar(agRoot);
2702   ErrorTableOffset = siGetTableOffset( agRoot, MAIN_MERRDCTO_MERRDCES );
2703 
2704   SA_DBG4(("siNonFatalErrorBuffer: ErrorTableOffset 0x%x\n",ErrorTableOffset ));
2705 
2706   SA_DBG4(("siNonFatalErrorBuffer: MPI_FATAL_EDUMP_TABLE_STATUS Offset 0x%x   0x%x\n",
2707             ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_STATUS,
2708             ossaHwRegReadExt(agRoot,pcibar,ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_STATUS)));
2709   SA_DBG4(("siNonFatalErrorBuffer: MPI_FATAL_EDUMP_TABLE_ACCUM_LEN Offset 0x%x   0x%x\n",
2710             ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN,
2711             ossaHwRegReadExt(agRoot,pcibar,ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN)));
2712 
2713   biggest = saRoot->memoryAllocated.agMemory[HDA_DMA_BUFFER].totalLength;
2714 
2715   if(biggest >= forensicData->BufferType.dataBuf.directLen )
2716   {
2717     biggest = forensicData->BufferType.dataBuf.directLen;
2718   }
2719   else
2720   {
2721     SA_DBG1(("siNonFatalErrorBuffer: directLen larger than DMA Buffer 0x%x < 0x%x\n",
2722               biggest, forensicData->BufferType.dataBuf.directLen));
2723     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2b");
2724     return(AGSA_RC_FAILURE);
2725   }
2726 
2727   if(saRoot->memoryAllocated.agMemory[HDA_DMA_BUFFER].virtPtr)
2728   {
2729     si_memset(saRoot->memoryAllocated.agMemory[HDA_DMA_BUFFER].virtPtr, 0, biggest);
2730   }
2731   else
2732   {
2733     SA_DBG1(("siNonFatalErrorBuffer: Error\n" ));
2734     return(AGSA_RC_FAILURE);
2735   }
2736 
2737 
2738   if(forensicData->BufferType.dataBuf.directOffset)
2739   {
2740     /* Write FDDSTAT and ACCDDLEN to zero step 2 */
2741     ossaHwRegWriteExt(agRoot, pcibar, ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_STATUS, 0);
2742     goto skip_setup;
2743   }
2744 
2745   SA_DBG1(("siNonFatalErrorBuffer: %p Offset 0x%x Len 0x%x total_len 0x%x\n",
2746                         forensicData->BufferType.dataBuf.directData,
2747                         forensicData->BufferType.dataBuf.directOffset,
2748                         forensicData->BufferType.dataBuf.directLen,
2749                         forensicData->BufferType.dataBuf.readLen ));
2750 
2751   SA_DBG1(("siNonFatalErrorBuffer: directOffset zero setup\n" ));
2752   SA_DBG1(("siNonFatalErrorBuffer: MPI_FATAL_EDUMP_TABLE_STATUS  0x%x LEN 0x%x\n",
2753       ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+MPI_FATAL_EDUMP_TABLE_STATUS),
2754       ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) ));
2755 
2756   SA_DBG1(("siNonFatalErrorBuffer: Clear V_Scratchpad_Rsvd_0_Register 0x%x\n",
2757           ossaHwRegReadExt(agRoot, 0,V_Scratchpad_Rsvd_0_Register) ));
2758   ossaHwRegWriteExt(agRoot, 0,V_Scratchpad_Rsvd_0_Register ,0);
2759 
2760   saRoot->ForensicLastOffset = 0;
2761 
2762   /* WriteACCDDLEN  for error interface Step 0 */
2763   /*ossaHwRegWriteExt(agRoot, pcibar, ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN ,0);*/
2764 
2765   /* Write DMA get Offset for error interface Step 1 */
2766   ossaHwRegWriteExt(agRoot, pcibar, ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_LO_OFFSET, saRoot->memoryAllocated.agMemory[HDA_DMA_BUFFER].phyAddrLower);
2767   ossaHwRegWriteExt(agRoot, pcibar, ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_HI_OFFSET, saRoot->memoryAllocated.agMemory[HDA_DMA_BUFFER].phyAddrUpper);
2768   ossaHwRegWriteExt(agRoot, pcibar, ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_LENGTH, biggest);
2769 
2770   /* Write FDDSTAT and ACCDDLEN to zero step 2 */
2771   ossaHwRegWriteExt(agRoot, pcibar, ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_STATUS, 0);
2772   ossaHwRegWriteExt(agRoot, pcibar, ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN, 0);
2773 
2774   SA_DBG4(("siNonFatalErrorBuffer: MPI_FATAL_EDUMP_TABLE_STATUS Offset 0x%x   0x%x\n",
2775            ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_STATUS,
2776            ossaHwRegReadExt(agRoot,pcibar,ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_STATUS )));
2777   SA_DBG4(("siNonFatalErrorBuffer: MPI_FATAL_EDUMP_TABLE_ACCUM_LEN Offset 0x%x   0x%x\n",
2778            ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN,
2779            ossaHwRegReadExt(agRoot, pcibar, ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN)));
2780 
2781   if( 0 != ossaHwRegReadExt(agRoot, pcibar, ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN))
2782   {
2783     SA_DBG1(("siNonFatalErrorBuffer: MPI_FATAL_EDUMP_TABLE_ACCUM_LEN  0x%x   0x%x\n",
2784              forensicData->BufferType.dataBuf.directOffset,
2785              ossaHwRegReadExt(agRoot, pcibar, ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN)));
2786   }
2787   skip_setup:
2788 
2789   if( saRoot->ForensicLastOffset == 0xFFFFFFFF)
2790   {
2791     forensicData->BufferType.dataBuf.readLen = 0xFFFFFFFF;
2792     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2b");
2793     return(AGSA_RC_SUCCESS);
2794   }
2795 
2796 
2797   /* Write bit7 of inbound doorbell set register and wait for complete step 3 and 4*/
2798   siWaitForNonFatalTransfer(agRoot,pcibar);
2799 
2800   SA_DBG3(("siNonFatalErrorBuffer: MPI_FATAL_EDUMP_TABLE_STATUS  0x%x LEN 0x%x\n",
2801       ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+MPI_FATAL_EDUMP_TABLE_STATUS),
2802       ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) ));
2803 
2804 
2805 
2806   max_wait_time = (2000 * 1000); /* wait 2 seconds */
2807   max_wait_count = MAKE_MODULO(max_wait_time,WAIT_INCREMENT) - WAIT_INCREMENT;
2808   ready = ossaHwRegReadExt(agRoot,pcibar,ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_STATUS );
2809   do
2810   {
2811     ossaStallThread(agRoot, WAIT_INCREMENT);
2812     ready =  ossaHwRegReadExt(agRoot,pcibar ,ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_STATUS );
2813     forensicData->BufferType.dataBuf.directOffset = ossaHwRegReadExt(agRoot,pcibar,ErrorTableOffset + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
2814     if( ready == MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_MORE_DATA )
2815     {
2816       SA_DBG2(("siNonFatalErrorBuffer: More data available MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x%x\n", ossaHwRegReadExt(agRoot,pcibar,ErrorTableOffset+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) ));
2817       break;
2818     }
2819   } while ( ready != MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE && (max_wait_count -= WAIT_INCREMENT));
2820 
2821 
2822   if(max_wait_count == 0 || ready == MPI_FATAL_EDUMP_TABLE_STAT_DMA_FAILED)
2823   {
2824     status = AGSA_RC_FAILURE;
2825     SA_DBG1(("siNonFatalErrorBuffer: timeout waiting ready\n"));
2826   }
2827   else
2828   {
2829     forensicData->BufferType.dataBuf.readLen = forensicData->BufferType.dataBuf.directOffset - saRoot->ForensicLastOffset;
2830     if( ready == MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE && forensicData->BufferType.dataBuf.readLen == 0)
2831     {
2832       SA_DBG1(("siNonFatalErrorBuffer:ready 0x%x readLen 0x%x\n",ready ,forensicData->BufferType.dataBuf.readLen));
2833       saRoot->ForensicLastOffset = 0xFFFFFFFF;
2834     }
2835     else
2836     {
2837       saRoot->ForensicLastOffset = forensicData->BufferType.dataBuf.directOffset;
2838     }
2839 
2840     if(forensicData->BufferType.dataBuf.directData )
2841     {
2842       si_memcpy(forensicData->BufferType.dataBuf.directData, saRoot->memoryAllocated.agMemory[HDA_DMA_BUFFER].virtPtr,biggest);
2843     }
2844     status = AGSA_RC_SUCCESS;
2845   }
2846   /* step 5 */
2847   SA_DBG3(("siNonFatalErrorBuffer: %p directOffset 0x%x directLen 0x%x readLen 0x%x\n",
2848                         forensicData->BufferType.dataBuf.directData,
2849                         forensicData->BufferType.dataBuf.directOffset,
2850                         forensicData->BufferType.dataBuf.directLen,
2851                         forensicData->BufferType.dataBuf.readLen ));
2852   smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2b");
2853   return(status);
2854 }
2855 
2856 
2857 LOCAL bit32 siGetForensicData(
2858     agsaRoot_t         *agRoot,
2859     agsaContext_t      *agContext,
2860     agsaForensicData_t *forensicData
2861     )
2862 {
2863   bit32 status = AGSA_RC_FAILURE;
2864 	agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
2865 
2866   smTraceFuncEnter(hpDBG_VERY_LOUD,"2Z");
2867 
2868   if(forensicData->DataType == TYPE_GSM_SPACE)
2869 	{
2870 #define _1M 0x100000
2871 		if( forensicData->BufferType.gsmBuf.directLen >= _1M )
2872   {
2873 			return AGSA_RC_FAILURE;
2874 		}
2875 
2876 		if(forensicData->BufferType.dataBuf.readLen)
2877     {
2878 			SA_DBG1(("siGetForensicData: Incorrect readLen 0x%08X\n", forensicData->BufferType.dataBuf.readLen));
2879 			forensicData->BufferType.dataBuf.readLen = forensicData->BufferType.dataBuf.directLen;
2880 		}
2881 		if( forensicData->BufferType.dataBuf.directOffset >= ONE_MEGABYTE )
2882 		{
2883 			SA_DBG1(("siGSMDump:	total length > ONE_MEGABYTE  0x%x\n",forensicData->BufferType.dataBuf.directOffset));
2884 			forensicData->BufferType.dataBuf.readLen = 0xFFFFFFFF;
2885 			return(AGSA_RC_SUCCESS);
2886     }
2887 		if(smIS_SPC(agRoot))
2888 		{
2889     if( forensicData->BufferType.dataBuf.directLen >= SIXTYFOURKBYTE )
2890     {
2891       SA_DBG1(("siGetForensicData directLen too large !\n"));
2892       return AGSA_RC_FAILURE;
2893     }
2894     SA_DBG1(("siGetForensicData: TYPE_GSM_SPACE directLen 0x%X directOffset 0x%08X %p\n",
2895                   forensicData->BufferType.dataBuf.directLen,
2896                   forensicData->BufferType.dataBuf.directOffset,
2897                   forensicData->BufferType.dataBuf.directData ));
2898 
2899 
2900     /* Shift BAR4 original address */
2901     if (AGSA_RC_FAILURE == siBar4Shift(agRoot, BAR_SHIFT_GSM_OFFSET + forensicData->BufferType.dataBuf.directOffset))
2902     {
2903       SA_DBG1(("siGSMDump:Shift Bar4 to 0x%x failed\n", 0x0));
2904       return AGSA_RC_FAILURE;
2905     }
2906 
2907 
2908 			//if( forensicData->BufferType.dataBuf.directOffset >= ONE_MEGABYTE )
2909 			//{
2910 			//SA_DBG1(("siGSMDump:  total length > ONE_MEGABYTE  0x%x\n",forensicData->BufferType.dataBuf.directOffset));
2911 			//forensicData->BufferType.dataBuf.readLen = 0xFFFFFFFF;
2912 			//return(AGSA_RC_SUCCESS);
2913 			//}
2914 			forensicData->BufferType.gsmBuf.directOffset = 0;
2915     }
2916     status = siGSMDump( agRoot,
2917 				forensicData->BufferType.gsmBuf.directOffset,
2918 				forensicData->BufferType.gsmBuf.directLen,
2919 				forensicData->BufferType.gsmBuf.directData );
2920 
2921     if(status == AGSA_RC_SUCCESS)
2922     {
2923       forensicData->BufferType.dataBuf.readLen = forensicData->BufferType.dataBuf.directLen;
2924     }
2925 
2926     if( forensicData->BufferType.dataBuf.directOffset == 0 )
2927     {
2928       SA_DBG1(("siGetForensicData: TYPE_GSM_SPACE readLen 0x%08X\n", forensicData->BufferType.dataBuf.readLen));
2929     }
2930     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2Z");
2931 
2932     return status;
2933   }
2934 	else if(forensicData->DataType == TYPE_INBOUND_QUEUE )
2935   {
2936       mpiICQueue_t        *circularQ = NULL;
2937 		SA_DBG2(("siGetForensicData: TYPE_INBOUND \n"));
2938 
2939       if(forensicData->BufferType.queueBuf.queueIndex >=AGSA_MAX_INBOUND_Q )
2940       {
2941         smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2Z");
2942         return AGSA_RC_FAILURE;
2943       }
2944       circularQ = &saRoot->inboundQueue[forensicData->BufferType.queueBuf.queueIndex];
2945       status = siDumpInboundQueue( forensicData->BufferType.queueBuf.directData,
2946                                  forensicData->BufferType.queueBuf.directLen,
2947                                  circularQ );
2948 		smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "2Z");
2949 		return status;
2950     }
2951 	else if(forensicData->DataType == TYPE_OUTBOUND_QUEUE )
2952 	//else if( forensicData->BufferType.queueBuf.queueType == TYPE_OUTBOUND_QUEUE )
2953     {
2954       mpiOCQueue_t        *circularQ = NULL;
2955 		SA_DBG2(("siGetForensicData: TYPE_OUTBOUND\n"));
2956 
2957       if(forensicData->BufferType.queueBuf.queueIndex >= AGSA_MAX_OUTBOUND_Q )
2958       {
2959         smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "2Z");
2960         return AGSA_RC_FAILURE;
2961       }
2962 
2963       circularQ = &saRoot->outboundQueue[forensicData->BufferType.queueBuf.queueIndex];
2964       status = siDumpOutboundQueue(forensicData->BufferType.queueBuf.directData,
2965                                  forensicData->BufferType.queueBuf.directLen,
2966                                  circularQ );
2967     smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "2Z");
2968 
2969     return status;
2970   }
2971   else if(forensicData->DataType == TYPE_NON_FATAL  )
2972   {
2973 		// if(smIS_SPCV(agRoot))
2974 		// {
2975 		SA_DBG2(("siGetForensicData:TYPE_NON_FATAL \n"));
2976       status = siNonFatalErrorBuffer(agRoot,forensicData);
2977 		// }
2978     smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "2Z");
2979     return status;
2980   }
2981   else if(forensicData->DataType == TYPE_FATAL  )
2982   {
2983 		// if(smIS_SPCV(agRoot))
2984 		//{
2985 		SA_DBG2(("siGetForensicData:TYPE_NON_FATAL \n"));
2986       status = siFatalErrorBuffer(agRoot,forensicData );
2987 		// }
2988 		smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "2Z");
2989 		return status;
2990 	}
2991 	else
2992 	{
2993 		SA_DBG1(("siGetForensicData receive error parameter!\n"));
2994 		smTraceFuncExit(hpDBG_VERY_LOUD, 'h', "2Z");
2995 		return AGSA_RC_FAILURE;
2996 	}
2997 	smTraceFuncExit(hpDBG_VERY_LOUD, 'i', "2Z");
2998 
2999 	return status;
3000 }
3001 
3002 
3003 //GLOBAL bit32 saGetForensicData(
3004 bit32 saGetForensicData(
3005     agsaRoot_t         *agRoot,
3006     agsaContext_t      *agContext,
3007     agsaForensicData_t *forensicData
3008     )
3009 {
3010   bit32 status;
3011   status = siGetForensicData(agRoot, agContext, forensicData);
3012   ossaGetForensicDataCB(agRoot, agContext, status, forensicData);
3013   return status;
3014 }
3015 
3016 bit32 saGetIOErrorStats(
3017                          agsaRoot_t        *agRoot,
3018                          agsaContext_t     *agContext,
3019                          bit32              flag
3020                          )
3021 {
3022   agsaLLRoot_t  *saRoot = (agsaLLRoot_t*)agRoot->sdkData;
3023   bit32          status = AGSA_RC_SUCCESS;
3024 
3025   ossaGetIOErrorStatsCB(agRoot, agContext, status, &saRoot->IoErrorCount);
3026 
3027   if (flag)
3028   {
3029     /* clear IO error counter */
3030     si_memset(&saRoot->IoErrorCount, 0, sizeof(agsaIOErrorEventStats_t));
3031   }
3032 
3033   return status;
3034 }
3035 
3036 bit32 saGetIOEventStats(
3037                          agsaRoot_t        *agRoot,
3038                          agsaContext_t     *agContext,
3039                          bit32              flag
3040                          )
3041 {
3042   agsaLLRoot_t  *saRoot = (agsaLLRoot_t*)agRoot->sdkData;
3043   bit32          status = AGSA_RC_SUCCESS;
3044 
3045   ossaGetIOEventStatsCB(agRoot, agContext, status, &saRoot->IoEventCount);
3046 
3047   if (flag)
3048   {
3049     /* clear IO event counter */
3050     si_memset(&saRoot->IoEventCount, 0, sizeof(agsaIOErrorEventStats_t));
3051   }
3052 
3053   return status;
3054 }
3055 
3056 /******************************************************************************/
3057 /*! \brief Initiate a GET REGISTER DUMP command
3058  *
3059  *  This function is called to Get Register Dump from the SPC.
3060  *
3061  *  \param agRoot      handles for this instance of SAS/SATA hardware
3062  *  \param agContext   the context of this API
3063  *  \param queueNum    queue number
3064  *  \param regDumpInfo register dump information
3065  *
3066  *  \return
3067  *          - SUCCESS or FAILURE
3068  */
3069 /*******************************************************************************/
3070 //GLOBAL bit32 saGetRegisterDump(
3071 bit32 saGetRegisterDump(
3072               agsaRoot_t        *agRoot,
3073               agsaContext_t     *agContext,
3074               bit32             queueNum,
3075               agsaRegDumpInfo_t *regDumpInfo
3076               )
3077 {
3078   agsaLLRoot_t          *saRoot = agNULL;
3079   bit32                 ret = AGSA_RC_SUCCESS;
3080 //  bit32                 value, value1;
3081 
3082   smTraceFuncEnter(hpDBG_VERY_LOUD,"6p");
3083 
3084   /* sanity check */
3085   SA_ASSERT((agNULL != agRoot), "");
3086 
3087   saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
3088   /* sanity check */
3089   SA_ASSERT((agNULL != saRoot), "");
3090 
3091   /* sanity check */
3092   SA_ASSERT((agNULL != regDumpInfo), "");
3093 
3094   SA_DBG3(("saGetRegisterDump: agContext %p\n", agContext));
3095 
3096   if (regDumpInfo->regDumpSrc > 3)
3097   {
3098     SA_DBG1(("saGetRegisterDump, regDumpSrc %d or regDumpNum %d invalid\n",
3099             regDumpInfo->regDumpNum, regDumpInfo->regDumpNum));
3100     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6p");
3101     /* CB error for Register Dump */
3102     ossaGetRegisterDumpCB(agRoot, agContext, OSSA_FAILURE);
3103     return AGSA_RC_FAILURE;
3104   }
3105 
3106   switch(regDumpInfo->regDumpSrc)
3107   {
3108   case REG_DUMP_NONFLASH:
3109     /*First 6 64k data from GSMDUMP, contains IOST and RB info*/
3110     if (regDumpInfo->regDumpNum == GET_IOST_RB_INFO)
3111     {
3112       regDumpInfo->regDumpOffset = regDumpInfo->regDumpOffset + 0;
3113       ret = siGSMDump(agRoot, regDumpInfo->regDumpOffset, regDumpInfo->directLen, regDumpInfo->directData);
3114       /* CB error for Register Dump */
3115       ossaGetRegisterDumpCB(agRoot, agContext, ret);
3116       return ret;
3117     }
3118     /* Last 1MB data from GSMDUMP, contains GSM_SM info*/
3119 
3120     if (regDumpInfo->regDumpNum == GET_GSM_SM_INFO)
3121     {
3122       /* GSM_SM - total 1 Mbytes */
3123       bit32    offset;
3124       if(smIS_SPC(agRoot))
3125       {
3126         offset = regDumpInfo->regDumpOffset + SPC_GSM_SM_OFFSET;
3127       }else if(smIS_SPCV(agRoot))
3128       {
3129         offset = regDumpInfo->regDumpOffset + SPCV_GSM_SM_OFFSET;
3130       } else
3131       {
3132         SA_DBG1(("saGetRegisterDump: the device type is not support\n"));
3133         return AGSA_RC_FAILURE;
3134       }
3135 
3136       ret = siGSMDump(agRoot, offset, regDumpInfo->directLen, regDumpInfo->directData);
3137       /* CB error for Register Dump */
3138       ossaGetRegisterDumpCB(agRoot, agContext, ret);
3139       return ret;
3140     }
3141 
3142     /* check fatal errors */
3143     if(smIS_SPC(agRoot)) {
3144       siSpcGetErrorContent(agRoot);
3145     }
3146     else if(smIS_SPCV(agRoot)) {
3147       siSpcvGetErrorContent(agRoot);
3148     }
3149     /* Then read from local copy */
3150     if (regDumpInfo->directLen > REGISTER_DUMP_BUFF_SIZE)
3151     {
3152       SA_DBG1(("saGetRegisterDump, Request too many bytes %d\n",
3153               regDumpInfo->directLen));
3154       regDumpInfo->directLen = REGISTER_DUMP_BUFF_SIZE;
3155     }
3156 
3157     if (regDumpInfo->regDumpNum == 0)
3158     {
3159       /* Copy the LL Local register dump0 data to the destination */
3160       si_memcpy(regDumpInfo->directData, (bit8 *)&saRoot->registerDump0[0] +
3161                 regDumpInfo->regDumpOffset, regDumpInfo->directLen);
3162     }
3163     else if( regDumpInfo->regDumpNum == 1)
3164     {
3165       /* Copy the LL Local register dump1 data to the destination */
3166       si_memcpy(regDumpInfo->directData, (bit8 *)&saRoot->registerDump1[0] +
3167                 regDumpInfo->regDumpOffset, regDumpInfo->directLen);
3168     } else {
3169       SA_DBG1(("saGetRegisterDump, the regDumpNum value is wrong %x\n",
3170               regDumpInfo->regDumpNum));
3171     }
3172 
3173     /* CB for Register Dump */
3174     ossaGetRegisterDumpCB(agRoot, agContext, OSSA_SUCCESS);
3175     break;
3176 
3177   case REG_DUMP_FLASH:
3178     /* build IOMB command and send to SPC */
3179     ret = mpiNVMReadRegDumpCmd(agRoot, agContext, queueNum,
3180                             regDumpInfo->regDumpNum,
3181                             regDumpInfo->regDumpOffset,
3182                             regDumpInfo->indirectAddrUpper32,
3183                             regDumpInfo->indirectAddrLower32,
3184                             regDumpInfo->indirectLen);
3185 
3186     break;
3187 
3188   default:
3189     break;
3190   }
3191 
3192   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6p");
3193 
3194   return ret;
3195 }
3196 
3197 /******************************************************************************/
3198 /*! \brief Initiate a GET REGISTER DUMP from GSM command
3199  *
3200  *  This function is called to Get Register Dump from the GSM of SPC.
3201  *
3202  *  \param agRoot      handles for this instance of SAS/SATA hardware
3203  *  \param destinationAddress address of the register dump data copied to
3204  *  \param regDumpNum  Register Dump # 0 or 1
3205  *  \param regDumpOffset Offset within the register dump area
3206  *  \param len         Length in bytes of the register dump data to copy
3207  *
3208  *  \return
3209  *          - SUCCESS or FAILURE
3210  */
3211 /*******************************************************************************/
3212 //GLOBAL bit32 siGetRegisterDumpGSM(
3213 bit32 siGetRegisterDumpGSM(
3214                         agsaRoot_t        *agRoot,
3215                         void              *destinationAddress,
3216                         bit32             regDumpNum,
3217                         bit32             regDumpOffset,
3218                         bit32             len
3219                         )
3220 {
3221   agsaLLRoot_t          *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
3222   bit32                 ret = AGSA_RC_SUCCESS;
3223   bit32                 rDumpOffset, rDumpLen; //, rDumpValue;
3224   bit8                  *dst;
3225 
3226   smTraceFuncEnter(hpDBG_VERY_LOUD,"2V");
3227 
3228   /* sanity check */
3229   SA_ASSERT((agNULL != agRoot), "");
3230 
3231   dst = (bit8 *)destinationAddress;
3232 
3233   if (regDumpNum > 1)
3234   {
3235     SA_DBG1(("siGetRegisterDump, regDumpNum %d is invalid\n", regDumpNum));
3236     return AGSA_RC_FAILURE;
3237   }
3238 
3239   if (!regDumpNum)
3240   {
3241     rDumpOffset = saRoot->mainConfigTable.FatalErrorDumpOffset0;
3242     rDumpLen = saRoot->mainConfigTable.FatalErrorDumpLength0;
3243   }
3244   else
3245   {
3246     rDumpOffset = saRoot->mainConfigTable.FatalErrorDumpOffset1;
3247     rDumpLen = saRoot->mainConfigTable.FatalErrorDumpLength1;
3248   }
3249 
3250   if (len > rDumpLen)
3251   {
3252     SA_DBG1(("siGetRegisterDump, Request too many bytes %d, rDumpLen %d\n", len, rDumpLen));
3253     len = rDumpLen;
3254   }
3255 
3256   if (regDumpOffset >= len)
3257   {
3258     SA_DBG1(("siGetRegisterDump, Offset is not within the area %d, regDumpOffset%d\n", rDumpLen, regDumpOffset));
3259     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2V");
3260     return AGSA_RC_FAILURE;
3261   }
3262 
3263   /* adjust length to dword boundary */
3264   if ((len % 4) > 0)
3265   {
3266     len = (len/4 + 1) * 4;
3267   }
3268 
3269   ret = siGSMDump(agRoot, rDumpOffset, len, dst);
3270   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2V");
3271 
3272   return ret;
3273 }
3274 
3275 /******************************************************************************/
3276 /*! \brief SPC Get NVMD Command
3277  *
3278  *  This command sends GET_NVMD_DATA Command to SPC.
3279  *
3280  *  \param agRoot       Handles for this instance of SAS/SATA LL
3281  *  \param agContext    Context of SPC FW Flash Update Command
3282  *  \param queueNum     Inbound/outbound queue number
3283  *  \param NVMDInfo     Pointer of NVM Device information
3284  *
3285  *  \return If the MPI command is sent to SPC successfully
3286  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
3287  *          - \e AGSA_RC_FAILURE the MPI command is failure
3288  *
3289  */
3290 /*******************************************************************************/
3291 //GLOBAL bit32 saGetNVMDCommand(
3292 bit32 saGetNVMDCommand(
3293   agsaRoot_t                *agRoot,
3294   agsaContext_t             *agContext,
3295   bit32                     queueNum,
3296   agsaNVMDData_t            *NVMDInfo
3297   )
3298 {
3299   bit32 ret           = AGSA_RC_SUCCESS;
3300 
3301   /* sanity check */
3302   SA_ASSERT((agNULL != agRoot), "");
3303 
3304   /* build IOMB command and send to SPC */
3305   ret = mpiGetNVMDCmd(agRoot, agContext, NVMDInfo, queueNum);
3306 
3307   return ret;
3308 }
3309 
3310 /******************************************************************************/
3311 /*! \brief SPC Set NVMD Command
3312  *
3313  *  This command sends SET_NVMD_DATA Command to SPC.
3314  *
3315  *  \param agRoot       Handles for this instance of SAS/SATA LL
3316  *  \param agContext    Context of SPC FW Flash Update Command
3317  *  \param queueNum     Inbound/outbound queue number
3318  *  \param NVMDInfo     Pointer of NVM Device information
3319  *
3320  *  \return If the MPI command is sent to SPC successfully
3321  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
3322  *          - \e AGSA_RC_FAILURE the MPI command is failure
3323  *
3324  */
3325 /*******************************************************************************/
3326 //GLOBAL bit32 saSetNVMDCommand(
3327 bit32 saSetNVMDCommand(
3328   agsaRoot_t                *agRoot,
3329   agsaContext_t             *agContext,
3330   bit32                     queueNum,
3331   agsaNVMDData_t            *NVMDInfo
3332   )
3333 {
3334   bit32 ret           = AGSA_RC_SUCCESS;
3335 
3336   /* sanity check */
3337   SA_ASSERT((agNULL != agRoot), "");
3338 
3339   /* build IOMB command and send to SPC */
3340   ret = mpiSetNVMDCmd(agRoot, agContext, NVMDInfo, queueNum);
3341 
3342   return ret;
3343 }
3344 
3345 
3346 GLOBAL bit32 saSendSMPIoctl(
3347   agsaRoot_t                *agRoot,
3348   agsaDevHandle_t           *agDevHandle,
3349   bit32                      queueNum,
3350   agsaSMPFrame_t            *pSMPFrame,
3351   ossaSMPCompletedCB_t       agCB
3352   )
3353 {
3354   bit32 ret           = AGSA_RC_SUCCESS;
3355   //bit32 IR_IP_OV_res_phyId_DPdLen_res = 0;
3356   bit32 retVal;
3357   bit8                      inq, outq;
3358   agsaIORequestDesc_t       *pRequest;
3359   void                      *pMessage;
3360   bit8                      *payload_ptr;
3361   agsaDeviceDesc_t          *pDevice;
3362   bit8                      using_reserved = agFALSE;
3363   agsaPort_t                *pPort;
3364   mpiICQueue_t              *circularQ;
3365   agsaLLRoot_t              *saRoot = agNULL;
3366 //  agsaDevHandle_t       	*agDevHandle;
3367 
3368   saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
3369   SA_ASSERT((agNULL != saRoot), "");
3370 
3371   /* sanity check */
3372   SA_ASSERT((agNULL != agRoot), "");
3373 
3374 
3375 
3376   /* Get request from free IO Requests */
3377   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3378   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
3379 
3380   /* If no LL IO request entry available */
3381   if ( agNULL == pRequest )
3382   {
3383     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests));
3384 
3385     if(agNULL != pRequest)
3386     {
3387       using_reserved = agTRUE;
3388       SA_DBG1(("saSMPStart, using saRoot->freeReservedRequests\n"));
3389     }
3390     else
3391     {
3392       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3393       SA_DBG1(("saSMPStart, No request from free list Not using saRoot->freeReservedRequests\n"));
3394       smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "9a");
3395       return AGSA_RC_BUSY;
3396     }
3397   }
3398 
3399   inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
3400   outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
3401 
3402 
3403 
3404 
3405   SA_ASSERT((agNULL != agDevHandle), "");
3406   /* Find the outgoing port for the device */
3407   if (agNULL == agDevHandle->sdkData)
3408   {
3409 	/* Device has been removed */
3410       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3411 	SA_DBG1(("saSMPStart, Device has been removed. agDevHandle=%p\n", agDevHandle));
3412 	smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "9a");
3413 	return AGSA_RC_FAILURE;
3414   }
3415 
3416   pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
3417 
3418   pPort = pDevice->pPort;
3419 
3420 
3421 
3422 	  /* If free IOMB avaliable */
3423 	  /* Remove the request from free list */
3424 	  if( using_reserved )
3425 	  {
3426 		saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
3427 	  }
3428 	  else
3429 	  {
3430 		saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
3431 	  }
3432 
3433 	  /* Add the request to the pendingSMPRequests list of the device */
3434 	  saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode));
3435 	  SA_ASSERT((!pRequest->valid), "The pRequest is in use");
3436 	  pRequest->valid			  = agTRUE;
3437 	  ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3438 
3439 	  /* set up pRequest */
3440 	  pRequest->pIORequestContext = (agsaIORequest_t *)pRequest;
3441 	  pRequest->pDevice 		  = pDevice;
3442 	  pRequest->pPort			  = pPort;
3443 	  pRequest->startTick		  = saRoot->timeTick;
3444 	  pRequest->completionCB	  = (ossaSSPCompletedCB_t)agCB;
3445 	  pRequest->requestType		  = AGSA_SMP_IOCTL_REQUEST;
3446 
3447 	  /* Set request to the sdkData of agIORequest */
3448 	 // agIORequest->sdkData		  = pRequest;
3449 
3450 	  /* save tag to IOMap */
3451 	  saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
3452 	  saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
3453 
3454 #ifdef SA_LL_IBQ_PROTECT
3455 	  ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
3456 #endif /* SA_LL_IBQ_PROTECT */
3457 
3458 	  /* If LL IO request entry avaliable */
3459 	  /* Get a free inbound queue entry */
3460 	  circularQ = &saRoot->inboundQueue[inq];
3461 	  retVal	= mpiMsgFreeGet(circularQ, IOMB_SIZE64, &pMessage);
3462 
3463 	  if (AGSA_RC_FAILURE == retVal)
3464 	  {
3465 #ifdef SA_LL_IBQ_PROTECT
3466 		ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
3467 #endif /* SA_LL_IBQ_PROTECT */
3468 		/* if not sending return to free list rare */
3469 		ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3470 		saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
3471 		pRequest->valid = agFALSE;
3472 		saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
3473 		ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3474 
3475 		SA_DBG1(("saSMPStart, error when get free IOMB\n"));
3476 		smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "9a");
3477 		return AGSA_RC_FAILURE;
3478 	  }
3479 
3480 	  /* return busy if inbound queue is full */
3481 	  if (AGSA_RC_BUSY == retVal)
3482 	  {
3483 #ifdef SA_LL_IBQ_PROTECT
3484 		ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
3485 #endif /* SA_LL_IBQ_PROTECT */
3486 		/* if not sending return to free list rare */
3487 		ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3488 		saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
3489 		pRequest->valid = agFALSE;
3490 		saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
3491 		ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3492 
3493 		SA_DBG1(("saSMPStart, no more IOMB\n"));
3494 		smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "9a");
3495 		return AGSA_RC_BUSY;
3496 	  }
3497 #ifdef SA_LL_IBQ_PROTECT
3498 			  ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
3499 #endif /* SA_LL_IBQ_PROTECT */
3500 
3501 
3502 	if(smIS_SPC(agRoot))
3503 	{
3504 	 agsaSMPCmd_t payload;
3505 
3506 
3507 		  bit32 IR_IP_OV_res_phyId_DPdLen_res = 0;
3508 		  /* Prepare the payload of IOMB */
3509 		  si_memset(&payload, 0, sizeof(agsaSMPCmd_V_t));
3510 		  OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, tag), pRequest->HTag);
3511 		  OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, deviceId), pDevice->DeviceMapIndex);
3512 
3513 
3514 
3515 		  /*Indirect request and response*/
3516 		  if (smpFrameFlagIndirectResponse & pSMPFrame->flag && smpFrameFlagIndirectPayload & pSMPFrame->flag) /* */
3517 		  {
3518 
3519 			SA_DBG2(("saSMPStart:V Indirect payload and indirect response\n"));
3520 
3521 			/* Indirect Response mode */
3522 			pRequest->IRmode = INDIRECT_MODE;
3523 			IR_IP_OV_res_phyId_DPdLen_res = 3;
3524 
3525 
3526 			/* payload */
3527 			OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[4]), (pSMPFrame->outFrameAddrLower32));
3528 			OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[5]), (pSMPFrame->outFrameAddrUpper32));
3529 			OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[6]), (pSMPFrame->outFrameLen));
3530 
3531 			OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[8]), (pSMPFrame->inFrameAddrLower32));
3532 			OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[9]), (pSMPFrame->inFrameAddrUpper32));
3533 			OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[10]), (pSMPFrame->inFrameLen));
3534 
3535 		  }
3536 
3537 
3538 		  IR_IP_OV_res_phyId_DPdLen_res |= (pSMPFrame->flag & 3);
3539 		  /* fatal error if missing */
3540 		  OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, IR_IP_OV_res_phyId_DPdLen_res), IR_IP_OV_res_phyId_DPdLen_res);
3541 		  /* fatal error if missing */
3542 
3543 
3544 		/* check IR bit */
3545 
3546 		/* Build IOMB command and send it to SPC */
3547 		payload_ptr = (bit8 *)&payload;
3548 #ifdef SA_LL_IBQ_PROTECT
3549 				ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
3550 #endif /* SA_LL_IBQ_PROTECT */
3551 
3552 		ret = mpiSMPCmd(agRoot, pMessage, OPC_INB_SMP_REQUEST, (agsaSMPCmd_t *)payload_ptr, inq, outq);
3553 
3554 #ifdef SA_LL_IBQ_PROTECT
3555 			  ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
3556 #endif /* SA_LL_IBQ_PROTECT */
3557 
3558 
3559   }
3560 	else /* IOMB is different for SPCV SMP */
3561 	{
3562 	 agsaSMPCmd_V_t vpayload;
3563 
3564 
3565 		  bit32 IR_IP_OV_res_phyId_DPdLen_res = 0;
3566 		  /* Prepare the payload of IOMB */
3567 		  si_memset(&vpayload, 0, sizeof(agsaSMPCmd_V_t));
3568 		  OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, tag), pRequest->HTag);
3569 		  OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, deviceId), pDevice->DeviceMapIndex);
3570 		  OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMPHDR ), *((bit32*)pSMPFrame->outFrameBuf+0) );
3571 
3572 		  /*Indirect request and response*/
3573 		  if (smpFrameFlagIndirectResponse & pSMPFrame->flag && smpFrameFlagIndirectPayload & pSMPFrame->flag) /* */
3574 		  {
3575 
3576 			SA_DBG2(("saSMPStart:V Indirect payload and indirect response\n"));
3577 
3578 			/* Indirect Response mode */
3579 			pRequest->IRmode = INDIRECT_MODE;
3580 			IR_IP_OV_res_phyId_DPdLen_res = 3;
3581 
3582 
3583 			/* payload */
3584 			OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirL_SMPRF15_12 ), (pSMPFrame->outFrameAddrLower32));
3585 			OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirH_or_SMPRF19_16 ), (pSMPFrame->outFrameAddrUpper32));
3586 			OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirLen_or_SMPRF23_20 ), (pSMPFrame->outFrameLen));
3587 
3588 			OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,ISRAL_or_SMPRF31_28), (pSMPFrame->inFrameAddrLower32));
3589 			OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,ISRAH_or_SMPRF35_32), (pSMPFrame->inFrameAddrUpper32));
3590 			OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,ISRL_or_SMPRF39_36), (pSMPFrame->inFrameLen));
3591 
3592 		  }
3593 
3594 		  /*Direct request and indirect response*/
3595 		  else if (smpFrameFlagIndirectResponse & pSMPFrame->flag ) /* */
3596 		  {
3597 
3598   			SA_DBG2(("saSMPStart:V Direct payload and indirect response\n"));
3599 			IR_IP_OV_res_phyId_DPdLen_res = (pSMPFrame->outFrameLen << SHIFT16) | pSMPFrame->flag;
3600 
3601 
3602 			  /* Write IR_IP_OV_res_phyId_DPdLen_res field in the payload*/
3603 			  OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, IR_IP_OV_res_phyId_DPdLen_res), IR_IP_OV_res_phyId_DPdLen_res);
3604 			  /* setup indirect response frame address */
3605 			  OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRAL_or_SMPRF31_28 ), (pSMPFrame->inFrameAddrLower32));
3606 			  OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRAH_or_SMPRF35_32 ), (pSMPFrame->inFrameAddrUpper32));
3607 			  OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRL_or_SMPRF39_36 ), (pSMPFrame->inFrameLen));
3608 
3609 		  }
3610 		  IR_IP_OV_res_phyId_DPdLen_res |= (pSMPFrame->flag & 3);
3611 		  /* fatal error if missing */
3612 		  OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, IR_IP_OV_res_phyId_DPdLen_res), IR_IP_OV_res_phyId_DPdLen_res);
3613 		  /* fatal error if missing */
3614 
3615 
3616 		/* check IR bit */
3617 
3618 #ifdef SA_LL_IBQ_PROTECT
3619 				ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
3620 #endif /* SA_LL_IBQ_PROTECT */
3621 		/* Build IOMB command and send it to SPCv */
3622 		payload_ptr = (bit8 *)&vpayload;
3623 		ret = mpiSMPCmd(agRoot, pMessage, OPC_INB_SMP_REQUEST, (agsaSMPCmd_t *)payload_ptr, inq, outq);
3624 
3625 #ifdef SA_LL_IBQ_PROTECT
3626 			  ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
3627 #endif /* SA_LL_IBQ_PROTECT */
3628 
3629 
3630   }
3631 
3632 
3633   return ret;
3634 }
3635 
3636 
3637 /******************************************************************************/
3638 /*! \brief Reconfiguration of SAS Parameters Command
3639  *
3640  *  This command Reconfigure the SAS parameters to SPC.
3641  *
3642  *  \param agRoot       Handles for this instance of SAS/SATA LL
3643  *  \param agContext    Context of SPC FW Flash Update Command
3644  *  \param queueNum     Inbound/outbound queue number
3645  *  \param agSASConfig  Pointer of SAS Configuration Parameters
3646  *
3647  *  \return If the MPI command is sent to SPC successfully
3648  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
3649  *          - \e AGSA_RC_FAILURE the MPI command is failure
3650  *
3651  */
3652 /*******************************************************************************/
3653 //GLOBAL bit32 saReconfigSASParams(
3654 bit32 saReconfigSASParams(
3655   agsaRoot_t        *agRoot,
3656   agsaContext_t     *agContext,
3657   bit32             queueNum ,
3658   agsaSASReconfig_t *agSASConfig
3659   )
3660 {
3661   bit32 ret           = AGSA_RC_SUCCESS;
3662 
3663   /* sanity check */
3664   SA_ASSERT((agNULL != agRoot), "");
3665 
3666   if(smIS_SPCV(agRoot))
3667   {
3668     SA_DBG1(("saReconfigSASParams: AGSA_RC_FAILURE for SPCv\n" ));
3669     return(AGSA_RC_FAILURE);
3670   }
3671 
3672   /* build IOMB command and send to SPC */
3673   ret = mpiSasReinitializeCmd(agRoot, agContext, agSASConfig, queueNum);
3674 
3675   return ret;
3676 }
3677 
3678 /******************************************************************************/
3679 /*! \brief Dump GSM registers from the controller
3680  *
3681  *  \param agRoot         Handles for this instance of SAS/SATA hardware
3682  *  \param gsmDumpOffset  Offset of GSM
3683  *  \param length         Max is 1 MB
3684  *  \param directData     address of GSM data dump to
3685  *
3686  *  \return
3687  *          - \e AGSA_RC_SUCCESS saGSMDump is successfully
3688  *          - \e AGSA_RC_FAILURE saGSMDump is not successfully
3689  *
3690  */
3691 /*******************************************************************************/
3692 //LOCAL bit32 siGSMDump(
3693 bit32 siGSMDump(
3694   agsaRoot_t     *agRoot,
3695   bit32          gsmDumpOffset,
3696   bit32          length,
3697   void           *directData)
3698 {
3699   bit8  *dst;
3700   bit32 value, rem, offset = 0;
3701   bit32 i, workOffset, dwLength;
3702   bit32 bar = 0;
3703 
3704   SA_DBG1(("siGSMDump: gsmDumpOffset 0x%x length 0x%x\n", gsmDumpOffset, length));
3705 
3706   /* check max is 64k chunks */
3707   if (length > (64 * 1024))
3708   {
3709     SA_DBG1(("siGSMDump: Max length is greater than 64K  bytes 0x%x\n", length));
3710     return AGSA_RC_FAILURE;
3711   }
3712 
3713   if (gsmDumpOffset & 3)
3714   {
3715     SA_DBG1(("siGSMDump: Not allow NON_DW Boundary 0x%x\n", gsmDumpOffset));
3716     return AGSA_RC_FAILURE;
3717   }
3718 
3719   if ((gsmDumpOffset + length) > ONE_MEGABYTE)
3720   {
3721     SA_DBG1(("siGSMDump: Out of GSM end address boundary 0x%x\n", (gsmDumpOffset+length)));
3722     return AGSA_RC_FAILURE;
3723   }
3724 
3725   if( smIS_SPCV(agRoot))
3726   {
3727     bar = PCIBAR1;
3728   }
3729   else if( smIS_SPC(agRoot))
3730   {
3731     bar = PCIBAR2;
3732   }
3733   else
3734   {
3735     SA_DBG1(("siGSMDump: device type is not supported"));
3736     return AGSA_RC_FAILURE;
3737   }
3738 
3739   workOffset = gsmDumpOffset & 0xFFFF0000;
3740   offset = gsmDumpOffset & 0x0000FFFF;
3741   gsmDumpOffset = workOffset;
3742 
3743   dst = (bit8 *)directData;
3744 
3745   /* adjust length to dword boundary */
3746   rem = length & 3;
3747   dwLength = length >> 2;
3748 
3749   for (i =0; i < dwLength; i++)
3750   {
3751     if((workOffset + offset) > length )
3752     {
3753       break;
3754     }
3755     value = ossaHwRegReadExt(agRoot, bar, (workOffset + offset) & 0x0000FFFF);
3756     /* xfr for dw */
3757     si_memcpy(dst, &value, 4);
3758     dst += 4;
3759     offset += 4;
3760   }
3761 
3762   if (rem != 0)
3763   {
3764     value = ossaHwRegReadExt(agRoot, bar, (workOffset + offset) & 0x0000FFFF);
3765     /* xfr for non_dw */
3766     if(dst)
3767     {
3768       si_memcpy(dst, &value, rem);
3769     }
3770   }
3771 
3772   /* Shift back to BAR4 original address */
3773   if (AGSA_RC_FAILURE == siBar4Shift(agRoot, 0x0))
3774   {
3775     SA_DBG1(("siGSMDump:Shift Bar4 to 0x%x failed\n", 0x0));
3776     return AGSA_RC_FAILURE;
3777   }
3778 
3779   return AGSA_RC_SUCCESS;
3780 }
3781 
3782 //GLOBAL bit32 saPCIeDiagExecute(
3783 bit32 saPCIeDiagExecute(
3784             agsaRoot_t            *agRoot,
3785             agsaContext_t         *agContext,
3786             bit32                 queueNum,
3787             agsaPCIeDiagExecute_t *diag)
3788 {
3789   bit32                    ret    = AGSA_RC_SUCCESS;
3790   agsaLLRoot_t            *saRoot = agNULL;
3791   agsaIORequestDesc_t     *pRequest;
3792   bit32  payload[32];
3793 
3794   smTraceFuncEnter(hpDBG_VERY_LOUD,"6r");
3795 
3796   /* sanity check */
3797   SA_ASSERT((agNULL != agRoot), "");
3798 
3799   saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
3800   /* sanity check */
3801   SA_ASSERT((agNULL != saRoot), "");
3802   SA_ASSERT((agNULL != diag), "");
3803 
3804   if(diag->len == 0)
3805   {
3806     SA_DBG1(("saPCIeDiagExecute,  diag->len Zero\n"));
3807   }
3808   SA_DBG1(("saPCIeDiagExecute, diag->command  0x%X\n", diag->command ));
3809   SA_DBG1(("saPCIeDiagExecute, diag->flags  0x%X\n",diag->flags ));
3810   SA_DBG1(("saPCIeDiagExecute,  diag->initialIOSeed  0x%X\n", diag->initialIOSeed));
3811   SA_DBG1(("saPCIeDiagExecute, diag->reserved   0x%X\n",diag->reserved ));
3812   SA_DBG1(("saPCIeDiagExecute, diag->rdAddrLower   0x%X\n", diag->rdAddrLower));
3813   SA_DBG1(("saPCIeDiagExecute, diag->rdAddrUpper   0x%X\n", diag->rdAddrUpper ));
3814   SA_DBG1(("saPCIeDiagExecute, diag->wrAddrLower   0x%X\n", diag->wrAddrLower));
3815   SA_DBG1(("saPCIeDiagExecute, diag->wrAddrUpper   0x%X\n",diag->wrAddrUpper ));
3816   SA_DBG1(("saPCIeDiagExecute,  diag->len   0x%X\n",diag->len  ));
3817   SA_DBG1(("saPCIeDiagExecute, diag->pattern  0x%X\n",diag->pattern ));
3818   SA_DBG1(("saPCIeDiagExecute, %02X %02X %02X %02X %02X %02X\n",
3819                   diag->udtArray[0],
3820                   diag->udtArray[1],
3821                   diag->udtArray[2],
3822                   diag->udtArray[3],
3823                   diag->udtArray[4],
3824                   diag->udtArray[5] ));
3825 
3826    SA_DBG1(("saPCIeDiagExecute, %02X %02X %02X %02X %02X %02X\n",
3827                   diag->udrtArray[0],
3828                   diag->udrtArray[1],
3829                   diag->udrtArray[2],
3830                   diag->udrtArray[3],
3831                   diag->udrtArray[4],
3832                   diag->udrtArray[5]));
3833 
3834 
3835   /* Get request from free IORequests */
3836   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3837   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
3838 
3839   /* If no LL Control request entry available */
3840   if ( agNULL == pRequest )
3841   {
3842     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3843     SA_DBG1(("saPCIeDiagExecute, No request from free list\n" ));
3844     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "6r");
3845     return AGSA_RC_BUSY;
3846   }
3847   /* If LL Control request entry avaliable */
3848   /* Remove the request from free list */
3849   saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
3850   saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
3851   saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
3852   saRoot->IOMap[pRequest->HTag].agContext = agContext;
3853   pRequest->valid = agTRUE;
3854 
3855   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3856 
3857   /* set payload to zeros */
3858   si_memset(&payload, 0, sizeof(payload));
3859 
3860   if(smIS_SPCV(agRoot))
3861   {
3862     bit32      UDTR1_UDT0 ,UDT5_UDT2,UDTR5_UDTR2;
3863 
3864     UDTR5_UDTR2 = (( diag->udrtArray[5] << SHIFT24) | (diag->udrtArray[4] << SHIFT16) | (diag->udrtArray[3] << SHIFT8) | diag->udrtArray[2]);
3865     UDT5_UDT2 =   ((  diag->udtArray[5] << SHIFT24) |  (diag->udtArray[4] << SHIFT16) |  (diag->udtArray[3] << SHIFT8) |  diag->udtArray[2]);
3866     UDTR1_UDT0 =  (( diag->udrtArray[1] << SHIFT24) | (diag->udrtArray[0] << SHIFT16) |  (diag->udtArray[1] << SHIFT8) |  diag->udtArray[0]);
3867 
3868     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, tag)        , pRequest->HTag);
3869     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, CmdTypeDesc), diag->command );
3870     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, UUM_EDA)    , diag->flags);
3871     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, UDTR1_UDT0) , UDTR1_UDT0);
3872     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, UDT5_UDT2)  , UDT5_UDT2);
3873     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, UDTR5_UDTR2), UDTR5_UDTR2);
3874     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, Res_IOS)    , diag->initialIOSeed);
3875     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, rdAddrLower), diag->rdAddrLower);
3876     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, rdAddrUpper), diag->rdAddrUpper);
3877     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, wrAddrLower), diag->wrAddrLower);
3878     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, wrAddrUpper), diag->wrAddrUpper);
3879     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, len),         diag->len);
3880     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPCIeDiagExecuteCmd_t, pattern),     diag->pattern);
3881     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_PCIE_DIAG_EXECUTE, IOMB_SIZE128, queueNum);
3882   }
3883   else
3884   {
3885     /* build IOMB command and send to SPC */
3886     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_PCIDiagExecuteCmd_t, tag),         pRequest->HTag);
3887     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_PCIDiagExecuteCmd_t, CmdTypeDesc), diag->command );
3888     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_PCIDiagExecuteCmd_t, rdAddrLower), diag->rdAddrLower);
3889     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_PCIDiagExecuteCmd_t, rdAddrUpper), diag->rdAddrUpper);
3890     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_PCIDiagExecuteCmd_t, wrAddrLower), diag->wrAddrLower);
3891     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_PCIDiagExecuteCmd_t, wrAddrUpper), diag->wrAddrUpper);
3892     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_PCIDiagExecuteCmd_t, len),         diag->len);
3893     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsa_SPC_PCIDiagExecuteCmd_t, pattern),     diag->pattern);
3894     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_PCIE_DIAG_EXECUTE, IOMB_SIZE64, queueNum);
3895   }
3896 
3897   if (AGSA_RC_SUCCESS != ret)
3898   {
3899     /* remove the request from IOMap */
3900     saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
3901     saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
3902     saRoot->IOMap[pRequest->HTag].agContext = agNULL;
3903 
3904     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3905     pRequest->valid = agFALSE;
3906 
3907     /* return the request to free pool */
3908     saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
3909 
3910     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3911 
3912     SA_DBG1(("saPCIeDiagExecute, sending IOMB failed\n" ));
3913     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "6r");
3914 
3915     return ret;
3916   }
3917 
3918   smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "6r");
3919   return ret;
3920 }
3921 
3922 //GLOBAL bit32 saGetDFEData(
3923 bit32 saGetDFEData(
3924                           agsaRoot_t     *agRoot,
3925                           agsaContext_t  *agContext,
3926                           bit32           queueNum,
3927                           bit32           interface,
3928                           bit32           laneNumber,
3929                           bit32           interations,
3930                           agsaSgl_t      *agSgl)
3931 {
3932   bit32                    ret    = AGSA_RC_SUCCESS;
3933   agsaLLRoot_t            *saRoot = agNULL;
3934   agsaIORequestDesc_t     *pRequest = agNULL;
3935   bit32  payload[32];
3936   bit32 reserved_In_Ln;
3937 
3938   smTraceFuncEnter(hpDBG_VERY_LOUD,"2X");
3939   /* sanity check */
3940   SA_ASSERT((agNULL != agRoot), "");
3941   saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
3942   SA_ASSERT((agNULL != saRoot), "");
3943   SA_ASSERT((agNULL != agSgl), "");
3944 
3945   /* Get request from free IORequests */
3946   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3947   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
3948 
3949   /* If no LL Control request entry available */
3950   if ( agNULL == pRequest )
3951   {
3952     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3953     SA_DBG1(("saGetDFEData, No request from free list\n" ));
3954     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2X");
3955     return AGSA_RC_BUSY;
3956   }
3957   /* If LL Control request entry avaliable */
3958   /* Remove the request from free list */
3959   saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
3960   saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
3961   saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
3962   saRoot->IOMap[pRequest->HTag].agContext = agContext;
3963   pRequest->valid = agTRUE;
3964 
3965   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3966 
3967   /* set payload to zeros */
3968   si_memset(&payload, 0, sizeof(payload));
3969 
3970   if(smIS_SPCV(agRoot))
3971   {
3972     reserved_In_Ln = ((interface & 0x1) << SHIFT7) | (laneNumber & 0x7F);
3973     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDDEFDataCmd_t, tag)        , pRequest->HTag);
3974     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDDEFDataCmd_t, reserved_In_Ln)        , reserved_In_Ln);
3975     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDDEFDataCmd_t, MCNT)        , interations);
3976     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDDEFDataCmd_t, Buf_AddrL)        , agSgl->sgLower);
3977     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDDEFDataCmd_t, Buf_AddrH)        , agSgl->sgUpper);
3978     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDDEFDataCmd_t, Buf_Len)        , agSgl->len);
3979     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDDEFDataCmd_t, E_reserved)        , agSgl->extReserved);
3980     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_DFE_DATA, IOMB_SIZE128, queueNum);
3981 
3982   }
3983   else
3984   {
3985     /* SPC does not support this command */
3986     ret = AGSA_RC_FAILURE;
3987   }
3988 
3989   if (AGSA_RC_SUCCESS != ret)
3990   {
3991     /* remove the request from IOMap */
3992     saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
3993     saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
3994     saRoot->IOMap[pRequest->HTag].agContext = agNULL;
3995 
3996     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
3997     pRequest->valid = agFALSE;
3998     /* return the request to free pool */
3999     saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
4000     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
4001 
4002     SA_DBG1(("saPCIeDiagExecute, sending IOMB failed\n" ));
4003     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2X");
4004     return ret;
4005   }
4006 
4007   smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2X");
4008   return ret;
4009 }
4010 
4011