saphy.c revision 285809
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
42extern 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/*******************************************************************************/
60GLOBAL 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/*******************************************************************************/
183GLOBAL 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/*******************************************************************************/
314GLOBAL 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/*******************************************************************************/
420GLOBAL 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
823GLOBAL 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
936GLOBAL 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/*******************************************************************************/
1004GLOBAL 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
1205GLOBAL 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