xref: /freebsd/sys/dev/pms/RefTisa/sallsdk/spc/sadisc.c (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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 /*******************************************************************************/
57 GLOBAL 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 /*******************************************************************************/
83 GLOBAL 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 /*******************************************************************************/
158 GLOBAL 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 /*******************************************************************************/
243 GLOBAL 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 /*******************************************************************************/
302 GLOBAL 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 /*******************************************************************************/
566 GLOBAL 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 /*******************************************************************************/
609 GLOBAL 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 /*******************************************************************************/
672 GLOBAL 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 /*******************************************************************************/
739 GLOBAL 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 /*******************************************************************************/
801 GLOBAL 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