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/*******************************************************************************/
57GLOBAL 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/*******************************************************************************/
94GLOBAL 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/*******************************************************************************/
189GLOBAL 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
283GLOBAL 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
358GLOBAL 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
440GLOBAL 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/*******************************************************************************/
541GLOBAL 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/*******************************************************************************/
642GLOBAL 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/*******************************************************************************/
755GLOBAL 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/*******************************************************************************/
854GLOBAL 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/*******************************************************************************/
901GLOBAL 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/*******************************************************************************/
965GLOBAL 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/*******************************************************************************/
1058GLOBAL 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/*******************************************************************************/
1173GLOBAL 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/*******************************************************************************/
1222GLOBAL 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/*******************************************************************************/
1350GLOBAL 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/*******************************************************************************/
1462GLOBAL 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/*******************************************************************************/
1639GLOBAL 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/*******************************************************************************/
1800GLOBAL 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/*******************************************************************************/
1890GLOBAL 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/*******************************************************************************/
2003GLOBAL 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/*******************************************************************************/
2098GLOBAL bit32
2099mpiSetControllerConfigCmd(
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/*******************************************************************************/
2198GLOBAL 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/*******************************************************************************/
2289GLOBAL 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/*******************************************************************************/
2372GLOBAL 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/*******************************************************************************/
2462GLOBAL 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/*******************************************************************************/
2545GLOBAL 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/*******************************************************************************/
2636GLOBAL bit32
2637mpiSetOperatorCmd(
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/*******************************************************************************/
2721GLOBAL bit32
2722mpiGetOperatorCmd(
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
2790GLOBAL 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
2939