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 sadisc.c
24 *  \brief The file implements the functions to do SAS/SATA discovery
25 */
26
27/******************************************************************************/
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31#include <dev/pms/config.h>
32
33#include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
34#ifdef SA_ENABLE_TRACE_FUNCTIONS
35#ifdef siTraceFileID
36#undef siTraceFileID
37#endif
38#define siTraceFileID 'C'
39#endif
40
41/******************************************************************************/
42/*! \brief Start/Abort SAS/SATA discovery
43 *
44 *  Start/Abort SAS/SATA discovery
45 *
46 *  \param agRoot         Handles for this instance of SAS/SATA hardware
47 *  \param agPortContext  Pointer to this instance of port context
48 *  \param type           Specifies the type(s) of discovery operation to start or cancel
49 *  \param option         Specified the discovery option
50 *
51 *  \return If discovery is started/aborted successfully
52 *          - \e AGSA_RC_SUCCESS discovery is started/aborted successfully
53 *          - \e AGSA_RC_FAILURE discovery is not started/aborted successfully
54 *
55 */
56/*******************************************************************************/
57GLOBAL bit32 saDiscover(
58  agsaRoot_t        *agRoot,
59  agsaPortContext_t *agPortContext,
60  bit32             type,
61  bit32             option
62  )
63{
64  /* Currently not supported */
65  return AGSA_RC_FAILURE;
66}
67
68/******************************************************************************/
69/*! \brief Function for target to remove stale initiator device handle
70 *
71 *  function is called to ask the LL layer to remove all LL layer and SPC firmware
72 *  internal resources associated with a device handle
73 *
74 *  \param agRoot       Handles for this instance of SAS/SATA hardware
75 *  \param agDevHandle  Handle of the device that this I/O request will be made on
76 *
77 *  \return If the device handle is removed successfully
78 *          - \e AGSA_RC_SUCCESS the device handle is removed successfully
79 *          - \e AGSA_RC_BUSY the device is busy, cannot be removed now
80 *
81 */
82/*******************************************************************************/
83GLOBAL bit32 saDeregisterDeviceHandle(
84  agsaRoot_t      *agRoot,
85  agsaContext_t   *agContext,
86  agsaDevHandle_t *agDevHandle,
87  bit32           queueNum
88  )
89{
90  agsaLLRoot_t          *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
91  agsaDeviceDesc_t      *pDevice;
92  agsaPort_t            *pPort;
93  bit32                 ret = AGSA_RC_SUCCESS;
94  bit32                 deviceid, portid;
95  bit32                 deviceIdx;
96
97  OS_ASSERT(agDevHandle != agNULL, "saDeregisterDeviceHandle agDevHandle is NULL");
98
99  smTraceFuncEnter(hpDBG_VERY_LOUD, "za");
100
101  if(agNULL == agDevHandle)
102  {
103    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "za");
104    return AGSA_RC_FAILURE;
105  }
106
107  pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
108
109  OS_ASSERT(pDevice != agNULL, "saDeregisterDeviceHandle pDevice is NULL");
110  if(pDevice == agNULL)
111  {
112    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "za");
113    return AGSA_RC_FAILURE;
114  }
115
116  /* find device id */
117  deviceid = pDevice->DeviceMapIndex;
118  deviceIdx = deviceid & DEVICE_ID_BITS;
119  OS_ASSERT(deviceIdx < MAX_IO_DEVICE_ENTRIES, "deviceIdx MAX_IO_DEVICE_ENTRIES");
120  pPort = pDevice->pPort;
121  /* find port id */
122  portid = pPort->portId;
123
124  SA_DBG3(("saDeregisterDeviceHandle: start DeviceHandle %p\n", agDevHandle));
125  SA_DBG1(("saDeregisterDeviceHandle: deviceId 0x%x Device Context %p\n", deviceid, pDevice));
126
127  if ((deviceid != saRoot->DeviceMap[deviceIdx].DeviceIdFromFW) ||
128     (pDevice != saRoot->DeviceMap[deviceIdx].DeviceHandle))
129  {
130    SA_DBG1(("saDeregisterDeviceHandle: Not match failure\n"));
131    ret = AGSA_RC_FAILURE;
132    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "za");
133    return ret;
134  }
135
136  /* Build IOMB and send it to SPC */
137  ret = mpiDeregDevHandleCmd(agRoot, agContext, pDevice, deviceid, portid, queueNum);
138
139  smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "za");
140  return ret;
141}
142
143/******************************************************************************/
144/*! \brief Function for target to remove stale initiator device handle
145 *
146 *  function is called to ask the LL layer to remove all LL layer internal resources
147 *  associated with a device handle
148 *
149 *  \param agRoot       Handles for this instance of SAS/SATA hardware
150 *  \param agDevHandle  Handle of the device that this I/O request will be made on
151 *
152 *  \return If the device handle is removed successfully
153 *          - \e AGSA_RC_SUCCESS the device handle is removed successfully
154 *          - \e AGSA_RC_BUSY the device is busy, cannot be removed now
155 *
156 */
157/*******************************************************************************/
158GLOBAL bit32 siRemoveDevHandle(
159  agsaRoot_t      *agRoot,
160  agsaDevHandle_t *agDevHandle
161  )
162{
163  agsaDeviceDesc_t      *pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
164  agsaPort_t            *pPort;
165  bit32                 ret = AGSA_RC_SUCCESS;
166
167  OS_ASSERT(pDevice != agNULL, "siRemoveDevHandle is NULL");
168  smTraceFuncEnter(hpDBG_VERY_LOUD,"zb");
169
170  if (pDevice == agNULL)
171  {
172    SA_DBG1(("siRemoveDevHandle: pDevice is NULL \n"));
173    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "zb");
174    return AGSA_RC_FAILURE;
175  }
176
177  /* If it's to remove an initiator device handle */
178  if ( &(pDevice->initiatorDevHandle) == agDevHandle )
179  {
180    (pDevice->initiatorDevHandle).sdkData = agNULL;
181  }
182  /* If it's to remove an target device handle */
183  else if ( &(pDevice->targetDevHandle) == agDevHandle )
184  {
185    (pDevice->targetDevHandle).sdkData = agNULL;
186  }
187  else
188  {
189    SA_ASSERT(agFALSE, "");
190  }
191
192  /* remove the device descriptor if it doesn't have either initiator handle and target handle */
193  if ( (agNULL == (pDevice->initiatorDevHandle).sdkData)
194      && (agNULL == (pDevice->targetDevHandle).sdkData) )
195  {
196    /* Find the port of the device */
197    pPort = pDevice->pPort;
198
199    /* remove the device descriptor free discover list */
200    switch ( pDevice->deviceType )
201    {
202      case STP_DEVICE: /* fall through */
203      case SSP_SMP_DEVICE:
204      case DIRECT_SATA_DEVICE:
205      {
206        SA_DBG3(("siRemoveDevHandle: remove device context %p\n", pDevice));
207        siPortDeviceRemove(agRoot, pPort, pDevice, agTRUE);
208        break;
209      }
210      default:
211      {
212        SA_DBG1(("siRemoveDevHandle: switch. Not calling siPortDeviceRemove %d\n", pDevice->deviceType));
213        break;
214      }
215    }
216  }
217  else
218  {
219    SA_DBG1(("siRemoveDevHandle: else. Not caling siPortDeviceRemove\n"));
220  }
221  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "zb");
222  return ret;
223}
224
225/******************************************************************************/
226/*! \brief Get Device Handles from a specific local port
227 *
228 *  Get a Device Handles
229 *
230 *  \param agRoot         Handles for this instance of SAS/SATA hardware
231 *  \param agsaContext    Pointer to this API context
232 *  \param agPortContext  Pointer to this instance of port context
233 *  \param flags          Device flags
234 *  \param agDev[]        Pointer of array of device handles
235 *  \param MaxDevs        Specified Maximum number of Device Handles
236 *
237 *  \return If GetDeviceHandles is successfully or failure
238 *          - \e AGSA_RC_SUCCESS GetDeviceHandles is successfully
239 *          - \e AGSA_RC_FAILURE GetDeviceHandles is not successfully
240 *
241 */
242/*******************************************************************************/
243GLOBAL bit32 saGetDeviceHandles(
244  agsaRoot_t        *agRoot,
245  agsaContext_t     *agContext,
246  bit32             queueNum,
247  agsaPortContext_t *agPortContext,
248  bit32             flags,
249  agsaDevHandle_t   *agDev[],
250  bit32             skipCount,
251  bit32             MaxDevs
252  )
253{
254  agsaLLRoot_t      *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
255  agsaPort_t        *pPort = (agsaPort_t *) (agPortContext->sdkData);
256  bit32             portIndex, i;
257  bit32             ret = AGSA_RC_SUCCESS;
258
259  OS_ASSERT(pPort != agNULL, "saGetDeviceHandles is NULL");
260  smTraceFuncEnter(hpDBG_VERY_LOUD,"zc");
261
262  if (pPort == agNULL)
263  {
264    SA_DBG1(("saGetDeviceHandles: pPort is NULL \n"));
265    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "zc");
266    return AGSA_RC_FAILURE;
267  }
268
269  SA_DBG1(("saGetDeviceHandles: start portId %d\n", pPort->portId));
270
271  /* save the device handles arrary pointer */
272  for (i = 0; i < MaxDevs; i ++)
273  {
274    saRoot->DeviceHandle[i] = agDev[i];
275  }
276
277  /* send GET_DEVICE_HANDLE IOMB to SPC */
278  portIndex = pPort->portId;
279  mpiGetDeviceHandleCmd(agRoot, agContext, portIndex, flags, MaxDevs, queueNum, skipCount);
280
281  /* return */
282  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "zc");
283  return ret;
284}
285
286/******************************************************************************/
287/*! \brief Register New Device from a specific local port
288 *
289 *  Register New Device API
290 *
291 *  \param agRoot         Handles for this instance of SAS/SATA hardware
292 *  \param agContext      Pointer to this API context
293 *  \param agDeviceInfo   Pointer to this instance of device info
294 *  \param agPortContext  Pointer to this instance of port context
295 *
296 *  \return If discovery is started/aborted successfully
297 *          - \e AGSA_RC_SUCCESS discovery is started/aborted successfully
298 *          - \e AGSA_RC_FAILURE discovery is not started/aborted successfully
299 *
300 */
301/*******************************************************************************/
302GLOBAL bit32 saRegisterNewDevice(
303  agsaRoot_t            *agRoot,
304  agsaContext_t         *agContext,
305  bit32                 queueNum,
306  agsaDeviceInfo_t      *agDeviceInfo,
307  agsaPortContext_t     *agPortContext,
308  bit16                 hostAssignedDeviceId
309  )
310{
311  bit32               ret = AGSA_RC_SUCCESS;
312  agsaRegDevCmd_t     payload;
313  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
314  agsaIORequestDesc_t *pRequest;
315  agsaPort_t          *pPort = (agsaPort_t *) (agPortContext->sdkData);
316  agsaSASIdentify_t   remoteIdentify;
317  bit32               i, phyId, sDTypeRate;
318  agsaDeviceDesc_t    *pDevice = agNULL;
319
320  OS_ASSERT(pPort != agNULL, "saRegisterNewDevice is NULL");
321  OS_ASSERT(saRoot != agNULL, "saRoot is NULL");
322  smTraceFuncEnter(hpDBG_VERY_LOUD,"zd");
323
324  if(saRoot == agNULL)
325  {
326    SA_DBG1(("saRegisterNewDevice: saRoot == agNULL\n"));
327      smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "zd");
328    return(AGSA_RC_FAILURE);
329  }
330
331  if (pPort == agNULL)
332  {
333    SA_DBG1(("saRegisterNewDevice: pPort is NULL \n"));
334      smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "zd");
335    return AGSA_RC_FAILURE;
336  }
337
338  SA_DBG2(("saRegisterNewDevice: start portId %d Port Context %p\n", pPort->portId, agPortContext));
339
340  SA_DBG2(("saRegisterNewDevice: smpTimeout 0x%x\n", agDeviceInfo->smpTimeout));
341  SA_DBG2(("saRegisterNewDevice: it_NexusTimeout 0x%x\n", agDeviceInfo->it_NexusTimeout));
342  SA_DBG2(("saRegisterNewDevice: firstBurstSize 0x%x\n", agDeviceInfo->firstBurstSize));
343  SA_DBG2(("saRegisterNewDevice: devType_S_Rate 0x%x\n", agDeviceInfo->devType_S_Rate));
344  SA_DBG2(("saRegisterNewDevice: flag 0x%x\n", agDeviceInfo->flag));
345  SA_DBG2(("saRegisterNewDevice: hostAssignedDeviceId  0x%x\n",hostAssignedDeviceId ));
346  SA_DBG2(("saRegisterNewDevice: Addr 0x%02x%02x%02x%02x 0x%02x%02x%02x%02x\n",
347          agDeviceInfo->sasAddressHi[0],agDeviceInfo->sasAddressHi[1],agDeviceInfo->sasAddressHi[2],agDeviceInfo->sasAddressHi[3],
348          agDeviceInfo->sasAddressLo[0],agDeviceInfo->sasAddressLo[1],agDeviceInfo->sasAddressLo[2],agDeviceInfo->sasAddressLo[3] ));
349
350  agDeviceInfo->devType_S_Rate &= DEV_LINK_RATE;
351
352  /*
353    Using agsaDeviceInfo_t, fill in only sas address and device type
354    of identify address frame
355  */
356  si_memset(&remoteIdentify, 0, sizeof(agsaSASIdentify_t));
357  for (i=0;i<4;i++)
358  {
359    remoteIdentify.sasAddressHi[i] = agDeviceInfo->sasAddressHi[i];
360    remoteIdentify.sasAddressLo[i] = agDeviceInfo->sasAddressLo[i];
361  }
362  remoteIdentify.deviceType_addressFrameType = (bit8)(agDeviceInfo->devType_S_Rate & 0xC0);
363
364  /* Get request from free IORequests */
365  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
366  pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
367
368  /* If no LL Control request entry available */
369  if ( agNULL == pRequest )
370  {
371    pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests)); /**/
372    if(agNULL != pRequest)
373    {
374      saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
375      SA_DBG1(("saRegisterNewDevice, using saRoot->freeReservedRequests\n"));
376    }
377    else
378    {
379      SA_DBG1(("saRegisterNewDevice, No request from free list Not using saRoot->freeReservedRequests\n"));
380      ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
381      smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "zd");
382      return AGSA_RC_BUSY;
383    }
384  }
385  else
386  {
387    /* If LL Control request entry avaliable */
388    saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
389  }
390
391  saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
392  saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
393  saRoot->IOMap[pRequest->HTag].agContext = agContext;
394  pRequest->valid = agTRUE;
395
396  ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
397  /* checking bit5 for SATA direct device */
398  if (!(agDeviceInfo->devType_S_Rate & 0x20))
399  {
400    /* SAS device */
401    /* Add SAS device to the device list */
402    pDevice = siPortSASDeviceAdd(agRoot,
403                       pPort,
404                       remoteIdentify,
405                       agFALSE,
406                       agDeviceInfo->smpTimeout,
407                       agDeviceInfo->it_NexusTimeout,
408                       agDeviceInfo->firstBurstSize,
409                       agDeviceInfo->devType_S_Rate,
410                       (agDeviceInfo->flag & DEV_INFO_MASK));
411   }
412   else
413   {
414    /* SATA device */
415    /* Add SATA device to the device list */
416    pDevice = siPortSATADeviceAdd(agRoot,
417                                  pPort,
418                                  agNULL,
419                                  agNULL, /* no signature */
420                                  agFALSE,
421                                  0,
422                                  agDeviceInfo->smpTimeout,
423                                  agDeviceInfo->it_NexusTimeout,
424                                  agDeviceInfo->firstBurstSize,
425                                  agDeviceInfo->devType_S_Rate,
426                                  (agDeviceInfo->flag & DEV_INFO_MASK));
427    }
428
429    SA_DBG1(("saRegisterNewDevice: Device Context %p, TypeRate 0x%x\n", pDevice, agDeviceInfo->devType_S_Rate));
430
431    pRequest->pDevice = pDevice;
432
433    /* adjust the flag bit to build the IOMB; use only bit0 and 1 */
434    sDTypeRate = agDeviceInfo->devType_S_Rate << SHIFT24;
435    sDTypeRate |= (agDeviceInfo->flag & 0x01);
436    /* set AWT flag */
437    sDTypeRate |= (agDeviceInfo->flag & 0x02) << 1;
438
439    /* If the host assigned device ID is used, then set the HA bit. */
440    if ( hostAssignedDeviceId != 0 )
441    {
442      sDTypeRate |= 2;
443      SA_DBG3(("saRegisterNewDevice:hostAssignedDeviceId 0x%x sDTypeRate 0x%x\n",hostAssignedDeviceId,sDTypeRate ));
444    }
445
446    /* Add the MCN field */
447
448    sDTypeRate |= ((agDeviceInfo->flag >> DEV_INFO_MCN_SHIFT) & 0xf) << 4;
449
450    /* Add the IR field */
451    sDTypeRate |= ((agDeviceInfo->flag >> DEV_INFO_IR_SHIFT) & 0x1) <<  3;
452
453    /* Add the ATAPI protocol flag */
454    sDTypeRate |= ((agDeviceInfo->flag & ATAPI_DEVICE_FLAG) << SHIFT9 );
455
456    /* Add the AWT  flag */
457    sDTypeRate |= (agDeviceInfo->flag & AWT_DEVICE_FLAG) ? (1 << SHIFT2) : 0;
458
459    /* Add the XFER_READY flag  */
460    sDTypeRate |= (agDeviceInfo->flag & XFER_RDY_PRIORTY_DEVICE_FLAG) ? (1 << SHIFT31) : 0;
461    if(agDeviceInfo->flag & XFER_RDY_PRIORTY_DEVICE_FLAG)
462    {
463      SA_DBG1(("saRegisterNewDevice: sflag XFER_RDY_PRIORTY_DEVICE_FLAG sDTypeRate 0x%x\n",sDTypeRate ));
464    }
465#ifdef CCFLAG_FORCE_AWT_ON
466    sDTypeRate |= (1 << SHIFT2);
467    SA_DBG1(("saRegisterNewDevice: Force AWT_DEVICE_FLAG sDTypeRate 0x%x\n",sDTypeRate ));
468#endif /* CCFLAG_FORCE_AWT_ON */
469
470    /* create payload for IOMB */
471    si_memset(&payload, 0, sizeof(agsaRegDevCmd_t));
472
473    SA_DBG2(("saRegisterNewDevice,flag 0x%08X\n",agDeviceInfo->flag));
474    if ((agDeviceInfo->devType_S_Rate & 0x30) == 0x20)
475    {
476      if(smIS_SPC(agRoot))
477      {
478        /* direct SATA device */
479        phyId = (agDeviceInfo->flag & 0xF0);
480      }
481      else
482      {
483        phyId = (agDeviceInfo->flag & 0xF0) << SHIFT4;
484      }
485    }
486    else
487    {
488      phyId = 0;
489    }
490
491    smTrace(hpDBG_VERY_LOUD,"QQ",phyId);
492    /* TP:QQ phyId */
493    smTrace(hpDBG_VERY_LOUD,"QR",pPort->portId);
494    /* TP:QR portId */
495    smTrace(hpDBG_VERY_LOUD,"QS",sDTypeRate);
496    /* TP:QS sDTypeRate */
497    smTrace(hpDBG_VERY_LOUD,"QT",agDeviceInfo->it_NexusTimeout);
498    /* TP:QT agDeviceInfo->it_NexusTimeout */
499
500    OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaRegDevCmd_t, phyIdportId), (bit32)(pPort->portId & PORTID_MASK) | phyId);
501    OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaRegDevCmd_t, dTypeLRateAwtHa), sDTypeRate);
502    OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaRegDevCmd_t, ITNexusTimeOut), (agDeviceInfo->it_NexusTimeout));
503
504    smTrace(hpDBG_VERY_LOUD,"QT",(bit32)(pPort->portId & PORTID_MASK) | phyId);
505    /* TP:QT phyIdportId */
506    /* no conversion is needed since SAS address is in BE format */
507    payload.sasAddrHi = *(bit32*)agDeviceInfo->sasAddressHi;
508    payload.sasAddrLo = *(bit32*)agDeviceInfo->sasAddressLo;
509
510    OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaRegDevCmd_t, tag), pRequest->HTag);
511    OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaRegDevCmd_t, DeviceId), ((bit32)hostAssignedDeviceId) << 16);
512
513    if(smIS_SPC(agRoot))
514    {
515      ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SPC_REG_DEV, IOMB_SIZE64, queueNum);
516    }
517    else
518    {
519      ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_REG_DEV, IOMB_SIZE64, queueNum);
520    }
521
522    if (AGSA_RC_SUCCESS != ret)
523    {
524      /* return the request to free pool */
525      ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
526      /* remove the request from IOMap */
527      saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
528      saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
529      saRoot->IOMap[pRequest->HTag].agContext = agNULL;
530      pRequest->valid = agFALSE;
531
532      if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
533      {
534        SA_DBG1(("saRegisterNewDevice: saving pRequest (%p) for later use\n", pRequest));
535        saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
536      }
537      else
538      {
539        /* return the request to free pool */
540        saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
541      }
542      ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
543      SA_DBG1(("saRegisterNewDevice, sending IOMB failed\n" ));
544    }
545    SA_DBG3(("saRegisterNewDevice: end\n"));
546
547    smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "zd");
548    return ret;
549}
550
551/******************************************************************************/
552/*! \brief Register a callback for a specific event
553 *
554 *  Register a callback for a Event API
555 *
556 *  \param agRoot          Handles for this instance of SAS/SATA hardware
557 *  \param eventSourceType Event Type
558 *  \param callbackPtr     Function pointer to OS layer
559 *
560 *  \return
561 *          - \e AGSA_RC_SUCCESS
562 *          - \e AGSA_RC_FAILURE
563 *
564 */
565/*******************************************************************************/
566GLOBAL bit32 saRegisterEventCallback(
567                        agsaRoot_t                *agRoot,
568                        bit32                     eventSourceType,
569                        ossaGenericCB_t           callbackPtr
570                        )
571{
572  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
573  bit32               ret = AGSA_RC_FAILURE;
574
575  SA_DBG3(("saRegisterEventCallback: start\n"));
576  switch (eventSourceType)
577  {
578    case OSSA_EVENT_SOURCE_DEVICE_HANDLE_ADDED:
579      saRoot->DeviceRegistrationCB =  (ossaDeviceRegistrationCB_t)callbackPtr;
580      ret = AGSA_RC_SUCCESS;
581      break;
582    case OSSA_EVENT_SOURCE_DEVICE_HANDLE_REMOVED:
583      saRoot->DeviceDeregistrationCB = (ossaDeregisterDeviceHandleCB_t) callbackPtr;
584      ret = AGSA_RC_SUCCESS;
585      break;
586    default:
587      SA_DBG1(("saRegisterEventCallback: not allowed case %d\n", eventSourceType));
588      ret = AGSA_RC_FAILURE;
589      break;
590  }
591  return ret;
592}
593
594/******************************************************************************/
595/*! \brief Get Device Information
596 *
597 *  Get SAS/SATA device information API
598 *
599 *  \param agRoot          Handles for this instance of SAS/SATA hardware
600 *  \param option          device general information or extended information
601 *  \param agDevHandle     Pointer of device handle
602 *
603 *  \return
604 *          - \e AGSA_RC_SUCCESS
605 *          - \e AGSA_RC_FAILURE
606 *
607 */
608/*******************************************************************************/
609GLOBAL bit32 saGetDeviceInfo(
610                        agsaRoot_t                *agRoot,
611                        agsaContext_t             *agContext,
612                        bit32                     option,
613                        bit32                     queueNum,
614                        agsaDevHandle_t           *agDevHandle
615                        )
616{
617  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
618  agsaDeviceDesc_t    *pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
619  bit32               deviceid;
620  bit32               ret = AGSA_RC_FAILURE;
621
622  OS_ASSERT(pDevice != agNULL, "saGetDeviceInfo is NULL");
623  smTraceFuncEnter(hpDBG_VERY_LOUD,"ze");
624
625  if (pDevice == agNULL)
626  {
627    SA_DBG1(("saGetDeviceInfo: pDevice is NULL \n"));
628    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "ze");
629    return AGSA_RC_FAILURE;
630  }
631
632  /* Get deviceid */
633  deviceid = pDevice->DeviceMapIndex;
634  SA_DBG3(("saGetDeviceInfo: start pDevice %p, deviceId %d\n", pDevice, deviceid));
635
636  /* verify the agDeviceHandle with the one in the deviceMap */
637  if ((deviceid != saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceIdFromFW) ||
638     (pDevice != saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceHandle))
639  {
640    SA_DBG1(("saGetDeviceInfo: Not match failure or device not exist\n"));
641    ret = AGSA_RC_FAILURE;
642    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "ze");
643    return ret;
644  }
645
646  /* send IOMB to the SPC */
647  ret = mpiGetDeviceInfoCmd(agRoot, agContext, deviceid, option, queueNum);
648
649  SA_DBG3(("saGetDeviceInfo: end\n"));
650  smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "ze");
651  return ret;
652}
653
654/******************************************************************************/
655/*! \brief Set Device Information
656 *
657 *  Set SAS/SATA device information API
658 *
659 *  \param agRoot          Handles for this instance of SAS/SATA hardware
660 *  \param agContext       Pointer to this API context
661 *  \param queueNum        IQ/OQ number
662 *  \param agDevHandle     Pointer of device handle
663 *  \param option          device general information or extended information
664 *  \param param           Parameter of Set Device Infomation
665 *
666 *  \return
667 *          - \e AGSA_RC_SUCCESS
668 *          - \e AGSA_RC_FAILURE
669 *
670 */
671/*******************************************************************************/
672GLOBAL bit32 saSetDeviceInfo(
673                        agsaRoot_t            *agRoot,
674                        agsaContext_t         *agContext,
675                        bit32                 queueNum,
676                        agsaDevHandle_t       *agDevHandle,
677                        bit32                  option,
678                        bit32                  param,
679                        ossaSetDeviceInfoCB_t  agCB
680                        )
681{
682  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
683  agsaDeviceDesc_t    *pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
684  bit32               deviceid;
685  bit32               ret = AGSA_RC_FAILURE;
686
687  OS_ASSERT(pDevice != agNULL, "saSetDeviceInfo is NULL");
688  smTraceFuncEnter(hpDBG_VERY_LOUD,"zf");
689
690  SA_DBG2(("saSetDeviceInfo: start pDevice %p, option=0x%x param=0x0%x\n", pDevice, option, param));
691  if(agNULL ==  pDevice )
692  {
693    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "zf");
694    return ret;
695  }
696
697
698  /* Get deviceid */
699  deviceid = pDevice->DeviceMapIndex;
700  pDevice->option = option;
701  pDevice->param = param;
702
703  SA_DBG3(("saSetDeviceInfo: deviceId %d\n", deviceid));
704
705  /* verify the agDeviceHandle with the one in the deviceMap */
706  if ((deviceid != saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceIdFromFW) ||
707     (pDevice != saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceHandle))
708  {
709    SA_DBG1(("saSetDeviceInfo: Not match failure or device not exist\n"));
710    ret = AGSA_RC_FAILURE;
711    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "zf");
712    return ret;
713  }
714
715  /* send IOMB to the SPC */
716  ret = mpiSetDeviceInfoCmd(agRoot, agContext, deviceid, option, queueNum, param, agCB);
717
718  SA_DBG3(("saSetDeviceInfo: end\n"));
719  smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "zf");
720  return ret;
721}
722
723/******************************************************************************/
724/*! \brief Get Device State
725 *
726 *  Get SAS/SATA device state API
727 *
728 *  \param agRoot          Handles for this instance of SAS/SATA hardware
729 *  \param agContext       Pointer to this API context
730 *  \param queueNum        IQ/OQ number
731 *  \param agDevHandle     Pointer of device handler
732 *
733 *  \return
734 *          - \e AGSA_RC_SUCCESS
735 *          - \e AGSA_RC_FAILURE
736 *
737 */
738/*******************************************************************************/
739GLOBAL bit32 saGetDeviceState(
740                        agsaRoot_t                *agRoot,
741                        agsaContext_t             *agContext,
742                        bit32                     queueNum,
743                        agsaDevHandle_t           *agDevHandle
744                        )
745{
746  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
747  agsaDeviceDesc_t    *pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
748  bit32               deviceid;
749  bit32               ret = AGSA_RC_FAILURE;
750
751  OS_ASSERT(pDevice != agNULL, "saGetDeviceState is NULL");
752  smTraceFuncEnter(hpDBG_VERY_LOUD,"zg");
753
754  if (pDevice == agNULL)
755  {
756    SA_DBG1(("saGetDeviceState: pDevice is NULL \n"));
757    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "zg");
758    return AGSA_RC_FAILURE;
759  }
760
761  SA_DBG3(("saGetDeviceState: start pDevice %p\n", pDevice));
762
763  /* Get deviceid */
764  deviceid = pDevice->DeviceMapIndex;
765
766  /* verify the agDeviceHandle with the one in the deviceMap */
767  if ((deviceid != saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceIdFromFW) ||
768     (pDevice != saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceHandle))
769  {
770    SA_DBG1(("saGetDeviceState: Not match failure or device not exist\n"));
771    ret = AGSA_RC_FAILURE;
772    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "zg");
773    return ret;
774  }
775
776  /* send IOMB to the SPC */
777  ret = mpiGetDeviceStateCmd(agRoot, agContext, deviceid, queueNum);
778
779  SA_DBG3(("saGetDeviceState: end\n"));
780  smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "zg");
781  return ret;
782}
783
784/******************************************************************************/
785/*! \brief Set Device State
786 *
787 *  Set SAS/SATA device state API
788 *
789 *  \param agRoot          Handles for this instance of SAS/SATA hardware
790 *  \param agContext       Pointer to this API context
791 *  \param queueNum        IQ/OQ number
792 *  \param agDevHandle     Pointer of device handler
793 *  \param newDeviceState  new device state
794 *
795 *  \return
796 *          - \e AGSA_RC_SUCCESS
797 *          - \e AGSA_RC_FAILURE
798 *
799 */
800/*******************************************************************************/
801GLOBAL bit32 saSetDeviceState(
802                        agsaRoot_t      *agRoot,
803                        agsaContext_t   *agContext,
804                        bit32           queueNum,
805                        agsaDevHandle_t *agDevHandle,
806                        bit32            newDeviceState
807                        )
808{
809  agsaLLRoot_t        *saRoot;
810  agsaDeviceDesc_t    *pDevice;
811  bit32               deviceid;
812  bit32               ret = AGSA_RC_FAILURE;
813
814  saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
815  OS_ASSERT(saRoot != agNULL, "saSetDeviceState saRoot");
816
817  if(saRoot == agNULL )
818  {
819    SA_DBG1(("saSetDeviceState: saRoot is NULL\n"));
820    return ret;
821  }
822
823  OS_ASSERT(agDevHandle != agNULL, "saSetDeviceState agDevHandle  is NULL");
824
825  smTraceFuncEnter(hpDBG_VERY_LOUD,"zh");
826
827  if(agDevHandle == agNULL )
828  {
829    SA_DBG1(("saSetDeviceState: agDevHandle is NULL\n"));
830    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "zh");
831    return ret;
832  }
833
834  pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
835
836  OS_ASSERT(pDevice != agNULL, "saSetDeviceState pDevice is NULL");
837
838  SA_DBG3(("saSetDeviceState: start pDevice %p\n", pDevice));
839
840  if(pDevice == agNULL )
841  {
842    SA_DBG1(("saSetDeviceState: pDevice is NULL\n"));
843    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "zh");
844    return ret;
845  }
846  /* Get deviceid */
847  deviceid = pDevice->DeviceMapIndex;
848
849  /* verify the agDeviceHandle with the one in the deviceMap */
850  if ((deviceid != saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceIdFromFW) ||
851     (pDevice != saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceHandle))
852  {
853    SA_DBG1(("saSetDeviceState: Not match failure or device not exist\n"));
854    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "zh");
855    return ret;
856  }
857
858  /* send IOMB to the SPC */
859  ret = mpiSetDeviceStateCmd(agRoot, agContext, deviceid, newDeviceState, queueNum);
860
861  SA_DBG3(("saSetDeviceState: end\n"));
862  smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "zh");
863  return ret;
864}
865