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