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