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