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