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