xref: /freebsd/sys/dev/pms/RefTisa/sallsdk/spc/saphy.c (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
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 saphy.c
24  *  \brief The file implements the functions to Start, Stop a phy
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 'K'
38 #endif
39 
40 
41 extern bit32 gFPGA_TEST;
42 /******************************************************************************/
43 /*! \brief Start a Phy
44  *
45  *  Start a Phy
46  *
47  *  \param agRoot handles for this instance of SAS/SATA hardware
48  *  \param agContext
49  *  \param phyId the phy id of the link will be started
50  *  \param agPhyConfig the phy configuration
51  *  \param agSASIdentify the SAS identify frame will be sent by the phy
52  *
53  *  \return If phy is started successfully
54  *          - \e AGSA_RC_SUCCESS phy is started successfully
55  *          - \e AGSA_RC_BUSY phy is already started or starting
56  *          - \e AGSA_RC_FAILURE phy is not started successfully
57  */
58 /*******************************************************************************/
59 GLOBAL bit32 saPhyStart(
60   agsaRoot_t         *agRoot,
61   agsaContext_t      *agContext,
62   bit32              queueNum,
63   bit32              phyId,
64   agsaPhyConfig_t    *agPhyConfig,
65   agsaSASIdentify_t  *agSASIdentify
66   )
67 {
68   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
69   agsaIORequestDesc_t *pRequest;
70   bit32               ret = AGSA_RC_SUCCESS;
71   bit32               using_reserved = agFALSE;
72 
73   smTraceFuncEnter(hpDBG_VERY_LOUD, "7a");
74 
75   /* sanity check */
76   SA_ASSERT((agNULL != agRoot), "");
77   SA_ASSERT((agNULL != agSASIdentify), "");
78 
79   SA_DBG3(("saPhyStart: phy%d started with ID %08X:%08X\n",
80     phyId,
81     SA_IDFRM_GET_SAS_ADDRESSHI(agSASIdentify),
82     SA_IDFRM_GET_SAS_ADDRESSLO(agSASIdentify)));
83 
84   /* If phyId is invalid, return failure */
85   if ( phyId >= saRoot->phyCount )
86   {
87     ret = AGSA_RC_FAILURE;
88   }
89   /* If phyId is valid */
90   else
91   {
92     /* Get request from free IORequests */
93     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
94     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /* */
95     /* If no LL Control request entry available */
96     if ( agNULL == pRequest )
97     {
98       pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests));
99       /* If no LL Control request entry available */
100       if(agNULL != pRequest)
101       {
102         using_reserved = agTRUE;
103         SA_DBG1(("saPhyStart, using saRoot->freeReservedRequests\n"));
104       }
105       else
106       {
107         ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
108         SA_DBG1(("saPhyStart, No request from free list Not using saRoot->freeReservedRequests\n"));
109         smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "7a");
110         return AGSA_RC_BUSY;
111       }
112     }
113     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
114     pRequest->valid = agTRUE;
115     /* If LL Control request entry avaliable */
116     if( using_reserved )
117     {
118       saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
119     }
120     else
121     {
122       /* Remove the request from free list */
123       saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
124     }
125     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
126 
127     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
128     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
129     saRoot->IOMap[pRequest->HTag].agContext = agContext;
130     pRequest->valid = agTRUE;
131 
132     /* Build the Phy Start IOMB command and send to SPC */
133 
134     smTrace(hpDBG_VERY_LOUD,"P2", phyId);
135     /* TP:P2 phyId */
136 
137     ret = mpiPhyStartCmd(agRoot, pRequest->HTag, phyId, agPhyConfig, agSASIdentify, queueNum);
138     if (AGSA_RC_SUCCESS != ret)
139     {
140       /* remove the request from IOMap */
141       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
142       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
143       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
144       pRequest->valid = agFALSE;
145 
146       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
147       /* return the request to free pool */
148       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
149       {
150         SA_DBG1(("saPhyStart: saving pRequest (%p) for later use\n", pRequest));
151         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
152       }
153       else
154       {
155         /* return the request to free pool */
156         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
157       }
158       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
159       SA_DBG1(("saPhyStart, sending IOMB failed\n" ));
160     }
161   }
162 
163   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "7a");
164 
165   return ret;
166 }
167 
168 /******************************************************************************/
169 /*! \brief Stop a Phy
170  *
171  *  Stop a Phy
172  *
173  *  \param agRoot handles for this instance of SAS/SATA hardware
174  *  \param agContext the context of this API
175  *  \param phyId the phy id of the link will be stopped
176  *
177  *  \return If phy is stopped successfully
178  *          - \e AGSA_RC_SUCCESS phy is stopped successfully
179  *          - \e AGSA_RC_FAILURE phy is not stopped successfully
180  */
181 /*******************************************************************************/
182 GLOBAL bit32 saPhyStop(
183   agsaRoot_t      *agRoot,
184   agsaContext_t   *agContext,
185   bit32           queueNum,
186   bit32           phyId
187   )
188 {
189   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
190   agsaIORequestDesc_t *pRequest;
191   bit32               ret = AGSA_RC_SUCCESS;
192   bit32               using_reserved = agFALSE;
193 
194   smTraceFuncEnter(hpDBG_VERY_LOUD,"7b");
195 
196   /* sanity check */
197   SA_ASSERT((agNULL != agRoot), "");
198 
199   SA_DBG2(("saPhyStop: phy%d stop\n", phyId));
200 
201   if(1)
202   {
203     mpiOCQueue_t         *circularQ;
204     int i;
205     SA_DBG4(("saPhyStop:\n"));
206     for ( i = 0; i < saRoot->QueueConfig.numOutboundQueues; i++ )
207     {
208       circularQ = &saRoot->outboundQueue[i];
209       OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
210       if(circularQ->producerIdx != circularQ->consumerIdx)
211       {
212         SA_DBG1(("saPhyStop: PI 0x%03x CI 0x%03x\n",circularQ->producerIdx, circularQ->consumerIdx ));
213       }
214     }
215   }
216 
217   if(smIS_SPC(agRoot))
218   {
219     phyId &= 0xF;
220   }
221   /* If phyId is invalid, return failure */
222   if ( (phyId & 0xF) >= saRoot->phyCount )
223   {
224     ret = AGSA_RC_FAILURE;
225     SA_DBG1(("saPhyStop: phy%d - failure with phyId\n", phyId));
226   }
227   else
228   {
229     /* If phyId is valid */
230     /* Get request from free IORequests */
231     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
232     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
233     /* If no LL Control request entry available */
234     if ( agNULL == pRequest )
235     {
236       pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests));
237       /* If no LL Control request entry available */
238       if(agNULL != pRequest)
239       {
240         using_reserved = agTRUE;
241         SA_DBG1(("saPhyStop: using saRoot->freeReservedRequests\n"));
242       }
243       else
244       {
245         ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
246         SA_DBG1(("saPhyStop, No request from free list Not using saRoot->freeReservedRequests\n"));
247         smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "7b");
248         return AGSA_RC_BUSY;
249       }
250     }
251     /* Remove the request from free list */
252     if( using_reserved )
253     {
254       saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
255     }
256     else
257     {
258       saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
259     }
260     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
261     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
262     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
263     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
264     saRoot->IOMap[pRequest->HTag].agContext = agContext;
265     pRequest->valid = agTRUE;
266 
267     /* build IOMB command and send to SPC */
268     ret = mpiPhyStopCmd(agRoot, pRequest->HTag, phyId, queueNum);
269     if (AGSA_RC_SUCCESS != ret)
270     {
271       /* remove the request from IOMap */
272       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
273       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
274       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
275 
276       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
277       /* return the request to free pool */
278       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
279       {
280         SA_DBG2(("saPhyStop: saving pRequest (%p) for later use\n", pRequest));
281         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
282       }
283       else
284       {
285         /* return the request to free pool */
286         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
287       }
288       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
289       SA_DBG1(("saPhyStop, sending IOMB failed\n" ));
290     }
291   }
292 
293   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "7b");
294 
295   return ret;
296 }
297 
298 /******************************************************************************/
299 /*! \brief CallBack Routine to stop a Phy
300  *
301  *  CallBack for Stop a Phy
302  *
303  *  \param agRoot handles for this instance of SAS/SATA hardware
304  *  \param phyId the phy id of the link will be stopped
305  *  \param status the status of the phy
306  *  \param agContext the context of the saPhyStop
307  *
308  *  \return If phy is stopped successfully
309  *          - \e AGSA_RC_SUCCESS phy is stopped successfully
310  *          - \e AGSA_RC_FAILURE phy is not stopped successfully
311  */
312 /*******************************************************************************/
313 GLOBAL bit32 siPhyStopCB(
314   agsaRoot_t    *agRoot,
315   bit32         phyId,
316   bit32         status,
317   agsaContext_t *agContext,
318   bit32         portId,
319   bit32         npipps
320   )
321 {
322   agsaLLRoot_t            *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
323   agsaPhy_t               *pPhy;
324   agsaPort_t              *pPort;
325   bit32                   ret = AGSA_RC_SUCCESS;
326   bit32                   iomb_status = status;
327 
328   smTraceFuncEnter(hpDBG_VERY_LOUD,"7c");
329 
330   /* sanity check */
331   SA_ASSERT((agNULL != agRoot), "");
332 
333   /* If phyId is invalid, return failure */
334   if ( phyId >= saRoot->phyCount )
335   {
336     ret = AGSA_RC_FAILURE;
337     SA_DBG1(("siPhyStopCB: phy%d - failure with phyId\n", phyId));
338     /* makeup for CB */
339     status = (status << SHIFT8) | phyId;
340     status |= ((npipps & PORT_STATE_MASK) << SHIFT16);
341     ossaHwCB(agRoot, agNULL, OSSA_HW_EVENT_PHY_STOP_STATUS, status, agContext, agNULL);
342   }
343   /* If phyId is valid */
344   else
345   {
346     pPhy = &(saRoot->phys[phyId]);
347 
348     /* get the port of the phy */
349     pPort = pPhy->pPort;
350 
351     /* makeup for CB */
352     status = (status << SHIFT8) | phyId;
353     status |= ((npipps & PORT_STATE_MASK) << SHIFT16);
354     /* Callback to stop phy */
355     if ( agNULL != pPort )
356     {
357       if ( iomb_status == OSSA_SUCCESS && (OSSA_PORT_INVALID == (npipps & PORT_STATE_MASK) ))
358       {
359         SA_DBG1(("siPhyStopCB: phy%d invalidating port\n", phyId));
360         /* invalid port state, remove the port */
361         pPort->status |= PORT_INVALIDATING;
362         saRoot->PortMap[portId].PortStatus  |= PORT_INVALIDATING;
363         /* invalid the port */
364         siPortInvalid(agRoot, pPort);
365         /* map out the portmap */
366         saRoot->PortMap[pPort->portId].PortContext = agNULL;
367         saRoot->PortMap[pPort->portId].PortID = PORT_MARK_OFF;
368         saRoot->PortMap[pPort->portId].PortStatus  |= PORT_INVALIDATING;
369       }
370       ossaHwCB(agRoot, &(pPort->portContext), OSSA_HW_EVENT_PHY_STOP_STATUS, status, agContext, agNULL);
371     }
372     else
373     {
374       SA_DBG1(("siPhyStopCB: phy%d - Port is not established\n", phyId));
375       ossaHwCB(agRoot, agNULL, OSSA_HW_EVENT_PHY_STOP_STATUS, status, agContext, agNULL);
376     }
377 
378     /* set PHY_STOPPED status */
379     PHY_STATUS_SET(pPhy, PHY_STOPPED);
380 
381     /* Exclude the phy from a port */
382     if ( agNULL != pPort )
383     {
384       /* Acquire port list lock */
385       ossaSingleThreadedEnter(agRoot, LL_PORT_LOCK);
386 
387       /* Delete the phy from the port */
388       pPort->phyMap[phyId] = agFALSE;
389       saRoot->phys[phyId].pPort = agNULL;
390 
391       /* Release port list lock */
392       ossaSingleThreadedLeave(agRoot, LL_PORT_LOCK);
393     }
394   }
395 
396   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "7c");
397 
398   /* return */
399   return ret;
400 }
401 
402 /******************************************************************************/
403 /*! \brief Initiate a Local PHY control command
404  *
405  *  This function is called to initiate a PHY control command to the local PHY.
406  *  The completion of this function is reported in ossaLocalPhyControlCB()
407 
408  *
409  *  \param agRoot handles for this instance of SAS/SATA hardware
410  *  \param agContext the context of this API
411  *  \param phyId  phy number
412  *  \param phyOperation
413  *    one of AGSA_PHY_LINK_RESET, AGSA_PHY_HARD_RESET, AGSA_PHY_ENABLE_SPINUP
414  *
415  *  \return
416  *          - none
417  */
418 /*******************************************************************************/
419 GLOBAL bit32 saLocalPhyControl(
420   agsaRoot_t             *agRoot,
421   agsaContext_t          *agContext,
422   bit32                   queueNum,
423   bit32                   phyId,
424   bit32                   phyOperation,
425   ossaLocalPhyControlCB_t agCB
426   )
427 {
428   agsaLLRoot_t         *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
429   agsaIORequestDesc_t  *pRequest;
430   agsaPhyErrCounters_t errorParam;
431   bit32                ret = AGSA_RC_SUCCESS;
432   bit32                value, value1, value2, copyPhyId;
433   bit32                count = 100;
434   bit32                using_reserved = agFALSE;
435 
436 
437   /* sanity check */
438   SA_ASSERT((agNULL != saRoot), "");
439   if(saRoot == agNULL)
440   {
441     SA_DBG1(("saLocalPhyControl: saRoot == agNULL\n"));
442     return(AGSA_RC_FAILURE);
443   }
444   smTraceFuncEnter(hpDBG_VERY_LOUD,"7d");
445 
446   si_memset(&errorParam,0,sizeof(agsaPhyErrCounters_t));
447   SA_DBG2(("saLocalPhyControl: phy%d operation %08X\n", phyId, phyOperation));
448 
449   switch(phyOperation)
450   {
451     case AGSA_PHY_LINK_RESET:
452     case AGSA_PHY_HARD_RESET:
453     case AGSA_PHY_NOTIFY_ENABLE_SPINUP:
454     case AGSA_PHY_BROADCAST_ASYNCH_EVENT:
455     case AGSA_PHY_COMINIT_OOB:
456     {
457       /* Get request from free IORequests */
458       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
459       pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
460 
461       /* If no LL Control request entry available */
462       if ( agNULL == pRequest )
463       {
464         pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests));
465         /* If no LL Control request entry available */
466         if(agNULL != pRequest)
467         {
468           using_reserved = agTRUE;
469           SA_DBG1(("saLocalPhyControl, using saRoot->freeReservedRequests\n"));
470         }
471         else
472         {
473           ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
474           SA_DBG1(("saLocalPhyControl, No request from free list Not using saRoot->freeReservedRequests\n"));
475           smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "7d");
476           return AGSA_RC_BUSY;
477         }
478       }
479       if( using_reserved )
480       {
481         saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
482       }
483       else
484       {
485         saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
486       }
487       /* Remove the request from free list */
488       SA_ASSERT((!pRequest->valid), "The pRequest is in use");
489       pRequest->completionCB = (void*)agCB;
490       //  pRequest->abortCompletionCB = agCB;
491       saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
492       saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
493       saRoot->IOMap[pRequest->HTag].agContext = agContext;
494       pRequest->valid = agTRUE;
495       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
496 
497       /* Build the local phy control IOMB command and send to SPC */
498       ret = mpiLocalPhyControlCmd(agRoot, pRequest->HTag, phyId, phyOperation, queueNum);
499       if (AGSA_RC_SUCCESS != ret)
500       {
501         /* remove the request from IOMap */
502         saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
503         saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
504         saRoot->IOMap[pRequest->HTag].agContext = agNULL;
505         pRequest->valid = agFALSE;
506 
507         ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
508         /* return the request to free pool */
509         if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
510         {
511           SA_DBG1(("saLocalPhyControl: saving pRequest (%p) for later use\n", pRequest));
512           saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
513         }
514         else
515         {
516           /* return the request to free pool */
517           saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
518         }
519         SA_DBG1(("saLocalPhyControl, sending IOMB failed\n" ));
520         ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
521         return ret;
522       }
523     }
524     break;
525     case AGSA_PHY_GET_ERROR_COUNTS:
526     {
527       if(smIS_SPCV(agRoot))
528       {
529 
530         SA_ASSERT((smIS_SPC(agRoot)), "SPC only");
531         SA_DBG1(("saLocalPhyControl: V AGSA_PHY_GET_ERROR_COUNTS\n" ));
532         smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "7d");
533         return AGSA_RC_FAILURE;
534       }
535       /* If phyId is invalid, return failure */
536       if ( phyId >= saRoot->phyCount )
537       {
538         ret = AGSA_RC_FAILURE;
539         si_memset(&errorParam, 0, sizeof(agsaPhyErrCounters_t));
540         SA_DBG1(("saLocalPhyControl: phy%d - failure with phyId\n", phyId));
541         /* call back with the status */
542 
543         if( agCB == agNULL )
544         {
545           ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
546         }
547         else
548         {
549           agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
550         }
551         smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "7d");
552         return ret;
553       }
554       /* save phyId */
555       copyPhyId = phyId;
556       /* map 0x030000 or 0x040000 based on phyId to BAR4(0x20), BAT2(win) to access the register  */
557       if (phyId < 4)
558       {
559         /* for phyId = 0, 1, 2, 3 */
560         value = 0x030000;
561       }
562       else
563       {
564         /* for phyId = 4, 5, 6, 7 */
565         phyId = phyId - 4;
566         value = 0x040000;
567       }
568 
569       /* Need to make sure DEVICE_LCLK_GENERATION register bit 6 is 0 */
570       value1 = ossaHwRegReadExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK);
571 
572       SA_DBG3(("saLocalPhyControl: TOP DEVICE LCLK Register value = %08X\n", value1));
573       /* If LCLK_CLEAR bit set then disable it */
574       if (value1 & DEVICE_LCLK_CLEAR)
575       {
576         ossaHwRegWriteExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK, (value1 & 0xFFFFFFBF) );
577         SA_DBG3(("saLocalPhyControl: TOP DEVICE LCLK value = %08X\n", (value1 & 0xFFFFFFBF)));
578       }
579 
580       if (AGSA_RC_FAILURE == siBar4Shift(agRoot, value))
581       {
582         SA_DBG1(("saLocalPhyControl:Shift Bar4 to 0x%x failed\n", value));
583         phyId = copyPhyId;
584         /* call back with the status */
585 
586         if( agCB == agNULL )
587         {
588           ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
589         }
590         else
591         {
592           agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
593         }
594 
595         smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "7d");
596         return AGSA_RC_FAILURE;
597       }
598 
599       /* set LCLK = 1 and LCLK_CLEAR = 0 */
600       SPC_WRITE_COUNTER_CNTL(phyId, LCLK);
601 
602       /* LCLK bit should be low to be able to read error registers */
603       while((value = SPC_READ_COUNTER_CNTL(phyId)) & LCLK)
604       {
605         if(--count == 0)
606         {
607           SA_DBG1(("saLocalPhyControl: Timeout,SPC_COUNTER_CNTL value = %08X\n", value));
608           ret = AGSA_RC_FAILURE;
609           break;
610         }
611       } /* while */
612 
613       value = SPC_READ_COUNTER_CNTL(phyId);
614       SA_DBG3(("saLocalPhyControl: SPC_COUNTER_CNTL value = %08X\n", value));
615 
616       /* invalidDword */
617       errorParam.invalidDword = SPC_READ_INV_DW_COUNT(phyId);
618       /* runningDisparityError */
619       errorParam.runningDisparityError = SPC_READ_DISP_ERR_COUNT(phyId);
620       /* lossOfDwordSynch */
621       errorParam.lossOfDwordSynch = SPC_READ_LOSS_DW_COUNT(phyId);
622       /* phyResetProblem */
623       errorParam.phyResetProblem = SPC_READ_PHY_RESET_COUNT(phyId);
624       /* codeViolation */
625       errorParam.codeViolation = SPC_READ_CODE_VIO_COUNT(phyId);
626       /* never occurred in SPC8x6G */
627       errorParam.elasticityBufferOverflow = 0;
628       errorParam.receivedErrorPrimitive = 0;
629       errorParam.inboundCRCError = 0;
630 
631       SA_DBG3(("saLocalPhyControl:INV_DW_COUNT         0x%x\n", SPC_READ_INV_DW_COUNT(phyId)));
632       SA_DBG3(("saLocalPhyControl:DISP_ERR_COUNT       0x%x\n", SPC_READ_DISP_ERR_COUNT(phyId)));
633       SA_DBG3(("saLocalPhyControl:LOSS_DW_COUNT        0x%x\n", SPC_READ_LOSS_DW_COUNT(phyId)));
634       SA_DBG3(("saLocalPhyControl:PHY_RESET_COUNT      0x%x\n", SPC_READ_PHY_RESET_COUNT(phyId)));
635       SA_DBG3(("saLocalPhyControl:CODE_VIOLATION_COUNT 0x%x\n", SPC_READ_CODE_VIO_COUNT(phyId)));
636 
637       /* Shift back to BAR4 original address */
638       if (AGSA_RC_FAILURE == siBar4Shift(agRoot, 0x0))
639       {
640         SA_DBG1(("saLocalPhyControl:Shift Bar4 to 0x%x failed\n", 0x0));
641         ret = AGSA_RC_FAILURE;
642       }
643 
644       /* restore back the Top Device LCLK generation register value */
645       ossaHwRegWriteExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK, value1);
646 
647       /* restore phyId */
648       phyId = copyPhyId;
649       /* call back with the status */
650 
651       if (AGSA_RC_SUCCESS == ret)
652       {
653         if( agCB == agNULL )
654         {
655           ossaLocalPhyControlCB(agRoot, agContext, copyPhyId, phyOperation, OSSA_SUCCESS, (void *)&errorParam);
656         }
657         else
658         {
659           agCB(agRoot, agContext, copyPhyId, phyOperation, OSSA_SUCCESS, (void *)&errorParam);
660         }
661       }
662       else
663       {
664         if( agCB == agNULL )
665         {
666           ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
667         }
668         else
669         {
670           agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
671         }
672       }
673       break;
674     }
675     case AGSA_PHY_CLEAR_ERROR_COUNTS:
676     {
677       if(smIS_SPCV(agRoot))
678       {
679 
680         SA_ASSERT((smIS_SPC(agRoot)), "SPC only");
681         SA_DBG1(("saLocalPhyControl: V AGSA_PHY_CLEAR_ERROR_COUNTS\n" ));
682         smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "7d");
683         return AGSA_RC_FAILURE;
684       }
685       /* If phyId is invalid, return failure */
686       if ( phyId >= saRoot->phyCount )
687       {
688         si_memset(&errorParam, 0, sizeof(agsaPhyErrCountersPage_t));
689         SA_DBG3(("saLocalPhyControl(CLEAR): phy%d - failure with phyId\n", phyId));
690         /* call back with the status */
691         if( agCB == agNULL )
692         {
693           ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
694         }
695         else
696         {
697           agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
698         }
699         smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "7d");
700         return AGSA_RC_FAILURE;
701       }
702       /* save phyId */
703       copyPhyId = phyId;
704       /* map 0x030000 or 0x040000 based on phyId to BAR4(0x20), BAT2(win) to access the register  */
705       if (phyId < 4)
706       {
707         /* for phyId = 0, 1, 2, 3 */
708         value = 0x030000;
709       }
710       else
711       {
712         /* for phyId = 4, 5, 6, 7 */
713         phyId = phyId - 4;
714         value = 0x040000;
715       }
716       /* Need to make sure DEVICE_LCLK_GENERATION register bit 6 is 1 */
717       value2 = ossaHwRegReadExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK);
718 
719       SA_DBG3(("saLocalPhyControl: TOP DEVICE LCLK Register value = %08X\n", value2));
720       /* If LCLK_CLEAR bit not set then set it */
721       if ((value2 & DEVICE_LCLK_CLEAR) == 0)
722       {
723         ossaHwRegWriteExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK, (value2 | DEVICE_LCLK_CLEAR) );
724         SA_DBG3(("saLocalPhyControl: TOP DEVICE LCLK value = %08X\n", (value2 & 0xFFFFFFBF)));
725       }
726 
727       if (AGSA_RC_FAILURE == siBar4Shift(agRoot, value))
728       {
729         SA_DBG1(("saLocalPhyControl(CLEAR):Shift Bar4 to 0x%x failed\n", value));
730         phyId = copyPhyId;
731         /* call back with the status */
732         if( agCB == agNULL )
733         {
734           ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
735         }
736         else
737         {
738           agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
739         }
740         smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "7d");
741         return AGSA_RC_FAILURE;
742       }
743 
744       /* read Counter Control register */
745       value1 = SPC_READ_COUNTER_CNTL(phyId);
746       SA_DBG3(("saLocalPhyControl(CLEAR): SPC_COUNTER_CNTL value = %08X\n", value1));
747       /* set LCLK and LCLK_CLEAR */
748       SPC_WRITE_COUNTER_CNTL(phyId, (LCLK_CLEAR | LCLK));
749       /* read back the value of register */
750       /* poll LCLK bit = 0 */
751       while((value = SPC_READ_COUNTER_CNTL(phyId)) & LCLK)
752       {
753         if(--count == 0)
754         {
755           SA_DBG1(("saLocalPhyControl: Timeout,SPC_COUNTER_CNTL value = %08X\n", value));
756           ret = AGSA_RC_FAILURE;
757           break;
758         }
759       } /* while */
760 
761       value = SPC_READ_COUNTER_CNTL(phyId);
762       SA_DBG3(("saLocalPhyControl(CLEAR): SPC_COUNTER_CNTL value = %08X\n", value));
763 
764       /* restore the value */
765       SPC_WRITE_COUNTER_CNTL(phyId, value1);
766 
767       /* Shift back to BAR4 original address */
768       if (AGSA_RC_FAILURE == siBar4Shift(agRoot, 0x0))
769       {
770         SA_DBG1(("saLocalPhyControl:Shift Bar4 to 0x%x failed\n", 0x0));
771         ret = AGSA_RC_FAILURE;
772       }
773 
774       /* restore back the Top Device LCLK generation register value */
775       ossaHwRegWriteExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK, value2);
776 
777       /* restore phyId */
778       phyId = copyPhyId;
779       /* call back with the status */
780       if (AGSA_RC_SUCCESS == ret)
781       {
782         if( agCB == agNULL )
783         {
784           ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_SUCCESS, agNULL);
785         }
786         else
787         {
788           agCB(agRoot, agContext, phyId, phyOperation, OSSA_SUCCESS, agNULL);
789         }
790       }
791       else
792       {
793         if( agCB == agNULL )
794         {
795           ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
796         }
797         else
798         {
799           agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
800         }
801       }
802       break;
803     }
804     case AGSA_PHY_GET_BW_COUNTS:
805     {
806       SA_ASSERT((smIS_SPC(agRoot)), "SPCv only");
807       SA_DBG1(("saLocalPhyControl: AGSA_PHY_GET_BW_COUNTS\n" ));
808       break;
809     }
810 
811     default:
812       ret = AGSA_RC_FAILURE;
813       SA_ASSERT(agFALSE, "(saLocalPhyControl) Unknown operation");
814       break;
815   }
816 
817   smTraceFuncExit(hpDBG_VERY_LOUD, 'h', "7d");
818   return ret;
819 }
820 
821 
822 GLOBAL bit32 saGetPhyProfile(
823                       agsaRoot_t    *agRoot,
824                       agsaContext_t *agContext,
825                       bit32         queueNum,
826                       bit32         ppc,
827                       bit32         phyId
828                       )
829 {
830   bit32 ret = AGSA_RC_SUCCESS;
831 
832   agsaLLRoot_t            *saRoot = agNULL;
833   agsaPhyErrCountersPage_t errorParam;
834 
835   ossaLocalPhyControlCB_t agCB = ossaGetPhyProfileCB;
836 
837   /* sanity check */
838   SA_ASSERT((agNULL != agRoot), "");
839   saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
840   SA_ASSERT((agNULL != saRoot), "");
841 
842   if(saRoot == agNULL)
843   {
844     SA_DBG3(("saGetPhyProfile : saRoot is NULL"));
845     return AGSA_RC_FAILURE;
846   }
847 
848   SA_DBG1(("saGetPhyProfile: ppc 0x%x phyID %d\n", ppc,phyId));
849 
850   switch(ppc)
851   {
852     case AGSA_SAS_PHY_ERR_COUNTERS_PAGE:
853     {
854       if(smIS_SPCV(agRoot))
855       {
856 
857         SA_DBG1(("saGetPhyProfile: V AGSA_SAS_PHY_ERR_COUNTERS_PAGE\n" ));
858 
859         ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
860         smTraceFuncExit(hpDBG_VERY_LOUD, 'i', "7d");
861         return ret;
862       }
863     }
864     case AGSA_SAS_PHY_ERR_COUNTERS_CLR_PAGE:
865     {
866       /* If phyId is invalid, return failure */
867       if ( phyId >= saRoot->phyCount )
868       {
869         si_memset(&errorParam, 0, sizeof(agsaPhyErrCountersPage_t));
870         SA_DBG3(("saGetPhyProfile(CLEAR): phy%d - failure with phyId\n", phyId));
871         /* call back with the status */
872         ossaGetPhyProfileCB(agRoot, agContext, phyId, ppc, OSSA_FAILURE, (void *)&errorParam);
873         smTraceFuncExit(hpDBG_VERY_LOUD, 'j', "7d");
874         return AGSA_RC_FAILURE;
875       }
876       if(smIS_SPCV(agRoot))
877       {
878         SA_DBG1(("saGetPhyProfile: V AGSA_SAS_PHY_ERR_COUNTERS_CLR_PAGE\n" ));
879 
880         ret = mpiGetPhyProfileCmd( agRoot,agContext, ppc,phyId,agCB);
881         smTraceFuncExit(hpDBG_VERY_LOUD, 'k', "7d");
882         return ret;
883       }
884 
885     }
886     case AGSA_SAS_PHY_BW_COUNTERS_PAGE:
887     {
888       SA_DBG1(("saGetPhyProfile: AGSA_SAS_PHY_BW_COUNTERS_PAGE\n" ));
889       ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
890       break;
891     }
892     case AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE:
893     {
894       SA_DBG1(("saGetPhyProfile: AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE\n" ));
895       ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
896       break;
897     }
898 
899     case AGSA_SAS_PHY_GENERAL_STATUS_PAGE:
900     {
901       SA_DBG1(("saGetPhyProfile: AGSA_SAS_PHY_GENERAL_STATUS_PAGE\n" ));
902       ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
903       break;
904     }
905     case AGSA_PHY_SNW3_PAGE:
906     {
907       SA_DBG1(("saGetPhyProfile: AGSA_PHY_SNW3_PAGE\n" ));
908       ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
909       break;
910     }
911     case AGSA_PHY_RATE_CONTROL_PAGE:
912     {
913       SA_DBG1(("saGetPhyProfile: AGSA_PHY_RATE_CONTROL_PAGE\n" ));
914       ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
915       break;
916     }
917     case AGSA_SAS_PHY_OPEN_REJECT_RETRY_BACKOFF_THRESHOLD_PAGE:
918     {
919       SA_DBG1(("saGetPhyProfile: AGSA_SAS_PHY_OPEN_REJECT_RETRY_BACKOFF_THRESHOLD_PAGE\n" ));
920       ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
921       break;
922     }
923 
924     default:
925       SA_DBG1(("saGetPhyProfile: Unknown operation 0x%X\n",ppc ));
926       SA_ASSERT(agFALSE, "saGetPhyProfile Unknown operation " );
927       break;
928 
929   }
930   return ret;
931 
932 }
933 
934 
935 GLOBAL bit32 saSetPhyProfile (
936                       agsaRoot_t    *agRoot,
937                       agsaContext_t *agContext,
938                       bit32         queueNum,
939                       bit32         ppc,
940                       bit32         length,
941                       void          *buffer,
942                       bit32         phyID
943                       )
944 {
945   bit32 ret = AGSA_RC_SUCCESS;
946 
947   SA_DBG1(("saSetPhyProfile: ppc 0x%x length 0x%x phyID %d\n", ppc,length,phyID));
948 
949   switch(ppc)
950   {
951     case AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE:
952     {
953       SA_DBG1(("saSetPhyProfile: AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE\n" ));
954       ret = mpiSetPhyProfileCmd( agRoot,agContext,ppc ,phyID,length,buffer);
955       break;
956     }
957     case AGSA_PHY_SNW3_PAGE:
958     {
959       SA_DBG1(("saSetPhyProfile: AGSA_PHY_SNW3_PAGE\n" ));
960       ret = mpiSetPhyProfileCmd( agRoot,agContext,ppc ,phyID,length,buffer);
961       break;
962     }
963     case AGSA_PHY_RATE_CONTROL_PAGE:
964     {
965       SA_DBG1(("saSetPhyProfile: AGSA_PHY_RATE_CONTROL_PAGE\n" ));
966       ret = mpiSetPhyProfileCmd( agRoot,agContext,ppc ,phyID,length,buffer);
967       break;
968     }
969     case AGSA_SAS_PHY_MISC_PAGE:
970     {
971       SA_DBG1(("saSetPhyProfile: AGSA_SAS_PHY_MISC_PAGE\n"));
972       ret = mpiSetPhyProfileCmd( agRoot,agContext,ppc ,phyID,length,buffer);
973       break;
974     }
975 
976     default:
977       SA_DBG1(("saSetPhyProfile: Unknown operation 0x%X\n",ppc ));
978       SA_ASSERT(agFALSE, "saSetPhyProfile Unknown operation " );
979       ret = AGSA_RC_FAILURE;
980       break;
981   }
982   return ret;
983 }
984 
985 
986 /******************************************************************************/
987 /*! \brief Initiate a HW Event Ack command
988  *
989  *  This function is called to initiate a HW Event Ack command to the SPC.
990  *  The completion of this function is reported in ossaHwEventAckCB().
991  *
992  *  \param agRoot      handles for this instance of SAS/SATA hardware
993  *  \param agContext   the context of this API
994  *  \param queueNum    queue number
995  *  \param eventSource point to the event source structure
996  *  \param param0
997  *  \param param1
998  *
999  *  \return
1000  *          - none
1001  */
1002 /*******************************************************************************/
1003 GLOBAL bit32 saHwEventAck(
1004                       agsaRoot_t        *agRoot,
1005                       agsaContext_t     *agContext,
1006                       bit32             queueNum,
1007                       agsaEventSource_t *eventSource,
1008                       bit32             param0,
1009                       bit32             param1
1010                       )
1011 {
1012   agsaLLRoot_t           *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
1013   agsaIORequestDesc_t    *pRequest;
1014   agsaPortContext_t      *agPortContext;
1015   agsaPort_t             *pPort = agNULL;
1016   agsaSASHwEventAckCmd_t payload;
1017   bit32                  phyportid;
1018   bit32                  ret = AGSA_RC_SUCCESS;
1019   bit32                  using_reserved = agFALSE;
1020 
1021   smTraceFuncEnter(hpDBG_VERY_LOUD,"7e");
1022 
1023   /* sanity check */
1024   SA_ASSERT((agNULL != saRoot), "");
1025   if(saRoot == agNULL)
1026   {
1027     SA_DBG1(("saHwEventAck: saRoot == agNULL\n"));
1028     return(AGSA_RC_FAILURE);
1029   }
1030 
1031   SA_DBG2(("saHwEventAck: agContext %p eventSource %p\n", agContext, eventSource));
1032   SA_DBG1(("saHwEventAck: event 0x%x param0 0x%x param1 0x%x\n", eventSource->event, param0, param1));
1033 
1034   agPortContext = eventSource->agPortContext;
1035 
1036   /* Get request from free IORequests */
1037   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1038   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
1039 
1040   /* If no LL Control request entry available */
1041   if ( agNULL == pRequest )
1042   {
1043     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests)); /**/
1044     if(agNULL != pRequest)
1045     {
1046       using_reserved = agTRUE;
1047       SA_DBG1(("saHwEventAck, using saRoot->freeReservedRequests\n"));
1048     }
1049     else
1050     {
1051       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1052       /* If no LL Control request entry available */
1053       SA_DBG1(("saHwEventAck, No request from free list Not using saRoot->freeReservedRequests\n"));
1054       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "7e");
1055       return AGSA_RC_BUSY;
1056     }
1057   }
1058   if( using_reserved )
1059   {
1060     saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1061   }
1062   else
1063   {
1064     /* Remove the request from free list */
1065     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1066   }
1067   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1068   SA_ASSERT((!pRequest->valid), "The pRequest is in use");
1069 
1070   SA_DBG2(("saHwEventAck: queueNum 0x%x HTag 0x%x\n",queueNum ,pRequest->HTag));
1071 
1072   saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1073   saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1074   saRoot->IOMap[pRequest->HTag].agContext = agContext;
1075   pRequest->valid = agTRUE;
1076 
1077   /* build IOMB command and send to SPC */
1078   /* set payload to zeros */
1079   si_memset(&payload, 0, sizeof(agsaSASHwEventAckCmd_t));
1080 
1081   /* find port id */
1082   if (agPortContext)
1083   {
1084     pPort = (agsaPort_t *) (agPortContext->sdkData);
1085     if (pPort)
1086     {
1087       if(eventSource->event == OSSA_HW_EVENT_PHY_DOWN)
1088       {
1089         pPort->tobedeleted = agTRUE;
1090       }
1091       SA_DBG3(("saHwEventAck,pPort->portId %X\n",pPort->portId));
1092 
1093       if(smIS_SPC(agRoot))
1094       {
1095         /* fillup PORT_ID field */
1096         phyportid = pPort->portId & 0xF;
1097       }
1098       else
1099       {
1100         /* fillup PORT_ID field */
1101         phyportid = pPort->portId & 0xFF;
1102 
1103       }
1104     }
1105     else
1106     {
1107       /*  pPort is NULL - set PORT_ID to not intialized  */
1108       if(smIS_SPC(agRoot))
1109       {
1110         phyportid = 0xF;
1111       }
1112       else
1113       {
1114         phyportid = 0xFF;
1115       }
1116     }
1117   }
1118   else
1119   {
1120     /* agPortContext is NULL - set PORT_ID to not intialized  */
1121     if(smIS_SPC(agRoot))
1122     {
1123       phyportid = 0xF;
1124     }
1125     else
1126     {
1127       phyportid = 0xFF;
1128     }
1129   }
1130 
1131   pRequest->pPort = pPort;
1132 
1133   SA_DBG3(("saHwEventAck,eventSource->param 0x%X\n",eventSource->param));
1134   SA_DBG3(("saHwEventAck,eventSource->event 0x%X\n",eventSource->event));
1135 
1136   if(smIS_SPC(agRoot))
1137   {
1138     /* fillup up PHY_ID */
1139     phyportid |= ((eventSource->param & 0x0000000F) << 4);
1140     /* fillup SEA field */
1141     phyportid |= (eventSource->event & 0x0000FFFF) << 8;
1142     SA_DBG3(("saHwEventAck: portId 0x%x phyId 0x%x SEA 0x%x\n", phyportid & 0xF,
1143       eventSource->param & 0x0000000F, eventSource->event & 0x0000FFFF));
1144   }
1145   else
1146   {
1147     /* fillup up PHY_ID */
1148     phyportid |= ((eventSource->param & 0x000000FF) << SHIFT24);
1149     /* fillup SEA field */
1150     phyportid |= (eventSource->event & 0x00FFFFFF) << SHIFT8;
1151     SA_DBG3(("saHwEventAck: portId 0x%x phyId 0x%x SEA 0x%x\n", phyportid & 0xFF,
1152       eventSource->param & 0x0000000F, eventSource->event & 0x0000FFFF));
1153   }
1154 
1155   pRequest->HwAckType =  (bit16)phyportid;
1156 
1157   SA_DBG1(("saHwEventAck,phyportid 0x%X HwAckType 0x%X\n",phyportid,pRequest->HwAckType));
1158   /* set tag */
1159   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASHwEventAckCmd_t, tag), pRequest->HTag);
1160   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASHwEventAckCmd_t, sEaPhyIdPortId), phyportid);
1161   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASHwEventAckCmd_t, Param0), param0);
1162   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASHwEventAckCmd_t, Param1), param1);
1163 
1164   /* build IOMB command and send to SPC */
1165 
1166   if(smIS_SPC(agRoot))
1167   {
1168     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SPC_SAS_HW_EVENT_ACK, IOMB_SIZE64, queueNum);
1169   }
1170   else
1171   {
1172     ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SAS_HW_EVENT_ACK, IOMB_SIZE64, queueNum);
1173   }
1174 
1175   if (AGSA_RC_SUCCESS != ret)
1176   {
1177     /* remove the request from IOMap */
1178     saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1179     saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1180     saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1181     pRequest->valid = agFALSE;
1182 
1183     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1184     /* return the request to free pool */
1185     if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1186     {
1187       SA_DBG1(("saHwEventAck: saving pRequest (%p) for later use\n", pRequest));
1188       saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1189     }
1190     else
1191     {
1192       /* return the request to free pool */
1193       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1194     }
1195     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1196     SA_DBG1(("saHwEventAck, sending IOMB failed\n" ));
1197   }
1198   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "7e");
1199 
1200   return ret;
1201 }
1202 
1203 
1204 GLOBAL bit32 saVhistCapture(
1205                           agsaRoot_t    *agRoot,
1206                           agsaContext_t *agContext,
1207                           bit32         queueNum,
1208                           bit32         Channel,
1209                           bit32         NumBitLo,
1210                           bit32         NumBitHi,
1211                           bit32         PcieAddrLo,
1212                           bit32         PcieAddrHi,
1213                           bit32         ByteCount )
1214 {
1215 
1216   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
1217   agsaIORequestDesc_t *pRequest;
1218   bit32               ret = AGSA_RC_SUCCESS;
1219   bit32               using_reserved = agFALSE;
1220 
1221   smTraceFuncEnter(hpDBG_VERY_LOUD,"3N");
1222 
1223   /* sanity check */
1224   SA_ASSERT((agNULL != agRoot), "");
1225 
1226   SA_DBG1(("saVhistCapture:Channel 0x%08X 0x%08X%08X 0x%08X%08X  count 0x%X\n",Channel, NumBitHi, NumBitLo ,PcieAddrHi,PcieAddrLo,ByteCount));
1227 
1228   {
1229     /* Get request from free IORequests */
1230     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1231     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /* */
1232     /* If no LL Control request entry available */
1233     if ( agNULL == pRequest )
1234     {
1235       pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests));
1236       /* If no LL Control request entry available */
1237       if(agNULL != pRequest)
1238       {
1239         using_reserved = agTRUE;
1240         SA_DBG1((", using saRoot->freeReservedRequests\n"));
1241       }
1242       else
1243       {
1244         ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1245         SA_DBG1(("saVhistCapture: No request from free list Not using saRoot->freeReservedRequests\n"));
1246         smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3N");
1247         return AGSA_RC_BUSY;
1248       }
1249     }
1250     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
1251     pRequest->valid = agTRUE;
1252     /* If LL Control request entry avaliable */
1253     if( using_reserved )
1254     {
1255       saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1256     }
1257     else
1258     {
1259       /* Remove the request from free list */
1260       saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1261     }
1262     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1263 
1264     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1265     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1266     saRoot->IOMap[pRequest->HTag].agContext = agContext;
1267     pRequest->valid = agTRUE;
1268 
1269     /* Build the VhisCapture IOMB command and send to SPCv */
1270 
1271     ret = mpiVHistCapCmd(agRoot,agContext, queueNum, Channel, NumBitLo, NumBitHi ,PcieAddrLo, PcieAddrHi, ByteCount);
1272     if (AGSA_RC_SUCCESS != ret)
1273     {
1274       /* remove the request from IOMap */
1275       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
1276       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
1277       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
1278       pRequest->valid = agFALSE;
1279 
1280       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1281       /* return the request to free pool */
1282       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1283       {
1284         SA_DBG1(("saPhyStart: saving pRequest (%p) for later use\n", pRequest));
1285         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1286       }
1287       else
1288       {
1289         /* return the request to free pool */
1290         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1291       }
1292       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1293       SA_DBG1(("saVhistCapture: sending IOMB failed\n" ));
1294     }
1295   }
1296 
1297   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3N");
1298 
1299   return ret;
1300 }
1301 
1302