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