itddisc.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
24 *
25 * This file contains initiator discover related functions
26 *
27 */
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD$");
30#include <dev/pms/config.h>
31
32#include <dev/pms/freebsd/driver/common/osenv.h>
33#include <dev/pms/freebsd/driver/common/ostypes.h>
34#include <dev/pms/freebsd/driver/common/osdebug.h>
35
36#include <dev/pms/RefTisa/sallsdk/api/sa.h>
37#include <dev/pms/RefTisa/sallsdk/api/saapi.h>
38#include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
39
40#include <dev/pms/RefTisa/tisa/api/titypes.h>
41#include <dev/pms/RefTisa/tisa/api/ostiapi.h>
42#include <dev/pms/RefTisa/tisa/api/tiapi.h>
43#include <dev/pms/RefTisa/tisa/api/tiglobal.h>
44
45#ifdef FDS_SM
46#include <dev/pms/RefTisa/sat/api/sm.h>
47#include <dev/pms/RefTisa/sat/api/smapi.h>
48#include <dev/pms/RefTisa/sat/api/tdsmapi.h>
49#endif
50
51#ifdef FDS_DM
52#include <dev/pms/RefTisa/discovery/api/dm.h>
53#include <dev/pms/RefTisa/discovery/api/dmapi.h>
54#include <dev/pms/RefTisa/discovery/api/tddmapi.h>
55#endif
56
57#include <dev/pms/RefTisa/tisa/sassata/sas/common/tdtypes.h>
58#include <dev/pms/freebsd/driver/common/osstring.h>
59#include <dev/pms/RefTisa/tisa/sassata/common/tdutil.h>
60
61#ifdef INITIATOR_DRIVER
62#include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdtypes.h>
63#include <dev/pms/RefTisa/tisa/sassata/sas/ini/itddefs.h>
64#include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdglobl.h>
65#endif
66
67#ifdef TARGET_DRIVER
68#include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdglobl.h>
69#include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdxchg.h>
70#include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdtypes.h>
71#endif
72
73#include <dev/pms/RefTisa/tisa/sassata/common/tdsatypes.h>
74#include <dev/pms/RefTisa/tisa/sassata/common/tdproto.h>
75
76/*****************************************************************************
77*! \brief  tiINIDiscoverTargets
78*
79*  Purpose:  This function is called to send a transport dependent discovery
80*            request. An implicit login will be started following the
81*            completion of discovery.
82*
83*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
84*                   instance.
85*  \param   portalContext: Pointer to the portal context instance.
86*  \param   option: This is a bit field option on how the session is to be
87*                   created
88*  \return:
89*           tiSuccess    Discovery initiated.
90*           tiBusy       Discovery could not be initiated at this time.
91*
92*   \note:
93*
94*****************************************************************************/
95osGLOBAL bit32
96tiINIDiscoverTargets(
97                     tiRoot_t            *tiRoot,
98                     tiPortalContext_t   *portalContext,
99                     bit32               option
100                     )
101{
102  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
103  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
104  tdList_t          *PortContextList;
105  tdsaPortContext_t *onePortContext = agNULL;
106  bit32             found = agFALSE;
107
108#ifdef FDS_DM
109  dmRoot_t          *dmRoot = &(tdsaAllShared->dmRoot);
110  dmPortContext_t   *dmPortContext = agNULL;
111#endif
112  /*
113   this function is called after LINK_UP by ossaHWCB()
114   Therefore, tdsaportcontext is ready at this point
115  */
116
117  TI_DBG3(("tiINIDiscoverTargets: start\n"));
118
119  /* find a right tdsaPortContext using tiPortalContext
120     then, check the status of tdsaPortContext
121     then, if status is right, start the discovery
122  */
123
124  TI_DBG6(("tiINIDiscoverTargets: portalContext %p\n", portalContext));
125  tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
126  if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
127  {
128    tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
129    TI_DBG1(("tiINIDiscoverTargets: No tdsaPortContext\n"));
130    return tiError;
131  }
132  else
133  {
134    tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
135  }
136
137  /* find a right portcontext */
138  PortContextList = tdsaAllShared->MainPortContextList.flink;
139  if (PortContextList == agNULL)
140  {
141    TI_DBG1(("tiINIDiscoverTargets: PortContextList is NULL\n"));
142    return tiError;
143  }
144  while (PortContextList != &(tdsaAllShared->MainPortContextList))
145  {
146    onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
147    if (onePortContext == agNULL)
148    {
149      TI_DBG1(("tiINIDiscoverTargets: onePortContext is NULL, PortContextList = %p\n", PortContextList));
150      return tiError;
151    }
152    if (onePortContext->tiPortalContext == portalContext && onePortContext->valid == agTRUE)
153    {
154      TI_DBG6(("tiINIDiscoverTargets: found; oneportContext ID %d\n", onePortContext->id));
155      found = agTRUE;
156      break;
157    }
158    PortContextList = PortContextList->flink;
159  }
160
161  if (found == agFALSE)
162  {
163    TI_DBG1(("tiINIDiscoverTargets: No corresponding tdsaPortContext\n"));
164    return tiError;
165  }
166
167  TI_DBG2(("tiINIDiscoverTargets: pid %d\n", onePortContext->id));
168  if (onePortContext->DiscoveryState == ITD_DSTATE_NOT_STARTED)
169  {
170    TI_DBG6(("tiINIDiscoverTargets: calling Discovery\n"));
171    /* start SAS discovery */
172#ifdef FDS_DM
173    if (onePortContext->UseDM == agTRUE)
174    {
175      TI_DBG1(("tiINIDiscoverTargets: calling dmDiscover, pid %d\n", onePortContext->id));
176      onePortContext->DiscoveryState = ITD_DSTATE_STARTED;
177      dmPortContext = &(onePortContext->dmPortContext);
178      dmDiscover(dmRoot, dmPortContext, DM_DISCOVERY_OPTION_FULL_START);
179    }
180    else
181    {
182      /* complete discovery */
183      onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
184      ostiInitiatorEvent(
185                         tiRoot,
186                         portalContext,
187                         agNULL,
188                         tiIntrEventTypeDiscovery,
189                         tiDiscOK,
190                         agNULL
191                         );
192
193      return tiSuccess;
194    }
195
196#else
197
198#ifdef TD_DISCOVER
199    tdsaDiscover(
200                 tiRoot,
201                 onePortContext,
202                 AG_SA_DISCOVERY_TYPE_SAS,
203                 TDSA_DISCOVERY_OPTION_FULL_START
204                 );
205#else
206    saDiscover(onePortContext->agRoot, onePortContext->agPortContext, AG_SA_DISCOVERY_TYPE_SAS, onePortContext->discoveryOptions);
207
208
209
210#endif
211#endif /* FDS_DM */
212  }
213  else
214  {
215    TI_DBG1(("tiINIDiscoverTargets: Discovery has started or incorrect initialization; state %d pid 0x%x\n",
216                      onePortContext->DiscoveryState,
217                      onePortContext->id));
218    return tiError;
219  }
220
221  return tiSuccess;
222}
223
224/*****************************************************************************
225*! \brief  tiINIGetDeviceHandles
226*
227*  Purpose: This routine is called to to return the device handles for each
228*           device currently available.
229*
230*  \param  tiRoot:   Pointer to driver Instance.
231*  \param  tiPortalContext: Pointer to the portal context instance.
232*  \param  agDev[]:  Array to receive pointers to the device handles.
233*  \param  maxDevs:  Number of device handles which will fit in array pointed
234*                    by agDev.
235*  \return:
236*    Number of device handle slots present (however, only maxDevs
237*    are copied into tiDev[]) which may be greater than the number of
238*    handles actually present. In short, returns the number of devices that
239*    were found.
240*
241*  \note:
242*
243*****************************************************************************/
244osGLOBAL bit32
245tiINIGetDeviceHandles(
246                      tiRoot_t          * tiRoot,
247                      tiPortalContext_t * tiPortalContext,
248                      tiDeviceHandle_t  * tiDev[],
249                      bit32               maxDevs
250                      )
251{
252  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
253  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
254  tdList_t          *PortContextList;
255  tdsaPortContext_t *onePortContext = agNULL;
256  tdsaDeviceData_t  *oneDeviceData = agNULL;
257  tdList_t          *DeviceListList;
258  bit32             i;
259  bit32             FoundDevices = 0;
260  bit32             DeviceIndex = 0;
261  bit32             found = agFALSE;
262#ifdef  TD_DEBUG_ENABLE
263  satDeviceData_t   *pSatDevData;
264#endif
265#ifdef FDS_DM
266  dmRoot_t          *dmRoot = &(tdsaAllShared->dmRoot);
267#endif
268
269  TI_DBG2(("tiINIGetDeviceHandles: start\n"));
270  TI_DBG2(("tiINIGetDeviceHandles: tiPortalContext %p\n", tiPortalContext));
271
272
273  if (maxDevs == 0)
274  {
275    TI_DBG1(("tiINIGetDeviceHandles: maxDevs is 0\n"));
276    TI_DBG1(("tiINIGetDeviceHandles: first, returning 0\n"));
277    /* nullify all device handles */
278    for (i = 0 ; i < maxDevs ; i++)
279    {
280      tiDev[i] = agNULL;
281    }
282    return 0;
283  }
284
285  tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
286  if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
287  {
288    tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
289    TI_DBG1(("tiINIGetDeviceHandles: No available tdsaPortContext\n"));
290    TI_DBG1(("tiINIGetDeviceHandles: second, returning 0\n"));
291    /* nullify all device handles */
292    for (i = 0 ; i < maxDevs ; i++)
293    {
294      tiDev[i] = agNULL;
295    }
296    return 0;
297  }
298  else
299  {
300    tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
301  }
302  /* find a corresponding portcontext */
303  PortContextList = tdsaAllShared->MainPortContextList.flink;
304  while (PortContextList != &(tdsaAllShared->MainPortContextList))
305  {
306    onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
307    if(onePortContext == agNULL) continue;
308
309    TI_DBG3(("tiINIGetDeviceHandles: oneportContext pid %d\n", onePortContext->id));
310    if (onePortContext->tiPortalContext == tiPortalContext && onePortContext->valid == agTRUE)
311    {
312      TI_DBG3(("tiINIGetDeviceHandles: found; oneportContext pid %d\n", onePortContext->id));
313      found = agTRUE;
314      break;
315    }
316    PortContextList = PortContextList->flink;
317  }
318
319  if (found == agFALSE)
320  {
321    TI_DBG1(("tiINIGetDeviceHandles: First, No corresponding tdsaPortContext\n"));
322    TI_DBG1(("tiINIGetDeviceHandles: third, returning 0\n"));
323    /* nullify all device handles */
324    for (i = 0 ; i < maxDevs ; i++)
325    {
326      tiDev[i] = agNULL;
327    }
328    return 0;
329  }
330
331  if (onePortContext == agNULL)
332  {
333    TI_DBG1(("tiINIGetDeviceHandles: Second, No corressponding tdsaPortContext\n"));
334    TI_DBG1(("tiINIGetDeviceHandles: fourth, returning 0\n"));
335    /* nullify all device handles */
336    for (i = 0 ; i < maxDevs ; i++)
337    {
338      tiDev[i] = agNULL;
339    }
340    return 0;
341  }
342
343  if (onePortContext->valid == agFALSE)
344  {
345    TI_DBG1(("tiINIGetDeviceHandles: Third, tdsaPortContext is invalid, pid %d\n", onePortContext->id));
346    TI_DBG1(("tiINIGetDeviceHandles: fifth, returning 0\n"));
347    /* nullify all device handles */
348    for (i = 0 ; i < maxDevs ; i++)
349    {
350      tiDev[i] = agNULL;
351    }
352    return 0;
353  }
354
355  if (onePortContext->DiscoveryState == ITD_DSTATE_COMPLETED &&  onePortContext->DMDiscoveryState == dmDiscFailed)
356  {
357    TI_DBG1(("tiINIGetDeviceHandles: forth, discovery failed, pid %d\n", onePortContext->id));
358    TI_DBG1(("tiINIGetDeviceHandles: sixth, returning 0\n"));
359    /* nullify all device handles */
360    for (i = 0 ; i < maxDevs ; i++)
361    {
362      tiDev[i] = agNULL;
363    }
364    return 0;
365  }
366
367  if (onePortContext->DiscoveryState != ITD_DSTATE_COMPLETED)
368  {
369    TI_DBG1(("tiINIGetDeviceHandles: discovery not completed\n"));
370    TI_DBG1(("tiINIGetDeviceHandles: sixth, returning DISCOVERY_IN_PROGRESS, pid %d\n", onePortContext->id));
371    onePortContext->discovery.forcedOK = agTRUE;
372    return DISCOVERY_IN_PROGRESS;
373  }
374
375  TI_DBG2(("tiINIGetDeviceHandles: pid %d\n", onePortContext->id));
376
377#ifdef FDS_DM
378  tdsaUpdateMCN(dmRoot, onePortContext);
379#endif
380
381  /* nullify all device handles */
382  for (i = 0 ; i < maxDevs ; i++)
383  {
384    tiDev[i] = agNULL;
385  }
386
387  /*
388     From the device list, returns only valid devices
389  */
390  DeviceListList = tdsaAllShared->MainDeviceList.flink;
391
392  TD_ASSERT(DeviceListList, "DeviceListList NULL");
393  if (DeviceListList == agNULL  )
394  {
395    TI_DBG1(("tiINIGetDeviceHandles: DeviceListList == agNULL\n"));
396    TI_DBG1(("tiINIGetDeviceHandles: seventh, returning not found, pid %d\n", onePortContext->id));
397    return 0;
398  }
399
400  while ((DeviceIndex < maxDevs) &&
401          DeviceListList != &(tdsaAllShared->MainDeviceList))
402  {
403    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
404#ifdef  TD_DEBUG_ENABLE
405    pSatDevData = (satDeviceData_t *)&(oneDeviceData->satDevData);
406    if (pSatDevData != agNULL)
407    {
408      TI_DBG3(("tiINIGetDeviceHandles: device %p satPendingIO %d satNCQMaxIO %d\n",pSatDevData, pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO ));
409      TI_DBG3(("tiINIGetDeviceHandles: device %p satPendingNCQIO %d satPendingNONNCQIO %d\n",pSatDevData, pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO));
410    }
411#endif
412    TI_DBG3(("tiINIGetDeviceHandles: pid %d did %d\n", onePortContext->id, oneDeviceData->id));
413    TI_DBG3(("tiINIGetDeviceHandles: device AddrHi 0x%08x AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
414
415    TI_DBG6(("tiINIGetDeviceHandles: handle %p\n",  &(oneDeviceData->tiDeviceHandle)));
416    if (oneDeviceData->tdPortContext != onePortContext)
417    {
418      TI_DBG3(("tiINIGetDeviceHandles: different port\n"));
419      DeviceListList = DeviceListList->flink;
420    }
421    else
422    {
423#ifdef SATA_ENABLE
424      if ((oneDeviceData->valid == agTRUE) &&
425          (oneDeviceData->registered == agTRUE) &&
426          (oneDeviceData->tdPortContext == onePortContext) &&
427          ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData)
428            || DEVICE_IS_SATA_DEVICE(oneDeviceData) )
429          )
430#else
431      if ((oneDeviceData->valid == agTRUE) &&
432          (oneDeviceData->registered == agTRUE) &&
433          (oneDeviceData->tdPortContext == onePortContext) &&
434          ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData) )
435          )
436#endif
437      {
438        if (DEVICE_IS_SSP_TARGET(oneDeviceData))
439        {
440          TI_DBG2(("tiINIGetDeviceHandles: SSP DeviceIndex %d tiDeviceHandle %p\n",  DeviceIndex, &(oneDeviceData->tiDeviceHandle)));
441          tiDev[DeviceIndex] = &(oneDeviceData->tiDeviceHandle);
442          FoundDevices++;
443        }
444        else if ( (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
445                  &&
446                  oneDeviceData->satDevData.IDDeviceValid == agTRUE )
447        {
448          TI_DBG2(("tiINIGetDeviceHandles: SATA DeviceIndex %d tiDeviceHandle %p\n",  DeviceIndex, &(oneDeviceData->tiDeviceHandle)));
449          tiDev[DeviceIndex] = &(oneDeviceData->tiDeviceHandle);
450          FoundDevices++;
451        }
452        else
453        {
454          TI_DBG3(("tiINIGetDeviceHandles: skip case !!!\n"));
455          TI_DBG3(("tiINIGetDeviceHandles: valid %d SSP target %d STP target %d SATA device %d\n", oneDeviceData->valid, DEVICE_IS_SSP_TARGET(oneDeviceData), DEVICE_IS_STP_TARGET(oneDeviceData), DEVICE_IS_SATA_DEVICE(oneDeviceData)));
456          TI_DBG3(("tiINIGetDeviceHandles: oneDeviceData->satDevData.IDDeviceValid %d\n", oneDeviceData->satDevData.IDDeviceValid));
457          TI_DBG3(("tiINIGetDeviceHandles: registered %d right port %d \n", oneDeviceData->registered, (oneDeviceData->tdPortContext == onePortContext)));
458          TI_DBG3(("tiINIGetDeviceHandles: oneDeviceData->tdPortContext %p onePortContext %p\n", oneDeviceData->tdPortContext, onePortContext));
459        }
460        TI_DBG3(("tiINIGetDeviceHandles: valid FoundDevices %d\n", FoundDevices));
461        TI_DBG3(("tiINIGetDeviceHandles: agDevHandle %p\n", oneDeviceData->agDevHandle));
462      }
463      else
464      {
465        TI_DBG3(("tiINIGetDeviceHandles: valid %d SSP target %d STP target %d SATA device %d\n", oneDeviceData->valid, DEVICE_IS_SSP_TARGET(oneDeviceData), DEVICE_IS_STP_TARGET(oneDeviceData), DEVICE_IS_SATA_DEVICE(oneDeviceData)));
466        TI_DBG3(("tiINIGetDeviceHandles: registered %d right port %d \n", oneDeviceData->registered, (oneDeviceData->tdPortContext == onePortContext)));
467        TI_DBG3(("tiINIGetDeviceHandles: oneDeviceData->tdPortContext %p onePortContext %p\n", oneDeviceData->tdPortContext, onePortContext));
468      }
469      DeviceIndex++;
470      DeviceListList = DeviceListList->flink;
471    } /* else */
472  }
473
474  if (DeviceIndex > maxDevs)
475  {
476    TI_DBG1(("tiINIGetDeviceHandles: DeviceIndex(%d) >= maxDevs(%d)\n", DeviceIndex, maxDevs));
477    FoundDevices = maxDevs;
478  }
479
480  TI_DBG1(("tiINIGetDeviceHandles: returning %d found devices, pid %d\n", FoundDevices, onePortContext->id));
481
482  return FoundDevices;
483}
484
485/*****************************************************************************
486*! \brief  tiINIGetDeviceHandlesForWinIOCTL
487*
488*  Purpose: This routine is called to to return the device handles for each
489*           device currently available, this routine is only for Win IOCTL to display SAS topology.
490*
491*  \param  tiRoot:   Pointer to driver Instance.
492*  \param  tiPortalContext: Pointer to the portal context instance.
493*  \param  agDev[]:  Array to receive pointers to the device handles.
494*  \param  maxDevs:  Number of device handles which will fit in array pointed
495*                    by agDev.
496*  \return:
497*    Number of device handle slots present (however, only maxDevs
498*    are copied into tiDev[]) which may be greater than the number of
499*    handles actually present. In short, returns the number of devices that
500*    were found.
501*
502*  \note:
503*
504*****************************************************************************/
505osGLOBAL bit32
506tiINIGetDeviceHandlesForWinIOCTL(
507                      tiRoot_t          * tiRoot,
508                      tiPortalContext_t * tiPortalContext,
509                      tiDeviceHandle_t  * tiDev[],
510                      bit32               maxDevs
511                      )
512{
513  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
514  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
515  tdList_t          *PortContextList;
516  tdsaPortContext_t *onePortContext = agNULL;
517  tdsaDeviceData_t  *oneDeviceData = agNULL;
518  tdList_t          *DeviceListList;
519  bit32             i;
520  bit32             FoundDevices = 0;
521  bit32             DeviceIndex = 0;
522  bit32             found = agFALSE;
523#ifdef  TD_DEBUG_ENABLE
524  satDeviceData_t   *pSatDevData;
525#endif
526#ifdef FDS_DM
527  dmRoot_t          *dmRoot = &(tdsaAllShared->dmRoot);
528#endif
529
530  TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: start\n"));
531  TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: tiPortalContext %p\n", tiPortalContext));
532
533
534  if (maxDevs == 0)
535  {
536    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: maxDevs is 0\n"));
537    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: first, returning 0\n"));
538    /* nullify all device handles */
539    for (i = 0 ; i < maxDevs ; i++)
540    {
541      tiDev[i] = agNULL;
542    }
543    return 0;
544  }
545
546  tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
547  if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
548  {
549    tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
550    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: No available tdsaPortContext\n"));
551    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: second, returning 0\n"));
552    /* nullify all device handles */
553    for (i = 0 ; i < maxDevs ; i++)
554    {
555      tiDev[i] = agNULL;
556    }
557    return 0;
558  }
559  else
560  {
561    tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
562  }
563  /* find a corresponding portcontext */
564  PortContextList = tdsaAllShared->MainPortContextList.flink;
565  while (PortContextList != &(tdsaAllShared->MainPortContextList))
566  {
567    onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
568    if(onePortContext == agNULL) continue;
569
570    TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: oneportContext pid %d\n", onePortContext->id));
571    if (onePortContext->tiPortalContext == tiPortalContext && onePortContext->valid == agTRUE)
572    {
573      TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: found; oneportContext pid %d\n", onePortContext->id));
574      found = agTRUE;
575      break;
576    }
577    PortContextList = PortContextList->flink;
578  }
579
580  if (found == agFALSE)
581  {
582    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: First, No corresponding tdsaPortContext\n"));
583    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: third, returning 0\n"));
584    /* nullify all device handles */
585    for (i = 0 ; i < maxDevs ; i++)
586    {
587      tiDev[i] = agNULL;
588    }
589    return 0;
590  }
591
592  if (onePortContext == agNULL)
593  {
594    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: Second, No corressponding tdsaPortContext\n"));
595    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: fourth, returning 0\n"));
596    /* nullify all device handles */
597    for (i = 0 ; i < maxDevs ; i++)
598    {
599      tiDev[i] = agNULL;
600    }
601    return 0;
602  }
603
604  if (onePortContext->valid == agFALSE)
605  {
606    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: Third, tdsaPortContext is invalid, pid %d\n", onePortContext->id));
607    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: fifth, returning 0\n"));
608    /* nullify all device handles */
609    for (i = 0 ; i < maxDevs ; i++)
610    {
611      tiDev[i] = agNULL;
612    }
613    return 0;
614  }
615
616  if (onePortContext->DiscoveryState == ITD_DSTATE_COMPLETED &&  onePortContext->DMDiscoveryState == dmDiscFailed)
617  {
618    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: forth, discovery failed, pid %d\n", onePortContext->id));
619    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: sixth, returning 0\n"));
620    /* nullify all device handles */
621    for (i = 0 ; i < maxDevs ; i++)
622    {
623      tiDev[i] = agNULL;
624    }
625    return 0;
626  }
627
628  if (onePortContext->DiscoveryState != ITD_DSTATE_COMPLETED)
629  {
630    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: discovery not completed\n"));
631    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: sixth, returning DISCOVERY_IN_PROGRESS, pid %d\n", onePortContext->id));
632    onePortContext->discovery.forcedOK = agTRUE;
633    return DISCOVERY_IN_PROGRESS;
634  }
635
636  TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: pid %d\n", onePortContext->id));
637
638#ifdef FDS_DM
639  tdsaUpdateMCN(dmRoot, onePortContext);
640#endif
641
642  /* nullify all device handles */
643  for (i = 0 ; i < maxDevs ; i++)
644  {
645    tiDev[i] = agNULL;
646  }
647
648  /*
649     From the device list, returns only valid devices
650  */
651  DeviceListList = tdsaAllShared->MainDeviceList.flink;
652
653  TD_ASSERT(DeviceListList, "DeviceListList NULL");
654  if (DeviceListList == agNULL  )
655  {
656    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: DeviceListList == agNULL\n"));
657    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: seventh, returning not found, pid %d\n", onePortContext->id));
658    return 0;
659  }
660
661  while ((DeviceIndex < maxDevs) &&
662          DeviceListList != &(tdsaAllShared->MainDeviceList))
663  {
664    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
665    if(oneDeviceData == agNULL)
666    {
667	TI_DBG3(("tiINIGetDeviceHandles: OneDeviceData is NULL\n"));
668	return 0;
669    }
670#ifdef  TD_DEBUG_ENABLE
671    pSatDevData = (satDeviceData_t *)&(oneDeviceData->satDevData);
672    if (pSatDevData != agNULL)
673    {
674      TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: device %p satPendingIO %d satNCQMaxIO %d\n",pSatDevData, pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO ));
675      TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: device %p satPendingNCQIO %d satPendingNONNCQIO %d\n",pSatDevData, pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO));
676    }
677#endif
678    TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: pid %d did %d\n", onePortContext->id, oneDeviceData->id));
679    TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: device AddrHi 0x%08x AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
680
681    TI_DBG6(("tiINIGetDeviceHandlesForWinIOCTL: handle %p\n",  &(oneDeviceData->tiDeviceHandle)));
682    if (oneDeviceData->tdPortContext != onePortContext)
683    {
684      TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: different port\n"));
685      DeviceListList = DeviceListList->flink;
686    }
687    else
688    {
689#ifdef SATA_ENABLE
690      if ((oneDeviceData->valid == agTRUE) &&
691          (oneDeviceData->registered == agTRUE) &&
692          (oneDeviceData->tdPortContext == onePortContext) &&
693          ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData)
694            || DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_SMP_TARGET(oneDeviceData))
695          )
696#else
697      if ((oneDeviceData->valid == agTRUE) &&
698          (oneDeviceData->registered == agTRUE) &&
699          (oneDeviceData->tdPortContext == onePortContext) &&
700          ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
701          )
702#endif
703      {
704        if (DEVICE_IS_SSP_TARGET(oneDeviceData))
705        {
706          TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: SSP DeviceIndex %d tiDeviceHandle %p\n",  DeviceIndex, &(oneDeviceData->tiDeviceHandle)));
707          tiDev[DeviceIndex] = &(oneDeviceData->tiDeviceHandle);
708          DeviceIndex++;
709	  FoundDevices++;
710        }
711        else if ( (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
712                  &&
713                  oneDeviceData->satDevData.IDDeviceValid == agTRUE )
714        {
715          TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: SATA DeviceIndex %d tiDeviceHandle %p\n",  DeviceIndex, &(oneDeviceData->tiDeviceHandle)));
716          tiDev[DeviceIndex] = &(oneDeviceData->tiDeviceHandle);
717          DeviceIndex++;
718	  FoundDevices++;
719        }
720        else if (DEVICE_IS_SMP_TARGET(oneDeviceData))
721        {
722          TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: SMP DeviceIndex %d tiDeviceHandle %p\n",  DeviceIndex, &(oneDeviceData->tiDeviceHandle)));
723          tiDev[DeviceIndex] = &(oneDeviceData->tiDeviceHandle);
724          DeviceIndex++;
725	  FoundDevices++;
726        }
727        else
728        {
729          TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: skip case !!!\n"));
730          TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: valid %d SSP target %d STP target %d SATA device %d\n", oneDeviceData->valid, DEVICE_IS_SSP_TARGET(oneDeviceData), DEVICE_IS_STP_TARGET(oneDeviceData), DEVICE_IS_SATA_DEVICE(oneDeviceData)));
731          TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: oneDeviceData->satDevData.IDDeviceValid %d\n", oneDeviceData->satDevData.IDDeviceValid));
732          TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: registered %d right port %d \n", oneDeviceData->registered, (oneDeviceData->tdPortContext == onePortContext)));
733          TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: oneDeviceData->tdPortContext %p onePortContext %p\n", oneDeviceData->tdPortContext, onePortContext));
734        }
735        TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: valid FoundDevices %d\n", FoundDevices));
736        TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: agDevHandle %p\n", oneDeviceData->agDevHandle));
737      }
738      else
739      {
740        TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: valid %d SSP target %d STP target %d SATA device %d\n", oneDeviceData->valid, DEVICE_IS_SSP_TARGET(oneDeviceData), DEVICE_IS_STP_TARGET(oneDeviceData), DEVICE_IS_SATA_DEVICE(oneDeviceData)));
741        TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: registered %d right port %d \n", oneDeviceData->registered, (oneDeviceData->tdPortContext == onePortContext)));
742        TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: oneDeviceData->tdPortContext %p onePortContext %p\n", oneDeviceData->tdPortContext, onePortContext));
743      }
744      //DeviceIndex++;
745      DeviceListList = DeviceListList->flink;
746    } /* else */
747  }
748
749  if (DeviceIndex > maxDevs)
750  {
751    TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: DeviceIndex(%d) >= maxDevs(%d)\n", DeviceIndex, maxDevs));
752    FoundDevices = maxDevs;
753  }
754
755  TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: returning %d found devices, pid %d\n", FoundDevices, onePortContext->id));
756
757  return FoundDevices;
758}
759
760
761/*****************************************************************************
762*! \brief  tiINIGetDeviceInfo
763*
764*  Purpose: This routine is called by the OS Layer find out
765*           the name associated with the device and where
766*           it is mapped (address1 and address2).
767*
768*  \param  tiRoot:          Pointer to driver Instance.
769*  \param  tiDeviceHandle:  device handle associated with the device
770*  \param  tiDeviceInfo:    pointer to structure where the information
771*                           needs to be copied.
772*  \return:
773*          tiSuccess - successful
774*          tiInvalidHandle - device handle passed is not a valid handle.
775*
776*  \note:
777*
778*****************************************************************************/
779osGLOBAL bit32
780tiINIGetDeviceInfo(
781                   tiRoot_t            *tiRoot,
782                   tiDeviceHandle_t    *tiDeviceHandle,
783                   tiDeviceInfo_t      *tiDeviceInfo)
784{
785  tdsaDeviceData_t     *oneDeviceData = agNULL;
786  satDeviceData_t      *pSatDevData = agNULL;
787  bit8                 id_limit[5];
788  bit8                 SN_id_limit[25];
789  agsaRoot_t           *agRoot = agNULL;
790
791  TI_DBG6(("tiINIGetDeviceInfo: start \n"));
792
793  if (tiDeviceHandle == agNULL)
794  {
795    TI_DBG6(("tiINIGetDeviceInfo: tiDeviceHandle NULL\n"));
796    return tiInvalidHandle;
797  }
798
799  if (tiDeviceHandle->tdData == agNULL)
800  {
801    TI_DBG6(("tiINIGetDeviceInfo: ^^^^^^^^^ tiDeviceHandle->tdData NULL\n"));
802    return tiInvalidHandle;
803  }
804  else
805  {
806
807    oneDeviceData = (tdsaDeviceData_t *)(tiDeviceHandle->tdData);
808    agRoot = oneDeviceData->agRoot;
809    TI_DBG6(("tiINIGetDeviceInfo: ^^^^^^^^^ tiDeviceHandle->tdData NOT NULL\n"));
810  }
811  if (oneDeviceData == agNULL)
812  {
813    TI_DBG6(("tiINIGetDeviceInfo: ^^^^^^^^^ oneDeviceData NULL\n"));
814    return tiInvalidHandle;
815  }
816
817
818  /* filling in the link rate */
819  if (oneDeviceData->registered == agTRUE)
820  {
821    tiDeviceInfo->info.devType_S_Rate = oneDeviceData->agDeviceInfo.devType_S_Rate;
822  }
823  else
824  {
825    tiDeviceInfo->info.devType_S_Rate = (bit8)(oneDeviceData->agDeviceInfo.devType_S_Rate & 0x0f);
826  }
827
828  /* just returning local and remote SAS address; doesn't have a name for SATA device, returns identify device data */
829  if (DEVICE_IS_SATA_DEVICE(oneDeviceData) && (oneDeviceData->directlyAttached == agTRUE))
830  {
831    osti_memset(&id_limit, 0, sizeof(id_limit));
832    osti_memset(&SN_id_limit, 0, sizeof(SN_id_limit));
833
834    /* SATA signature 0xABCD */
835    id_limit[0] = 0xA;
836    id_limit[1] = 0xB;
837    id_limit[2] = 0xC;
838    id_limit[3] = 0xD;
839
840    pSatDevData = &(oneDeviceData->satDevData);
841    if (pSatDevData->satNCQ == agTRUE)
842    {
843      id_limit[4] = (bit8)pSatDevData->satNCQMaxIO;
844    }
845    else
846    {
847      /* no NCQ */
848      id_limit[4] = 1;
849    }
850
851    osti_memcpy(&SN_id_limit, &(oneDeviceData->satDevData.satIdentifyData.serialNumber), 20);
852    osti_memcpy(&(SN_id_limit[20]), &id_limit, 5);
853    osti_memcpy(oneDeviceData->satDevData.SN_id_limit, SN_id_limit, 25);
854    /* serialNumber, 20 bytes + ABCD + NCQ LENGTH ; modelNumber, 40 bytes */
855//  tiDeviceInfo->remoteName    = (char *)&(oneDeviceData->satDevData.satIdentifyData.serialNumber);
856    tiDeviceInfo->remoteName    = (char *)oneDeviceData->satDevData.SN_id_limit;
857    tiDeviceInfo->remoteAddress = (char *)&(oneDeviceData->satDevData.satIdentifyData.modelNumber);
858//    TI_DBG1(("tiINIGetDeviceInfo: SATA device remote hi 0x%08x lo 0x%08x\n", oneDeviceData->tdPortContext->sasRemoteAddressHi, oneDeviceData->tdPortContext->sasRemoteAddressLo));
859//    tdhexdump("tiINIGetDeviceInfo remotename", (bit8 *)&(oneDeviceData->satDevData.satIdentifyData.serialNumber), 20);
860//    tdhexdump("tiINIGetDeviceInfo new name", (bit8 *)&(SN_id_limit), sizeof(SN_id_limit));
861//    tdhexdump("tiINIGetDeviceInfo remoteaddress", (bit8 *)&(oneDeviceData->satDevData.satIdentifyData.modelNumber),40);
862    tiDeviceInfo->osAddress1 = 25;
863    tiDeviceInfo->osAddress2 = 40;
864
865  }
866  else if (DEVICE_IS_STP_TARGET(oneDeviceData))
867  {
868    /* serialNumber, 20 bytes; modelNumber, 40 bytes */
869    tiDeviceInfo->remoteName    = (char *)&(oneDeviceData->satDevData.satIdentifyData.serialNumber);
870    tiDeviceInfo->remoteAddress = (char *)&(oneDeviceData->satDevData.satIdentifyData.modelNumber);
871//    TI_DBG1(("tiINIGetDeviceInfo: SATA device remote hi 0x%08x lo 0x%08x\n", oneDeviceData->tdPortContext->sasRemoteAddressHi, oneDeviceData->tdPortContext->sasRemoteAddressLo));
872//    tdhexdump("tiINIGetDeviceInfo remotename", (bit8 *)&(oneDeviceData->satDevData.satIdentifyData.serialNumber), 20);
873//    tdhexdump("tiINIGetDeviceInfo remoteaddress", (bit8 *)&(oneDeviceData->satDevData.satIdentifyData.modelNumber),40);
874    tiDeviceInfo->osAddress1 = 20;
875    tiDeviceInfo->osAddress2 = 40;
876  }
877  else
878  {
879    tiDeviceInfo->remoteName    = (char *)&(oneDeviceData->SASAddressID.sasAddressHi);
880    tiDeviceInfo->remoteAddress = (char *)&(oneDeviceData->SASAddressID.sasAddressLo);
881    TI_DBG1(("tiINIGetDeviceInfo: SAS device remote hi 0x%08x lo 0x%08x\n", oneDeviceData->tdPortContext->sasRemoteAddressHi, oneDeviceData->tdPortContext->sasRemoteAddressLo));
882    tiDeviceInfo->osAddress1 = 4;
883    tiDeviceInfo->osAddress2 = 4;
884  }
885
886  tiDeviceInfo->localName     = (char *)&(oneDeviceData->tdPortContext->sasLocalAddressHi);
887  tiDeviceInfo->localAddress  = (char *)&(oneDeviceData->tdPortContext->sasLocalAddressLo);
888
889  TI_DBG6(("tiINIGetDeviceInfo: local hi 0x%08x lo 0x%08x\n", oneDeviceData->tdPortContext->sasLocalAddressHi, oneDeviceData->tdPortContext->sasLocalAddressLo));
890
891  if (oneDeviceData->agDevHandle == agNULL)
892  {
893    TI_DBG1(("tiINIGetDeviceInfo: Error! oneDeviceData->agDevHandle is NULL"));
894    return tiError;
895  }
896  else
897  {
898    saGetDeviceInfo(agRoot, agNULL, 0, 0,oneDeviceData->agDevHandle);
899  }
900
901
902  return tiSuccess;
903}
904
905/*****************************************************************************
906*! \brief  tiINILogin
907*
908*  Purpose: This function is called to request that the Transport Dependent
909*           Layer initiates login for a specific target.
910*
911*  \param tiRoot:          Pointer to driver Instance.
912*  \param tiDeviceHandle:  Pointer to a target device handle discovered
913*                          following the discovery.
914*
915*  \return:
916*        tiSuccess       Login initiated.
917*        tiError         Login failed.
918*        tiBusy          Login can not be initiated at this time.
919*        tiNotSupported  This API is currently not supported by this
920*                        Transport Layer
921*
922*
923*****************************************************************************/
924osGLOBAL bit32
925tiINILogin(
926           tiRoot_t            *tiRoot,
927           tiDeviceHandle_t    *tiDeviceHandle
928           )
929{
930  TI_DBG6(("tiINILogin: start\n"));
931  return tiNotSupported;
932}
933
934/*****************************************************************************
935*! \brief  tiINILogout
936*
937*  Purpose: This function is called to request that the Transport Dependent
938*           Layer initiates logout for a specific target from the previously
939*           successful login through tiINILogin() call.
940*
941*  \param   tiRoot      :  Pointer to the OS Specific module allocated tiRoot_t
942*                          instance.
943*  \param tiDeviceHandle:  Pointer to a target device handle.
944*
945*  \return:
946*         tiSuccess       Logout initiated.
947*         tiError         Logout failed.
948*         tiBusy          Logout can not be initiated at this time.
949*         tiNotSupported  This API is currently not supported by this
950*                         Transport Layer
951*
952*
953*****************************************************************************/
954osGLOBAL bit32
955tiINILogout(
956            tiRoot_t            *tiRoot,
957            tiDeviceHandle_t    *tiDeviceHandle
958            )
959{
960  TI_DBG6(("tiINILogout: start\n"));
961  return tiNotSupported;
962}
963/*****************************************************************************
964*! \brief  tiINIGetExpander
965*
966*
967*  \note:
968*
969*****************************************************************************/
970osGLOBAL bit32
971tiINIGetExpander(
972                  tiRoot_t          * tiRoot,
973                  tiPortalContext_t * tiPortalContext,
974                  tiDeviceHandle_t  * tiDev,
975                  tiDeviceHandle_t  ** tiExp
976                 )
977{
978  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
979  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
980  tdList_t          *PortContextList;
981  tdsaPortContext_t *onePortContext = agNULL;
982  tdsaDeviceData_t  *oneDeviceData = agNULL;
983  tdList_t          *DeviceListList;
984  tdsaDeviceData_t  *oneTargetDeviceData = agNULL;
985  tdsaDeviceData_t  *oneExpanderDeviceData = agNULL;
986  bit32             found = agFALSE;
987  oneTargetDeviceData = (tdsaDeviceData_t *)tiDev->tdData;
988  if (oneTargetDeviceData == agNULL)
989  {
990    TI_DBG1(("tiINIGetExpander: oneTargetDeviceData is NULL\n"));
991    return tiError;
992  }
993  tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
994  if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
995  {
996    tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
997    TI_DBG1(("tiINIGetExpander: No available tdsaPortContext\n"));
998    TI_DBG1(("tiINIGetExpander: second, returning 0\n"));
999    return tiError;
1000  }
1001  else
1002  {
1003    tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
1004  }
1005  /* find a corresponding portcontext */
1006  PortContextList = tdsaAllShared->MainPortContextList.flink;
1007  while (PortContextList != &(tdsaAllShared->MainPortContextList))
1008  {
1009    onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
1010    TI_DBG3(("tiINIGetExpander: oneportContext pid %d\n", onePortContext->id));
1011    if (onePortContext->tiPortalContext == tiPortalContext && onePortContext->valid == agTRUE)
1012    {
1013      TI_DBG3(("tiINIGetExpander: found; oneportContext pid %d\n", onePortContext->id));
1014      found = agTRUE;
1015      break;
1016    }
1017    PortContextList = PortContextList->flink;
1018  }
1019  if (found == agFALSE)
1020  {
1021    TI_DBG1(("tiINIGetExpander: First, No corresponding tdsaPortContext\n"));
1022    TI_DBG1(("tiINIGetExpander: third, returning 0\n"));
1023    return tiError;
1024  }
1025  if (onePortContext == agNULL)
1026  {
1027    TI_DBG1(("tiINIGetExpander: Second, No corressponding tdsaPortContext\n"));
1028    TI_DBG1(("tiINIGetExpander: fourth, returning 0\n"));
1029    return tiError;
1030  }
1031  if (onePortContext->valid == agFALSE)
1032  {
1033    TI_DBG1(("tiINIGetExpander: Third, tdsaPortContext is invalid, pid %d\n", onePortContext->id));
1034    TI_DBG1(("tiINIGetExpander: fifth, returning 0\n"));
1035    return tiError;
1036  }
1037  DeviceListList = tdsaAllShared->MainDeviceList.flink;
1038  while ( DeviceListList != &(tdsaAllShared->MainDeviceList) )
1039  {
1040    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
1041    if (oneDeviceData->tdPortContext != onePortContext)
1042    {
1043      TI_DBG3(("tiINIGetExpander: different port\n"));
1044      DeviceListList = DeviceListList->flink;
1045    }
1046    else
1047    {
1048      if (oneDeviceData == oneTargetDeviceData)
1049      {
1050        oneExpanderDeviceData = oneDeviceData->ExpDevice;
1051        if (oneExpanderDeviceData == agNULL)
1052        {
1053          TI_DBG1(("tiINIGetExpander: oneExpanderDeviceData is NULL\n"));
1054          return tiError;
1055        }
1056        *tiExp = &(oneExpanderDeviceData->tiDeviceHandle);
1057        return tiSuccess;
1058      }
1059      DeviceListList = DeviceListList->flink;
1060    }
1061  }
1062  return tiError;
1063}
1064
1065
1066osGLOBAL void tiIniGetDirectSataSasAddr(tiRoot_t * tiRoot, bit32 phyId, bit8 **sasAddressHi, bit8 **sasAddressLo)
1067{
1068	tdsaRoot_t		  *tdsaRoot 	   = (tdsaRoot_t *) tiRoot->tdData;
1069	tdsaContext_t	  *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1070	agsaRoot_t	  *agRoot = &tdsaAllShared->agRootInt;
1071        tiIOCTLPayload_wwn_t   agIoctlPayload;
1072   	bit8 nvmDev;
1073	bit32 status;
1074	int i;
1075	agIoctlPayload.Length = 4096;
1076	agIoctlPayload.Reserved = 0;
1077	agIoctlPayload.MinorFunction = IOCTL_MN_NVMD_GET_CONFIG;
1078	agIoctlPayload.MajorFunction = IOCTL_MJ_NVMD_GET;
1079	  tiCOMDelayedInterruptHandler(tiRoot, 0,1, tiNonInterruptContext);
1080	if(tiIS_SPC(agRoot))
1081 	{
1082	  nvmDev = 4;
1083	  status = tdsaNVMDGetIoctl(tiRoot, (tiIOCTLPayload_t *)&agIoctlPayload, agNULL, agNULL, &nvmDev);
1084	}
1085	else
1086	{
1087          nvmDev = 1;
1088	  status = tdsaNVMDGetIoctl(tiRoot, (tiIOCTLPayload_t *)&agIoctlPayload, agNULL, agNULL, &nvmDev);
1089 	}
1090	if(status == IOCTL_CALL_FAIL)
1091	{
1092#if !(defined(__FreeBSD__))
1093	   printk("Error getting Adapter WWN\n");
1094#else
1095	   printf("Error getting Adapter WWN\n");
1096#endif
1097	   return;
1098	}
1099 	for(i=0; i< TD_MAX_NUM_PHYS; i++)
1100	{
1101	   *(bit32 *)(tdsaAllShared->Ports[i].SASID.sasAddressHi) = *(bit32 *)&agIoctlPayload.FunctionSpecificArea[0];
1102	   *(bit32 *)(tdsaAllShared->Ports[i].SASID.sasAddressLo) = *(bit32 *)&agIoctlPayload.FunctionSpecificArea[4];
1103	TI_DBG3(("SAS AddressHi is 0x%x\n",  *(bit32 *)(tdsaAllShared->Ports[i].SASID.sasAddressHi)));
1104	TI_DBG3(("SAS AddressLo is 0x%x\n",  *(bit32 *)(tdsaAllShared->Ports[i].SASID.sasAddressLo)));
1105	}
1106	*sasAddressHi = tdsaAllShared->Ports[phyId].SASID.sasAddressHi;
1107	*sasAddressLo = tdsaAllShared->Ports[phyId].SASID.sasAddressLo;
1108}
1109osGLOBAL tiDeviceHandle_t *
1110tiINIGetExpDeviceHandleBySasAddress(
1111                      tiRoot_t          * tiRoot,
1112                      tiPortalContext_t * tiPortalContext,
1113					  bit32 sas_addr_hi,
1114					  bit32 sas_addr_lo,
1115					  bit32               maxDevs
1116                      )
1117
1118{
1119  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
1120  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1121  tdList_t          *PortContextList;
1122  tdsaPortContext_t *onePortContext = agNULL;
1123  tdsaDeviceData_t  *oneDeviceData = agNULL;
1124  tdList_t          *DeviceListList;
1125  //bit32             i;
1126  //bit32             FoundDevices = 0;
1127  bit32             DeviceIndex = 0;
1128  bit32             found = agFALSE;
1129
1130
1131  TI_DBG2(("tiINIGetExpDeviceHandleBySasAddress: start\n"));
1132  TI_DBG2(("tiINIGetExpDeviceHandleBySasAddress: tiPortalContext %p\n", tiPortalContext));
1133
1134
1135  if (maxDevs == 0)
1136  {
1137    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: maxDevs is 0\n"));
1138
1139    return agNULL;
1140  }
1141
1142  tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
1143  if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
1144  {
1145    tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
1146    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: No available tdsaPortContext\n"));
1147    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: second, returning 0\n"));
1148    return agNULL;
1149  }
1150  else
1151  {
1152    tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
1153  }
1154  /* find a corresponding portcontext */
1155  PortContextList = tdsaAllShared->MainPortContextList.flink;
1156
1157  if(PortContextList == agNULL)
1158  {
1159	TI_DBG6(("tiINIGetExpDeviceHandleBySasAddress: PortContextList is NULL!!\n"));
1160	return agNULL;
1161  }
1162
1163  while (PortContextList != &(tdsaAllShared->MainPortContextList))
1164  {
1165    onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
1166
1167	if(onePortContext == agNULL)
1168	{
1169	  TI_DBG6(("tiINIGetExpDeviceHandleBySasAddress: onePortContext is NULL!!\n"));
1170	  return agNULL;
1171    }
1172
1173    TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: oneportContext pid %d\n", onePortContext->id));
1174    if (onePortContext->tiPortalContext == tiPortalContext && onePortContext->valid == agTRUE)
1175    {
1176      TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: found; oneportContext pid %d\n", onePortContext->id));
1177      found = agTRUE;
1178      break;
1179    }
1180
1181	if(PortContextList != agNULL)
1182	{
1183      PortContextList = PortContextList->flink;
1184	}
1185
1186  }
1187
1188  if (found == agFALSE)
1189  {
1190    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: First, No corresponding tdsaPortContext\n"));
1191    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: third, returning 0\n"));
1192    /* nullify all device handles */
1193    return agNULL;
1194  }
1195
1196  if (onePortContext == agNULL)
1197  {
1198    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: Second, No corressponding tdsaPortContext\n"));
1199    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: fourth, returning 0\n"));
1200    /* nullify all device handles */
1201    return agNULL;
1202  }
1203
1204  if (onePortContext->valid == agFALSE)
1205  {
1206    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: Third, tdsaPortContext is invalid, pid %d\n", onePortContext->id));
1207    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: fifth, returning 0\n"));
1208    return agNULL;
1209  }
1210
1211
1212  TI_DBG2(("tiINIGetExpDeviceHandleBySasAddress: pid %d\n", onePortContext->id));
1213
1214
1215  /* to do: check maxdev and length of Mainlink */
1216  /*
1217     From the device list, returns only valid devices
1218  */
1219  DeviceListList = tdsaAllShared->MainDeviceList.flink;
1220
1221  if(DeviceListList == agNULL)
1222  {
1223    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: DeviceListList == agNULL\n"));
1224    TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: seventh, returning not found, pid %d\n", onePortContext->id));
1225    return agNULL;
1226  }
1227
1228  while ((DeviceIndex < maxDevs) &&
1229          DeviceListList != &(tdsaAllShared->MainDeviceList))
1230  {
1231    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
1232
1233	if(oneDeviceData == agNULL)
1234	{
1235	  TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: oneDeviceData is NULL!!\n"));
1236	  return agNULL;
1237	}
1238
1239
1240    TI_DBG6(("tiINIGetExpDeviceHandleBySasAddress: handle %p\n",  &(oneDeviceData->tiDeviceHandle)));
1241    if (oneDeviceData->tdPortContext != onePortContext)
1242    {
1243      TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: different port\n"));
1244
1245	  if(DeviceListList != agNULL)
1246	  {
1247        DeviceListList = DeviceListList->flink;
1248	  }
1249
1250    }
1251    else
1252    {
1253
1254      if ((oneDeviceData->valid == agTRUE) &&
1255          (oneDeviceData->registered == agTRUE) &&
1256          (oneDeviceData->tdPortContext == onePortContext) &&
1257          (
1258          (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE) ||
1259          (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE) ||
1260           DEVICE_IS_SMP_TARGET(oneDeviceData)
1261          )
1262         )
1263
1264      {
1265
1266		if(oneDeviceData->SASAddressID.sasAddressLo == sas_addr_lo && oneDeviceData->SASAddressID.sasAddressHi == sas_addr_hi)
1267		{
1268		  //TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: valid FoundDevices %d\n", FoundDevices));
1269	      TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: agDevHandle %p\n", oneDeviceData->agDevHandle));
1270          TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: Matched sas address:  low %x and high %x\n", oneDeviceData->SASAddressID.sasAddressLo,  oneDeviceData->SASAddressID.sasAddressHi));
1271 		  return &(oneDeviceData->tiDeviceHandle);
1272		}
1273      }
1274      DeviceIndex++;
1275      DeviceListList = DeviceListList->flink;
1276    } /* else */
1277  }
1278
1279  return agNULL;
1280}
1281
1282
1283
1284
1285#ifdef TD_DISCOVER
1286/*****************************************************************************
1287*! \brief  tdsaDiscover
1288*
1289*  Purpose:  This function is called to trigger topology discovery within a
1290*            portcontext.
1291*
1292*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1293*                   instance.
1294*  \param   onePortContext: Pointer to the portal context instance.
1295*  \param   type: Type of discovery. It can be SAS or SATA.
1296*  \param   option: discovery option. It can be Full or Incremental discovery.
1297*
1298*  \return:
1299*           tiSuccess    Discovery initiated.
1300*           tiError      Discovery could not be initiated at this time.
1301*
1302*   \note:
1303*
1304*****************************************************************************/
1305osGLOBAL bit32
1306tdsaDiscover(
1307             tiRoot_t          *tiRoot,
1308             tdsaPortContext_t *onePortContext,
1309             bit32             type,
1310             bit32             option
1311             )
1312
1313{
1314  bit32             ret = tiError;
1315  TI_DBG3(("tdsaDiscover: start\n"));
1316
1317  if (onePortContext->valid == agFALSE)
1318  {
1319    TI_DBG1(("tdsaDiscover: aborting discovery\n"));
1320    tdsaSASDiscoverAbort(tiRoot, onePortContext);
1321    return ret;
1322  }
1323
1324  switch ( option )
1325  {
1326  case TDSA_DISCOVERY_OPTION_FULL_START:
1327    TI_DBG3(("tdsaDiscover: full\n"));
1328    onePortContext->discovery.type = TDSA_DISCOVERY_OPTION_FULL_START;
1329    if ( type == TDSA_DISCOVERY_TYPE_SAS )
1330    {
1331      ret = tdsaSASFullDiscover(tiRoot, onePortContext);
1332    }
1333#ifdef SATA_ENABLE
1334    else if ( type == TDSA_DISCOVERY_TYPE_SATA )
1335    {
1336      if (onePortContext->discovery.status == DISCOVERY_SAS_DONE)
1337      {
1338        ret = tdsaSATAFullDiscover(tiRoot, onePortContext);
1339      }
1340    }
1341#endif
1342    break;
1343  case TDSA_DISCOVERY_OPTION_INCREMENTAL_START:
1344    TI_DBG3(("tdsaDiscover: incremental\n"));
1345    onePortContext->discovery.type = TDSA_DISCOVERY_OPTION_INCREMENTAL_START;
1346    if ( type == TDSA_DISCOVERY_TYPE_SAS )
1347    {
1348      TI_DBG3(("tdsaDiscover: incremental SAS\n"));
1349      ret = tdsaSASIncrementalDiscover(tiRoot, onePortContext);
1350    }
1351#ifdef SATA_ENABLE
1352    else if ( type == TDSA_DISCOVERY_TYPE_SATA )
1353    {
1354      if (onePortContext->discovery.status == DISCOVERY_SAS_DONE)
1355      {
1356        TI_DBG3(("tdsaDiscover: incremental SATA\n"));
1357        ret = tdsaSATAIncrementalDiscover(tiRoot, onePortContext);
1358      }
1359    }
1360#endif
1361    break;
1362  case TDSA_DISCOVERY_OPTION_ABORT:
1363    TI_DBG1(("tdsaDiscover: abort\n"));
1364    break;
1365  default:
1366    break;
1367
1368  }
1369  if (ret != tiSuccess)
1370  {
1371    TI_DBG1(("tdsaDiscover: fail, error 0x%x\n", ret));
1372  }
1373  return ret;
1374}
1375
1376/*****************************************************************************
1377*! \brief  tdsaSASFullDiscover
1378*
1379*  Purpose:  This function is called to trigger full SAS topology discovery
1380*            within a portcontext.
1381*
1382*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1383*                   instance.
1384*  \param   onePortContext: Pointer to the portal context instance.
1385*
1386*  \return:
1387*           tiSuccess    Discovery initiated.
1388*           tiError      Discovery could not be initiated at this time.
1389*
1390*   \note:
1391*
1392*****************************************************************************/
1393osGLOBAL bit32
1394tdsaSASFullDiscover(
1395                    tiRoot_t          *tiRoot,
1396                    tdsaPortContext_t *onePortContext
1397                    )
1398{
1399  tdsaRoot_t           *tdsaRoot       = (tdsaRoot_t *) tiRoot->tdData;
1400  tdsaContext_t        *tdsaAllShared  = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1401  tdsaDeviceData_t     *oneDeviceData  = agNULL;
1402  tdList_t             *DeviceListList;
1403  int                  i, j;
1404  bit8                 portMaxRate;
1405  TI_DBG3(("tdsaSASFullDiscover: start\n"));
1406  if (onePortContext->valid == agFALSE)
1407  {
1408    TI_DBG1(("tdsaSASFullDiscover: aborting discovery\n"));
1409    tdsaSASDiscoverAbort(tiRoot, onePortContext);
1410    return tiError;
1411  }
1412  /*
1413    1. abort all IO; may need a new LL API since TD does not queue IO's
1414    2. initializes(or invalidate) devices belonging to the port
1415    3. onePortContext->DiscoveryState == ITD_DSTATE_STARTED
1416    4. add directly connected one; if directed-SAS, spin-up
1417    5. tdsaSASUpStreamDiscoverStart(agRoot, pPort, pDevice)
1418  */
1419  /*
1420    invalidate all devices belonging to the portcontext except direct attached SAS/SATA
1421  */
1422  DeviceListList = tdsaAllShared->MainDeviceList.flink;
1423  while (DeviceListList != &(tdsaAllShared->MainDeviceList))
1424  {
1425    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
1426    TI_DBG3(("tdsaSASFullDiscover: STARTED loop id %d\n", oneDeviceData->id));
1427    TI_DBG3(("tdsaSASFullDiscover: STARTED loop sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
1428    TI_DBG3(("tdsaSASFullDiscover: STARTED loop sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
1429    if (oneDeviceData->tdPortContext == onePortContext &&
1430        (onePortContext->nativeSATAMode == agFALSE && onePortContext->directAttatchedSAS == agFALSE)             )
1431
1432    {
1433      TI_DBG3(("tdsaSASFullDiscover: invalidate\n"));
1434      oneDeviceData->valid = agFALSE;
1435      oneDeviceData->processed = agFALSE;
1436    }
1437    else
1438    {
1439      TI_DBG3(("tdsaSASFullDiscover: not invalidate\n"));
1440      /* no changes */
1441    }
1442    DeviceListList = DeviceListList->flink;
1443  }
1444
1445  onePortContext->DiscoveryState = ITD_DSTATE_STARTED;
1446  /* nativeSATAMode is set in ossaHwCB() in link up */
1447  if (onePortContext->nativeSATAMode == agFALSE) /* default: SAS and SAS/SATA mode */
1448  {
1449    if (SA_IDFRM_GET_DEVICETTYPE(&onePortContext->sasIDframe) == SAS_END_DEVICE &&
1450        SA_IDFRM_IS_SSP_TARGET(&onePortContext->sasIDframe) )
1451    {
1452      for(i=0;i<TD_MAX_NUM_PHYS;i++)
1453      {
1454        if (onePortContext->PhyIDList[i] == agTRUE)
1455        {
1456
1457           for (j=0;j<TD_MAX_NUM_NOTIFY_SPINUP;j++)
1458           {
1459             saLocalPhyControl(onePortContext->agRoot, agNULL, tdsaRotateQnumber(tiRoot, agNULL), i, AGSA_PHY_NOTIFY_ENABLE_SPINUP, agNULL);
1460           }
1461           break;
1462        }
1463      }
1464    }
1465    /*
1466      add the device
1467      1. add device in TD layer
1468      2. call saRegisterNewDevice
1469      3. update agDevHandle in ossaDeviceRegistrationCB()
1470    */
1471    portMaxRate = onePortContext->LinkRate;
1472    oneDeviceData = tdsaPortSASDeviceAdd(
1473                                         tiRoot,
1474                                         onePortContext,
1475                                         onePortContext->sasIDframe,
1476                                         agFALSE,
1477                                         portMaxRate,
1478                                         IT_NEXUS_TIMEOUT,
1479                                         0,
1480                                         SAS_DEVICE_TYPE,
1481                                         agNULL,
1482                                         0xFF
1483                                         );
1484    if (oneDeviceData)
1485    {
1486      if (oneDeviceData->registered == agFALSE)
1487      {
1488        /*
1489          set the timer and wait till the device(directly attached. eg Expander) to be registered.
1490         Then, in tdsaDeviceRegistrationTimerCB(), tdsaSASUpStreamDiscoverStart() is called
1491        */
1492        tdsaDeviceRegistrationTimer(tiRoot, onePortContext, oneDeviceData);
1493      }
1494      else
1495      {
1496        tdsaSASUpStreamDiscoverStart(tiRoot, onePortContext, oneDeviceData);
1497      }
1498    }
1499#ifdef REMOVED
1500    // temp testing code
1501    tdsaReportManInfoSend(tiRoot, oneDeviceData);
1502    //end temp testing code
1503#endif
1504  }
1505  else /* SATAOnlyMode*/
1506  {
1507    tdsaSASDiscoverDone(tiRoot, onePortContext, tiSuccess);
1508  }
1509
1510  return tiSuccess;
1511}
1512
1513/*****************************************************************************
1514*! \brief  tdsaSASUpStreamDiscoverStart
1515*
1516*  Purpose:  This function is called to trigger upstream traverse in topology
1517*            within a portcontext.
1518*
1519*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1520*                   instance.
1521*  \param   onePortContext: Pointer to the portal context instance.
1522*  \param   oneDeviceData: Pointer to the device data.
1523*
1524*  \return:
1525*           None
1526*
1527*   \note:
1528*
1529*****************************************************************************/
1530osGLOBAL void
1531tdsaSASUpStreamDiscoverStart(
1532                             tiRoot_t             *tiRoot,
1533                             tdsaPortContext_t    *onePortContext,
1534                             tdsaDeviceData_t     *oneDeviceData
1535                             )
1536{
1537  tdsaExpander_t        *oneExpander;
1538
1539  TI_DBG3(("tdsaSASUpStreamDiscoverStart: start\n"));
1540
1541  if (onePortContext->valid == agFALSE)
1542  {
1543    TI_DBG1(("tdsaSASUpStreamDiscoverStart: aborting discovery\n"));
1544    tdsaSASDiscoverAbort(tiRoot, onePortContext);
1545    return;
1546  }
1547
1548  /*
1549    1. update discovery state to UP_STREAM
1550    2. if (expander) add it
1551    3. tdsaSASUpStreamDiscovering
1552
1553  */
1554  onePortContext->discovery.status = DISCOVERY_UP_STREAM;
1555  if (
1556      (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
1557       ||
1558      (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE)
1559      )
1560  {
1561    oneExpander = tdssSASDiscoveringExpanderAlloc(tiRoot, onePortContext, oneDeviceData);
1562    if ( oneExpander != agNULL)
1563    {
1564      /* (2.2.1) Add to discovering list */
1565      tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, oneExpander);
1566    }
1567    else
1568    {
1569      TI_DBG1(("tdsaSASUpStreamDiscoverStart: failed to allocate expander or discovey aborted\n"));
1570      return;
1571    }
1572  }
1573
1574  tdsaSASUpStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
1575
1576  return;
1577}
1578
1579/*****************************************************************************
1580*! \brief  tdsaSASUpStreamDiscovering
1581*
1582*  Purpose:  For each expander in the expander list, this function sends SMP to
1583*            find information for discovery and calls
1584*            tdsaSASDownStreamDiscoverStart() function.
1585*
1586*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1587*                   instance.
1588*  \param   onePortContext: Pointer to the portal context instance.
1589*  \param   oneDeviceData: Pointer to the device data.
1590*
1591*  \return:
1592*           None
1593*
1594*   \note:
1595*
1596*****************************************************************************/
1597osGLOBAL void
1598tdsaSASUpStreamDiscovering(
1599                           tiRoot_t             *tiRoot,
1600                           tdsaPortContext_t    *onePortContext,
1601                           tdsaDeviceData_t     *oneDeviceData
1602                           )
1603{
1604  tdList_t          *ExpanderList;
1605  tdsaExpander_t    *oneNextExpander = agNULL;
1606
1607  TI_DBG3(("tdsaSASUpStreamDiscovering: start\n"));
1608  if (onePortContext->valid == agFALSE)
1609  {
1610    TI_DBG1(("tdsaSASUpStreamDiscovering: aborting discovery\n"));
1611    tdsaSASDiscoverAbort(tiRoot, onePortContext);
1612    return;
1613  }
1614  /*
1615    1. find the next expander
1616    2. if (there is next expander) send report general with saSMPStart
1617       else tdsaSASDownStreamDiscoverStart
1618
1619  */
1620  tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1621  if (TDLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList)))
1622  {
1623    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1624    TI_DBG3(("tdsaSASUpStreamDiscovering: should be the end\n"));
1625    oneNextExpander = agNULL;
1626  }
1627  else
1628  {
1629    TDLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList));
1630    oneNextExpander = TDLIST_OBJECT_BASE(tdsaExpander_t, linkNode, ExpanderList);
1631    TDLIST_ENQUEUE_AT_HEAD(&(oneNextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));
1632    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1633
1634    TI_DBG3(("tdssSASDiscoveringExpander tdsaSASUpStreamDiscovering: dequeue head\n"));
1635    TI_DBG3(("tdsaSASUpStreamDiscovering: expander id %d\n", oneNextExpander->id));
1636  }
1637
1638  if (oneNextExpander != agNULL)
1639  {
1640    tdsaReportGeneralSend(tiRoot, oneNextExpander->tdDevice);
1641  }
1642  else
1643  {
1644    TI_DBG3(("tdsaSASUpStreamDiscovering: No more expander list\n"));
1645    tdsaSASDownStreamDiscoverStart(tiRoot, onePortContext, oneDeviceData);
1646  }
1647
1648  return;
1649}
1650
1651/*****************************************************************************
1652*! \brief  tdsaSASDownStreamDiscoverStart
1653*
1654*  Purpose:  This function is called to trigger downstream traverse in topology
1655*            within a portcontext.
1656*
1657*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1658*                   instance.
1659*  \param   onePortContext: Pointer to the portal context instance.
1660*  \param   oneDeviceData: Pointer to the device data.
1661*
1662*  \return:
1663*           None
1664*
1665*   \note:
1666*
1667*****************************************************************************/
1668osGLOBAL void
1669tdsaSASDownStreamDiscoverStart(
1670                               tiRoot_t             *tiRoot,
1671                               tdsaPortContext_t    *onePortContext,
1672                               tdsaDeviceData_t     *oneDeviceData
1673                               )
1674{
1675  tdsaExpander_t        *oneExpander;
1676  tdsaExpander_t        *UpStreamExpander;
1677  TI_DBG3(("tdsaSASDownStreamDiscoverStart: start\n"));
1678
1679  if (onePortContext->valid == agFALSE)
1680  {
1681    TI_DBG1(("tdsaSASDownStreamDiscoverStart: aborting discovery\n"));
1682    tdsaSASDiscoverAbort(tiRoot, onePortContext);
1683    return;
1684  }
1685  /*
1686    1. update discover state
1687    2. if (expander is root) add it
1688       else just add it
1689    3. tdsaSASDownStreamDiscovering
1690
1691  */
1692  /* set discovery status */
1693  onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
1694
1695  TI_DBG3(("tdsaSASDownStreamDiscoverStart: pPort=%p pDevice=%p\n", onePortContext, oneDeviceData));
1696
1697  /* If it's an expander */
1698  if ( (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
1699       || (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE))
1700  {
1701    oneExpander = oneDeviceData->tdExpander;
1702    UpStreamExpander = oneExpander->tdUpStreamExpander;
1703
1704    /* If the two expanders are the root of two edge sets; sub-to-sub */
1705    if ( (UpStreamExpander != agNULL) && ( UpStreamExpander->tdUpStreamExpander == oneExpander ) )
1706    {
1707      TI_DBG3(("tdsaSASDownStreamDiscoverStart: Root found pExpander=%p pUpStreamExpander=%p\n",
1708               oneExpander, UpStreamExpander));
1709      //Saves the root expander
1710      onePortContext->discovery.RootExp = oneExpander;
1711      TI_DBG3(("tdsaSASDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
1712      TI_DBG3(("tdsaSASDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
1713
1714      /* reset up stream inform for pExpander */
1715      oneExpander->tdUpStreamExpander = agNULL;
1716      /* Add the pExpander to discovering list */
1717      tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, oneExpander);
1718
1719      /* reset up stream inform for oneExpander */
1720      UpStreamExpander->tdUpStreamExpander = agNULL;
1721      /* Add the UpStreamExpander to discovering list */
1722      tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, UpStreamExpander);
1723    }
1724    /* If the two expanders are not the root of two edge sets. eg) one root */
1725    else
1726    {
1727      //Saves the root expander
1728      onePortContext->discovery.RootExp = oneExpander;
1729
1730      TI_DBG3(("tdsaSASDownStreamDiscoverStart: NO Root pExpander=%p\n", oneExpander));
1731      TI_DBG3(("tdsaSASDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
1732      TI_DBG3(("tdsaSASDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
1733
1734      /* (2.2.2.1) Add the pExpander to discovering list */
1735      tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, oneExpander);
1736    }
1737  }
1738
1739  /* Continue down stream discovering */
1740  tdsaSASDownStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
1741
1742  return;
1743}
1744
1745/*****************************************************************************
1746*! \brief  tdsaSASDownStreamDiscovering
1747*
1748*  Purpose:  For each expander in the expander list, this function sends SMP to
1749*            find information for discovery and calls
1750*            tdsaSASDownStreamDiscoverStart() function.
1751*
1752*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1753*                   instance.
1754*  \param   onePortContext: Pointer to the portal context instance.
1755*  \param   oneDeviceData: Pointer to the device data.
1756*
1757*  \return:
1758*           None
1759*
1760*   \note:
1761*
1762*****************************************************************************/
1763osGLOBAL void
1764tdsaSASDownStreamDiscovering(
1765                               tiRoot_t             *tiRoot,
1766                               tdsaPortContext_t    *onePortContext,
1767                               tdsaDeviceData_t     *oneDeviceData
1768                               )
1769{
1770  tdsaExpander_t    *NextExpander = agNULL;
1771  tdList_t          *ExpanderList;
1772
1773  TI_DBG3(("tdsaSASDownStreamDiscovering: start\n"));
1774
1775  TI_DBG3(("tdsaSASDownStreamDiscovering: pPort=%p  pDevice=%p\n", onePortContext, oneDeviceData));
1776
1777  if (onePortContext->valid == agFALSE)
1778  {
1779    TI_DBG1(("tdsaSASDownStreamDiscovering: aborting discovery\n"));
1780    tdsaSASDiscoverAbort(tiRoot, onePortContext);
1781    return;
1782  }
1783
1784  tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1785  if (TDLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList)))
1786  {
1787    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1788    TI_DBG3(("tdsaSASDownStreamDiscovering: should be the end\n"));
1789    NextExpander = agNULL;
1790  }
1791  else
1792  {
1793    TDLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList));;
1794    NextExpander = TDLIST_OBJECT_BASE(tdsaExpander_t, linkNode, ExpanderList);
1795    TDLIST_ENQUEUE_AT_HEAD(&(NextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));;
1796    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1797    TI_DBG3(("tdssSASDiscoveringExpander tdsaSASDownStreamDiscovering: dequeue head\n"));
1798    TI_DBG3(("tdsaSASDownStreamDiscovering: expander id %d\n", NextExpander->id));
1799
1800  }
1801
1802  /* If there is an expander for continue discoving */
1803  if ( NextExpander != agNULL)
1804  {
1805    TI_DBG3(("tdsaSASDownStreamDiscovering: Found pNextExpander=%p\n, discoveryStatus=0x%x",
1806             NextExpander, onePortContext->discovery.status));
1807
1808    switch (onePortContext->discovery.status)
1809    {
1810      /* If the discovery status is DISCOVERY_DOWN_STREAM */
1811    case DISCOVERY_DOWN_STREAM:
1812      /* Send report general for the next expander */
1813      TI_DBG3(("tdsaSASDownStreamDiscovering: DownStream pNextExpander->pDevice=%p\n", NextExpander->tdDevice));
1814      tdsaReportGeneralSend(tiRoot, NextExpander->tdDevice);
1815      break;
1816      /* If the discovery status is DISCOVERY_CONFIG_ROUTING */
1817    case DISCOVERY_CONFIG_ROUTING:
1818    case DISCOVERY_REPORT_PHY_SATA:
1819
1820      /* set discovery status */
1821      onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
1822
1823      TI_DBG3(("tdsaSASDownStreamDiscovering: pPort->discovery.status=DISCOVERY_CONFIG_ROUTING, nake it DOWN_STREAM\n"));
1824      /* If not the last phy */
1825      if ( NextExpander->discoveringPhyId < NextExpander->tdDevice->numOfPhys )
1826      {
1827        TI_DBG3(("tdsaSASDownStreamDiscovering: pNextExpander->discoveringPhyId=0x%x pNextExpander->pDevice->numOfPhys=0x%x.  Send More Discover\n",
1828                 NextExpander->discoveringPhyId, NextExpander->tdDevice->numOfPhys));
1829        /* Send discover for the next expander */
1830        tdsaDiscoverSend(tiRoot, NextExpander->tdDevice);
1831        }
1832      /* If it's the last phy */
1833      else
1834      {
1835        TI_DBG3(("tdsaSASDownStreamDiscovering: Last Phy, remove expander%p  start DownStream=%p\n",
1836                 NextExpander, NextExpander->tdDevice));
1837        tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, NextExpander);
1838        tdsaSASDownStreamDiscovering(tiRoot, onePortContext, NextExpander->tdDevice);
1839      }
1840      break;
1841
1842    default:
1843      TI_DBG3(("tdsaSASDownStreamDiscovering: *** Unknown pPort->discovery.status=0x%x\n", onePortContext->discovery.status));
1844    }
1845  }
1846  /* If no expander for continue discoving */
1847  else
1848  {
1849    TI_DBG3(("tdsaSASDownStreamDiscovering: No more expander DONE\n"));
1850    /* discover done */
1851    tdsaSASDiscoverDone(tiRoot, onePortContext, tiSuccess);
1852  }
1853
1854  return;
1855}
1856
1857/*****************************************************************************
1858*! \brief  tdsaCleanAllExp
1859*
1860*  Purpose:  This function cleans up expander data structures after discovery
1861*            is complete.
1862*
1863*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1864*                   instance.
1865*  \param   onePortContext: Pointer to the portal context instance.
1866*
1867*  \return:
1868*           None
1869*
1870*   \note:
1871*
1872*****************************************************************************/
1873osGLOBAL void
1874tdsaCleanAllExp(
1875                tiRoot_t                 *tiRoot,
1876                tdsaPortContext_t        *onePortContext
1877                )
1878{
1879  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
1880  tdsaContext_t     *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1881  tdList_t          *ExpanderList;
1882  tdsaExpander_t    *tempExpander;
1883  tdsaPortContext_t *tmpOnePortContext = onePortContext;
1884
1885  TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: start\n"));
1886
1887  TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: before all clean up\n"));
1888  tdsaDumpAllFreeExp(tiRoot);
1889
1890  /* clean up UpdiscoveringExpanderList*/
1891  TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: clean discoveringExpanderList\n"));
1892  tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1893  if (!TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
1894  {
1895    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1896    ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
1897    while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
1898    {
1899      tempExpander = TDLIST_OBJECT_BASE(tdsaExpander_t, linkNode, ExpanderList);
1900      TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: exp addrHi 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressHi));
1901      TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: exp addrLo 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressLo));
1902      /* putting back to the free pool */
1903      tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1904      TDLIST_DEQUEUE_THIS(&(tempExpander->linkNode));
1905      TDLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(tdsaAllShared->freeExpanderList));
1906
1907      if (TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
1908      {
1909        tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1910        break;
1911      }
1912      else
1913      {
1914        tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1915      }
1916      ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
1917
1918//      ExpanderList = ExpanderList->flink;
1919    }
1920  }
1921  else
1922  {
1923    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1924    TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: empty discoveringExpanderList\n"));
1925  }
1926
1927  /* reset UpdiscoveringExpanderList */
1928  TDLIST_INIT_HDR(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList));
1929
1930  TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: after all clean up\n"));
1931  tdsaDumpAllFreeExp(tiRoot);
1932
1933  return;
1934}
1935
1936/*****************************************************************************
1937*! \brief  tdsaFreeAllExp
1938*
1939*  Purpose:  This function frees up expander data structures as a part of
1940*            soft reset.
1941*
1942*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1943*                   instance.
1944*  \param   onePortContext: Pointer to the portal context instance.
1945*
1946*  \return:
1947*           None
1948*
1949*   \note:
1950*
1951*****************************************************************************/
1952osGLOBAL void
1953tdsaFreeAllExp(
1954                tiRoot_t                 *tiRoot,
1955                tdsaPortContext_t        *onePortContext
1956                )
1957{
1958  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
1959  tdsaContext_t     *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1960  tdList_t          *ExpanderList;
1961  tdsaExpander_t    *tempExpander;
1962  tdsaPortContext_t *tmpOnePortContext = onePortContext;
1963
1964  TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: start\n"));
1965
1966  TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: before all clean up\n"));
1967  tdsaDumpAllFreeExp(tiRoot);
1968
1969  /* clean up UpdiscoveringExpanderList*/
1970  TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: clean discoveringExpanderList\n"));
1971  tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1972  if (!TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
1973  {
1974    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1975    ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
1976    while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
1977    {
1978      tempExpander = TDLIST_OBJECT_BASE(tdsaExpander_t, linkNode, ExpanderList);
1979      TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: exp addrHi 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressHi));
1980      TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: exp addrLo 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressLo));
1981      /* putting back to the free pool */
1982      tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1983      TDLIST_DEQUEUE_THIS(&(tempExpander->linkNode));
1984      TDLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(tdsaAllShared->freeExpanderList));
1985
1986      if (TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
1987      {
1988        tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1989        break;
1990      }
1991      else
1992      {
1993        tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1994      }
1995      ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
1996
1997//      ExpanderList = ExpanderList->flink;
1998    }
1999  }
2000  else
2001  {
2002    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
2003    TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: empty discoveringExpanderList\n"));
2004  }
2005
2006  /* reset UpdiscoveringExpanderList */
2007  TDLIST_INIT_HDR(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList));
2008
2009  return;
2010}
2011/*****************************************************************************
2012*! \brief  tdsaResetValidDeviceData
2013*
2014*  Purpose:  This function resets valid and valid2 field for discovered devices
2015*            in the device list. This is used only in incremental discovery.
2016*
2017*  \param   agRoot        :  Pointer to chip/driver Instance.
2018*  \param   onePortContext: Pointer to the portal context instance.
2019*  \param   oneDeviceData: Pointer to the device data.
2020*
2021*  \return:
2022*           None
2023*
2024*   \note:
2025*
2026*****************************************************************************/
2027osGLOBAL void
2028tdsaResetValidDeviceData(
2029                                 agsaRoot_t           *agRoot,
2030                                 tdsaPortContext_t    *onePortContext
2031                                 )
2032{
2033  tdsaRootOsData_t  *osData = (tdsaRootOsData_t *)agRoot->osData;
2034  tiRoot_t          *tiRoot = (tiRoot_t *)osData->tiRoot;
2035  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
2036  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2037  tdList_t          *DeviceListList;
2038  tdsaDeviceData_t  *oneDeviceData;
2039
2040  TI_DBG3(("tdsaResetValidDeviceData: start\n"));
2041
2042  tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2043  if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2044  {
2045    tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2046    TI_DBG1(("tdsaResetValidDeviceData: empty device list\n"));
2047  }
2048  else
2049  {
2050    tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2051    DeviceListList = tdsaAllShared->MainDeviceList.flink;
2052    while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2053    {
2054      oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2055      oneDeviceData->valid = oneDeviceData->valid2;
2056      oneDeviceData->valid2 = agFALSE;
2057      DeviceListList = DeviceListList->flink;
2058      TI_DBG3(("tdsaResetValidDeviceData: valid %d valid2 %d\n", oneDeviceData->valid, oneDeviceData->valid2));
2059    }
2060  }
2061
2062  return;
2063}
2064
2065/*****************************************************************************
2066*! \brief  tdssReportChanges
2067*
2068*  Purpose:  This function goes throuhg device list and finds out whether
2069*            a device is removed and newly added. Based on the findings,
2070*            this function notifies OS layer of the change.
2071*
2072*  \param   agRoot        :  Pointer to chip/driver Instance.
2073*  \param   onePortContext: Pointer to the portal context instance.
2074*
2075*  \return:
2076*           None
2077*
2078*   \note:
2079*
2080*****************************************************************************/
2081osGLOBAL void
2082tdssReportChanges(
2083                  agsaRoot_t           *agRoot,
2084                  tdsaPortContext_t    *onePortContext
2085                  )
2086{
2087  tdsaDeviceData_t  *oneDeviceData = agNULL;
2088  tdList_t          *DeviceListList;
2089  tdsaRootOsData_t  *osData = (tdsaRootOsData_t *)agRoot->osData;
2090  tiRoot_t          *tiRoot = (tiRoot_t *)osData->tiRoot;
2091  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
2092  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2093  bit32             added = agFALSE, removed = agFALSE;
2094
2095  TI_DBG1(("tdssReportChanges: start\n"));
2096
2097  tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2098  if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2099  {
2100    tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2101    TI_DBG1(("tdssReportChanges: empty device list\n"));
2102    return;
2103  }
2104  else
2105  {
2106    tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2107  }
2108  DeviceListList = tdsaAllShared->MainDeviceList.flink;
2109  while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2110  {
2111    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2112    TI_DBG3(("tdssReportChanges: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2113    TI_DBG3(("tdssReportChanges: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2114    if ( oneDeviceData->tdPortContext == onePortContext)
2115    {
2116      TI_DBG3(("tdssReportChanges: right portcontext\n"));
2117      if ( (oneDeviceData->valid == agTRUE) && (oneDeviceData->valid2 == agTRUE) )
2118      {
2119        TI_DBG3(("tdssReportChanges: same\n"));
2120        /* reset valid bit */
2121        oneDeviceData->valid = oneDeviceData->valid2;
2122        oneDeviceData->valid2 = agFALSE;
2123      }
2124      else if ( (oneDeviceData->valid == agTRUE) && (oneDeviceData->valid2 == agFALSE) )
2125      {
2126        TI_DBG3(("tdssReportChanges: removed\n"));
2127        removed = agTRUE;
2128        /* reset valid bit */
2129        oneDeviceData->valid = oneDeviceData->valid2;
2130        oneDeviceData->valid2 = agFALSE;
2131        /* reset NumOfFCA */
2132        oneDeviceData->satDevData.NumOfFCA = 0;
2133
2134        if ( (oneDeviceData->registered == agTRUE) &&
2135             ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData)
2136             || DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_SMP_TARGET(oneDeviceData) )
2137           )
2138        {
2139          tdsaAbortAll(tiRoot, agRoot, oneDeviceData);
2140        }
2141        else if (oneDeviceData->registered == agTRUE)
2142        {
2143          TI_DBG1(("tdssReportChanges: calling saDeregisterDeviceHandle, did %d\n", oneDeviceData->id));
2144          saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, 0);
2145        }
2146
2147        oneDeviceData->registered = agFALSE;
2148
2149#ifdef REMOVED  /* don't remove device from the device list. May screw up ordering of report */
2150        TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
2151        TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList));
2152#endif
2153      }
2154      else if ( (oneDeviceData->valid == agFALSE) && (oneDeviceData->valid2 == agTRUE) )
2155      {
2156        TI_DBG3(("tdssReportChanges: added\n"));
2157        added = agTRUE;
2158        /* reset valid bit */
2159        oneDeviceData->valid = oneDeviceData->valid2;
2160        oneDeviceData->valid2 = agFALSE;
2161      }
2162      else
2163      {
2164        TI_DBG6(("tdssReportChanges: else\n"));
2165      }
2166    }
2167    else
2168    {
2169      TI_DBG1(("tdssReportChanges: different portcontext\n"));
2170    }
2171    DeviceListList = DeviceListList->flink;
2172  }
2173  /* arrival or removal at once */
2174  if (added == agTRUE)
2175  {
2176    TI_DBG3(("tdssReportChanges: added at the end\n"));
2177#ifdef AGTIAPI_CTL
2178    if (tdsaAllShared->SASConnectTimeLimit)
2179      tdsaCTLSet(tiRoot, onePortContext, tiIntrEventTypeDeviceChange,
2180                 tiDeviceArrival);
2181    else
2182#endif
2183      ostiInitiatorEvent(
2184                         tiRoot,
2185                         onePortContext->tiPortalContext,
2186                         agNULL,
2187                         tiIntrEventTypeDeviceChange,
2188                         tiDeviceArrival,
2189                         agNULL
2190                         );
2191
2192  }
2193  if (removed == agTRUE)
2194  {
2195    TI_DBG3(("tdssReportChanges: removed at the end\n"));
2196    ostiInitiatorEvent(
2197                       tiRoot,
2198                       onePortContext->tiPortalContext,
2199                       agNULL,
2200                       tiIntrEventTypeDeviceChange,
2201                       tiDeviceRemoval,
2202                       agNULL
2203                       );
2204  }
2205
2206  if (onePortContext->discovery.forcedOK == agTRUE && added == agFALSE && removed == agFALSE)
2207  {
2208    TI_DBG1(("tdssReportChanges: missed chance to report. forced to report OK\n"));
2209    onePortContext->discovery.forcedOK = agFALSE;
2210    ostiInitiatorEvent(
2211                       tiRoot,
2212                       onePortContext->tiPortalContext,
2213                       agNULL,
2214                       tiIntrEventTypeDiscovery,
2215                       tiDiscOK,
2216                       agNULL
2217                       );
2218  }
2219
2220  if (added == agFALSE && removed == agFALSE)
2221  {
2222    TI_DBG3(("tdssReportChanges: the same\n"));
2223  }
2224  return;
2225}
2226/*****************************************************************************
2227*! \brief  tdssReportRemovals
2228*
2229*  Purpose:  This function goes through device list and removes all devices
2230*            belong to the portcontext. This function also deregiters those
2231*            devices. This function is called in case of incremental discovery
2232*            failure.
2233*
2234*  \param   agRoot        :  Pointer to chip/driver Instance.
2235*  \param   onePortContext: Pointer to the portal context instance.
2236*  \param   oneDeviceData: Pointer to the device data.
2237*
2238*  \return:
2239*           None
2240*
2241*   \note:
2242*
2243*****************************************************************************/
2244osGLOBAL void
2245tdssReportRemovals(
2246                  agsaRoot_t           *agRoot,
2247                  tdsaPortContext_t    *onePortContext,
2248                  bit32                flag
2249                  )
2250{
2251  tdsaDeviceData_t  *oneDeviceData = agNULL;
2252  tdList_t          *DeviceListList;
2253  tdsaRootOsData_t  *osData = (tdsaRootOsData_t *)agRoot->osData;
2254  tiRoot_t          *tiRoot = (tiRoot_t *)osData->tiRoot;
2255  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
2256  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2257  bit32             removed = agFALSE;
2258  agsaEventSource_t *eventSource;
2259  bit32             PhyID;
2260  bit32             HwAckSatus;
2261  agsaDevHandle_t   *agDevHandle = agNULL;
2262
2263  TI_DBG2(("tdssReportRemovals: start\n"));
2264  /* in case nothing was registered */
2265  PhyID = onePortContext->eventPhyID;
2266  if (tdsaAllShared->eventSource[PhyID].EventValid == agTRUE &&
2267      onePortContext->RegisteredDevNums == 0 &&
2268      PhyID != 0xFF
2269      )
2270  {
2271    TI_DBG2(("tdssReportRemovals: calling saHwEventAck\n"));
2272    eventSource = &(tdsaAllShared->eventSource[PhyID].Source);
2273    HwAckSatus = saHwEventAck(
2274                              agRoot,
2275                              agNULL, /* agContext */
2276                              0,
2277                              eventSource, /* agsaEventSource_t */
2278                              0,
2279                              0
2280                              );
2281    if ( HwAckSatus != AGSA_RC_SUCCESS)
2282    {
2283      TI_DBG1(("tdssReportRemovals: failing in saHwEventAck; status %d\n", HwAckSatus));
2284    }
2285
2286    /* toggle */
2287    tdsaAllShared->eventSource[PhyID].EventValid = agFALSE;
2288    if (onePortContext->valid == agFALSE)
2289    {
2290      /* put device belonging to the port to freedevice list */
2291      DeviceListList = tdsaAllShared->MainDeviceList.flink;
2292      while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2293      {
2294        oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2295        if (oneDeviceData->tdPortContext == onePortContext)
2296        {
2297          osti_memset(&(oneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t));
2298          tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2299          TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
2300          TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList));
2301          if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2302          {
2303            tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2304            break;
2305          }
2306          tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2307          DeviceListList = tdsaAllShared->MainDeviceList.flink;
2308        }
2309        else
2310        {
2311          DeviceListList = DeviceListList->flink;
2312        }
2313      } /* while */
2314
2315      tdsaPortContextReInit(tiRoot, onePortContext);
2316      /*
2317        put all devices belonging to the onePortContext
2318        back to the free link
2319       */
2320      tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
2321      TDLIST_DEQUEUE_THIS(&(onePortContext->MainLink));
2322      TDLIST_ENQUEUE_AT_TAIL(&(onePortContext->FreeLink), &(tdsaAllShared->FreePortContextList));
2323      tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
2324    }
2325  }
2326
2327  else
2328  {
2329    tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2330    if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2331    {
2332      tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2333      TI_DBG1(("tdssReportRemovals: 1st empty device list\n"));
2334      return;
2335    }
2336    else
2337    {
2338      tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2339    }
2340    DeviceListList = tdsaAllShared->MainDeviceList.flink;
2341    /* needs to clean up devices which were not removed in ossaDeregisterDeviceHandleCB() since port was in valid (discovery error) */
2342    while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2343    {
2344      oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2345      if (oneDeviceData == agNULL)
2346      {
2347        TI_DBG1(("tdssReportRemovals: oneDeviceData is NULL!!!\n"));
2348        return;
2349      }
2350      TI_DBG2(("tdssReportRemovals: 1st loop did %d\n", oneDeviceData->id));
2351      TI_DBG2(("tdssReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2352      TI_DBG2(("tdssReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2353      TI_DBG2(("tdssReportRemovals: valid %d\n", oneDeviceData->valid));
2354      TI_DBG2(("tdssReportRemovals: valid2 %d\n", oneDeviceData->valid2));
2355      TI_DBG2(("tdssReportRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
2356      TI_DBG2(("tdssReportRemovals: registered %d\n", oneDeviceData->registered));
2357      if ( oneDeviceData->tdPortContext == onePortContext && oneDeviceData->valid == agFALSE &&
2358           oneDeviceData->valid2 == agFALSE && oneDeviceData->registered == agFALSE
2359         )
2360      {
2361        /* remove oneDevice from MainLink */
2362        TI_DBG2(("tdssReportRemovals: delete from MainLink\n"));
2363        agDevHandle = oneDeviceData->agDevHandle;
2364        tdsaDeviceDataReInit(tiRoot, oneDeviceData);
2365        //save agDevHandle and tdPortContext
2366        oneDeviceData->agDevHandle = agDevHandle;
2367        oneDeviceData->tdPortContext = onePortContext;
2368        osti_memset(&(oneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t));
2369        tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2370        TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
2371        TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList));
2372        tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2373        DeviceListList = tdsaAllShared->MainDeviceList.flink;
2374        tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2375        if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2376        {
2377          tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2378          break;
2379        }
2380        else
2381        {
2382          tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2383        }
2384      }
2385      else
2386      {
2387        DeviceListList = DeviceListList->flink;
2388      }
2389    } /* while */
2390
2391
2392    tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2393    if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2394    {
2395      tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2396      TI_DBG1(("tdssReportRemovals: 2nd empty device list\n"));
2397      return;
2398    }
2399    else
2400    {
2401      tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2402    }
2403    DeviceListList = tdsaAllShared->MainDeviceList.flink;
2404    while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2405    {
2406      oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2407      if (oneDeviceData == agNULL)
2408      {
2409        TI_DBG1(("tdssReportRemovals: oneDeviceData is NULL!!!\n"));
2410        return;
2411      }
2412      TI_DBG2(("tdssReportRemovals: loop did %d\n", oneDeviceData->id));
2413      TI_DBG2(("tdssReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2414      TI_DBG2(("tdssReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2415      TI_DBG2(("tdssReportRemovals: valid %d\n", oneDeviceData->valid));
2416      TI_DBG2(("tdssReportRemovals: valid2 %d\n", oneDeviceData->valid2));
2417      TI_DBG2(("tdssReportRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
2418      TI_DBG2(("tdssReportRemovals: registered %d\n", oneDeviceData->registered));
2419      if ( oneDeviceData->tdPortContext == onePortContext)
2420      {
2421        TI_DBG2(("tdssReportRemovals: right portcontext pid %d\n", onePortContext->id));
2422        if (oneDeviceData->valid == agTRUE && oneDeviceData->registered == agTRUE)
2423        {
2424          TI_DBG2(("tdssReportRemovals: removing\n"));
2425
2426          /* notify only reported devices to OS layer*/
2427          if ( DEVICE_IS_SSP_TARGET(oneDeviceData) ||
2428               DEVICE_IS_STP_TARGET(oneDeviceData) ||
2429               DEVICE_IS_SATA_DEVICE(oneDeviceData)
2430              )
2431          {
2432            removed = agTRUE;
2433          }
2434
2435          if ( (oneDeviceData->registered == agTRUE) &&
2436               ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData)
2437               || DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_SMP_TARGET(oneDeviceData) )
2438             )
2439          {
2440            /* all targets except expanders */
2441            TI_DBG2(("tdssReportRemovals: calling tdsaAbortAll\n"));
2442            TI_DBG2(("tdssReportRemovals: did %d\n", oneDeviceData->id));
2443            TI_DBG2(("tdssReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2444            TI_DBG2(("tdssReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2445            tdsaAbortAll(tiRoot, agRoot, oneDeviceData);
2446          }
2447          else if (oneDeviceData->registered == agTRUE)
2448          {
2449            /* expanders */
2450            TI_DBG1(("tdssReportRemovals: calling saDeregisterDeviceHandle, did %d\n", oneDeviceData->id));
2451            TI_DBG2(("tdssReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2452            TI_DBG2(("tdssReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2453            saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, 0);
2454          }
2455
2456          /* reset valid bit */
2457          oneDeviceData->valid = agFALSE;
2458          oneDeviceData->valid2 = agFALSE;
2459          oneDeviceData->registered = agFALSE;
2460          /* reset NumOfFCA */
2461          oneDeviceData->satDevData.NumOfFCA = 0;
2462
2463        }
2464        /* called by port invalid case */
2465        if (flag == agTRUE)
2466        {
2467          oneDeviceData->tdPortContext = agNULL;
2468          TI_DBG1(("tdssReportRemovals: nulling-out tdPortContext; oneDeviceData did %d\n", oneDeviceData->id));
2469        }
2470#ifdef REMOVED /* removed */
2471        /* directly attached SATA -> always remove it */
2472        if (oneDeviceData->DeviceType == TD_SATA_DEVICE &&
2473            oneDeviceData->directlyAttached == agTRUE)
2474        {
2475          TI_DBG1(("tdssReportRemovals: device did %d\n", oneDeviceData->id));
2476          TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
2477          TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceLis));
2478          DeviceListList = tdsaAllShared->MainDeviceList.flink;
2479          if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2480          {
2481            break;
2482          }
2483        }
2484        else
2485        {
2486          DeviceListList = DeviceListList->flink;
2487        }
2488#endif /* REMOVED */
2489        DeviceListList = DeviceListList->flink;
2490      }
2491      else
2492      {
2493        if (oneDeviceData->tdPortContext != agNULL)
2494        {
2495          TI_DBG2(("tdssReportRemovals: different portcontext; oneDeviceData->tdPortContext pid %d oneportcontext pid %d oneDeviceData did %d\n",
2496          oneDeviceData->tdPortContext->id, onePortContext->id, oneDeviceData->id));
2497        }
2498        else
2499        {
2500          TI_DBG1(("tdssReportRemovals: different portcontext; oneDeviceData->tdPortContext pid NULL oneportcontext pid %d oneDeviceData did %d\n",
2501          onePortContext->id, oneDeviceData->id));
2502        }
2503        DeviceListList = DeviceListList->flink;
2504      }
2505    }
2506
2507    if (removed == agTRUE)
2508    {
2509      TI_DBG2(("tdssReportRemovals: removed at the end\n"));
2510      ostiInitiatorEvent(
2511                         tiRoot,
2512                         onePortContext->tiPortalContext,
2513                         agNULL,
2514                         tiIntrEventTypeDeviceChange,
2515                         tiDeviceRemoval,
2516                         agNULL
2517                         );
2518    }
2519  } /* big else */
2520  return;
2521}
2522
2523/*
2524  changes valid and valid2 based on discovery type
2525*/
2526osGLOBAL void
2527tdssInternalRemovals(
2528                     agsaRoot_t           *agRoot,
2529                     tdsaPortContext_t    *onePortContext
2530                     )
2531{
2532  tdsaDeviceData_t  *oneDeviceData = agNULL;
2533  tdList_t          *DeviceListList;
2534  tdsaRootOsData_t  *osData = (tdsaRootOsData_t *)agRoot->osData;
2535  tiRoot_t          *tiRoot = (tiRoot_t *)osData->tiRoot;
2536  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
2537  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2538
2539  TI_DBG2(("tdssInternalRemovals: start\n"));
2540
2541  tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2542  if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2543  {
2544    tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2545    TI_DBG1(("tdssInternalRemovals: empty device list\n"));
2546    return;
2547  }
2548  else
2549  {
2550    tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2551  }
2552  DeviceListList = tdsaAllShared->MainDeviceList.flink;
2553  while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2554  {
2555    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2556    TI_DBG3(("tdssInternalRemovals: loop did %d\n", oneDeviceData->id));
2557    TI_DBG3(("tdssInternalRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2558    TI_DBG3(("tdssInternalRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2559    TI_DBG3(("tdssInternalRemovals: valid %d\n", oneDeviceData->valid));
2560    TI_DBG3(("tdssInternalRemovals: valid2 %d\n", oneDeviceData->valid2));
2561    TI_DBG3(("tdssInternalRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
2562    TI_DBG3(("tdssInternalRemovals: registered %d\n", oneDeviceData->registered));
2563    if ( oneDeviceData->tdPortContext == onePortContext)
2564    {
2565      TI_DBG3(("tdssInternalRemovals: right portcontext pid %d\n", onePortContext->id));
2566      if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_INCREMENTAL_START)
2567      {
2568        TI_DBG3(("tdssInternalRemovals: incremental discovery\n"));
2569        oneDeviceData->valid2 = agFALSE;
2570      }
2571      else
2572      {
2573        TI_DBG3(("tdssInternalRemovals: full discovery\n"));
2574        oneDeviceData->valid = agFALSE;
2575      }
2576      DeviceListList = DeviceListList->flink;
2577    }
2578    else
2579    {
2580      if (oneDeviceData->tdPortContext != agNULL)
2581      {
2582        TI_DBG3(("tdssInternalRemovals: different portcontext; oneDeviceData->tdPortContext pid %d oneportcontext pid %d\n", oneDeviceData->tdPortContext->id, onePortContext->id));
2583      }
2584      else
2585      {
2586        TI_DBG3(("tdssInternalRemovals: different portcontext; oneDeviceData->tdPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
2587      }
2588      DeviceListList = DeviceListList->flink;
2589    }
2590  }
2591
2592
2593  return;
2594}
2595
2596/* resets all valid and valid2 */
2597osGLOBAL void
2598tdssDiscoveryErrorRemovals(
2599                                 agsaRoot_t           *agRoot,
2600                                 tdsaPortContext_t    *onePortContext
2601                                 )
2602{
2603  tdsaDeviceData_t  *oneDeviceData = agNULL;
2604  tdList_t          *DeviceListList;
2605  tdsaRootOsData_t  *osData = (tdsaRootOsData_t *)agRoot->osData;
2606  tiRoot_t          *tiRoot = (tiRoot_t *)osData->tiRoot;
2607  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
2608  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2609
2610  TI_DBG1(("tdssDiscoveryErrorRemovals: start\n"));
2611
2612  tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2613  if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2614  {
2615    tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2616    TI_DBG1(("tdssDiscoveryErrorRemovals: empty device list\n"));
2617    return;
2618  }
2619  else
2620  {
2621    tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2622  }
2623  DeviceListList = tdsaAllShared->MainDeviceList.flink;
2624  while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2625  {
2626    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2627    TI_DBG2(("tdssDiscoveryErrorRemovals: loop did %d\n", oneDeviceData->id));
2628    TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2629    TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2630    TI_DBG2(("tdssDiscoveryErrorRemovals: valid %d\n", oneDeviceData->valid));
2631    TI_DBG2(("tdssDiscoveryErrorRemovals: valid2 %d\n", oneDeviceData->valid2));
2632    TI_DBG2(("tdssDiscoveryErrorRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
2633    TI_DBG2(("tdssDiscoveryErrorRemovals: registered %d\n", oneDeviceData->registered));
2634    if ( oneDeviceData->tdPortContext == onePortContext)
2635    {
2636      TI_DBG2(("tdssDiscoveryErrorRemovals: right portcontext pid %d\n", onePortContext->id));
2637      oneDeviceData->valid = agFALSE;
2638      oneDeviceData->valid2 = agFALSE;
2639      /* reset NumOfFCA */
2640      oneDeviceData->satDevData.NumOfFCA = 0;
2641
2642      if ( (oneDeviceData->registered == agTRUE) &&
2643           ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData)
2644           || DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_SMP_TARGET(oneDeviceData) )
2645         )
2646      {
2647        /* all targets other than expanders */
2648        TI_DBG2(("tdssDiscoveryErrorRemovals: calling tdsaAbortAll\n"));
2649        TI_DBG2(("tdssDiscoveryErrorRemovals: did %d\n", oneDeviceData->id));
2650        TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2651        TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2652        tdsaAbortAll(tiRoot, agRoot, oneDeviceData);
2653      }
2654      else if (oneDeviceData->registered == agTRUE)
2655      {
2656        /* expanders */
2657        TI_DBG2(("tdssDiscoveryErrorRemovals: calling saDeregisterDeviceHandle\n"));
2658        TI_DBG2(("tdssDiscoveryErrorRemovals: did %d\n", oneDeviceData->id));
2659        TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2660        TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2661        saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, 0);
2662      }
2663
2664      oneDeviceData->registered = agFALSE;
2665      DeviceListList = DeviceListList->flink;
2666    }
2667    else
2668    {
2669      if (oneDeviceData->tdPortContext != agNULL)
2670      {
2671        TI_DBG2(("tdssDiscoveryErrorRemovals: different portcontext; oneDeviceData->tdPortContext pid %d oneportcontext pid %d\n", oneDeviceData->tdPortContext->id, onePortContext->id));
2672      }
2673      else
2674      {
2675        TI_DBG2(("tdssDiscoveryErrorRemovals: different portcontext; oneDeviceData->tdPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
2676      }
2677      DeviceListList = DeviceListList->flink;
2678    }
2679  }
2680
2681
2682  return;
2683}
2684
2685/*****************************************************************************
2686*! \brief  tdsaSASDiscoverAbort
2687*
2688*  Purpose:  This function aborts on-going discovery.
2689*
2690*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
2691*                   instance.
2692*  \param   onePortContext: Pointer to the portal context instance.
2693*
2694*  \return:
2695*           None
2696*
2697*   \note:
2698*
2699*****************************************************************************/
2700/* this called when discovery is aborted
2701   aborted by whom
2702*/
2703osGLOBAL void
2704tdsaSASDiscoverAbort(
2705                    tiRoot_t             *tiRoot,
2706                    tdsaPortContext_t    *onePortContext
2707                    )
2708{
2709
2710  TI_DBG2(("tdsaSASDiscoverAbort: start\n"));
2711  TI_DBG2(("tdsaSASDiscoverAbort: pPort=%p  DONE\n", onePortContext));
2712  TI_DBG2(("tdsaSASDiscoverAbort: DiscoveryState %d\n", onePortContext->DiscoveryState));
2713
2714  onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
2715  /* clean up expanders data strucures; move to free exp when device is cleaned */
2716  tdsaCleanAllExp(tiRoot, onePortContext);
2717
2718  /* unregister devices */
2719  tdssReportRemovals(onePortContext->agRoot,
2720                     onePortContext,
2721                     agFALSE
2722                    );
2723}
2724
2725#ifdef AGTIAPI_CTL
2726
2727STATIC void
2728tdsaCTLNextDevice(
2729  tiRoot_t          *tiRoot,
2730  tdsaPortContext_t *onePortContext,
2731  tdIORequest_t     *tdIORequest,
2732  tdList_t          *DeviceList);
2733
2734STATIC void
2735tdsaCTLIOCompleted(
2736  agsaRoot_t      *agRoot,
2737  agsaIORequest_t *agIORequest,
2738  bit32           agIOStatus,
2739  bit32           agIOInfoLen,
2740  void            *agParam,
2741  bit16           sspTag,
2742  bit32           agOtherInfo)
2743{
2744  tiRoot_t          *tiRoot = (tiRoot_t*)
2745                      ((tdsaRootOsData_t*)agRoot->osData)->tiRoot;
2746  tdIORequestBody_t *tdIORequestBody;
2747  tdIORequest_t     *tdIORequest;
2748  tdsaDeviceData_t  *oneDeviceData;
2749
2750  tdIORequest = (tdIORequest_t *)agIORequest->osData;
2751  tdIORequestBody = &tdIORequest->tdIORequestBody;
2752  tdIORequestBody->ioCompleted = agTRUE;
2753  tdIORequestBody->ioStarted = agFALSE;
2754  oneDeviceData = (tdsaDeviceData_t *)tdIORequestBody->tiDevHandle->tdData;
2755
2756  TI_DBG6(("tdsaCTLIOCompleted: stat x%x len %d id %d\n", agIOStatus,
2757           agIOInfoLen, oneDeviceData->id));
2758
2759  //if ((agIOStatus == OSSA_IO_SUCCESS) && (agIOInfoLen == 0))
2760  /* SCSI command was completed OK, this is the normal path. */
2761  if (agIOInfoLen)
2762  {
2763    TI_DBG6(("tdsaCTLIOCompleted: SASDevAddr 0x%x / 0x%x PhyId 0x%x WARN "
2764             "setting CTL\n",
2765             oneDeviceData->SASAddressID.sasAddressHi,
2766             oneDeviceData->SASAddressID.sasAddressLo,
2767             oneDeviceData->SASAddressID.phyIdentifier));
2768    tdhexdump("tdsaCTLIOCompleted: response", (bit8 *)agParam, agIOInfoLen);
2769  }
2770
2771  tdsaCTLNextDevice(tiRoot, oneDeviceData->tdPortContext, tdIORequest,
2772                    oneDeviceData->MainLink.flink);
2773} /* tdsaCTLIOCompleted */
2774
2775STATIC int
2776tdsaCTLModeSelect(
2777  tiRoot_t                  *tiRoot,
2778  tiDeviceHandle_t          *tiDeviceHandle,
2779  tdIORequest_t             *tdIORequest)
2780{
2781  tiIORequest_t             *tiIORequest;
2782  tdsaDeviceData_t          *oneDeviceData;
2783  agsaRoot_t                *agRoot = agNULL;
2784  tdsaRoot_t                *tdsaRoot = (tdsaRoot_t*)tiRoot->tdData;
2785  tdsaContext_t             *tdsaAllShared = (tdsaContext_t*)
2786                              &tdsaRoot->tdsaAllShared;
2787  agsaIORequest_t           *agIORequest = agNULL;
2788  agsaDevHandle_t           *agDevHandle = agNULL;
2789  agsaSASRequestBody_t      *agSASRequestBody = agNULL;
2790  bit32                     tiStatus;
2791  bit32                     saStatus;
2792  tdIORequestBody_t         *tdIORequestBody;
2793  agsaSSPInitiatorRequest_t *agSSPInitiatorRequest;
2794  unsigned char             *virtAddr;
2795  tiSgl_t                   agSgl;
2796  static unsigned char      cdb[6] =
2797  {
2798    MODE_SELECT,
2799    PAGE_FORMAT,
2800    0,
2801    0,
2802    DR_MODE_PG_SZ
2803  };
2804
2805  virtAddr = (unsigned char*)tdIORequest->virtAddr;
2806  virtAddr[0] = DR_MODE_PG_CODE; /* Disconnect-Reconnect mode page code */
2807  virtAddr[1] = DR_MODE_PG_LENGTH; /* DR Mode pg length */
2808  virtAddr[8] = tdsaAllShared->SASConnectTimeLimit >> 8;
2809  virtAddr[9] = tdsaAllShared->SASConnectTimeLimit & 0xff;
2810
2811  oneDeviceData = (tdsaDeviceData_t*)tiDeviceHandle->tdData;
2812  TI_DBG4(("tdsaCTLModeSelect: id %d\n", oneDeviceData->id));
2813
2814  agRoot = oneDeviceData->agRoot;
2815  agDevHandle = oneDeviceData->agDevHandle;
2816  tiIORequest = &tdIORequest->tiIORequest;
2817
2818  tdIORequestBody = &tdIORequest->tdIORequestBody;
2819
2820  //tdIORequestBody->IOCompletionFunc = tdsaCTLIOCompleted;//itdssIOCompleted;
2821  tdIORequestBody->tiDevHandle = tiDeviceHandle;
2822  tdIORequestBody->IOType.InitiatorRegIO.expDataLength = DR_MODE_PG_SZ;
2823
2824  agIORequest = &tdIORequestBody->agIORequest;
2825  agIORequest->sdkData = agNULL; /* LL takes care of this */
2826
2827  agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody);
2828  agSSPInitiatorRequest = &(agSASRequestBody->sspInitiatorReq);
2829
2830  osti_memcpy(agSSPInitiatorRequest->sspCmdIU.cdb, cdb, 6);
2831  agSSPInitiatorRequest->dataLength = DR_MODE_PG_SZ;
2832
2833  agSSPInitiatorRequest->firstBurstSize = 0;
2834
2835  tdIORequestBody->agRequestType = AGSA_SSP_INIT_WRITE;
2836  tdIORequestBody->ioStarted = agTRUE;
2837  tdIORequestBody->ioCompleted = agFALSE;
2838
2839  agSgl.lower = BIT32_TO_LEBIT32(tdIORequest->physLower32);
2840#if (BITS_PER_LONG > 32)
2841  agSgl.upper = BIT32_TO_LEBIT32(tdIORequest->physUpper32);
2842#else
2843  agSgl1.upper = 0;
2844#endif
2845  agSgl.type = BIT32_TO_LEBIT32(tiSgl);
2846  agSgl.len = BIT32_TO_LEBIT32(DR_MODE_PG_SZ);
2847
2848  /* initializes "agsaSgl_t   agSgl" of "agsaDifSSPInitiatorRequest_t" */
2849  tiStatus = itdssIOPrepareSGL(tiRoot, tdIORequestBody, &agSgl,
2850                               tdIORequest->virtAddr);
2851  if (tiStatus != tiSuccess)
2852  {
2853    TI_DBG1(("tdsaCTLModeSelect: can't get SGL\n"));
2854    ostiFreeMemory(tiRoot, tdIORequest->osMemHandle2, DR_MODE_PG_SZ);
2855    ostiFreeMemory(tiRoot, tdIORequest->osMemHandle, sizeof(*tdIORequest));
2856    return tiError;
2857  }
2858
2859  saStatus = saSSPStart(agRoot, agIORequest,
2860                        tdsaRotateQnumber(tiRoot, oneDeviceData), agDevHandle,
2861                        AGSA_SSP_INIT_WRITE, agSASRequestBody, agNULL,
2862                        &tdsaCTLIOCompleted);
2863  if (saStatus == AGSA_RC_SUCCESS)
2864  {
2865    tiStatus = tiSuccess;
2866    TI_DBG4(("tdsaCTLModeSelect: saSSPStart OK\n"));
2867  }
2868  else
2869  {
2870    tdIORequestBody->ioStarted = agFALSE;
2871    tdIORequestBody->ioCompleted = agTRUE;
2872    if (saStatus == AGSA_RC_BUSY)
2873    {
2874      tiStatus = tiBusy;
2875      TI_DBG4(("tdsaCTLModeSelect: saSSPStart busy\n"));
2876    }
2877    else
2878    {
2879      tiStatus = tiError;
2880      TI_DBG4(("tdsaCTLModeSelect: saSSPStart Error\n"));
2881    }
2882    tdsaCTLNextDevice(tiRoot, oneDeviceData->tdPortContext, tdIORequest,
2883                      oneDeviceData->MainLink.flink);
2884  }
2885  return tiStatus;
2886} /* tdsaCTLModeSelect */
2887
2888STATIC void
2889tdsaCTLNextDevice(
2890  tiRoot_t          *tiRoot,
2891  tdsaPortContext_t *onePortContext,
2892  tdIORequest_t     *tdIORequest,
2893  tdList_t          *DeviceList)
2894{
2895  tdsaRoot_t        *tdsaRoot      = (tdsaRoot_t *)tiRoot->tdData;
2896  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2897  tdsaDeviceData_t  *oneDeviceData;
2898  tiIntrEventType_t eventType;
2899  bit32             eventStatus;
2900  int               rc;
2901
2902  /*
2903   * From the device list, returns only valid devices
2904   */
2905  for (; DeviceList && DeviceList != &(tdsaAllShared->MainDeviceList);
2906       DeviceList = DeviceList->flink)
2907  {
2908    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceList);
2909    TI_DBG6(("tdsaCTLNextDevice: devHandle %p\n",
2910             &(oneDeviceData->tiDeviceHandle)));
2911    if (oneDeviceData->tdPortContext != onePortContext)
2912      continue;
2913    if ((oneDeviceData->discovered == agFALSE) &&
2914        (oneDeviceData->registered == agTRUE) &&
2915        DEVICE_IS_SSP_TARGET(oneDeviceData) &&
2916        !DEVICE_IS_SSP_INITIATOR(oneDeviceData))
2917    {
2918      oneDeviceData->discovered = agTRUE;
2919      rc = tdsaCTLModeSelect(tiRoot, &oneDeviceData->tiDeviceHandle,
2920                              tdIORequest);
2921      TI_DBG1(("tdsaCTLNextDevice: ModeSelect ret %d\n", rc));
2922      return;
2923    }
2924  }
2925  TI_DBG2(("tdsaCTLNextDevice: no more devices found\n"));
2926
2927  eventType = tdIORequest->eventType;
2928  eventStatus = tdIORequest->eventStatus;
2929
2930  /* no more devices, free the memory */
2931  ostiFreeMemory(tiRoot, tdIORequest->osMemHandle2, DR_MODE_PG_SZ);
2932  ostiFreeMemory(tiRoot, tdIORequest->osMemHandle, sizeof(*tdIORequest));
2933
2934  /* send Discovery Done event */
2935  ostiInitiatorEvent(tiRoot, onePortContext->tiPortalContext, agNULL,
2936                     eventType, eventStatus, agNULL);
2937} /* tdsaCTLNextDevice */
2938
2939osGLOBAL void
2940tdsaCTLSet(
2941  tiRoot_t          *tiRoot,
2942  tdsaPortContext_t *onePortContext,
2943  tiIntrEventType_t eventType,
2944  bit32             eventStatus)
2945{
2946  tdsaRoot_t        *tdsaRoot      = (tdsaRoot_t *)tiRoot->tdData;
2947  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2948  tdIORequest_t     *tdIORequest;
2949  tdIORequestBody_t *tdIORequestBody;
2950  tiIORequest_t     *tiIORequest;
2951  bit32             memAllocStatus;
2952  void              *osMemHandle;
2953  bit32             physUpper32;
2954  bit32             physLower32;
2955
2956  TI_DBG2(("tdsaCTLSet: tiPortalContext pid %d etyp %x stat %x\n",
2957           onePortContext->id, eventType, eventStatus));
2958
2959  if (onePortContext->DiscoveryState != ITD_DSTATE_COMPLETED)
2960  {
2961    TI_DBG1(("tdsaCTLSet: discovery not completed\n"));
2962    return;
2963  }
2964
2965  /* use the same memory for all valid devices */
2966  memAllocStatus = ostiAllocMemory(tiRoot, &osMemHandle, (void **)&tdIORequest,
2967                                   &physUpper32, &physLower32, 8,
2968                                   sizeof(*tdIORequest), agTRUE);
2969  if (memAllocStatus != tiSuccess || tdIORequest == agNULL)
2970  {
2971    TI_DBG1(("tdsaCTLSet: ostiAllocMemory failed\n"));
2972    return;// tiError;
2973  }
2974  osti_memset(tdIORequest, 0, sizeof(*tdIORequest));
2975
2976  tdIORequest->osMemHandle = osMemHandle;
2977  tdIORequest->eventType = eventType;
2978  tdIORequest->eventStatus = eventStatus;
2979
2980  tiIORequest = &tdIORequest->tiIORequest;
2981  tdIORequestBody = &tdIORequest->tdIORequestBody;
2982  /* save context if we need to abort later */
2983  tiIORequest->tdData = tdIORequestBody;
2984
2985  tdIORequestBody->IOCompletionFunc = NULL;//itdssIOCompleted;
2986  tdIORequestBody->tiIORequest = tiIORequest;
2987  tdIORequestBody->IOType.InitiatorRegIO.expDataLength = 16;
2988
2989  tdIORequestBody->agIORequest.osData = (void *)tdIORequest; //tdIORequestBody;
2990
2991  memAllocStatus = ostiAllocMemory(tiRoot, &tdIORequest->osMemHandle2,
2992                                   (void **)&tdIORequest->virtAddr,
2993                                   &tdIORequest->physUpper32,
2994                                   &tdIORequest->physLower32,
2995                                   8, DR_MODE_PG_SZ, agFALSE);
2996  if (memAllocStatus != tiSuccess || tdIORequest == agNULL)
2997  {
2998    TI_DBG1(("tdsaCTLSet: ostiAllocMemory noncached failed\n"));
2999    ostiFreeMemory(tiRoot, tdIORequest->osMemHandle, sizeof(*tdIORequest));
3000    return;// tiError;
3001  }
3002
3003  osti_memset(tdIORequest->virtAddr, 0, DR_MODE_PG_SZ);
3004  tdsaCTLNextDevice(tiRoot, onePortContext, tdIORequest,
3005                    tdsaAllShared->MainDeviceList.flink);
3006} /* tdsaCTLSet*/
3007#endif
3008
3009/*****************************************************************************
3010*! \brief  tdsaSASDiscoverDone
3011*
3012*  Purpose:  This function called to finish up SAS discovery.
3013*
3014*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3015*                   instance.
3016*  \param   onePortContext: Pointer to the portal context instance.
3017*
3018*  \return:
3019*           None
3020*
3021*   \note:
3022*
3023*****************************************************************************/
3024osGLOBAL void
3025tdsaSASDiscoverDone(
3026                    tiRoot_t             *tiRoot,
3027                    tdsaPortContext_t    *onePortContext,
3028                    bit32                flag
3029                    )
3030{
3031#ifndef SATA_ENABLE
3032  tdsaRoot_t    *tdsaRoot = (tdsaRoot_t *)tiRoot->tdData;
3033  tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
3034#endif
3035
3036  TI_DBG3(("tdsaSASDiscoverDone: start\n"));
3037  TI_DBG3(("tdsaSASDiscoverDone: pPort=%p  DONE\n", onePortContext));
3038  TI_DBG3(("tdsaSASDiscoverDone: pid %d\n", onePortContext->id));
3039
3040  /* Set discovery status */
3041  onePortContext->discovery.status = DISCOVERY_SAS_DONE;
3042
3043#ifdef TD_INTERNAL_DEBUG /* debugging only */
3044  TI_DBG3(("tdsaSASDiscoverDone: BEFORE\n"));
3045  tdsaDumpAllExp(tiRoot, onePortContext, agNULL);
3046  tdsaDumpAllUpExp(tiRoot, onePortContext, agNULL);
3047#endif
3048
3049  /* clean up expanders data strucures; move to free exp when device is cleaned */
3050  tdsaCleanAllExp(tiRoot, onePortContext);
3051
3052#ifdef TD_INTERNAL_DEBUG /* debugging only */
3053  TI_DBG3(("tdsaSASDiscoverDone: AFTER\n"));
3054  tdsaDumpAllExp(tiRoot, onePortContext, agNULL);
3055  tdsaDumpAllUpExp(tiRoot, onePortContext, agNULL);
3056#endif
3057
3058
3059  /* call back to notify discovery is done */
3060  /* SATA is NOT enbled */
3061#ifndef SATA_ENABLE
3062  if (onePortContext->discovery.SeenBC == agTRUE)
3063  {
3064    TI_DBG3(("tdsaSASDiscoverDone: broadcast change; discover again\n"));
3065    tdssInternalRemovals(onePortContext->agRoot,
3066                         onePortContext
3067                         );
3068
3069    /* processed broadcast change */
3070    onePortContext->discovery.SeenBC = agFALSE;
3071    if (tdsaAllShared->ResetInDiscovery != 0 &&
3072        onePortContext->discovery.ResetTriggerred == agTRUE)
3073    {
3074      TI_DBG2(("tdsaSASDiscoverDone: tdsaBCTimer\n"));
3075      tdsaBCTimer(tiRoot, onePortContext);
3076    }
3077    else
3078    {
3079      tdsaDiscover(
3080                   tiRoot,
3081                   onePortContext,
3082                   TDSA_DISCOVERY_TYPE_SAS,
3083                   TDSA_DISCOVERY_OPTION_INCREMENTAL_START
3084                  );
3085    }
3086  }
3087  else
3088  {
3089    onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
3090
3091    if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
3092    {
3093      if (flag == tiSuccess)
3094      {
3095#ifdef AGTIAPI_CTL
3096        if (tdsaAllShared->SASConnectTimeLimit)
3097          tdsaCTLSet(tiRoot, onePortContext, tiIntrEventTypeDiscovery,
3098                     tiDiscOK);
3099        else
3100#endif
3101          ostiInitiatorEvent(
3102                             tiRoot,
3103                             onePortContext->tiPortalContext,
3104                             agNULL,
3105                             tiIntrEventTypeDiscovery,
3106                             tiDiscOK,
3107                             agNULL
3108                             );
3109      }
3110      else
3111      {
3112        TI_DBG1(("tdsaSASDiscoverDone: discovery failed\n"));
3113        tdssDiscoveryErrorRemovals(onePortContext->agRoot,
3114                                   onePortContext
3115                                   );
3116
3117        ostiInitiatorEvent(
3118                           tiRoot,
3119                           onePortContext->tiPortalContext,
3120                           agNULL,
3121                           tiIntrEventTypeDiscovery,
3122                           tiDiscFailed,
3123                           agNULL
3124                           );
3125      }
3126    }
3127    else
3128    {
3129      if (flag == tiSuccess)
3130      {
3131        tdssReportChanges(onePortContext->agRoot,
3132                          onePortContext
3133                          );
3134      }
3135      else
3136      {
3137        tdssReportRemovals(onePortContext->agRoot,
3138                           onePortContext,
3139                           agFALSE
3140                           );
3141      }
3142    }
3143  }
3144#ifdef TBD
3145  /* ACKing BC */
3146  tdsaAckBC(tiRoot, onePortContext);
3147#endif
3148
3149#endif
3150
3151#ifdef SATA_ENABLE
3152
3153  if (flag == tiSuccess)
3154  {
3155    TI_DBG3(("tdsaSASDiscoverDone: calling SATA discovery\n"));
3156    /*
3157       tdsaSATAFullDiscover() or tdsaincrementalDiscover()
3158       call sata discover
3159       when sata discover is done, call ostiInitiatorEvent
3160    */
3161    if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
3162    {
3163      TI_DBG3(("tdsaSASDiscoverDone: calling FULL SATA discovery\n"));
3164      tdsaDiscover(
3165                   tiRoot,
3166                   onePortContext,
3167                   AG_SA_DISCOVERY_TYPE_SATA,
3168                   TDSA_DISCOVERY_OPTION_FULL_START
3169                   );
3170    }
3171    else
3172    {
3173      TI_DBG3(("tdsaSASDiscoverDone: calling INCREMENTAL SATA discovery\n"));
3174      tdsaDiscover(
3175                   tiRoot,
3176                   onePortContext,
3177                   AG_SA_DISCOVERY_TYPE_SATA,
3178                   TDSA_DISCOVERY_OPTION_INCREMENTAL_START
3179                   );
3180    }
3181  }
3182  else
3183  {
3184    /* error case */
3185    TI_DBG1(("tdsaSASDiscoverDone: Error; clean up\n"));
3186    tdssDiscoveryErrorRemovals(onePortContext->agRoot,
3187                               onePortContext
3188                               );
3189
3190    onePortContext->discovery.SeenBC = agFALSE;
3191    onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
3192    ostiInitiatorEvent(
3193                       tiRoot,
3194                       onePortContext->tiPortalContext,
3195                       agNULL,
3196                       tiIntrEventTypeDiscovery,
3197                       tiDiscFailed,
3198                       agNULL
3199                       );
3200  }
3201#endif
3202  return;
3203}
3204
3205//temp only for testing
3206osGLOBAL void
3207tdsaReportManInfoSend(
3208                      tiRoot_t             *tiRoot,
3209                      tdsaDeviceData_t     *oneDeviceData
3210                      )
3211{
3212  agsaRoot_t            *agRoot;
3213
3214  agRoot = oneDeviceData->agRoot;
3215
3216  TI_DBG2(("tdsaReportManInfoSend: start\n"));
3217
3218  tdSMPStart(
3219             tiRoot,
3220             agRoot,
3221             oneDeviceData,
3222             SMP_REPORT_MANUFACTURE_INFORMATION,
3223             agNULL,
3224             0,
3225             AGSA_SMP_INIT_REQ,
3226             agNULL,
3227             0
3228             );
3229
3230  return;
3231}
3232
3233
3234osGLOBAL void
3235tdsaReportManInfoRespRcvd(
3236                          tiRoot_t              *tiRoot,
3237                          agsaRoot_t            *agRoot,
3238                          tdsaDeviceData_t      *oneDeviceData,
3239                          tdssSMPFrameHeader_t  *frameHeader,
3240                          agsaFrameHandle_t     frameHandle
3241                          )
3242{
3243  tdsaPortContext_t            *onePortContext;
3244  tdsaDiscovery_t              *discovery;
3245
3246  TI_DBG2(("tdsaReportManInfoRespRcvd: start\n"));
3247  TI_DBG2(("tdsaReportManInfoRespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3248  TI_DBG2(("tdsaReportManInfoRespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3249
3250  onePortContext = oneDeviceData->tdPortContext;
3251  discovery = &(onePortContext->discovery);
3252
3253  if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
3254  {
3255    TI_DBG2(("tdsaReportManInfoRespRcvd: SMP accepted\n"));
3256  }
3257  else
3258  {
3259    TI_DBG1(("tdsaReportManInfoRespRcvd: SMP NOT accepted; fn result 0x%x\n", frameHeader->smpFunctionResult));
3260  }
3261
3262  TI_DBG2(("tdsaReportManInfoRespRcvd: discovery retries %d\n", discovery->retries));
3263  discovery->retries++;
3264
3265  if (discovery->retries >= DISCOVERY_RETRIES)
3266  {
3267    TI_DBG1(("tdsaReportManInfoRespRcvd: retries are over\n"));
3268    discovery->retries = 0;
3269    /* failed the discovery */
3270  }
3271  else
3272  {
3273    TI_DBG1(("tdsaReportManInfoRespRcvd: keep retrying\n"));
3274    // start timer
3275    tdsaDiscoveryTimer(tiRoot, onePortContext, oneDeviceData);
3276  }
3277
3278  return;
3279}
3280
3281//end temp only for testing
3282
3283/*****************************************************************************
3284*! \brief  tdsaReportGeneralSend
3285*
3286*  Purpose:  This function sends Report General SMP to a device.
3287*
3288*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3289*                   instance.
3290*  \param   oneDeviceData: Pointer to the device data.
3291*
3292*  \return:
3293*           None
3294*
3295*   \note:
3296*
3297*****************************************************************************/
3298osGLOBAL void
3299tdsaReportGeneralSend(
3300                      tiRoot_t             *tiRoot,
3301                      tdsaDeviceData_t     *oneDeviceData
3302                      )
3303{
3304  agsaRoot_t            *agRoot;
3305
3306  agRoot = oneDeviceData->agRoot;
3307
3308  TI_DBG3(("tdsaReportGeneralSend: start\n"));
3309
3310  tdSMPStart(
3311             tiRoot,
3312             agRoot,
3313             oneDeviceData,
3314             SMP_REPORT_GENERAL,
3315             agNULL,
3316             0,
3317             AGSA_SMP_INIT_REQ,
3318             agNULL,
3319             0
3320             );
3321
3322  return;
3323}
3324
3325/*****************************************************************************
3326*! \brief  tdsaReportGeneralRespRcvd
3327*
3328*  Purpose:  This function processes Report General response.
3329*
3330*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3331*                   instance.
3332*  \param   agRoot: Pointer to chip/driver Instance.
3333*  \param   oneDeviceData: Pointer to the device data.
3334*  \param   frameHeader: Pointer to SMP frame header.
3335*  \param   frameHandle: A Handle used to refer to the response frame
3336*
3337*  \return:
3338*           None
3339*
3340*   \note:
3341*
3342*****************************************************************************/
3343osGLOBAL void
3344tdsaReportGeneralRespRcvd(
3345                          tiRoot_t              *tiRoot,
3346                          agsaRoot_t            *agRoot,
3347                          agsaIORequest_t       *agIORequest,
3348                          tdsaDeviceData_t      *oneDeviceData,
3349                          tdssSMPFrameHeader_t  *frameHeader,
3350                          agsaFrameHandle_t     frameHandle
3351                          )
3352{
3353  smpRespReportGeneral_t     tdSMPReportGeneralResp;
3354  smpRespReportGeneral_t    *ptdSMPReportGeneralResp;
3355  tdsaExpander_t            *oneExpander;
3356  tdsaPortContext_t         *onePortContext;
3357  tdsaDiscovery_t           *discovery;
3358#ifdef REMOVED
3359  bit32                      i;
3360#endif
3361#ifndef DIRECT_SMP
3362  tdssSMPRequestBody_t      *tdSMPRequestBody;
3363  tdSMPRequestBody = (tdssSMPRequestBody_t *)agIORequest->osData;
3364#endif
3365
3366  TI_DBG3(("tdsaReportGeneralRespRcvd: start\n"));
3367  TI_DBG3(("tdsaReportGeneralRespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3368  TI_DBG3(("tdsaReportGeneralRespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3369  ptdSMPReportGeneralResp = &tdSMPReportGeneralResp;
3370  osti_memset(&tdSMPReportGeneralResp, 0, sizeof(smpRespReportGeneral_t));
3371#ifdef DIRECT_SMP
3372  saFrameReadBlock(agRoot, frameHandle, 4, ptdSMPReportGeneralResp, sizeof(smpRespReportGeneral_t));
3373#else
3374  saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 4, ptdSMPReportGeneralResp, sizeof(smpRespReportGeneral_t));
3375#endif
3376
3377  //tdhexdump("tdsaReportGeneralRespRcvd", (bit8 *)ptdSMPReportGeneralResp, sizeof(smpRespReportGeneral_t));
3378#ifndef DIRECT_SMP
3379  ostiFreeMemory(
3380                 tiRoot,
3381                 tdSMPRequestBody->IndirectSMPReqosMemHandle,
3382                 tdSMPRequestBody->IndirectSMPReqLen
3383                );
3384  ostiFreeMemory(
3385                 tiRoot,
3386                 tdSMPRequestBody->IndirectSMPResposMemHandle,
3387                 tdSMPRequestBody->IndirectSMPRespLen
3388                );
3389#endif
3390
3391  onePortContext = oneDeviceData->tdPortContext;
3392  discovery = &(onePortContext->discovery);
3393
3394  if (onePortContext->valid == agFALSE)
3395  {
3396    TI_DBG1(("tdsaReportGeneralRespRcvd: aborting discovery\n"));
3397    tdsaSASDiscoverAbort(tiRoot, onePortContext);
3398    return;
3399  }
3400  if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
3401  {
3402    oneDeviceData->numOfPhys = (bit8) ptdSMPReportGeneralResp->numOfPhys;
3403    oneExpander = oneDeviceData->tdExpander;
3404    oneExpander->routingIndex = (bit16) REPORT_GENERAL_GET_ROUTEINDEXES(ptdSMPReportGeneralResp);
3405#ifdef REMOVED
3406    for ( i = 0; i < oneDeviceData->numOfPhys; i++ )
3407    {
3408      oneExpander->currentIndex[i] = 0;
3409    }
3410#endif
3411    oneExpander->configReserved = 0;
3412    oneExpander->configRouteTable = REPORT_GENERAL_IS_CONFIGURABLE(ptdSMPReportGeneralResp) ? 1 : 0;
3413    oneExpander->configuring = REPORT_GENERAL_IS_CONFIGURING(ptdSMPReportGeneralResp) ? 1 : 0;
3414    TI_DBG3(("tdsaReportGeneralRespRcvd: oneExpander=%p numberofPhys=0x%x RoutingIndex=0x%x\n",
3415      oneExpander, oneDeviceData->numOfPhys, oneExpander->routingIndex));
3416    TI_DBG3(("tdsaReportGeneralRespRcvd: configRouteTable=%d configuring=%d\n",
3417      oneExpander->configRouteTable, oneExpander->configuring));
3418    if (oneExpander->configuring == 1)
3419    {
3420      discovery->retries++;
3421      if (discovery->retries >= DISCOVERY_RETRIES)
3422      {
3423        TI_DBG1(("tdsaReportGeneralRespRcvd: retries are over\n"));
3424        discovery->retries = 0;
3425        /* failed the discovery */
3426        tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3427      }
3428      else
3429      {
3430        TI_DBG1(("tdsaReportGeneralRespRcvd: keep retrying\n"));
3431        // start timer for sending ReportGeneral
3432        tdsaDiscoveryTimer(tiRoot, onePortContext, oneDeviceData);
3433      }
3434    }
3435    else
3436    {
3437      discovery->retries = 0;
3438      tdsaDiscoverSend(tiRoot, oneDeviceData);
3439    }
3440  }
3441  else
3442  {
3443     TI_DBG1(("tdsaReportGeneralRespRcvd: SMP failed; fn result 0x%x; stopping discovery\n", frameHeader->smpFunctionResult));
3444     tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3445  }
3446  return;
3447}
3448
3449
3450/*****************************************************************************
3451*! \brief  tdsaDiscoverSend
3452*
3453*  Purpose:  This function sends Discovery SMP to a device.
3454*
3455*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3456*                   instance.
3457*  \param   oneDeviceData: Pointer to the device data.
3458*
3459*  \return:
3460*           None
3461*
3462*   \note:
3463*
3464*****************************************************************************/
3465osGLOBAL void
3466tdsaDiscoverSend(
3467                 tiRoot_t             *tiRoot,
3468                 tdsaDeviceData_t     *oneDeviceData
3469                 )
3470{
3471  agsaRoot_t            *agRoot;
3472  tdsaExpander_t        *oneExpander;
3473  smpReqDiscover_t      smpDiscoverReq;
3474
3475  TI_DBG3(("tdsaDiscoverSend: start\n"));
3476  TI_DBG3(("tdsaDiscoverSend: device %p did %d\n", oneDeviceData, oneDeviceData->id));
3477  agRoot = oneDeviceData->agRoot;
3478  oneExpander = oneDeviceData->tdExpander;
3479  TI_DBG3(("tdsaDiscoverSend: phyID 0x%x\n", oneExpander->discoveringPhyId));
3480
3481
3482  osti_memset(&smpDiscoverReq, 0, sizeof(smpReqDiscover_t));
3483
3484  smpDiscoverReq.reserved1 = 0;
3485  smpDiscoverReq.reserved2 = 0;
3486  smpDiscoverReq.phyIdentifier = oneExpander->discoveringPhyId;
3487  smpDiscoverReq.reserved3 = 0;
3488
3489
3490  tdSMPStart(
3491             tiRoot,
3492             agRoot,
3493             oneDeviceData,
3494             SMP_DISCOVER,
3495             (bit8 *)&smpDiscoverReq,
3496             sizeof(smpReqDiscover_t),
3497             AGSA_SMP_INIT_REQ,
3498             agNULL,
3499             0
3500             );
3501  return;
3502}
3503
3504
3505/*****************************************************************************
3506*! \brief  tdsaDiscoverRespRcvd
3507*
3508*  Purpose:  This function processes Discovery response.
3509*
3510*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3511*                   instance.
3512*  \param   agRoot: Pointer to chip/driver Instance.
3513*  \param   oneDeviceData: Pointer to the device data.
3514*  \param   frameHeader: Pointer to SMP frame header.
3515*  \param   frameHandle: A Handle used to refer to the response frame
3516*
3517*  \return:
3518*           None
3519*
3520*   \note:
3521*
3522*****************************************************************************/
3523osGLOBAL void
3524tdsaDiscoverRespRcvd(
3525                     tiRoot_t              *tiRoot,
3526                     agsaRoot_t            *agRoot,
3527                     agsaIORequest_t       *agIORequest,
3528                     tdsaDeviceData_t      *oneDeviceData,
3529                     tdssSMPFrameHeader_t  *frameHeader,
3530                     agsaFrameHandle_t     frameHandle
3531                     )
3532{
3533  smpRespDiscover_t   *ptdSMPDiscoverResp;
3534  tdsaPortContext_t   *onePortContext;
3535  tdsaExpander_t      *oneExpander;
3536  tdsaDiscovery_t     *discovery;
3537#ifndef DIRECT_SMP
3538  tdssSMPRequestBody_t *tdSMPRequestBody;
3539#endif
3540
3541  TI_DBG3(("tdsaDiscoverRespRcvd: start\n"));
3542  TI_DBG3(("tdsaDiscoverRespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3543  TI_DBG3(("tdsaDiscoverRespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3544
3545
3546  onePortContext = oneDeviceData->tdPortContext;
3547  oneExpander = oneDeviceData->tdExpander;
3548  discovery = &(onePortContext->discovery);
3549#ifndef DIRECT_SMP
3550  tdSMPRequestBody = (tdssSMPRequestBody_t *)agIORequest->osData;
3551#endif
3552
3553  if (onePortContext->valid == agFALSE)
3554  {
3555    TI_DBG1(("tdsaDiscoverRespRcvd: aborting discovery\n"));
3556    tdsaSASDiscoverAbort(tiRoot, onePortContext);
3557    return;
3558  }
3559  ptdSMPDiscoverResp = &(discovery->SMPDiscoverResp);
3560#ifdef DIRECT_SMP
3561  saFrameReadBlock(agRoot, frameHandle, 4, ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
3562#else
3563  saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 4, ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
3564#endif
3565  //tdhexdump("tdsaDiscoverRespRcvd", (bit8 *)ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
3566
3567#ifndef DIRECT_SMP
3568  ostiFreeMemory(
3569                 tiRoot,
3570                 tdSMPRequestBody->IndirectSMPReqosMemHandle,
3571                 tdSMPRequestBody->IndirectSMPReqLen
3572                );
3573  ostiFreeMemory(
3574                 tiRoot,
3575                 tdSMPRequestBody->IndirectSMPResposMemHandle,
3576                 tdSMPRequestBody->IndirectSMPRespLen
3577                );
3578#endif
3579
3580  if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
3581  {
3582    if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3583    {
3584      tdsaSASUpStreamDiscoverExpanderPhy(tiRoot, onePortContext, oneExpander, ptdSMPDiscoverResp);
3585    }
3586    else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
3587    {
3588      tdsaSASDownStreamDiscoverExpanderPhy(tiRoot, onePortContext, oneExpander, ptdSMPDiscoverResp);
3589    }
3590    else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING)
3591    {
3592      /* not done with configuring routing
3593         1. set the timer
3594         2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy()
3595      */
3596      TI_DBG2(("tdsaDiscoverRespRcvd: still configuring routing; setting timer\n"));
3597      TI_DBG2(("tdsaDiscoverRespRcvd: onePortContext %p oneDeviceData %p ptdSMPDiscoverResp %p\n", onePortContext, oneDeviceData, ptdSMPDiscoverResp));
3598      tdhexdump("tdsaDiscoverRespRcvd", (bit8*)ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
3599
3600      tdsaConfigureRouteTimer(tiRoot, onePortContext, oneExpander, ptdSMPDiscoverResp);
3601    }
3602    else
3603    {
3604      /* nothing */
3605    }
3606  }
3607  else if (frameHeader->smpFunctionResult == PHY_VACANT)
3608  {
3609    TI_DBG3(("tdsaDiscoverRespRcvd: smpFunctionResult is PHY_VACANT, phyid %d\n",
3610    oneExpander->discoveringPhyId));
3611    if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3612    {
3613      tdsaSASUpStreamDiscoverExpanderPhySkip(tiRoot, onePortContext, oneExpander);
3614    }
3615    else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
3616    {
3617      tdsaSASDownStreamDiscoverExpanderPhySkip(tiRoot, onePortContext, oneExpander);
3618    }
3619    else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING)
3620    {
3621      /* not done with configuring routing
3622         1. set the timer
3623         2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy()
3624      */
3625      TI_DBG1(("tdsaDiscoverRespRcvd: still configuring routing; setting timer\n"));
3626      TI_DBG1(("tdsaDiscoverRespRcvd: onePortContext %p oneDeviceData %p ptdSMPDiscoverResp %p\n", onePortContext, oneDeviceData, ptdSMPDiscoverResp));
3627      tdhexdump("tdsaDiscoverRespRcvd", (bit8*)ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
3628
3629      tdsaConfigureRouteTimer(tiRoot, onePortContext, oneExpander, ptdSMPDiscoverResp);
3630    }
3631  }
3632  else
3633  {
3634    TI_DBG1(("tdsaDiscoverRespRcvd: Discovery Error SMP function return result error=%x\n",
3635             frameHeader->smpFunctionResult));
3636     tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3637  }
3638  return;
3639}
3640
3641/*****************************************************************************
3642*! \brief  tdsaSASUpStreamDiscoverExpanderPhy
3643*
3644*  Purpose:  This function actully does upstream traverse and finds out detailed
3645*            information about topology.
3646*
3647*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3648*                   instance.
3649*  \param   onePortContext: Pointer to the portal context instance.
3650*  \param   oneExpander: Pointer to the expander data.
3651*  \param   pDiscoverResp: Pointer to the Discovery SMP respsonse.
3652*
3653*  \return:
3654*           None
3655*
3656*   \note:
3657*
3658*****************************************************************************/
3659osGLOBAL void
3660tdsaSASUpStreamDiscoverExpanderPhy(
3661                                   tiRoot_t              *tiRoot,
3662                                   tdsaPortContext_t     *onePortContext,
3663                                   tdsaExpander_t        *oneExpander,
3664                                   smpRespDiscover_t     *pDiscoverResp
3665                                   )
3666{
3667  tdsaDeviceData_t        *oneDeviceData;
3668  tdsaDeviceData_t        *AttachedDevice = agNULL;
3669  tdsaExpander_t          *AttachedExpander;
3670  agsaSASIdentify_t       sasIdentify;
3671  bit8                    connectionRate;
3672  bit32                   attachedSasHi, attachedSasLo;
3673  tdsaSASSubID_t          agSASSubID;
3674
3675  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: start\n"));
3676  if (onePortContext->valid == agFALSE)
3677  {
3678    TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: aborting discovery\n"));
3679    tdsaSASDiscoverAbort(tiRoot, onePortContext);
3680    return;
3681  }
3682
3683  oneDeviceData = oneExpander->tdDevice;
3684  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n",
3685           oneExpander->discoveringPhyId,
3686           oneDeviceData->SASAddressID.sasAddressHi,
3687           oneDeviceData->SASAddressID.sasAddressLo));
3688  TI_DBG3(("   Attached device: %s\n",
3689           ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" :
3690             (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" :
3691              (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
3692
3693  if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
3694  {
3695    TI_DBG3(("   SAS address    : %08x-%08x\n",
3696      DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp),
3697              DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
3698    TI_DBG3(("   SSP Target     : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
3699    TI_DBG3(("   STP Target     : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
3700    TI_DBG3(("   SMP Target     : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
3701    TI_DBG3(("   SATA DEVICE    : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
3702    TI_DBG3(("   SSP Initiator  : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
3703    TI_DBG3(("   STP Initiator  : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
3704    TI_DBG3(("   SMP Initiator  : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
3705    TI_DBG3(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
3706    TI_DBG3(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
3707  }
3708  /* end for debugging */
3709
3710  /* for debugging */
3711  if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
3712  {
3713    TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n"));
3714    TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
3715    tdhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
3716    tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3717    return;
3718  }
3719
3720  /* saving routing attribute for non self-configuring expanders */
3721  oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
3722
3723  /* for debugging */
3724//  dumpRoutingAttributes(tiRoot, oneExpander, pDiscoverResp->phyIdentifier);
3725
3726  if ( oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE )
3727  {
3728    TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_FANOUT_EXPANDER\n"));
3729    if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
3730    {
3731      TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing on fanout expander device\n"));
3732
3733      /* discovery error */
3734      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
3735        = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
3736      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
3737        = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
3738      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
3739
3740      /* (2.1.3) discovery done */
3741      tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3742      return;
3743    }
3744  }
3745  else
3746  {
3747    TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_EDGE_EXPANDER\n"));
3748
3749    if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
3750    {
3751      /* Setup sasIdentify for the attached device */
3752      sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
3753      sasIdentify.deviceType_addressFrameType = (bit8)(pDiscoverResp->attachedDeviceType & 0x70);
3754      sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
3755      sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
3756      *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
3757      *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
3758
3759      /* incremental discovery */
3760      agSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
3761      agSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
3762      agSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
3763      agSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
3764
3765      attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
3766      attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
3767
3768      /* If the phy has subtractive routing attribute */
3769      if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
3770      {
3771        TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: SA_SAS_ROUTING_SUBTRACTIVE\n"));
3772        /* Setup upstream phys */
3773        tdsaSASExpanderUpStreamPhyAdd(tiRoot, oneExpander, (bit8) pDiscoverResp->attachedPhyIdentifier);
3774        /* If the expander already has an upsteam device set up */
3775        if (oneExpander->hasUpStreamDevice == agTRUE)
3776        {
3777          /* If the sas address doesn't match */
3778          if ( ((oneExpander->upStreamSASAddressHi != attachedSasHi) ||
3779                (oneExpander->upStreamSASAddressLo != attachedSasLo)) &&
3780               (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
3781                DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
3782              )
3783          {
3784            /* TODO: discovery error, callback */
3785            TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address\n"));
3786            /* call back to notify discovery error */
3787            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
3788              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
3789            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
3790              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
3791            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
3792            /* discovery done */
3793            tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3794          }
3795        }
3796        else
3797        {
3798          /* Setup SAS address for up stream device */
3799          oneExpander->hasUpStreamDevice = agTRUE;
3800          oneExpander->upStreamSASAddressHi = attachedSasHi;
3801          oneExpander->upStreamSASAddressLo = attachedSasLo;
3802
3803          if ( (onePortContext->sasLocalAddressHi != attachedSasHi)
3804              || (onePortContext->sasLocalAddressLo != attachedSasLo) )
3805          {
3806            /* Find the device from the discovered list */
3807            AttachedDevice = tdsaPortSASDeviceFind(tiRoot, onePortContext, attachedSasLo, attachedSasHi);
3808            /* If the device has been discovered before */
3809            if ( AttachedDevice != agNULL)
3810            {
3811              TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Seen This Device Before\n"));
3812              /* If attached device is an edge expander */
3813              if ( AttachedDevice->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
3814              {
3815                /* The attached device is an expander */
3816                AttachedExpander = AttachedDevice->tdExpander;
3817                /* If the two expanders are the root of the two edge expander sets */
3818                if ( (AttachedExpander->upStreamSASAddressHi ==
3819                      DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
3820                     && (AttachedExpander->upStreamSASAddressLo ==
3821                        DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)) )
3822                {
3823                  /* Setup upstream expander for the pExpander */
3824                  oneExpander->tdUpStreamExpander = AttachedExpander;
3825                }
3826                /* If the two expanders are not the root of the two edge expander sets */
3827                else
3828                {
3829                  /* TODO: loop found, discovery error, callback */
3830                  TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: **** Topology Error loop detection\n"));
3831                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
3832                    = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
3833                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
3834                    = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
3835                  onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
3836                  /* discovery done */
3837                  tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3838                }
3839              }
3840              /* If attached device is not an edge expander */
3841              else
3842              {
3843                /*TODO: should not happen, ASSERT */
3844                TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy, *** Attached Device is not Edge. Confused!!\n"));
3845              }
3846            }
3847            /* If the device has not been discovered before */
3848            else
3849            {
3850              /* Add the device */
3851              TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: New device\n"));
3852              /* read minimum rate from the configuration
3853                 onePortContext->LinkRate is SPC's local link rate
3854              */
3855              connectionRate = (bit8)(MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)));
3856              TI_DBG3(("siSASUpStreamDiscoverExpanderPhy: link rate 0x%x\n", onePortContext->LinkRate));
3857              TI_DBG3(("siSASUpStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp)));
3858              TI_DBG3(("siSASUpStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate));
3859              //hhhhhhhh
3860              if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
3861              {
3862                /* incremental discovery */
3863                if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
3864                {
3865                  AttachedDevice = tdsaPortSASDeviceAdd(
3866                                                    tiRoot,
3867                                                    onePortContext,
3868                                                    sasIdentify,
3869                                                    agFALSE,
3870                                                    connectionRate,
3871                                                    IT_NEXUS_TIMEOUT,
3872                                                    0,
3873                                                    STP_DEVICE_TYPE,
3874                                                    oneDeviceData,
3875                                                    pDiscoverResp->phyIdentifier
3876                                                    );
3877                }
3878                else
3879                {
3880                  /* incremental discovery */
3881                  AttachedDevice = tdsaFindRegNValid(
3882                                                     onePortContext->agRoot,
3883                                                     onePortContext,
3884                                                     &agSASSubID
3885                                                     );
3886                  /* not registered and not valid; add this*/
3887                  if (AttachedDevice == agNULL)
3888                  {
3889                    AttachedDevice = tdsaPortSASDeviceAdd(
3890                                                    tiRoot,
3891                                                    onePortContext,
3892                                                    sasIdentify,
3893                                                    agFALSE,
3894                                                    connectionRate,
3895                                                    IT_NEXUS_TIMEOUT,
3896                                                    0,
3897                                                    STP_DEVICE_TYPE,
3898                                                    oneDeviceData,
3899                                                    pDiscoverResp->phyIdentifier
3900                                                    );
3901                  }
3902                }
3903              }
3904              else
3905              {
3906                /* incremental discovery */
3907                if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
3908                {
3909                  AttachedDevice = tdsaPortSASDeviceAdd(
3910                                                    tiRoot,
3911                                                    onePortContext,
3912                                                    sasIdentify,
3913                                                    agFALSE,
3914                                                    connectionRate,
3915                                                    IT_NEXUS_TIMEOUT,
3916                                                    0,
3917                                                    SAS_DEVICE_TYPE,
3918                                                    oneDeviceData,
3919                                                    pDiscoverResp->phyIdentifier
3920                                                    );
3921                }
3922                else
3923                {
3924                  /* incremental discovery */
3925                  AttachedDevice = tdsaFindRegNValid(
3926                                                     onePortContext->agRoot,
3927                                                     onePortContext,
3928                                                     &agSASSubID
3929                                                     );
3930                  /* not registered and not valid; add this*/
3931                  if (AttachedDevice == agNULL)
3932                  {
3933                    AttachedDevice = tdsaPortSASDeviceAdd(
3934                                                    tiRoot,
3935                                                    onePortContext,
3936                                                    sasIdentify,
3937                                                    agFALSE,
3938                                                    connectionRate,
3939                                                    IT_NEXUS_TIMEOUT,
3940                                                    0,
3941                                                    SAS_DEVICE_TYPE,
3942                                                    oneDeviceData,
3943                                                    pDiscoverResp->phyIdentifier
3944                                                    );
3945                  }
3946                }
3947              }
3948              /* If the device is added successfully */
3949              if ( AttachedDevice != agNULL)
3950              {
3951
3952                 /* (3.1.2.3.2.3.2.1) callback about new device */
3953                if ( DISCRSP_IS_SSP_TARGET(pDiscoverResp)
3954                    || DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)
3955                    || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)
3956                    || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) )
3957                {
3958                  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Found SSP/SMP SAS %08x-%08x\n",
3959                      attachedSasHi, attachedSasLo));
3960                }
3961                else
3962                {
3963                  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Found a SAS STP device.\n"));
3964                }
3965                 /* If the attached device is an expander */
3966                if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
3967                    || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) )
3968                {
3969                  /* Allocate an expander data structure */
3970                  AttachedExpander = tdssSASDiscoveringExpanderAlloc(
3971                                                                     tiRoot,
3972                                                                     onePortContext,
3973                                                                     AttachedDevice
3974                                                                     );
3975
3976                  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Found expander=%p\n", AttachedExpander));
3977                  /* If allocate successfully */
3978                  if ( AttachedExpander != agNULL)
3979                  {
3980                    /* Add the pAttachedExpander to discovering list */
3981                    tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, AttachedExpander);
3982                    /* Setup upstream expander for the pExpander */
3983                    oneExpander->tdUpStreamExpander = AttachedExpander;
3984                  }
3985                  /* If failed to allocate */
3986                  else
3987                  {
3988                    TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy, Failed to allocate expander data structure\n"));
3989                    tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3990                  }
3991                }
3992                /* If the attached device is an end device */
3993                else
3994                {
3995                  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Found end device\n"));
3996                  /* LP2006-05-26 added upstream device to the newly found device */
3997                  AttachedDevice->tdExpander = oneExpander;
3998                  oneExpander->tdUpStreamExpander = agNULL;
3999                }
4000              }
4001              else
4002              {
4003                TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy, Failed to add a device\n"));
4004                tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4005              }
4006            }
4007          }
4008        }
4009      } /* substractive routing */
4010    }
4011  }
4012
4013
4014   oneExpander->discoveringPhyId ++;
4015   if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
4016     {
4017       if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
4018       {
4019         TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM find more ...\n"));
4020         /* continue discovery for the next phy */
4021         tdsaDiscoverSend(tiRoot, oneDeviceData);
4022       }
4023       else
4024       {
4025         TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM last phy continue upstream..\n"));
4026
4027         /* remove the expander from the discovering list */
4028         tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, oneExpander);
4029         /* continue upstream discovering */
4030         tdsaSASUpStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
4031       }
4032   }
4033   else
4034   {
4035      TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));
4036
4037   }
4038
4039  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
4040
4041  return;
4042}
4043
4044// for debugging only
4045osGLOBAL tdsaExpander_t *
4046tdsaFindUpStreamConfigurableExp(tiRoot_t              *tiRoot,
4047                                                                tdsaExpander_t        *oneExpander)
4048{
4049  tdsaExpander_t    *ret=agNULL;
4050  tdsaExpander_t    *UpsreamExpander = oneExpander->tdUpStreamExpander;
4051
4052  TI_DBG3(("tdsaFindUpStreamConfigurableExp: start\n"));
4053  TI_DBG3(("tdsaFindUpStreamConfigurableExp: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4054  TI_DBG3(("tdsaFindUpStreamConfigurableExp: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4055
4056
4057  if (UpsreamExpander)
4058  {
4059    TI_DBG3(("tdsaFindUpStreamConfigurableExp: NO upsream expander\n"));
4060  }
4061  else
4062  {
4063    while (UpsreamExpander)
4064    {
4065      TI_DBG3(("tdsaFindUpStreamConfigurableExp: exp addrHi 0x%08x\n", UpsreamExpander->tdDevice->SASAddressID.sasAddressHi));
4066      TI_DBG3(("tdsaFindUpStreamConfigurableExp: exp addrLo 0x%08x\n", UpsreamExpander->tdDevice->SASAddressID.sasAddressLo));
4067
4068      UpsreamExpander = UpsreamExpander->tdUpStreamExpander;
4069    }
4070  }
4071  return ret;
4072}
4073
4074/*****************************************************************************
4075*! \brief  tdsaSASUpStreamDiscoverExpanderPhySkip
4076*
4077*  Purpose:  This function skips a phy which returned PHY_VACANT in SMP
4078*            response in upstream
4079*
4080*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4081*                   instance.
4082*  \param   onePortContext: Pointer to the portal context instance.
4083*  \param   oneExpander: Pointer to the expander data.
4084*
4085*  \return:
4086*           None
4087*
4088*   \note:
4089*
4090*****************************************************************************/
4091osGLOBAL void
4092tdsaSASUpStreamDiscoverExpanderPhySkip(
4093                                   tiRoot_t              *tiRoot,
4094                                   tdsaPortContext_t     *onePortContext,
4095                                   tdsaExpander_t        *oneExpander
4096                                   )
4097{
4098  tdsaDeviceData_t        *oneDeviceData;
4099  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: start\n"));
4100  oneDeviceData = oneExpander->tdDevice;
4101
4102  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
4103  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
4104
4105  oneExpander->discoveringPhyId ++;
4106  if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
4107  {
4108    if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
4109    {
4110      TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: More Phys to discover\n"));
4111      /* continue discovery for the next phy */
4112      tdsaDiscoverSend(tiRoot, oneDeviceData);
4113    }
4114    else
4115    {
4116       TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: No More Phys\n"));
4117
4118       /* remove the expander from the discovering list */
4119       tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, oneExpander);
4120       /* continue upstream discovering */
4121       tdsaSASUpStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
4122     }
4123  }
4124  else
4125  {
4126    TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));
4127
4128  }
4129
4130  TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
4131
4132
4133  return;
4134}
4135
4136
4137// for debugging only
4138osGLOBAL tdsaExpander_t *
4139tdsaFindDownStreamConfigurableExp(tiRoot_t              *tiRoot,
4140                                                                  tdsaExpander_t        *oneExpander)
4141{
4142  tdsaExpander_t  *ret=agNULL;
4143  tdsaExpander_t  *DownsreamExpander = oneExpander->tdCurrentDownStreamExpander;
4144
4145  TI_DBG3(("tdsaFindDownStreamConfigurableExp: start\n"));
4146  TI_DBG3(("tdsaFindDownStreamConfigurableExp: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4147  TI_DBG3(("tdsaFindDownStreamConfigurableExp: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4148
4149
4150  if (DownsreamExpander)
4151  {
4152    TI_DBG3(("tdsaFindDownStreamConfigurableExp: NO downsream expander\n"));
4153  }
4154  else
4155  {
4156    while (DownsreamExpander)
4157    {
4158      TI_DBG3(("tdsaFindDownStreamConfigurableExp: exp addrHi 0x%08x\n", DownsreamExpander->tdDevice->SASAddressID.sasAddressHi));
4159      TI_DBG3(("tdsaFindDownStreamConfigurableExp: exp addrLo 0x%08x\n", DownsreamExpander->tdDevice->SASAddressID.sasAddressLo));
4160
4161      DownsreamExpander = DownsreamExpander->tdCurrentDownStreamExpander;
4162    }
4163  }
4164  return ret;
4165}
4166
4167// for debugging only
4168osGLOBAL void
4169dumpRoutingAttributes(
4170                      tiRoot_t                 *tiRoot,
4171                      tdsaExpander_t           *oneExpander,
4172                      bit8                     phyID
4173                      )
4174{
4175  bit32 i;
4176
4177  TI_DBG3(("dumpRoutingAttributes: start\n"));
4178  TI_DBG3(("dumpRoutingAttributes: phyID %d\n", phyID));
4179  TI_DBG3(("dumpRoutingAttributes: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4180  TI_DBG3(("dumpRoutingAttributes: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4181
4182  for(i=0;i <= ((bit32)phyID + 1); i++)
4183  {
4184    TI_DBG3(("dumpRoutingAttributes: index %d routing attribute %d\n", i, oneExpander->routingAttribute[i]));
4185  }
4186  return;
4187}
4188
4189/*****************************************************************************
4190*! \brief  tdsaDumpAllExp
4191*
4192*  Purpose:  This function prints out all expanders seen by discovery.
4193*
4194*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4195*                   instance.
4196*  \param   onePortContext: Pointer to the portal context instance.
4197*  \param   oneExpander: Pointer to the expander data.
4198*
4199*  \return:
4200*           None
4201*
4202*   \note: For debugging only
4203*
4204*****************************************************************************/
4205osGLOBAL void
4206tdsaDumpAllExp(
4207               tiRoot_t                 *tiRoot,
4208               tdsaPortContext_t        *onePortContext,
4209               tdsaExpander_t           *oneExpander
4210              )
4211{
4212#if 0 /* for debugging only */
4213  tdList_t          *ExpanderList;
4214  tdsaExpander_t    *tempExpander;
4215  tdsaExpander_t    *UpsreamExpander;
4216  tdsaExpander_t    *DownsreamExpander;
4217  tdsaPortContext_t *tmpOnePortContext = onePortContext;
4218
4219  TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: start\n"));
4220  TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: onePortcontext %p oneExpander %p\n", onePortContext, oneExpander));
4221
4222  /* debugging */
4223  tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
4224  if (TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
4225  {
4226    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
4227    TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: empty discoveringExpanderList\n"));
4228    return;
4229  }
4230  else
4231  {
4232    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
4233  }
4234  ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
4235  while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
4236  {
4237    tempExpander = TDLIST_OBJECT_BASE(tdsaExpander_t, linkNode, ExpanderList);
4238    UpsreamExpander = tempExpander->tdUpStreamExpander;
4239    DownsreamExpander = tempExpander->tdCurrentDownStreamExpander;
4240    TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: expander id %d\n", tempExpander->id));
4241    TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: exp addrHi 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressHi));
4242    TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: exp addrLo 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressLo));
4243    if (UpsreamExpander)
4244    {
4245      TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: Up exp addrHi 0x%08x\n", UpsreamExpander->tdDevice->SASAddressID.sasAddressHi));
4246      TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: Up exp addrLo 0x%08x\n", UpsreamExpander->tdDevice->SASAddressID.sasAddressLo));
4247    }
4248    else
4249    {
4250      TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: No Upstream expander\n"));
4251    }
4252    if (DownsreamExpander)
4253    {
4254      TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: Down exp addrHi 0x%08x\n", DownsreamExpander->tdDevice->SASAddressID.sasAddressHi));
4255      TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: Down exp addrLo 0x%08x\n", DownsreamExpander->tdDevice->SASAddressID.sasAddressLo));
4256    }
4257    else
4258    {
4259      TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: No Downstream expander\n"));
4260    }
4261
4262    ExpanderList = ExpanderList->flink;
4263  }
4264#endif
4265  return;
4266
4267}
4268
4269/*****************************************************************************
4270*! \brief  tdsaDumpAllUpExp
4271*
4272*  Purpose:  This function prints out all upstream expanders seen by discovery.
4273*
4274*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4275*                   instance.
4276*  \param   onePortContext: Pointer to the portal context instance.
4277*  \param   oneExpander: Pointer to the expander data.
4278*
4279*  \return:
4280*           None
4281*
4282*   \note: For debugging only
4283*
4284*****************************************************************************/
4285osGLOBAL void
4286tdsaDumpAllUpExp(
4287                              tiRoot_t                 *tiRoot,
4288                              tdsaPortContext_t        *onePortContext,
4289                              tdsaExpander_t           *oneExpander
4290                              )
4291{
4292  return;
4293
4294}
4295
4296/*****************************************************************************
4297*! \brief  tdsaDumpAllFreeExp
4298*
4299*  Purpose:  This function prints out all free expanders.
4300*
4301*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4302*                   instance.
4303*  \return:
4304*           None
4305*
4306*   \note: For debugging only
4307*
4308*****************************************************************************/
4309osGLOBAL void
4310tdsaDumpAllFreeExp(
4311                   tiRoot_t                 *tiRoot
4312                  )
4313{
4314
4315  return;
4316}
4317
4318/*****************************************************************************
4319*! \brief  tdsaDuplicateConfigSASAddr
4320*
4321*  Purpose:  This function finds whether SAS address has added to the routing
4322*            table of expander or not.
4323*
4324*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4325*                   instance.
4326*  \param   oneExpander: Pointer to the expander data.
4327*  \param   configSASAddressHi: Upper 4 byte of SAS address.
4328*  \param   configSASAddressLo: Lower 4 byte of SAS address.
4329*
4330*  \return:
4331*           agTRUE  No need to add configSASAddress.
4332*           agFALSE Need to add configSASAddress.
4333*
4334*   \note:
4335*
4336*****************************************************************************/
4337osGLOBAL bit32
4338tdsaDuplicateConfigSASAddr(
4339                      tiRoot_t                 *tiRoot,
4340                      tdsaExpander_t           *oneExpander,
4341                      bit32                    configSASAddressHi,
4342                      bit32                    configSASAddressLo
4343                      )
4344{
4345  bit32 i;
4346  bit32 ret = agFALSE;
4347  TI_DBG3(("tdsaDuplicateConfigSASAddr: start\n"));
4348
4349  if (oneExpander == agNULL)
4350  {
4351    TI_DBG3(("tdsaDuplicateConfigSASAddr: NULL expander\n"));
4352    return agTRUE;
4353  }
4354
4355  if (oneExpander->tdDevice->SASAddressID.sasAddressHi == configSASAddressHi &&
4356      oneExpander->tdDevice->SASAddressID.sasAddressLo == configSASAddressLo
4357     )
4358  {
4359    TI_DBG3(("tdsaDuplicateConfigSASAddr: unnecessary\n"));
4360    return agTRUE;
4361  }
4362
4363  TI_DBG3(("tdsaDuplicateConfigSASAddr: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4364  TI_DBG3(("tdsaDuplicateConfigSASAddr: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4365  TI_DBG3(("tdsaDuplicateConfigSASAddr: configsasAddressHi 0x%08x\n", configSASAddressHi));
4366  TI_DBG3(("tdsaDuplicateConfigSASAddr: configsasAddressLo 0x%08x\n", configSASAddressLo));
4367  TI_DBG3(("tdsaDuplicateConfigSASAddr: configSASAddrTableIndex %d\n", oneExpander->configSASAddrTableIndex));
4368  for(i=0;i<oneExpander->configSASAddrTableIndex;i++)
4369  {
4370    if (oneExpander->configSASAddressHiTable[i] == configSASAddressHi &&
4371        oneExpander->configSASAddressLoTable[i] == configSASAddressLo
4372        )
4373    {
4374      TI_DBG3(("tdsaDuplicateConfigSASAddr: FOUND!!!\n"));
4375      ret = agTRUE;
4376      break;
4377    }
4378  }
4379  /* new one; let's add it */
4380  if (ret == agFALSE)
4381  {
4382    TI_DBG3(("tdsaDuplicateConfigSASAddr: adding configSAS Addr!!!\n"));
4383    TI_DBG3(("tdsaDuplicateConfigSASAddr: configSASAddrTableIndex %d\n", oneExpander->configSASAddrTableIndex));
4384    oneExpander->configSASAddressHiTable[oneExpander->configSASAddrTableIndex] = configSASAddressHi;
4385    oneExpander->configSASAddressLoTable[oneExpander->configSASAddrTableIndex] = configSASAddressLo;
4386    oneExpander->configSASAddrTableIndex++;
4387  }
4388
4389  return ret;
4390}
4391/*****************************************************************************
4392*! \brief  tdsaFindConfigurableExp
4393*
4394*  Purpose:  This function finds whether there is a configurable expander in
4395*            the upstream expander list.
4396*
4397*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4398*                   instance.
4399*  \param   onePortContext: Pointer to the portal context instance.
4400*  \param   oneExpander: Pointer to the expander data.
4401*
4402*  \return:
4403*           agTRUE  There is configurable expander.
4404*           agFALSE There is not configurable expander.
4405*
4406*   \note:
4407*
4408*****************************************************************************/
4409osGLOBAL tdsaExpander_t *
4410tdsaFindConfigurableExp(
4411                         tiRoot_t                 *tiRoot,
4412                         tdsaPortContext_t        *onePortContext,
4413                         tdsaExpander_t           *oneExpander
4414                        )
4415{
4416  tdsaExpander_t    *tempExpander;
4417  tdsaPortContext_t *tmpOnePortContext = onePortContext;
4418  tdsaExpander_t    *ret = agNULL;
4419
4420  TI_DBG3(("tdsaFindConfigurableExp: start\n"));
4421
4422  if (oneExpander == agNULL)
4423  {
4424    TI_DBG3(("tdsaFindConfigurableExp: NULL expander\n"));
4425    return agNULL;
4426  }
4427
4428  TI_DBG3(("tdsaFindConfigurableExp: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4429  TI_DBG3(("tdsaFindConfigurableExp: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4430
4431  tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
4432  if (TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
4433  {
4434    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
4435    TI_DBG3(("tdsaFindConfigurableExp: empty UpdiscoveringExpanderList\n"));
4436    return agNULL;
4437  }
4438  else
4439  {
4440    tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
4441  }
4442  tempExpander = oneExpander->tdUpStreamExpander;
4443  while (tempExpander)
4444  {
4445    TI_DBG3(("tdsaFindConfigurableExp: loop exp addrHi 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressHi));
4446    TI_DBG3(("tdsaFindConfigurableExp: loop exp addrLo 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressLo));
4447    if (tempExpander->configRouteTable)
4448    {
4449      TI_DBG3(("tdsaFindConfigurableExp: found configurable expander\n"));
4450      ret = tempExpander;
4451      break;
4452    }
4453   tempExpander = tempExpander->tdUpStreamExpander;
4454  }
4455
4456  return ret;
4457}
4458
4459/*****************************************************************************
4460*! \brief  tdsaSASDownStreamDiscoverExpanderPhy
4461*
4462*  Purpose:  This function actully does downstream traverse and finds out detailed
4463*            information about topology.
4464*
4465*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4466*                   instance.
4467*  \param   onePortContext: Pointer to the portal context instance.
4468*  \param   oneExpander: Pointer to the expander data.
4469*  \param   pDiscoverResp: Pointer to the Discovery SMP respsonse.
4470*
4471*  \return:
4472*           None
4473*
4474*   \note:
4475*
4476*****************************************************************************/
4477osGLOBAL void
4478tdsaSASDownStreamDiscoverExpanderPhy(
4479                                     tiRoot_t              *tiRoot,
4480                                     tdsaPortContext_t     *onePortContext,
4481                                     tdsaExpander_t        *oneExpander,
4482                                     smpRespDiscover_t     *pDiscoverResp
4483                                     )
4484{
4485  tdsaDeviceData_t        *oneDeviceData;
4486  tdsaExpander_t          *UpStreamExpander;
4487  tdsaDeviceData_t        *AttachedDevice = agNULL;
4488  tdsaExpander_t          *AttachedExpander;
4489  agsaSASIdentify_t       sasIdentify;
4490  bit8                    connectionRate;
4491  bit32                   attachedSasHi, attachedSasLo;
4492  tdsaSASSubID_t          agSASSubID;
4493  tdsaExpander_t          *ConfigurableExpander = agNULL;
4494  bit32                   dupConfigSASAddr = agFALSE;
4495  bit32                   configSASAddressHi;
4496  bit32                   configSASAddressLo;
4497
4498  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: start\n"));
4499  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4500  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4501
4502  TD_ASSERT(tiRoot, "(tdsaSASDownStreamDiscoverExpanderPhy) agRoot NULL");
4503  TD_ASSERT(onePortContext, "(tdsaSASDownStreamDiscoverExpanderPhy) pPort NULL");
4504  TD_ASSERT(oneExpander, "(tdsaSASDownStreamDiscoverExpanderPhy) pExpander NULL");
4505  TD_ASSERT(pDiscoverResp, "(tdsaSASDownStreamDiscoverExpanderPhy) pDiscoverResp NULL");
4506
4507  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: onePortContxt=%p  oneExpander=%p  oneDeviceData=%p\n", onePortContext, oneExpander, oneExpander->tdDevice));
4508
4509  if (onePortContext->valid == agFALSE)
4510  {
4511    TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: aborting discovery\n"));
4512    tdsaSASDiscoverAbort(tiRoot, onePortContext);
4513    return;
4514  }
4515#ifdef TD_INTERNAL_DEBUG
4516    tdsaDumpAllExp(tiRoot, onePortContext, oneExpander);
4517    tdsaFindUpStreamConfigurableExp(tiRoot, oneExpander);
4518    tdsaFindDownStreamConfigurableExp(tiRoot, oneExpander);
4519#endif
4520  /* (1) Find the device structure of the expander */
4521  oneDeviceData = oneExpander->tdDevice;
4522  TD_ASSERT(oneDeviceData, "(tdsaSASDownStreamDiscoverExpanderPhy) pDevice NULL");
4523
4524  /* for debugging */
4525  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n",
4526           oneExpander->discoveringPhyId,
4527           oneDeviceData->SASAddressID.sasAddressHi,
4528           oneDeviceData->SASAddressID.sasAddressLo));
4529  TI_DBG3(("   Attached device: %s\n",
4530           ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" :
4531             (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" :
4532              (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
4533  /* for debugging */
4534  if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
4535  {
4536    TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n"));
4537    TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
4538    tdhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
4539    tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4540    return;
4541  }
4542
4543#ifdef TD_INTERNAL_DEBUG  /* debugging only */
4544  if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_NO_DEVICE)
4545  {
4546    tdhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
4547  }
4548#endif
4549  if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
4550  {
4551    TI_DBG3(("   SAS address    : %08x-%08x\n",
4552      DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp),
4553              DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
4554    TI_DBG3(("   SSP Target     : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
4555    TI_DBG3(("   STP Target     : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
4556    TI_DBG3(("   SMP Target     : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
4557    TI_DBG3(("   SATA DEVICE    : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
4558    TI_DBG3(("   SSP Initiator  : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
4559    TI_DBG3(("   STP Initiator  : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
4560    TI_DBG3(("   SMP Initiator  : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
4561    TI_DBG3(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
4562    TI_DBG3(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
4563
4564  }
4565  /* end for debugging */
4566
4567  /* saving routing attribute for non self-configuring expanders */
4568  oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
4569
4570  /* for debugging */
4571//  dumpRoutingAttributes(tiRoot, oneExpander, pDiscoverResp->phyIdentifier);
4572
4573  oneExpander->discoverSMPAllowed = agTRUE;
4574
4575  /* If a device is attached */
4576  if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) !=  SAS_NO_DEVICE)
4577  {
4578    /* Setup sasIdentify for the attached device */
4579    sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
4580    sasIdentify.deviceType_addressFrameType = (bit8)(pDiscoverResp->attachedDeviceType & 0x70);
4581    sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
4582    sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
4583    *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
4584    *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
4585
4586    /* incremental discovery */
4587    agSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
4588    agSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
4589    agSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
4590    agSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
4591
4592    attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
4593    attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
4594
4595    /* If it's a direct routing */
4596    if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_DIRECT)
4597    {
4598      /* If the attached device is an expander */
4599      if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
4600          || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) )
4601
4602      {
4603        TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error direct routing can't connect to expander\n"));
4604        onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4605           = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4606        onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4607          = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4608        onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4609
4610        tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4611
4612        return;
4613      }
4614    }
4615
4616    /* If the expander's attached device is not myself */
4617    if ( (attachedSasHi != onePortContext->sasLocalAddressHi)
4618         || (attachedSasLo != onePortContext->sasLocalAddressLo) )
4619    {
4620      /* Find the attached device from discovered list */
4621      AttachedDevice = tdsaPortSASDeviceFind(tiRoot, onePortContext, attachedSasLo, attachedSasHi);
4622      /* If the device has not been discovered before */
4623      if ( AttachedDevice == agNULL) //11
4624      {
4625        /* If the phy has subtractive routing attribute */
4626        if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE &&
4627             (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
4628              DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
4629           )
4630        {
4631          /* TODO: discovery error, callback */
4632          TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address\n"));
4633          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4634            = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4635          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4636            = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4637          onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4638          /* discovery done */
4639          tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4640        }
4641        else
4642        {
4643          /* Add the device */
4644          /* read minimum rate from the configuration
4645             onePortContext->LinkRate is SPC's local link rate
4646          */
4647          connectionRate = (bit8)(MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)));
4648          TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: link rate 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo)));
4649          TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp)));
4650          TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate));
4651
4652          if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
4653          {
4654            if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
4655            {
4656              AttachedDevice = tdsaPortSASDeviceAdd(
4657                                                    tiRoot,
4658                                                    onePortContext,
4659                                                    sasIdentify,
4660                                                    agFALSE,
4661                                                    connectionRate,
4662                                                    IT_NEXUS_TIMEOUT,
4663                                                    0,
4664                                                    STP_DEVICE_TYPE,
4665                                                    oneDeviceData,
4666                                                    pDiscoverResp->phyIdentifier
4667                                                    );
4668            }
4669            else
4670            {
4671              /* incremental discovery */
4672              AttachedDevice = tdsaFindRegNValid(
4673                                                 onePortContext->agRoot,
4674                                                 onePortContext,
4675                                                 &agSASSubID
4676                                                 );
4677              /* not registered and not valid; add this*/
4678              if (AttachedDevice == agNULL)
4679              {
4680                AttachedDevice = tdsaPortSASDeviceAdd(
4681                                                      tiRoot,
4682                                                      onePortContext,
4683                                                      sasIdentify,
4684                                                      agFALSE,
4685                                                      connectionRate,
4686                                                      IT_NEXUS_TIMEOUT,
4687                                                      0,
4688                                                      STP_DEVICE_TYPE,
4689                                                      oneDeviceData,
4690                                                      pDiscoverResp->phyIdentifier
4691                                                      );
4692              }
4693            }
4694          }
4695          else
4696          {
4697            if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
4698            {
4699              AttachedDevice = tdsaPortSASDeviceAdd(
4700                                                    tiRoot,
4701                                                    onePortContext,
4702                                                    sasIdentify,
4703                                                    agFALSE,
4704                                                    connectionRate,
4705                                                    IT_NEXUS_TIMEOUT,
4706                                                    0,
4707                                                    SAS_DEVICE_TYPE,
4708                                                    oneDeviceData,
4709                                                    pDiscoverResp->phyIdentifier
4710                                                    );
4711            }
4712            else
4713            {
4714              /* incremental discovery */
4715              AttachedDevice = tdsaFindRegNValid(
4716                                                 onePortContext->agRoot,
4717                                                 onePortContext,
4718                                                 &agSASSubID
4719                                                 );
4720              /* not registered and not valid; add this*/
4721              if (AttachedDevice == agNULL)
4722              {
4723                AttachedDevice = tdsaPortSASDeviceAdd(
4724                                                      tiRoot,
4725                                                      onePortContext,
4726                                                      sasIdentify,
4727                                                      agFALSE,
4728                                                      connectionRate,
4729                                                      IT_NEXUS_TIMEOUT,
4730                                                      0,
4731                                                      SAS_DEVICE_TYPE,
4732                                                      oneDeviceData,
4733                                                      pDiscoverResp->phyIdentifier
4734                                                      );
4735              }
4736            }
4737          }
4738          TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: newDevice  pDevice=%p\n", AttachedDevice));
4739          /* If the device is added successfully */
4740          if ( AttachedDevice != agNULL)
4741          {
4742            if ( SA_IDFRM_IS_SSP_TARGET(&sasIdentify)
4743                 || SA_IDFRM_IS_SMP_TARGET(&sasIdentify)
4744                 || SA_IDFRM_IS_SSP_INITIATOR(&sasIdentify)
4745                 || SA_IDFRM_IS_SMP_INITIATOR(&sasIdentify) )
4746            {
4747              TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Report a new SAS device !!\n"));
4748
4749            }
4750            else
4751            {
4752              if ( SA_IDFRM_IS_STP_TARGET(&sasIdentify) ||
4753                   SA_IDFRM_IS_SATA_DEVICE(&sasIdentify) )
4754              {
4755
4756                TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Found an STP or SATA device.\n"));
4757              }
4758              else
4759              {
4760                TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Found Other type of device.\n"));
4761              }
4762            }
4763
4764            /* LP2006-05-26 added upstream device to the newly found device */
4765            AttachedDevice->tdExpander = oneExpander;
4766
4767            /* If the phy has table routing attribute */
4768            if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
4769            {
4770              /* If the attached device is a fan out expander */
4771              if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
4772              {
4773                /* TODO: discovery error, callback */
4774                TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys are connected\n"));
4775                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4776                  = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4777                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4778                  = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4779                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4780                /* discovery done */
4781                tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4782              }
4783              else if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
4784              {
4785                /* Allocate an expander data structure */
4786                AttachedExpander = tdssSASDiscoveringExpanderAlloc(tiRoot, onePortContext, AttachedDevice);
4787
4788                TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Found a EDGE exp device.%p\n", AttachedExpander));
4789                /* If allocate successfully */
4790                if ( AttachedExpander != agNULL)
4791                {
4792                  /* set up downstream information on configurable expander */
4793                  if (oneExpander->configRouteTable)
4794                  {
4795                    tdsaSASExpanderDownStreamPhyAdd(tiRoot, oneExpander, (bit8) oneExpander->discoveringPhyId);
4796                  }
4797                  /* Setup upstream information */
4798                  tdsaSASExpanderUpStreamPhyAdd(tiRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
4799                  AttachedExpander->hasUpStreamDevice = agTRUE;
4800                  AttachedExpander->upStreamSASAddressHi
4801                    = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4802                  AttachedExpander->upStreamSASAddressLo
4803                    = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4804                  AttachedExpander->tdUpStreamExpander = oneExpander;
4805                  /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */
4806                  tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, AttachedExpander);
4807                }
4808                /* If failed to allocate */
4809                else
4810                {
4811                  TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy, Failed to allocate expander data structure\n"));
4812                  /*  discovery done */
4813                  tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4814                }
4815              }
4816            }
4817            /* If status is still DISCOVERY_DOWN_STREAM */
4818            if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
4819            {
4820              TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 1st before\n"));
4821              tdsaDumpAllUpExp(tiRoot, onePortContext, oneExpander);
4822              UpStreamExpander = oneExpander->tdUpStreamExpander;
4823              ConfigurableExpander = tdsaFindConfigurableExp(tiRoot, onePortContext, oneExpander);
4824              configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
4825              configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
4826              if (ConfigurableExpander)
4827              {
4828                if ( (ConfigurableExpander->tdDevice->SASAddressID.sasAddressHi
4829                      == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
4830                     (ConfigurableExpander->tdDevice->SASAddressID.sasAddressLo
4831                      == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
4832                   )
4833                { /* directly attached between oneExpander and ConfigurableExpander */
4834                  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 1st before loc 1\n"));
4835                  configSASAddressHi = oneExpander->tdDevice->SASAddressID.sasAddressHi;
4836                  configSASAddressLo = oneExpander->tdDevice->SASAddressID.sasAddressLo;
4837                }
4838                else
4839                {
4840                  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 1st before loc 2\n"));
4841                  configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
4842                  configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
4843                }
4844              } /* if !ConfigurableExpander */
4845              dupConfigSASAddr = tdsaDuplicateConfigSASAddr(tiRoot,
4846                                                          ConfigurableExpander,
4847                                                          configSASAddressHi,
4848                                                          configSASAddressLo
4849                                                          );
4850
4851
4852              if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
4853              {
4854                TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 1st q123\n"));
4855                UpStreamExpander->tdCurrentDownStreamExpander = oneExpander;
4856                ConfigurableExpander->currentDownStreamPhyIndex =
4857                        tdsaFindCurrentDownStreamPhyIndex(tiRoot, ConfigurableExpander);
4858                ConfigurableExpander->tdReturnginExpander = oneExpander;
4859                tdsaSASRoutingEntryAdd(tiRoot,
4860                                       ConfigurableExpander,
4861                                       ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
4862                                       configSASAddressHi,
4863                                       configSASAddressLo
4864                                       );
4865              }
4866            }
4867          }
4868          /*  If fail to add the device */
4869          else
4870          {
4871            TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy, Failed to add a device\n"));
4872            /*  discovery done */
4873            tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4874          }
4875        }
4876      }
4877      /* If the device has been discovered before */
4878      else /* haha discovered before */
4879      {
4880        /* If the phy has subtractive routing attribute */
4881        if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
4882        {
4883          /* If the expander doesn't have up stream device */
4884          if ( oneExpander->hasUpStreamDevice == agFALSE)
4885          {
4886            /* TODO: discovery error, callback */
4887            TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error loop, or end device connects to two expanders\n"));
4888            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4889              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4890            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4891              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4892            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4893            /* discovery done */
4894            tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4895          }
4896          /* If the expander has up stream device */
4897          else
4898          {
4899            /* If sas address doesn't match */
4900            if ( (oneExpander->upStreamSASAddressHi != attachedSasHi)
4901                 || (oneExpander->upStreamSASAddressLo != attachedSasLo) )
4902            {
4903              /* TODO: discovery error, callback */
4904              TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error two subtractive phys\n"));
4905              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4906                = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4907              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4908                = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4909              onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4910              /* discovery done */
4911              tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4912            }
4913          }
4914        }
4915        /* If the phy has table routing attribute */
4916        else if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
4917        {
4918          /* If the attached device is a fan out expander */
4919          if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
4920          {
4921            /* (2.3.3.2.1.1) TODO: discovery error, callback */
4922            TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error fan out expander to routing table phy\n"));
4923            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4924              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4925            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4926              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4927            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4928            /* discovery done */
4929            tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4930          }
4931          /* If the attached device is an edge expander */
4932          else if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
4933          {
4934            /* Setup up stream inform */
4935            AttachedExpander = AttachedDevice->tdExpander;
4936            TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Found edge expander=%p\n", AttachedExpander));
4937            //hhhhhh
4938            /* If the attached expander has up stream device */
4939            if ( AttachedExpander->hasUpStreamDevice == agTRUE)
4940            {
4941              /* compare the sas address */
4942              if ( (AttachedExpander->upStreamSASAddressHi
4943                    != DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
4944                   || (AttachedExpander->upStreamSASAddressLo
4945                       != DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)))
4946              {
4947                /* TODO: discovery error, callback */
4948                TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys connected (1)\n"));
4949                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4950                  = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4951                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4952                  = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4953                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4954                /* discovery done */
4955                tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4956              }
4957              else
4958              {
4959                TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Add edge expander=%p\n", AttachedExpander));
4960                /* set up downstream information on configurable expander */
4961                if (oneExpander->configRouteTable)
4962                {
4963                  tdsaSASExpanderDownStreamPhyAdd(tiRoot, oneExpander, (bit8) oneExpander->discoveringPhyId);
4964                }
4965                /* haha */
4966                tdsaSASExpanderUpStreamPhyAdd(tiRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
4967                /* Add the pAttachedExpander to discovering list */
4968                tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, AttachedExpander);
4969              }
4970            }
4971            /* If the attached expander doesn't have up stream device */
4972            else
4973            {
4974              /* TODO: discovery error, callback */
4975              TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys connected (2)\n"));
4976              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4977                = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4978              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4979                = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4980              onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4981              /* discovery done */
4982              tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4983            }
4984          }
4985        } /* for else if (DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE) */
4986
4987        /* do this regradless of sub or table */
4988        /* If status is still DISCOVERY_DOWN_STREAM */
4989        if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
4990        {
4991          TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 2nd before\n"));
4992          tdsaDumpAllUpExp(tiRoot, onePortContext, oneExpander);
4993
4994          UpStreamExpander = oneExpander->tdUpStreamExpander;
4995          ConfigurableExpander = tdsaFindConfigurableExp(tiRoot, onePortContext, oneExpander);
4996          configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
4997          configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
4998          if (ConfigurableExpander)
4999          {
5000            if ( (ConfigurableExpander->tdDevice->SASAddressID.sasAddressHi
5001                 == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
5002                 (ConfigurableExpander->tdDevice->SASAddressID.sasAddressLo
5003                   == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
5004               )
5005            { /* directly attached between oneExpander and ConfigurableExpander */
5006              TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 2nd before loc 1\n"));
5007              configSASAddressHi = oneExpander->tdDevice->SASAddressID.sasAddressHi;
5008              configSASAddressLo = oneExpander->tdDevice->SASAddressID.sasAddressLo;
5009            }
5010            else
5011            {
5012              TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 2nd before loc 2\n"));
5013              configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
5014              configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
5015            }
5016          } /* if !ConfigurableExpander */
5017          dupConfigSASAddr = tdsaDuplicateConfigSASAddr(tiRoot,
5018                                                        ConfigurableExpander,
5019                                                        configSASAddressHi,
5020                                                        configSASAddressLo
5021                                                        );
5022
5023          if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
5024          {
5025            TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 2nd q123 \n"));
5026            UpStreamExpander->tdCurrentDownStreamExpander = oneExpander;
5027            ConfigurableExpander->currentDownStreamPhyIndex =
5028                        tdsaFindCurrentDownStreamPhyIndex(tiRoot, ConfigurableExpander);
5029            ConfigurableExpander->tdReturnginExpander = oneExpander;
5030            tdsaSASRoutingEntryAdd(tiRoot,
5031                                   ConfigurableExpander,
5032                                   ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
5033                                   configSASAddressHi,
5034                                   configSASAddressLo
5035                                   );
5036          }
5037        } /* if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) */
5038        /* incremental discovery */
5039        if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_INCREMENTAL_START)
5040        {
5041          connectionRate = (bit8)(MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)));
5042
5043          if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
5044          {
5045            TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: incremental SATA_STP\n"));
5046
5047            tdsaPortSASDeviceAdd(
5048                                                    tiRoot,
5049                                                    onePortContext,
5050                                                    sasIdentify,
5051                                                    agFALSE,
5052                                                    connectionRate,
5053                                                    IT_NEXUS_TIMEOUT,
5054                                                    0,
5055                                                    STP_DEVICE_TYPE,
5056                                                    oneDeviceData,
5057                                                    pDiscoverResp->phyIdentifier
5058                                                    );
5059          }
5060          else
5061          {
5062            TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: incremental SAS\n"));
5063
5064             tdsaPortSASDeviceAdd(
5065                                                    tiRoot,
5066                                                    onePortContext,
5067                                                    sasIdentify,
5068                                                    agFALSE,
5069                                                    connectionRate,
5070                                                    IT_NEXUS_TIMEOUT,
5071                                                    0,
5072                                                    SAS_DEVICE_TYPE,
5073                                                    oneDeviceData,
5074                                                    pDiscoverResp->phyIdentifier
5075                                                    );
5076
5077          }
5078        }
5079
5080
5081      }/* else; existing devce */
5082    } /* not attached to myself */
5083    /* If the attached device is myself */
5084    else
5085    {
5086      TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Found Self\n"));
5087      TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 3rd before\n"));
5088      tdsaDumpAllUpExp(tiRoot, onePortContext, oneExpander);
5089
5090      UpStreamExpander = oneExpander->tdUpStreamExpander;
5091      ConfigurableExpander = tdsaFindConfigurableExp(tiRoot, onePortContext, oneExpander);
5092      dupConfigSASAddr = tdsaDuplicateConfigSASAddr(tiRoot,
5093                                                    ConfigurableExpander,
5094                                                    onePortContext->sasLocalAddressHi,
5095                                                    onePortContext->sasLocalAddressLo
5096                                                    );
5097
5098      if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
5099      {
5100        TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 3rd q123 Setup routing table\n"));
5101        UpStreamExpander->tdCurrentDownStreamExpander = oneExpander;
5102        ConfigurableExpander->currentDownStreamPhyIndex =
5103                        tdsaFindCurrentDownStreamPhyIndex(tiRoot, ConfigurableExpander);
5104        ConfigurableExpander->tdReturnginExpander = oneExpander;
5105        tdsaSASRoutingEntryAdd(tiRoot,
5106                               ConfigurableExpander,
5107                               ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
5108                               onePortContext->sasLocalAddressHi,
5109                               onePortContext->sasLocalAddressLo
5110                               );
5111      }
5112    }
5113  }
5114  /* If no device is attached */
5115  else
5116  {
5117  }
5118
5119
5120  /* Increment the discovering phy id */
5121  oneExpander->discoveringPhyId ++;
5122
5123  /* If the discovery status is DISCOVERY_DOWN_STREAM */
5124  if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
5125  {
5126    /* If not the last phy */
5127    if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
5128    {
5129      TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: More Phys to discover\n"));
5130      /* continue discovery for the next phy */
5131      tdsaDiscoverSend(tiRoot, oneDeviceData);
5132    }
5133    /* If the last phy */
5134    else
5135    {
5136      TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: No More Phys\n"));
5137
5138      /* remove the expander from the discovering list */
5139      tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, oneExpander);
5140      /* continue downstream discovering */
5141      tdsaSASDownStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
5142    }
5143  }
5144  else
5145  {
5146    TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));
5147  }
5148  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
5149
5150  return;
5151}
5152
5153/*****************************************************************************
5154*! \brief  tdsaSASDownStreamDiscoverExpanderPhySkip
5155*
5156*  Purpose:  This function skips a phy which returned PHY_VACANT in SMP
5157*            response in downstream
5158*
5159*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5160*                   instance.
5161*  \param   onePortContext: Pointer to the portal context instance.
5162*  \param   oneExpander: Pointer to the expander data.
5163*
5164*  \return:
5165*           None
5166*
5167*   \note:
5168*
5169*****************************************************************************/
5170osGLOBAL void
5171tdsaSASDownStreamDiscoverExpanderPhySkip(
5172                                     tiRoot_t              *tiRoot,
5173                                     tdsaPortContext_t     *onePortContext,
5174                                     tdsaExpander_t        *oneExpander
5175                                     )
5176{
5177  tdsaDeviceData_t        *oneDeviceData;
5178  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: start\n"));
5179  oneDeviceData = oneExpander->tdDevice;
5180
5181  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
5182  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
5183
5184  /* Increment the discovering phy id */
5185  oneExpander->discoveringPhyId ++;
5186
5187  /* If the discovery status is DISCOVERY_DOWN_STREAM */
5188  if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
5189  {
5190    /* If not the last phy */
5191    if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
5192    {
5193      TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: More Phys to discover\n"));
5194      /* continue discovery for the next phy */
5195      tdsaDiscoverSend(tiRoot, oneDeviceData);
5196    }
5197    /* If the last phy */
5198    else
5199    {
5200      TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: No More Phys\n"));
5201
5202      /* remove the expander from the discovering list */
5203      tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, oneExpander);
5204      /* continue downstream discovering */
5205      tdsaSASDownStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
5206    }
5207  }
5208  else
5209  {
5210    TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));
5211  }
5212  TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
5213
5214  return;
5215}
5216
5217/*****************************************************************************
5218*! \brief  tdsaSASRoutingEntryAdd
5219*
5220*  Purpose:  This function adds a routing entry in the configurable expander.
5221*
5222*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5223*                   instance.
5224*  \param   oneExpander: Pointer to the expander data.
5225*  \param   phyId: Phy identifier.
5226*  \param   configSASAddressHi: Upper 4 byte of SAS address.
5227*  \param   configSASAddressLo: Lower 4 byte of SAS address.
5228*
5229*  \return:
5230*           agTRUE   Routing entry is added successfully
5231*           agFALSE  Routing entry is not added successfully
5232*
5233*   \note:
5234*
5235*****************************************************************************/
5236osGLOBAL bit32
5237tdsaSASRoutingEntryAdd(
5238                       tiRoot_t          *tiRoot,
5239                       tdsaExpander_t    *oneExpander,
5240                       bit32             phyId,
5241                       bit32             configSASAddressHi,
5242                       bit32             configSASAddressLo
5243                       )
5244{
5245  bit32                                   ret = agTRUE;
5246  smpReqConfigureRouteInformation_t       confRoutingInfo;
5247  tdsaPortContext_t                       *onePortContext;
5248  bit32                                   i;
5249  agsaRoot_t                              *agRoot;
5250
5251  TI_DBG3(("tdsaSASRoutingEntryAdd: start\n"));
5252  TI_DBG3(("tdsaSASRoutingEntryAdd: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
5253  TI_DBG3(("tdsaSASRoutingEntryAdd: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
5254  TI_DBG3(("tdsaSASRoutingEntryAdd: phyid %d\n", phyId));
5255
5256  /* needs to compare the location of oneExpander and configSASAddress
5257     add only if
5258     oneExpander
5259          |
5260     configSASaddress
5261
5262  */
5263  if (oneExpander->tdDevice->SASAddressID.sasAddressHi == configSASAddressHi &&
5264      oneExpander->tdDevice->SASAddressID.sasAddressLo == configSASAddressLo
5265     )
5266  {
5267    TI_DBG3(("tdsaSASRoutingEntryAdd: unnecessary\n"));
5268    return ret;
5269  }
5270  if (oneExpander->routingAttribute[phyId] != SAS_ROUTING_TABLE)
5271  {
5272    TI_DBG3(("tdsaSASRoutingEntryAdd: not table routing, routing is %d\n", oneExpander->routingAttribute[phyId]));
5273    return ret;
5274  }
5275
5276  agRoot = oneExpander->tdDevice->agRoot;
5277  onePortContext = oneExpander->tdDevice->tdPortContext;
5278
5279  onePortContext->discovery.status = DISCOVERY_CONFIG_ROUTING;
5280
5281  /* reset smpReqConfigureRouteInformation_t */
5282  osti_memset(&confRoutingInfo, 0, sizeof(smpReqConfigureRouteInformation_t));
5283  if ( oneExpander->currentIndex[phyId] < oneExpander->routingIndex )
5284  {
5285    TI_DBG3(("tdsaSASRoutingEntryAdd: adding sasAddressHi 0x%08x\n", configSASAddressHi));
5286    TI_DBG3(("tdsaSASRoutingEntryAdd: adding sasAddressLo 0x%08x\n", configSASAddressLo));
5287    TI_DBG3(("tdsaSASRoutingEntryAdd: phyid %d currentIndex[phyid] %d\n", phyId, oneExpander->currentIndex[phyId]));
5288
5289    oneExpander->configSASAddressHi = configSASAddressHi;
5290    oneExpander->configSASAddressLo = configSASAddressLo;
5291    confRoutingInfo.reserved1[0] = 0;
5292    confRoutingInfo.reserved1[1] = 0;
5293    OSSA_WRITE_BE_16(agRoot, confRoutingInfo.expanderRouteIndex, 0, (oneExpander->currentIndex[phyId]));
5294    confRoutingInfo.reserved2 = 0;
5295    confRoutingInfo.phyIdentifier = (bit8)phyId;
5296    confRoutingInfo.reserved3[0] = 0;
5297    confRoutingInfo.reserved3[1] = 0;
5298    confRoutingInfo.disabledBit_reserved4 = 0;
5299    confRoutingInfo.reserved5[0] = 0;
5300    confRoutingInfo.reserved5[1] = 0;
5301    confRoutingInfo.reserved5[2] = 0;
5302    OSSA_WRITE_BE_32(agRoot, confRoutingInfo.routedSasAddressHi, 0, configSASAddressHi);
5303    OSSA_WRITE_BE_32(agRoot, confRoutingInfo.routedSasAddressLo, 0, configSASAddressLo);
5304    for ( i = 0; i < 16; i ++ )
5305    {
5306      confRoutingInfo.reserved6[i] = 0;
5307    }
5308    tdSMPStart(tiRoot, agRoot, oneExpander->tdDevice, SMP_CONFIGURE_ROUTING_INFORMATION, (bit8 *)&confRoutingInfo, sizeof(smpReqConfigureRouteInformation_t), AGSA_SMP_INIT_REQ, agNULL, 0);
5309
5310    oneExpander->currentIndex[phyId] ++;
5311  }
5312  else
5313  {
5314    TI_DBG1(("tdsaSASRoutingEntryAdd: Discovery Error routing index overflow for currentIndex=%d, routingIndex=%d\n", oneExpander->currentIndex[phyId], oneExpander->routingIndex));
5315    tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
5316
5317    ret = agFALSE;
5318  }
5319
5320
5321  return ret;
5322}
5323/*****************************************************************************
5324*! \brief  tdsaConfigRoutingInfoRespRcvd
5325*
5326*  Purpose:  This function processes Configure Routing Information response.
5327*
5328*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5329*                   instance.
5330*  \param   agRoot: Pointer to chip/driver Instance.
5331*  \param   oneDeviceData: Pointer to the device data.
5332*  \param   frameHeader: Pointer to SMP frame header.
5333*  \param   frameHandle: A Handle used to refer to the response frame
5334*
5335*  \return:
5336*           None
5337*
5338*   \note:
5339*
5340*****************************************************************************/
5341/* needs to traverse only upstream not downstream */
5342osGLOBAL void
5343tdsaConfigRoutingInfoRespRcvd(
5344                              tiRoot_t              *tiRoot,
5345                              agsaRoot_t            *agRoot,
5346                              agsaIORequest_t       *agIORequest,
5347                              tdsaDeviceData_t      *oneDeviceData,
5348                              tdssSMPFrameHeader_t  *frameHeader,
5349                              agsaFrameHandle_t     frameHandle
5350                              )
5351{
5352  tdsaExpander_t                          *oneExpander = oneDeviceData->tdExpander;
5353  tdsaExpander_t                          *UpStreamExpander;
5354  tdsaExpander_t                          *DownStreamExpander;
5355  tdsaExpander_t                          *ReturningExpander;
5356  tdsaExpander_t                          *ConfigurableExpander;
5357
5358  tdsaPortContext_t                       *onePortContext;
5359  tdsaDeviceData_t                        *ReturningExpanderDeviceData;
5360  bit32                                   dupConfigSASAddr = agFALSE;
5361
5362  TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: start\n"));
5363  TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
5364  TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
5365
5366  onePortContext = oneDeviceData->tdPortContext;
5367
5368  if (onePortContext->valid == agFALSE)
5369  {
5370    TI_DBG1(("tdsaConfigRoutingInfoRespRcvd: aborting discovery\n"));
5371    tdsaSASDiscoverAbort(tiRoot, onePortContext);
5372    return;
5373  }
5374
5375  if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ||
5376       frameHeader->smpFunctionResult == PHY_VACANT
5377     )
5378  {
5379    DownStreamExpander = oneExpander->tdCurrentDownStreamExpander;
5380    if (DownStreamExpander != agNULL)
5381    {
5382      DownStreamExpander->currentUpStreamPhyIndex ++;
5383      TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex));
5384      TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander->numOfUpStreamPhys %d\n", DownStreamExpander->numOfUpStreamPhys));
5385      TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander addrHi 0x%08x\n", DownStreamExpander->tdDevice->SASAddressID.sasAddressHi));
5386      TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander addrLo 0x%08x\n", DownStreamExpander->tdDevice->SASAddressID.sasAddressLo));
5387
5388    }
5389
5390    oneExpander->currentDownStreamPhyIndex++;
5391    TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: oneExpander->currentDownStreamPhyIndex %d oneExpander->numOfDownStreamPhys %d\n", oneExpander->currentDownStreamPhyIndex, oneExpander->numOfDownStreamPhys));
5392
5393    if ( DownStreamExpander != agNULL)
5394    {
5395      if (DownStreamExpander->currentUpStreamPhyIndex < DownStreamExpander->numOfUpStreamPhys)
5396      {
5397        TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: first if\n"));
5398        TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex));
5399
5400        TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander->upStreamPhys[] %d\n", DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex]));
5401
5402        tdsaSASRoutingEntryAdd(tiRoot,
5403                               oneExpander,
5404                               DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex],
5405                               oneExpander->configSASAddressHi,
5406                               oneExpander->configSASAddressLo
5407                               );
5408      }
5409      else
5410      {
5411        /* traversing up till discovery Root onePortContext->discovery.RootExp */
5412        TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: else\n"));
5413
5414        UpStreamExpander = oneExpander->tdUpStreamExpander;
5415        ConfigurableExpander = tdsaFindConfigurableExp(tiRoot, onePortContext, oneExpander);
5416        if (UpStreamExpander != agNULL)
5417        {
5418          TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: UpStreamExpander addrHi 0x%08x\n", UpStreamExpander->tdDevice->SASAddressID.sasAddressHi));
5419          TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: UpStreamExpander addrLo 0x%08x\n", UpStreamExpander->tdDevice->SASAddressID.sasAddressLo));
5420          dupConfigSASAddr = tdsaDuplicateConfigSASAddr(tiRoot,
5421                                                      ConfigurableExpander,
5422                                                      oneExpander->configSASAddressHi,
5423                                                      oneExpander->configSASAddressLo
5424                                                      );
5425
5426          if ( ConfigurableExpander != agNULL && dupConfigSASAddr == agFALSE)
5427          {
5428            TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: else if\n"));
5429
5430            TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ConfigurableExpander addrHi 0x%08x\n", ConfigurableExpander->tdDevice->SASAddressID.sasAddressHi));
5431            TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ConfigurableExpander addrLo 0x%08x\n", ConfigurableExpander->tdDevice->SASAddressID.sasAddressLo));
5432
5433            UpStreamExpander->tdCurrentDownStreamExpander = oneExpander;
5434            ConfigurableExpander->currentDownStreamPhyIndex =
5435                    tdsaFindCurrentDownStreamPhyIndex(tiRoot, ConfigurableExpander);
5436            ConfigurableExpander->tdReturnginExpander = oneExpander->tdReturnginExpander;
5437            DownStreamExpander->currentUpStreamPhyIndex = 0;
5438            TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ConfigurableExpander->currentDownStreamPhyIndex %d\n", ConfigurableExpander->currentDownStreamPhyIndex));
5439
5440            TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ConfigurableExpander->downStreamPhys[] %d\n", ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex]));
5441            tdsaSASRoutingEntryAdd(tiRoot,
5442                                   ConfigurableExpander,
5443                                   ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
5444                                   oneExpander->configSASAddressHi,
5445                                   oneExpander->configSASAddressLo
5446                                   );
5447          }
5448          else
5449          {
5450            /* going back to where it was */
5451            /* ConfigRoutingInfo is done for a target */
5452            TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: $$$$$$ my change $$$$$ \n"));
5453            ReturningExpander = oneExpander->tdReturnginExpander;
5454            DownStreamExpander->currentUpStreamPhyIndex = 0;
5455            /* debugging */
5456            if (ReturningExpander != agNULL)
5457            {
5458              TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ReturningExpander addrHi 0x%08x\n", ReturningExpander->tdDevice->SASAddressID.sasAddressHi));
5459              TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ReturningExpander addrLo 0x%08x\n", ReturningExpander->tdDevice->SASAddressID.sasAddressLo));
5460
5461              ReturningExpanderDeviceData = ReturningExpander->tdDevice;
5462
5463              /* No longer in DISCOVERY_CONFIG_ROUTING */
5464              onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
5465
5466              /* If not the last phy */
5467              if ( ReturningExpander->discoveringPhyId < ReturningExpanderDeviceData->numOfPhys )
5468              {
5469                TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: More Phys to discover\n"));
5470                /* continue discovery for the next phy */
5471                /* needs to send only one Discovery not multiple times */
5472                if (ReturningExpander->discoverSMPAllowed == agTRUE)
5473                {
5474                  tdsaDiscoverSend(tiRoot, ReturningExpanderDeviceData);
5475                }
5476                ReturningExpander->discoverSMPAllowed = agFALSE;
5477              }
5478              /* If the last phy */
5479              else
5480              {
5481                TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: No More Phys\n"));
5482                ReturningExpander->discoverSMPAllowed = agTRUE;
5483
5484                /* remove the expander from the discovering list */
5485                tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, ReturningExpander);
5486                /* continue downstream discovering */
5487                tdsaSASDownStreamDiscovering(tiRoot, onePortContext, ReturningExpanderDeviceData);
5488
5489                //DownStreamExpander
5490              }
5491            }
5492            else
5493            {
5494              TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ReturningExpander is NULL\n"));
5495            }
5496          }
5497        }
5498        else
5499        {
5500          TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: UpStreamExpander is NULL\n"));
5501        }
5502      }
5503    }
5504  }
5505  else
5506  {
5507    TI_DBG1(("tdsaConfigRoutingInfoRespRcvd: Discovery Error SMP function return result error=%x\n", frameHeader->smpFunctionResult));
5508    tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
5509  }
5510  return;
5511}
5512
5513/*****************************************************************************
5514*! \brief  tdsaReportPhySataSend
5515*
5516*  Purpose:  This function sends Report Phy SATA to a device.
5517*
5518*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5519*                   instance.
5520*  \param   oneDeviceData: Pointer to the device data.
5521*  \param   phyId: Phy Identifier.
5522*
5523*  \return:
5524*           None
5525*
5526*   \note:
5527*
5528*****************************************************************************/
5529osGLOBAL void
5530tdsaReportPhySataSend(
5531                      tiRoot_t             *tiRoot,
5532                      tdsaDeviceData_t     *oneDeviceData,
5533                      bit8                 phyId
5534                      )
5535{
5536  agsaRoot_t            *agRoot;
5537  tdsaExpander_t        *oneExpander;
5538  tdsaPortContext_t     *onePortContext;
5539  smpReqReportPhySata_t smpReportPhySataReq;
5540
5541  TI_DBG3(("tdsaReportPhySataSend: start\n"));
5542
5543  agRoot = oneDeviceData->agRoot;
5544  onePortContext = oneDeviceData->tdPortContext;
5545  oneExpander = oneDeviceData->tdExpander;
5546
5547  if (onePortContext == agNULL)
5548  {
5549    TI_DBG1(("tdsaReportPhySataSend: Error!!! portcontext is NULL\n"));
5550  }
5551
5552  if (oneExpander == agNULL)
5553  {
5554    TI_DBG1(("tdsaReportPhySataSend: Error!!! expander is NULL\n"));
5555    return;
5556  }
5557  TI_DBG3(("tdsaReportPhySataSend: device %p did %d\n", oneDeviceData, oneDeviceData->id));
5558  TI_DBG3(("tdsaReportPhySataSend: phyid %d\n", phyId));
5559
5560  oneExpander->tdDeviceToProcess = oneDeviceData;
5561
5562  osti_memset(&smpReportPhySataReq, 0, sizeof(smpReqReportPhySata_t));
5563
5564  smpReportPhySataReq.phyIdentifier = phyId;
5565
5566
5567  tdSMPStart(
5568             tiRoot,
5569             agRoot,
5570             oneExpander->tdDevice,
5571             SMP_REPORT_PHY_SATA,
5572             (bit8 *)&smpReportPhySataReq,
5573             sizeof(smpReqReportPhySata_t),
5574             AGSA_SMP_INIT_REQ,
5575             agNULL,
5576             0
5577             );
5578
5579  return;
5580}
5581
5582/*****************************************************************************
5583*! \brief  tdsaReportPhySataRcvd
5584*
5585*  Purpose:  This function processes Report Phy SATA response.
5586*
5587*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5588*                   instance.
5589*  \param   agRoot: Pointer to chip/driver Instance.
5590*  \param   oneDeviceData: Pointer to the device data.
5591*  \param   frameHeader: Pointer to SMP frame header.
5592*  \param   frameHandle: A Handle used to refer to the response frame
5593*
5594*  \return:
5595*           None
5596*
5597*   \note:
5598*
5599*****************************************************************************/
5600osGLOBAL void
5601tdsaReportPhySataRcvd(
5602                      tiRoot_t              *tiRoot,
5603                      agsaRoot_t            *agRoot,
5604                      agsaIORequest_t       *agIORequest,
5605                      tdsaDeviceData_t      *oneDeviceData,
5606                      tdssSMPFrameHeader_t  *frameHeader,
5607                      agsaFrameHandle_t     frameHandle
5608                      )
5609{
5610  smpRespReportPhySata_t      SMPreportPhySataResp;
5611  smpRespReportPhySata_t      *pSMPReportPhySataResp;
5612  tdsaExpander_t              *oneExpander = oneDeviceData->tdExpander;
5613  tdsaPortContext_t           *onePortContext;
5614  agsaFisRegDeviceToHost_t    *fis;
5615  tdsaDeviceData_t            *SataDevice;
5616#ifndef DIRECT_SMP
5617  tdssSMPRequestBody_t        *tdSMPRequestBody;
5618#endif
5619
5620  TI_DBG3(("tdsaReportPhySataRcvd: start\n"));
5621  TI_DBG3(("tdsaReportPhySataRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
5622  TI_DBG3(("tdsaReportPhySataRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
5623#ifndef DIRECT_SMP
5624  tdSMPRequestBody = (tdssSMPRequestBody_t *)agIORequest->osData;
5625#endif
5626  /* get the current sata device hanlde stored in the expander structure */
5627  SataDevice = oneExpander->tdDeviceToProcess;
5628  pSMPReportPhySataResp = &SMPreportPhySataResp;
5629#ifdef DIRECT_SMP
5630  saFrameReadBlock(agRoot, frameHandle, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));
5631#else
5632  saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));
5633#endif
5634
5635  //tdhexdump("tdsaReportPhySataRcvd", (bit8 *)pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));
5636
5637#ifndef DIRECT_SMP
5638  ostiFreeMemory(
5639                 tiRoot,
5640                 tdSMPRequestBody->IndirectSMPReqosMemHandle,
5641                 tdSMPRequestBody->IndirectSMPReqLen
5642                );
5643  ostiFreeMemory(
5644                 tiRoot,
5645                 tdSMPRequestBody->IndirectSMPResposMemHandle,
5646                 tdSMPRequestBody->IndirectSMPRespLen
5647                );
5648#endif
5649
5650  onePortContext = oneDeviceData->tdPortContext;
5651
5652  if (onePortContext->valid == agFALSE)
5653  {
5654    TI_DBG1(("tdsaReportPhySataRcvd: aborting discovery\n"));
5655    tdsaSASDiscoverAbort(tiRoot, onePortContext);
5656    return;
5657  }
5658  if (SataDevice == agNULL)
5659  {
5660    TI_DBG1(("tdsaReportPhySataRcvd: SataDevice is NULL, wrong\n"));
5661    tdsaSASDiscoverAbort(tiRoot, onePortContext);
5662    return;
5663  }
5664  if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ||
5665       frameHeader->smpFunctionResult == PHY_VACANT
5666     )
5667  {
5668    fis = (agsaFisRegDeviceToHost_t*) &SMPreportPhySataResp.regDevToHostFis;
5669    if (fis->h.fisType == REG_DEV_TO_HOST_FIS)
5670    {
5671      /* save signature */
5672      TI_DBG3(("tdsaReportPhySataRcvd: saves the signature\n"));
5673      /* saves signature */
5674      SataDevice->satDevData.satSignature[0] = fis->d.sectorCount;
5675      SataDevice->satDevData.satSignature[1] = fis->d.lbaLow;
5676      SataDevice->satDevData.satSignature[2] = fis->d.lbaMid;
5677      SataDevice->satDevData.satSignature[3] = fis->d.lbaHigh;
5678      SataDevice->satDevData.satSignature[4] = fis->d.device;
5679      SataDevice->satDevData.satSignature[5] = 0;
5680      SataDevice->satDevData.satSignature[6] = 0;
5681      SataDevice->satDevData.satSignature[7] = 0;
5682
5683      TI_DBG3(("tdsaReportPhySataRcvd: SATA Signature = %02x %02x %02x %02x %02x\n",
5684        SataDevice->satDevData.satSignature[0],
5685        SataDevice->satDevData.satSignature[1],
5686        SataDevice->satDevData.satSignature[2],
5687        SataDevice->satDevData.satSignature[3],
5688        SataDevice->satDevData.satSignature[4]));
5689      /*
5690        no longer, discovery sends sata identify device command
5691        tdsaSATAIdentifyDeviceCmdSend(tiRoot, SataDevice);
5692      */
5693      SataDevice = tdsaFindRightDevice(tiRoot, onePortContext, SataDevice);
5694      tdsaDiscoveringStpSATADevice(tiRoot, onePortContext, SataDevice);
5695    }
5696    else
5697    {
5698      TI_DBG3(("tdsaReportPhySataRcvd: getting next stp bride\n"));
5699      SataDevice = tdsaFindRightDevice(tiRoot, onePortContext, SataDevice);
5700      tdsaDiscoveringStpSATADevice(tiRoot, onePortContext, SataDevice);
5701    }
5702  }
5703  else
5704  {
5705    TI_DBG3(("tdsaReportPhySataRcvd: siReportPhySataRcvd SMP function return result %x\n",
5706             frameHeader->smpFunctionResult));
5707    tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
5708  }
5709  return;
5710}
5711
5712/*****************************************************************************
5713*! \brief  tdsaSASExpanderUpStreamPhyAdd
5714*
5715*  Purpose:  This function adds upstream expander to a specfic phy.
5716*
5717*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5718*                   instance.
5719*  \param   oneExpander: Pointer to the expander data.
5720*  \param   phyId: Phy Identifier.
5721*
5722*  \return:
5723*           None
5724*
5725*   \note:
5726*
5727*****************************************************************************/
5728osGLOBAL void
5729tdsaSASExpanderUpStreamPhyAdd(
5730                              tiRoot_t          *tiRoot,
5731                              tdsaExpander_t    *oneExpander,
5732                              bit8              phyId
5733                              )
5734{
5735  bit32   i;
5736  bit32   hasSet = agFALSE;
5737
5738  TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: start, phyid %d\n", phyId));
5739  TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
5740  TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
5741  TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: phyid %d  numOfUpStreamPhys %d\n", phyId, oneExpander->numOfUpStreamPhys));
5742
5743  for ( i = 0; i < oneExpander->numOfUpStreamPhys; i ++ )
5744  {
5745    if ( oneExpander->upStreamPhys[i] == phyId )
5746    {
5747      hasSet = agTRUE;
5748      break;
5749    }
5750  }
5751
5752  if ( hasSet == agFALSE )
5753  {
5754    oneExpander->upStreamPhys[oneExpander->numOfUpStreamPhys ++] = phyId;
5755  }
5756
5757  TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: AFTER phyid %d  numOfUpStreamPhys %d\n", phyId, oneExpander->numOfUpStreamPhys));
5758
5759  /* for debugging */
5760  for ( i = 0; i < oneExpander->numOfUpStreamPhys; i ++ )
5761  {
5762    TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: index %d upstream[index] %d\n", i, oneExpander->upStreamPhys[i]));
5763  }
5764  return;
5765}
5766
5767/*
5768  just add phys in downstream in configurable expnader
5769*/
5770/*****************************************************************************
5771*! \brief  tdsaSASExpanderDownStreamPhyAdd
5772*
5773*  Purpose:  This function adds downstream expander to a specfic phy.
5774*
5775*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5776*                   instance.
5777*  \param   oneExpander: Pointer to the expander data.
5778*  \param   phyId: Phy Identifier.
5779*
5780*  \return:
5781*           None
5782*
5783*   \note:
5784*
5785*****************************************************************************/
5786osGLOBAL void
5787tdsaSASExpanderDownStreamPhyAdd(
5788                              tiRoot_t          *tiRoot,
5789                              tdsaExpander_t    *oneExpander,
5790                              bit8              phyId
5791                              )
5792{
5793  bit32   i;
5794  bit32   hasSet = agFALSE;
5795
5796  TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: start, phyid %d\n", phyId));
5797  TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
5798  TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
5799  TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: phyid %d  numOfDownStreamPhys %d\n", phyId, oneExpander->numOfDownStreamPhys));
5800
5801  for ( i = 0; i < oneExpander->numOfDownStreamPhys; i ++ )
5802  {
5803    if ( oneExpander->downStreamPhys[i] == phyId )
5804    {
5805      hasSet = agTRUE;
5806      break;
5807    }
5808  }
5809
5810  if ( hasSet == agFALSE )
5811  {
5812    oneExpander->downStreamPhys[oneExpander->numOfDownStreamPhys ++] = phyId;
5813  }
5814
5815  TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: AFTER phyid %d  numOfDownStreamPhys %d\n", phyId, oneExpander->numOfDownStreamPhys));
5816
5817  /* for debugging */
5818  for ( i = 0; i < oneExpander->numOfDownStreamPhys; i ++ )
5819  {
5820     TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: index %d downstream[index] %d\n", i, oneExpander->downStreamPhys[i]));
5821  }
5822  return;
5823}
5824
5825/* oneExpander is the configurable expander of interest
5826   phyId is the first phyID in upStreamPhys[0] of downExpander
5827*/
5828/*****************************************************************************
5829*! \brief  tdsaFindCurrentDownStreamPhyIndex
5830*
5831*  Purpose:  This function finds CurrentDownStreamPhyIndex from a configurable
5832*            expander.
5833*
5834*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5835*                   instance.
5836*  \param   oneExpander: Pointer to the configuralbe expander data.
5837*
5838*  \return:
5839*           CurrentDownStreamPhyIndex
5840*
5841*
5842*****************************************************************************/
5843osGLOBAL bit16
5844tdsaFindCurrentDownStreamPhyIndex(
5845                              tiRoot_t          *tiRoot,
5846                              tdsaExpander_t    *oneExpander
5847                              )
5848{
5849  tdsaExpander_t    *DownStreamExpander;
5850  bit16              index = 0;
5851  bit16              i;
5852  bit8               phyId = 0;
5853
5854  TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: start\n"));
5855
5856  if (oneExpander == agNULL)
5857  {
5858    TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: wrong!!! oneExpander is NULL\n"));
5859    return 0;
5860  }
5861
5862  DownStreamExpander = oneExpander->tdCurrentDownStreamExpander;
5863
5864  if (DownStreamExpander == agNULL)
5865  {
5866    TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: wrong!!! DownStreamExpander is NULL\n"));
5867    return 0;
5868  }
5869
5870  TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
5871  TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
5872  TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: downstream exp addrHi 0x%08x\n", DownStreamExpander->tdDevice->SASAddressID.sasAddressHi));
5873  TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: downstream exp addrLo 0x%08x\n", DownStreamExpander->tdDevice->SASAddressID.sasAddressLo));
5874  TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: numOfDownStreamPhys %d\n", oneExpander->numOfDownStreamPhys));
5875
5876  phyId = DownStreamExpander->upStreamPhys[0];
5877
5878  TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: phyId %d\n", phyId));
5879
5880  for (i=0; i<oneExpander->numOfDownStreamPhys;i++)
5881  {
5882    if (oneExpander->downStreamPhys[i] == phyId)
5883    {
5884      index = i;
5885      break;
5886    }
5887  }
5888  TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: index %d\n", index));
5889  return index;
5890}
5891/*****************************************************************************
5892*! \brief  tdsaPortSASDeviceFind
5893*
5894*  Purpose:  Given SAS address, this function finds a device with that SAS address
5895*            in the device list.
5896*
5897*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5898*                   instance.
5899*  \param   onePortContext: Pointer to the portal context instance.
5900*  \param   sasAddrLo: Lower 4 byte of SAS address.
5901*  \param   sasAddrHi: Upper 4 byte of SAS address.
5902*
5903*  \return:
5904*           agNULL  When no device found
5905*           Pointer to device   When device is found
5906*
5907*   \note:
5908*
5909*****************************************************************************/
5910osGLOBAL tdsaDeviceData_t *
5911tdsaPortSASDeviceFind(
5912                      tiRoot_t           *tiRoot,
5913                      tdsaPortContext_t  *onePortContext,
5914                      bit32              sasAddrLo,
5915                      bit32              sasAddrHi
5916                      )
5917{
5918  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
5919  tdsaContext_t     *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
5920  tdsaDeviceData_t  *oneDeviceData, *RetDeviceData=agNULL;
5921  tdList_t          *DeviceListList;
5922
5923  TI_DBG3(("tdsaPortSASDeviceFind: start\n"));
5924
5925  TD_ASSERT((agNULL != tiRoot), "");
5926  TD_ASSERT((agNULL != onePortContext), "");
5927
5928  tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
5929
5930  /* find a device's existence */
5931  DeviceListList = tdsaAllShared->MainDeviceList.flink;
5932  if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
5933  {
5934    TI_DBG3(("tdsaPortSASDeviceFind: Full discovery\n"));
5935    while (DeviceListList != &(tdsaAllShared->MainDeviceList))
5936    {
5937      oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
5938      if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) &&
5939          (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) &&
5940          (oneDeviceData->valid == agTRUE) &&
5941          (oneDeviceData->tdPortContext == onePortContext)
5942        )
5943      {
5944        TI_DBG3(("tdsaPortSASDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
5945        TI_DBG3(("tdsaPortSASDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
5946        TI_DBG3(("tdsaPortSASDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
5947        RetDeviceData = oneDeviceData;
5948        break;
5949      }
5950      DeviceListList = DeviceListList->flink;
5951    }
5952  }
5953  else
5954  {
5955    /* incremental discovery */
5956    TI_DBG3(("tdsaPortSASDeviceFind: Incremental discovery\n"));
5957    while (DeviceListList != &(tdsaAllShared->MainDeviceList))
5958    {
5959      oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
5960      if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) &&
5961          (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) &&
5962          (oneDeviceData->valid2 == agTRUE) &&
5963          (oneDeviceData->tdPortContext == onePortContext)
5964          )
5965      {
5966        TI_DBG3(("tdsaPortSASDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
5967        TI_DBG3(("tdsaPortSASDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
5968        TI_DBG3(("tdsaPortSASDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
5969
5970        RetDeviceData = oneDeviceData;
5971        break;
5972      }
5973      DeviceListList = DeviceListList->flink;
5974    }
5975  }
5976
5977  tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
5978
5979  return RetDeviceData;
5980}
5981
5982/* include both sas and stp-sata targets*/
5983/*****************************************************************************
5984*! \brief  tdsaPortSASDeviceAdd
5985*
5986*  Purpose:  This function adds the SAS device to the device list.
5987*
5988*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5989*                   instance.
5990*  \param   onePortContext: Pointer to the portal context instance.
5991*  \param   sasIdentify: SAS identify address frame.
5992*  \param   sasInitiator: SAS initiator.
5993*  \param   connectionRate: Connection Rate.
5994*  \param   itNexusTimeout: IT NEXUS timeout value.
5995*  \param   firstBurstSize: First Burst Size.
5996*  \param   deviceType: Device Type.
5997*
5998*  \return:
5999*           Pointer to device data.
6000*
6001*   \note:
6002*
6003*****************************************************************************/
6004GLOBAL tdsaDeviceData_t *
6005tdsaPortSASDeviceAdd(
6006                     tiRoot_t            *tiRoot,
6007                     tdsaPortContext_t   *onePortContext,
6008                     agsaSASIdentify_t   sasIdentify,
6009                     bit32               sasInitiator,
6010                     bit8                connectionRate,
6011                     bit32               itNexusTimeout,
6012                     bit32               firstBurstSize,
6013                     bit32               deviceType,
6014                     tdsaDeviceData_t    *oneExpDeviceData,
6015                     bit8                phyID
6016                     )
6017{
6018  tdsaDeviceData_t  *oneDeviceData = agNULL;
6019  bit8              dev_s_rate = 0;
6020  bit8              sasorsata = 1;
6021//  bit8              devicetype;
6022  tdsaSASSubID_t    agSASSubID;
6023  tdsaDeviceData_t  *oneAttachedExpDeviceData = agNULL;
6024
6025  TI_DBG3(("tdsaPortSASDeviceAdd: start\n"));
6026  TI_DBG3(("tdsaPortSASDeviceAdd: connectionRate %d\n", connectionRate));
6027
6028  agSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
6029  agSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
6030  agSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
6031  agSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
6032
6033  /* old device and already registered to LL; added by link-up event */
6034  if ( agFALSE == tdssNewSASorNot(
6035                                   onePortContext->agRoot,
6036                                   onePortContext,
6037                                   &agSASSubID
6038                                   )
6039       )
6040  {
6041    /* old device and already registered to LL; added by link-up event */
6042    TI_DBG3(("tdsaPortSASDeviceAdd: OLD qqqq initiator_ssp_stp_smp %d target_ssp_stp_smp %d\n", agSASSubID.initiator_ssp_stp_smp, agSASSubID.target_ssp_stp_smp));
6043    /* find the old device */
6044    oneDeviceData = tdssNewAddSASToSharedcontext(
6045                                                 onePortContext->agRoot,
6046                                                 onePortContext,
6047                                                 &agSASSubID,
6048                                                 oneExpDeviceData,
6049                                                 phyID
6050                                                 );
6051
6052    if (oneDeviceData == agNULL)
6053    {
6054      TI_DBG1(("tdsaPortSASDeviceAdd: no more device!!! oneDeviceData is null\n"));
6055    }
6056
6057    /* If a device is allocated */
6058    if ( oneDeviceData != agNULL )
6059    {
6060
6061      TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify)));
6062      TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify)));
6063
6064      oneDeviceData->sasIdentify = sasIdentify;
6065
6066      TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
6067      TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
6068
6069      /* parse sasIDframe to fill in agDeviceInfo */
6070      DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT);
6071      DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)itNexusTimeout);
6072      DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, (bit16)firstBurstSize);
6073      DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 1);
6074
6075      oneDeviceData->SASSpecDeviceType = (bit8)(SA_IDFRM_GET_DEVICETTYPE(&sasIdentify));
6076
6077      /* adjusting connectionRate */
6078      oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
6079      if (oneAttachedExpDeviceData != agNULL)
6080      {
6081        connectionRate = (bit8)(MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6082        TI_DBG3(("tdsaPortSASDeviceAdd: 1st connectionRate 0x%x  DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n",
6083                 connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6084      }
6085      else
6086      {
6087       TI_DBG3(("tdsaPortSASDeviceAdd: 1st oneAttachedExpDeviceData is NULL\n"));
6088      }
6089
6090      /* Device Type, SAS or SATA, connection rate; bit7 --- bit0 */
6091      sasorsata = (bit8)deviceType;
6092      /* sTSDK spec device typ */
6093      dev_s_rate = (bit8)(dev_s_rate | (sasorsata << 4));
6094      dev_s_rate = (bit8)(dev_s_rate | connectionRate);
6095      DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate);
6096
6097
6098      DEVINFO_PUT_SAS_ADDRESSLO(
6099                                &oneDeviceData->agDeviceInfo,
6100                                SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)
6101                                );
6102      DEVINFO_PUT_SAS_ADDRESSHI(
6103                                &oneDeviceData->agDeviceInfo,
6104                                SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)
6105                                );
6106      oneDeviceData->agContext.osData = oneDeviceData;
6107      oneDeviceData->agContext.sdkData = agNULL;
6108
6109    }
6110    return oneDeviceData;
6111  } /* old device */
6112
6113  /* new device */
6114
6115  TI_DBG3(("tdsaPortSASDeviceAdd: NEW qqqq initiator_ssp_stp_smp %d target_ssp_stp_smp %d\n", agSASSubID.initiator_ssp_stp_smp, agSASSubID.target_ssp_stp_smp));
6116
6117  /* allocate a new device and set the valid bit */
6118  oneDeviceData = tdssNewAddSASToSharedcontext(
6119                                               onePortContext->agRoot,
6120                                               onePortContext,
6121                                               &agSASSubID,
6122                                               oneExpDeviceData,
6123                                               phyID
6124                                               );
6125
6126  if (oneDeviceData == agNULL)
6127  {
6128    TI_DBG1(("tdsaPortSASDeviceAdd: no more device!!! oneDeviceData is null\n"));
6129  }
6130
6131   /* If a device is allocated */
6132  if ( oneDeviceData != agNULL )
6133  {
6134
6135    TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify)));
6136    TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify)));
6137
6138    oneDeviceData->sasIdentify = sasIdentify;
6139
6140    TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
6141    TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
6142
6143
6144    /* parse sasIDframe to fill in agDeviceInfo */
6145    DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT);
6146    DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)itNexusTimeout);
6147    DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, (bit16)firstBurstSize);
6148    DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 1);
6149
6150    oneDeviceData->SASSpecDeviceType = (bit8)(SA_IDFRM_GET_DEVICETTYPE(&sasIdentify));
6151
6152    /* adjusting connectionRate */
6153    oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
6154    if (oneAttachedExpDeviceData != agNULL)
6155    {
6156      connectionRate = (bit8)(MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6157      TI_DBG3(("tdsaPortSASDeviceAdd: 2nd connectionRate 0x%x  DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n",
6158                connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6159    }
6160    else
6161    {
6162     TI_DBG3(("tdsaPortSASDeviceAdd: 2nd oneAttachedExpDeviceData is NULL\n"));
6163    }
6164
6165    /* Device Type, SAS or SATA, connection rate; bit7 --- bit0 */
6166    sasorsata = (bit8)deviceType;
6167    dev_s_rate = (bit8)(dev_s_rate | (sasorsata << 4));
6168    dev_s_rate = (bit8)(dev_s_rate | connectionRate);
6169    DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate);
6170
6171
6172    DEVINFO_PUT_SAS_ADDRESSLO(
6173                              &oneDeviceData->agDeviceInfo,
6174                              SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)
6175                              );
6176    DEVINFO_PUT_SAS_ADDRESSHI(
6177                              &oneDeviceData->agDeviceInfo,
6178                              SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)
6179                              );
6180    oneDeviceData->agContext.osData = oneDeviceData;
6181    oneDeviceData->agContext.sdkData = agNULL;
6182
6183    TI_DBG3(("tdsaPortSASDeviceAdd: did %d\n", oneDeviceData->id));
6184
6185    /* don't add and register initiator for T2D */
6186    if ( (((sasIdentify.initiator_ssp_stp_smp & DEVICE_SSP_BIT) == DEVICE_SSP_BIT) &&
6187         ((sasIdentify.target_ssp_stp_smp & DEVICE_SSP_BIT) != DEVICE_SSP_BIT))
6188        ||
6189         (((sasIdentify.initiator_ssp_stp_smp & DEVICE_STP_BIT) == DEVICE_STP_BIT) &&
6190         ((sasIdentify.target_ssp_stp_smp & DEVICE_SSP_BIT) != DEVICE_SSP_BIT))
6191       )
6192    {
6193      TI_DBG1(("tdsaPortSASDeviceAdd: initiator. no add and registration\n"));
6194      TI_DBG1(("tdsaPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
6195      TI_DBG1(("tdsaPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
6196
6197    }
6198    else
6199    {
6200      if (oneDeviceData->registered == agFALSE)
6201      {
6202        TI_DBG2(("tdsaPortSASDeviceAdd: did %d\n", oneDeviceData->id));
6203        saRegisterNewDevice( /* tdsaPortSASDeviceAdd  */
6204                            onePortContext->agRoot,
6205                            &oneDeviceData->agContext,
6206                            tdsaRotateQnumber(tiRoot, oneDeviceData),
6207                            &oneDeviceData->agDeviceInfo,
6208                            onePortContext->agPortContext,
6209                            0
6210                            );
6211      }
6212    }
6213  }
6214
6215  return oneDeviceData;
6216}
6217
6218/*****************************************************************************
6219*! \brief  tdsaDiscoveryResetProcessed
6220*
6221*  Purpose:  This function called to reset "processed flag" of device belong to
6222*            a specified port.
6223*
6224*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6225*                   instance.
6226*  \param   onePortContext: Pointer to the portal context instance.
6227*
6228*  \return:
6229*           None
6230*
6231*   \note:
6232*
6233*****************************************************************************/
6234
6235osGLOBAL void
6236tdsaDiscoveryResetProcessed(
6237                    tiRoot_t             *tiRoot,
6238                    tdsaPortContext_t    *onePortContext
6239                    )
6240{
6241  tdsaDeviceData_t  *oneDeviceData = agNULL;
6242  tdList_t          *DeviceListList;
6243  tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
6244  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
6245
6246  TI_DBG6(("tdsaDiscoveryResetProcessed: start\n"));
6247
6248  /* reinitialize the device data belonging to this portcontext */
6249  DeviceListList = tdsaAllShared->MainDeviceList.flink;
6250  while (DeviceListList != &(tdsaAllShared->MainDeviceList))
6251  {
6252    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6253    TI_DBG6(("tdsaDiscoveryResetProcessed: loop did %d\n", oneDeviceData->id));
6254    if (oneDeviceData->tdPortContext == onePortContext)
6255    {
6256      TI_DBG6(("tdsaDiscoveryResetProcessed: resetting procssed flag\n"));
6257      oneDeviceData->processed = agFALSE;
6258    }
6259    DeviceListList = DeviceListList->flink;
6260  }
6261
6262  return;
6263}
6264
6265/*****************************************************************************
6266*! \brief  tdsaSATADiscoverDone
6267*
6268*  Purpose:  This function called to finish up SATA discovery.
6269*
6270*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6271*                   instance.
6272*  \param   onePortContext: Pointer to the portal context instance.
6273*  \param   flag: status of discovery (success or failure).
6274*
6275*  \return:
6276*           None
6277*
6278*   \note:
6279*
6280*****************************************************************************/
6281osGLOBAL void
6282tdsaSATADiscoverDone(
6283                    tiRoot_t             *tiRoot,
6284                    tdsaPortContext_t    *onePortContext,
6285                    bit32                flag
6286                    )
6287{
6288  tdsaRoot_t           *tdsaRoot      = (tdsaRoot_t *) tiRoot->tdData;
6289  tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
6290  TI_DBG3(("tdsaSATADiscoverDone: start\n"));
6291  tdsaDiscoveryResetProcessed(tiRoot, onePortContext);
6292
6293  if (onePortContext->discovery.SeenBC == agTRUE)
6294  {
6295    TI_DBG3(("tdsaSATADiscoverDone: broadcast change; discover again\n"));
6296    tdssInternalRemovals(onePortContext->agRoot,
6297                         onePortContext
6298                         );
6299
6300    /* processed broadcast change */
6301    onePortContext->discovery.SeenBC = agFALSE;
6302    if (tdsaAllShared->ResetInDiscovery != 0 &&
6303        onePortContext->discovery.ResetTriggerred == agTRUE)
6304    {
6305      TI_DBG1(("tdsaSATADiscoverDone: tdsaBCTimer\n"));
6306      tdsaBCTimer(tiRoot, onePortContext);
6307    }
6308    else
6309    {
6310      tdsaDiscover(
6311                   tiRoot,
6312                   onePortContext,
6313                   TDSA_DISCOVERY_TYPE_SAS,
6314                   TDSA_DISCOVERY_OPTION_INCREMENTAL_START
6315                  );
6316    }
6317  }
6318  else
6319  {
6320    onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
6321
6322    if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
6323    {
6324      if (flag == tiSuccess)
6325      {
6326#ifdef AGTIAPI_CTL
6327        tdsaContext_t *tdsaAllShared =
6328                        &((tdsaRoot_t*)tiRoot->tdData)->tdsaAllShared;
6329
6330        if (tdsaAllShared->SASConnectTimeLimit)
6331          tdsaCTLSet(tiRoot, onePortContext, tiIntrEventTypeDiscovery,
6332                     tiDiscOK);
6333        else
6334#endif
6335          ostiInitiatorEvent(
6336                             tiRoot,
6337                             onePortContext->tiPortalContext,
6338                             agNULL,
6339                             tiIntrEventTypeDiscovery,
6340                             tiDiscOK,
6341                             agNULL
6342                             );
6343      }
6344      else
6345      {
6346        TI_DBG1(("tdsaSATADiscoverDone: Error; clean up\n"));
6347        tdssDiscoveryErrorRemovals(onePortContext->agRoot,
6348                                   onePortContext
6349                                   );
6350
6351        ostiInitiatorEvent(
6352                           tiRoot,
6353                           onePortContext->tiPortalContext,
6354                           agNULL,
6355                           tiIntrEventTypeDiscovery,
6356                           tiDiscFailed,
6357                           agNULL
6358                           );
6359      }
6360    }
6361    else
6362    {
6363      if (flag == tiSuccess)
6364      {
6365        tdssReportChanges(onePortContext->agRoot,
6366                          onePortContext
6367                          );
6368      }
6369      else
6370      {
6371        tdssReportRemovals(onePortContext->agRoot,
6372                           onePortContext,
6373                           agFALSE
6374                           );
6375      }
6376    }
6377  }
6378#ifdef TBD
6379  /* ACKing BC */
6380  tdsaAckBC(tiRoot, onePortContext);
6381#endif
6382  return;
6383}
6384
6385osGLOBAL void
6386tdsaAckBC(
6387                    tiRoot_t             *tiRoot,
6388                    tdsaPortContext_t    *onePortContext
6389                    )
6390{
6391#ifdef TBD /* not yet */
6392  agsaEventSource_t        eventSource[TD_MAX_NUM_PHYS];
6393  bit32                    HwAckSatus = AGSA_RC_SUCCESS;
6394  int                      i;
6395  TI_DBG3(("tdsaAckBC: start\n"));
6396
6397  for (i=0;i<TD_MAX_NUM_PHYS;i++)
6398  {
6399    if (onePortContext->BCPhyID[i] == agTRUE)
6400    {
6401      /* saHwEventAck() */
6402      eventSource[i].agPortContext = onePortContext->agPortContext;
6403      eventSource[i].event = OSSA_HW_EVENT_BROADCAST_CHANGE;
6404      /* phy ID */
6405      eventSource[i].param = i;
6406      HwAckSatus = saHwEventAck(
6407                                onePortContext->agRoot,
6408                                agNULL, /* agContext */
6409                                0,
6410                                &eventSource[i], /* agsaEventSource_t */
6411                                0,
6412                                0
6413                                );
6414      TI_DBG3(("tdsaAckBC: calling saHwEventAck\n"));
6415
6416      if ( HwAckSatus != AGSA_RC_SUCCESS)
6417      {
6418        TI_DBG1(("tdsaAckBC: failing in saHwEventAck; status %d\n", HwAckSatus));
6419        return;
6420      }
6421    }
6422    onePortContext->BCPhyID[i] = agFALSE;
6423  }
6424#endif
6425}
6426
6427#ifdef SATA_ENABLE
6428
6429/*****************************************************************************
6430*! \brief  tdsaSATAFullDiscover
6431*
6432*  Purpose:  This function is called to trigger full SATA topology discovery
6433*            within a portcontext.
6434*
6435*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6436*                   instance.
6437*  \param   onePortContext: Pointer to the portal context instance.
6438*
6439*  \return:
6440*           tiSuccess    Discovery initiated.
6441*           tiError      Discovery could not be initiated at this time.
6442*
6443*   \note:
6444*
6445*****************************************************************************/
6446osGLOBAL bit32
6447tdsaSATAFullDiscover(
6448                     tiRoot_t          *tiRoot,
6449                     tdsaPortContext_t *onePortContext
6450                     )
6451{
6452  bit32                 ret = tiSuccess;
6453  tdsaDeviceData_t      *oneDeviceData = agNULL;
6454  bit32                 deviceType;
6455  bit8                  phyRate = SAS_CONNECTION_RATE_3_0G;
6456  bit32                 i;
6457  tdsaRoot_t            *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
6458  tdsaContext_t         *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
6459//  tdsaDeviceData_t      *tdsaDeviceData  = (tdsaDeviceData_t *)tdsaAllShared->DeviceMem;
6460  tdsaDeviceData_t      *tdsaDeviceData;
6461  tdList_t              *DeviceListList;
6462
6463  TI_DBG3(("tdsaSATAFullDiscover: start\n"));
6464  if (onePortContext->valid == agFALSE)
6465  {
6466    TI_DBG1(("tdsaSATAFullDiscover: aborting discovery\n"));
6467    tdsaSASDiscoverAbort(tiRoot, onePortContext);
6468    return tiError;
6469  }
6470  phyRate = onePortContext->LinkRate;
6471  DeviceListList = tdsaAllShared->MainDeviceList.flink;
6472  tdsaDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6473  /*  If port is SATA mode */
6474  /*
6475    Native SATA mode is decided in ossaHWCB() SAS_LINK_UP or SATA_LINK_UP
6476   */
6477  if (onePortContext->nativeSATAMode == agTRUE)
6478  {
6479    /* Decode device type */
6480    deviceType = tdssSATADeviceTypeDecode(onePortContext->remoteSignature);
6481    /* Create a device descriptor for the SATA device attached to the port */
6482    if ( deviceType == SATA_PM_DEVICE)
6483    {
6484      TI_DBG3(("tdsaSATAFullDiscover: Found a PM device\n"));
6485      oneDeviceData = tdsaPortSATADeviceAdd(
6486                                            tiRoot,
6487                                            onePortContext,
6488                                            agNULL,
6489                                            onePortContext->remoteSignature,
6490                                            agTRUE,
6491                                            0xF,
6492                                            phyRate,
6493                                            agNULL,
6494                                            0xFF
6495                                            );
6496    }
6497    else
6498    {
6499      /* already added in ossahwcb() in SATA link up */
6500      TI_DBG3(("tdsaSATAFullDiscover: Found a DIRECT SATA device\n"));
6501    }
6502
6503    /* Process for different device type */
6504    switch ( deviceType )
6505    {
6506      /* if it's PM */
6507      case SATA_PM_DEVICE:
6508      {
6509
6510        TI_DBG3(("tdsaSATAFullDiscover: Process a PM device\n"));
6511        /* For each port of the PM */
6512        for ( i = 0; i < SATA_MAX_PM_PORTS; i ++ )
6513        {
6514          /* Read the signature */
6515          /* Decode the device type */
6516          /* Create device descriptor */
6517          /* Callback with the discovered devices */
6518        }
6519        break;
6520      }
6521      /* if it's ATA device */
6522      case SATA_ATA_DEVICE:
6523      case SATA_ATAPI_DEVICE:
6524      {
6525        TI_DBG3(("tdsaSATAFullDiscover: Process an ATA device. Sending Identify Device cmd\n"));
6526
6527        /* to-check: for this direct attached one, already added and do nothing */
6528        /* no longer, discovery sends sata identify device command */
6529        //tdsaSATAIdentifyDeviceCmdSend(tiRoot, oneDeviceData);
6530        tdsaSATADiscoverDone(tiRoot, onePortContext, tiSuccess);
6531        break;
6532      }
6533      /* Other devices */
6534      default:
6535      {
6536        /* callback */
6537        TI_DBG3(("siSATAFullDiscover: Process OTHER SATA device. Just report the device\n"));
6538        break;
6539      }
6540    }
6541  }
6542  /* If port is SAS mode */
6543  else
6544  {
6545    TI_DBG3(("tdsaSATAFullDiscover: Discovering attached STP devices  starts....\n"));
6546    oneDeviceData = tdsaFindRightDevice(tiRoot, onePortContext, tdsaDeviceData);
6547    tdsaDiscoveringStpSATADevice(tiRoot, onePortContext, oneDeviceData);
6548  }
6549  return ret;
6550}
6551
6552/* adding only direct attached SATA such as PM
6553  Other directly attached SATA device such as disk is reported by ossahwcb() in link up
6554  used in sata native mode
6555  */
6556/*****************************************************************************
6557*! \brief  tdsaPortSATADeviceAdd
6558*
6559*  Purpose:  This function adds the SATA device to the device list.
6560*
6561*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6562*                   instance.
6563*  \param   onePortContext: Pointer to the portal context instance.
6564*  \param   oneSTPBridge: STP bridge.
6565*  \param   Signature: SATA signature.
6566*  \param   pm: Port Multiplier.
6567*  \param   pmField: Port Multiplier field.
6568*  \param   connectionRate: Connection Rate.
6569*
6570*  \return:
6571*           Pointer to device data.
6572*
6573*   \note:
6574*
6575*****************************************************************************/
6576GLOBAL tdsaDeviceData_t *
6577tdsaPortSATADeviceAdd(
6578                      tiRoot_t                *tiRoot,
6579                      tdsaPortContext_t       *onePortContext,
6580                      tdsaDeviceData_t        *oneSTPBridge,
6581                      bit8                    *Signature,
6582                      bit8                    pm,
6583                      bit8                    pmField,
6584                      bit8                    connectionRate,
6585                      tdsaDeviceData_t        *oneExpDeviceData,
6586                      bit8                    phyID
6587                      )
6588{
6589  tdsaDeviceData_t      *oneDeviceData = agNULL;
6590  agsaRoot_t            *agRoot = onePortContext->agRoot;
6591  bit8                  dev_s_rate = 0;
6592  bit8                  sasorsata = SATA_DEVICE_TYPE;
6593//  bit8                  devicetype = 0;
6594  bit8                  flag = 0;
6595  bit8                  TLR = 0;
6596  tdsaDeviceData_t      *oneAttachedExpDeviceData = agNULL;
6597
6598  TI_DBG3(("tdsaPortSATADeviceAdd: start\n"));
6599
6600  /* sanity check */
6601  TD_ASSERT((agNULL != tiRoot), "");
6602  TD_ASSERT((agNULL != agRoot), "");
6603  TD_ASSERT((agNULL != onePortContext), "");
6604  TD_ASSERT((agNULL != Signature), "");
6605
6606  oneDeviceData = tdssNewAddSATAToSharedcontext(
6607                                                tiRoot,
6608                                                agRoot,
6609                                                onePortContext,
6610                                                agNULL,
6611                                                Signature,
6612                                                pm,
6613                                                pmField,
6614                                                connectionRate,
6615                                                oneExpDeviceData,
6616                                                phyID
6617                                                );
6618  if (oneDeviceData == agNULL)
6619  {
6620    TI_DBG1(("tdsaPortSATADeviceAdd: no more device!!! oneDeviceData is null\n"));
6621    return agNULL;
6622  }
6623
6624  flag = (bit8)((phyID << 4) | TLR);
6625  DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT);
6626  DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, 0xFFF);
6627  DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, 0);
6628  DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, flag);
6629
6630  /* adjusting connectionRate */
6631  oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
6632  if (oneAttachedExpDeviceData != agNULL)
6633  {
6634    connectionRate = (bit8)(MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6635    TI_DBG3(("tdsaPortSATADeviceAdd: 1st connectionRate 0x%x  DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n",
6636              connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6637  }
6638  else
6639  {
6640    TI_DBG3(("tdsaPortSATADeviceAdd: 1st oneAttachedExpDeviceData is NULL\n"));
6641  }
6642
6643   /* Device Type, SAS or SATA, connection rate; bit7 --- bit0*/
6644//   dev_s_rate = dev_s_rate | (devicetype << 6);
6645   dev_s_rate = (bit8)(dev_s_rate | (sasorsata << 4));
6646   dev_s_rate = (bit8)(dev_s_rate | connectionRate);
6647   DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate);
6648
6649   osti_memset(&oneDeviceData->agDeviceInfo.sasAddressHi, 0, 4);
6650   osti_memset(&oneDeviceData->agDeviceInfo.sasAddressLo, 0, 4);
6651
6652   oneDeviceData->agContext.osData = oneDeviceData;
6653   oneDeviceData->agContext.sdkData = agNULL;
6654
6655   TI_DBG1(("tdsaPortSATADeviceAdd: did %d\n", oneDeviceData->id));
6656   if (oneDeviceData->registered == agFALSE)
6657   {
6658     TI_DBG2(("tdsaPortSATADeviceAdd: did %d\n", oneDeviceData->id));
6659     saRegisterNewDevice( /* tdsaPortSATADeviceAdd */
6660                         onePortContext->agRoot,
6661                         &oneDeviceData->agContext,
6662                         tdsaRotateQnumber(tiRoot, oneDeviceData),
6663                         &oneDeviceData->agDeviceInfo,
6664                         onePortContext->agPortContext,
6665                         0
6666                         );
6667   }
6668
6669   return oneDeviceData;
6670}
6671#endif
6672
6673/*****************************************************************************
6674*! \brief  tdsaFindRightDevice
6675*
6676*  Purpose:  This function returns device-to-be processed.
6677*
6678*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6679*                   instance.
6680*  \param   onePortContext: Pointer to the portal context instance.
6681*  \param   tdsaDeviceData: Pointer to the starting device data.
6682*
6683*  \return:
6684*           Pointer to device data.
6685*
6686*   \note:
6687*
6688*****************************************************************************/
6689osGLOBAL tdsaDeviceData_t  *
6690tdsaFindRightDevice(
6691                   tiRoot_t               *tiRoot,
6692                   tdsaPortContext_t      *onePortContext,
6693                   tdsaDeviceData_t       *tdsaDeviceData
6694                   )
6695{
6696  tdList_t          *DeviceListList;
6697  tdsaDeviceData_t  *oneDeviceData = agNULL;
6698  bit32             found = agFALSE;
6699
6700  TI_DBG3(("tdsaFindHeadDevice: start\n"));
6701
6702  DeviceListList = tdsaDeviceData->MainLink.flink;
6703
6704  while (DeviceListList != &(tdsaDeviceData->MainLink))
6705  {
6706    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6707    TI_DBG3(("tdsaFindRightDevice: did %d STP %d SATA %d \n", onePortContext->id, DEVICE_IS_STP_TARGET(oneDeviceData), DEVICE_IS_SATA_DEVICE(oneDeviceData)));
6708    DeviceListList = DeviceListList->flink;
6709  }
6710
6711  DeviceListList = tdsaDeviceData->MainLink.flink;
6712
6713  while (DeviceListList != &(tdsaDeviceData->MainLink))
6714  {
6715    oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6716    if ((oneDeviceData->registered == agTRUE) &&
6717        (oneDeviceData->tdPortContext == onePortContext) &&
6718        (oneDeviceData->processed == agFALSE) &&
6719        (SA_IDFRM_IS_STP_TARGET(&oneDeviceData->sasIdentify) ||
6720         SA_IDFRM_IS_SATA_DEVICE(&oneDeviceData->sasIdentify))
6721        )
6722    {
6723      TI_DBG3(("tdsaFindRightDevice: pid %d did %d\n", onePortContext->id, oneDeviceData->id));
6724      oneDeviceData->processed = agTRUE;
6725      found = agTRUE;
6726      break;
6727    }
6728    DeviceListList = DeviceListList->flink;
6729  }
6730
6731  if (found == agTRUE)
6732  {
6733    return oneDeviceData;
6734  }
6735  else
6736  {
6737    return agNULL;
6738  }
6739}
6740
6741
6742
6743// tdsaDeviceData is head of list
6744/*****************************************************************************
6745*! \brief  tdsaDiscoveringStpSATADevice
6746*
6747*  Purpose:  For each device in the device list, this function peforms
6748*            SATA discovery.
6749*
6750*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6751*                   instance.
6752*  \param   onePortContext: Pointer to the portal context instance.
6753*  \param   oneDeviceData: Pointer to the heade of device list.
6754*
6755*  \return:
6756*           None
6757*
6758*   \note:
6759*
6760*****************************************************************************/
6761osGLOBAL void
6762tdsaDiscoveringStpSATADevice(
6763                             tiRoot_t               *tiRoot,
6764                             tdsaPortContext_t      *onePortContext,
6765                             tdsaDeviceData_t       *oneDeviceData
6766                             )
6767{
6768  bit32                 status;
6769  tdsaRoot_t            *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
6770  tdsaContext_t         *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
6771//  tdsaDeviceData_t      *tdsaDeviceData  = (tdsaDeviceData_t *)tdsaAllShared->DeviceMem;
6772  tdsaDeviceData_t      *tdsaDeviceData;
6773  tdList_t              *DeviceListList;
6774
6775  TI_DBG3(("tdsaDiscoveringStpSATADevice: start\n"));
6776
6777  DeviceListList = tdsaAllShared->MainDeviceList.flink;
6778  tdsaDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6779
6780  if (oneDeviceData)
6781  {
6782    TI_DBG3(("tdsaDiscoveringStpSATADevice: Found STP-SATA Device=%p\n", oneDeviceData));
6783    if ((SA_IDFRM_IS_SATA_DEVICE(&oneDeviceData->sasIdentify) || SA_IDFRM_IS_STP_TARGET(&oneDeviceData->sasIdentify))
6784         &&
6785        ((onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START &&
6786          oneDeviceData->valid == agTRUE) ||
6787        (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_INCREMENTAL_START &&
6788         oneDeviceData->valid2 == agTRUE)) &&
6789        (oneDeviceData->tdPortContext == onePortContext)
6790       )
6791    {
6792      /* if found an STP bridges */
6793      /* in order to get sata signature and etc */
6794      TI_DBG3(("tdsaDiscoveringStpSATADevice: sending report phy sata\n"));
6795      tdsaReportPhySataSend(tiRoot, oneDeviceData, oneDeviceData->sasIdentify.phyIdentifier);
6796      //send ID in every discovery? No
6797      if (oneDeviceData->satDevData.IDDeviceValid == agFALSE)
6798      {
6799        TI_DBG3(("tdsaDiscoveringStpSATADevice: sending identify device data\n"));
6800        /* all internal */
6801        status = tdsaDiscoveryStartIDDev(tiRoot,
6802                                         agNULL,
6803                                         &(oneDeviceData->tiDeviceHandle),
6804                                         agNULL,
6805                                         oneDeviceData);
6806
6807        if (status != tiSuccess)
6808        {
6809          /* identify device data is not valid */
6810          TI_DBG1(("tdsaDiscoveringStpSATADevice: fail or busy %d\n", status));
6811          oneDeviceData->satDevData.IDDeviceValid = agFALSE;
6812        }
6813      }
6814    }
6815    else
6816    {
6817      TI_DBG2(("tdsaDiscoveringStpSATADevice: moving to the next\n"));
6818      oneDeviceData = tdsaFindRightDevice(tiRoot, onePortContext, tdsaDeviceData);
6819      tdsaDiscoveringStpSATADevice(tiRoot, onePortContext, oneDeviceData);
6820    }
6821  }
6822  else
6823  {
6824    /* otherwise, there is no more SATA device found */
6825    TI_DBG3(("tdsaDiscoveringStpSATADevice: No More Device; SATA discovery finished\n"));
6826
6827    tdsaSATADiscoverDone(tiRoot, onePortContext, tiSuccess);
6828  }
6829
6830  return;
6831}
6832
6833/*****************************************************************************
6834*! \brief  tdsaSASIncrementalDiscover
6835*
6836*  Purpose:  This function is called to trigger incremental SAS topology discovery
6837*            within a portcontext.
6838*
6839*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6840*                   instance.
6841*  \param   onePortContext: Pointer to the portal context instance.
6842*
6843*  \return:
6844*           tiSuccess    Discovery initiated.
6845*           tiError      Discovery could not be initiated at this time.
6846*
6847*   \note:
6848*
6849*****************************************************************************/
6850osGLOBAL bit32
6851tdsaSASIncrementalDiscover(
6852                    tiRoot_t          *tiRoot,
6853                    tdsaPortContext_t *onePortContext
6854                    )
6855{
6856  tdsaDeviceData_t     *oneDeviceData  = agNULL;
6857  int                  i,j;
6858  bit8                 portMaxRate;
6859
6860  TI_DBG3(("tdsaSASIncrementalDiscover: start\n"));
6861
6862  if (onePortContext->valid == agFALSE)
6863  {
6864    TI_DBG1(("tdsaSASIncrementalDiscover: aborting discovery\n"));
6865    tdsaSASDiscoverAbort(tiRoot, onePortContext);
6866    return tiError;
6867  }
6868
6869  onePortContext->DiscoveryState = ITD_DSTATE_STARTED;
6870
6871  /* nativeSATAMode is set in ossaHwCB() in link up */
6872  if (onePortContext->nativeSATAMode == agFALSE) /* default: SAS and SAS/SATA mode */
6873  {
6874    if (SA_IDFRM_GET_DEVICETTYPE(&onePortContext->sasIDframe) == SAS_END_DEVICE &&
6875        SA_IDFRM_IS_SSP_TARGET(&onePortContext->sasIDframe) )
6876    {
6877      for(i=0;i<TD_MAX_NUM_PHYS;i++)
6878      {
6879        if (onePortContext->PhyIDList[i] == agTRUE)
6880        {
6881
6882          for (j=0;j<TD_MAX_NUM_NOTIFY_SPINUP;j++)
6883          {
6884            saLocalPhyControl(onePortContext->agRoot, agNULL, tdsaRotateQnumber(tiRoot, agNULL), i, AGSA_PHY_NOTIFY_ENABLE_SPINUP, agNULL);
6885          }
6886          break;
6887        }
6888      }
6889    }
6890    /*
6891      add the device
6892      1. add device in TD layer
6893      2. call saRegisterNewDevice
6894      3. update agDevHandle in ossaDeviceRegistrationCB()
6895    */
6896    portMaxRate = onePortContext->LinkRate;
6897    oneDeviceData = tdsaPortSASDeviceAdd(
6898                                         tiRoot,
6899                                         onePortContext,
6900                                         onePortContext->sasIDframe,
6901                                         agFALSE,
6902                                         portMaxRate,
6903                                         IT_NEXUS_TIMEOUT,
6904                                         0,
6905                                         SAS_DEVICE_TYPE,
6906                                         agNULL,
6907                                         0xFF
6908                                         );
6909    if (oneDeviceData)
6910    {
6911      if (oneDeviceData->registered == agFALSE)
6912      {
6913        /*
6914          set the timer and wait till the device(directly attached. eg Expander) to be registered.
6915          Then, in tdsaDeviceRegistrationTimerCB(), tdsaSASUpStreamDiscoverStart() is called
6916        */
6917        tdsaDeviceRegistrationTimer(tiRoot, onePortContext, oneDeviceData);
6918      }
6919      else
6920      {
6921        tdsaSASUpStreamDiscoverStart(tiRoot, onePortContext, oneDeviceData);
6922      }
6923    }
6924  }
6925  else /* SATAOnlyMode*/
6926  {
6927    tdsaSASDiscoverDone(tiRoot, onePortContext, tiSuccess);
6928  }
6929  return tiSuccess;
6930}
6931
6932#ifdef SATA_ENABLE
6933/* For the sake of completness; this is the same as  tdsaSATAFullDiscover*/
6934/*****************************************************************************
6935*! \brief  tdsaSATAIncrementalDiscover
6936*
6937*  Purpose:  This function is called to trigger incremental SATA topology discovery
6938*            within a portcontext.
6939*
6940*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6941*                   instance.
6942*  \param   onePortContext: Pointer to the portal context instance.
6943*
6944*  \return:
6945*           tiSuccess    Discovery initiated.
6946*           tiError      Discovery could not be initiated at this time.
6947*
6948*   \note:
6949*
6950*****************************************************************************/
6951osGLOBAL bit32
6952tdsaSATAIncrementalDiscover(
6953                            tiRoot_t          *tiRoot,
6954                            tdsaPortContext_t *onePortContext
6955                           )
6956{
6957  bit32                 ret = tiSuccess;
6958  tdsaDeviceData_t      *oneDeviceData = agNULL;
6959  bit32                 deviceType;
6960  bit8                  phyRate = SAS_CONNECTION_RATE_3_0G;
6961  bit32                 i;
6962  tdsaRoot_t            *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
6963  tdsaContext_t         *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
6964//  tdsaDeviceData_t      *tdsaDeviceData  = (tdsaDeviceData_t *)tdsaAllShared->DeviceMem;
6965  tdsaDeviceData_t      *tdsaDeviceData;
6966  tdList_t              *DeviceListList;
6967
6968  TI_DBG3(("tdsaSATAIncrementalDiscover: start\n"));
6969
6970  if (onePortContext->valid == agFALSE)
6971  {
6972    TI_DBG1(("tdsaSATAIncrementalDiscover: aborting discovery\n"));
6973    tdsaSASDiscoverAbort(tiRoot, onePortContext);
6974    return tiError;
6975  }
6976
6977  DeviceListList = tdsaAllShared->MainDeviceList.flink;
6978  tdsaDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6979
6980  /*  If port is SATA mode */
6981  /*
6982    Native SATA mode is decided in ossaHWCB() SAS_LINK_UP or SATA_LINK_UP
6983   */
6984  if (onePortContext->nativeSATAMode == agTRUE)
6985  {
6986    /* Decode device type */
6987    deviceType = tdssSATADeviceTypeDecode(onePortContext->remoteSignature);
6988    /* Create a device descriptor for the SATA device attached to the port */
6989    if ( deviceType == SATA_PM_DEVICE)
6990    {
6991      TI_DBG3(("tdsaSATAIncrementalDiscover: Found a PM device\n"));
6992      oneDeviceData = tdsaPortSATADeviceAdd(
6993                                            tiRoot,
6994                                            onePortContext,
6995                                            agNULL,
6996                                            onePortContext->remoteSignature,
6997                                            agTRUE,
6998                                            0xF,
6999                                            phyRate,
7000                                            agNULL,
7001                                            0xFF);
7002    }
7003    else
7004    {
7005      /* already added in ossahwcb() in SATA link up */
7006      TI_DBG3(("tdsaSATAIncrementalDiscover: Found a DIRECT SATA device\n"));
7007    }
7008
7009    /* Process for different device type */
7010    switch ( deviceType )
7011    {
7012      /* if it's PM */
7013      case SATA_PM_DEVICE:
7014      {
7015
7016        TI_DBG3(("tdsaSATAIncrementalDiscover: Process a PM device\n"));
7017        /* For each port of the PM */
7018        for ( i = 0; i < SATA_MAX_PM_PORTS; i ++ )
7019        {
7020          /* Read the signature */
7021          /* Decode the device type */
7022          /* Create device descriptor */
7023          /* Callback with the discovered devices */
7024        }
7025        break;
7026      }
7027      /* if it's ATA device */
7028      case SATA_ATA_DEVICE:
7029      case SATA_ATAPI_DEVICE:
7030      {
7031        TI_DBG3(("tdsaSATAIncrementalDiscover: Process an ATA device. Sending Identify Device cmd\n"));
7032
7033        /* to-check: for this direct attached one, already added and do nothing */
7034        /* no longer, discovery sends sata identify device command */
7035        //tdsaSATAIdentifyDeviceCmdSend(tiRoot, oneDeviceData);
7036
7037        tdsaSATADiscoverDone(tiRoot, onePortContext, tiSuccess);
7038
7039        break;
7040      }
7041      /* Other devices */
7042      default:
7043      {
7044        /* callback */
7045        TI_DBG3(("siSATAIncrementalDiscover: Process OTHER SATA device. Just report the device\n"));
7046
7047        break;
7048      }
7049    }
7050  }
7051  /* If port is SAS mode */
7052  else
7053  {
7054    TI_DBG3(("tdsaSATAIncrementalDiscover: Discovering attached STP devices  starts....\n"));
7055    oneDeviceData = tdsaFindRightDevice(tiRoot, onePortContext, tdsaDeviceData);
7056
7057    tdsaDiscoveringStpSATADevice(tiRoot, onePortContext, oneDeviceData);
7058  }
7059  return ret;
7060
7061}
7062#endif
7063
7064
7065/********************  SMP *******************************/
7066
7067/*****************************************************************************
7068*! \brief  tdSMPStart
7069*
7070*  Purpose:  This function sends SMP request.
7071*
7072*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7073*                   instance.
7074*  \param   agRoot: Pointer to chip/driver Instance.
7075*  \param   oneDeviceData: Pointer to the device data.
7076*  \param   functionCode: SMP function code.
7077*  \param   pSmpBody: Pointer to SMP payload.
7078*  \param   smpBodySize: Size of SMP request without SMP header.
7079*  \param   agRequestType: SPC-specfic request type
7080*
7081*  \return:
7082*           tiSuccess  SMP is sent successfully
7083*           tiError    SMP is not sent successfully
7084*
7085*   \note:
7086*
7087*****************************************************************************/
7088osGLOBAL bit32
7089tdSMPStart(
7090           tiRoot_t              *tiRoot,
7091           agsaRoot_t            *agRoot,
7092           tdsaDeviceData_t      *oneDeviceData,
7093           bit32                 functionCode,
7094           bit8                  *pSmpBody, /* smp payload itself w/o first 4 bytes(header) */
7095           bit32                 smpBodySize, /* smp payload size w/o first 4 bytes(header) */
7096           bit32                 agRequestType,
7097           tiIORequest_t         *CurrentTaskTag,
7098           bit32                 queueNumber
7099           )
7100{
7101  void                        *osMemHandle;
7102  bit32                       PhysUpper32;
7103  bit32                       PhysLower32;
7104  bit32                       memAllocStatus;
7105  bit32                       expectedRspLen = 0;
7106
7107#ifdef REMOVED
7108  tdsaRoot_t                  *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
7109  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared);
7110#endif
7111  tdssSMPRequestBody_t        *tdSMPRequestBody;
7112  agsaSASRequestBody_t        *agSASRequestBody;
7113  agsaSMPFrame_t              *agSMPFrame;
7114  agsaIORequest_t             *agIORequest;
7115  agsaDevHandle_t             *agDevHandle;
7116  tdssSMPFrameHeader_t        tdSMPFrameHeader;
7117  tdsaPortContext_t           *onePortContext = agNULL;
7118  bit32                       status;
7119
7120#ifndef DIRECT_SMP
7121  void                        *IndirectSMPReqosMemHandle;
7122  bit32                       IndirectSMPReqPhysUpper32;
7123  bit32                       IndirectSMPReqPhysLower32;
7124  bit32                       IndirectSMPReqmemAllocStatus;
7125  bit8                        *IndirectSMPReq;
7126
7127  void                        *IndirectSMPResposMemHandle;
7128  bit32                       IndirectSMPRespPhysUpper32;
7129  bit32                       IndirectSMPRespPhysLower32;
7130  bit32                       IndirectSMPRespmemAllocStatus;
7131  bit8                        *IndirectSMPResp;
7132#endif
7133
7134  TI_DBG3(("tdSMPStart: start\n"));
7135  TI_DBG3(("tdSMPStart: oneDeviceData %p\n", oneDeviceData));
7136  TI_DBG3(("tdSMPStart: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
7137  TI_DBG3(("tdSMPStart: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
7138  TI_DBG3(("tdSMPStart: 2nd sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
7139  TI_DBG3(("tdSMPStart: 2nd sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
7140
7141  onePortContext = oneDeviceData->tdPortContext;
7142
7143  if (onePortContext != agNULL)
7144  {
7145    TI_DBG3(("tdSMPStart: pid %d\n", onePortContext->id));
7146    /* increment the number of pending SMP */
7147    onePortContext->discovery.pendingSMP++;
7148  }
7149  else
7150  {
7151    TI_DBG1(("tdSMPStart: Wrong!!! onePortContext is NULL\n"));
7152    return tiError;
7153  }
7154
7155
7156
7157  memAllocStatus = ostiAllocMemory(
7158                                   tiRoot,
7159                                   &osMemHandle,
7160                                   (void **)&tdSMPRequestBody,
7161                                   &PhysUpper32,
7162                                   &PhysLower32,
7163                                   8,
7164                                   sizeof(tdssSMPRequestBody_t),
7165                                   agTRUE
7166                                   );
7167
7168  if (memAllocStatus != tiSuccess)
7169  {
7170    TI_DBG1(("tdSMPStart: ostiAllocMemory failed...\n"));
7171    return tiError;
7172  }
7173
7174  if (tdSMPRequestBody == agNULL)
7175  {
7176    TI_DBG1(("tdSMPStart: ostiAllocMemory returned NULL tdSMPRequestBody\n"));
7177    return tiError;
7178  }
7179  /* saves mem handle for freeing later */
7180  tdSMPRequestBody->osMemHandle = osMemHandle;
7181
7182  /* saves tdsaDeviceData */
7183  tdSMPRequestBody->tdDevice = oneDeviceData;
7184
7185  /* saving port id */
7186  tdSMPRequestBody->tdPortContext = onePortContext;
7187
7188
7189  agDevHandle = oneDeviceData->agDevHandle;
7190
7191  /* save the callback funtion */
7192  tdSMPRequestBody->SMPCompletionFunc = itdssSMPCompleted; /* in itdcb.c */
7193
7194  /* for simulate warm target reset */
7195  tdSMPRequestBody->CurrentTaskTag = CurrentTaskTag;
7196
7197  /* initializes the number of SMP retries */
7198  tdSMPRequestBody->retries = 0;
7199
7200#ifdef TD_INTERNAL_DEBUG  /* debugging */
7201  TI_DBG4(("tdSMPStart: SMPRequestbody %p\n", tdSMPRequestBody));
7202  TI_DBG4(("tdSMPStart: callback fn %p\n", tdSMPRequestBody->SMPCompletionFunc));
7203#endif
7204
7205  agIORequest = &(tdSMPRequestBody->agIORequest);
7206  agIORequest->osData = (void *) tdSMPRequestBody;
7207  agIORequest->sdkData = agNULL; /* SALL takes care of this */
7208
7209
7210  agSASRequestBody = &(tdSMPRequestBody->agSASRequestBody);
7211  agSMPFrame = &(agSASRequestBody->smpFrame);
7212
7213  TI_DBG3(("tdSMPStart: agIORequest %p\n", agIORequest));
7214  TI_DBG3(("tdSMPStart: SMPRequestbody %p\n", tdSMPRequestBody));
7215
7216  /*
7217    depending on functionCode, set expectedRspLen in smp
7218  */
7219  switch (functionCode)
7220  {
7221  case SMP_REPORT_GENERAL:
7222    expectedRspLen = sizeof(smpRespReportGeneral_t) + 4;
7223    break;
7224  case SMP_REPORT_MANUFACTURE_INFORMATION:
7225    expectedRspLen = sizeof(smpRespReportManufactureInfo_t) + 4;
7226    break;
7227  case SMP_DISCOVER:
7228    expectedRspLen = sizeof(smpRespDiscover_t) + 4;
7229    break;
7230  case SMP_REPORT_PHY_ERROR_LOG:
7231    expectedRspLen = 32 - 4;
7232    break;
7233  case SMP_REPORT_PHY_SATA:
7234    expectedRspLen = sizeof(smpRespReportPhySata_t) + 4;
7235    break;
7236  case SMP_REPORT_ROUTING_INFORMATION:
7237    expectedRspLen = sizeof(smpRespReportRouteTable_t) + 4;
7238    break;
7239  case SMP_CONFIGURE_ROUTING_INFORMATION:
7240    expectedRspLen = 4;
7241    break;
7242  case SMP_PHY_CONTROL:
7243    expectedRspLen = 4;
7244    break;
7245  case SMP_PHY_TEST_FUNCTION:
7246    expectedRspLen = 4;
7247    break;
7248  case SMP_PMC_SPECIFIC:
7249    expectedRspLen = 4;
7250    break;
7251  default:
7252    expectedRspLen = 0;
7253    TI_DBG1(("tdSMPStart: error!!! undefined or unused smp function code 0x%x\n", functionCode));
7254    return tiError;
7255  }
7256
7257  if (tiIS_SPC(agRoot))
7258  {
7259#ifdef DIRECT_SMP  /* direct SMP with 48 or less payload */
7260  if ( (smpBodySize + 4) <= SMP_DIRECT_PAYLOAD_LIMIT) /* 48 */
7261  {
7262    TI_DBG3(("tdSMPStart: DIRECT smp payload\n"));
7263    osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t));
7264    osti_memset(tdSMPRequestBody->smpPayload, 0, SMP_DIRECT_PAYLOAD_LIMIT);
7265
7266    /* SMP header */
7267    tdSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
7268    tdSMPFrameHeader.smpFunction = (bit8)functionCode;
7269    tdSMPFrameHeader.smpFunctionResult = 0;
7270    tdSMPFrameHeader.smpReserved = 0;
7271
7272    osti_memcpy(tdSMPRequestBody->smpPayload, &tdSMPFrameHeader, 4);
7273//    osti_memcpy((tdSMPRequestBody->smpPayload)+4, pSmpBody, smpBodySize);
7274    osti_memcpy(&(tdSMPRequestBody->smpPayload[4]), pSmpBody, smpBodySize);
7275
7276    /* direct SMP payload eg) REPORT_GENERAL, DISCOVER etc */
7277    agSMPFrame->outFrameBuf = tdSMPRequestBody->smpPayload;
7278    agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */
7279    /* to specify DIRECT SMP response */
7280    agSMPFrame->inFrameLen = 0;
7281
7282    /* temporary solution for T2D Combo*/
7283#if defined (INITIATOR_DRIVER) && defined (TARGET_DRIVER)
7284    /* force smp repsonse to be direct */
7285    agSMPFrame->expectedRespLen = 0;
7286#else
7287    agSMPFrame->expectedRespLen = expectedRspLen;
7288#endif
7289//    tdhexdump("tdSMPStart", (bit8*)agSMPFrame->outFrameBuf, agSMPFrame->outFrameLen);
7290//    tdhexdump("tdSMPStart new", (bit8*)tdSMPRequestBody->smpPayload, agSMPFrame->outFrameLen);
7291//    tdhexdump("tdSMPStart - tdSMPRequestBody", (bit8*)tdSMPRequestBody, sizeof(tdssSMPRequestBody_t));
7292  }
7293  else
7294  {
7295    TI_DBG3(("tdSMPStart: INDIRECT smp payload\n"));
7296  }
7297
7298#else
7299
7300  /* indirect SMP */
7301  /* allocate Direct SMP request payload */
7302  IndirectSMPReqmemAllocStatus = ostiAllocMemory(
7303                                   tiRoot,
7304                                   &IndirectSMPReqosMemHandle,
7305                                   (void **)&IndirectSMPReq,
7306                                   &IndirectSMPReqPhysUpper32,
7307                                   &IndirectSMPReqPhysLower32,
7308                                   8,
7309                                   smpBodySize + 4,
7310                                   agFALSE
7311                                   );
7312
7313  if (IndirectSMPReqmemAllocStatus != tiSuccess)
7314  {
7315    TI_DBG1(("tdSMPStart: ostiAllocMemory failed for indirect SMP request...\n"));
7316    return tiError;
7317  }
7318
7319  if (IndirectSMPReq == agNULL)
7320  {
7321    TI_DBG1(("tdSMPStart: ostiAllocMemory returned NULL IndirectSMPReq\n"));
7322    return tiError;
7323  }
7324
7325  /* allocate indirect SMP response payload */
7326  IndirectSMPRespmemAllocStatus = ostiAllocMemory(
7327                                   tiRoot,
7328                                   &IndirectSMPResposMemHandle,
7329                                   (void **)&IndirectSMPResp,
7330                                   &IndirectSMPRespPhysUpper32,
7331                                   &IndirectSMPRespPhysLower32,
7332                                   8,
7333                                   expectedRspLen,
7334                                   agFALSE
7335                                   );
7336
7337  if (IndirectSMPRespmemAllocStatus != tiSuccess)
7338  {
7339    TI_DBG1(("tdSMPStart: ostiAllocMemory failed for indirect SMP reponse...\n"));
7340    return tiError;
7341  }
7342
7343  if (IndirectSMPResp == agNULL)
7344  {
7345    TI_DBG1(("tdSMPStart: ostiAllocMemory returned NULL IndirectSMPResp\n"));
7346    return tiError;
7347  }
7348
7349  /* saves mem handle for freeing later */
7350  tdSMPRequestBody->IndirectSMPReqosMemHandle = IndirectSMPReqosMemHandle;
7351  tdSMPRequestBody->IndirectSMPResposMemHandle = IndirectSMPResposMemHandle;
7352
7353  /* saves Indirect SMP request/repsonse pointer and length for free them later */
7354  tdSMPRequestBody->IndirectSMPReq = IndirectSMPReq;
7355  tdSMPRequestBody->IndirectSMPResp = IndirectSMPResp;
7356  tdSMPRequestBody->IndirectSMPReqLen = smpBodySize + 4;
7357  tdSMPRequestBody->IndirectSMPRespLen = expectedRspLen;
7358
7359  /* fill in indirect SMP request fields */
7360  TI_DBG3(("tdSMPStart: INDIRECT smp payload\n"));
7361
7362  /* SMP request and response initialization */
7363  osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t));
7364  osti_memset(IndirectSMPReq, 0, smpBodySize + 4);
7365  osti_memset(IndirectSMPResp, 0, expectedRspLen);
7366
7367  /* SMP request header */
7368  tdSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
7369  tdSMPFrameHeader.smpFunction = (bit8)functionCode;
7370  tdSMPFrameHeader.smpFunctionResult = 0;
7371  tdSMPFrameHeader.smpReserved = 0;
7372
7373  osti_memcpy(IndirectSMPReq, &tdSMPFrameHeader, 4);
7374  osti_memcpy(IndirectSMPReq+4, pSmpBody, smpBodySize);
7375
7376  /* Indirect SMP request */
7377  agSMPFrame->outFrameBuf = agNULL;
7378  agSMPFrame->outFrameAddrUpper32 = IndirectSMPReqPhysUpper32;
7379  agSMPFrame->outFrameAddrLower32 = IndirectSMPReqPhysLower32;
7380  agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */
7381
7382  /* Indirect SMP response */
7383  agSMPFrame->expectedRespLen = expectedRspLen;
7384  agSMPFrame->inFrameLen = expectedRspLen; /* without last 4 byte crc */
7385  agSMPFrame->inFrameAddrUpper32 = IndirectSMPRespPhysUpper32;
7386  agSMPFrame->inFrameAddrLower32 = IndirectSMPRespPhysLower32;
7387#endif
7388  }
7389  else /* SPCv controller */
7390  {
7391    /* only direct mode for both request and response */
7392    TI_DBG3(("tdSMPStart: DIRECT smp payload\n"));
7393    agSMPFrame->flag = 0;
7394    osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t));
7395    osti_memset(tdSMPRequestBody->smpPayload, 0, SMP_DIRECT_PAYLOAD_LIMIT);
7396
7397    /* SMP header */
7398    tdSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
7399    tdSMPFrameHeader.smpFunction = (bit8)functionCode;
7400    tdSMPFrameHeader.smpFunctionResult = 0;
7401    tdSMPFrameHeader.smpReserved = 0;
7402
7403    osti_memcpy(tdSMPRequestBody->smpPayload, &tdSMPFrameHeader, 4);
7404//    osti_memcpy((tdSMPRequestBody->smpPayload)+4, pSmpBody, smpBodySize);
7405    osti_memcpy(&(tdSMPRequestBody->smpPayload[4]), pSmpBody, smpBodySize);
7406
7407    /* direct SMP payload eg) REPORT_GENERAL, DISCOVER etc */
7408    agSMPFrame->outFrameBuf = tdSMPRequestBody->smpPayload;
7409    agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */
7410    /* to specify DIRECT SMP response */
7411    agSMPFrame->inFrameLen = 0;
7412
7413    /* temporary solution for T2D Combo*/
7414#if defined (INITIATOR_DRIVER) && defined (TARGET_DRIVER)
7415    /* force smp repsonse to be direct */
7416    agSMPFrame->expectedRespLen = 0;
7417#else
7418    agSMPFrame->expectedRespLen = expectedRspLen;
7419#endif
7420//    tdhexdump("tdSMPStart", (bit8*)agSMPFrame->outFrameBuf, agSMPFrame->outFrameLen);
7421//    tdhexdump("tdSMPStart new", (bit8*)tdSMPRequestBody->smpPayload, agSMPFrame->outFrameLen);
7422//    tdhexdump("tdSMPStart - tdSMPRequestBody", (bit8*)tdSMPRequestBody, sizeof(tdssSMPRequestBody_t));
7423  }
7424
7425
7426  if (agDevHandle == agNULL)
7427  {
7428    TI_DBG1(("tdSMPStart: !!! agDevHandle is NULL !!! \n"));
7429    return tiError;
7430  }
7431
7432  tdSMPRequestBody->queueNumber = queueNumber;
7433  status = saSMPStart(
7434                      agRoot,
7435                      agIORequest,
7436                      queueNumber, //tdsaAllShared->SMPQNum, //tdsaRotateQnumber(tiRoot, oneDeviceData),
7437                      agDevHandle,
7438                      agRequestType,
7439                      agSASRequestBody,
7440                      &ossaSMPCompleted
7441                      );
7442
7443  if (status == AGSA_RC_SUCCESS)
7444  {
7445    /* start SMP timer */
7446    if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER ||
7447        functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION
7448        )
7449    {
7450      tdsaDiscoverySMPTimer(tiRoot, onePortContext, functionCode, tdSMPRequestBody);
7451    }
7452    return tiSuccess;
7453  }
7454  else if (status == AGSA_RC_BUSY)
7455  {
7456    /* set timer */
7457    if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER ||
7458        functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION)
7459    {
7460      /* only for discovery related SMPs*/
7461      tdsaSMPBusyTimer(tiRoot, onePortContext, oneDeviceData, tdSMPRequestBody);
7462      return tiSuccess;
7463    }
7464    else if (functionCode == SMP_PHY_CONTROL)
7465    {
7466      ostiFreeMemory(
7467                     tiRoot,
7468                     osMemHandle,
7469                     sizeof(tdssSMPRequestBody_t)
7470                     );
7471      return tiBusy;
7472    }
7473    else
7474    {
7475      ostiFreeMemory(
7476                     tiRoot,
7477                     osMemHandle,
7478                     sizeof(tdssSMPRequestBody_t)
7479                     );
7480      return tiBusy;
7481    }
7482  }
7483  else /* AGSA_RC_FAILURE */
7484  {
7485    /* discovery failure or task management failure */
7486    if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER ||
7487        functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION)
7488    {
7489      tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
7490    }
7491    ostiFreeMemory(
7492                   tiRoot,
7493                   osMemHandle,
7494                   sizeof(tdssSMPRequestBody_t)
7495                   );
7496
7497    return tiError;
7498  }
7499}
7500
7501#ifdef REMOVED
7502/*****************************************************************************
7503*! \brief  tdsaFindLocalLinkRate
7504*
7505*  Purpose:  This function finds local link rate.
7506*
7507*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7508*                   instance.
7509*  \param   tdsaPortStartInfo: Pointer to the port start information.
7510*
7511*  \return:
7512*           None
7513*
7514*   \note:
7515*
7516*****************************************************************************/
7517osGLOBAL bit8
7518tdsaFindLocalLinkRate(
7519                    tiRoot_t                  *tiRoot,
7520                    tdsaPortStartInfo_t       *tdsaPortStartInfo
7521                    )
7522{
7523  bit8 ans = SAS_CONNECTION_RATE_3_0G; /* default */
7524  bit32 phyProperties;
7525
7526  phyProperties = tdsaPortStartInfo->agPhyConfig.phyProperties;
7527
7528  TI_DBG3(("tdsaFindLocalLinkRate: start\n"));
7529  if (phyProperties & 0x4)
7530  {
7531    ans = SAS_CONNECTION_RATE_6_0G;
7532  }
7533  if (phyProperties & 0x2)
7534  {
7535    ans = SAS_CONNECTION_RATE_3_0G;
7536  }
7537  if (phyProperties & 0x1)
7538  {
7539    ans = SAS_CONNECTION_RATE_1_5G;
7540  }
7541  TI_DBG3(("tdsaFindLocalLinkRate: ans 0x%x\n", ans));
7542  return ans;
7543}
7544#endif
7545/*****************************************************************************
7546*! \brief  tdsaConfigureRouteTimer
7547*
7548*  Purpose:  This function sets timers for configuring routing of discovery and
7549*            its callback function.
7550*
7551*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7552*                   instance.
7553*  \param   onePortContext: Pointer to the portal context instance.
7554*  \param   oneExpander: Pointer to the expander.
7555*  \param   ptdSMPDiscoverResp: Pointer to SMP discover repsonse data.
7556*
7557*  \return:
7558*           None
7559*
7560*   \note: called by tdsaDiscoverRespRcvd()
7561*
7562*****************************************************************************/
7563osGLOBAL void
7564tdsaConfigureRouteTimer(tiRoot_t                 *tiRoot,
7565                        tdsaPortContext_t        *onePortContext,
7566                        tdsaExpander_t           *oneExpander,
7567                        smpRespDiscover_t        *ptdSMPDiscoverResp
7568                        )
7569{
7570  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
7571  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
7572  itdsaIni_t                  *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
7573  tdsaDiscovery_t             *discovery;
7574
7575  TI_DBG1(("tdsaConfigureRouteTimer: start\n"));
7576  TI_DBG1(("tdsaConfigureRouteTimer: pid %d\n", onePortContext->id));
7577
7578  discovery = &(onePortContext->discovery);
7579
7580  TI_DBG1(("tdsaConfigureRouteTimer: onePortContext %p oneExpander %p ptdSMPDiscoverResp %p\n", onePortContext, oneExpander, ptdSMPDiscoverResp));
7581
7582  TI_DBG1(("tdsaConfigureRouteTimer: discovery %p \n", discovery));
7583
7584  TI_DBG1(("tdsaConfigureRouteTimer:  pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries));
7585
7586  TI_DBG1(("tdsaConfigureRouteTimer: discovery->status %d\n", discovery->status));
7587
7588  if (discovery->configureRouteTimer.timerRunning == agTRUE)
7589  {
7590    tdsaKillTimer(
7591              tiRoot,
7592              &discovery->configureRouteTimer
7593              );
7594  }
7595
7596  TI_DBG1(("tdsaConfigureRouteTimer: UsecsPerTick %d\n", Initiator->OperatingOption.UsecsPerTick));
7597  TI_DBG1(("tdsaConfigureRouteTimer: Timervalue %d\n", CONFIGURE_ROUTE_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick));
7598
7599  tdsaSetTimerRequest(
7600                    tiRoot,
7601                    &discovery->configureRouteTimer,
7602                    CONFIGURE_ROUTE_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
7603                    tdsaConfigureRouteTimerCB,
7604                    (void *)onePortContext,
7605                    (void *)oneExpander,
7606                    (void *)ptdSMPDiscoverResp
7607                   );
7608
7609  tdsaAddTimer (
7610              tiRoot,
7611              &Initiator->timerlist,
7612              &discovery->configureRouteTimer
7613              );
7614
7615  return;
7616}
7617
7618/*****************************************************************************
7619*! \brief  tdsaConfigureRouteTimerCB
7620*
7621*  Purpose:  This function is callback function for tdsaConfigureRouteTimer.
7622*
7623*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7624*                   instance.
7625*  \param   timerData1: Pointer to timer-related data structure
7626*  \param   timerData2: Pointer to timer-related data structure
7627*  \param   timerData3: Pointer to timer-related data structure
7628*
7629*  \return:
7630*           None
7631*
7632*   \note:
7633*
7634*****************************************************************************/
7635osGLOBAL void
7636tdsaConfigureRouteTimerCB(
7637                          tiRoot_t    * tiRoot,
7638                          void        * timerData1,
7639                          void        * timerData2,
7640                          void        * timerData3
7641                         )
7642{
7643  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
7644  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
7645  itdsaIni_t                  *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
7646  tdsaPortContext_t           *onePortContext;
7647  tdsaExpander_t              *oneExpander;
7648  smpRespDiscover_t           *ptdSMPDiscoverResp;
7649  tdsaDiscovery_t             *discovery;
7650
7651  TI_DBG1(("tdsaConfigureRouteTimerCB: start\n"));
7652
7653  onePortContext = (tdsaPortContext_t *)timerData1;
7654  oneExpander = (tdsaExpander_t *)timerData2;
7655  ptdSMPDiscoverResp = (smpRespDiscover_t *)timerData3;
7656
7657  discovery = &(onePortContext->discovery);
7658
7659  TI_DBG1(("tdsaConfigureRouteTimerCB: onePortContext %p oneExpander %p ptdSMPDiscoverResp %p\n", onePortContext, oneExpander, ptdSMPDiscoverResp));
7660
7661  TI_DBG1(("tdsaConfigureRouteTimerCB: discovery %p\n", discovery));
7662
7663  TI_DBG1(("tdsaConfigureRouteTimerCB: pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries));
7664
7665  TI_DBG1(("tdsaConfigureRouteTimerCB: discovery.status %d\n", discovery->status));
7666
7667  discovery->configureRouteRetries++;
7668  if (discovery->configureRouteRetries >= DISCOVERY_RETRIES)
7669  {
7670    TI_DBG1(("tdsaConfigureRouteTimerCB: retries are over\n"));
7671    discovery->configureRouteRetries = 0;
7672    /* failed the discovery */
7673    tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
7674    if (discovery->configureRouteTimer.timerRunning == agTRUE)
7675    {
7676      tdsaKillTimer(
7677                    tiRoot,
7678                    &discovery->configureRouteTimer
7679                   );
7680    }
7681    return;
7682  }
7683
7684
7685  if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
7686  {
7687    TI_DBG1(("tdsaConfigureRouteTimerCB: proceed by calling tdsaSASDownStreamDiscoverExpanderPhy\n"));
7688    tdhexdump("tdsaConfigureRouteTimerCB", (bit8*)ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
7689    discovery->configureRouteRetries = 0;
7690
7691    tdsaSASDownStreamDiscoverExpanderPhy(tiRoot, onePortContext, oneExpander, ptdSMPDiscoverResp);
7692  }
7693  else
7694  {
7695    TI_DBG1(("tdsaConfigureRouteTimerCB: setting timer again\n"));
7696    /* set the timer again */
7697    tdsaSetTimerRequest(
7698                        tiRoot,
7699                        &discovery->configureRouteTimer,
7700                        CONFIGURE_ROUTE_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
7701                        tdsaConfigureRouteTimerCB,
7702                        (void *)onePortContext,
7703                        (void *)oneExpander,
7704                        (void *)ptdSMPDiscoverResp
7705                       );
7706
7707    tdsaAddTimer (
7708                  tiRoot,
7709                  &Initiator->timerlist,
7710                  &discovery->configureRouteTimer
7711                  );
7712   }
7713//  tdsaReportGeneralSend(tiRoot, oneDeviceData);
7714  return;
7715}
7716
7717/*****************************************************************************
7718*! \brief  tdsaDiscoveryTimer
7719*
7720*  Purpose:  This function sets timers for discovery and its callback
7721*            function.
7722*
7723*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7724*                   instance.
7725*  \param   onePortContext: Pointer to the portal context instance.
7726*  \param   oneDeviceData: Pointer to the device data.
7727*
7728*  \return:
7729*           None
7730*
7731*   \note:
7732*
7733*****************************************************************************/
7734osGLOBAL void
7735tdsaDiscoveryTimer(tiRoot_t                 *tiRoot,
7736                   tdsaPortContext_t        *onePortContext,
7737                   tdsaDeviceData_t         *oneDeviceData
7738                   )
7739{
7740  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
7741  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
7742  itdsaIni_t                  *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
7743  tdsaDiscovery_t             *discovery;
7744
7745  TI_DBG1(("tdsaDiscoveryTimer: start\n"));
7746  TI_DBG1(("tdsaDiscoveryTimer: pid %d\n", onePortContext->id));
7747
7748  discovery = &(onePortContext->discovery);
7749
7750  if (discovery->discoveryTimer.timerRunning == agTRUE)
7751  {
7752    tdsaKillTimer(
7753              tiRoot,
7754              &discovery->discoveryTimer
7755              );
7756  }
7757
7758  TI_DBG1(("tdsaDiscoveryTimer: UsecsPerTick %d\n", Initiator->OperatingOption.UsecsPerTick));
7759  TI_DBG1(("tdsaDiscoveryTimer: Timervalue %d\n", DISCOVERY_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick));
7760
7761  tdsaSetTimerRequest(
7762                    tiRoot,
7763                    &discovery->discoveryTimer,
7764                    DISCOVERY_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
7765                    tdsaDiscoveryTimerCB,
7766                    oneDeviceData,
7767                    agNULL,
7768                    agNULL
7769                   );
7770
7771  tdsaAddTimer (
7772              tiRoot,
7773              &Initiator->timerlist,
7774              &discovery->discoveryTimer
7775              );
7776
7777  return;
7778}
7779
7780/*****************************************************************************
7781*! \brief  tdsaDiscoveryTimerCB
7782*
7783*  Purpose:  This function is callback function for discovery timer.
7784*
7785*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7786*                   instance.
7787*  \param   timerData1: Pointer to timer-related data structure
7788*  \param   timerData2: Pointer to timer-related data structure
7789*  \param   timerData3: Pointer to timer-related data structure
7790*
7791*  \return:
7792*           None
7793*
7794*   \note:
7795*
7796*****************************************************************************/
7797osGLOBAL void
7798tdsaDiscoveryTimerCB(
7799                       tiRoot_t    * tiRoot,
7800                       void        * timerData1,
7801                       void        * timerData2,
7802                       void        * timerData3
7803                      )
7804{
7805  tdsaDeviceData_t            *oneDeviceData;
7806  oneDeviceData = (tdsaDeviceData_t *)timerData1;
7807
7808  TI_DBG1(("tdsaDiscoveryTimerCB: start\n"));
7809
7810  if (oneDeviceData->registered == agTRUE)
7811  {
7812    TI_DBG1(("tdsaDiscoveryTimerCB: resumes discovery\n"));
7813    tdsaReportGeneralSend(tiRoot, oneDeviceData);
7814  }
7815
7816  return;
7817}
7818
7819/*****************************************************************************
7820*! \brief  tdsaDeviceRegistrationTimer
7821*
7822*  Purpose:  This function sets timers for device registration in discovery
7823*
7824*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7825*                   instance.
7826*  \param   onePortContext: Pointer to the portal context instance.
7827*  \param   oneDeviceData: Pointer to the device data.
7828*  \return:
7829*           None
7830*
7831*   \note: called by tdsaSASFullDiscover() or tdsaSASIncrementalDiscover()
7832*          or tdsaDeviceRegistrationTimerCB()
7833*
7834*****************************************************************************/
7835osGLOBAL void
7836tdsaDeviceRegistrationTimer(tiRoot_t                 *tiRoot,
7837                            tdsaPortContext_t        *onePortContext,
7838                            tdsaDeviceData_t         *oneDeviceData
7839                            )
7840{
7841  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
7842  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
7843  itdsaIni_t                  *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
7844  tdsaDiscovery_t             *discovery;
7845
7846  TI_DBG1(("tdsaDeviceRegistrationTimer: start\n"));
7847  TI_DBG1(("tdsaDeviceRegistrationTimer: pid %d\n", onePortContext->id));
7848
7849  discovery = &(onePortContext->discovery);
7850
7851  if (discovery->deviceRegistrationTimer.timerRunning == agTRUE)
7852  {
7853    tdsaKillTimer(
7854              tiRoot,
7855              &discovery->deviceRegistrationTimer
7856              );
7857  }
7858
7859  TI_DBG1(("tdsaDeviceRegistrationTimer: UsecsPerTick %d\n", Initiator->OperatingOption.UsecsPerTick));
7860  TI_DBG1(("tdsaDeviceRegistrationTimer: Timervalue %d\n", DEVICE_REGISTRATION_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick));
7861
7862  tdsaSetTimerRequest(
7863                    tiRoot,
7864                    &discovery->deviceRegistrationTimer,
7865                    DEVICE_REGISTRATION_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
7866                    tdsaDeviceRegistrationTimerCB,
7867                    onePortContext,
7868                    oneDeviceData,
7869                    agNULL
7870                   );
7871
7872  tdsaAddTimer (
7873              tiRoot,
7874              &Initiator->timerlist,
7875              &discovery->deviceRegistrationTimer
7876              );
7877  return;
7878}
7879
7880/*****************************************************************************
7881*! \brief  tdsaDeviceRegistrationTimerCB
7882*
7883*  Purpose:  This function is callback function for tdsaDeviceRegistrationTimer.
7884*
7885*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7886*                   instance.
7887*  \param   timerData1: Pointer to timer-related data structure
7888*  \param   timerData2: Pointer to timer-related data structure
7889*  \param   timerData3: Pointer to timer-related data structure
7890*
7891*  \return:
7892*           None
7893*
7894*   \note:
7895*
7896*****************************************************************************/
7897osGLOBAL void
7898tdsaDeviceRegistrationTimerCB(
7899                       tiRoot_t    * tiRoot,
7900                       void        * timerData1,
7901                       void        * timerData2,
7902                       void        * timerData3
7903                      )
7904{
7905  tdsaPortContext_t        *onePortContext;
7906  tdsaDeviceData_t         *oneDeviceData;
7907  tdsaDiscovery_t          *discovery;
7908
7909  TI_DBG1(("tdsaDeviceRegistrationTimerCB: start\n"));
7910
7911  onePortContext = (tdsaPortContext_t *)timerData1;
7912  oneDeviceData = (tdsaDeviceData_t *)timerData2;
7913  discovery = &(onePortContext->discovery);
7914
7915  if (oneDeviceData->registered == agFALSE)
7916  {
7917    discovery->deviceRetistrationRetries++;
7918    if (discovery->deviceRetistrationRetries >= DISCOVERY_RETRIES)
7919    {
7920      TI_DBG1(("tdsaDeviceRegistrationTimerCB: retries are over\n"));
7921      discovery->deviceRetistrationRetries = 0;
7922      /* failed the discovery */
7923      tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
7924      if (discovery->deviceRegistrationTimer.timerRunning == agTRUE)
7925      {
7926        tdsaKillTimer(
7927                      tiRoot,
7928                      &discovery->deviceRegistrationTimer
7929                     );
7930      }
7931    }
7932    else
7933    {
7934      TI_DBG1(("tdsaDeviceRegistrationTimerCB: keep retrying\n"));
7935      /* start timer for device registration */
7936      tdsaDeviceRegistrationTimer(tiRoot, onePortContext, oneDeviceData);
7937    }
7938  }
7939  else
7940  {
7941    /* go ahead; continue the discovery */
7942    discovery->deviceRetistrationRetries = 0;
7943    tdsaSASUpStreamDiscoverStart(tiRoot, onePortContext, oneDeviceData);
7944  }
7945}
7946
7947/*****************************************************************************
7948*! \brief  tdsaSMPBusyTimer
7949*
7950*  Purpose:  This function sets timers for busy of saSMPStart.
7951*
7952*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7953*                   instance.
7954*  \param   onePortContext: Pointer to the portal context instance.
7955*  \param   oneDeviceData: Pointer to the device data.
7956*  \param   tdSMPRequestBody: Pointer to the SMP request body.
7957*
7958*  \return:
7959*           None
7960*
7961*   \note:
7962*
7963*****************************************************************************/
7964osGLOBAL void
7965tdsaSMPBusyTimer(tiRoot_t                 *tiRoot,
7966                 tdsaPortContext_t        *onePortContext,
7967                 tdsaDeviceData_t         *oneDeviceData,
7968                 tdssSMPRequestBody_t     *tdSMPRequestBody
7969                 )
7970{
7971  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
7972  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
7973  itdsaIni_t                  *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
7974  tdsaDiscovery_t             *discovery;
7975
7976  TI_DBG1(("tdsaSMPBusyTimer: start\n"));
7977  TI_DBG1(("tdsaSMPBusyTimer: pid %d\n", onePortContext->id));
7978
7979  discovery = &(onePortContext->discovery);
7980
7981  if (discovery->SMPBusyTimer.timerRunning == agTRUE)
7982  {
7983    tdsaKillTimer(
7984              tiRoot,
7985              &discovery->SMPBusyTimer
7986              );
7987  }
7988
7989  tdsaSetTimerRequest(
7990                    tiRoot,
7991                    &discovery->SMPBusyTimer,
7992                    SMP_BUSY_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
7993                    tdsaSMPBusyTimerCB,
7994                    onePortContext,
7995                    oneDeviceData,
7996                    tdSMPRequestBody
7997                   );
7998
7999  tdsaAddTimer (
8000              tiRoot,
8001              &Initiator->timerlist,
8002              &discovery->SMPBusyTimer
8003              );
8004  return;
8005}
8006
8007/*****************************************************************************
8008*! \brief  tdsaSMPBusyTimerCB
8009*
8010*  Purpose:  This function is callback function for SMP busy timer.
8011*
8012*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8013*                   instance.
8014*  \param   timerData1: Pointer to timer-related data structure
8015*  \param   timerData2: Pointer to timer-related data structure
8016*  \param   timerData3: Pointer to timer-related data structure
8017*
8018*  \return:
8019*           None
8020*
8021*   \note:
8022*
8023*****************************************************************************/
8024osGLOBAL void
8025tdsaSMPBusyTimerCB(
8026                       tiRoot_t    * tiRoot,
8027                       void        * timerData1,
8028                       void        * timerData2,
8029                       void        * timerData3
8030                       )
8031{
8032  tdsaRoot_t                  *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
8033  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared);
8034  agsaRoot_t                  *agRoot;
8035  tdsaPortContext_t           *onePortContext;
8036  tdsaDeviceData_t            *oneDeviceData;
8037  tdssSMPRequestBody_t        *tdSMPRequestBody;
8038  agsaSASRequestBody_t        *agSASRequestBody;
8039  agsaIORequest_t             *agIORequest;
8040  agsaDevHandle_t             *agDevHandle;
8041  tdsaDiscovery_t             *discovery;
8042  bit32                       status = AGSA_RC_FAILURE;
8043
8044  TI_DBG1(("tdsaSMPBusyTimerCB: start\n"));
8045
8046  onePortContext = (tdsaPortContext_t *)timerData1;
8047  oneDeviceData = (tdsaDeviceData_t *)timerData2;
8048  tdSMPRequestBody = (tdssSMPRequestBody_t *)timerData3;
8049  agRoot = oneDeviceData->agRoot;
8050  agIORequest = &(tdSMPRequestBody->agIORequest);
8051  agDevHandle = oneDeviceData->agDevHandle;
8052  agSASRequestBody = &(tdSMPRequestBody->agSASRequestBody);
8053  discovery = &(onePortContext->discovery);
8054
8055  discovery->SMPRetries++;
8056
8057  if (discovery->SMPRetries < SMP_BUSY_RETRIES)
8058  {
8059    status = saSMPStart(
8060                         agRoot,
8061                         agIORequest,
8062                         tdsaAllShared->SMPQNum, //tdsaRotateQnumber(tiRoot, oneDeviceData),
8063                         agDevHandle,
8064                         AGSA_SMP_INIT_REQ,
8065                         agSASRequestBody,
8066                         &ossaSMPCompleted
8067                         );
8068  }
8069
8070  if (status == AGSA_RC_SUCCESS)
8071  {
8072    discovery->SMPRetries = 0;
8073    if (discovery->SMPBusyTimer.timerRunning == agTRUE)
8074    {
8075      tdsaKillTimer(
8076                    tiRoot,
8077                    &discovery->SMPBusyTimer
8078                   );
8079    }
8080  }
8081  else if (status == AGSA_RC_FAILURE)
8082  {
8083    discovery->SMPRetries = 0;
8084    tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
8085    if (discovery->SMPBusyTimer.timerRunning == agTRUE)
8086    {
8087      tdsaKillTimer(
8088                    tiRoot,
8089                    &discovery->SMPBusyTimer
8090                   );
8091    }
8092  }
8093  else /* AGSA_RC_BUSY */
8094  {
8095    if (discovery->SMPRetries >= SMP_BUSY_RETRIES)
8096    {
8097      /* done with retris; give up */
8098      TI_DBG1(("tdsaSMPBusyTimerCB: retries are over\n"));
8099      discovery->SMPRetries = 0;
8100      tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
8101      if (discovery->SMPBusyTimer.timerRunning == agTRUE)
8102      {
8103        tdsaKillTimer(
8104                      tiRoot,
8105                      &discovery->SMPBusyTimer
8106                     );
8107      }
8108    }
8109    else
8110    {
8111      /* keep retrying */
8112      tdsaSMPBusyTimer(tiRoot, onePortContext, oneDeviceData, tdSMPRequestBody);
8113    }
8114  }
8115
8116  return;
8117}
8118
8119/*****************************************************************************
8120*! \brief  tdsaBCTimer
8121*
8122*  Purpose:  This function sets timers for sending ID device data only for
8123*            directly attached SATA device.
8124*
8125*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8126*                   instance.
8127*  \param   onePortContext: Pointer to the portal context instance.
8128*  \param   oneDeviceData: Pointer to the device data.
8129*  \param   tdSMPRequestBody: Pointer to the SMP request body.
8130*
8131*  \return:
8132*           None
8133*
8134*   \note:
8135*
8136*****************************************************************************/
8137osGLOBAL void
8138tdsaBCTimer(tiRoot_t                 *tiRoot,
8139            tdsaPortContext_t        *onePortContext
8140           )
8141{
8142  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
8143  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
8144  itdsaIni_t                  *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
8145  tdsaDiscovery_t             *discovery;
8146
8147
8148  TI_DBG1(("tdsaBCTimer: start\n"));
8149
8150  discovery = &(onePortContext->discovery);
8151
8152  if (discovery->BCTimer.timerRunning == agTRUE)
8153  {
8154    tdsaKillTimer(
8155              tiRoot,
8156              &discovery->BCTimer
8157              );
8158  }
8159
8160  if (onePortContext->valid == agTRUE)
8161  {
8162    tdsaSetTimerRequest(
8163                        tiRoot,
8164                        &discovery->BCTimer,
8165                        BC_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
8166                        tdsaBCTimerCB,
8167                        onePortContext,
8168                        agNULL,
8169                        agNULL
8170                        );
8171
8172    tdsaAddTimer(
8173                 tiRoot,
8174                 &Initiator->timerlist,
8175                 &discovery->BCTimer
8176                );
8177
8178  }
8179
8180  return;
8181}
8182
8183/*****************************************************************************
8184*! \brief  tdsaBCTimerCB
8185*
8186*  Purpose:  This function is callback function for SATA ID device data.
8187*
8188*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8189*                   instance.
8190*  \param   timerData1: Pointer to timer-related data structure
8191*  \param   timerData2: Pointer to timer-related data structure
8192*  \param   timerData3: Pointer to timer-related data structure
8193*
8194*  \return:
8195*           None
8196*
8197*   \note:
8198*
8199*****************************************************************************/
8200osGLOBAL void
8201tdsaBCTimerCB(
8202              tiRoot_t    * tiRoot,
8203              void        * timerData1,
8204              void        * timerData2,
8205              void        * timerData3
8206              )
8207{
8208  tdsaPortContext_t           *onePortContext;
8209  tdsaDiscovery_t             *discovery;
8210
8211  TI_DBG1(("tdsaBCTimerCB: start\n"));
8212
8213  onePortContext = (tdsaPortContext_t *)timerData1;
8214  discovery = &(onePortContext->discovery);
8215
8216  discovery->ResetTriggerred = agFALSE;
8217
8218  if (onePortContext->valid == agTRUE)
8219  {
8220    tdsaDiscover(
8221                 tiRoot,
8222                 onePortContext,
8223                 TDSA_DISCOVERY_TYPE_SAS,
8224                 TDSA_DISCOVERY_OPTION_INCREMENTAL_START
8225                );
8226  }
8227  if (discovery->BCTimer.timerRunning == agTRUE)
8228  {
8229    tdsaKillTimer(
8230              tiRoot,
8231              &discovery->BCTimer
8232              );
8233  }
8234
8235  return;
8236}
8237
8238/*****************************************************************************
8239*! \brief  tdsaDiscoverySMPTimer
8240*
8241*  Purpose:  This function sets timers for sending discovery-related SMP
8242*
8243*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8244*                   instance.
8245*  \param   onePortContext: Pointer to the portal context instance.
8246*  \param   functionCode: SMP function.
8247*  \param   tdSMPRequestBody: Pointer to the SMP request body.
8248*
8249*  \return:
8250*           None
8251*
8252*   \note:
8253*
8254*****************************************************************************/
8255osGLOBAL void
8256tdsaDiscoverySMPTimer(tiRoot_t                 *tiRoot,
8257                      tdsaPortContext_t        *onePortContext,
8258                      bit32                    functionCode, /* smp function code */
8259                      tdssSMPRequestBody_t     *tdSMPRequestBody
8260                     )
8261{
8262  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
8263  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
8264  itdsaIni_t                  *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
8265  tdsaDiscovery_t             *discovery;
8266
8267  TI_DBG3(("tdsaDiscoverySMPTimer: start\n"));
8268  TI_DBG3(("tdsaDiscoverySMPTimer: pid %d SMPFn 0x%x\n", onePortContext->id, functionCode));
8269
8270  /* start the SMP timer which works as SMP application timer */
8271  discovery = &(onePortContext->discovery);
8272
8273  if (discovery->DiscoverySMPTimer.timerRunning == agTRUE)
8274  {
8275    tdsaKillTimer(
8276              tiRoot,
8277              &discovery->DiscoverySMPTimer
8278              );
8279  }
8280  tdsaSetTimerRequest(
8281                    tiRoot,
8282                    &discovery->DiscoverySMPTimer,
8283                    SMP_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
8284                    tdsaDiscoverySMPTimerCB,
8285                    onePortContext,
8286                    tdSMPRequestBody,
8287                    agNULL
8288                   );
8289
8290  tdsaAddTimer (
8291              tiRoot,
8292              &Initiator->timerlist,
8293              &discovery->DiscoverySMPTimer
8294              );
8295
8296  return;
8297}
8298
8299/*****************************************************************************
8300*! \brief  tdsaDiscoverySMPTimerCB
8301*
8302*  Purpose:  This function is callback function for tdsaDiscoverySMPTimer.
8303*
8304*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8305*                   instance.
8306*  \param   timerData1: Pointer to timer-related data structure
8307*  \param   timerData2: Pointer to timer-related data structure
8308*  \param   timerData3: Pointer to timer-related data structure
8309*
8310*  \return:
8311*           None
8312*
8313*   \note:
8314*
8315*****************************************************************************/
8316osGLOBAL void
8317tdsaDiscoverySMPTimerCB(
8318                        tiRoot_t    * tiRoot,
8319                        void        * timerData1,
8320                        void        * timerData2,
8321                        void        * timerData3
8322                       )
8323{
8324  agsaRoot_t                  *agRoot;
8325  tdsaPortContext_t           *onePortContext;
8326  bit8                        SMPFunction;
8327#ifndef DIRECT_SMP
8328  tdssSMPFrameHeader_t        *tdSMPFrameHeader;
8329  bit8                        smpHeader[4];
8330#endif
8331  tdssSMPRequestBody_t        *tdSMPRequestBody;
8332  tdsaDiscovery_t             *discovery;
8333  tdsaDeviceData_t            *oneDeviceData;
8334  agsaIORequest_t             *agAbortIORequest = agNULL;
8335  tdIORequestBody_t           *tdAbortIORequestBody = agNULL;
8336  bit32                       PhysUpper32;
8337  bit32                       PhysLower32;
8338  bit32                       memAllocStatus;
8339  void                        *osMemHandle;
8340  agsaIORequest_t             *agToBeAbortIORequest = agNULL;
8341
8342  TI_DBG1(("tdsaDiscoverySMPTimerCB: start\n"));
8343
8344  /* no retry
8345     if discovery related SMP, fail the discovery
8346     else ....
8347     be sure to abort SMP
8348  */
8349  onePortContext = (tdsaPortContext_t *)timerData1;
8350  tdSMPRequestBody = (tdssSMPRequestBody_t *)timerData2;
8351
8352  discovery = &(onePortContext->discovery);
8353  oneDeviceData = tdSMPRequestBody->tdDevice;
8354  agToBeAbortIORequest = &(tdSMPRequestBody->agIORequest);
8355  agRoot = oneDeviceData->agRoot;
8356
8357#ifdef DIRECT_SMP
8358  SMPFunction = tdSMPRequestBody->smpPayload[1];
8359#else
8360  saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 0, smpHeader, 4);
8361  tdSMPFrameHeader = (tdssSMPFrameHeader_t *)smpHeader;
8362  SMPFunction = tdSMPFrameHeader->smpFunction;
8363#endif
8364
8365  TI_DBG1(("tdsaDiscoverySMPTimerCB: SMP function 0x%x\n", SMPFunction));
8366
8367  if (discovery->DiscoverySMPTimer.timerRunning == agTRUE)
8368  {
8369    tdsaKillTimer(
8370                  tiRoot,
8371                  &discovery->DiscoverySMPTimer
8372                 );
8373  }
8374  switch (SMPFunction)
8375  {
8376  case SMP_REPORT_GENERAL: /* fall through */
8377  case SMP_DISCOVER:  /* fall through */
8378  case SMP_CONFIGURE_ROUTING_INFORMATION:  /* fall through */
8379    TI_DBG1(("tdsaDiscoverySMPTimerCB: failing discovery, SMP function 0x%x\n", SMPFunction));
8380    tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
8381    return;
8382  case SMP_REPORT_PHY_SATA:
8383    TI_DBG1(("tdsaDiscoverySMPTimerCB: failing discovery, SMP function SMP_REPORT_PHY_SATA\n"));
8384    tdsaSATADiscoverDone(tiRoot, onePortContext, tiError);
8385    break;
8386  default:
8387    /* do nothing */
8388    TI_DBG1(("tdsaDiscoverySMPTimerCB: Error!!!! not allowed case\n"));
8389    break;
8390  }
8391
8392  if (onePortContext->discovery.SeenBC == agTRUE)
8393  {
8394    /* allocating agIORequest for abort itself */
8395    memAllocStatus = ostiAllocMemory(
8396                                     tiRoot,
8397                                     &osMemHandle,
8398                                     (void **)&tdAbortIORequestBody,
8399                                     &PhysUpper32,
8400                                     &PhysLower32,
8401                                     8,
8402                                     sizeof(tdIORequestBody_t),
8403                                     agTRUE
8404                                     );
8405    if (memAllocStatus != tiSuccess)
8406    {
8407      /* let os process IO */
8408      TI_DBG1(("tdsaDiscoverySMPTimerCB: ostiAllocMemory failed...\n"));
8409      return;
8410    }
8411
8412    if (tdAbortIORequestBody == agNULL)
8413    {
8414      /* let os process IO */
8415      TI_DBG1(("tdsaDiscoverySMPTimerCB: ostiAllocMemory returned NULL tdAbortIORequestBody\n"));
8416      return;
8417    }
8418
8419    /* setup task management structure */
8420    tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle;
8421    /* setting callback */
8422    tdAbortIORequestBody->IOCompletionFunc = itdssIOAbortedHandler;
8423
8424    tdAbortIORequestBody->tiDevHandle = (tiDeviceHandle_t *)&(oneDeviceData->tiDeviceHandle);
8425
8426    /* initialize agIORequest */
8427    agAbortIORequest = &(tdAbortIORequestBody->agIORequest);
8428    agAbortIORequest->osData = (void *) tdAbortIORequestBody;
8429    agAbortIORequest->sdkData = agNULL; /* LL takes care of this */
8430
8431    /* SMPAbort - abort one */
8432    saSMPAbort(agRoot,
8433               agAbortIORequest,
8434               0,
8435               oneDeviceData->agDevHandle,
8436               0, /* abort one */
8437               agToBeAbortIORequest,
8438               agNULL
8439               );
8440
8441  }
8442  return;
8443}
8444
8445
8446/*****************************************************************************
8447*! \brief  tdsaSATAIDDeviceTimer
8448*
8449*  Purpose:  This function sets timers for sending ID device data only for
8450*            directly attached SATA device.
8451*
8452*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8453*                   instance.
8454*  \param   onePortContext: Pointer to the portal context instance.
8455*  \param   oneDeviceData: Pointer to the device data.
8456*  \param   tdSMPRequestBody: Pointer to the SMP request body.
8457*
8458*  \return:
8459*           None
8460*
8461*   \note:
8462*
8463*****************************************************************************/
8464osGLOBAL void
8465tdsaSATAIDDeviceTimer(tiRoot_t                 *tiRoot,
8466                      tdsaDeviceData_t         *oneDeviceData
8467                     )
8468{
8469  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
8470  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
8471  itdsaIni_t                  *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
8472
8473  TI_DBG1(("tdsaSATAIDDeviceTimer: start\n"));
8474
8475  if (oneDeviceData->SATAIDDeviceTimer.timerRunning == agTRUE)
8476  {
8477    tdsaKillTimer(
8478              tiRoot,
8479              &oneDeviceData->SATAIDDeviceTimer
8480              );
8481  }
8482
8483  tdsaSetTimerRequest(
8484                    tiRoot,
8485                    &oneDeviceData->SATAIDDeviceTimer,
8486                    SATA_ID_DEVICE_DATA_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
8487                    tdsaSATAIDDeviceTimerCB,
8488                    oneDeviceData,
8489                    agNULL,
8490                    agNULL
8491                   );
8492
8493  tdsaAddTimer (
8494              tiRoot,
8495              &Initiator->timerlist,
8496              &oneDeviceData->SATAIDDeviceTimer
8497              );
8498
8499  return;
8500}
8501
8502/*****************************************************************************
8503*! \brief  tdsaSATAIDDeviceTimerCB
8504*
8505*  Purpose:  This function is callback function for SATA ID device data.
8506*
8507*  \param   tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8508*                   instance.
8509*  \param   timerData1: Pointer to timer-related data structure
8510*  \param   timerData2: Pointer to timer-related data structure
8511*  \param   timerData3: Pointer to timer-related data structure
8512*
8513*  \return:
8514*           None
8515*
8516*   \note:
8517*
8518*****************************************************************************/
8519osGLOBAL void
8520tdsaSATAIDDeviceTimerCB(
8521                       tiRoot_t    * tiRoot,
8522                       void        * timerData1,
8523                       void        * timerData2,
8524                       void        * timerData3
8525                       )
8526{
8527  tdsaDeviceData_t            *oneDeviceData;
8528
8529  TI_DBG1(("tdsaSATAIDDeviceTimerCB: start\n"));
8530
8531  oneDeviceData = (tdsaDeviceData_t *)timerData1;
8532
8533  /* send identify device data */
8534  tdssSubAddSATAToSharedcontext(tiRoot, oneDeviceData);
8535
8536  if (oneDeviceData->SATAIDDeviceTimer.timerRunning == agTRUE)
8537  {
8538    tdsaKillTimer(
8539              tiRoot,
8540              &oneDeviceData->SATAIDDeviceTimer
8541              );
8542  }
8543
8544  return;
8545}
8546
8547#endif /* TD_DISCOVER */
8548