xref: /freebsd/sys/dev/pms/RefTisa/sallsdk/spc/sampicmd.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
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 sampicmd.c
24  *  \brief The file implements the functions of MPI Inbound IOMB/Command to 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 'I'
37 #endif
38 
39 /******************************************************************************/
40 /*! \brief SAS/SATA LL API ECHO Command
41  *
42  *  This command used to test that MPI between host and SPC IOP is operational.
43  *
44  *  \param agRoot       Handles for this instance of SAS/SATA hardware
45  *  \param agContext    Context of SPC FW Flash Update Command
46  *  \param queueNum     Inbound/outbound queue number
47  *  \param echoPayload  Pointer of Echo payload of IOMB
48  *
49  *  \return If the MPI command is sent to SPC successfully
50  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
51  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
52  *          - \e AGSA_RC_FAILURE the MPI command is failure
53  *
54  */
55 /*******************************************************************************/
56 GLOBAL bit32 saEchoCommand(
57   agsaRoot_t            *agRoot,
58   agsaContext_t         *agContext,
59   bit32                 queueNum,
60   void                  *echoPayload
61 )
62 {
63   bit32 ret = AGSA_RC_SUCCESS;
64 
65   smTraceFuncEnter(hpDBG_VERY_LOUD, "xa");
66 
67   /* setup IOMB payload */
68   ret = mpiEchoCmd(agRoot, queueNum, agContext, echoPayload);
69 
70   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xa");
71 
72   return ret;
73 }
74 
75 /******************************************************************************/
76 /*! \brief Build a IOMB command and send to SPC
77  *
78  *  Build an IOMB if there is a free message buffer and Send it to SPC
79  *
80  *  \param agRoot       Handles for this instance of SAS/SATA hardware
81  *  \param payload      Pointer of payload in the IOMB
82  *  \param category     Category of IOMB
83  *  \param opcode       Opcode of IOMB
84  *  \param size         Size of IOMB
85  *  \param queueNum     Inbound/outbound queue number
86  *
87  *  \return If the MPI command is sent to SPC successfully
88  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
89  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
90  *          - \e AGSA_RC_FAILURE the MPI command is failure
91  */
92 /*******************************************************************************/
93 GLOBAL bit32 mpiBuildCmd(
94   agsaRoot_t        *agRoot,
95   bit32             *payload,
96   mpiMsgCategory_t  category,
97   bit16             opcode,
98   bit16             size,
99   bit32             queueNum
100   )
101 {
102   agsaLLRoot_t      *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
103   mpiICQueue_t      *circularQ;
104   void              *pMessage;
105   bit32             ret = AGSA_RC_SUCCESS;
106   bit32             retVal;
107   bit8              inq, outq;
108 
109   smTraceFuncEnter(hpDBG_VERY_LOUD, "xb");
110 
111   inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
112   outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
113   SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
114   SA_ASSERT((AGSA_MAX_OUTBOUND_Q > outq), "The OBQ Number is out of range.");
115 
116 #ifdef SA_USE_MAX_Q
117   outq = saRoot->QueueConfig.numOutboundQueues -1;
118   SA_DBG1(("mpiBuildCmd, set OBQ to  %d\n",outq));
119 #endif /* SA_USE_MAX_Q */
120   /* get a free inbound queue entry */
121 
122 #ifdef SA_LL_IBQ_PROTECT
123   ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
124 #endif /* SA_LL_IBQ_PROTECT */
125 
126   circularQ = &saRoot->inboundQueue[inq];
127   retVal    = mpiMsgFreeGet(circularQ, size, &pMessage);
128 
129   /* return FAILURE if error happened */
130   if (AGSA_RC_FAILURE == retVal)
131   {
132 #ifdef SA_LL_IBQ_PROTECT
133     ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
134 #endif /* SA_LL_IBQ_PROTECT */
135     /* the message size exceeds the inbound queue message size */
136     SA_DBG1(("mpiBuildCmd, failure\n"));
137     ret = AGSA_RC_FAILURE;
138     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xb");
139     return ret;
140   }
141 
142   /* return BUSY if no more inbound queue entry available */
143   if (AGSA_RC_BUSY == retVal)
144   {
145     SA_DBG1(("mpiBuildCmd, no more IOMB\n"));
146     ret = AGSA_RC_BUSY;
147   }
148   else
149   {
150     /* copy payload if it is necessary */
151     if (agNULL != payload)
152     {
153       si_memcpy(pMessage, payload, (size - sizeof(mpiMsgHeader_t)));
154     }
155 
156     /* post the message to SPC */
157     if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pMessage, category, opcode, outq, (bit8)circularQ->priority))
158     {
159       ret = AGSA_RC_FAILURE;
160     }
161   }
162 
163 #ifdef SA_LL_IBQ_PROTECT
164   ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
165 #endif /* SA_LL_IBQ_PROTECT */
166 
167   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xb");
168   return ret;
169 }
170 
171 /******************************************************************************/
172 /*! \brief SPC MPI ECHO Command
173  *
174  *  This command used to test that MPI between host and SPC IOP is operational.
175  *
176  *  \param agRoot       Handles for this instance of SAS/SATA LLL
177  *  \param queueNum     Inbound/outbound queue number
178  *  \param tag          Tag of this IOMB
179  *  \param echoPayload  Pointer to the ECHO payload of inbound IOMB
180  *
181  *  \return If the MPI command is sent to SPC successfully
182  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
183  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
184  *          - \e AGSA_RC_FAILURE the MPI command is failure
185  *
186  */
187 /*******************************************************************************/
188 GLOBAL bit32 mpiEchoCmd(
189   agsaRoot_t          *agRoot,
190   bit32               queueNum,
191   agsaContext_t       *agContext,
192   void                *echoPayload
193   )
194 {
195   bit32               ret = AGSA_RC_SUCCESS;
196   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
197   agsaIORequestDesc_t *pRequest;
198   agsaEchoCmd_t       payload;
199 
200   smTraceFuncEnter(hpDBG_VERY_LOUD, "xc");
201 
202   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
203   /* Get request from free IORequests */
204   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
205 
206   /* If no LL Control request entry available */
207   if ( agNULL == pRequest )
208   {
209     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
210     SA_DBG1(("mpiEchoCmd, No request from free list\n" ));
211     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xc");
212     return AGSA_RC_BUSY;
213   }
214   /* If LL Control request entry avaliable */
215   else
216   {
217     /* Remove the request from free list */
218     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
219     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
220     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
221     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
222     saRoot->IOMap[pRequest->HTag].agContext = agContext;
223     pRequest->valid = agTRUE;
224 
225     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
226 
227 
228     /* build IOMB command and send to SPC */
229     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaEchoCmd_t, tag), pRequest->HTag);
230     /* copy Echo payload */
231     si_memcpy(&payload.payload[0], echoPayload, (sizeof(agsaEchoCmd_t) - 4));
232     /* build IOMB command and send to SPC */
233     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_ECHO, IOMB_SIZE64, queueNum);
234     SA_DBG3(("mpiEchoCmd, return value = %d\n", ret));
235     if (AGSA_RC_SUCCESS != ret)
236     {
237       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
238       /* remove the request from IOMap */
239       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
240       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
241       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
242       pRequest->valid = agFALSE;
243       /* return the request to free pool */
244       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
245 
246       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
247 
248       SA_DBG1(("mpiEchoCmd, sending IOMB failed\n" ));
249     }
250 #ifdef SALL_API_TEST
251     else
252     {
253       saRoot->LLCounters.IOCounter.numEchoSent++;
254     }
255 #endif
256 
257   }
258 
259   /* return value */
260   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xc");
261   return ret;
262 }
263 
264 
265 /******************************************************************************/
266 /*! \brief Get Phy Profile Command SPCv
267  *
268  *  This command is get # of phys and support speeds from SPCV.
269  *
270  *  \param agRoot       Handles for this instance of SAS/SATA LLL
271  *  \param agDevHandle  Handle of device
272  *
273  *  \return If the MPI command is sent to SPC successfully
274  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
275  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
276  *          - \e AGSA_RC_FAILURE the MPI command is failure
277  *
278  */
279 /*******************************************************************************/
280 
281 
282 GLOBAL bit32 mpiGetPhyProfileCmd(
283   agsaRoot_t          *agRoot,
284   agsaContext_t       *agContext,
285   bit32                Operation,
286   bit32                PhyId,
287   void                *agCB
288   )
289 {
290   agsaLLRoot_t            *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
291   agsaIORequestDesc_t     *pRequest;
292   bit32                   ret = AGSA_RC_SUCCESS;
293   agsaGetPhyProfileCmd_V_t   payload;
294 
295   smTraceFuncEnter(hpDBG_VERY_LOUD, "xd");
296 
297   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
298   /* Get request from free IORequests */
299   pRequest = (agsaIORequestDesc_t *)saLlistGetHead(&(saRoot->freeIORequests));
300 
301   SA_DBG1(("mpiGetPhyProfileCmd, Operation 0x%x PhyId %d \n",Operation ,PhyId ));
302 
303   /* If no LL Control request entry avalibale */
304   if ( agNULL == pRequest )
305   {
306     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
307     SA_DBG1(("mpiGetPhyProfileCmd, No request from free list\n" ));
308     return AGSA_RC_BUSY;
309   }
310   /* If LL Control request entry avaliable */
311   else
312   {
313     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
314 
315     /* Remove the request from free list */
316     saLlistRemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
317     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
318     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
319     saRoot->IOMap[pRequest->HTag].agContext = agContext;
320 
321     pRequest->valid = agTRUE;
322     pRequest->completionCB  = agCB;
323     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
324 
325 
326     /* set payload to zeros */
327     si_memset(&payload, 0, sizeof(agsaGetPhyProfileCmd_V_t));
328 
329     /* set tag field */
330     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetPhyProfileCmd_V_t, tag), pRequest->HTag);
331     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetPhyProfileCmd_V_t, Reserved_Ppc_SOP_PHYID), (((Operation & 0xF) << SHIFT8 ) | (PhyId  & 0xFF) ) );
332     /* build IOMB command and send to SPC */
333     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_PHY_PROFILE, IOMB_SIZE128, 0);
334     if (AGSA_RC_SUCCESS != ret)
335     {
336       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
337       pRequest->valid = agFALSE;
338       /* return the request to free pool */
339       saLlistAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
340       /* remove the request from IOMap */
341       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
342       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
343       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
344       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
345 
346       SA_DBG1(("mpiGetPhyProfileCmd, sending IOMB failed\n" ));
347     }
348     SA_DBG3(("mpiGetPhyProfileCmd, return value = %d\n", ret));
349   }
350 
351   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xd");
352   /* return value */
353   return ret;
354 }
355 
356 
357 GLOBAL bit32 mpiVHistCapCmd(
358                           agsaRoot_t    *agRoot,
359                           agsaContext_t *agContext,
360                           bit32         queueNum,
361                           bit32         Channel,
362                           bit32         NumBitLo,
363                           bit32         NumBitHi,
364                           bit32         PcieAddrLo,
365                           bit32         PcieAddrHi,
366                           bit32         ByteCount )
367 {
368   agsaLLRoot_t            *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
369   agsaIORequestDesc_t     *pRequest= agNULL;
370   bit32                   ret = AGSA_RC_SUCCESS;
371   agsaGetVHistCap_V_t payload;
372 
373   smTraceFuncEnter(hpDBG_VERY_LOUD,"3C");
374   SA_DBG1(("mpiVHistCapCmd\n"));
375 
376   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
377   /* Get request from free IORequests */
378   pRequest = (agsaIORequestDesc_t *)saLlistGetHead(&(saRoot->freeIORequests));
379   /* If no LL Control request entry avalibale */
380   if ( agNULL == pRequest )
381   {
382     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
383     SA_DBG1((", No request from free list\n" ));
384     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3C");
385     return AGSA_RC_BUSY;
386   }
387   /* If LL Control request entry avaliable */
388   else
389   {
390     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
391     /* Remove the request from free list */
392     saLlistRemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
393     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
394     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
395     saRoot->IOMap[pRequest->HTag].agContext = agContext;
396 
397     pRequest->valid = agTRUE;
398     pRequest->completionCB  = (void *)ossaGetPhyProfileCB;
399     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
400 
401     /* set payload to zeros */
402     si_memset(&payload, 0, sizeof(agsaGetVHistCap_V_t));
403 
404     /* set tag field */
405     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, tag),       pRequest->HTag);
406     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, Channel),   Channel );
407     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, NumBitLo),  NumBitLo);
408     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, NumBitHi),  NumBitHi);
409     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, PcieAddrLo),PcieAddrLo);
410     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, PcieAddrHi),PcieAddrHi);
411     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, ByteCount), ByteCount );
412 
413 
414     /* build IOMB command and send to SPC */
415     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_VHIST_CAP, IOMB_SIZE128,queueNum );
416     if (AGSA_RC_SUCCESS != ret)
417     {
418       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
419       pRequest->valid = agFALSE;
420       /* return the request to free pool */
421       saLlistAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
422       /* remove the request from IOMap */
423       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
424       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
425       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
426       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
427 
428       SA_DBG1(("mpiVHistCapCmd, sending IOMB failed\n" ));
429     }
430     SA_DBG3(("mpiVHistCapCmd, return value = %d\n", ret));
431   }
432 
433   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3C");
434   /* return value */
435 
436   return(ret);
437 }
438 
439 GLOBAL bit32 mpiSetPhyProfileCmd(
440   agsaRoot_t    *agRoot,
441   agsaContext_t *agContext,
442   bit32         Operation,
443   bit32         PhyId,
444   bit32         length,
445   void *        buffer
446   )
447 {
448   agsaLLRoot_t            *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
449   agsaIORequestDesc_t     *pRequest;
450   bit32                   ret = AGSA_RC_SUCCESS;
451   bit32                   i;
452   agsaSetPhyProfileCmd_V_t     payload;
453   bit32               * PageData =(bit32 * )buffer;
454 
455   smTraceFuncEnter(hpDBG_VERY_LOUD,"2P");
456 
457   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
458   /* Get request from free IORequests */
459   pRequest = (agsaIORequestDesc_t *)saLlistGetHead(&(saRoot->freeIORequests));
460 
461   SA_DBG1(("mpiSetPhyProfileCmd, Operation 0x%x PhyId %d \n",Operation ,PhyId ));
462 
463   /* If no LL Control request entry avalibale */
464   if ( agNULL == pRequest )
465   {
466     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
467     SA_DBG1(("mpiSetPhyProfileCmd, No request from free list\n" ));
468     return AGSA_RC_BUSY;
469   }
470   /* If LL Control request entry avaliable */
471   else
472   {
473     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
474     /* Remove the request from free list */
475     saLlistRemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
476     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
477     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
478     saRoot->IOMap[pRequest->HTag].agContext = agContext;
479 
480     pRequest->valid = agTRUE;
481     pRequest->SOP = (bit16) Operation;
482     pRequest->completionCB  = (void *)ossaGetPhyProfileCB;
483     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
484 
485 
486     /* set payload to zeros */
487     si_memset(&payload, 0, sizeof(agsaSetPhyProfileCmd_V_t));
488 
489     /* set tag field */
490     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetPhyProfileCmd_V_t, tag), pRequest->HTag);
491     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetPhyProfileCmd_V_t, Reserved_Ppc_SOP_PHYID), (((Operation & 0xF) << SHIFT8 ) | (PhyId  & 0xFF) ) );
492 
493     for(i=0; i < (length / sizeof(bit32)); i++)
494     {
495       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetPhyProfileCmd_V_t, PageSpecificArea[i]),* (PageData+i)  );
496     }
497 
498     /* build IOMB command and send to SPC */
499     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_PHY_PROFILE, IOMB_SIZE128, 0);
500     if (AGSA_RC_SUCCESS != ret)
501     {
502       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
503       pRequest->valid = agFALSE;
504       /* return the request to free pool */
505       saLlistAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
506       /* remove the request from IOMap */
507       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
508       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
509       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
510       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
511 
512       SA_DBG1(("mpiSetPhyProfileCmd, sending IOMB failed\n" ));
513     }
514     SA_DBG3(("mpiGetPhyProfileCmd, return value = %d\n", ret));
515   }
516 
517   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2P");
518   /* return value */
519   return ret;
520 }
521 
522 
523 /******************************************************************************/
524 /*! \brief Get Device Information Command
525  *
526  *  This command is get # of phys and support speeds from SPC.
527  *
528  *  \param agRoot       Handles for this instance of SAS/SATA LLL
529  *  \param agDevHandle  Handle of device
530  *  \param deviceid     Device Id
531  *  \param opton        oprion
532  *
533  *  \return If the MPI command is sent to SPC successfully
534  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
535  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
536  *          - \e AGSA_RC_FAILURE the MPI command is failure
537  *
538  */
539 /*******************************************************************************/
540 GLOBAL bit32 mpiGetDeviceInfoCmd(
541   agsaRoot_t          *agRoot,
542   agsaContext_t       *agContext,
543   bit32               deviceid,
544   bit32               option,
545   bit32               queueNum
546   )
547 {
548   agsaLLRoot_t            *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
549   agsaIORequestDesc_t     *pRequest;
550   bit32                   ret = AGSA_RC_SUCCESS;
551   agsaGetDevInfoCmd_t     payload;
552 
553   SA_ASSERT((agNULL !=saRoot ), "");
554   if(saRoot == agNULL)
555   {
556     SA_DBG1(("mpiGetDeviceInfoCmd: saRoot == agNULL\n"));
557     return(AGSA_RC_FAILURE);
558   }
559   smTraceFuncEnter(hpDBG_VERY_LOUD,"2K");
560 
561   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
562   /* Get request from free IORequests */
563   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
564 
565   /* If no LL Control request entry available */
566   if ( agNULL == pRequest )
567   {
568     SA_DBG1(("mpiGetDeviceInfoCmd, No request from free list\n" ));
569     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2K");
570     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
571     return AGSA_RC_BUSY;
572   }
573   /* If LL Control request entry avaliable */
574   else
575   {
576     /* Remove the request from free list */
577     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
578     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
579     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
580     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
581     saRoot->IOMap[pRequest->HTag].agContext = agContext;
582     pRequest->valid = agTRUE;
583     pRequest->DeviceInfoCmdOption = (bit8)option;
584     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
585 
586 
587     /* set payload to zeros */
588     si_memset(&payload, 0, sizeof(agsaGetDevInfoCmd_t));
589 
590     /* set tag field */
591     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDevInfoCmd_t, tag), pRequest->HTag);
592     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDevInfoCmd_t, DeviceId), deviceid);
593     /* build IOMB command and send to SPC */
594     if( smIS_SPC(agRoot))
595     {
596       ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SPC_GET_DEV_INFO, IOMB_SIZE64, queueNum);
597     }
598     else
599     {
600       ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_DEV_INFO, IOMB_SIZE64, queueNum);
601     }
602     if (AGSA_RC_SUCCESS != ret)
603     {
604       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
605       /* remove the request from IOMap */
606       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
607       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
608       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
609       pRequest->valid = agFALSE;
610       /* return the request to free pool */
611       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
612       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
613 
614       SA_DBG1(("mpiGetDeviceInfoCmd, sending IOMB failed\n" ));
615     }
616     SA_DBG3(("mpiGetDeviceInfoCmd, return value = %d\n", ret));
617   }
618 
619   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2K");
620   /* return value */
621   return ret;
622 }
623 
624 /******************************************************************************/
625 /*! \brief Set Device Information Command
626  *
627  *  This command is Set Device Information to SPC.
628  *
629  *  \param agRoot       Handles for this instance of SAS/SATA LLL
630  *  \param agDevHandle  Handle of device
631  *  \param deviceid     Device Id
632  *  \param opton        oprion
633  *
634  *  \return If the MPI command is sent to SPC successfully
635  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
636  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
637  *          - \e AGSA_RC_FAILURE the MPI command is failure
638  *
639  */
640 /*******************************************************************************/
641 GLOBAL bit32 mpiSetDeviceInfoCmd(
642   agsaRoot_t          *agRoot,
643   agsaContext_t       *agContext,
644   bit32               deviceid,
645   bit32               option,
646   bit32               queueNum,
647   bit32               param,
648   ossaSetDeviceInfoCB_t   agCB
649   )
650 {
651   agsaLLRoot_t            *saRoot = agNULL;
652   agsaIORequestDesc_t     *pRequest = agNULL;
653   bit32                   ret = AGSA_RC_SUCCESS;
654   agsaSetDevInfoCmd_t     payload;
655 
656   smTraceFuncEnter(hpDBG_VERY_LOUD,"xe");
657 
658   /* sanity check */
659   SA_ASSERT((agNULL != agRoot), "");
660   saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
661   SA_ASSERT((agNULL != saRoot), "");
662 
663   /* Get request from free IORequests */
664   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
665   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
666 
667   SA_DBG2(("mpiSetDeviceInfoCmd, param 0x%08X option 0x%08X\n",param,option ));
668 
669   /* If no LL Control request entry available */
670   if ( agNULL == pRequest )
671   {
672     SA_DBG1(("mpiSetDeviceInfoCmd, No request from free list\n" ));
673     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xe");
674     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
675     return AGSA_RC_BUSY;
676   }
677   /* If LL Control request entry avaliable */
678   else
679   {
680     /* Remove the request from free list */
681     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
682     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
683     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
684     saRoot->IOMap[pRequest->HTag].agContext = agContext;
685     pRequest->valid = agTRUE;
686     pRequest->completionCB = (ossaSSPCompletedCB_t)agCB;
687     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
688 
689     /* set payload to zeros */
690     si_memset(&payload, 0, sizeof(agsaSetDevInfoCmd_t));
691 
692     /* set tag field */
693 
694     if(smIS_SPC(agRoot))
695     {
696       option &= SET_DEV_INFO_SPC_DW3_MASK;
697       param  &= SET_DEV_INFO_SPC_DW4_MASK;
698     }
699     else
700     {
701       option &= SET_DEV_INFO_V_DW3_MASK;
702       param  &= SET_DEV_INFO_V_DW4_MASK;
703     }
704 
705     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDevInfoCmd_t, tag), pRequest->HTag);
706     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDevInfoCmd_t, deviceId), deviceid);
707     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDevInfoCmd_t, SA_SR_SI), option);
708     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDevInfoCmd_t, DEVA_MCN_R_ITNT), param );
709 
710     /* build IOMB command and send to SPC */
711     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_DEV_INFO, IOMB_SIZE64, queueNum);
712     if (AGSA_RC_SUCCESS != ret)
713     {
714       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
715       /* remove the request from IOMap */
716       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
717       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
718       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
719       pRequest->valid = agFALSE;
720 
721       /* return the request to free pool */
722       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
723       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
724 
725       SA_DBG1(("mpiSetDeviceInfoCmd, sending IOMB failed\n" ));
726     }
727     SA_DBG3(("mpiSetDeviceInfoCmd, return value = %d\n", ret));
728   }
729 
730   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xe");
731   /* return value */
732 
733   return ret;
734 }
735 
736 /******************************************************************************/
737 /*! \brief SPC MPI Phy Start Command
738  *
739  *  This command sends to SPC for the I/O.
740  *
741  *  \param agRoot        Handles for this instance of SAS/SATA LLL
742  *  \param tag           tage for IOMB
743  *  \param phyId         the phy id of the link will be started
744  *  \param agPhyConfig   the phy properity
745  *  \param agSASIdentify the SAS identify frame will be sent by the phy
746  *
747  *  \return If the MPI command is sent to SPC successfully
748  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
749  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
750  *          - \e AGSA_RC_FAILURE the MPI command is failure
751  *
752  */
753 /*******************************************************************************/
754 GLOBAL bit32 mpiPhyStartCmd(
755   agsaRoot_t          *agRoot,
756   bit32               tag,
757   bit32               phyId,
758   agsaPhyConfig_t     *agPhyConfig,
759   agsaSASIdentify_t   *agSASIdentify,
760   bit32               queueNum
761   )
762 {
763   bit32               ret = AGSA_RC_SUCCESS;
764   agsaPhyStartCmd_t   payload;
765   bit32               *pValue;
766   bit32               *ptemp;
767   bit32               index;
768   bit32               dw2 = 0;
769 
770 #if defined(SALLSDK_DEBUG)
771   bit32               Sscd;
772 #endif  /* SALLSDK_DEBUG */
773   smTraceFuncEnter(hpDBG_VERY_LOUD,"xg");
774 
775   /* set payload to zeros */
776   si_memset(&payload, 0, sizeof(agsaPhyStartCmd_t));
777 
778   pValue = (bit32 *)agSASIdentify;
779   ptemp = (bit32 *)&payload.sasIdentify;
780   index = (agPhyConfig->phyProperties & 0x0ff00) >> SHIFT8;
781 
782 #if defined(SALLSDK_DEBUG)
783   Sscd =  (agPhyConfig->phyProperties & 0xf0000) >> SHIFT16;
784 #endif  /* SALLSDK_DEBUG */
785 
786   SA_DBG1(("mpiPhyStartCmd,phyId = %d dw 2 0x%08X\n",phyId ,((phyId & SM_PHYID_MASK) | ((agPhyConfig->phyProperties & 0xfff) << SHIFT8) | (agPhyConfig->phyProperties & 0xf0000) )));
787 
788 
789   SA_DBG2(("mpiPhyStartCmd,phyId 0x%x phyProperties 0x%x index 0x%x Sscd 0x%x\n",phyId, agPhyConfig->phyProperties,index,Sscd));
790 
791   dw2 = ((phyId & SM_PHYID_MASK)                             | /* PHY id */
792         ((agPhyConfig->phyProperties & 0x000000FF) << SHIFT8)| /* SLR Mode */
793          (agPhyConfig->phyProperties & 0x000f0000)           | /* SSCD */
794          (agPhyConfig->phyProperties & 0x00700000)           | /* setting bit20, bit21 and bit22 for optical mode */
795          (agPhyConfig->phyProperties & 0x00800000) );          /* bit23 active cable mode BCT Disable 12g only*/
796 
797   /* Haileah Phy analogsetting bit enable*/
798   if(smIS_SPC(agRoot))
799   {
800     if( smIS_spc8081(agRoot))
801     {
802        dw2 = dw2 | 0x08000;
803      }
804   }
805 
806   SA_DBG1(("mpiPhyStartCmd,dw2 0x%08x\n",dw2));
807   SA_ASSERT(((agSASIdentify->sasAddressHi[0] || agSASIdentify->sasAddressHi[1] ||
808   agSASIdentify->sasAddressHi[2] || agSASIdentify->sasAddressHi[3] ||
809   agSASIdentify->sasAddressLo[0] || agSASIdentify->sasAddressLo[1] ||
810   agSASIdentify->sasAddressLo[2] || agSASIdentify->sasAddressLo[3])), "SAS Address Zero");
811 
812   SA_DBG1(("mpiPhyStartCmd,SAS addr Hi 0x%02X%02X%02X%02X Lo 0x%02X%02X%02X%02X\n",
813                                                               agSASIdentify->sasAddressHi[0],agSASIdentify->sasAddressHi[1],
814                                                               agSASIdentify->sasAddressHi[2],agSASIdentify->sasAddressHi[3],
815                                                               agSASIdentify->sasAddressLo[0],agSASIdentify->sasAddressLo[1],
816                                                               agSASIdentify->sasAddressLo[2],agSASIdentify->sasAddressLo[3]));
817 
818   /* setup phy ID field */
819   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPhyStartCmd_t, SscdAseSHLmMlrPhyId),dw2);
820 
821   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPhyStartCmd_t, tag), tag);
822 
823   /* setup analog setting index field */
824   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPhyStartCmd_t, analogSetupIdx), index);
825   /* copy SASIdentify to payload of IOMB */
826   si_memcpy(ptemp, pValue, sizeof(agsaSASIdentify_t));
827 
828   /* build IOMB command and send to SPC */
829   ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_PHYSTART, IOMB_SIZE64, queueNum);
830 
831   SA_DBG3(("mpiPhyStartCmd, return value = %d\n", ret));
832 
833   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xg");
834   return ret;
835 }
836 
837 /******************************************************************************/
838 /*! \brief SPC MPI Phy Stop Command
839  *
840  *  This command sends to SPC for the I/O.
841  *
842  *  \param agRoot       Handles for this instance of SAS/SATA LLL
843  *  \param tag          tag of IOMB
844  *  \param phyId        To stop the phyId
845  *
846  *  \return If the MPI command is sent to SPC successfully
847  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
848  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
849  *          - \e AGSA_RC_FAILURE the MPI command is failure
850  *
851  */
852 /*******************************************************************************/
853 GLOBAL bit32 mpiPhyStopCmd(
854   agsaRoot_t          *agRoot,
855   bit32               tag,
856   bit32               phyId,
857   bit32               queueNum
858   )
859 {
860   bit32 ret = AGSA_RC_SUCCESS;
861   agsaPhyStopCmd_t    payload;
862 
863   smTraceFuncEnter(hpDBG_VERY_LOUD,"xh");
864 
865   /* set payload to zeros */
866   si_memset(&payload, 0, sizeof(agsaPhyStopCmd_t));
867 
868   /* set tag */
869   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPhyStopCmd_t, tag), tag);
870   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPhyStopCmd_t, phyId), (phyId & SM_PHYID_MASK ));
871   /* build IOMB command and send to SPC */
872   ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_PHYSTOP, IOMB_SIZE64, queueNum);
873 
874   SA_DBG3(("mpiPhyStopCmd, return value = %d\n", ret));
875 
876   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xh");
877 
878   return ret;
879 }
880 
881 /******************************************************************************/
882 /*! \brief SPC MPI SMP Request Command
883  *
884  *  This command sends to SPC for the SMP.
885  *
886  *  \param agRoot       Handles for this instance of SAS/SATA LLL
887  *  \param pIomb        pointer of IOMB
888  *  \param opcode       opcode of IOMB
889  *  \param payload      pointer of payload
890  *  \param inq          inbound queue number
891  *  \param outq         outbound queue number
892  *
893  *  \return If the MPI command is sent to SPC successfully
894  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
895  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
896  *          - \e AGSA_RC_FAILURE the MPI command is failure
897  *
898  */
899 /*******************************************************************************/
900 GLOBAL bit32 mpiSMPCmd(
901   agsaRoot_t             *agRoot,
902   void                   *pIomb,
903   bit16                  opcode,
904   agsaSMPCmd_t           *payload,
905   bit8                   inq,
906   bit8                   outq
907   )
908 {
909   agsaLLRoot_t   *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
910   mpiICQueue_t   *circularQ;
911   bit32          ret = AGSA_RC_SUCCESS;
912 #if defined(SALLSDK_DEBUG)
913  mpiMsgHeader_t *msgHeader;
914   bit32                bc;
915 #endif /* SALLSDK_DEBUG */
916   smTraceFuncEnter(hpDBG_VERY_LOUD,"xi");
917 
918   SA_DBG6(("mpiSMPCmd: start\n"));
919 
920 #if defined(SALLSDK_DEBUG)
921   msgHeader = (mpiMsgHeader_t*)(((bit8*)pIomb) - sizeof(mpiMsgHeader_t));
922   bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
923 #endif /* SALLSDK_DEBUG */
924   SA_DBG6(("mpiSMPCmd: before msgHeader bc %d\n", bc));
925 
926   /* copy payload if it is necessary */
927   if (agNULL != payload)
928   {
929     si_memcpy(pIomb, payload, sizeof(agsaSMPCmd_t));
930   }
931 
932   SA_DBG6(("mpiSMPCmd: after msgHeader bc %d\n", bc));
933 
934   /* post the IOMB to SPC */
935   circularQ = &saRoot->inboundQueue[inq];
936   if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pIomb, MPI_CATEGORY_SAS_SATA, opcode, outq, (bit8)circularQ->priority))
937     ret = AGSA_RC_FAILURE;
938 
939   SA_DBG3(("mpiSMPCmd, return value = %d\n", ret));
940 
941   /* return value */
942   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xi");
943   return ret;
944 }
945 
946 /******************************************************************************/
947 /*! \brief SPC MPI Deregister Device Handle Command
948  *
949  *  This command used to deregister(remove) the device handle.
950  *
951  *  \param agRoot       Handles for this instance of SAS/SATA LLL
952  *  \param agDevHandle  Device Handle
953  *  \param deviceId     index of device
954  *  \param portId       index of port
955  *  \param queueNum     IQ/OQ number
956  *
957  *  \return If the MPI command is sent to SPC successfully
958  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
959  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
960  *          - \e AGSA_RC_FAILURE the MPI command is failure
961  *
962  */
963 /*******************************************************************************/
964 GLOBAL bit32 mpiDeregDevHandleCmd(
965   agsaRoot_t          *agRoot,
966   agsaContext_t       *agContext,
967   agsaDeviceDesc_t    *pDevice,
968   bit32               deviceId,
969   bit32               portId,
970   bit32               queueNum
971   )
972 {
973   bit32                   ret = AGSA_RC_SUCCESS;
974   agsaLLRoot_t            *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
975   agsaIORequestDesc_t     *pRequest;
976   agsaDeregDevHandleCmd_t payload;
977 
978   smTraceFuncEnter(hpDBG_VERY_LOUD,"xp");
979 
980   /* Get request from free IORequests */
981   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
982   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
983 
984   /* If no LL Control request entry available */
985   if ( agNULL == pRequest )
986   {
987     SA_DBG1(("mpiDeregDevHandleCmd, No request from free list\n" ));
988     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xp");
989     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
990     return AGSA_RC_BUSY;
991   }
992   /* If LL Control request entry avaliable */
993   else
994   {
995     pRequest->pDevice = pDevice;
996     /* Remove the request from free list */
997     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
998     pRequest->valid = agTRUE;
999     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1000     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1001     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1002     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1003     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1004 
1005     /* clean the payload to zeros */
1006     si_memset(&payload, 0, sizeof(agsaDeregDevHandleCmd_t));
1007 
1008     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDeregDevHandleCmd_t, tag), pRequest->HTag);
1009     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDeregDevHandleCmd_t, deviceId), deviceId);
1010 
1011     /* build IOMB command and send it to SPC */
1012     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_DEREG_DEV_HANDLE, IOMB_SIZE64, queueNum);
1013     if (AGSA_RC_SUCCESS != ret)
1014     {
1015       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1016       /* remove the request from IOMap */
1017       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1018       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1019       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1020       pRequest->valid = agFALSE;
1021 
1022       /* return the request to free pool */
1023       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1024 
1025       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1026       SA_DBG1(("mpiSetVPDCmd, sending IOMB failed\n" ));
1027     }
1028     SA_DBG3(("mpiDeregDevHandleCmd, return value = %d\n", ret));
1029   }
1030 
1031   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xp");
1032 
1033   /* return value */
1034   return ret;
1035 }
1036 
1037 /******************************************************************************/
1038 /*! \brief SPC MPI Get Device Handle Command
1039  *
1040  *  This command used to get device handle.
1041  *
1042  *  \param agRoot       Handles for this instance of SAS/SATA LLL
1043  *  \param agContext    Context of Device Handle Command
1044  *  \param portId       index of port
1045  *  \param flags        flags
1046  *  \param maxDevs      Maximum Device Handles
1047  *  \param queueNum     IQ/OQ number
1048  *  \param skipCount    skip device entry count
1049  *
1050  *  \return If the MPI command is sent to SPC successfully
1051  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1052  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
1053  *          - \e AGSA_RC_FAILURE the MPI command is failure
1054  *
1055  */
1056 /*******************************************************************************/
1057 GLOBAL bit32 mpiGetDeviceHandleCmd(
1058   agsaRoot_t          *agRoot,
1059   agsaContext_t       *agContext,
1060   bit32               portId,
1061   bit32               flags,
1062   bit32               maxDevs,
1063   bit32               queueNum,
1064   bit32               skipCount
1065   )
1066 {
1067   bit32                 ret = AGSA_RC_SUCCESS;
1068   agsaLLRoot_t          *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1069   agsaIORequestDesc_t   *pRequest;
1070   agsaGetDevHandleCmd_t payload;
1071   bit32               using_reserved = agFALSE;
1072 
1073   smTraceFuncEnter(hpDBG_VERY_LOUD,"xj");
1074 
1075   /* Get request from free CntrlRequests */
1076   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1077   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1078 
1079   /* If no LL Control request entry available */
1080   if ( agNULL == pRequest )
1081   {
1082     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests)); /**/
1083     if(agNULL != pRequest)
1084     {
1085       using_reserved = agTRUE;
1086       SA_DBG1(("mpiGetDeviceHandleCmd, using saRoot->freeReservedRequests\n"));
1087     }
1088     else
1089     {
1090       SA_DBG1(("mpiGetDeviceHandleCmd, No request from free list Not using saRoot->freeReservedRequests\n"));
1091       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xj");
1092       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1093       return AGSA_RC_BUSY;
1094     }
1095   }
1096 
1097   /* Remove the request from free list */
1098   if( using_reserved )
1099   {
1100     saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1101   }
1102   else
1103   {
1104     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1105   }
1106   SA_ASSERT((!pRequest->valid), "The pRequest is in use");
1107   saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1108   saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1109   saRoot->IOMap[pRequest->HTag].agContext = agContext;
1110   pRequest->valid = agTRUE;
1111   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1112 
1113 
1114   /* clean the payload to zeros */
1115   si_memset(&payload, 0, sizeof(agsaGetDevHandleCmd_t));
1116   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDevHandleCmd_t, tag), pRequest->HTag);
1117   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDevHandleCmd_t, DevADevTMaxDIDportId),
1118                    ((portId & PORTID_MASK) | (maxDevs << SHIFT8) | (flags << SHIFT24)));
1119     /* set starting Number */
1120   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDevHandleCmd_t, skipCount), skipCount);
1121 
1122   /* build IOMB command and send it to SPC */
1123   ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_DEV_HANDLE, IOMB_SIZE64, queueNum);
1124   if (AGSA_RC_SUCCESS != ret)
1125   {
1126     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1127     /* remove the request from IOMap */
1128     saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1129     saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1130     saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1131     pRequest->valid = agFALSE;
1132     /* return the request to free pool */
1133     if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1134     {
1135       SA_DBG1(("mpiGetDeviceHandleCmd: saving pRequest (%p) for later use\n", pRequest));
1136       saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1137     }
1138     else
1139     {
1140       /* return the request to free pool */
1141       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1142     }
1143     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1144 
1145     SA_DBG1(("mpiGetDeviceHandleCmd, sending IOMB failed\n" ));
1146   }
1147   SA_DBG3(("mpiGetDeviceHandleCmd, return value = %d\n", ret));
1148 
1149   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xj");
1150 
1151   return ret;
1152 }
1153 
1154 /******************************************************************************/
1155 /*! \brief SPC MPI LOCAL PHY CONTROL Command
1156  *
1157  *  This command used to do the SPC Phy operation.
1158  *
1159  *  \param agRoot       Handles for this instance of SAS/SATA LLL
1160  *  \param tag          tag of IOMB
1161  *  \param phyId        PHY Id
1162  *  \param operation    operation of PHY control
1163  *  \param queueNum     IQ/OQ number
1164  *
1165  *  \return If the MPI command is sent to SPC successfully
1166  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1167  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
1168  *          - \e AGSA_RC_FAILURE the MPI command is failure
1169  *
1170  */
1171 /*******************************************************************************/
1172 GLOBAL bit32 mpiLocalPhyControlCmd(
1173   agsaRoot_t          *agRoot,
1174   bit32               tag,
1175   bit32               phyId,
1176   bit32               operation,
1177   bit32               queueNum
1178   )
1179 {
1180   bit32                   ret = AGSA_RC_SUCCESS;
1181   agsaLocalPhyCntrlCmd_t  payload;
1182   smTraceFuncEnter(hpDBG_VERY_LOUD,"xl");
1183 
1184   SA_DBG3(("mpiLocalPhyControlCmd, phyId 0x%X operation 0x%x dw2 0x%x\n",phyId, operation,(((operation & BYTE_MASK) << SHIFT8) | (phyId & SM_PHYID_MASK))));
1185 
1186   /* clean the payload field */
1187   si_memset(&payload, 0, sizeof(agsaLocalPhyCntrlCmd_t));
1188 
1189   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaLocalPhyCntrlCmd_t, phyOpPhyId),
1190     (((operation & BYTE_MASK) << SHIFT8) | (phyId & SM_PHYID_MASK)));
1191   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaLocalPhyCntrlCmd_t, tag), tag);
1192   /* build IOMB command and send to SPC */
1193   ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_LOCAL_PHY_CONTROL, IOMB_SIZE64, queueNum);
1194 
1195   SA_DBG3(("mpiLocalPhyControlCmd, return value = %d\n", ret));
1196 
1197   /* return value */
1198   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xl");
1199   return ret;
1200 }
1201 
1202 /******************************************************************************/
1203 /*! \brief Device Handle Accept Command
1204  *
1205  *  This command is Device Handle Accept IOMB to SPC.
1206  *
1207  *  \param agRoot       Handles for this instance of SAS/SATA LLL
1208  *  \param agContext    Context for the set VPD command
1209  *  \param ctag         controller tag
1210  *  \param deviceId     device Id
1211  *  \param action       action
1212  *  \param queueNum     queue Number
1213  *
1214  *  \return If the MPI command is sent to SPC successfully
1215  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1216  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
1217  *          - \e AGSA_RC_FAILURE the MPI command is failure
1218  *
1219  */
1220 /*******************************************************************************/
1221 GLOBAL bit32 mpiDevHandleAcceptCmd(
1222   agsaRoot_t          *agRoot,
1223   agsaContext_t       *agContext,
1224   bit32               ctag,
1225   bit32               deviceId,
1226   bit32               action,
1227   bit32               flag,
1228   bit32               itlnx,
1229   bit32               queueNum
1230   )
1231 {
1232   bit32                    ret = AGSA_RC_SUCCESS;
1233   agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1234   agsaIORequestDesc_t      *pRequest;
1235   agsaDevHandleAcceptCmd_t payload;
1236   bit32                    DW4 =0;
1237   bit32                    mcn =0;
1238   bit32                    awt =0;
1239   bit32                    ha =0;
1240 
1241   smTraceFuncEnter(hpDBG_VERY_LOUD,"xt");
1242 
1243   if(deviceId & 0xFFFF0000)
1244   {
1245     ha = 1;
1246   }
1247   /* Get request from free IORequests */
1248   ossaSingleThreadedEnter(agRoot,LL_IOREQ_LOCKEQ_LOCK );
1249   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1250 
1251   SA_DBG2(("mpiDevHandleAcceptCmd, deviceId 0x%x action 0x%x flag 0x%x itlnx 0x%x\n",deviceId,action,flag,itlnx ));
1252 
1253   /* If no LL Control request entry available */
1254   if ( agNULL == pRequest )
1255   {
1256     ossaSingleThreadedLeave(agRoot,LL_IOREQ_LOCKEQ_LOCK );
1257     SA_DBG1(("mpiDevHandleAcceptCmd, No request from free list\n" ));
1258     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xt");
1259     return AGSA_RC_BUSY;
1260   }
1261   /* If LL Control request entry avaliable */
1262   else
1263   {
1264     /* Remove the request from free list */
1265     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
1266     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1267     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1268     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1269     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1270     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1271 
1272     /* Do not mark as valid at this IOMB does not complete in OBQ */
1273 
1274     /* set payload to zeros */
1275     si_memset(&payload, 0, sizeof(agsaDevHandleAcceptCmd_t));
1276 
1277     /* set tag field */
1278     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDevHandleAcceptCmd_t, tag), pRequest->HTag);
1279     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDevHandleAcceptCmd_t, deviceId), deviceId);
1280     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDevHandleAcceptCmd_t, Ctag), ctag);
1281     mcn = (flag & 0xF0000) >>SHIFT16;
1282     awt = (flag & 2)>>SHIFT1;
1283     DW4 = (action << SHIFT24) | \
1284              mcn << SHIFT20   | \
1285              awt << SHIFT17   | \
1286              ha  << SHIFT16   | \
1287                      itlnx;
1288     SA_DBG2(("mpiDevHandleAcceptCmd,DW4 0x%x\n",DW4 ));
1289     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDevHandleAcceptCmd_t, DevA_MCN_R_R_HA_ITNT),DW4);
1290   }
1291 
1292   /* build IOMB command and send to SPC */
1293   ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_DEV_HANDLE_ACCEPT, IOMB_SIZE64, queueNum);
1294   if (AGSA_RC_SUCCESS != ret)
1295   {
1296     SA_DBG1(("mpiDevHandleAcceptCmd, sending IOMB failed\n" ));
1297   }
1298   else
1299   {
1300     SA_DBG1(("mpiDevHandleAcceptCmd, sending IOMB succeeded\n" ));
1301   }
1302 
1303   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1304   /* remove the request from IOMap */
1305   saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1306   saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1307   saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1308   pRequest->valid = agFALSE;
1309   /* return the request to free pool */
1310   if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1311   {
1312     SA_DBG1(("mpiDevHandleAcceptCmd: saving pRequest (%p) for later use\n", pRequest));
1313     saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1314   }
1315   else
1316   {
1317     /* return the request to free pool */
1318     saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1319   }
1320 
1321   /* return value */
1322   ossaSingleThreadedLeave(agRoot,LL_IOREQ_LOCKEQ_LOCK );
1323   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xt");
1324   return ret;
1325 }
1326 
1327 /******************************************************************************/
1328 /*! \brief SPC READ REGISTER DUMP Command
1329  *
1330  *  This command used to do the SPC Read Register Dump command.
1331  *
1332  *  \param agRoot       Handles for this instance of SAS/SATA LLL
1333  *  \param tag          tag of IOMB
1334  *  \param cpuId        CPU Id
1335  *  \param queueNum     IQ/OQ number
1336  *  \param cpuId        AAP1 or IOP
1337  *  \param cOffset      offset of the register dump data
1338  *  \param addrHi       Hi address if Register Dump data
1339  *  \param addrHi       Low address if Register Dump data
1340  *  \param len          the length of for read
1341  *
1342  *  \return If the MPI command is sent to SPC successfully
1343  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1344  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
1345  *          - \e AGSA_RC_FAILURE the MPI command is failure
1346  *
1347  */
1348 /*******************************************************************************/
1349 GLOBAL bit32 mpiNVMReadRegDumpCmd(
1350   agsaRoot_t          *agRoot,
1351   agsaContext_t       *agContext,
1352   bit32               queueNum,
1353   bit32               cpuId,
1354   bit32               cOffset,
1355   bit32               addrHi,
1356   bit32               addrLo,
1357   bit32               len
1358   )
1359 {
1360   bit32                 ret = AGSA_RC_SUCCESS;
1361   agsaLLRoot_t          *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1362   agsaIORequestDesc_t   *pRequest;
1363   agsaGetNVMDataCmd_t   payload;
1364   bit32 nvmd = 0;
1365 
1366   smTraceFuncEnter(hpDBG_VERY_LOUD,"xk");
1367 
1368   /* Get request from free IORequests */
1369   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1370   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1371 
1372   /* If no LL Control request entry available */
1373   if ( agNULL == pRequest )
1374   {
1375     SA_DBG1(("mpiNVMReadRegDumpCmd, No request from free list\n" ));
1376     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xk");
1377     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1378     return AGSA_RC_BUSY;
1379   }
1380   /* If LL Control request entry avaliable */
1381   else
1382   {
1383     /* Remove the request from free list */
1384     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
1385     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1386     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1387     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1388     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1389     pRequest->valid = agTRUE;
1390     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1391 
1392     /* clean the payload field */
1393     si_memset(&payload, 0, sizeof(agsaGetNVMDataCmd_t));
1394 
1395     /* only indirect mode */
1396     if (cpuId <= 1)
1397     {
1398       if (cpuId == 0)
1399         nvmd = AAP1_RDUMP | IRMode;
1400       else
1401         nvmd = IOP_RDUMP | IRMode;
1402 
1403       /* setup IOMB */
1404       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, tag), pRequest->HTag);
1405       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD), nvmd);
1406       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset), cOffset);
1407       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respAddrLo), addrLo);
1408       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respAddrHi), addrHi);
1409       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respLen), len);
1410 
1411       /* build IOMB command and send to SPC */
1412       ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_NVMD_DATA, IOMB_SIZE64, queueNum);
1413     }
1414     else
1415     {
1416       SA_DBG1(("mpiNVMReadRegDumpCmd, Wrong device type\n" ));
1417       ret = AGSA_RC_FAILURE;
1418     }
1419 
1420     if (AGSA_RC_SUCCESS != ret)
1421     {
1422       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1423       /* remove the request from IOMap */
1424       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1425       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1426       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1427       pRequest->valid = agFALSE;
1428       /* return the request to free pool */
1429       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1430 
1431       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1432       SA_DBG1(("mpiNVMReadRegDumpCmd, sending IOMB failed\n" ));
1433     }
1434   }
1435 
1436   SA_DBG3(("mpiNVMReadRegDumpCmd, return value = %d\n", ret));
1437 
1438   /* return value */
1439   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xk");
1440 
1441   return ret;
1442 }
1443 
1444 /******************************************************************************/
1445 /*! \brief Get NVM Data command
1446  *
1447  *  This command is get NVM Data from SPC.
1448  *
1449  *  \param agRoot       Handles for this instance of SAS/SATA LLL
1450  *  \param agContext    Context for the VPD command
1451  *  \param VPDInfo      Pointer of VPD Information
1452  *  \param queueNum     Queue Number of inbound/outbound queue
1453  *
1454  *  \return If the MPI command is sent to SPC successfully
1455  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1456  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
1457  *          - \e AGSA_RC_FAILURE the MPI command is failure
1458  *
1459  */
1460 /*******************************************************************************/
1461 GLOBAL bit32 mpiGetNVMDCmd(
1462   agsaRoot_t          *agRoot,
1463   agsaContext_t       *agContext,
1464   agsaNVMDData_t      *NVMDInfo,
1465   bit32               queueNum
1466   )
1467 {
1468   bit32                 ret = AGSA_RC_FAILURE;
1469   agsaLLRoot_t          *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1470   agsaIORequestDesc_t   *pRequest;
1471   agsaGetNVMDataCmd_t   payload;
1472 
1473   smTraceFuncEnter(hpDBG_VERY_LOUD,"xr");
1474 
1475   /* Get request from free IORequests */
1476   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1477   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1478 
1479   /* If no LL Control request entry available */
1480   if ( agNULL == pRequest )
1481   {
1482     SA_DBG1(("mpiGetNVMDCmd, No request from free list\n" ));
1483     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xr");
1484     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1485     return AGSA_RC_BUSY;
1486   }
1487   /* If LL Control request entry avaliable */
1488   else
1489   {
1490     SA_DBG3(("mpiGetNVMDCmd, Build IOMB NVMDDevice= 0x%x\n", NVMDInfo->NVMDevice));
1491     /* Remove the request from free list */
1492     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
1493     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1494     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1495     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1496     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1497     pRequest->valid = agTRUE;
1498     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1499 
1500     /* set payload to zeros */
1501     si_memset(&payload, 0, sizeof(agsaGetNVMDataCmd_t));
1502     /* set tag field */
1503     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, tag), pRequest->HTag);
1504 
1505     if (NVMDInfo->indirectPayload)
1506     {
1507       /* indirect payload IP = 1 */
1508       switch (NVMDInfo->NVMDevice)
1509       {
1510       case AGSA_NVMD_TWI_DEVICES:
1511         /* NVMD = 0 */
1512         /* indirect payload IP = 1 and 0x0 (TWI) */
1513         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
1514           (NVMDInfo->TWIDeviceAddress << 16) | (NVMDInfo->TWIBusNumber << 12) |
1515           (NVMDInfo->TWIDevicePageSize << 8) | (NVMDInfo->TWIDeviceAddressSize << 4) |
1516           (NVMDInfo->indirectPayload << 31) | NVMDInfo->NVMDevice);
1517             OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
1518           NVMDInfo->dataOffsetAddress);
1519         break;
1520       case AGSA_NVMD_CONFIG_SEEPROM:
1521         /* NVMD = 1 */
1522         /* Data Offset should be 0 */
1523         if (NVMDInfo->dataOffsetAddress != 0)
1524         {
1525           /* Error for Offset */
1526           SA_DBG1(("mpiGetNVMDCmd, (IP=1)wrong offset = 0x%x\n", NVMDInfo->dataOffsetAddress));
1527         }
1528         /* indirect payload IP = 1, NVMD = 0x1 (SEEPROM0) */
1529         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
1530           (NVMDInfo->indirectPayload << SHIFT31) | (NVMDInfo->NVMDevice));
1531         break;
1532       case AGSA_NVMD_VPD_FLASH:
1533         /* indirect payload IP = 1 and 0x4 (FLASH) */
1534         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
1535           (NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
1536         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
1537           NVMDInfo->dataOffsetAddress);
1538         break;
1539       case AGSA_NVMD_EXPANSION_ROM:
1540         /* indirect payload IP = 1 and 0x7 (EXPANSION ROM PARTITION) */
1541         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
1542           (NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
1543         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
1544           NVMDInfo->dataOffsetAddress);
1545         break;
1546       case  AGSA_NVMD_AAP1_REG_FLASH: /* AGSA_NVMD_REG_FLASH  SPCv uses 5 as well */
1547         /* indirect payload IP = 1 and 0x5 (AGSA_NVMD_AAP1_REG_FLASH ) */
1548         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
1549           (NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
1550         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
1551           NVMDInfo->dataOffsetAddress);
1552         break;
1553       case  AGSA_NVMD_IOP_REG_FLASH:
1554         /* indirect payload IP = 1 and 0x6 ( AGSA_NVMD_IOP_REG_FLASH ) */
1555         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
1556           (NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
1557         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
1558           NVMDInfo->dataOffsetAddress);
1559         break;
1560 
1561       default:
1562         SA_DBG1(("mpiGetNVMDCmd, (IP=1)wrong device type = 0x%x\n", NVMDInfo->NVMDevice));
1563         break;
1564       }
1565 
1566       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respAddrLo), NVMDInfo->indirectAddrLower32);
1567       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respAddrHi), NVMDInfo->indirectAddrUpper32);
1568       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respLen), NVMDInfo->indirectLen);
1569       /* build IOMB command and send to SPC */
1570       ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_NVMD_DATA, IOMB_SIZE64, queueNum);
1571     }
1572     else
1573     {
1574       /* direct payload IP = 0 only for TWI device */
1575       if (AGSA_NVMD_TWI_DEVICES == NVMDInfo->NVMDevice)
1576       {
1577         /* NVMD = 0 */
1578         /* indirect payload IP = 0 and 0x0 (TWI) */
1579         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
1580           (NVMDInfo->TWIDeviceAddress << SHIFT16) | (NVMDInfo->TWIBusNumber << SHIFT12) |
1581           (NVMDInfo->TWIDevicePageSize << SHIFT8) | (NVMDInfo->TWIDeviceAddressSize << SHIFT4) |
1582           NVMDInfo->NVMDevice);
1583             OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
1584           NVMDInfo->dataOffsetAddress | (NVMDInfo->directLen << SHIFT24));
1585         /* build IOMB command and send to SPC */
1586         ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_NVMD_DATA, IOMB_SIZE64, queueNum);
1587       }
1588       else
1589       {
1590         SA_DBG1(("mpiGetNVMDCmd, (IP=0)wrong device type = 0x%x\n", NVMDInfo->NVMDevice));
1591         ret = AGSA_RC_FAILURE;
1592         /* CB for NVMD with error */
1593         ossaGetNVMDResponseCB(agRoot, agContext, OSSA_NVMD_MODE_ERROR, 0, NVMDInfo->directLen, agNULL);
1594       }
1595     }
1596 
1597     if (AGSA_RC_SUCCESS != ret)
1598     {
1599       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1600       /* remove the request from IOMap */
1601       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1602       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1603       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1604       pRequest->valid = agFALSE;
1605 
1606       /* return the request to free pool */
1607       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1608 
1609       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1610       SA_DBG1(("mpiGetNVMDCmd, sending IOMB failed\n" ));
1611     }
1612     SA_DBG3(("mpiGetNVMDCmd, return value = %d\n", ret));
1613   }
1614 
1615   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xr");
1616 
1617   /* return value */
1618   return ret;
1619 }
1620 
1621 /******************************************************************************/
1622 /*! \brief Set NVM Data Command
1623  *
1624  *  This command is set NVM Data to SPC.
1625  *
1626  *  \param agRoot       Handles for this instance of SAS/SATA LLL
1627  *  \param agContext    Context for the set VPD command
1628  *  \param NVMDInfo      pointer of VPD information
1629  *  \param queueNum     queue Number
1630  *
1631  *  \return If the MPI command is sent to SPC successfully
1632  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1633  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
1634  *          - \e AGSA_RC_FAILURE the MPI command is failure
1635  *
1636  */
1637 /*******************************************************************************/
1638 GLOBAL bit32 mpiSetNVMDCmd(
1639   agsaRoot_t          *agRoot,
1640   agsaContext_t       *agContext,
1641   agsaNVMDData_t      *NVMDInfo,
1642   bit32               queueNum
1643   )
1644 {
1645   bit32               ret = AGSA_RC_FAILURE;
1646   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1647   agsaIORequestDesc_t *pRequest;
1648   agsaSetNVMDataCmd_t payload;
1649 
1650   smTraceFuncEnter(hpDBG_VERY_LOUD,"xm");
1651 
1652 
1653   /* Get request from free IORequests */
1654   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1655   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1656 
1657   /* If no LL Control request entry available */
1658   if ( agNULL == pRequest )
1659   {
1660     SA_DBG1(("mpiSetNVMDCmd, No request from free list\n" ));
1661     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xm");
1662     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1663     return AGSA_RC_BUSY;
1664   }
1665   /* If LL Control request entry avaliable */
1666   else
1667   {
1668     SA_DBG3(("mpiSetNVMDCmd, Build IOMB NVMDDevice= 0x%x\n", NVMDInfo->NVMDevice));
1669     /* Remove the request from free list */
1670     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
1671     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1672     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1673     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1674     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1675     pRequest->valid = agTRUE;
1676     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1677 
1678     /* set payload to zeros */
1679     si_memset(&payload, 0, sizeof(agsaSetNVMDataCmd_t));
1680 
1681     /* set tag field */
1682     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, tag), pRequest->HTag);
1683 
1684     if (NVMDInfo->indirectPayload)
1685     {
1686       /* indirect payload IP = 1 */
1687       switch (NVMDInfo->NVMDevice)
1688       {
1689       case AGSA_NVMD_TWI_DEVICES:
1690         /* NVMD = 0 */
1691         /* indirect payload IP = 1 and 0x0 (TWI) */
1692         /* set up signature */
1693         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, Data.indirectData.signature), NVMDInfo->signature);
1694         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, LEN_IR_VPDD),
1695           (NVMDInfo->TWIDeviceAddress << SHIFT16) | (NVMDInfo->TWIBusNumber << SHIFT12) |
1696           (NVMDInfo->TWIDevicePageSize << SHIFT8) | (NVMDInfo->TWIDeviceAddressSize << SHIFT4) |
1697           (NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
1698         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, VPDOffset),
1699           NVMDInfo->dataOffsetAddress);
1700         break;
1701       /* 0x01:SEEPROM-0 and 0x04:FLASH only in indirect mode */
1702       case AGSA_NVMD_CONFIG_SEEPROM:
1703         /* NVMD=1 */
1704         /* Data Offset should be 0 */
1705         /* set up signature */
1706         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, Data.indirectData.signature), NVMDInfo->signature);
1707         /* indirect payload IP = 1, NVMD = 0x1 (SEEPROM0) */
1708         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, LEN_IR_VPDD),
1709           (NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
1710         break;
1711       case AGSA_NVMD_VPD_FLASH:
1712         /* indirect payload IP = 1, NVMD=0x4 (FLASH) */
1713         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, LEN_IR_VPDD),
1714           (NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
1715         /* set up Offset */
1716             OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, VPDOffset),
1717           NVMDInfo->dataOffsetAddress);
1718         break;
1719       default:
1720         SA_DBG1(("mpiSetNVMDCmd, (IP=1)wrong device type = 0x%x\n", NVMDInfo->NVMDevice));
1721         ret = AGSA_RC_FAILURE;
1722         ossaSetNVMDResponseCB(agRoot, agContext, OSSA_NVMD_MODE_ERROR);
1723         break;
1724       }
1725 
1726       /* set up SGL field */
1727       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, Data.indirectData.ISglAL), (NVMDInfo->indirectAddrLower32));
1728       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, Data.indirectData.ISglAH), (NVMDInfo->indirectAddrUpper32));
1729       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, Data.indirectData.ILen), (NVMDInfo->indirectLen));
1730       /* build IOMB command and send to SPC */
1731       ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_NVMD_DATA, IOMB_SIZE64, queueNum);
1732     }
1733     else
1734     {
1735       /* direct payload IP = 0 */
1736       if (AGSA_NVMD_TWI_DEVICES == NVMDInfo->NVMDevice)
1737       {
1738         /* NVMD = 0 */
1739         /* indirect payload IP = 0 and 0x0 (TWI) */
1740         /* not allow write to Config SEEPROM for direct mode, so don't set singature */
1741         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, LEN_IR_VPDD),
1742           (NVMDInfo->TWIDeviceAddress << SHIFT16) | (NVMDInfo->TWIBusNumber << SHIFT12) |
1743           (NVMDInfo->TWIDevicePageSize << SHIFT8) | (NVMDInfo->TWIDeviceAddressSize << SHIFT4) |
1744           NVMDInfo->NVMDevice);
1745         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, VPDOffset),
1746           NVMDInfo->dataOffsetAddress | (NVMDInfo->directLen << SHIFT24));
1747         si_memcpy(&payload.Data.NVMData[0], NVMDInfo->directData, NVMDInfo->directLen);
1748         /* build IOMB command and send to SPC */
1749         ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_NVMD_DATA, IOMB_SIZE64, queueNum);
1750       }
1751       else
1752       {
1753         SA_DBG1(("mpiSetNVMDCmd, (IP=0)wrong device type = 0x%x\n", NVMDInfo->NVMDevice));
1754         ret = AGSA_RC_FAILURE;
1755         ossaSetNVMDResponseCB(agRoot, agContext, OSSA_NVMD_MODE_ERROR);
1756       }
1757     }
1758 
1759     if (AGSA_RC_SUCCESS != ret)
1760     {
1761       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1762       /* remove the request from IOMap */
1763       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1764       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1765       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1766       pRequest->valid = agFALSE;
1767 
1768       /* return the request to free pool */
1769       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1770       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1771       SA_DBG1(("mpiSetVPDCmd, sending IOMB failed\n" ));
1772     }
1773     SA_DBG3(("mpiSetNVMDCmd, return value = %d\n", ret));
1774   }
1775 
1776 
1777   /* return value */
1778   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xm");
1779   return ret;
1780 }
1781 
1782 /******************************************************************************/
1783 /*! \brief Set Device State command
1784  *
1785  *  This command is set Device State to SPC.
1786  *
1787  *  \param agRoot       Handles for this instance of SAS/SATA LLL
1788  *  \param agContext    Context for the Set Nexus State command
1789  *  \param deviceId     DeviceId
1790  *  \param queueNum     Queue Number of inbound/outbound queue
1791  *
1792  *  \return If the MPI command is sent to SPC successfully
1793  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1794  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
1795  *          - \e AGSA_RC_FAILURE the MPI command is failure
1796  *
1797  */
1798 /*******************************************************************************/
1799 GLOBAL bit32 mpiSetDeviceStateCmd(
1800   agsaRoot_t          *agRoot,
1801   agsaContext_t       *agContext,
1802   bit32               deviceId,
1803   bit32               nds,
1804   bit32               queueNum
1805   )
1806 {
1807   bit32                  ret = AGSA_RC_SUCCESS;
1808   agsaLLRoot_t           *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1809   agsaIORequestDesc_t    *pRequest;
1810   agsaSetDeviceStateCmd_t payload;
1811 
1812   smTraceFuncEnter(hpDBG_VERY_LOUD,"xn");
1813 
1814   /* Get request from free IORequests */
1815   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1816   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1817 
1818   /* If no LL Control request entry available */
1819   if ( agNULL == pRequest )
1820   {
1821     SA_DBG1(("mpiSetDeviceStateCmd, No request from free list\n" ));
1822     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xn");
1823     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1824     return AGSA_RC_BUSY;
1825   }
1826   /* If LL Control request entry avaliable */
1827   else
1828   {
1829     SA_DBG3(("mpiSetDeviceStateCmd, Build IOMB DeviceId= 0x%x\n", deviceId));
1830     /* Remove the request from free list */
1831     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1832     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1833     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1834     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1835     pRequest->valid = agTRUE;
1836     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1837 
1838     /* set payload to zeros */
1839     si_memset(&payload, 0, sizeof(agsaSetDeviceStateCmd_t));
1840     /* set tag field */
1841     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDeviceStateCmd_t, tag), pRequest->HTag);
1842     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDeviceStateCmd_t, deviceId), deviceId);
1843     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDeviceStateCmd_t, NDS), nds);
1844 
1845     /* build IOMB command and send to SPC */
1846     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_DEVICE_STATE, IOMB_SIZE64, queueNum);
1847     if (AGSA_RC_SUCCESS != ret)
1848     {
1849       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1850       /* remove the request from IOMap */
1851       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1852       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1853       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1854       pRequest->valid = agFALSE;
1855 
1856       /* return the request to free pool */
1857       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1858 
1859       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1860 
1861       SA_DBG1(("mpiSetNexusStateCmd, sending IOMB failed\n" ));
1862     }
1863    SA_DBG3(("mpiSetDeviceStateCmd, return value = %d\n", ret));
1864   }
1865 
1866   /* return value */
1867   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xn");
1868 
1869   return ret;
1870 }
1871 
1872 /******************************************************************************/
1873 /*! \brief Get Device State command
1874  *
1875  *  This command is get device State to SPC.
1876  *
1877  *  \param agRoot       Handles for this instance of SAS/SATA LLL
1878  *  \param agContext    Context for the Get Nexus State command
1879  *  \param deviceId     DeviceId
1880  *  \param queueNum     Queue Number of inbound/outbound queue
1881  *
1882  *  \return If the MPI command is sent to SPC successfully
1883  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1884  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
1885  *          - \e AGSA_RC_FAILURE the MPI command is failure
1886  *
1887  */
1888 /*******************************************************************************/
1889 GLOBAL bit32 mpiGetDeviceStateCmd(
1890   agsaRoot_t          *agRoot,
1891   agsaContext_t       *agContext,
1892   bit32               deviceId,
1893   bit32               queueNum
1894   )
1895 {
1896   bit32                  ret = AGSA_RC_SUCCESS;
1897   agsaLLRoot_t           *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
1898   agsaIORequestDesc_t    *pRequest;
1899   agsaGetDeviceStateCmd_t payload;
1900   bit32               using_reserved = agFALSE;
1901 
1902   smTraceFuncEnter(hpDBG_VERY_LOUD,"xf");
1903 
1904   /* Get request from free IORequests */
1905   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1906   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
1907 
1908   /* If no LL Control request entry available */
1909   if ( agNULL == pRequest )
1910   {
1911     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests)); /**/
1912     /* If no LL Control request entry available */
1913     if(agNULL != pRequest)
1914     {
1915       using_reserved = agTRUE;
1916       SA_DBG1(("mpiGetDeviceStateCmd, using saRoot->freeReservedRequests\n"));
1917     }
1918     else
1919     {
1920       SA_DBG1(("mpiGetDeviceStateCmd, No request from free list Not using saRoot->freeReservedRequests\n"));
1921       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xf");
1922       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1923       return AGSA_RC_BUSY;
1924     }
1925 
1926   }
1927   /* If LL Control request entry avaliable */
1928   SA_DBG3(("mpiGetDeviceStateCmd, Build IOMB DeviceId= 0x%x\n", deviceId));
1929   /* Remove the request from free list */
1930   if( using_reserved )
1931   {
1932     saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1933   }
1934   else
1935   {
1936     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1937   }
1938   saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1939   saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1940   saRoot->IOMap[pRequest->HTag].agContext = agContext;
1941   pRequest->valid = agTRUE;
1942 
1943   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1944 
1945   /* set payload to zeros */
1946   si_memset(&payload, 0, sizeof(agsaGetDeviceStateCmd_t));
1947   /* set tag field */
1948   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDeviceStateCmd_t, tag), pRequest->HTag);
1949   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDeviceStateCmd_t, deviceId), deviceId);
1950 
1951   /* build IOMB command and send to SPC */
1952   ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_DEVICE_STATE, IOMB_SIZE64, queueNum);
1953   if (AGSA_RC_SUCCESS != ret)
1954   {
1955     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1956     /* remove the request from IOMap */
1957     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
1958     saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1959     saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1960     saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1961     pRequest->valid = agFALSE;
1962     /* return the request to free pool */
1963     if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1964     {
1965       SA_DBG1(("mpiGetDeviceStateCmd: saving pRequest (%p) for later use\n", pRequest));
1966       saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1967     }
1968     else
1969     {
1970       /* return the request to free pool */
1971       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1972     }
1973     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1974 
1975     SA_DBG1(("mpiGetDeviceStateCmd, sending IOMB failed\n" ));
1976   }
1977   SA_DBG3(("mpiGetDeviceStateCmd, return value = %d\n", ret));
1978 
1979   /* return value */
1980   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xf");
1981 
1982   return ret;
1983 }
1984 
1985 /******************************************************************************/
1986 /*! \brief SAS ReInitialize command
1987  *
1988  *  This command is Reinitialize SAS paremeters to SPC.
1989  *
1990  *  \param agRoot       Handles for this instance of SAS/SATA LLL
1991  *  \param agContext    Context for the Get Nexus State command
1992  *  \param agSASConfig  SAS Configuration Parameters
1993  *  \param queueNum     Queue Number of inbound/outbound queue
1994  *
1995  *  \return If the MPI command is sent to SPC successfully
1996  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
1997  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
1998  *          - \e AGSA_RC_FAILURE the MPI command is failure
1999  *
2000  */
2001 /*******************************************************************************/
2002 GLOBAL bit32 mpiSasReinitializeCmd(
2003    agsaRoot_t        *agRoot,
2004    agsaContext_t     *agContext,
2005    agsaSASReconfig_t *agSASConfig,
2006    bit32             queueNum
2007    )
2008 {
2009   bit32                    ret = AGSA_RC_SUCCESS;
2010   agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
2011   agsaIORequestDesc_t      *pRequest;
2012   agsaSasReInitializeCmd_t payload;
2013 
2014   smTraceFuncEnter(hpDBG_VERY_LOUD,"xo");
2015 
2016   /* Get request from free IORequests */
2017   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2018   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2019 
2020   /* If no LL Control request entry available */
2021   if ( agNULL == pRequest )
2022   {
2023     SA_DBG1(("mpiSasReinitializeCmd, No request from free list\n" ));
2024     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xo");
2025     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2026     return AGSA_RC_BUSY;
2027   }
2028   /* If LL Control request entry avaliable */
2029   else
2030   {
2031     SA_DBG3(("mpiSasReinitializeCmd, Build IOMB SAS_RE_INITIALIZE\n"));
2032     /* Remove the request from free list */
2033     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2034     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2035     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2036     saRoot->IOMap[pRequest->HTag].agContext = agContext;
2037     pRequest->valid = agTRUE;
2038     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2039 
2040     /* set payload to zeros */
2041     si_memset(&payload, 0, sizeof(agsaSasReInitializeCmd_t));
2042 
2043     /* set tag field */
2044     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSasReInitializeCmd_t, tag), pRequest->HTag);
2045     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSasReInitializeCmd_t, setFlags), agSASConfig->flags);
2046     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSasReInitializeCmd_t, MaxPorts), agSASConfig->maxPorts);
2047     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSasReInitializeCmd_t, openRejReCmdData),
2048                     (agSASConfig->openRejectRetriesCmd << SHIFT16) | agSASConfig->openRejectRetriesData);
2049     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSasReInitializeCmd_t, sataHOLTMO), agSASConfig->sataHolTmo);
2050 
2051 
2052     /* build IOMB command and send to SPC */
2053     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SAS_RE_INITIALIZE, IOMB_SIZE64, queueNum);
2054     if (AGSA_RC_SUCCESS != ret)
2055     {
2056       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2057       /* remove the request from IOMap */
2058       SA_ASSERT((!pRequest->valid), "The pRequest is in use");
2059       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2060       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2061       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2062       pRequest->valid = agFALSE;
2063 
2064       /* return the request to free pool */
2065       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2066 
2067       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2068 
2069       SA_DBG1(("mpiSasReinitializeCmd, sending IOMB failed\n" ));
2070     }
2071     SA_DBG3(("mpiSasReinitializeCmd, return value = %d\n", ret));
2072   }
2073 
2074   /* return value */
2075   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xo");
2076 
2077   return ret;
2078 }
2079 
2080 /******************************************************************************/
2081 /*! \brief SAS Set Controller Configuration Command
2082  *
2083  *  This command updates the contents of a controller mode page.
2084  *
2085  *  \param agRoot               Handles for this instance of SAS/SATA LLL
2086  *  \param agContext            Context for the Get Nexus State command
2087  *  \param agControllerConfig   Mode page being sent to the controller
2088  *  \param queueNum             Queue Number of inbound/outbound queue
2089  *
2090  *  \return If the MPI command is sent to SPC successfully
2091  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
2092  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
2093  *          - \e AGSA_RC_FAILURE the MPI command is failure
2094  *
2095  */
2096 /*******************************************************************************/
2097 GLOBAL bit32
2098 mpiSetControllerConfigCmd(
2099    agsaRoot_t                   *agRoot,
2100    agsaContext_t                *agContext,
2101    agsaSetControllerConfigCmd_t *agControllerConfig,
2102    bit32                         queueNum,
2103    bit8                          modePageContext
2104    )
2105 {
2106     bit32                    ret = AGSA_RC_SUCCESS;
2107     agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
2108     agsaIORequestDesc_t      *pRequest;
2109 
2110     smTraceFuncEnter(hpDBG_VERY_LOUD,"x1");
2111 
2112     SA_DBG2(("mpiSetControllerConfigCmd: agControllerConfig 0x%08x 0x%08x 0x%08x 0x%08x\n",
2113                                      agControllerConfig->pageCode,agControllerConfig->configPage[0],
2114                                      agControllerConfig->configPage[1], agControllerConfig->configPage[2]));
2115     SA_DBG2(("mpiSetControllerConfigCmd: agControllerConfig 0x%08x 0x%08x 0x%08x 0x%08x\n",
2116                                      agControllerConfig->configPage[3],agControllerConfig->configPage[4],
2117                                      agControllerConfig->configPage[5], agControllerConfig->configPage[6]));
2118     SA_DBG2(("mpiSetControllerConfigCmd: agControllerConfig 0x%08x 0x%08x 0x%08x 0x%08x\n",
2119                                      agControllerConfig->configPage[7],agControllerConfig->configPage[8],
2120                                      agControllerConfig->configPage[9], agControllerConfig->configPage[10]));
2121     SA_DBG2(("mpiSetControllerConfigCmd: agControllerConfig 0x%08x 0x%08x\n",
2122                                      agControllerConfig->configPage[11],agControllerConfig->configPage[12]));
2123 
2124     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2125     /* Get request from free IORequests */
2126     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2127 
2128     /* If no LL Control request entry available */
2129     if ( agNULL == pRequest )
2130     {
2131       SA_DBG1(("mpiSetControllerConfigCmd, No request from free list\n" ));
2132       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "x1");
2133       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2134       return AGSA_RC_BUSY;
2135     }
2136     /* If LL Control request entry avaliable */
2137     else
2138     {
2139       SA_DBG2(("mpiSetControllerConfigCmd, Build IOMB pageCode 0x%x configPage[0] 0x%x\n",agControllerConfig->pageCode,agControllerConfig->configPage[0]));
2140       /* Remove the request from free list */
2141       SA_ASSERT((!pRequest->valid), "The pRequest is in use");
2142       saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2143       saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2144       saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2145       saRoot->IOMap[pRequest->HTag].agContext = agContext;
2146       pRequest->valid = agTRUE;
2147       pRequest->modePageContext = modePageContext;
2148       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2149 
2150       /* set tag field */
2151       agControllerConfig->tag =  pRequest->HTag;
2152       ret = mpiBuildCmd(agRoot, (bit32 *)agControllerConfig,
2153                         MPI_CATEGORY_SAS_SATA, OPC_INB_SET_CONTROLLER_CONFIG, IOMB_SIZE64, 0);
2154 
2155       if (AGSA_RC_SUCCESS != ret)
2156       {
2157           ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2158           /* remove the request from IOMap */
2159           saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2160           saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2161           saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2162           pRequest->valid = agFALSE;
2163 
2164           /* return the request to free pool */
2165           saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2166 
2167           ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2168 
2169           SA_DBG1(("mpiSetControllerConfigCmd, sending IOMB failed\n" ));
2170       }
2171       SA_DBG3(("mpiSetControllerConfigCmd, return value = %d\n", ret));
2172     }
2173 
2174     /* return value */
2175     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "x1");
2176 
2177     return ret;
2178 }
2179 
2180 /******************************************************************************/
2181 /*! \brief SAS Get Controller Configuration Command
2182  *
2183  *  This command retrieves the contents of a controller mode page.
2184  *
2185  *  \param agRoot               Handles for this instance of SAS/SATA LLL
2186  *  \param agContext            Context for the Get Nexus State command
2187  *  \param agControllerConfig   Mode page to retrieve from the controller
2188  *  \param queueNum             Queue Number of inbound/outbound queue
2189  *
2190  *  \return If the MPI command is sent to SPC successfully
2191  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
2192  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
2193  *          - \e AGSA_RC_FAILURE the MPI command is failure
2194  *
2195  */
2196 /*******************************************************************************/
2197 GLOBAL bit32 mpiGetControllerConfigCmd(
2198    agsaRoot_t        *agRoot,
2199    agsaContext_t     *agContext,
2200    agsaGetControllerConfigCmd_t *agControllerConfig,
2201    bit32             queueNum
2202    )
2203 {
2204     bit32                    ret = AGSA_RC_SUCCESS;
2205     agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
2206     agsaIORequestDesc_t      *pRequest;
2207 
2208     smTraceFuncEnter(hpDBG_VERY_LOUD,"xq");
2209 
2210     SA_DBG1(("mpiGetControllerConfigCmd: Tag 0x%0X Page Code %0X\n",agControllerConfig->tag,agControllerConfig->pageCode ));
2211     /* Get request from free IORequests */
2212     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2213     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2214 
2215     /* If no LL Control request entry available */
2216     if ( agNULL == pRequest )
2217     {
2218       SA_DBG1(("mpiGetControllerConfigCmd, No request from free list\n" ));
2219       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xq");
2220       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2221       return AGSA_RC_BUSY;
2222     }
2223     /* If LL Control request entry avaliable */
2224     else
2225     {
2226       SA_DBG3(("mpiGetControllerConfig, Build IOMB mpiGetControllerConfigCmd\n"));
2227       /* Remove the request from free list */
2228       SA_ASSERT((!pRequest->valid), "The pRequest is in use");
2229       saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2230       saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2231       saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2232       saRoot->IOMap[pRequest->HTag].agContext = agContext;
2233       pRequest->valid = agTRUE;
2234       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2235 
2236       /* set tag field */
2237       agControllerConfig->tag =  pRequest->HTag;
2238 
2239       ret = mpiBuildCmd(agRoot, (bit32 *) agControllerConfig,
2240                         MPI_CATEGORY_SAS_SATA, OPC_INB_GET_CONTROLLER_CONFIG, IOMB_SIZE64, 0);
2241 
2242       if (AGSA_RC_SUCCESS != ret)
2243       {
2244           ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2245           /* remove the request from IOMap */
2246           saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2247           saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2248           saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2249           pRequest->valid = agFALSE;
2250 
2251           /* return the request to free pool */
2252           saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2253 
2254           ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2255 
2256           SA_DBG1(("mpiGetControllerConfigCmd, sending IOMB failed\n" ));
2257       }
2258       else
2259       {
2260         SA_DBG3(("mpiGetControllerConfigCmd, set OK\n"));
2261       }
2262       SA_DBG3(("mpiGetControllerConfigCmd, return value = %d\n", ret));
2263     }
2264 
2265     /* return value */
2266     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xq");
2267 
2268     return ret;
2269 }
2270 
2271 /******************************************************************************/
2272 /*! \brief SAS Encryption KEK command
2273  *
2274  *  This command updates one or more KEK in a controller that supports encryption.
2275  *
2276  *  \param agRoot      Handles for this instance of SAS/SATA LLL
2277  *  \param agContext   Context for the Get Nexus State command
2278  *  \param agKekMgmt   Kek information that will be sent to the controller
2279  *  \param queueNum    Queue Number of inbound/outbound queue
2280  *
2281  *  \return If the MPI command is sent to SPC successfully
2282  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
2283  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
2284  *          - \e AGSA_RC_FAILURE the MPI command is failure
2285  *
2286  */
2287 /*******************************************************************************/
2288 GLOBAL bit32 mpiKekManagementCmd(
2289    agsaRoot_t        *agRoot,
2290    agsaContext_t     *agContext,
2291    agsaKekManagementCmd_t *agKekMgmt,
2292    bit32             queueNum
2293    )
2294 {
2295     bit32                    ret = AGSA_RC_SUCCESS;
2296     agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
2297     agsaIORequestDesc_t      *pRequest;
2298 
2299     smTraceFuncEnter(hpDBG_VERY_LOUD,"x2");
2300 
2301     /* Get request from free IORequests */
2302     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2303     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2304 
2305     /* If no LL Control request entry available */
2306     if ( agNULL == pRequest )
2307     {
2308       SA_DBG1(("mpiKekManagementCmd, No request from free list\n" ));
2309       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "x2");
2310       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2311       return AGSA_RC_BUSY;
2312     }
2313     /* If LL Control request entry avaliable */
2314     else
2315     {
2316       SA_DBG3(("mpiKekManagementCmd, Build OPC_INB_KEK_MANAGEMENT\n"));
2317       /* Remove the request from free list */
2318       SA_ASSERT((!pRequest->valid), "The pRequest is in use");
2319       saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2320       saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2321       saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2322       saRoot->IOMap[pRequest->HTag].agContext = agContext;
2323       pRequest->valid = agTRUE;
2324       agKekMgmt->tag = pRequest->HTag;
2325       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2326 
2327       SA_DBG1(("mpiKekManagementCmd, 0x%X 0x%X 0x%X\n", agKekMgmt->tag,agKekMgmt->NEWKIDX_CURKIDX_KBF_Reserved_SKNV_KSOP, agKekMgmt->reserved ));
2328 
2329       ret = mpiBuildCmd(agRoot, (bit32 *)agKekMgmt, MPI_CATEGORY_SAS_SATA, OPC_INB_KEK_MANAGEMENT, IOMB_SIZE64, 0);
2330 
2331       if (AGSA_RC_SUCCESS != ret)
2332       {
2333           ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2334           /* remove the request from IOMap */
2335           saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2336           saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2337           saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2338           pRequest->valid = agFALSE;
2339           /* return the request to free pool */
2340           saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2341 
2342           ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2343           SA_DBG1(("mpiKekManagementCmd, sending IOMB failed\n" ));
2344       }
2345       SA_DBG3(("mpiKekManagementCmd, return value = %d\n", ret));
2346     }
2347 
2348     /* return value */
2349     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "x2");
2350 
2351     return ret;
2352 }
2353 
2354 /******************************************************************************/
2355 /*! \brief SAS Encryption DEK management command
2356  *
2357  *  This command updates one or more DEK in a controller that supports encryption.
2358  *
2359  *  \param agRoot      Handles for this instance of SAS/SATA LLL
2360  *  \param agContext   Context for the Get Nexus State command
2361  *  \param agDekMgmt   DEK information that will be sent to the controller
2362  *  \param queueNum    Queue Number of inbound/outbound queue
2363  *
2364  *  \return If the MPI command is sent to SPC successfully
2365  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
2366  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
2367  *          - \e AGSA_RC_FAILURE the MPI command is failure
2368  *
2369  */
2370 /*******************************************************************************/
2371 GLOBAL bit32 mpiDekManagementCmd(
2372    agsaRoot_t                *agRoot,
2373    agsaContext_t             *agContext,
2374    agsaDekManagementCmd_t    *agDekMgmt,
2375    bit32                     queueNum
2376    )
2377 {
2378      bit32                    ret = AGSA_RC_SUCCESS;
2379     agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
2380     agsaIORequestDesc_t      *pRequest;
2381 
2382     smTraceFuncEnter(hpDBG_VERY_LOUD,"xs");
2383 
2384     /* Get request from free IORequests */
2385     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2386     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2387 
2388     /* If no LL Control request entry available */
2389     if ( agNULL == pRequest )
2390     {
2391       SA_DBG1(("mpiDekManagementCmd, No request from free list\n" ));
2392       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xs");
2393       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2394       return AGSA_RC_BUSY;
2395     }
2396     /* If LL Control request entry avaliable */
2397     else
2398     {
2399       SA_DBG1(("mpiDekManagementCmd, Build OPC_INB_DEK_MANAGEMENT pRequest %p\n",pRequest));
2400       /* Remove the request from free list */
2401       SA_ASSERT((!pRequest->valid), "The pRequest is in use");
2402       saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2403       saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2404       saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2405       saRoot->IOMap[pRequest->HTag].agContext = agContext;
2406       pRequest->valid = agTRUE;
2407       agDekMgmt->tag = pRequest->HTag;
2408       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2409 
2410       SA_DBG1(("mpiDekManagementCmd: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n",
2411                                     agDekMgmt->tag,
2412                                     agDekMgmt->KEKIDX_Reserved_TBLS_DSOP,
2413                                     agDekMgmt->dekIndex,
2414                                     agDekMgmt->tableAddrLo,
2415                                     agDekMgmt->tableAddrHi,
2416                                     agDekMgmt->tableEntries,
2417                                     agDekMgmt->Reserved_DBF_TBL_SIZE ));
2418       ret = mpiBuildCmd(agRoot, (bit32 *) agDekMgmt, MPI_CATEGORY_SAS_SATA, OPC_INB_DEK_MANAGEMENT, IOMB_SIZE64, 0);
2419 
2420       if (AGSA_RC_SUCCESS != ret)
2421       {
2422         ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2423         /* remove the request from IOMap */
2424         saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2425         saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2426         saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2427         pRequest->valid = agFALSE;
2428 
2429         /* return the request to free pool */
2430         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2431 
2432         ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2433 
2434         SA_DBG1(("mpiDekManagementCmd, sending IOMB failed\n" ));
2435       }
2436       SA_DBG3(("mpiDekManagementCmd, return value = %d\n", ret));
2437     }
2438 
2439     /* return value */
2440     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xs");
2441 
2442     return ret;
2443 }
2444 
2445 /******************************************************************************/
2446 /*! \brief
2447  *
2448  *  This command sends operator management command.
2449  *
2450  *  \param agRoot      Handles for this instance of SAS/SATA LLL
2451  *  \param agContext   Context
2452  *  \param queueNum    Queue Number of inbound/outbound queue
2453  *
2454  *  \return If the MPI command is sent to SPC successfully
2455  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
2456  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
2457  *          - \e AGSA_RC_FAILURE the MPI command is failure
2458  *
2459  */
2460 /*******************************************************************************/
2461 GLOBAL bit32 mpiOperatorManagementCmd(
2462   agsaRoot_t                *agRoot,
2463   bit32                     queueNum,
2464   agsaContext_t             *agContext,
2465   agsaOperatorMangmentCmd_t *operatorcode )
2466 {
2467    bit32                    ret = AGSA_RC_SUCCESS;
2468   agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
2469   agsaIORequestDesc_t      *pRequest;
2470 
2471   smTraceFuncEnter(hpDBG_VERY_LOUD,"2q");
2472 
2473   SA_DBG1(("mpiOperatorManagementCmd, enter\n" ));
2474 
2475   /* Get request from free IORequests */
2476   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2477   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2478 
2479   /* If no LL Control request entry available */
2480   if ( agNULL == pRequest )
2481   {
2482     SA_DBG1(("mpiOperatorManagementCmd, No request from free list\n" ));
2483     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2q");
2484     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2485     return AGSA_RC_BUSY;
2486   }
2487   /* If LL Control request entry avaliable */
2488   else
2489   {
2490     SA_DBG1(("mpiOperatorManagementCmd, Build OPC_INB_OPR_MGMT\n"));
2491     /* Remove the request from free list */
2492     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
2493     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2494     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2495     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2496     saRoot->IOMap[pRequest->HTag].agContext = agContext;
2497     pRequest->valid = agTRUE;
2498     operatorcode->tag = pRequest->HTag;
2499     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2500 
2501     ret = mpiBuildCmd(agRoot, (bit32 *)operatorcode , MPI_CATEGORY_SAS_SATA, OPC_INB_OPR_MGMT, IOMB_SIZE128, 0);
2502 
2503     if (AGSA_RC_SUCCESS != ret)
2504     {
2505       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2506       /* remove the request from IOMap */
2507       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2508       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2509       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2510       pRequest->valid = agFALSE;
2511 
2512       /* return the request to free pool */
2513       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2514 
2515       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2516 
2517       SA_DBG1(("mpiOperatorManagementCmd, sending IOMB failed\n" ));
2518     }
2519     SA_DBG1(("mpiOperatorManagementCmd, return value = %d\n", ret));
2520   }
2521 
2522   /* return value */
2523   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2q");
2524 
2525   return ret;
2526 }
2527 
2528 /******************************************************************************/
2529 /*! \brief
2530  *
2531  *  This command sends encrypt self test command.
2532  *
2533  *  \param agRoot      Handles for this instance of SAS/SATA LLL
2534  *  \param agContext   Context
2535  *  \param queueNum    Queue Number of inbound/outbound queue
2536  *
2537  *  \return If the MPI command is sent to SPC successfully
2538  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
2539  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
2540  *          - \e AGSA_RC_FAILURE the MPI command is failure
2541  *
2542  */
2543 /*******************************************************************************/
2544 GLOBAL bit32 mpiEncryptBistCmd(
2545   agsaRoot_t        *agRoot,
2546   bit32              queueNum,
2547   agsaContext_t     *agContext,
2548   agsaEncryptBist_t *bist )
2549 {
2550    bit32                    ret = AGSA_RC_SUCCESS;
2551   agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
2552   agsaIORequestDesc_t      *pRequest;
2553 
2554   smTraceFuncEnter(hpDBG_VERY_LOUD,"2z");
2555 
2556   SA_DBG1(("mpiEncryptBistCmd, enter\n" ));
2557 
2558   /* Get request from free IORequests */
2559   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2560   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2561 
2562   /* If no LL Control request entry available */
2563   if ( agNULL == pRequest )
2564   {
2565     SA_DBG1(("mpiEncryptBistCmd, No request from free list\n" ));
2566     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2z");
2567     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2568     return AGSA_RC_BUSY;
2569   }
2570   /* If LL Control request entry avaliable */
2571   else
2572   {
2573     SA_DBG1(("mpiEncryptBistCmd, Build OPC_INB_ENC_TEST_EXECUTE\n"));
2574     /* Remove the request from free list */
2575     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
2576     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2577     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2578     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2579     saRoot->IOMap[pRequest->HTag].agContext = agContext;
2580     pRequest->valid = agTRUE;
2581     bist->tag = pRequest->HTag;
2582     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2583 
2584     SA_DBG1(("mpiEncryptBistCmd: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n",
2585                                   bist->tag,
2586                                   bist->r_subop,
2587                                   bist->testDiscption[0],
2588                                   bist->testDiscption[1],
2589                                   bist->testDiscption[2],
2590                                   bist->testDiscption[3],
2591                                   bist->testDiscption[4] ));
2592     ret = mpiBuildCmd(agRoot, (bit32 *)bist , MPI_CATEGORY_SAS_SATA, OPC_INB_ENC_TEST_EXECUTE, IOMB_SIZE64, 0);
2593 
2594     if (AGSA_RC_SUCCESS != ret)
2595     {
2596       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2597       /* remove the request from IOMap */
2598       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2599       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2600       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2601       pRequest->valid = agFALSE;
2602 
2603       /* return the request to free pool */
2604       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2605 
2606       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2607 
2608       SA_DBG1(("mpiEncryptBistCmd, sending IOMB failed\n" ));
2609     }
2610     SA_DBG1(("mpiEncryptBistCmd, return value = %d\n", ret));
2611   }
2612 
2613   /* return value */
2614   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2z");
2615 
2616   return ret;
2617 }
2618 
2619 /******************************************************************************/
2620 /*! \brief
2621  *
2622  *  This command sends set operator command.
2623  *
2624  *  \param agRoot      Handles for this instance of SAS/SATA LLL
2625  *  \param agContext   Context
2626  *  \param queueNum    Queue Number of inbound/outbound queue
2627  *
2628  *  \return If the MPI command is sent to SPC successfully
2629  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
2630  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
2631  *          - \e AGSA_RC_FAILURE the MPI command is failure
2632  *
2633  */
2634 /*******************************************************************************/
2635 GLOBAL bit32
2636 mpiSetOperatorCmd(
2637   agsaRoot_t                *agRoot,
2638   bit32                      queueNum,
2639   agsaContext_t             *agContext,
2640   agsaSetOperatorCmd_t      *operatorcode
2641   )
2642 {
2643    bit32                    ret = AGSA_RC_SUCCESS;
2644   agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
2645   agsaIORequestDesc_t      *pRequest;
2646 
2647   smTraceFuncEnter(hpDBG_VERY_LOUD,"39");
2648 
2649   SA_DBG1(("mpiSetOperatorCmd, enter\n" ));
2650 
2651   /* Get request from free IORequests */
2652   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2653   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2654 
2655   /* If no LL Control request entry available */
2656   if ( agNULL == pRequest )
2657   {
2658     SA_DBG1(("mpiSetOperatorCmd, No request from free list\n" ));
2659     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "39");
2660     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2661     return AGSA_RC_BUSY;
2662   }
2663   /* If LL Control request entry avaliable */
2664   else
2665   {
2666     SA_DBG1(("mpiSetOperatorCmd, Build OPC_INB_SET_OPERATOR\n"));
2667     /* Remove the request from free list */
2668     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
2669     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2670     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2671     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2672     saRoot->IOMap[pRequest->HTag].agContext = agContext;
2673     pRequest->valid = agTRUE;
2674     operatorcode->tag = pRequest->HTag;
2675     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2676 
2677     ret = mpiBuildCmd(agRoot, (bit32 *)operatorcode, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_OPERATOR, IOMB_SIZE64, 0);
2678 
2679     if (AGSA_RC_SUCCESS != ret)
2680     {
2681       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2682       /* remove the request from IOMap */
2683       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2684       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2685       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2686       pRequest->valid = agFALSE;
2687 
2688       /* return the request to free pool */
2689       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2690 
2691       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2692 
2693       SA_DBG1(("mpiSetOperatorCmd, sending IOMB failed\n" ));
2694     }
2695     SA_DBG1(("mpiSetOperatorCmd, return value = %d\n", ret));
2696   }
2697 
2698   /* return value */
2699   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "39");
2700 
2701   return ret;
2702 }
2703 
2704 /******************************************************************************/
2705 /*! \brief
2706  *
2707  *  This command sends get operator command.
2708  *
2709  *  \param agRoot      Handles for this instance of SAS/SATA LLL
2710  *  \param agContext   Context
2711  *  \param queueNum    Queue Number of inbound/outbound queue
2712  *
2713  *  \return If the MPI command is sent to SPC successfully
2714  *          - \e AGSA_RC_SUCCESS the MPI command is successfully
2715  *          - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
2716  *          - \e AGSA_RC_FAILURE the MPI command is failure
2717  *
2718  */
2719 /*******************************************************************************/
2720 GLOBAL bit32
2721 mpiGetOperatorCmd(
2722   agsaRoot_t                *agRoot,
2723   bit32                      queueNum,
2724   agsaContext_t             *agContext,
2725   agsaGetOperatorCmd_t      *operatorcode
2726   )
2727 {
2728    bit32                    ret = AGSA_RC_SUCCESS;
2729   agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
2730   agsaIORequestDesc_t      *pRequest;
2731 
2732   smTraceFuncEnter(hpDBG_VERY_LOUD,"3e");
2733 
2734   SA_DBG1(("mpiGetOperatorCmd, enter\n" ));
2735 
2736   /* Get request from free IORequests */
2737   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2738   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2739 
2740   /* If no LL Control request entry available */
2741   if ( agNULL == pRequest )
2742   {
2743     SA_DBG1(("mpiGetOperatorCmd, No request from free list\n" ));
2744     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3e");
2745     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2746     return AGSA_RC_BUSY;
2747   }
2748   /* If LL Control request entry avaliable */
2749   else
2750   {
2751     SA_DBG1(("mpiGetOperatorCmd, Build OPC_INB_GET_OPERATOR\n"));
2752     /* Remove the request from free list */
2753     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
2754     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2755     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2756     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2757     saRoot->IOMap[pRequest->HTag].agContext = agContext;
2758     pRequest->valid = agTRUE;
2759     operatorcode->tag = pRequest->HTag;
2760     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2761 
2762     ret = mpiBuildCmd(agRoot, (bit32 *)operatorcode, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_OPERATOR, IOMB_SIZE64, 0);
2763 
2764     if (AGSA_RC_SUCCESS != ret)
2765     {
2766       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2767       /* remove the request from IOMap */
2768       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2769       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2770       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2771       pRequest->valid = agFALSE;
2772 
2773       /* return the request to free pool */
2774       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2775 
2776       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2777 
2778       SA_DBG1(("mpiGetOperatorCmd, sending IOMB failed\n" ));
2779     }
2780     SA_DBG1(("mpiGetOperatorCmd, return value = %d\n", ret));
2781   }
2782 
2783   /* return value */
2784   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3e");
2785 
2786   return ret;
2787 }
2788 
2789 GLOBAL bit32 mpiDIFEncryptionOffloadCmd(
2790    agsaRoot_t                      *agRoot,
2791    agsaContext_t                   *agContext,
2792    bit32                            queueNum,
2793    bit32                            op,
2794    agsaDifEncPayload_t             *agDifEncOffload,
2795    ossaDIFEncryptionOffloadStartCB_t agCB
2796    )
2797 {
2798   bit32 ret = AGSA_RC_SUCCESS;
2799   bit32 dw8=0;
2800   bit32 dw9=0;
2801   bit32 dw10=0;
2802   bit32 dw14=0;
2803   bit32 dw15=0;
2804   agsaLLRoot_t             *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
2805   agsaIORequestDesc_t      *pRequest;
2806   agsaDifEncOffloadCmd_t   payload;
2807   smTraceFuncEnter(hpDBG_VERY_LOUD,"2b");
2808 
2809   /* Get request from free IORequests */
2810   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2811   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
2812 
2813   /* If no LL Control request entry available */
2814   if ( agNULL == pRequest )
2815   {
2816     SA_DBG1(("mpiDIFEncryptionOffloadCmd: No request from free list\n" ));
2817     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2b");
2818     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2819     return AGSA_RC_BUSY;
2820   }
2821   /* If LL Control request entry avaliable */
2822   else
2823   {
2824     SA_DBG1(("mpiDIFEncryptionOffloadCmd: Build OPC_INB_DIF_ENC_OFFLOAD_CMD pRequest %p\n",pRequest));
2825     /* Remove the request from free list */
2826     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
2827     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
2828     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
2829     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
2830     saRoot->IOMap[pRequest->HTag].agContext = agContext;
2831     pRequest->valid = agTRUE;
2832     pRequest->completionCB = (ossaSSPCompletedCB_t)agCB;
2833     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2834 
2835     si_memset(&payload, 0, sizeof(agsaDifEncOffloadCmd_t));
2836     SA_DBG1(("mpiDIFEncryptionOffloadCmd: op %d\n",op));
2837 
2838     if(smIS_SPCV(agRoot))
2839     {
2840       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, tag),            pRequest->HTag);
2841       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, option),         op);
2842       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, Src_Data_Len),   agDifEncOffload->SrcDL);
2843       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, Dst_Data_Len),   agDifEncOffload->DstDL);
2844       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, flags),          agDifEncOffload->dif.flags);
2845 
2846       dw8 = agDifEncOffload->dif.udrtArray[1] << SHIFT24 |
2847             agDifEncOffload->dif.udrtArray[0] << SHIFT16 |
2848             agDifEncOffload->dif.udtArray[1]  << SHIFT8  |
2849             agDifEncOffload->dif.udtArray[0];
2850       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, UDTR01UDT01), dw8);
2851 
2852       dw9 = agDifEncOffload->dif.udtArray[5]  << SHIFT24 |
2853             agDifEncOffload->dif.udtArray[4] << SHIFT16  |
2854             agDifEncOffload->dif.udtArray[3] << SHIFT8   |
2855             agDifEncOffload->dif.udtArray[2];
2856       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, UDT2345), dw9);
2857       dw10 = agDifEncOffload->dif.udrtArray[5] << SHIFT24 |
2858              agDifEncOffload->dif.udrtArray[4] << SHIFT16 |
2859              agDifEncOffload->dif.udrtArray[3] << SHIFT8  |
2860              agDifEncOffload->dif.udrtArray[2];
2861 
2862       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, UDTR2345), dw10);
2863 
2864       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, DPLR0SecCnt_IOSeed),
2865                agDifEncOffload->dif.DIFPerLARegion0SecCount << SHIFT16 |
2866                agDifEncOffload->dif.initialIOSeed);
2867 
2868       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, DPL_Addr_Lo)        , agDifEncOffload->dif.DIFPerLAAddrLo);
2869       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, DPL_Addr_Hi)        , agDifEncOffload->dif.DIFPerLAAddrHi);
2870 
2871       dw14 =  agDifEncOffload->encrypt.dekInfo.dekIndex          << SHIFT8 |
2872              (agDifEncOffload->encrypt.dekInfo.dekTable & 0x3)   << SHIFT2 |
2873              (agDifEncOffload->encrypt.keyTagCheck & 0x1)        << SHIFT1;
2874 
2875       if (agDifEncOffload->encrypt.cipherMode == agsaEncryptCipherModeXTS)
2876       {
2877         dw14 |= AGSA_ENCRYPT_XTS_Mode << SHIFT4;
2878       }
2879       else
2880       {
2881         dw14 |= (agDifEncOffload->encrypt.cipherMode & 0xF) << SHIFT4;
2882       }
2883 
2884       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, KeyIndex_CMode_KTS_ENT_R), dw14);
2885 
2886       dw15 = agDifEncOffload->encrypt.EncryptionPerLRegion0SecCount << SHIFT16 |
2887                            (agDifEncOffload->encrypt.kekIndex & 0xF) << SHIFT5 |
2888                            (agDifEncOffload->encrypt.sectorSizeIndex & 0x1F);
2889 
2890       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, EPLR0SecCnt_KS_ENSS), dw15);
2891 
2892       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, keyTag_W0),   agDifEncOffload->encrypt.keyTag_W0);
2893       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, keyTag_W1),   agDifEncOffload->encrypt.keyTag_W1);
2894       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, tweakVal_W0), agDifEncOffload->encrypt.tweakVal_W0);
2895       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, tweakVal_W1), agDifEncOffload->encrypt.tweakVal_W1);
2896       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, tweakVal_W2), agDifEncOffload->encrypt.tweakVal_W2);
2897       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, tweakVal_W3), agDifEncOffload->encrypt.tweakVal_W3);
2898       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, EPL_Addr_Lo), agDifEncOffload->encrypt.EncryptionPerLAAddrLo);
2899       OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, EPL_Addr_Hi), agDifEncOffload->encrypt.EncryptionPerLAAddrHi);
2900 
2901       si_memcpy((bit32 *) &(payload.SrcSgl), (bit32 *) &(agDifEncOffload->SrcSgl), sizeof(agsaSgl_t));
2902       si_memcpy((bit32 *) &(payload.DstSgl), (bit32 *) &(agDifEncOffload->DstSgl), sizeof(agsaSgl_t));
2903 
2904       ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_DIF_ENC_OFFLOAD_CMD, IOMB_SIZE128, queueNum);
2905 
2906     }
2907     else
2908     {
2909       /* SPC does not support this command */
2910       ret = AGSA_RC_FAILURE;
2911     }
2912 
2913     if (AGSA_RC_SUCCESS != ret)
2914     {
2915       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2916       /* remove the request from IOMap */
2917       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
2918       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
2919       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
2920       pRequest->valid = agFALSE;
2921 
2922       /* return the request to free pool */
2923       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
2924 
2925       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
2926 
2927       SA_DBG1(("mpiDIFEncryptionOffloadCmd: sending IOMB failed\n" ));
2928     }
2929     SA_DBG3(("mpiDIFEncryptionOffloadCmd: return value = %d\n", ret));
2930   }
2931 
2932   /* return value */
2933   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2b");
2934 
2935   return ret;
2936 }
2937 
2938