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