]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/pms/RefTisa/discovery/dm/dmdisc.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / pms / RefTisa / discovery / dm / dmdisc.c
1 /*******************************************************************************
2 **
3 *Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved. 
4 *
5 *Redistribution and use in source and binary forms, with or without modification, are permitted provided 
6 *that the following conditions are met: 
7 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8 *following disclaimer. 
9 *2. Redistributions in binary form must reproduce the above copyright notice, 
10 *this list of conditions and the following disclaimer in the documentation and/or other materials provided
11 *with the distribution. 
12 *
13 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED 
14 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
17 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
18 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
19 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
20 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
21 **
22 ********************************************************************************/
23 #include <sys/cdefs.h>
24 __FBSDID("$FreeBSD$");
25 #include <dev/pms/config.h>
26
27 #include <dev/pms/freebsd/driver/common/osenv.h>
28 #include <dev/pms/freebsd/driver/common/ostypes.h>
29 #include <dev/pms/freebsd/driver/common/osdebug.h>
30
31 #include <dev/pms/RefTisa/sallsdk/api/sa.h>
32 #include <dev/pms/RefTisa/sallsdk/api/saapi.h>
33 #include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
34
35 #ifdef FDS_DM
36 #include <dev/pms/RefTisa/discovery/api/dm.h>
37 #include <dev/pms/RefTisa/discovery/api/dmapi.h>
38 #include <dev/pms/RefTisa/discovery/api/tddmapi.h>
39
40 #include <dev/pms/RefTisa/discovery/dm/dmdefs.h>
41 #include <dev/pms/RefTisa/discovery/dm/dmtypes.h>
42 #include <dev/pms/RefTisa/discovery/dm/dmproto.h>
43
44 /*****************************************************************************/
45 /*! \brief dmDiscover
46  *  
47  *
48  *  Purpose: A discovery is started by this function 
49  *  
50  *  \param   dmRoot:              DM context handle.
51  *  \param   dmPortContext:       Pointer to this instance of port context 
52  *  \param   option:              Discovery option 
53  * 
54  *  \return: 
55  *          DM_RC_SUCCESS
56  *          DM_RC_FAILURE
57  *
58  */
59 /*****************************************************************************/
60 osGLOBAL bit32  
61 dmDiscover(  
62            dmRoot_t             *dmRoot,
63            dmPortContext_t      *dmPortContext,
64            bit32                option)
65 {
66   dmIntPortContext_t        *onePortContext = agNULL;
67   bit32                     ret = DM_RC_FAILURE;
68   
69   DM_DBG3(("dmDiscover: start\n"));
70   onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
71   
72   if (onePortContext == agNULL)
73   {
74     DM_DBG1(("dmDiscover: onePortContext is NULL!!!\n"));
75     return DM_RC_FAILURE;
76   }
77   
78   if (onePortContext->valid == agFALSE)
79   {
80     DM_DBG1(("dmDiscover: invalid port!!!\n"));
81     return DM_RC_FAILURE;
82   }
83   
84   if (onePortContext->RegFailed == agTRUE)
85   {
86     DM_DBG1(("dmDiscover: Registration failed!!!\n"));
87     return DM_RC_FAILURE;
88   }
89   
90   switch ( option )
91   {
92   case DM_DISCOVERY_OPTION_FULL_START:
93     DM_DBG3(("dmDiscover: full, pid %d\n", onePortContext->id));
94     onePortContext->discovery.type = DM_DISCOVERY_OPTION_FULL_START;
95     dmDiscoveryResetMCN(dmRoot, onePortContext);
96     ret = dmFullDiscover(dmRoot, onePortContext);
97     break;
98   case DM_DISCOVERY_OPTION_INCREMENTAL_START:
99     DM_DBG3(("dmDiscover: incremental, pid %d\n", onePortContext->id));
100     onePortContext->discovery.type = DM_DISCOVERY_OPTION_INCREMENTAL_START;
101     dmDiscoveryResetMCN(dmRoot, onePortContext);
102     ret = dmIncrementalDiscover(dmRoot, onePortContext, agFALSE);
103     break;
104   case DM_DISCOVERY_OPTION_ABORT:
105     DM_DBG3(("dmDiscover: abort\n"));
106     if (onePortContext->DiscoveryState != DM_DSTATE_COMPLETED)
107     {
108       if (onePortContext->discovery.pendingSMP == 0)
109       {
110         dmDiscoverAbort(dmRoot, onePortContext);
111         tddmDiscoverCB(
112                        dmRoot,
113                        onePortContext->dmPortContext,
114                        dmDiscAborted
115                        );
116       }
117       else
118       {
119         DM_DBG3(("dmDiscover: abortInProgress\n"));
120         onePortContext->DiscoveryAbortInProgress = agTRUE;
121         tddmDiscoverCB(
122                        dmRoot,
123                        dmPortContext,
124                        dmDiscAbortInProgress
125                        );
126       }
127     }
128     else
129     {
130       DM_DBG3(("dmDiscover: no discovery to abort\n"));
131       tddmDiscoverCB(
132                      dmRoot,
133                      dmPortContext,
134                      dmDiscAbortInvalid
135                      );
136     }
137     ret = DM_RC_SUCCESS;
138     break;
139   default:
140     break;
141   }  
142   return ret;
143 }                                       
144                                 
145 osGLOBAL bit32
146 dmFullDiscover(
147                dmRoot_t                 *dmRoot, 
148                dmIntPortContext_t       *onePortContext 
149               )
150 {
151   dmExpander_t              *oneExpander = agNULL;
152   dmSASSubID_t              dmSASSubID;
153   dmDeviceData_t            *oneExpDeviceData = agNULL;
154     
155   DM_DBG1(("dmFullDiscover: start\n"));
156
157   if (onePortContext->valid == agFALSE)
158   {
159     DM_DBG1(("dmFullDiscover: invalid port!!!\n"));
160     return DM_RC_FAILURE;
161   }
162   
163   if (onePortContext->DiscoveryState == DM_DSTATE_STARTED)
164   {
165     DM_DBG1(("dmFullDiscover: no two instances of discovery allowed!!!\n"));
166     return DM_RC_FAILURE;
167   }
168   
169   onePortContext->DiscoveryState = DM_DSTATE_STARTED;
170   
171   dmSASSubID.sasAddressHi = onePortContext->sasRemoteAddressHi;
172   dmSASSubID.sasAddressLo = onePortContext->sasRemoteAddressLo;
173   
174   /* check OnePortContext->discovery.discoveringExpanderList */
175   oneExpander = dmExpFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
176   if (oneExpander != agNULL)
177   {
178     oneExpDeviceData = oneExpander->dmDevice;
179   }
180   else
181   {
182     /* check dmAllShared->mainExpanderList */
183     oneExpander = dmExpMainListFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
184     if (oneExpander != agNULL)
185     {
186       oneExpDeviceData = oneExpander->dmDevice;
187     }
188   }
189   
190   if (oneExpDeviceData != agNULL)
191   {
192     dmSASSubID.initiator_ssp_stp_smp = oneExpDeviceData->initiator_ssp_stp_smp;
193     dmSASSubID.target_ssp_stp_smp = oneExpDeviceData->target_ssp_stp_smp;
194     oneExpDeviceData->registered = agTRUE;    
195     dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, oneExpDeviceData, 0xFF);  
196   }
197   else
198   {
199     DM_DBG1(("dmFullDiscover:oneExpDeviceData is NULL!!!\n"));
200     return DM_RC_FAILURE;
201   }
202   
203   dmUpStreamDiscoverStart(dmRoot, onePortContext);
204   
205   return DM_RC_SUCCESS;
206 }                             
207
208 osGLOBAL bit32
209 dmIncrementalDiscover(
210                       dmRoot_t                *dmRoot, 
211                       dmIntPortContext_t      *onePortContext,
212                       bit32                   flag      
213                      )
214 {
215   dmExpander_t              *oneExpander = agNULL;
216   dmSASSubID_t              dmSASSubID;
217   dmDeviceData_t            *oneExpDeviceData = agNULL;
218   
219   DM_DBG1(("dmIncrementalDiscover: start\n"));
220
221   if (onePortContext->valid == agFALSE)
222   {
223     DM_DBG1(("dmIncrementalDiscover: invalid port!!!\n"));
224     return DM_RC_FAILURE;
225   }
226   
227   /* TDM triggerred; let go DM triggerred */
228   if (flag == agFALSE)
229   {
230     if (onePortContext->DiscoveryState == DM_DSTATE_STARTED)
231     {
232       DM_DBG1(("dmIncrementalDiscover: no two instances of discovery allowed!!!\n"));
233       return DM_RC_FAILURE;
234     }
235   }
236   
237   onePortContext->DiscoveryState = DM_DSTATE_STARTED;
238   onePortContext->discovery.type = DM_DISCOVERY_OPTION_INCREMENTAL_START;
239   
240   dmSASSubID.sasAddressHi = onePortContext->sasRemoteAddressHi;
241   dmSASSubID.sasAddressLo = onePortContext->sasRemoteAddressLo;
242   
243   /* check OnePortContext->discovery.discoveringExpanderList */
244   oneExpander = dmExpFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
245   if (oneExpander != agNULL)
246   {
247     oneExpDeviceData = oneExpander->dmDevice;
248   }
249   else
250   {
251     /* check dmAllShared->mainExpanderList */
252     oneExpander = dmExpMainListFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
253     if (oneExpander != agNULL)
254     {
255       oneExpDeviceData = oneExpander->dmDevice;
256     }
257   }
258   
259   if (oneExpDeviceData != agNULL)
260   {
261     dmSASSubID.initiator_ssp_stp_smp = oneExpDeviceData->initiator_ssp_stp_smp;
262     dmSASSubID.target_ssp_stp_smp = oneExpDeviceData->target_ssp_stp_smp;
263     oneExpDeviceData->registered = agTRUE;    
264     dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, oneExpDeviceData, 0xFF);  
265   }
266   else
267   {
268     DM_DBG1(("dmIncrementalDiscover:oneExpDeviceData is NULL!!!\n"));
269     return DM_RC_FAILURE;
270   }
271   
272   dmUpStreamDiscoverStart(dmRoot, onePortContext);
273   
274   return DM_RC_SUCCESS;
275 }                                    
276
277 osGLOBAL void
278 dmUpStreamDiscoverStart(
279                         dmRoot_t             *dmRoot,
280                         dmIntPortContext_t   *onePortContext            
281                        )
282 {
283 //  dmExpander_t              *oneExpander = agNULL;
284   bit32                     sasAddressHi, sasAddressLo;
285   dmDeviceData_t            *oneDeviceData;
286   dmExpander_t              *oneExpander = agNULL;
287   
288   DM_DBG3(("dmUpStreamDiscoverStart: start\n"));
289   if (onePortContext->valid == agFALSE)
290   {
291     DM_DBG1(("dmUpStreamDiscoverStart: invalid port!!!\n"));
292     return;
293   }
294   /*
295     at this point, the 1st expander should have been registered.
296     find an expander from onePortContext 
297   */
298   sasAddressHi = onePortContext->sasRemoteAddressHi;
299   sasAddressLo = onePortContext->sasRemoteAddressLo;
300   DM_DBG3(("dmUpStreamDiscoverStart: Port Remote AddrHi 0x%08x Remote AddrLo 0x%08x\n", sasAddressHi, sasAddressLo));
301
302   oneDeviceData = dmDeviceFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo);
303
304 //  oneDeviceData = oneExpander->dmDevice; 
305 // start here
306   onePortContext->discovery.status = DISCOVERY_UP_STREAM;
307   if (oneDeviceData == agNULL)
308   {
309     DM_DBG1(("dmUpStreamDiscoverStart: oneExpander is NULL, wrong!!!\n"));
310     return;
311   }
312   else
313   {
314     if ( (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
315          ||
316          (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE)
317          ||
318          DEVICE_IS_SMP_TARGET(oneDeviceData)
319         )
320     {
321 #if 1  /* for incremental discovery */  
322       /* start here: if not on discoveringExpanderList, alloc and add 
323       dmNewEXPorNot()
324       */
325       oneExpander = dmExpFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo);
326       if ( oneExpander == agNULL)
327       {
328         /* alloc and add */
329         oneExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, oneDeviceData);
330         if ( oneExpander != agNULL)
331         {
332           dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);      
333         }       
334         else
335         {
336           DM_DBG1(("dmUpStreamDiscoverStart: failed to allocate expander or discovey aborted!!!\n"));
337           return;
338         }
339       }
340 #endif
341  
342       dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
343     }
344     else
345     {
346       DM_DBG1(("dmUpStreamDiscoverStart: oneDeviceData is not an Expander did %d, wrong!!!\n", oneDeviceData->id));
347       return;
348     }
349   }
350   return;
351 }                               
352
353 /* sends report general */
354 osGLOBAL void
355 dmUpStreamDiscovering(
356                       dmRoot_t              *dmRoot,
357                       dmIntPortContext_t    *onePortContext,
358                       dmDeviceData_t        *oneDeviceData
359                      )
360 {
361   dmList_t          *ExpanderList;
362   dmExpander_t      *oneNextExpander = agNULL;
363   
364   DM_DBG3(("dmUpStreamDiscovering: start\n"));
365   
366   if (onePortContext->valid == agFALSE)
367   {
368     DM_DBG1(("dmUpStreamDiscovering: invalid port!!!\n"));
369     return;
370   }
371   
372   tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
373   if (DMLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList)))
374   {
375     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
376     DM_DBG3(("dmUpStreamDiscovering: should be the end\n"));
377     oneNextExpander = agNULL;
378   }
379   else
380   {
381     DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList));
382     oneNextExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
383     if ( oneNextExpander != agNULL)
384     {
385       DMLIST_ENQUEUE_AT_HEAD(&(oneNextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));
386       DM_DBG3(("dmUpStreamDiscovering tdsaSASUpStreamDiscovering: dequeue head\n"));
387       DM_DBG3(("dmUpStreamDiscovering: expander id %d\n", oneNextExpander->id));
388     }
389     else
390     {
391       DM_DBG1(("dmUpStreamDiscovering: oneNextExpander is NULL!!!\n"));
392     }
393     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
394
395   }
396   
397   if (oneNextExpander != agNULL)
398   {
399     dmReportGeneralSend(dmRoot, oneNextExpander->dmDevice);
400   }
401   else
402   {
403     DM_DBG3(("dmUpStreamDiscovering: No more expander list\n"));
404     dmDownStreamDiscoverStart(dmRoot, onePortContext, oneDeviceData);
405   }
406   
407   return;
408 }                               
409
410 osGLOBAL void
411 dmDownStreamDiscoverStart(
412                           dmRoot_t              *dmRoot,
413                           dmIntPortContext_t    *onePortContext,
414                           dmDeviceData_t        *oneDeviceData
415                          )
416 {
417   dmExpander_t        *UpStreamExpander;
418   dmExpander_t        *oneExpander;
419   
420   DM_DBG3(("dmDownStreamDiscoverStart: start\n"));
421   
422   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
423   {
424     DM_DBG1(("dmDownStreamDiscoverStart: invalid port or aborted discovery!!!\n"));  
425     return;
426   }
427
428   /* set discovery status */
429   onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
430
431   /* If it's an expander */    
432   if ( (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
433        || (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE)
434        || DEVICE_IS_SMP_TARGET(oneDeviceData)
435        )
436   {
437     oneExpander = oneDeviceData->dmExpander;    
438     UpStreamExpander = oneExpander->dmUpStreamExpander;
439     
440     /* If the two expanders are the root of two edge sets; sub-to-sub */
441     if ( (UpStreamExpander != agNULL) && ( UpStreamExpander->dmUpStreamExpander == oneExpander ) )
442     {
443       DM_DBG3(("dmDownStreamDiscoverStart: Root found pExpander=%p pUpStreamExpander=%p\n", 
444                oneExpander, UpStreamExpander));
445       //Saves the root expander
446       onePortContext->discovery.RootExp = oneExpander;
447       DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
448       DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
449                
450       /* reset up stream inform for pExpander */
451       oneExpander->dmUpStreamExpander = agNULL;      
452       /* Add the pExpander to discovering list */
453       dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);
454
455       /* reset up stream inform for oneExpander */
456       UpStreamExpander->dmUpStreamExpander = agNULL;      
457       /* Add the UpStreamExpander to discovering list */
458       dmDiscoveringExpanderAdd(dmRoot, onePortContext, UpStreamExpander);
459     }
460     /* If the two expanders are not the root of two edge sets. eg) one root */
461     else
462     {
463       //Saves the root expander
464       onePortContext->discovery.RootExp = oneExpander;
465
466       DM_DBG3(("dmDownStreamDiscoverStart: NO Root pExpander=%p\n", oneExpander));
467       DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
468       DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
469       
470       /* (2.2.2.1) Add the pExpander to discovering list */
471       dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);      
472     }
473   }
474
475   /* Continue down stream discovering */
476   dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
477   
478   return;
479 }                        
480
481 osGLOBAL void
482 dmDownStreamDiscovering(
483                         dmRoot_t              *dmRoot,
484                         dmIntPortContext_t    *onePortContext,
485                         dmDeviceData_t        *oneDeviceData
486                        )
487 {
488   dmExpander_t      *NextExpander = agNULL;
489   dmList_t          *ExpanderList;
490   
491   DM_DBG3(("dmDownStreamDiscovering: start\n"));
492   
493   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
494   {
495     DM_DBG1(("dmDownStreamDiscovering: invalid port or aborted discovery!!!\n"));  
496     return;
497   }
498
499   tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
500   if (DMLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList)))
501   {
502     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
503     DM_DBG3(("dmDownStreamDiscovering: should be the end\n"));
504     NextExpander = agNULL;
505   }
506   else
507   {
508     DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList));;
509     NextExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
510     if ( NextExpander != agNULL)
511     {
512       DMLIST_ENQUEUE_AT_HEAD(&(NextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));;
513       DM_DBG3(("dmDownStreamDiscovering tdsaSASDownStreamDiscovering: dequeue head\n"));
514       DM_DBG3(("dmDownStreamDiscovering: expander id %d\n", NextExpander->id));
515     }
516     else
517     {
518      DM_DBG1(("dmDownStreamDiscovering: NextExpander is NULL!!!\n"));  
519     }
520     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
521     
522   }
523   
524   /* If there is an expander for continue discoving */
525   if ( NextExpander != agNULL)
526   {
527     DM_DBG3(("dmDownStreamDiscovering: Found pNextExpander=%p discoveryStatus=0x%x\n", 
528              NextExpander, onePortContext->discovery.status));
529
530     switch (onePortContext->discovery.status)
531     {
532       /* If the discovery status is DISCOVERY_DOWN_STREAM */
533     case DISCOVERY_DOWN_STREAM:
534       /* Send report general for the next expander */
535       DM_DBG3(("dmDownStreamDiscovering: DownStream pNextExpander=%p\n", NextExpander));
536       DM_DBG3(("dmDownStreamDiscovering: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
537       DM_DBG3(("dmDownStreamDiscovering: oneExpander %p did %d\n", oneDeviceData->dmExpander, oneDeviceData->dmExpander->id));
538       
539       DM_DBG3(("dmDownStreamDiscovering: 2nd oneDeviceData %p did %d\n", NextExpander->dmDevice, NextExpander->dmDevice->id));
540       DM_DBG3(("dmDownStreamDiscovering: 2nd oneExpander %p did %d\n", NextExpander, NextExpander->id));
541       DM_DBG3(("dmDownStreamDiscovering: 2nd used oneExpander %p did %d\n", NextExpander->dmDevice->dmExpander, NextExpander->dmDevice->dmExpander->id));
542       
543       if (NextExpander != NextExpander->dmDevice->dmExpander)
544       {
545         DM_DBG3(("dmDownStreamDiscovering: wrong!!!\n"));
546       }
547       
548                   
549       dmReportGeneralSend(dmRoot, NextExpander->dmDevice);            
550       break;
551       /* If the discovery status is DISCOVERY_CONFIG_ROUTING */
552     case DISCOVERY_CONFIG_ROUTING:
553     case DISCOVERY_REPORT_PHY_SATA:
554
555       /* set discovery status */
556       onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
557       
558       DM_DBG3(("dmDownStreamDiscovering: pPort->discovery.status=DISCOVERY_CONFIG_ROUTING, make it DOWN_STREAM\n"));
559       /* If not the last phy */    
560       if ( NextExpander->discoveringPhyId < NextExpander->dmDevice->numOfPhys )
561       {      
562         DM_DBG3(("dmDownStreamDiscovering: pNextExpander->discoveringPhyId=0x%x pNextExpander->numOfPhys=0x%x.  Send More Discover\n",
563                  NextExpander->discoveringPhyId, NextExpander->dmDevice->numOfPhys));
564         /* Send discover for the next expander */
565         dmDiscoverSend(dmRoot, NextExpander->dmDevice);                  
566         }
567       /* If it's the last phy */    
568       else
569       {
570         DM_DBG3(("dmDownStreamDiscovering: Last Phy, remove expander%p  start DownStream=%p\n",
571                  NextExpander, NextExpander->dmDevice));
572         dmDiscoveringExpanderRemove(dmRoot, onePortContext, NextExpander);
573         dmDownStreamDiscovering(dmRoot, onePortContext, NextExpander->dmDevice);
574       }
575       break;
576       
577     default:
578       DM_DBG3(("dmDownStreamDiscovering: *** Unknown pPort->discovery.status=0x%x\n", onePortContext->discovery.status));
579     }
580   }
581   /* If no expander for continue discoving */
582   else
583   {
584     DM_DBG3(("dmDownStreamDiscovering: No more expander DONE\n"));
585     /* discover done */
586     dmDiscoverDone(dmRoot, onePortContext, DM_RC_SUCCESS);
587   }  
588   
589   
590   return;
591 }                      
592
593 osGLOBAL void
594 dmUpStreamDiscoverExpanderPhy(
595                               dmRoot_t              *dmRoot,
596                               dmIntPortContext_t    *onePortContext,
597                               dmExpander_t          *oneExpander,
598                               smpRespDiscover_t     *pDiscoverResp
599                              )
600 {
601   agsaSASIdentify_t       sasIdentify;
602   dmSASSubID_t            dmSASSubID;
603   bit32                   attachedSasHi, attachedSasLo;
604   dmExpander_t            *AttachedExpander = agNULL;
605   bit8                    connectionRate;
606   dmDeviceData_t          *oneDeviceData = agNULL;
607   dmDeviceData_t          *AttachedDevice = agNULL;
608   dmIntRoot_t             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
609   dmIntContext_t          *dmAllShared  = (dmIntContext_t *)&dmIntRoot->dmAllShared;
610   
611   
612   DM_DBG3(("dmUpStreamDiscoverExpanderPhy: start\n"));
613   
614   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
615   {
616     DM_DBG1(("dmUpStreamDiscoverExpanderPhy: invalid port or aborted discovery!!!\n"));  
617     return;
618   }
619   
620   if (oneExpander != oneExpander->dmDevice->dmExpander)
621   {
622     DM_DBG1(("dmUpStreamDiscoverExpanderPhy: wrong!!!\n"));
623   }
624   
625   dm_memset(&sasIdentify, 0, sizeof(agsaSASIdentify_t));
626     
627   oneDeviceData = oneExpander->dmDevice;
628  
629   DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n",
630            oneExpander->discoveringPhyId,
631            oneDeviceData->SASAddressID.sasAddressHi,
632            oneDeviceData->SASAddressID.sasAddressLo));
633   
634   DM_DBG3(("   Attached device: %s\n",
635            ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" : 
636              (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" : 
637               (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
638   
639   
640   if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
641   {
642     DM_DBG3(("   SAS address    : %08x-%08x\n",
643       DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp), 
644               DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
645     DM_DBG3(("   SSP Target     : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
646     DM_DBG3(("   STP Target     : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
647     DM_DBG3(("   SMP Target     : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
648     DM_DBG3(("   SATA DEVICE    : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
649     DM_DBG3(("   SSP Initiator  : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
650     DM_DBG3(("   STP Initiator  : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
651     DM_DBG3(("   SMP Initiator  : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
652     DM_DBG3(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
653     DM_DBG3(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier)); 
654   }
655   
656   /* for debugging */
657   if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
658   {
659     DM_DBG1(("dmUpStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n"));
660     DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d !!!\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
661     dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
662     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
663     return;
664   }
665   
666   /* saving routing attribute for non self-configuring expanders */
667   oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = (bit8)DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
668   
669   if ( oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE )
670   {
671     DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_FANOUT_EXPANDER\n"));
672     if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
673     {
674       DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing on fanout expander device!!!\n"));
675
676       /* discovery error */
677       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
678         = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
679       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
680         = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
681       onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
682       DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
683                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
684                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
685                 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
686
687       /* (2.1.3) discovery done */
688       dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
689       return;        
690     }    
691   }
692   else
693   {
694     DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_EDGE_EXPANDER\n"));
695     if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
696     {
697       /* Setup sasIdentify for the attached device */
698       sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
699       sasIdentify.deviceType_addressFrameType = (bit8)(pDiscoverResp->attachedDeviceType & 0x70);
700       sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
701       sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
702       *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
703       *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
704
705       /* incremental discovery */       
706       dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
707       dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
708       dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
709       dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
710        
711       attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
712       attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
713  
714       /* If the phy has subtractive routing attribute */
715       if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
716       {       
717         DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_ROUTING_SUBTRACTIVE\n"));
718         /* Setup upstream phys */
719         dmExpanderUpStreamPhyAdd(dmRoot, oneExpander, (bit8) pDiscoverResp->attachedPhyIdentifier);
720         /* If the expander already has an upsteam device set up */
721         if (oneExpander->hasUpStreamDevice == agTRUE)
722         {
723           /* just to update MCN */          
724           dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
725           /* If the sas address doesn't match */
726           if ( ((oneExpander->upStreamSASAddressHi != attachedSasHi) ||
727                 (oneExpander->upStreamSASAddressLo != attachedSasLo)) &&
728                (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
729                 DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
730               )
731           {
732             /* TODO: discovery error, callback */
733             DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n"));
734             /* call back to notify discovery error */
735             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
736               = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
737             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
738               = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
739             onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
740             DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
741                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
742                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
743                 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
744             /* discovery done */
745             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
746           }
747         }
748         else
749         {
750           /* Setup SAS address for up stream device */
751           oneExpander->hasUpStreamDevice = agTRUE;
752           oneExpander->upStreamSASAddressHi = attachedSasHi;
753           oneExpander->upStreamSASAddressLo = attachedSasLo;
754           if ( (onePortContext->sasLocalAddressHi != attachedSasHi)
755               || (onePortContext->sasLocalAddressLo != attachedSasLo) )
756           {
757             /* Find the device from the discovered list */
758             AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
759             /* New device, If the device has been discovered before */
760             if ( AttachedDevice != agNULL) /* old device */
761             {
762               DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Seen This Device Before\n"));
763               /* If attached device is an edge expander */
764               if ( AttachedDevice->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
765               {
766                 /* The attached device is an expander */
767                 AttachedExpander = AttachedDevice->dmExpander;
768                 /* If the two expanders are the root of the two edge expander sets */
769                 if ( (AttachedExpander->upStreamSASAddressHi ==
770                       DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
771                      && (AttachedExpander->upStreamSASAddressLo ==
772                         DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)) )
773                 {
774                   /* Setup upstream expander for the pExpander */
775                   oneExpander->dmUpStreamExpander = AttachedExpander;                
776                 }
777                 /* If the two expanders are not the root of the two edge expander sets */
778                 else
779                 {
780                   /* TODO: loop found, discovery error, callback */
781                   DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error loop detection!!!\n"));
782                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
783                     = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
784                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
785                     = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
786                   onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
787                   DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
788                            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
789                            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
790                            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));                  
791                                 /* discovery done */
792                   dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
793                 }  
794               }
795               /* If attached device is not an edge expander */
796               else
797               {
798                 /*TODO: should not happen, ASSERT */
799                 DM_DBG3(("dmUpStreamDiscoverExpanderPhy, *** Attached Device is not Edge. Confused!!!\n"));
800               }
801             } /* AttachedExpander != agNULL */
802             /* New device, If the device has not been discovered before */
803             else /* new device */
804             {
805               /* Add the device */    
806               DM_DBG3(("dmUpStreamDiscoverExpanderPhy: New device\n"));
807               /* read minimum rate from the configuration 
808                  onePortContext->LinkRate is SPC's local link rate
809               */
810               connectionRate = (bit8)MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp));
811               DM_DBG3(("dmUpStreamDiscoverExpanderPhy: link rate 0x%x\n", onePortContext->LinkRate));
812               DM_DBG3(("dmUpStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp))); 
813               DM_DBG3(("dmUpStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate));
814               if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))    
815               {
816                 /* incremental discovery */
817                 if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
818                 {
819                   AttachedDevice = dmPortSASDeviceAdd(
820                                                     dmRoot,
821                                                     onePortContext,
822                                                     sasIdentify,
823                                                     agFALSE,
824                                                     connectionRate,
825                                                     dmAllShared->itNexusTimeout,
826                                                     0,
827                                                     STP_DEVICE_TYPE,
828                                                     oneDeviceData,
829                                                     oneExpander,
830                                                     pDiscoverResp->phyIdentifier
831                                                     );
832                 }
833                 else
834                 {
835                   /* incremental discovery */
836                   AttachedDevice = dmFindRegNValid(
837                                                      dmRoot,
838                                                      onePortContext,
839                                                      &dmSASSubID
840                                                      );
841                   /* not registered and not valid; add this*/                                   
842                   if (AttachedDevice == agNULL)
843                   {
844                     AttachedDevice = dmPortSASDeviceAdd(
845                                                     dmRoot,
846                                                     onePortContext,
847                                                     sasIdentify,
848                                                     agFALSE,
849                                                     connectionRate,
850                                                     dmAllShared->itNexusTimeout,
851                                                     0,
852                                                     STP_DEVICE_TYPE,
853                                                     oneDeviceData,
854                                                     oneExpander,
855                                                     pDiscoverResp->phyIdentifier
856                                                     );
857                   }
858                 }
859               } /* DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp) */
860               else
861               {
862                 /* incremental discovery */
863                 if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
864                 {            
865                   AttachedDevice = dmPortSASDeviceAdd(
866                                                     dmRoot,
867                                                     onePortContext,
868                                                     sasIdentify,
869                                                     agFALSE,
870                                                     connectionRate,
871                                                     dmAllShared->itNexusTimeout,
872                                                     0,
873                                                     SAS_DEVICE_TYPE,
874                                                     oneDeviceData,
875                                                     oneExpander,
876                                                     pDiscoverResp->phyIdentifier
877                                                     );
878                 }
879                 else
880                 {
881                   /* incremental discovery */
882                   AttachedDevice = dmFindRegNValid(
883                                                      dmRoot,
884                                                      onePortContext,
885                                                      &dmSASSubID
886                                                      );
887                   /* not registered and not valid; add this*/
888                   if (AttachedDevice == agNULL)
889                   {
890                     AttachedDevice = dmPortSASDeviceAdd(
891                                                     dmRoot,
892                                                     onePortContext,
893                                                     sasIdentify,
894                                                     agFALSE,
895                                                     connectionRate,
896                                                     dmAllShared->itNexusTimeout,
897                                                     0,
898                                                     SAS_DEVICE_TYPE,
899                                                     oneDeviceData,
900                                                     oneExpander,
901                                                     pDiscoverResp->phyIdentifier
902                                                     );
903                   }                    
904                 }                                                    
905               }
906                /* If the device is added successfully */    
907               if ( AttachedDevice != agNULL)
908               {
909
910                  /* (3.1.2.3.2.3.2.1) callback about new device */
911                 if ( DISCRSP_IS_SSP_TARGET(pDiscoverResp) 
912                     || DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)
913                     || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)
914                     || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) )
915                 {
916                   DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found SSP/SMP SAS %08x-%08x\n",
917                       attachedSasHi, attachedSasLo));
918                 }
919                 else
920                 {
921                   DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found a SAS STP device.\n"));
922                 }
923                  /* If the attached device is an expander */
924                 if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) 
925                     || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) )
926                 {
927                   /* Allocate an expander data structure */
928                   AttachedExpander = dmDiscoveringExpanderAlloc(
929                                                                 dmRoot,
930                                                                 onePortContext,
931                                                                 AttachedDevice
932                                                                                                                        );
933     
934                   DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found expander=%p\n", AttachedExpander));
935                   /* If allocate successfully */
936                   if ( AttachedExpander != agNULL)
937                   {                  
938                     /* Add the pAttachedExpander to discovering list */
939                     dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
940                     /* Setup upstream expander for the pExpander */
941                     oneExpander->dmUpStreamExpander = AttachedExpander;
942                   }
943                   /* If failed to allocate */
944                   else
945                   {
946                     DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Failed to allocate expander data structure!!!\n"));
947                     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
948                   }
949                 }
950                 /* If the attached device is an end device */
951                 else
952                 {
953                   DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found end device\n"));
954                   /* LP2006-05-26 added upstream device to the newly found device */
955                   AttachedDevice->dmExpander = oneExpander;
956                   oneExpander->dmUpStreamExpander = agNULL;
957                 }
958               }
959               else
960               {
961                 DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Failed to add a device!!!\n"));
962                 dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
963               }
964    
965     
966       
967             } /* else, new device */
968           } /* onePortContext->sasLocalAddressLo != attachedSasLo */
969         } /* else */
970       } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE */
971     } /* DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE */
972   } /* big else */
973   
974   
975   
976    oneExpander->discoveringPhyId ++;
977    if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
978      {
979        if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
980        {
981          DM_DBG3(("dmUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM find more ...\n"));
982          /* continue discovery for the next phy */  
983          dmDiscoverSend(dmRoot, oneDeviceData);
984        }
985        else
986        {
987          DM_DBG3(("dmUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM last phy continue upstream..\n"));
988
989          /* for MCN */
990          dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);         
991          /* remove the expander from the discovering list */
992          dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
993          /* continue upstream discovering */  
994          dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
995        }
996    }
997    else
998    {
999       DM_DBG3(("dmUpStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));  
1000    
1001    }
1002    
1003   DM_DBG3(("dmUpStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
1004   
1005   return;
1006 }                                       
1007
1008 osGLOBAL void
1009 dmUpStreamDiscover2ExpanderPhy(
1010                               dmRoot_t              *dmRoot,
1011                               dmIntPortContext_t    *onePortContext,
1012                               dmExpander_t          *oneExpander,
1013                               smpRespDiscover2_t    *pDiscoverResp
1014                               )
1015 {
1016   dmDeviceData_t          *oneDeviceData;
1017   dmDeviceData_t          *AttachedDevice = agNULL;
1018   dmExpander_t            *AttachedExpander;    
1019   agsaSASIdentify_t       sasIdentify;
1020   bit8                    connectionRate;
1021   bit32                   attachedSasHi, attachedSasLo;
1022   dmSASSubID_t            dmSASSubID;
1023   dmIntRoot_t             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
1024   dmIntContext_t          *dmAllShared  = (dmIntContext_t *)&dmIntRoot->dmAllShared;
1025   
1026   DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: start\n"));
1027   
1028   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
1029   {
1030     DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: invalid port or aborted discovery!!!\n"));  
1031     return;
1032   }
1033   
1034   if (oneExpander != oneExpander->dmDevice->dmExpander)
1035   {
1036     DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: wrong!!!\n"));
1037   }
1038   
1039   dm_memset(&sasIdentify, 0, sizeof(agsaSASIdentify_t));
1040     
1041   oneDeviceData = oneExpander->dmDevice;
1042   
1043   DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Phy #%d of SAS %08x-%08x\n",
1044            oneExpander->discoveringPhyId,
1045            oneDeviceData->SASAddressID.sasAddressHi,
1046            oneDeviceData->SASAddressID.sasAddressLo));
1047   
1048   DM_DBG2(("   Attached device: %s\n",
1049            ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" : 
1050              (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" : 
1051               (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
1052   
1053
1054   if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
1055   {
1056     DM_DBG2(("   SAS address    : %08x-%08x\n",
1057       SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp), 
1058               SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
1059     DM_DBG2(("   SSP Target     : %d\n", SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
1060     DM_DBG2(("   STP Target     : %d\n", SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
1061     DM_DBG2(("   SMP Target     : %d\n", SAS2_DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
1062     DM_DBG2(("   SATA DEVICE    : %d\n", SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
1063     DM_DBG2(("   SSP Initiator  : %d\n", SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
1064     DM_DBG2(("   STP Initiator  : %d\n", SAS2_DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
1065     DM_DBG2(("   SMP Initiator  : %d\n", SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
1066     DM_DBG2(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
1067     DM_DBG2(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier)); 
1068   }
1069   
1070   if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
1071   {
1072     DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: !!! Incorrect SMP response !!!\n"));
1073     DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
1074     dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover2_t));
1075     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1076     return;
1077   }
1078  
1079   /* saving routing attribute for non self-configuring expanders */
1080   oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
1081   
1082   if ( oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE )
1083   {
1084     DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_DEV_TYPE_FANOUT_EXPANDER\n"));
1085     if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
1086     {
1087       DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing on fanout expander device!!!\n"));
1088
1089       /* discovery error */
1090       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1091         = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1092       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1093         = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1094       onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1095       DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1096                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1097                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1098                 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1099
1100       /* (2.1.3) discovery done */
1101       dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1102       return;        
1103     }    
1104   }
1105   else
1106   {
1107     DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_DEV_TYPE_EDGE_EXPANDER\n"));
1108     
1109     if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
1110     {
1111       /* Setup sasIdentify for the attached device */
1112       sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
1113       sasIdentify.deviceType_addressFrameType = pDiscoverResp->attachedDeviceTypeReason & 0x70;
1114       sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
1115       sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
1116       *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
1117       *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
1118
1119       /* incremental discovery */       
1120       dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
1121       dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
1122       dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
1123       dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
1124        
1125       attachedSasHi = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
1126       attachedSasLo = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
1127       
1128       /* If the phy has subtractive routing attribute */
1129       if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
1130       {       
1131         DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_ROUTING_SUBTRACTIVE\n"));
1132         /* Setup upstream phys */
1133         dmExpanderUpStreamPhyAdd(dmRoot, oneExpander, (bit8) pDiscoverResp->attachedPhyIdentifier);
1134         /* If the expander already has an upsteam device set up */
1135         if (oneExpander->hasUpStreamDevice == agTRUE)
1136         {
1137           /* just to update MCN */          
1138           dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);          
1139           /* If the sas address doesn't match */
1140           if ( ((oneExpander->upStreamSASAddressHi != attachedSasHi) ||
1141                 (oneExpander->upStreamSASAddressLo != attachedSasLo)) &&
1142                (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
1143                 SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1144               )
1145           {
1146             /* TODO: discovery error, callback */
1147             DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n"));
1148             /* call back to notify discovery error */
1149             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1150               = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1151             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1152               = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1153             onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1154             DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1155                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1156                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1157                       onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1158             /* discovery done */
1159             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1160           }
1161         }
1162         else
1163         {
1164           /* Setup SAS address for up stream device */
1165           oneExpander->hasUpStreamDevice = agTRUE;
1166           oneExpander->upStreamSASAddressHi = attachedSasHi;
1167           oneExpander->upStreamSASAddressLo = attachedSasLo;
1168
1169           if ( (onePortContext->sasLocalAddressHi != attachedSasHi)
1170               || (onePortContext->sasLocalAddressLo != attachedSasLo) )
1171           {
1172             /* Find the device from the discovered list */
1173             AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
1174             /* If the device has been discovered before */
1175             if ( AttachedDevice != agNULL)
1176             {
1177               DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Seen This Device Before\n"));
1178               /* If attached device is an edge expander */
1179               if ( AttachedDevice->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
1180               {
1181                 /* The attached device is an expander */
1182                 AttachedExpander = AttachedDevice->dmExpander;
1183                 /* If the two expanders are the root of the two edge expander sets */
1184                 if ( (AttachedExpander->upStreamSASAddressHi ==
1185                       DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
1186                      && (AttachedExpander->upStreamSASAddressLo ==
1187                         DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)) )
1188                 {
1189                   /* Setup upstream expander for the pExpander */
1190                   oneExpander->dmUpStreamExpander = AttachedExpander;                
1191                 }
1192                 /* If the two expanders are not the root of the two edge expander sets */
1193                 else
1194                 {
1195                   /* TODO: loop found, discovery error, callback */
1196                   DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error loop detection!!!\n"));
1197                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1198                     = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1199                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1200                     = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1201                   onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1202                   DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1203                             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1204                             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1205                             onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1206                   /* discovery done */
1207                   dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1208                 }  
1209               }
1210               /* If attached device is not an edge expander */
1211               else
1212               {
1213                 /*TODO: should not happen, ASSERT */
1214                 DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, *** Attached Device is not Edge. Confused!!!\n"));
1215               }
1216             }
1217             /* If the device has not been discovered before */
1218             else
1219             {
1220               /* Add the device */    
1221               DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: New device\n"));
1222               /* read minimum rate from the configuration 
1223                  onePortContext->LinkRate is SPC's local link rate
1224               */
1225               connectionRate = MIN(onePortContext->LinkRate, SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pDiscoverResp));
1226               DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: link rate 0x%x\n", onePortContext->LinkRate));
1227               DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: negotiatedPhyLinkRate 0x%x\n", SAS2_DISCRSP_GET_LINKRATE(pDiscoverResp))); 
1228               DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: connectionRate 0x%x\n", connectionRate));
1229               //hhhhhhhh
1230               if (SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp))    
1231               {
1232                 /* incremental discovery */
1233                 if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
1234                 {
1235                   AttachedDevice = dmPortSASDeviceAdd(
1236                                                     dmRoot,
1237                                                     onePortContext,
1238                                                     sasIdentify,
1239                                                     agFALSE,
1240                                                     connectionRate,
1241                                                     dmAllShared->itNexusTimeout,
1242                                                     0,
1243                                                     STP_DEVICE_TYPE,
1244                                                     oneDeviceData,
1245                                                     oneExpander,
1246                                                     pDiscoverResp->phyIdentifier
1247                                                     );
1248                 }
1249                 else
1250                 {
1251                   /* incremental discovery */
1252                   AttachedDevice = dmFindRegNValid(
1253                                                      dmRoot,
1254                                                      onePortContext,
1255                                                      &dmSASSubID
1256                                                      );
1257                   /* not registered and not valid; add this*/                                   
1258                   if (AttachedDevice == agNULL)
1259                   {
1260                     AttachedDevice = dmPortSASDeviceAdd(
1261                                                     dmRoot,
1262                                                     onePortContext,
1263                                                     sasIdentify,
1264                                                     agFALSE,
1265                                                     connectionRate,
1266                                                     dmAllShared->itNexusTimeout,
1267                                                     0,
1268                                                     STP_DEVICE_TYPE,
1269                                                     oneDeviceData,
1270                                                     oneExpander,
1271                                                     pDiscoverResp->phyIdentifier
1272                                                     );
1273                   }
1274                 }
1275               }
1276               else
1277               {
1278                 /* incremental discovery */
1279                 if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
1280                 {            
1281                   AttachedDevice = dmPortSASDeviceAdd(
1282                                                     dmRoot,
1283                                                     onePortContext,
1284                                                     sasIdentify,
1285                                                     agFALSE,
1286                                                     connectionRate,
1287                                                     dmAllShared->itNexusTimeout,
1288                                                     0,
1289                                                     SAS_DEVICE_TYPE,
1290                                                     oneDeviceData,
1291                                                     oneExpander,
1292                                                     pDiscoverResp->phyIdentifier
1293                                                     );
1294                 }
1295                 else
1296                 {
1297                   /* incremental discovery */
1298                   AttachedDevice = dmFindRegNValid(
1299                                                      dmRoot,
1300                                                      onePortContext,
1301                                                      &dmSASSubID
1302                                                      );
1303                   /* not registered and not valid; add this*/
1304                   if (AttachedDevice == agNULL)
1305                   {
1306                     AttachedDevice = dmPortSASDeviceAdd(
1307                                                     dmRoot,
1308                                                     onePortContext,
1309                                                     sasIdentify,
1310                                                     agFALSE,
1311                                                     connectionRate,
1312                                                     dmAllShared->itNexusTimeout,
1313                                                     0,
1314                                                     SAS_DEVICE_TYPE,
1315                                                     oneDeviceData,
1316                                                     oneExpander,
1317                                                     pDiscoverResp->phyIdentifier
1318                                                     );
1319                   }                    
1320                 }                                                    
1321               }
1322               /* If the device is added successfully */    
1323               if ( AttachedDevice != agNULL)
1324               {
1325
1326                  /* (3.1.2.3.2.3.2.1) callback about new device */
1327                 if ( SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp) 
1328                     || SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)
1329                     || SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)
1330                     || SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) )
1331                 {
1332                   DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found SSP/SMP SAS %08x-%08x\n",
1333                       attachedSasHi, attachedSasLo));
1334                 }
1335                 else
1336                 {
1337                   DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found a SAS STP device.\n"));
1338                 }
1339                  /* If the attached device is an expander */
1340                 if ( (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) 
1341                     || (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) )
1342                 {
1343                   /* Allocate an expander data structure */
1344                   AttachedExpander = dmDiscoveringExpanderAlloc(
1345                                                                 dmRoot,
1346                                                                 onePortContext,
1347                                                                 AttachedDevice
1348                                                                );
1349     
1350                   DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found expander=%p\n", AttachedExpander));
1351                   /* If allocate successfully */
1352                   if ( AttachedExpander != agNULL)
1353                   {                  
1354                     /* Add the pAttachedExpander to discovering list */
1355                     dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
1356                     /* Setup upstream expander for the pExpander */
1357                     oneExpander->dmUpStreamExpander = AttachedExpander;
1358                   }
1359                   /* If failed to allocate */
1360                   else
1361                   {
1362                     DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, Failed to allocate expander data structure!!!\n"));
1363                     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1364                   }
1365                 }
1366                 /* If the attached device is an end device */
1367                 else
1368                 {
1369                   DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found end device\n"));
1370                   /* LP2006-05-26 added upstream device to the newly found device */
1371                   AttachedDevice->dmExpander = oneExpander;
1372                   oneExpander->dmUpStreamExpander = agNULL;
1373                 }
1374               }
1375               else
1376               {
1377                 DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, Failed to add a device!!!\n"));
1378                 dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1379               }
1380             }
1381           }
1382         }
1383       } /* substractive routing */
1384     }
1385   }
1386   
1387    oneExpander->discoveringPhyId ++;
1388    if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
1389      {
1390        if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
1391        {
1392          DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: DISCOVERY_UP_STREAM find more ...\n"));
1393          /* continue discovery for the next phy */  
1394          dmDiscoverSend(dmRoot, oneDeviceData);
1395        }
1396        else
1397        {
1398          DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: DISCOVERY_UP_STREAM last phy continue upstream..\n"));
1399
1400          /* for MCN */
1401          dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);         
1402          /* remove the expander from the discovering list */
1403          dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
1404          /* continue upstream discovering */  
1405          dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
1406        }
1407    }
1408    else
1409    {
1410       DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));  
1411    
1412    }
1413    
1414   DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
1415   
1416   return;
1417 }                            
1418
1419
1420 osGLOBAL void
1421 dmDownStreamDiscoverExpanderPhy(
1422                                 dmRoot_t              *dmRoot,
1423                                 dmIntPortContext_t    *onePortContext,
1424                                 dmExpander_t          *oneExpander,
1425                                 smpRespDiscover_t     *pDiscoverResp
1426                                )
1427 {
1428   agsaSASIdentify_t       sasIdentify;
1429   dmSASSubID_t            dmSASSubID;
1430   bit32                   attachedSasHi, attachedSasLo;
1431   dmExpander_t            *AttachedExpander;
1432   dmExpander_t            *UpStreamExpander;
1433   dmExpander_t            *ConfigurableExpander = agNULL;
1434   bit8                    connectionRate, negotiatedPhyLinkRate;
1435   bit32                   configSASAddressHi;
1436   bit32                   configSASAddressLo;
1437   bit32                   dupConfigSASAddr = agFALSE;
1438   dmDeviceData_t          *oneDeviceData;
1439   dmDeviceData_t          *AttachedDevice = agNULL;
1440   bit32                   SAS2SAS11Check = agFALSE;
1441   dmIntRoot_t             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
1442   dmIntContext_t          *dmAllShared  = (dmIntContext_t *)&dmIntRoot->dmAllShared;
1443   
1444   
1445   
1446   DM_DBG3(("dmDownStreamDiscoverExpanderPhy: start\n"));
1447   DM_DBG3(("dmDownStreamDiscoverExpanderPhy: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
1448   DM_DBG3(("dmDownStreamDiscoverExpanderPhy: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));  
1449   
1450   DM_ASSERT(dmRoot, "(dmDownStreamDiscoverExpanderPhy) dmRoot NULL");
1451   DM_ASSERT(onePortContext, "(dmDownStreamDiscoverExpanderPhy) pPort NULL");
1452   DM_ASSERT(oneExpander, "(dmDownStreamDiscoverExpanderPhy) pExpander NULL");
1453   DM_ASSERT(pDiscoverResp, "(dmDownStreamDiscoverExpanderPhy) pDiscoverResp NULL");
1454
1455   DM_DBG3(("dmDownStreamDiscoverExpanderPhy: onePortContxt=%p  oneExpander=%p\n", onePortContext, oneExpander));
1456            
1457   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
1458   {
1459     DM_DBG1(("dmDownStreamDiscoverExpanderPhy: invalid port or aborted discovery!!!\n"));  
1460     return;
1461   }
1462   
1463   if (oneExpander != oneExpander->dmDevice->dmExpander)
1464   {
1465     DM_DBG1(("dmDownStreamDiscoverExpanderPhy: wrong!!!\n"));
1466   }
1467   
1468   /* (1) Find the device structure of the expander */
1469   oneDeviceData = oneExpander->dmDevice;
1470   
1471   DM_ASSERT(oneDeviceData, "(dmDownStreamDiscoverExpanderPhy) pDevice NULL");
1472   
1473   /* for debugging */
1474   DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n",
1475            oneExpander->discoveringPhyId,
1476            oneDeviceData->SASAddressID.sasAddressHi,
1477            oneDeviceData->SASAddressID.sasAddressLo));
1478   
1479   DM_DBG3(("   Attached device: %s\n",
1480            ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" : 
1481              (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" : 
1482               (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
1483   
1484   
1485   /* for debugging */
1486   if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
1487   {
1488     DM_DBG1(("dmDownStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n"));
1489     DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d !!!\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
1490     dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
1491     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1492     return;
1493   }
1494   
1495   if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
1496   {
1497     DM_DBG3(("   SAS address    : %08x-%08x\n",
1498       DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp), 
1499               DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
1500     DM_DBG3(("   SSP Target     : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
1501     DM_DBG3(("   STP Target     : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
1502     DM_DBG3(("   SMP Target     : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
1503     DM_DBG3(("   SATA DEVICE    : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
1504     DM_DBG3(("   SSP Initiator  : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
1505     DM_DBG3(("   STP Initiator  : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
1506     DM_DBG3(("   SMP Initiator  : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
1507     DM_DBG3(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
1508     DM_DBG3(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
1509     
1510   }
1511   /* end for debugging */
1512   
1513   /* saving routing attribute for non self-configuring expanders */
1514   oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
1515   
1516   oneExpander->discoverSMPAllowed = agTRUE;
1517   
1518   /* If a device is attached */
1519   if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) !=  SAS_NO_DEVICE)
1520   {
1521     /* Setup sasIdentify for the attached device */
1522     sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
1523     sasIdentify.deviceType_addressFrameType = pDiscoverResp->attachedDeviceType & 0x70;
1524     sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
1525     sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
1526     *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
1527     *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
1528
1529     /* incremental discovery */       
1530     dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
1531     dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
1532     dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
1533     dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
1534         
1535     attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
1536     attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
1537   
1538     /* If it's a direct routing */
1539     if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_DIRECT)
1540     {
1541       /* If the attached device is an expander */
1542       if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1543           || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) )
1544
1545       {
1546         DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error direct routing can't connect to expander!!!\n"));
1547         onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1548            = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1549         onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1550           = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1551         onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1552         DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1553                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1554                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1555                   onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1556
1557         dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1558         return;
1559       }
1560     }
1561   
1562     /* If the expander's attached device is not myself */
1563     if ( (attachedSasHi != onePortContext->sasLocalAddressHi)
1564          || (attachedSasLo != onePortContext->sasLocalAddressLo) ) 
1565     {
1566       /* Find the attached device from discovered list */
1567       AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
1568       /* If the device has not been discovered before */
1569       if ( AttachedDevice == agNULL) //11
1570       {
1571         /* If the phy has subtractive routing attribute */
1572         if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE &&
1573              (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
1574               DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1575            )
1576         {
1577           /* TODO: discovery error, callback */
1578           DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Deferred!!! **** Topology Error subtractive routing error - inconsistent SAS address!!!\n"));
1579           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1580             = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1581           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1582             = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1583           onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1584           DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1585                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1586                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1587                   onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1588
1589           onePortContext->discovery.DeferredError = agTRUE;
1590         }
1591         else /* 11 */
1592         {
1593           /* Add the device */
1594           /* read minimum rate from the configuration 
1595              onePortContext->LinkRate is SPC's local link rate
1596           */
1597           connectionRate = MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)); 
1598           DM_DBG3(("dmDownStreamDiscoverExpanderPhy: link rate 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo)));
1599           DM_DBG3(("dmDownStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp)));
1600           DM_DBG3(("dmDownStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate));
1601           if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))    
1602           {
1603             if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
1604             {
1605               AttachedDevice = dmPortSASDeviceAdd(
1606                                                   dmRoot,
1607                                                   onePortContext,
1608                                                   sasIdentify,
1609                                                   agFALSE,
1610                                                   connectionRate,
1611                                                   dmAllShared->itNexusTimeout,
1612                                                   0,
1613                                                   STP_DEVICE_TYPE,
1614                                                   oneDeviceData,
1615                                                   oneExpander,
1616                                                   pDiscoverResp->phyIdentifier
1617                                                   );
1618             }
1619             else
1620             {
1621               /* incremental discovery */
1622               AttachedDevice = dmFindRegNValid(
1623                                                  dmRoot,
1624                                                  onePortContext,
1625                                                  &dmSASSubID
1626                                                  );
1627               /* not registered and not valid; add this*/                                   
1628               if (AttachedDevice == agNULL)
1629               {
1630                 AttachedDevice = dmPortSASDeviceAdd(
1631                                                     dmRoot,
1632                                                     onePortContext,
1633                                                     sasIdentify,
1634                                                     agFALSE,
1635                                                     connectionRate,
1636                                                     dmAllShared->itNexusTimeout,
1637                                                     0,
1638                                                     STP_DEVICE_TYPE,
1639                                                     oneDeviceData,
1640                                                     oneExpander,
1641                                                     pDiscoverResp->phyIdentifier
1642                                                     );
1643               }
1644             }
1645           } /* DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp) */
1646           else /* 22 */
1647           {
1648             if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
1649             {            
1650               AttachedDevice = dmPortSASDeviceAdd(
1651                                                   dmRoot,
1652                                                   onePortContext,
1653                                                   sasIdentify,
1654                                                   agFALSE,
1655                                                   connectionRate,
1656                                                   dmAllShared->itNexusTimeout,
1657                                                   0,
1658                                                   SAS_DEVICE_TYPE,
1659                                                   oneDeviceData,
1660                                                   oneExpander,
1661                                                   pDiscoverResp->phyIdentifier
1662                                                   );
1663             }
1664             else
1665             {
1666               /* incremental discovery */
1667               AttachedDevice = dmFindRegNValid(
1668                                               dmRoot,
1669                                               onePortContext,
1670                                               &dmSASSubID
1671                                               );
1672               /* not registered and not valid; add this*/
1673               if (AttachedDevice == agNULL)
1674               {
1675                 AttachedDevice = dmPortSASDeviceAdd(
1676                                                    dmRoot,
1677                                                    onePortContext,
1678                                                    sasIdentify,
1679                                                    agFALSE,
1680                                                    connectionRate,
1681                                                    dmAllShared->itNexusTimeout,
1682                                                    0,
1683                                                    SAS_DEVICE_TYPE,
1684                                                    oneDeviceData,
1685                                                    oneExpander,
1686                                                    pDiscoverResp->phyIdentifier
1687                                                    );
1688               }                    
1689             }                                                    
1690           } /* else 22 */
1691           DM_DBG3(("dmDownStreamDiscoverExpanderPhy: newDevice  pDevice=%p\n", AttachedDevice));
1692           /* If the device is added successfully */    
1693           if ( AttachedDevice != agNULL)
1694           {
1695             if ( SA_IDFRM_IS_SSP_TARGET(&sasIdentify) 
1696                  || SA_IDFRM_IS_SMP_TARGET(&sasIdentify)
1697                  || SA_IDFRM_IS_SSP_INITIATOR(&sasIdentify)
1698                  || SA_IDFRM_IS_SMP_INITIATOR(&sasIdentify) )
1699             {
1700               DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Report a new SAS device !!\n"));  
1701                
1702             }
1703             else
1704             {
1705               if ( SA_IDFRM_IS_STP_TARGET(&sasIdentify) || 
1706                    SA_IDFRM_IS_SATA_DEVICE(&sasIdentify) )
1707               {
1708                 
1709                 DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found an STP or SATA device.\n"));
1710               }
1711               else
1712               {
1713                 DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found Other type of device.\n"));
1714               }
1715             }
1716             
1717             /* LP2006-05-26 added upstream device to the newly found device */
1718             AttachedDevice->dmExpander = oneExpander;
1719             DM_DBG3(("dmDownStreamDiscoverExpanderPhy: AttachedDevice %p did %d\n", AttachedDevice, AttachedDevice->id));
1720             DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Attached oneExpander %p did %d\n",  AttachedDevice->dmExpander,  AttachedDevice->dmExpander->id));
1721             
1722             DM_DBG3(("dmDownStreamDiscoverExpanderPhy: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
1723             DM_DBG3(("dmDownStreamDiscoverExpanderPhy: oneExpander %p did %d\n",  oneDeviceData->dmExpander,  oneDeviceData->dmExpander->id));
1724             
1725             /* If the phy has table routing attribute */
1726             if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
1727             {
1728               /* If the attached device is a fan out expander */
1729               if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1730               {
1731                 /* TODO: discovery error, callback */
1732                 DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys are connected!!!\n"));
1733                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1734                   = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1735                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1736                   = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1737                 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1738                 DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1739                           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1740                           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1741                           onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1742                 /* discovery done */
1743                 dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1744               } 
1745               else if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) 
1746               {
1747                 /* Allocate an expander data structure */
1748                 AttachedExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, AttachedDevice);
1749                  
1750                 DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found a EDGE exp device.%p\n", AttachedExpander));
1751                 /* If allocate successfully */
1752                 if ( AttachedExpander != agNULL)
1753                 {
1754                   /* set up downstream information on configurable expander */              
1755                   dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId); 
1756                   /* Setup upstream information */
1757                   dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
1758                   AttachedExpander->hasUpStreamDevice = agTRUE;
1759                   AttachedExpander->upStreamSASAddressHi 
1760                     = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1761                   AttachedExpander->upStreamSASAddressLo
1762                     = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1763                   AttachedExpander->dmUpStreamExpander = oneExpander;
1764                   /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */
1765                   dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
1766                 }       
1767                 /* If failed to allocate */
1768                 else
1769                 {
1770                   DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Failed to allocate expander data structure!!!\n"));
1771                   /*  discovery done */
1772                   dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1773                 }
1774               } 
1775             } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE */
1776             /* If status is still DISCOVERY_DOWN_STREAM */        
1777             if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
1778             {
1779               DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st before\n"));
1780               dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); 
1781               UpStreamExpander = oneExpander->dmUpStreamExpander;
1782               ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
1783               configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
1784               configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); 
1785               if (ConfigurableExpander)
1786               { 
1787                 if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi 
1788                       == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
1789                      (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo 
1790                       == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
1791                    )
1792                 { /* directly attached between oneExpander and ConfigurableExpander */       
1793                   DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st before loc 1\n"));
1794                   configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi;
1795                   configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo; 
1796                 }
1797                 else
1798                 {
1799                   DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st before loc 2\n"));
1800                   configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
1801                   configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); 
1802                 }                                             
1803               } /* if !ConfigurableExpander */
1804           
1805               dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, 
1806                                                           ConfigurableExpander,   
1807                                                           configSASAddressHi,
1808                                                           configSASAddressLo
1809                                                           );
1810           
1811               if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
1812               {
1813                 DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st q123\n"));
1814                 UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
1815                 ConfigurableExpander->currentDownStreamPhyIndex = 
1816                         dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
1817                 ConfigurableExpander->dmReturnginExpander = oneExpander;
1818                 dmRoutingEntryAdd(dmRoot,
1819                                   ConfigurableExpander, 
1820                                   ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
1821                                   configSASAddressHi,
1822                                   configSASAddressLo
1823                                  );
1824               }                       
1825             } /* onePortContext->discovery.status == DISCOVERY_DOWN_STREAM */
1826           } /* AttachedDevice != agNULL */  
1827           /*  If fail to add the device */    
1828           else
1829           {
1830             DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Failed to add a device!!!\n"));
1831             /*  discovery done */
1832             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1833           }
1834         } /* else 11 */
1835       } /* AttachedDevice == agNULL */
1836       /* If the device has been discovered before */
1837       else /* haha discovered before 33 */
1838       {
1839         /* If the phy has subtractive routing attribute */
1840         if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
1841         {
1842           /* If the expander doesn't have up stream device */
1843           if ( oneExpander->hasUpStreamDevice == agFALSE)
1844           {
1845             /* TODO: discovery error, callback */
1846             DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error loop, or end device connects to two expanders!!!\n"));
1847             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1848               = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1849             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1850               = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1851             onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1852             DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1853                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1854                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1855                       onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1856             /* discovery done */
1857             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1858           }
1859           /* If the expander has up stream device */
1860           else /* 44 */
1861           {
1862             /* If sas address doesn't match */
1863             if ( (oneExpander->upStreamSASAddressHi != attachedSasHi)
1864                  || (oneExpander->upStreamSASAddressLo != attachedSasLo) )
1865             {
1866               /* TODO: discovery error, callback */
1867               DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two subtractive phys!!!\n"));
1868               onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1869                 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1870               onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1871                 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1872               onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1873               DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1874                        onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1875                        onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1876                        onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1877               /* discovery done */
1878               dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1879             }
1880           } /* else 44 */         
1881         } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE */      
1882         /* If the phy has table routing attribute */
1883         else if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
1884         {
1885           /* If the attached device is a fan out expander */
1886           if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1887           {
1888             /* (2.3.3.2.1.1) TODO: discovery error, callback */
1889             DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error fan out expander to routing table phy!!!\n"));
1890             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1891               = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1892             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1893               = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1894             onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1895             DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1896                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1897                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1898                      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1899             /* discovery done */
1900             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1901           }
1902           /* If the attached device is an edge expander */
1903           else if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) 
1904           {
1905             /* Setup up stream inform */
1906             AttachedExpander = AttachedDevice->dmExpander;
1907             DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found edge expander=%p\n", AttachedExpander));
1908             /* If the attached expander has up stream device */
1909             if ( AttachedExpander->hasUpStreamDevice == agTRUE)
1910             {
1911               /* compare the sas address */
1912               if ( (AttachedExpander->upStreamSASAddressHi
1913                     != DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
1914                    || (AttachedExpander->upStreamSASAddressLo
1915                        != DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)))
1916               {
1917                 /* TODO: discovery error, callback */
1918                 SAS2SAS11Check = dmSAS2SAS11ErrorCheck(dmRoot, onePortContext, AttachedExpander, oneExpander, oneExpander);
1919                 if (SAS2SAS11Check == agTRUE)
1920                 {
1921                    DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error SAS2 and SAS1.1!!!\n"));
1922                 }
1923                 else
1924                 {
1925                   DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys connected (1)!!!\n"));
1926                 }
1927                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1928                   = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1929                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1930                   = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1931                 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1932                 DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1933                          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1934                          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1935                          onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1936                 /* discovery done */
1937                 dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1938               }
1939               else
1940               {
1941                 DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Add edge expander=%p\n", AttachedExpander));
1942                 /* set up downstream information on configurable expander */
1943
1944                 dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId); 
1945                 /* haha */
1946                 dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
1947                 /* Add the pAttachedExpander to discovering list */
1948                 dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
1949               }
1950             } /* AttachedExpander->hasUpStreamDevice == agTRUE */      
1951             /* If the attached expander doesn't have up stream device */
1952             else
1953             {
1954               /* TODO: discovery error, callback */
1955               DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys connected (2)!!!\n"));
1956               onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1957                 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1958               onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1959                 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1960               onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1961               DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
1962                        onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
1963                        onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1964                        onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1965               /* discovery done */
1966               dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1967             }
1968           } /* DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE */      
1969         } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE */      
1970         /* do this regradless of sub or table */
1971         /* If status is still DISCOVERY_DOWN_STREAM */            
1972         if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
1973         {
1974           DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd before\n"));
1975           dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); 
1976
1977           UpStreamExpander = oneExpander->dmUpStreamExpander;
1978           ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
1979           configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
1980           configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); 
1981           if (ConfigurableExpander)
1982           { 
1983             if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi 
1984                  == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
1985                  (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo 
1986                    == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
1987                )
1988             { /* directly attached between oneExpander and ConfigurableExpander */       
1989               DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd before loc 1\n"));
1990               configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi;
1991               configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo; 
1992             }
1993             else
1994             {
1995               DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd before loc 2\n"));
1996               configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
1997               configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); 
1998             }                                             
1999           } /* if !ConfigurableExpander */
2000           dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, 
2001                                                       ConfigurableExpander,   
2002                                                       configSASAddressHi,
2003                                                       configSASAddressLo
2004                                                       );
2005           if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
2006           {
2007             DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd q123 \n"));
2008             UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
2009             ConfigurableExpander->currentDownStreamPhyIndex = 
2010                         dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
2011             ConfigurableExpander->dmReturnginExpander = oneExpander;
2012             dmRoutingEntryAdd(dmRoot,
2013                               ConfigurableExpander, 
2014                               ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
2015                               configSASAddressHi,
2016                               configSASAddressLo
2017                              );
2018           }                                        
2019         } /* onePortContext->discovery.status == DISCOVERY_DOWN_STREAM */         
2020         /* incremental discovery */
2021         if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START)
2022         {
2023           connectionRate = MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)); 
2024
2025           if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))    
2026           {
2027             DM_DBG3(("dmDownStreamDiscoverExpanderPhy: incremental SATA_STP\n"));
2028
2029             dmPortSASDeviceAdd(
2030                               dmRoot,
2031                               onePortContext,
2032                               sasIdentify,
2033                               agFALSE,
2034                               connectionRate,
2035                               dmAllShared->itNexusTimeout,
2036                               0,
2037                               STP_DEVICE_TYPE,
2038                               oneDeviceData,
2039                               oneExpander,
2040                               pDiscoverResp->phyIdentifier
2041                               );
2042           }
2043           else
2044           {
2045             DM_DBG3(("dmDownStreamDiscoverExpanderPhy: incremental SAS\n"));
2046
2047
2048              dmPortSASDeviceAdd(
2049                                dmRoot,
2050                                onePortContext,
2051                                sasIdentify,
2052                                agFALSE,
2053                                connectionRate,
2054                                dmAllShared->itNexusTimeout,
2055                                0,
2056                                SAS_DEVICE_TYPE,
2057                                oneDeviceData,
2058                                oneExpander,
2059                                pDiscoverResp->phyIdentifier
2060                                );
2061         
2062           }
2063         } /* onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START */ 
2064       } /* else 33 */       
2065     } /* (attachedSasLo != onePortContext->sasLocalAddressLo) */  
2066   
2067     else /* else 44 */
2068     {
2069       DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found Self\n"));
2070       DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 3rd before\n"));
2071       dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); 
2072
2073       UpStreamExpander = oneExpander->dmUpStreamExpander;
2074       ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
2075       dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, 
2076                                                   ConfigurableExpander,   
2077                                                   onePortContext->sasLocalAddressHi,
2078                                                   onePortContext->sasLocalAddressLo
2079                                                   );
2080       
2081       if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
2082       {
2083         DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 3rd q123 Setup routing table\n"));
2084         UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
2085         ConfigurableExpander->currentDownStreamPhyIndex = 
2086                         dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
2087         ConfigurableExpander->dmReturnginExpander = oneExpander;
2088         dmRoutingEntryAdd(dmRoot,
2089                           ConfigurableExpander, 
2090                           ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
2091                           onePortContext->sasLocalAddressHi,
2092                           onePortContext->sasLocalAddressLo
2093                          );
2094       } 
2095     } /* else 44 */  
2096   } /* DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) !=  SAS_NO_DEVICE */
2097   /* If no device is attached */
2098   else
2099   {
2100
2101    DM_DBG2(("!!!!!!!!!!!!!!!!!!!!! SPIN SATA !!!!!!!!!!!!!!!!!!!!!!!!!!!\n"));
2102    negotiatedPhyLinkRate =      DISCRSP_GET_LINKRATE(pDiscoverResp); // added by thenil
2103
2104      if (negotiatedPhyLinkRate == 0x03)
2105      {
2106
2107         DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: SPIN SATA sent reset\n"));
2108                 dmPhyControlSend(dmRoot,
2109                             oneDeviceData, 
2110                             SMP_PHY_CONTROL_HARD_RESET, 
2111                                                            pDiscoverResp->phyIdentifier
2112                            );
2113     }
2114        
2115     /* do nothing */
2116   }
2117   
2118   
2119   /* Increment the discovering phy id */
2120   oneExpander->discoveringPhyId ++;
2121   
2122   /* If the discovery status is DISCOVERY_DOWN_STREAM */
2123   if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
2124   {
2125     /* If not the last phy */  
2126     if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
2127     {
2128       DM_DBG3(("dmDownStreamDiscoverExpanderPhy: More Phys to discover\n"));
2129       /* continue discovery for the next phy */
2130       dmDiscoverSend(dmRoot, oneDeviceData);
2131     }
2132     /* If the last phy */
2133     else
2134     {
2135       DM_DBG3(("dmDownStreamDiscoverExpanderPhy: No More Phys\n"));
2136
2137       /* for MCN */
2138       dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);  
2139       /* remove the expander from the discovering list */
2140       dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
2141       /* continue downstream discovering */
2142       dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
2143     }  
2144   }
2145   else
2146   {
2147     DM_DBG3(("dmDownStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));  
2148   }  
2149   DM_DBG3(("dmDownStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
2150  
2151   return;
2152 }                                       
2153
2154
2155 /* works at SAS2 expander (called in dmDownStreamDiscover2ExpanderPhy())
2156    if currentExpander is SAS2, called in dmDownStreamDiscover2ExpanderPhy()
2157    if currentExpander is SAS1.1, called in dmDownStreamDiscoverExpanderPhy()
2158 */
2159 osGLOBAL bit32
2160 dmSAS2SAS11ErrorCheck(
2161                       dmRoot_t              *dmRoot,
2162                       dmIntPortContext_t    *onePortContext,
2163                       dmExpander_t          *topExpander,
2164                       dmExpander_t          *bottomExpander,
2165                       dmExpander_t          *currentExpander
2166                      )
2167 {
2168   bit32                   result = agFALSE, i = 0;
2169   bit8                    downStreamPhyID, upStreamPhyID; 
2170   
2171   DM_DBG2(("dmSAS2SAS11ErrorCheck: start\n"));
2172   
2173   if (topExpander == agNULL)
2174   {
2175     DM_DBG2(("dmSAS2SAS11ErrorCheck: topExpander is NULL\n"));
2176     return result;
2177   }
2178   if (bottomExpander == agNULL)
2179   {
2180     DM_DBG2(("dmSAS2SAS11ErrorCheck: bottomExpander is NULL\n"));
2181     return result;
2182   }
2183   
2184   if (currentExpander == agNULL)
2185   {
2186     DM_DBG2(("dmSAS2SAS11ErrorCheck: currentExpander is NULL\n"));
2187     return result;
2188   }
2189   
2190   DM_DBG2(("dmSAS2SAS11ErrorCheck: topExpander addrHi 0x%08x addrLo 0x%08x\n", 
2191             topExpander->dmDevice->SASAddressID.sasAddressHi, topExpander->dmDevice->SASAddressID.sasAddressLo));
2192   DM_DBG2(("dmSAS2SAS11ErrorCheck: bottomExpander addrHi 0x%08x addrLo 0x%08x\n", 
2193             bottomExpander->dmDevice->SASAddressID.sasAddressHi, bottomExpander->dmDevice->SASAddressID.sasAddressLo));
2194   DM_DBG2(("dmSAS2SAS11ErrorCheck: currentExpander addrHi 0x%08x addrLo 0x%08x\n", 
2195             currentExpander->dmDevice->SASAddressID.sasAddressHi, currentExpander->dmDevice->SASAddressID.sasAddressLo));
2196             
2197   for (i=0;i<DM_MAX_EXPANDER_PHYS;i++)
2198   {
2199     downStreamPhyID = topExpander->downStreamPhys[i];
2200     upStreamPhyID = bottomExpander->upStreamPhys[i];
2201     if (currentExpander->SAS2 == 1)
2202     {
2203       if ( downStreamPhyID ==  upStreamPhyID &&
2204            topExpander->routingAttribute[downStreamPhyID] == SAS_ROUTING_TABLE &&
2205            bottomExpander->routingAttribute[i] == SAS_ROUTING_SUBTRACTIVE && 
2206            topExpander->SAS2 == 0 &&
2207            bottomExpander->SAS2 == 1
2208          )
2209       {
2210         result = agTRUE;
2211         break;
2212       }
2213     }    
2214     else if (currentExpander->SAS2 == 0)
2215     {
2216       if ( downStreamPhyID ==  upStreamPhyID &&
2217            topExpander->routingAttribute[downStreamPhyID] == SAS_ROUTING_SUBTRACTIVE &&
2218            bottomExpander->routingAttribute[i] == SAS_ROUTING_TABLE &&
2219            topExpander->SAS2 == 1 &&
2220            bottomExpander->SAS2 == 0
2221          )
2222       {
2223         result = agTRUE;
2224         break;
2225       }
2226     }
2227   }
2228   return result;
2229 }                                    
2230
2231 osGLOBAL void
2232 dmDownStreamDiscover2ExpanderPhy(
2233                                 dmRoot_t              *dmRoot,
2234                                 dmIntPortContext_t    *onePortContext,
2235                                 dmExpander_t          *oneExpander,
2236                                 smpRespDiscover2_t     *pDiscoverResp
2237                                 )
2238 {
2239   dmDeviceData_t          *oneDeviceData;
2240   dmExpander_t            *UpStreamExpander;
2241   dmDeviceData_t          *AttachedDevice = agNULL;
2242   dmExpander_t            *AttachedExpander;
2243   agsaSASIdentify_t       sasIdentify;
2244   bit8                    connectionRate;
2245   bit32                   attachedSasHi, attachedSasLo;
2246   dmSASSubID_t            dmSASSubID;
2247   dmExpander_t            *ConfigurableExpander = agNULL;
2248   bit32                   dupConfigSASAddr = agFALSE;
2249   bit32                   configSASAddressHi;
2250   bit32                   configSASAddressLo;
2251   bit32                   SAS2SAS11Check = agFALSE;
2252   dmIntRoot_t             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
2253   dmIntContext_t          *dmAllShared  = (dmIntContext_t *)&dmIntRoot->dmAllShared;
2254
2255   
2256   DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: start\n"));
2257   DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
2258   DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); 
2259         
2260   DM_ASSERT(dmRoot, "(dmDownStreamDiscover2ExpanderPhy) dmRoot NULL");
2261   DM_ASSERT(onePortContext, "(dmDownStreamDiscover2ExpanderPhy) pPort NULL");
2262   DM_ASSERT(oneExpander, "(dmDownStreamDiscover2ExpanderPhy) pExpander NULL");
2263   DM_ASSERT(pDiscoverResp, "(dmDownStreamDiscover2ExpanderPhy) pDiscoverResp NULL");
2264
2265   DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: onePortContxt=%p  oneExpander=%p  oneDeviceData=%p\n", onePortContext, oneExpander, oneExpander->dmDevice));
2266   
2267   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
2268   {
2269     DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: invalid port or aborted discovery!!!\n"));  
2270     return;
2271   }
2272
2273   if (oneExpander != oneExpander->dmDevice->dmExpander)
2274   {
2275     DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: wrong!!!\n"));
2276   }
2277                       
2278            
2279   /* (1) Find the device structure of the expander */
2280   oneDeviceData = oneExpander->dmDevice;
2281   
2282   DM_ASSERT(oneDeviceData, "(dmDownStreamDiscover2ExpanderPhy) pDevice NULL");
2283
2284   /* for debugging */
2285   DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Phy #%d of SAS %08x-%08x\n",
2286            oneExpander->discoveringPhyId,
2287            oneDeviceData->SASAddressID.sasAddressHi,
2288            oneDeviceData->SASAddressID.sasAddressLo));
2289   
2290   DM_DBG2(("   Attached device: %s\n",
2291            ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" : 
2292              (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" : 
2293               (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
2294               
2295   
2296   /* for debugging */
2297   if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
2298   {
2299     DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: !!! Incorrect SMP response !!!\n"));
2300     DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
2301     dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover2_t));
2302     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2303     return;
2304   }
2305   
2306   if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
2307   {
2308     DM_DBG2(("   SAS address    : %08x-%08x\n",
2309       SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp), 
2310               SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
2311     DM_DBG2(("   SSP Target     : %d\n", SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
2312     DM_DBG2(("   STP Target     : %d\n", SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
2313     DM_DBG2(("   SMP Target     : %d\n", SAS2_DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
2314     DM_DBG2(("   SATA DEVICE    : %d\n", SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
2315     DM_DBG2(("   SSP Initiator  : %d\n", SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
2316     DM_DBG2(("   STP Initiator  : %d\n", SAS2_DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
2317     DM_DBG2(("   SMP Initiator  : %d\n", SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
2318     DM_DBG2(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
2319     DM_DBG2(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
2320     
2321   }
2322
2323     /* saving routing attribute for non self-configuring expanders */
2324   oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
2325  
2326   
2327   oneExpander->discoverSMPAllowed = agTRUE;
2328   
2329   /* If a device is attached */
2330   if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) !=  SAS_NO_DEVICE)
2331   {
2332     /* Setup sasIdentify for the attached device */
2333     sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
2334     sasIdentify.deviceType_addressFrameType = pDiscoverResp->attachedDeviceTypeReason & 0x70;
2335     sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
2336     sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
2337     *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
2338     *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
2339
2340     /* incremental discovery */       
2341     dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
2342     dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
2343     dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
2344     dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
2345         
2346     attachedSasHi = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
2347     attachedSasLo = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
2348
2349     /* If it's a direct routing */
2350     if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_DIRECT)
2351     {
2352       /* If the attached device is an expander */
2353       if ( (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
2354           || (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) )
2355
2356       {
2357         DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error direct routing can't connect to expander!!!\n"));
2358         onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2359            = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2360         onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2361           = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2362         onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2363
2364         DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
2365                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
2366                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2367                   onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2368         dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2369         
2370         return;
2371       }
2372     }
2373     
2374     /* If the expander's attached device is not myself */
2375     if ( (attachedSasHi != onePortContext->sasLocalAddressHi)
2376          || (attachedSasLo != onePortContext->sasLocalAddressLo) ) 
2377     {
2378       /* Find the attached device from discovered list */
2379       AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
2380       /* If the device has not been discovered before */
2381       if ( AttachedDevice == agNULL) //11
2382       {
2383         //qqqqqq
2384         if (0)     
2385         {
2386               DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n"));
2387           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2388             = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2389           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2390             = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2391           onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2392           DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
2393                     onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
2394                     onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2395                     onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2396           /* discovery done */
2397           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2398         }
2399         else 
2400         {
2401           /* Add the device */
2402           /* read minimum rate from the configuration 
2403              onePortContext->LinkRate is SPC's local link rate
2404           */
2405           connectionRate = MIN(onePortContext->LinkRate, SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pDiscoverResp)); 
2406           DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: link rate 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo)));
2407           DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: negotiatedPhyLinkRate 0x%x\n", SAS2_DISCRSP_GET_LINKRATE(pDiscoverResp)));
2408           DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: connectionRate 0x%x\n", connectionRate));
2409
2410           if (SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp))    
2411           {
2412             if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
2413             {
2414               AttachedDevice = dmPortSASDeviceAdd(
2415                                                  dmRoot,
2416                                                  onePortContext,
2417                                                  sasIdentify,
2418                                                  agFALSE,
2419                                                  connectionRate,
2420                                                  dmAllShared->itNexusTimeout,
2421                                                  0,
2422                                                  STP_DEVICE_TYPE,
2423                                                  oneDeviceData,
2424                                                  oneExpander,
2425                                                  pDiscoverResp->phyIdentifier
2426                                                  );
2427             }
2428             else
2429             {
2430               /* incremental discovery */
2431               AttachedDevice = dmFindRegNValid(
2432                                                dmRoot,
2433                                                onePortContext,
2434                                                &dmSASSubID
2435                                                );
2436               /* not registered and not valid; add this*/                                   
2437               if (AttachedDevice == agNULL)
2438               {
2439                 AttachedDevice = dmPortSASDeviceAdd(
2440                                                    dmRoot,
2441                                                    onePortContext,
2442                                                    sasIdentify,
2443                                                    agFALSE,
2444                                                    connectionRate,
2445                                                    dmAllShared->itNexusTimeout,
2446                                                    0,
2447                                                    STP_DEVICE_TYPE,
2448                                                    oneDeviceData,
2449                                                    oneExpander,
2450                                                    pDiscoverResp->phyIdentifier
2451                                                    );
2452               }
2453             }
2454           }
2455           else
2456           {
2457             if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
2458             {            
2459               AttachedDevice = dmPortSASDeviceAdd(
2460                                                  dmRoot,
2461                                                  onePortContext,
2462                                                  sasIdentify,
2463                                                  agFALSE,
2464                                                  connectionRate,
2465                                                  dmAllShared->itNexusTimeout,
2466                                                  0,
2467                                                  SAS_DEVICE_TYPE,
2468                                                  oneDeviceData,
2469                                                  oneExpander,
2470                                                  pDiscoverResp->phyIdentifier
2471                                                  );
2472             }
2473             else
2474             {
2475               /* incremental discovery */
2476               AttachedDevice = dmFindRegNValid(
2477                                                dmRoot,
2478                                                onePortContext,
2479                                                &dmSASSubID
2480                                                );
2481               /* not registered and not valid; add this*/
2482               if (AttachedDevice == agNULL)
2483               {
2484                 AttachedDevice = dmPortSASDeviceAdd(
2485                                                     dmRoot,
2486                                                     onePortContext,
2487                                                     sasIdentify,
2488                                                     agFALSE,
2489                                                     connectionRate,
2490                                                     dmAllShared->itNexusTimeout,
2491                                                     0,
2492                                                     SAS_DEVICE_TYPE,
2493                                                     oneDeviceData,
2494                                                     oneExpander,
2495                                                     pDiscoverResp->phyIdentifier
2496                                                     );
2497               }                    
2498             }                                                    
2499           }
2500           DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: newDevice  pDevice=%p\n", AttachedDevice));
2501           /* If the device is added successfully */    
2502           if ( AttachedDevice != agNULL)
2503           {
2504             if ( SA_IDFRM_IS_SSP_TARGET(&sasIdentify) 
2505                  || SA_IDFRM_IS_SMP_TARGET(&sasIdentify)
2506                  || SA_IDFRM_IS_SSP_INITIATOR(&sasIdentify)
2507                  || SA_IDFRM_IS_SMP_INITIATOR(&sasIdentify) )
2508             {
2509               DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Report a new SAS device !!\n"));  
2510                
2511             }
2512             else
2513             {
2514               if ( SA_IDFRM_IS_STP_TARGET(&sasIdentify) || 
2515                    SA_IDFRM_IS_SATA_DEVICE(&sasIdentify) )
2516               {
2517                 
2518                 DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found an STP or SATA device.\n"));
2519               }
2520               else
2521               {
2522                 DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found Other type of device.\n"));
2523               }
2524             }
2525             
2526             /* LP2006-05-26 added upstream device to the newly found device */
2527             AttachedDevice->dmExpander = oneExpander;
2528             DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: AttachedDevice %p did %d\n", AttachedDevice, AttachedDevice->id));
2529             DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: Attached oneExpander %p did %d\n",  AttachedDevice->dmExpander,  AttachedDevice->dmExpander->id));
2530             
2531             DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
2532             DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: oneExpander %p did %d\n",  oneDeviceData->dmExpander,  oneDeviceData->dmExpander->id));
2533                                                                                                  
2534             /* If the phy has table routing attribute */
2535             if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
2536             {
2537               /* If the attached device is a fan out expander */
2538               if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
2539               {
2540                 /* TODO: discovery error, callback */
2541                 DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error two table routing phys are connected!!!\n"));
2542                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2543                   = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2544                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2545                   = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2546                 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2547                 DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
2548                           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
2549                           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2550                           onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2551                 /* discovery done */
2552                 dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2553               }
2554               else if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) 
2555               {
2556                 /* Allocate an expander data structure */
2557                 AttachedExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, AttachedDevice);
2558                  
2559                 DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found a EDGE exp device.%p\n", AttachedExpander));
2560                 /* If allocate successfully */
2561                 if ( AttachedExpander != agNULL)
2562                 {
2563                   /* set up downstream information on configurable expander */
2564  
2565                   dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId); 
2566              
2567                   /* Setup upstream information */
2568                   dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
2569 //qqqqq           
2570                   AttachedExpander->hasUpStreamDevice = agTRUE;
2571                   AttachedExpander->upStreamSASAddressHi 
2572                     = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2573                   AttachedExpander->upStreamSASAddressLo
2574                     = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2575                   AttachedExpander->dmUpStreamExpander = oneExpander;
2576                   /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */
2577                   dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
2578                 }       
2579                 /* If failed to allocate */
2580                 else
2581                 {
2582                   DM_DBG1(("dmDownStreamDiscover2ExpanderPhy, Failed to allocate expander data structure!!!\n"));
2583                   /*  discovery done */
2584                   dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2585                 }
2586               } 
2587             }
2588             //qqqqq
2589             else if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE &&
2590                        (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE ||
2591                         SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)                       
2592                     )
2593             {
2594               /* Allocate an expander data structure */
2595               AttachedExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, AttachedDevice);
2596                  
2597               DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found a EDGE/FANOUT exp device.%p\n", AttachedExpander));
2598               /* If allocate successfully */
2599               if ( AttachedExpander != agNULL)
2600               {
2601                 /* set up downstream information on configurable expander */
2602                 dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId); 
2603                 
2604                 /* Setup upstream information */
2605                 dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
2606                 AttachedExpander->hasUpStreamDevice = agTRUE;
2607                 AttachedExpander->upStreamSASAddressHi 
2608                   = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2609                 AttachedExpander->upStreamSASAddressLo
2610                   = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2611                 AttachedExpander->dmUpStreamExpander = oneExpander;
2612                 /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */
2613                 dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
2614               } 
2615               /* If failed to allocate */
2616               else
2617               {
2618                 DM_DBG1(("dmDownStreamDiscover2ExpanderPhy, Failed to allocate expander data structure (2)!!!\n"));
2619                 /*  discovery done */
2620                 dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2621               }
2622                 
2623                 
2624             }
2625             /* If status is still DISCOVERY_DOWN_STREAM */        
2626             if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM &&
2627                  onePortContext->discovery.ConfiguresOthers == agFALSE)
2628             {
2629               DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st before\n"));
2630               dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); 
2631               UpStreamExpander = oneExpander->dmUpStreamExpander;
2632               ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
2633               configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
2634               configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); 
2635               if (ConfigurableExpander)
2636               { 
2637                 if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi 
2638                       == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
2639                      (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo 
2640                       == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
2641                    )
2642                 { /* directly attached between oneExpander and ConfigurableExpander */       
2643                   DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st before loc 1\n"));
2644                   configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi;
2645                   configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo; 
2646                 }
2647                 else
2648                 {
2649                   DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st before loc 2\n"));
2650                   configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
2651                   configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); 
2652                 }                                             
2653               } /* if !ConfigurableExpander */
2654               dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, 
2655                                                             ConfigurableExpander,   
2656                                                             configSASAddressHi,
2657                                                             configSASAddressLo
2658                                                             );
2659               
2660                                                         
2661               if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
2662               {
2663                 DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st q123\n"));
2664                 UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
2665                 ConfigurableExpander->currentDownStreamPhyIndex = 
2666                         dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
2667                 ConfigurableExpander->dmReturnginExpander = oneExpander;
2668                 dmRoutingEntryAdd(dmRoot,
2669                                   ConfigurableExpander, 
2670                                   ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
2671                                   configSASAddressHi,
2672                                   configSASAddressLo
2673                                  );
2674               }                       
2675             }
2676           } 
2677           /*  If fail to add the device */    
2678           else
2679           {
2680             DM_DBG1(("dmDownStreamDiscover2ExpanderPhy, Failed to add a device!!!\n"));
2681             /*  discovery done */
2682             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2683           }
2684         }
2685       }
2686       /* If the device has been discovered before */
2687       else /* discovered before */
2688       {
2689         /* If the phy has subtractive routing attribute */
2690         if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
2691         {
2692           /* If the expander doesn't have up stream device */
2693           if ( oneExpander->hasUpStreamDevice == agFALSE)
2694           {
2695             /* TODO: discovery error, callback */
2696             DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error loop, or end device connects to two expanders!!!\n"));
2697             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2698               = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2699             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2700               = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2701             onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2702             DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
2703                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
2704                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2705                       onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2706             /* discovery done */
2707             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2708           }
2709           /* If the expander has up stream device */
2710           else
2711           {
2712             
2713 //qqqqq
2714             /* If sas address doesn't match */
2715             if ( (oneExpander->upStreamSASAddressHi != attachedSasHi)
2716                  || (oneExpander->upStreamSASAddressLo != attachedSasLo) )
2717             {
2718               /* TODO: discovery error, callback */
2719               DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** two subtractive phys!!! Allowed in SAS2!!!\n"));
2720               onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2721                 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2722               onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2723                 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2724               onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2725               onePortContext->discovery.DeferredError = agTRUE;
2726      
2727             }
2728           }
2729         }
2730         /* If the phy has table routing attribute */
2731         else if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
2732         {
2733           /* If the attached device is a fan out expander */
2734           if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
2735           {
2736             /* (2.3.3.2.1.1) TODO: discovery error, callback */
2737             DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error fan out expander to routing table phy!!!\n"));
2738             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2739               = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2740             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2741               = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2742             onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2743             DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
2744                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
2745                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2746                       onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2747             /* discovery done */
2748             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2749           }
2750           /* If the attached device is an edge expander */
2751           else if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) 
2752           {
2753             /* Setup up stream inform */
2754             AttachedExpander = AttachedDevice->dmExpander;
2755             DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found edge expander=%p\n", AttachedExpander));
2756             //hhhhhh
2757             /* If the attached expander has up stream device */
2758             if ( AttachedExpander->hasUpStreamDevice == agTRUE)
2759             {
2760               /* compare the sas address */
2761               if ( (AttachedExpander->upStreamSASAddressHi
2762                     != DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
2763                    || (AttachedExpander->upStreamSASAddressLo
2764                        != DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)))
2765               {
2766                 if (AttachedExpander->TTTSupported && oneExpander->TTTSupported)
2767                 {
2768                   /*
2769                      needs further error checking 
2770                      UpstreamExpanderOfAttachedExpander = AttachedExpander->UpStreamExpander
2771                      for (i=0;i<DM_MAX_EXPANDER_PHYS;i++)
2772                      {
2773                        if (UpstreamExpanderOfAttachedExpander->downStreamPhys[i] != 0 &&
2774                      } 
2775                   */
2776                   SAS2SAS11Check = dmSAS2SAS11ErrorCheck(dmRoot, onePortContext, AttachedExpander->dmUpStreamExpander, AttachedExpander, oneExpander);                  
2777                   if (SAS2SAS11Check == agTRUE)
2778                   {
2779                     
2780                     DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error SAS2 and SAS1.1!!!\n"));                    
2781                     onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2782                       = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);                    
2783                     onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2784                       = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);                    
2785                     onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;                    
2786                     DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
2787                               onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
2788                               onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2789                               onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));                    
2790                     /* discovery done */                    
2791                     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2792                   }
2793                   else
2794                   {
2795                     DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: Allowed Table to Table (1)\n"));
2796                     /* move on to the next phys but should be not proceed after oneExpander */
2797                     oneExpander->UndoDueToTTTSupported = agTRUE;
2798                     onePortContext->discovery.DeferredError = agFALSE;
2799                   }
2800                 }
2801                 else
2802                 {
2803                   /* TODO: discovery error, callback */
2804                   DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error two table routing phys connected (1)!!!\n"));
2805                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2806                     = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2807                   onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2808                     = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2809                   onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2810                   DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
2811                             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
2812                             onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2813                             onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2814                   /* discovery done */
2815                   dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2816                 }
2817               }
2818               else
2819               {
2820                 DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Add edge expander=%p\n", AttachedExpander));
2821                 /* set up downstream information on configurable expander */
2822        
2823                 dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId); 
2824                 /* haha */
2825                 dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
2826                 /* Add the pAttachedExpander to discovering list */
2827                 dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
2828               }
2829             }
2830             /* If the attached expander doesn't have up stream device */
2831             else
2832             {
2833               if (AttachedExpander->TTTSupported && oneExpander->TTTSupported)
2834               {
2835                 DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: Allowed Table to Table (2)\n"));
2836                 /* move on to the next phys but should be not proceed after oneExpander */
2837                 oneExpander->UndoDueToTTTSupported = agTRUE;
2838                 onePortContext->discovery.DeferredError = agFALSE;
2839               }
2840               else
2841               {
2842                 /* TODO: discovery error, callback */
2843                 DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error two table routing phys connected (2)!!!\n"));
2844                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2845                   = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2846                 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2847                   = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2848                 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2849                 DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", 
2850                           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, 
2851                           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2852                           onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2853                 /* discovery done */
2854                 dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2855               }
2856             }
2857           }  
2858         } /* for else if (SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE) */
2859           
2860         /* do this regradless of sub or table */
2861         /* If status is still DISCOVERY_DOWN_STREAM */            
2862         if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM &&
2863              onePortContext->discovery.ConfiguresOthers == agFALSE)
2864         {
2865           DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd before\n"));
2866           dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); 
2867
2868           UpStreamExpander = oneExpander->dmUpStreamExpander;
2869           ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
2870           configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
2871           configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); 
2872           if (ConfigurableExpander)
2873           { 
2874             if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi 
2875                  == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
2876                  (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo 
2877                    == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
2878                )
2879             { /* directly attached between oneExpander and ConfigurableExpander */       
2880               DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd before loc 1\n"));
2881               configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi;
2882               configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo; 
2883             }
2884             else
2885             {
2886               DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd before loc 2\n"));
2887               configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
2888               configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); 
2889             }                                             
2890           } /* if !ConfigurableExpander */
2891           dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, 
2892                                                         ConfigurableExpander,   
2893                                                         configSASAddressHi,
2894                                                         configSASAddressLo
2895                                                         );
2896             
2897           if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
2898           {
2899             DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd q123 \n"));
2900             UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
2901             ConfigurableExpander->currentDownStreamPhyIndex = 
2902                         dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
2903             ConfigurableExpander->dmReturnginExpander = oneExpander;
2904             dmRoutingEntryAdd(dmRoot,
2905                               ConfigurableExpander, 
2906                               ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
2907                               configSASAddressHi,
2908                               configSASAddressLo
2909                              );
2910           }                                        
2911         } /* if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) */          
2912         /* incremental discovery */
2913         if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START)
2914         {
2915           connectionRate = MIN(onePortContext->LinkRate, SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pDiscoverResp)); 
2916
2917           if (SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp))    
2918           {
2919             DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: incremental SATA_STP\n"));
2920
2921             dmPortSASDeviceAdd(
2922                               dmRoot,
2923                               onePortContext,
2924                               sasIdentify,
2925                               agFALSE,
2926                               connectionRate,
2927                               dmAllShared->itNexusTimeout,
2928                               0,
2929                               STP_DEVICE_TYPE,
2930                               oneDeviceData,
2931                               oneExpander,
2932                               pDiscoverResp->phyIdentifier
2933                               );
2934           }
2935           else
2936           {
2937             DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: incremental SAS\n"));
2938
2939              dmPortSASDeviceAdd(
2940                                dmRoot,
2941                                onePortContext,
2942                                sasIdentify,
2943                                agFALSE,
2944                                connectionRate,
2945                                dmAllShared->itNexusTimeout,
2946                                0,
2947                                SAS_DEVICE_TYPE,
2948                                oneDeviceData,
2949                                oneExpander,
2950                                pDiscoverResp->phyIdentifier
2951                                );
2952         
2953           }
2954         }
2955         
2956         
2957       }/* else; existing devce */
2958     } /* not attached to myself */
2959     /* If the attached device is myself */
2960     else
2961     {
2962       DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found Self\n"));
2963       DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 3rd before\n"));
2964       dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); 
2965
2966       if (onePortContext->discovery.ConfiguresOthers == agFALSE)
2967       {   
2968         UpStreamExpander = oneExpander->dmUpStreamExpander;
2969         ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
2970         dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, 
2971                                                       ConfigurableExpander,   
2972                                                       onePortContext->sasLocalAddressHi,
2973                                                       onePortContext->sasLocalAddressLo
2974                                                       );
2975       
2976         if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
2977         {
2978           DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 3rd q123 Setup routing table\n"));
2979           UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
2980           ConfigurableExpander->currentDownStreamPhyIndex = 
2981                           dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
2982           ConfigurableExpander->dmReturnginExpander = oneExpander;
2983           dmRoutingEntryAdd(dmRoot,
2984                             ConfigurableExpander, 
2985                             ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
2986                             onePortContext->sasLocalAddressHi,
2987                             onePortContext->sasLocalAddressLo
2988                            );
2989         }
2990       } 
2991     }
2992   }
2993   /* If no device is attached */
2994   else
2995   {
2996   }
2997
2998
2999   /* Increment the discovering phy id */
3000   oneExpander->discoveringPhyId ++;
3001   
3002   /* If the discovery status is DISCOVERY_DOWN_STREAM */
3003   if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
3004   {
3005     /* If not the last phy */  
3006     if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
3007     {
3008       DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: More Phys to discover\n"));
3009       /* continue discovery for the next phy */
3010       dmDiscoverSend(dmRoot, oneDeviceData);
3011     }
3012     /* If the last phy */
3013     else
3014     {
3015       DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: No More Phys\n"));
3016      
3017       /* for MCN */
3018       dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);  
3019       ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
3020       if (oneExpander->UndoDueToTTTSupported == agTRUE && ConfigurableExpander != agNULL)
3021 //      if (oneExpander->UndoDueToTTTSupported == agTRUE)
3022       {
3023         DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Not sure!!!\n"));
3024         dmDiscoveringUndoAdd(dmRoot, onePortContext, oneExpander);       
3025         oneExpander->UndoDueToTTTSupported = agFALSE;
3026       }
3027       
3028       /* remove the expander from the discovering list */
3029       dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3030       /* continue downstream discovering */
3031       dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3032     }  
3033   }
3034   else
3035   {
3036     DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));  
3037   }  
3038   DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
3039  
3040   return;
3041 }                            
3042
3043
3044 osGLOBAL void
3045 dmDiscoveringUndoAdd(
3046                      dmRoot_t                 *dmRoot,
3047                      dmIntPortContext_t       *onePortContext,
3048                      dmExpander_t             *oneExpander
3049                     )
3050 {
3051   dmIntRoot_t        *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3052   dmIntContext_t     *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3053   dmList_t           *ExpanderList;
3054   dmExpander_t       *tempExpander;
3055   dmIntPortContext_t *tmpOnePortContext = onePortContext;
3056   
3057   DM_DBG2(("dmDiscoveringUndoAdd: start\n"));
3058   if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
3059   {
3060     DM_DBG2(("dmDiscoveringUndoAdd: empty discoveringExpanderList\n"));
3061     return;
3062   }
3063
3064 //  DM_DBG2(("dmDiscoveringUndoAdd: before\n"));
3065 //  dmDumpAllExp(dmRoot, onePortContext, oneExpander);
3066
3067   ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
3068   while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
3069   {
3070     tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
3071     if ( tempExpander == agNULL)
3072     {
3073       DM_DBG1(("dmDiscoveringUndoAdd: tempExpander is NULL!!!\n"));    
3074       return;    
3075     }
3076     if (tempExpander->dmUpStreamExpander == oneExpander)
3077     {
3078       DM_DBG2(("dmDiscoveringUndoAdd: match!!! expander id %d\n", tempExpander->id));
3079       DM_DBG2(("dmDiscoveringUndoAdd: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
3080       DM_DBG2(("dmDiscoveringUndoAdd: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
3081       tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
3082       DMLIST_DEQUEUE_THIS(&(tempExpander->linkNode));
3083 //      DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->freeExpanderList));
3084       DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->mainExpanderList));
3085       tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
3086       ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;      
3087     }
3088     if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
3089     {
3090       DM_DBG2(("dmDiscoveringUndoAdd: hitting break\n"));
3091       break;
3092     }
3093     ExpanderList = ExpanderList->flink;
3094   }
3095   
3096 //  DM_DBG2(("dmDiscoveringUndoAdd: after\n"));
3097 //  dmDumpAllExp(dmRoot, onePortContext, oneExpander);
3098   return;
3099 }                            
3100
3101 osGLOBAL void
3102 dmHandleZoneViolation(
3103                       dmRoot_t              *dmRoot,
3104                       agsaRoot_t            *agRoot,
3105                       agsaIORequest_t       *agIORequest,
3106                       dmDeviceData_t        *oneDeviceData,
3107                       dmSMPFrameHeader_t    *frameHeader,
3108                       agsaFrameHandle_t     frameHandle
3109                      )
3110 {
3111   dmIntPortContext_t           *onePortContext = agNULL;
3112   dmExpander_t                 *oneExpander = agNULL;
3113
3114   DM_DBG1(("dmHandleZoneViolation: start\n"));  
3115   DM_DBG1(("dmHandleZoneViolation: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3116   DM_DBG1(("dmHandleZoneViolation: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3117   onePortContext = oneDeviceData->dmPortContext;
3118   oneExpander = oneDeviceData->dmExpander;
3119   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
3120   {
3121     DM_DBG1(("dmHandleZoneViolation: invalid port or aborted discovery!!!\n"));
3122     return;
3123   }
3124   /* for MCN */
3125   dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
3126   /* remove the expander from the discovering list */
3127   dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3128   if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3129   {
3130     /* continue upstream discovering */
3131     dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3132   }
3133   else /* DISCOVERY_DOWN_STREAM or DISCOVERY_CONFIG_ROUTING */
3134   {
3135     /* continue downstream discovering */
3136     dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3137   }
3138   return;
3139 }
3140
3141
3142 osGLOBAL void
3143 dmUpStreamDiscoverExpanderPhySkip(
3144                                    dmRoot_t              *dmRoot,
3145                                    dmIntPortContext_t    *onePortContext,
3146                                    dmExpander_t          *oneExpander
3147                                    )
3148
3149 {
3150   dmDeviceData_t          *oneDeviceData;
3151   DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: start\n"));
3152   
3153   oneDeviceData = oneExpander->dmDevice;
3154   DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3155   DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3156   
3157   oneExpander->discoveringPhyId++;
3158   if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3159   {
3160     if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
3161     {
3162       DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: More Phys to discover\n"));
3163       /* continue discovery for the next phy */  
3164       dmDiscoverSend(dmRoot, oneDeviceData);
3165     }
3166     else
3167     {
3168       DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: No More Phys\n"));
3169
3170       /* for MCN */
3171       dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);  
3172       /* remove the expander from the discovering list */
3173       dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3174       /* continue upstream discovering */  
3175       dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3176     }
3177   }
3178   else
3179   {
3180     DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));  
3181    
3182   }
3183    
3184   DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
3185   
3186   return;
3187 }                                       
3188
3189
3190 osGLOBAL void
3191 dmUpStreamDiscover2ExpanderPhySkip(
3192                                    dmRoot_t              *dmRoot,
3193                                    dmIntPortContext_t    *onePortContext,
3194                                    dmExpander_t          *oneExpander
3195                                    )
3196 {
3197   dmDeviceData_t          *oneDeviceData;
3198   
3199   DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: start\n"));
3200   oneDeviceData = oneExpander->dmDevice;
3201   
3202   oneExpander->discoveringPhyId++;
3203   if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3204   {
3205     if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
3206     {
3207       DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: DISCOVERY_UP_STREAM find more ...\n"));
3208       /* continue discovery for the next phy */  
3209       dmDiscoverSend(dmRoot, oneDeviceData);
3210     }
3211     else
3212     {
3213       DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: DISCOVERY_UP_STREAM last phy continue upstream..\n"));
3214
3215       /* for MCN */
3216       dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);  
3217       /* remove the expander from the discovering list */
3218       dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3219       /* continue upstream discovering */  
3220       dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3221     }
3222   }
3223   else
3224   {
3225     DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));     
3226   }
3227    
3228   DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
3229   
3230
3231   return;
3232 }                            
3233
3234 osGLOBAL void
3235 dmDownStreamDiscoverExpanderPhySkip(
3236                                      dmRoot_t              *dmRoot,
3237                                      dmIntPortContext_t    *onePortContext,
3238                                      dmExpander_t          *oneExpander
3239                                      )
3240 {
3241   dmDeviceData_t          *oneDeviceData;
3242   DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: start\n"));
3243   
3244   oneDeviceData = oneExpander->dmDevice;
3245   DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3246   DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3247
3248   /* Increment the discovering phy id */
3249   oneExpander->discoveringPhyId ++;
3250   
3251   /* If the discovery status is DISCOVERY_DOWN_STREAM */
3252   if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
3253   {
3254     /* If not the last phy */  
3255     if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
3256     {
3257       DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: More Phys to discover\n"));
3258       /* continue discovery for the next phy */
3259       dmDiscoverSend(dmRoot, oneDeviceData);
3260     }
3261     /* If the last phy */
3262     else
3263     {
3264       DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: No More Phys\n"));
3265
3266       /* for MCN */
3267       dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);  
3268       /* remove the expander from the discovering list */
3269       dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3270       /* continue downstream discovering */
3271       dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3272     }  
3273   }
3274   else
3275   {
3276     DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));  
3277   }  
3278   DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
3279   
3280   
3281   return;
3282 }                                       
3283
3284 osGLOBAL void
3285 dmDownStreamDiscover2ExpanderPhySkip(
3286                                      dmRoot_t              *dmRoot,
3287                                      dmIntPortContext_t    *onePortContext,
3288                                      dmExpander_t          *oneExpander
3289                                      )
3290 {
3291   dmDeviceData_t          *oneDeviceData;
3292   
3293   DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: start\n"));
3294   
3295   oneDeviceData = oneExpander->dmDevice;
3296   /* Increment the discovering phy id */
3297   oneExpander->discoveringPhyId ++;
3298   
3299   /* If the discovery status is DISCOVERY_DOWN_STREAM */
3300   if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
3301   {
3302     /* If not the last phy */  
3303     if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
3304     {
3305       DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: More Phys to discover\n"));
3306       /* continue discovery for the next phy */
3307       dmDiscoverSend(dmRoot, oneDeviceData);
3308     }
3309     /* If the last phy */
3310     else
3311     {
3312       DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: No More Phys\n"));
3313
3314       /* for MCN */
3315       dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);  
3316       /* remove the expander from the discovering list */
3317       dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3318       /* continue downstream discovering */
3319       dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3320     }  
3321   }
3322   else
3323   {
3324     DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));  
3325   }  
3326   DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
3327   return;
3328 }                            
3329
3330 osGLOBAL void
3331 dmExpanderUpStreamPhyAdd(
3332                          dmRoot_t              *dmRoot,
3333                          dmExpander_t          *oneExpander,
3334                          bit8                  phyId
3335                          )
3336 {
3337   bit32   i;
3338   bit32   hasSet = agFALSE;
3339
3340   DM_DBG3(("dmExpanderUpStreamPhyAdd: start, phyid %d\n", phyId));
3341   DM_DBG3(("dmExpanderUpStreamPhyAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
3342   DM_DBG3(("dmExpanderUpStreamPhyAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
3343   DM_DBG3(("dmExpanderUpStreamPhyAdd: phyid %d  numOfUpStreamPhys %d\n", phyId, oneExpander->numOfUpStreamPhys));
3344
3345   for ( i = 0; i < oneExpander->numOfUpStreamPhys; i ++ )
3346   {
3347     if ( oneExpander->upStreamPhys[i] == phyId )
3348     {
3349       hasSet = agTRUE;
3350       break;
3351     }
3352   }
3353   
3354   if ( hasSet == agFALSE )
3355   {
3356     oneExpander->upStreamPhys[oneExpander->numOfUpStreamPhys ++] = phyId;    
3357   }
3358
3359   DM_DBG3(("dmExpanderUpStreamPhyAdd: AFTER phyid %d  numOfUpStreamPhys %d\n", phyId, oneExpander->numOfUpStreamPhys));
3360
3361   /* for debugging */
3362   for ( i = 0; i < oneExpander->numOfUpStreamPhys; i ++ )
3363   {
3364     DM_DBG3(("dmExpanderUpStreamPhyAdd: index %d upstream[index] %d\n", i, oneExpander->upStreamPhys[i]));
3365   }
3366   return;
3367 }                                       
3368
3369 osGLOBAL void
3370 dmExpanderDownStreamPhyAdd(
3371                            dmRoot_t              *dmRoot,
3372                            dmExpander_t          *oneExpander,
3373                            bit8                  phyId
3374                           )
3375 {
3376   bit32   i;
3377   bit32   hasSet = agFALSE;
3378
3379   DM_DBG3(("dmExpanderDownStreamPhyAdd: start, phyid %d\n", phyId));
3380   DM_DBG3(("dmExpanderDownStreamPhyAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
3381   DM_DBG3(("dmExpanderDownStreamPhyAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
3382   DM_DBG3(("dmExpanderDownStreamPhyAdd: phyid %d  numOfDownStreamPhys %d\n", phyId, oneExpander->numOfDownStreamPhys));
3383
3384   for ( i = 0; i < oneExpander->numOfDownStreamPhys; i ++ )
3385   {
3386     if ( oneExpander->downStreamPhys[i] == phyId )
3387     {
3388       hasSet = agTRUE;
3389       break;
3390     }
3391   }
3392   
3393   if ( hasSet == agFALSE )
3394   {
3395     oneExpander->downStreamPhys[oneExpander->numOfDownStreamPhys ++] = phyId;    
3396   }
3397
3398   DM_DBG3(("dmExpanderDownStreamPhyAdd: AFTER phyid %d  numOfDownStreamPhys %d\n", phyId, oneExpander->numOfDownStreamPhys));
3399
3400   /* for debugging */
3401   for ( i = 0; i < oneExpander->numOfDownStreamPhys; i ++ )
3402   {
3403      DM_DBG3(("dmExpanderDownStreamPhyAdd: index %d downstream[index] %d\n", i, oneExpander->downStreamPhys[i]));
3404   }
3405   return;
3406 }                                       
3407
3408 osGLOBAL void
3409 dmDiscoveryReportMCN(
3410                     dmRoot_t                 *dmRoot,
3411                     dmIntPortContext_t       *onePortContext
3412                    )
3413 {
3414   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3415   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3416   dmDeviceData_t    *oneDeviceData = agNULL;
3417   dmList_t          *DeviceListList;
3418   bit16             extension = 0;
3419   dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
3420     
3421   DM_DBG2(("dmDiscoveryReportMCN: start\n"));
3422
3423 /*
3424   if full disocvery, report all devices using MCN
3425   if incremental discovery, 
3426   1. compare MCN and PrevMCN
3427   2. report the changed ones; report MCN
3428   3. set PrevMCN to MCN
3429      PrevMCN = MCN
3430 */
3431
3432   DeviceListList = dmAllShared->MainDeviceList.flink;
3433   while (DeviceListList != &(dmAllShared->MainDeviceList))
3434   {
3435     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3436     if ( oneDeviceData == agNULL)
3437     {
3438       DM_DBG1(("dmDiscoveryReportMCN: oneDeviceData is NULL!!!\n"));
3439       return;
3440     }        
3441     DM_DBG3(("dmDiscoveryReportMCN: loop did %d\n", oneDeviceData->id));
3442     if (oneDeviceData->dmPortContext == onePortContext)
3443     {
3444       DM_DBG2(("dmDiscoveryReportMCN: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
3445       oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));         
3446       DM_DBG2(("dmDiscoveryReportMCN: MCN 0x%08x PrevMCN 0x%08x\n", oneDeviceData->MCN, oneDeviceData->PrevMCN));
3447       
3448       if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
3449       {
3450         DM_DBG2(("dmDiscoveryReportMCN: FULL_START\n"));
3451       }
3452       else
3453       {
3454         DM_DBG2(("dmDiscoveryReportMCN: INCREMENTAL_START\n"));
3455       }
3456       /*
3457         if MCN is 0, the device is removed 
3458       */
3459       if (oneDeviceData->MCN != oneDeviceData->PrevMCN && oneDeviceData->MCN != 0)
3460       {
3461         DM_DBG2(("dmDiscoveryReportMCN: reporting \n"));
3462         extension = oneDeviceData->dmDeviceInfo.ext;
3463         /* zero out MCN in extension */
3464         extension = extension & 0x7FF;
3465         /* sets MCN in extension */     
3466         extension = extension | (oneDeviceData->MCN << 11);
3467         DEVINFO_PUT_EXT(&(oneDeviceData->dmDeviceInfo), extension);
3468         DM_DBG5(("dmDiscoveryReportMCN: MCN 0x%08x PrevMCN 0x%08x\n", DEVINFO_GET_EXT_MCN(&(oneDeviceData->dmDeviceInfo)), oneDeviceData->PrevMCN));
3469         if (oneDeviceData->ExpDevice != agNULL)
3470         {
3471           DM_DBG2(("dmDiscoveryReportMCN: attached expander case\n"));
3472           oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
3473           tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, dmDeviceMCNChange);
3474         }
3475         else
3476         {
3477           DM_DBG2(("dmDiscoveryReportMCN: No attached expander case\n"));
3478           tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, dmDeviceMCNChange);
3479         }        
3480         oneDeviceData->PrevMCN = oneDeviceData->MCN;            
3481       }
3482       else
3483       {
3484         DM_DBG2(("dmDiscoveryReportMCN: No change; no reporting \n"));
3485         if (oneDeviceData->MCN == 0)
3486         {
3487           oneDeviceData->PrevMCN = oneDeviceData->MCN;                  
3488         }
3489       }
3490       
3491     }
3492     DeviceListList = DeviceListList->flink;  
3493   }
3494   
3495   return;
3496 }                  
3497
3498 osGLOBAL void
3499 dmDiscoveryDumpMCN(
3500                     dmRoot_t                 *dmRoot,
3501                     dmIntPortContext_t       *onePortContext
3502                    )
3503 {
3504   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3505   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3506   dmDeviceData_t    *oneDeviceData = agNULL;
3507   dmList_t          *DeviceListList;
3508   
3509   DM_DBG3(("dmDiscoveryDumpMCN: start\n"));
3510   
3511   DeviceListList = dmAllShared->MainDeviceList.flink;
3512   while (DeviceListList != &(dmAllShared->MainDeviceList))
3513   {
3514     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3515     if (oneDeviceData == agNULL)
3516     {
3517       DM_DBG1(("dmDiscoveryDumpMCN: oneDeviceData is NULL!!!\n"));
3518       return;   
3519     }
3520     DM_DBG3(("dmDiscoveryDumpMCN: loop did %d\n", oneDeviceData->id));
3521     if (oneDeviceData->dmPortContext == onePortContext)
3522     {
3523       DM_DBG3(("dmDiscoveryDumpMCN: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
3524       oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));         
3525       DM_DBG3(("dmDiscoveryDumpMCN: MCN 0x%08x PrevMCN 0x%08x\n", oneDeviceData->MCN, oneDeviceData->PrevMCN));
3526     }
3527     DeviceListList = DeviceListList->flink;  
3528   }
3529   
3530   return;
3531 }                  
3532
3533 osGLOBAL void
3534 dmDiscoveryResetMCN(
3535                     dmRoot_t                 *dmRoot,
3536                     dmIntPortContext_t       *onePortContext
3537                    )
3538 {
3539   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3540   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3541   dmDeviceData_t    *oneDeviceData = agNULL;
3542   dmList_t          *DeviceListList;
3543   
3544   DM_DBG2(("dmDiscoveryResetMCN: start\n"));
3545   
3546   /* reinitialize the device data belonging to this portcontext */
3547   DeviceListList = dmAllShared->MainDeviceList.flink;
3548   while (DeviceListList != &(dmAllShared->MainDeviceList))
3549   {
3550     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3551     if (oneDeviceData == agNULL)
3552     {
3553       DM_DBG1(("dmDiscoveryResetMCN: oneDeviceData is NULL!!!\n"));
3554       return;   
3555     }
3556     DM_DBG3(("dmDiscoveryResetMCN: loop did %d\n", oneDeviceData->id));
3557     if (oneDeviceData->dmPortContext == onePortContext)
3558     {
3559       if (oneDeviceData->ExpDevice != agNULL)
3560       {
3561         DM_DBG2(("dmDiscoveryResetMCN: resetting oneDeviceData->ExpDevice\n"));
3562         oneDeviceData->ExpDevice = agNULL;
3563       } 
3564       DM_DBG3(("dmDiscoveryResetMCN: resetting MCN and MCNdone\n"));
3565       oneDeviceData->MCN = 0;
3566
3567       oneDeviceData->MCNDone = agFALSE;
3568       DM_DBG2(("dmDiscoveryResetMCN: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
3569       oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));         
3570     }
3571     DeviceListList = DeviceListList->flink;  
3572   }
3573   
3574   return;
3575 }                  
3576
3577
3578 /*
3579 do min(oneDeviceData, found-one) in all upstream and downstream
3580 find ajcanent expanders and mark it done; sees only ajcacent targets
3581 */
3582 osGLOBAL void
3583 dmUpdateAllAdjacent(
3584                     dmRoot_t            *dmRoot,
3585                     dmIntPortContext_t  *onePortContext,
3586                     dmDeviceData_t      *oneDeviceData /* current one */
3587                    )
3588 {
3589   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3590   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3591   dmDeviceData_t    *tmponeDeviceData = agNULL;
3592   dmList_t          *DeviceListList;
3593     
3594   DM_DBG2(("dmUpdateAllAdjacent: start\n"));  
3595   if (oneDeviceData == agNULL)
3596   {
3597     DM_DBG1(("dmUpdateAllAdjacent: oneDeviceData is NULL!!!\n"));
3598     return;      
3599   }    
3600   
3601   oneDeviceData->MCNDone = agTRUE;
3602   
3603   DM_DBG2(("dmUpdateAllAdjacent: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
3604   oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));         
3605
3606  
3607   DeviceListList = dmAllShared->MainDeviceList.flink;
3608   while (DeviceListList != &(dmAllShared->MainDeviceList))
3609   {
3610     tmponeDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3611     if ( tmponeDeviceData == agNULL)
3612     {
3613       DM_DBG1(("dmUpdateAllAdjacent: tmponeDeviceData is NULL!!!\n"));
3614       return;
3615     }
3616     DM_DBG3(("dmUpdateAllAdjacent: loop did %d\n", tmponeDeviceData->id));
3617     if (tmponeDeviceData->dmPortContext == onePortContext && tmponeDeviceData->ExpDevice == oneDeviceData)
3618     {
3619       DM_DBG2(("dmUpdateAllAdjacent: setting MCN DONE\n"));
3620       DM_DBG2(("dmUpdateAllAdjacent: tmponeDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
3621       tmponeDeviceData->SASAddressID.sasAddressHi, tmponeDeviceData->SASAddressID.sasAddressLo));         
3622       tmponeDeviceData->MCNDone = agTRUE;
3623       if (oneDeviceData->directlyAttached == agFALSE)
3624       {
3625         DM_DBG2(("dmUpdateAllAdjacent: tmponeDeviceData MCN 0x%x\n", tmponeDeviceData->MCN));
3626         DM_DBG2(("dmUpdateAllAdjacent: oneDeviceData MCN 0x%x\n", oneDeviceData->MCN));
3627         tmponeDeviceData->MCN = MIN(oneDeviceData->MCN, tmponeDeviceData->MCN);
3628       }
3629     
3630     }
3631     DeviceListList = DeviceListList->flink;  
3632   }
3633   
3634   return;
3635
3636 }                  
3637
3638 osGLOBAL void
3639 dmUpdateMCN(
3640             dmRoot_t            *dmRoot,
3641             dmIntPortContext_t  *onePortContext,
3642             dmDeviceData_t      *AdjacentDeviceData, /* adjacent expander */                
3643             dmDeviceData_t      *oneDeviceData /* current one */
3644            )
3645 {
3646   
3647   DM_DBG2(("dmUpdateMCN: start\n"));  
3648   
3649   if (AdjacentDeviceData == agNULL)
3650   {
3651     DM_DBG1(("dmUpdateMCN: AdjacentDeviceData is NULL!!!\n"));
3652     return;      
3653   }    
3654   
3655   if (oneDeviceData == agNULL)
3656   {
3657     DM_DBG1(("dmUpdateMCN: oneDeviceData is NULL!!!\n"));
3658     return;      
3659   }    
3660   
3661   DM_DBG2(("dmUpdateMCN: Current sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
3662   oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));         
3663   
3664   DM_DBG2(("dmUpdateMCN: AdjacentDeviceData one sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
3665   AdjacentDeviceData->SASAddressID.sasAddressHi, AdjacentDeviceData->SASAddressID.sasAddressLo));         
3666   
3667   if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3668   {   
3669     DM_DBG2(("dmUpdateMCN: DISCOVERY_UP_STREAM\n"));  
3670   }  
3671   
3672   if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
3673   {   
3674     DM_DBG2(("dmUpdateMCN: DISCOVERY_DOWN_STREAM\n"));  
3675   }  
3676   
3677   
3678   /* MCN */
3679
3680   /* directly attached one does not have MCN 
3681      update only adjacent device data
3682   */
3683   
3684   if (oneDeviceData->directlyAttached == agTRUE && AdjacentDeviceData->MCNDone == agFALSE)
3685   {
3686     AdjacentDeviceData->MCN++;
3687     DM_DBG2(("dmUpdateMCN: case 1 oneDeviceData MCN 0x%x\n", oneDeviceData->MCN));
3688     DM_DBG2(("dmUpdateMCN: case 1 AdjacentDeviceData MCN 0x%x\n", AdjacentDeviceData->MCN));
3689   }
3690   else if (AdjacentDeviceData->MCNDone == agFALSE)
3691   {
3692     AdjacentDeviceData->MCN++;
3693     AdjacentDeviceData->MCN = MIN(oneDeviceData->MCN, AdjacentDeviceData->MCN);      
3694     DM_DBG2(("dmUpdateMCN: case 2 oneDeviceData MCN 0x%x\n", oneDeviceData->MCN));
3695     DM_DBG2(("dmUpdateMCN: case 2 AdjacentDeviceData MCN 0x%x\n", AdjacentDeviceData->MCN));
3696   }
3697   
3698         
3699   return;
3700 }
3701 /* go through expander list and device list array ??? */
3702 osGLOBAL dmDeviceData_t *
3703 dmPortSASDeviceFind(
3704                     dmRoot_t            *dmRoot,
3705                     dmIntPortContext_t  *onePortContext,
3706                     bit32               sasAddrLo,
3707                     bit32               sasAddrHi,
3708                     dmDeviceData_t      *CurrentDeviceData /* current expander */                   
3709                     )
3710 {
3711   dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3712   dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3713   dmDeviceData_t            *oneDeviceData, *RetDeviceData=agNULL;
3714   dmList_t                  *DeviceListList;
3715       
3716   DM_DBG3(("dmPortSASDeviceFind: start\n"));  
3717   DM_DBG3(("dmPortSASDeviceFind: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", sasAddrHi, sasAddrLo));         
3718  
3719   DM_ASSERT((agNULL != dmRoot), "");
3720   DM_ASSERT((agNULL != onePortContext), "");
3721
3722   tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
3723   
3724   /* find a device's existence */
3725   DeviceListList = dmAllShared->MainDeviceList.flink;
3726   if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
3727   {
3728     DM_DBG3(("dmPortSASDeviceFind: Full discovery\n"));
3729     while (DeviceListList != &(dmAllShared->MainDeviceList))
3730     {
3731       oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3732       if (oneDeviceData == agNULL)
3733       {
3734         DM_DBG1(("dmPortSASDeviceFind: oneDeviceData is NULL!!!\n"));  
3735         return agNULL;
3736       }      
3737       if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) &&
3738           (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) &&
3739           (oneDeviceData->valid == agTRUE) &&
3740           (oneDeviceData->dmPortContext == onePortContext)
3741         )
3742       {
3743         DM_DBG3(("dmPortSASDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
3744         DM_DBG3(("dmPortSASDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));         
3745         DM_DBG3(("dmPortSASDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3746         RetDeviceData = oneDeviceData;
3747         dmUpdateMCN(dmRoot, onePortContext, RetDeviceData, CurrentDeviceData);
3748         break;
3749       }
3750       DeviceListList = DeviceListList->flink;
3751     }
3752   }
3753   else
3754   {
3755     /* incremental discovery */
3756     DM_DBG3(("dmPortSASDeviceFind: Incremental discovery\n"));
3757     while (DeviceListList != &(dmAllShared->MainDeviceList))
3758     {
3759       oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3760       if (oneDeviceData == agNULL)
3761       {
3762         DM_DBG1(("dmPortSASDeviceFind: oneDeviceData is NULL!!!\n"));  
3763         return agNULL;
3764       }      
3765       if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) &&
3766           (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) &&
3767           (oneDeviceData->valid2 == agTRUE) &&
3768           (oneDeviceData->dmPortContext == onePortContext)
3769           )
3770       {
3771         DM_DBG3(("dmPortSASDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
3772         DM_DBG3(("dmPortSASDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));         
3773         DM_DBG3(("dmPortSASDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3774         RetDeviceData = oneDeviceData;
3775         dmUpdateMCN(dmRoot, onePortContext, RetDeviceData, CurrentDeviceData);
3776         break;
3777       }
3778       DeviceListList = DeviceListList->flink;
3779     }
3780   }
3781   
3782   tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
3783
3784   return RetDeviceData;
3785 }                     
3786
3787 bit32
3788 dmNewEXPorNot(
3789               dmRoot_t              *dmRoot,
3790               dmIntPortContext_t    *onePortContext,
3791               dmSASSubID_t          *dmSASSubID
3792              )
3793 {
3794 //  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3795 //  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3796   dmExpander_t      *oneExpander = agNULL;
3797   dmList_t          *ExpanderList;
3798   bit32             ret = agTRUE;
3799   dmDeviceData_t    *oneDeviceData = agNULL;
3800   
3801   DM_DBG3(("dmNewEXPorNot: start\n"));
3802   
3803   /* find a device's existence */
3804   ExpanderList = onePortContext->discovery.discoveringExpanderList.flink;
3805   while (ExpanderList != &(onePortContext->discovery.discoveringExpanderList))
3806   {
3807     oneExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
3808     if ( oneExpander == agNULL)
3809     {
3810       DM_DBG1(("dmNewEXPorNot: oneExpander is NULL!!!\n"));    
3811       return agFALSE;
3812     }    
3813     oneDeviceData = oneExpander->dmDevice;
3814     if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) &&
3815         (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) &&
3816         (oneDeviceData->dmPortContext == onePortContext)
3817         )
3818     {
3819       DM_DBG3(("dmNewEXPorNot: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
3820       ret = agFALSE;
3821       break;
3822     }
3823     ExpanderList = ExpanderList->flink;
3824   }
3825     
3826   return ret;
3827 }
3828
3829
3830 bit32
3831 dmNewSASorNot(
3832               dmRoot_t              *dmRoot,
3833               dmIntPortContext_t    *onePortContext,
3834               dmSASSubID_t          *dmSASSubID
3835              )
3836 {
3837   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3838   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3839   dmDeviceData_t    *oneDeviceData = agNULL;
3840   dmList_t          *DeviceListList;
3841   bit32             ret = agTRUE;
3842   
3843   DM_DBG3(("dmNewSASorNot: start\n"));
3844   
3845   /* find a device's existence */
3846   DeviceListList = dmAllShared->MainDeviceList.flink;
3847   while (DeviceListList != &(dmAllShared->MainDeviceList))
3848   {
3849     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3850     if (oneDeviceData == agNULL)
3851     {
3852       DM_DBG1(("dmNewSASorNot: oneDeviceData is NULL!!!\n"));
3853       return agFALSE;
3854     }    
3855     if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) &&
3856         (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) &&
3857         (oneDeviceData->dmPortContext == onePortContext) &&
3858         (oneDeviceData->registered == agTRUE)   
3859        )
3860     {
3861       DM_DBG3(("dmNewSASorNot: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
3862       ret = agFALSE;
3863       break;
3864     }
3865     DeviceListList = DeviceListList->flink;
3866   }
3867     
3868   return ret;
3869 }
3870 /* 
3871 call
3872 osGLOBAL bit32 
3873 tddmReportDevice(
3874                  dmRoot_t               *dmRoot,
3875                  dmPortContext_t        *dmPortContext,
3876                  dmDeviceInfo_t         *dmDeviceInfo
3877                  )
3878 if not reported, report Device to TDM
3879 */
3880 osGLOBAL dmDeviceData_t *
3881 dmPortSASDeviceAdd(
3882                    dmRoot_t            *dmRoot,
3883                    dmIntPortContext_t  *onePortContext,
3884                    agsaSASIdentify_t   sasIdentify,
3885                    bit32               sasInitiator,
3886                    bit8                connectionRate,
3887                    bit32               itNexusTimeout,
3888                    bit32               firstBurstSize,
3889                    bit32               deviceType,
3890                    dmDeviceData_t      *oneExpDeviceData,
3891                    dmExpander_t        *dmExpander,
3892                    bit8                phyID
3893                   )
3894 {
3895   dmDeviceData_t    *oneDeviceData = agNULL;
3896   bit8              dev_s_rate = 0;
3897   bit8              sasorsata = 1;
3898   dmSASSubID_t      dmSASSubID;
3899   bit8              ExpanderConnectionRate = connectionRate;
3900   dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
3901   bit16             extension = 0;
3902   bit32             current_link_rate = 0;
3903   
3904   DM_DBG3(("dmPortSASDeviceAdd: start\n"));
3905   DM_DBG3(("dmPortSASDeviceAdd: connectionRate %d\n", connectionRate));
3906   
3907   dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
3908   dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
3909   dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
3910   dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
3911   
3912   if (oneExpDeviceData != agNULL)
3913   {
3914     ExpanderConnectionRate =   DEVINFO_GET_LINKRATE(&oneExpDeviceData->agDeviceInfo);
3915     DM_DBG3(("dmPortSASDeviceAdd: ExpanderConnectionRate 0x%x\n", ExpanderConnectionRate));
3916   }
3917   if (oneExpDeviceData != agNULL)
3918   {
3919     if (oneExpDeviceData->SASAddressID.sasAddressHi == 0x0 &&
3920         oneExpDeviceData->SASAddressID.sasAddressLo == 0x0)
3921     {
3922       DM_DBG1(("dmPortSASDeviceAdd: 1st Wrong expander!!!\n"));    
3923     }               
3924   }
3925   /* old device and already reported to TDM */
3926   if ( agFALSE == dmNewSASorNot(
3927                                  dmRoot,
3928                                  onePortContext,
3929                                  &dmSASSubID
3930                                 )
3931        ) /* old device */
3932   {
3933     DM_DBG3(("dmPortSASDeviceAdd: OLD qqqq initiator_ssp_stp_smp %d target_ssp_stp_smp %d\n", dmSASSubID.initiator_ssp_stp_smp, dmSASSubID.target_ssp_stp_smp));
3934     /* allocate a new device and set the valid bit */ 
3935     oneDeviceData = dmAddSASToSharedcontext(
3936                                                dmRoot,
3937                                                onePortContext,
3938                                                &dmSASSubID,
3939                                                oneExpDeviceData,
3940                                                phyID
3941                                                );
3942     if (oneDeviceData == agNULL)
3943     {
3944       DM_DBG1(("dmPortSASDeviceAdd: no more device, oneDeviceData is null!!!\n"));
3945     }
3946     /* If a device is allocated */
3947     if ( oneDeviceData != agNULL )
3948     {
3949
3950
3951       if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3952       {
3953         DM_DBG3(("dmPortSASDeviceAdd: OLD, UP_STREAM\n"));
3954       }    
3955       if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
3956       {      
3957         DM_DBG3(("dmPortSASDeviceAdd: OLD, DOWN_STREAM\n"));
3958       }
3959       
3960       if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
3961       {
3962         DM_DBG3(("dmPortSASDeviceAdd: FULL_START\n"));  
3963         oneDeviceData->MCN++;
3964       }
3965       else
3966       {
3967         /* incremental */
3968         DM_DBG3(("dmPortSASDeviceAdd: INCREMENTAL_START\n"));  
3969         if (oneDeviceData->MCN == 0 && oneDeviceData->directlyAttached == agFALSE)
3970         {
3971           oneDeviceData->MCN++;   
3972         }
3973       }         
3974       
3975       DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData MCN 0x%08x\n", oneDeviceData->MCN));
3976       DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
3977       oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));         
3978
3979
3980       DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify)));
3981       DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify)));
3982       
3983 //      oneDeviceData->sasIdentify = sasIdentify;
3984       dm_memcpy(&(oneDeviceData->sasIdentify), &sasIdentify, sizeof(agsaSASIdentify_t));
3985       
3986       DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
3987       DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
3988       
3989       /* parse sasIDframe to fill in agDeviceInfo */
3990       DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT);
3991       DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)itNexusTimeout);
3992       DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, (bit16)firstBurstSize);
3993       DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 1);
3994       
3995       oneDeviceData->SASSpecDeviceType = SA_IDFRM_GET_DEVICETTYPE(&sasIdentify);
3996       
3997       /* adjusting connectionRate */
3998       oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
3999       if (oneAttachedExpDeviceData != agNULL)
4000       {
4001         connectionRate = MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo));
4002         DM_DBG3(("dmPortSASDeviceAdd: 1st connectionRate 0x%x  DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n",
4003                connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
4004       }
4005       else
4006       {
4007        DM_DBG3(("dmPortSASDeviceAdd: 1st oneAttachedExpDeviceData is NULL\n"));
4008       }
4009       
4010       /* Device Type, SAS or SATA, connection rate; bit7 --- bit0 */
4011       sasorsata = (bit8)deviceType;
4012       /* sTSDK spec device typ */
4013       dev_s_rate = dev_s_rate | (sasorsata << 4);
4014       dev_s_rate = dev_s_rate | MIN(connectionRate, ExpanderConnectionRate);
4015       /* detect link rate change */
4016       current_link_rate = DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo);
4017       if (current_link_rate != (bit32)MIN(connectionRate, ExpanderConnectionRate))
4018       {
4019         DM_DBG1(("dmPortSASDeviceAdd: link rate changed current 0x%x new 0x%x\n", current_link_rate, MIN(connectionRate, ExpanderConnectionRate)));
4020         DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->dmDeviceInfo, dev_s_rate);
4021         if (oneDeviceData->ExpDevice != agNULL)
4022         {
4023           oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
4024           tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, dmDeviceRateChange);
4025         }
4026         else
4027         {
4028           tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, dmDeviceArrival);
4029         }         
4030       }
4031       
4032       DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate);
4033       
4034     
4035       DEVINFO_PUT_SAS_ADDRESSLO(
4036                                 &oneDeviceData->agDeviceInfo,
4037                                 SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)
4038                                 );
4039       DEVINFO_PUT_SAS_ADDRESSHI(
4040                                 &oneDeviceData->agDeviceInfo,
4041                                 SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)
4042                                 );
4043       oneDeviceData->agContext.osData = oneDeviceData;
4044       oneDeviceData->agContext.sdkData = agNULL;
4045    
4046       
4047     }   
4048     return oneDeviceData;               
4049   }  /* old device */
4050   
4051   
4052   /* new device */
4053         
4054   DM_DBG3(("dmPortSASDeviceAdd: NEW qqqq initiator_ssp_stp_smp %d target_ssp_stp_smp %d\n", dmSASSubID.initiator_ssp_stp_smp, dmSASSubID.target_ssp_stp_smp));
4055   
4056   /* allocate a new device and set the valid bit */ 
4057   oneDeviceData = dmAddSASToSharedcontext(
4058                                                dmRoot,
4059                                                onePortContext,
4060                                                &dmSASSubID,
4061                                                oneExpDeviceData,
4062                                                phyID
4063                                                );
4064   if (oneDeviceData == agNULL)
4065   {
4066     DM_DBG1(("dmPortSASDeviceAdd: no more device, oneDeviceData is null !!!\n"));
4067   }
4068   
4069    /* If a device is allocated */
4070   if ( oneDeviceData != agNULL )
4071   {
4072
4073 //    DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify)));
4074 //    DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify)));
4075   
4076 //    oneDeviceData->sasIdentify = sasIdentify;
4077     dm_memcpy(&(oneDeviceData->sasIdentify), &sasIdentify, sizeof(agsaSASIdentify_t));
4078     
4079     if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
4080     {
4081       DM_DBG3(("dmPortSASDeviceAdd: NEW, UP_STREAM\n"));
4082     }    
4083     if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
4084     {      
4085       DM_DBG3(("dmPortSASDeviceAdd: NEW, DOWN_STREAM\n"));
4086     }
4087         
4088     if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
4089     {
4090       DM_DBG3(("dmPortSASDeviceAdd: FULL_START\n"));  
4091       oneDeviceData->MCN++;
4092     }
4093     else
4094     {
4095       /* incremental */
4096       DM_DBG3(("dmPortSASDeviceAdd: INCREMENTAL_START\n"));  
4097       if (oneDeviceData->MCN == 0 && oneDeviceData->directlyAttached == agFALSE)
4098       {
4099         oneDeviceData->MCN++;     
4100       }
4101     }      
4102     DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData MCN 0x%08x\n", oneDeviceData->MCN));
4103     DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
4104     oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));         
4105     
4106     DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
4107     DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
4108
4109     /* parse sasIDframe to fill in agDeviceInfo */
4110     DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT);
4111     DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)itNexusTimeout);
4112     DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, (bit16)firstBurstSize);
4113     DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 1);
4114     
4115     oneDeviceData->SASSpecDeviceType = SA_IDFRM_GET_DEVICETTYPE(&sasIdentify);
4116     
4117     /* adjusting connectionRate */
4118     oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
4119     if (oneAttachedExpDeviceData != agNULL)
4120     {
4121       connectionRate = MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo));
4122       DM_DBG3(("dmPortSASDeviceAdd: 2nd connectionRate 0x%x  DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n",
4123                 connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
4124     }
4125     else
4126     {
4127      DM_DBG3(("dmPortSASDeviceAdd: 2nd oneAttachedExpDeviceData is NULL\n"));
4128     }
4129     
4130     /* Device Type, SAS or SATA, connection rate; bit7 --- bit0 */
4131     sasorsata = (bit8)deviceType;
4132     dev_s_rate = dev_s_rate | (sasorsata << 4);
4133     dev_s_rate = dev_s_rate | MIN(connectionRate, ExpanderConnectionRate);
4134     DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate);
4135
4136     
4137     DEVINFO_PUT_SAS_ADDRESSLO(
4138                               &oneDeviceData->agDeviceInfo,
4139                               SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)
4140                               );
4141     DEVINFO_PUT_SAS_ADDRESSHI(
4142                               &oneDeviceData->agDeviceInfo,
4143                               SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)
4144                               );
4145     oneDeviceData->agContext.osData = oneDeviceData;
4146     oneDeviceData->agContext.sdkData = agNULL;
4147                 
4148     DM_DBG3(("dmPortSASDeviceAdd: did %d\n", oneDeviceData->id));
4149   
4150     
4151     /* reporting to TDM; setting dmDeviceInfo */
4152     DEVINFO_PUT_SMPTO(&oneDeviceData->dmDeviceInfo, DEFAULT_SMP_TIMEOUT);
4153     DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->dmDeviceInfo, (bit16)itNexusTimeout);
4154     DEVINFO_PUT_FBS(&oneDeviceData->dmDeviceInfo, (bit16)firstBurstSize);
4155     DEVINFO_PUT_FLAG(&oneDeviceData->dmDeviceInfo, 1);
4156     DEVINFO_PUT_INITIATOR_SSP_STP_SMP(&oneDeviceData->dmDeviceInfo, dmSASSubID.initiator_ssp_stp_smp);
4157     DEVINFO_PUT_TARGET_SSP_STP_SMP(&oneDeviceData->dmDeviceInfo, dmSASSubID.target_ssp_stp_smp);
4158     extension = phyID;
4159       
4160     /* setting 6th bit of dev_s_rate */
4161     if (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE ||
4162         oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE )
4163     {
4164       extension = (bit16)(extension | (1 << 8));
4165     }
4166     DEVINFO_PUT_EXT(&oneDeviceData->dmDeviceInfo, extension);
4167       
4168     DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->dmDeviceInfo, dev_s_rate);
4169     
4170     DEVINFO_PUT_SAS_ADDRESSLO(
4171                               &oneDeviceData->dmDeviceInfo,
4172                               SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)
4173                               );
4174     DEVINFO_PUT_SAS_ADDRESSHI(
4175                               &oneDeviceData->dmDeviceInfo,
4176                               SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)
4177                               );
4178     
4179     if (oneDeviceData->ExpDevice != agNULL)
4180     {
4181       DM_DBG3(("dmPortSASDeviceAdd: attached expander case\n"));
4182       oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
4183       /*
4184         Puts attached expander's SAS address into dmDeviceInfo
4185       */
4186       DEVINFO_PUT_SAS_ADDRESSLO(
4187                                 &oneAttachedExpDeviceData->dmDeviceInfo,
4188                                 oneAttachedExpDeviceData->SASAddressID.sasAddressLo
4189                                 );
4190       DEVINFO_PUT_SAS_ADDRESSHI(
4191                                 &oneAttachedExpDeviceData->dmDeviceInfo,
4192                                 oneAttachedExpDeviceData->SASAddressID.sasAddressHi
4193                                 );
4194       DM_DBG3(("dmPortSASDeviceAdd: oneAttachedExpDeviceData addrHi 0x%08x addrLo 0x%08x PhyID 0x%x ext 0x%x\n", 
4195       DM_GET_SAS_ADDRESSHI(oneAttachedExpDeviceData->dmDeviceInfo.sasAddressHi), 
4196       DM_GET_SAS_ADDRESSLO(oneAttachedExpDeviceData->dmDeviceInfo.sasAddressLo),
4197       phyID, extension));    
4198             
4199       if (oneAttachedExpDeviceData->SASAddressID.sasAddressHi == 0x0 &&
4200           oneAttachedExpDeviceData->SASAddressID.sasAddressLo == 0x0)
4201       {
4202         DM_DBG1(("dmPortSASDeviceAdd: 2nd Wrong expander!!!\n"));    
4203       }             
4204       if (oneDeviceData->reported == agFALSE)
4205       {
4206         oneDeviceData->registered = agTRUE;
4207         oneDeviceData->reported = agTRUE;
4208         if (deviceType == STP_DEVICE_TYPE)
4209         {
4210             /*STP device, DM need send SMP Report Phy SATA to get the SATA device type */
4211             oneAttachedExpDeviceData->dmExpander->dmDeviceToProcess = oneDeviceData;
4212             dmReportPhySataSend(dmRoot, oneAttachedExpDeviceData, phyID);  
4213         }
4214         else
4215         {
4216             /* SAS or SMP device */
4217             tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, dmDeviceArrival);
4218         }
4219       }      
4220     }
4221     else
4222     {
4223       DM_DBG3(("dmPortSASDeviceAdd: NO attached expander case\n"));
4224       if (oneDeviceData->reported == agFALSE)
4225       {
4226         oneDeviceData->registered = agTRUE;
4227         oneDeviceData->reported = agTRUE;
4228         tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, dmDeviceArrival);
4229       }      
4230     }   
4231   }  
4232   
4233   return oneDeviceData;
4234 }                     
4235
4236 osGLOBAL dmDeviceData_t *
4237 dmFindRegNValid(
4238                 dmRoot_t             *dmRoot,
4239                 dmIntPortContext_t   *onePortContext,
4240                 dmSASSubID_t         *dmSASSubID
4241                )                                                                
4242 {
4243   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
4244   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
4245   dmDeviceData_t    *oneDeviceData = agNULL;
4246   dmList_t          *DeviceListList;
4247   bit32             found = agFALSE;
4248   DM_DBG3(("dmFindRegNValid: start\n"));
4249   
4250   /* find a device's existence */
4251   DeviceListList = dmAllShared->MainDeviceList.flink;
4252   if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
4253   {
4254     DM_DBG3(("dmFindRegNValid: Full discovery\n"));
4255     while (DeviceListList != &(dmAllShared->MainDeviceList))
4256     {
4257       oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
4258       if (oneDeviceData == agNULL)
4259       {
4260         DM_DBG1(("dmFindRegNValid: oneDeviceData is NULL!!!\n"));
4261         return agFALSE;
4262       }    
4263       if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) &&
4264           (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) &&
4265           (oneDeviceData->valid == agTRUE) &&
4266           (oneDeviceData->dmPortContext == onePortContext)
4267           )
4268       {
4269         DM_DBG3(("dmFindRegNValid: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
4270         DM_DBG3(("dmFindRegNValid: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));         
4271         DM_DBG3(("dmFindRegNValid: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
4272         found = agTRUE;
4273         break;
4274       }
4275       DeviceListList = DeviceListList->flink;
4276     }
4277   }
4278   else
4279   {
4280     /* incremental discovery */
4281     DM_DBG3(("dmFindRegNValid: Incremental discovery\n"));
4282     while (DeviceListList != &(dmAllShared->MainDeviceList))
4283     {
4284       oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
4285       if (oneDeviceData == agNULL)
4286       {
4287         DM_DBG1(("dmFindRegNValid: oneDeviceData is NULL!!!\n"));
4288         return agFALSE;
4289       }    
4290       if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) &&
4291           (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) &&
4292           (oneDeviceData->valid2 == agTRUE) &&
4293           (oneDeviceData->dmPortContext == onePortContext)
4294           )
4295       {
4296         DM_DBG3(("dmFindRegNValid: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
4297         DM_DBG3(("dmFindRegNValid: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));         
4298         DM_DBG3(("dmFindRegNValid: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
4299         found = agTRUE;
4300         break;
4301       }
4302       DeviceListList = DeviceListList->flink;
4303     }
4304   }
4305     
4306         
4307                 
4308   if (found == agFALSE)
4309   {
4310     DM_DBG3(("dmFindRegNValid: end returning NULL\n"));
4311     return agNULL;
4312   }
4313   else
4314   {
4315     DM_DBG3(("dmFindRegNValid: end returning NOT NULL\n"));
4316     return oneDeviceData;
4317   }
4318 }                     
4319
4320 osGLOBAL void   
4321 dmNotifyBC(
4322            dmRoot_t                     *dmRoot,
4323            dmPortContext_t              *dmPortContext,
4324            bit32                        type)
4325 {
4326   dmIntPortContext_t        *onePortContext = agNULL;
4327   
4328   onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
4329   
4330   DM_DBG3(("dmNotifyBC: start\n"));
4331       
4332   if (onePortContext == agNULL)
4333   {
4334     DM_DBG1(("dmNotifyBC: onePortContext is NULL, wrong!!!\n"));  
4335     return;
4336   }
4337   
4338   if (type == OSSA_HW_EVENT_BROADCAST_CHANGE)
4339   {
4340     if (onePortContext->DiscoveryAbortInProgress == agFALSE)
4341     {
4342     if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED)
4343     {
4344       DM_DBG3(("dmNotifyBC: BROADCAST_CHANGE\n"));
4345       onePortContext->DiscoveryState = DM_DSTATE_NOT_STARTED;
4346       onePortContext->discoveryOptions = DM_DISCOVERY_OPTION_INCREMENTAL_START;
4347       /* processed broadcast change */
4348       onePortContext->discovery.SeenBC = agFALSE;       
4349     }
4350     else
4351     {
4352       DM_DBG3(("dmNotifyBC: pid %d BROADCAST_CHANGE; updating SeenBC. Do nothing.\n", onePortContext->id));      
4353       onePortContext->discovery.SeenBC = agTRUE;
4354     }
4355     }                 
4356   }
4357   else if (type == OSSA_HW_EVENT_BROADCAST_SES)
4358   {
4359     DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_SES\n"));      
4360   }
4361   else if (type == OSSA_HW_EVENT_BROADCAST_EXP)
4362   {
4363     DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_EXP\n"));      
4364   }
4365   else 
4366   {
4367     DM_DBG3(("dmNotifyBC: unspecified broadcast type 0x%x\n", type));      
4368   }
4369   return;
4370 }                                       
4371
4372
4373 #ifdef WORKED
4374 /* triggers incremental discovery */
4375 osGLOBAL void   
4376 dmNotifyBC(
4377            dmRoot_t                     *dmRoot,
4378            dmPortContext_t              *dmPortContext,
4379            bit32                        type)
4380 {
4381   dmIntPortContext_t        *onePortContext = agNULL;
4382   
4383   onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
4384   
4385   DM_DBG3(("dmNotifyBC: start\n"));
4386       
4387   
4388   if (type == OSSA_HW_EVENT_BROADCAST_CHANGE)
4389   {
4390     if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED)
4391     {
4392       DM_DBG3(("dmNotifyBC: BROADCAST_CHANGE; does incremental discovery\n"));
4393       onePortContext->DiscoveryState = DM_DSTATE_NOT_STARTED;
4394       onePortContext->discoveryOptions = DM_DISCOVERY_OPTION_INCREMENTAL_START;
4395       /* processed broadcast change */
4396       onePortContext->discovery.SeenBC = agFALSE;       
4397       if (onePortContext->discovery.ResetTriggerred == agTRUE)
4398       {
4399         DM_DBG3(("dmNotifyBC: tdsaBCTimer\n"));
4400         dmBCTimer(dmRoot, onePortContext);
4401       }
4402       else
4403       {
4404         dmDiscover(
4405                    dmRoot,
4406                    dmPortContext,
4407                    DM_DISCOVERY_OPTION_INCREMENTAL_START
4408                   );
4409       }
4410     }
4411     else
4412     {
4413       DM_DBG3(("dmNotifyBC: pid %d BROADCAST_CHANGE; updating SeenBC. Do nothing.\n", onePortContext->id));      
4414       onePortContext->discovery.SeenBC = agTRUE;
4415     }                 
4416   }
4417   else if (type == OSSA_HW_EVENT_BROADCAST_SES)
4418   {
4419     DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_SES\n"));      
4420   }
4421   else if (type == OSSA_HW_EVENT_BROADCAST_EXP)
4422   {
4423     DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_EXP\n"));      
4424   }
4425   else 
4426   {
4427     DM_DBG3(("dmNotifyBC: unspecified broadcast type 0x%x\n", type));      
4428   }
4429   return;
4430 }                                       
4431 #endif                          
4432                                 
4433 osGLOBAL bit32  
4434 dmResetFailedDiscovery(  
4435                  dmRoot_t               *dmRoot,
4436                  dmPortContext_t        *dmPortContext)
4437 {
4438   dmIntPortContext_t        *onePortContext = agNULL;
4439   
4440   DM_DBG1(("dmResetFailedDiscovery: start\n"));
4441   
4442   onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
4443   
4444   if (onePortContext == agNULL)
4445   {
4446     DM_DBG1(("dmResetFailedDiscovery: onePortContext is NULL, wrong!!!\n"));  
4447     return DM_RC_FAILURE;
4448   }
4449   
4450   if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED_WITH_FAILURE)
4451   {
4452     onePortContext->DiscoveryState = DM_DSTATE_COMPLETED;
4453   }
4454   else
4455   {
4456     DM_DBG1(("dmResetFailedDiscovery: discovery is NOT DM_DSTATE_COMPLETED_WITH_FAILURE. It is 0x%x\n", onePortContext->DiscoveryState));  
4457     return DM_RC_FAILURE;
4458   }
4459   
4460   return DM_RC_SUCCESS;
4461 }                                       
4462
4463 osGLOBAL bit32  
4464 dmQueryDiscovery(  
4465                  dmRoot_t               *dmRoot,
4466                  dmPortContext_t        *dmPortContext)
4467 {
4468   dmIntPortContext_t        *onePortContext = agNULL;
4469   
4470   DM_DBG3(("dmQueryDiscovery: start\n"));
4471   
4472   onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
4473   
4474   if (onePortContext == agNULL)
4475   {
4476     DM_DBG1(("dmQueryDiscovery: onePortContext is NULL, wrong!!!\n"));  
4477     return DM_RC_FAILURE;
4478   }
4479   
4480   /* call tddmQueryDiscoveryCB() */
4481   if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED)
4482   {
4483     tddmQueryDiscoveryCB(dmRoot, dmPortContext,  onePortContext->discoveryOptions, dmDiscCompleted); 
4484   }
4485   else if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED_WITH_FAILURE)
4486   {
4487     tddmQueryDiscoveryCB(dmRoot, dmPortContext,  onePortContext->discoveryOptions, dmDiscFailed); 
4488   }
4489   else
4490   {
4491     tddmQueryDiscoveryCB(dmRoot, dmPortContext,  onePortContext->discoveryOptions, dmDiscInProgress); 
4492   }  
4493   
4494   return DM_RC_SUCCESS;
4495 }                                       
4496
4497                                                                 
4498 /* 
4499   should only for an expander
4500 */
4501 osGLOBAL bit32  
4502 dmRegisterDevice(  
4503                  dmRoot_t               *dmRoot,
4504                  dmPortContext_t        *dmPortContext,
4505                  dmDeviceInfo_t         *dmDeviceInfo,
4506                  agsaDevHandle_t        *agDevHandle
4507                  )
4508 {
4509
4510   dmIntPortContext_t        *onePortContext = agNULL;
4511   dmExpander_t              *oneExpander = agNULL;
4512   bit32                     sasAddressHi, sasAddressLo;
4513   dmDeviceData_t            *oneDeviceData = agNULL;
4514   dmSASSubID_t              dmSASSubID;
4515   
4516   DM_DBG3(("dmRegisterDevice: start\n"));
4517   
4518   onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
4519   if (onePortContext == agNULL)
4520   {
4521     DM_DBG1(("dmRegisterDevice: onePortContext is NULL!!!\n"));
4522     return DM_RC_FAILURE;
4523   }
4524   
4525   if (onePortContext->valid == agFALSE)
4526   {
4527     DM_DBG1(("dmRegisterDevice: invalid port!!!\n"));
4528     return DM_RC_FAILURE;
4529   }
4530   
4531   onePortContext->RegFailed = agFALSE;
4532   
4533   /* tdssAddSASToSharedcontext() from ossaHwCB()
4534 osGLOBAL void
4535 tdssAddSASToSharedcontext(
4536                           tdsaPortContext_t    *tdsaPortContext_Instance,
4537                           agsaRoot_t           *agRoot,
4538                           agsaDevHandle_t      *agDevHandle,
4539                           tdsaSASSubID_t       *agSASSubID,
4540                           bit32                registered,
4541                           bit8                 phyID,
4542                           bit32                flag
4543                           );
4544 from discovery  
4545 osGLOBAL tdsaDeviceData_t *
4546 tdssNewAddSASToSharedcontext(
4547                                  agsaRoot_t           *agRoot,
4548                                  tdsaPortContext_t    *onePortContext,
4549                                  tdsaSASSubID_t       *agSASSubID,
4550                                  tdsaDeviceData_t     *oneExpDeviceData,
4551                                  bit8                 phyID
4552                                  );
4553   
4554   */
4555   /* start here */
4556   dmSASSubID.sasAddressHi = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressHi);
4557   dmSASSubID.sasAddressLo = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressLo);
4558   dmSASSubID.initiator_ssp_stp_smp = dmDeviceInfo->initiator_ssp_stp_smp;
4559   dmSASSubID.target_ssp_stp_smp = dmDeviceInfo->target_ssp_stp_smp;
4560  
4561   oneDeviceData = dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, agNULL, 0xFF);  
4562   if (oneDeviceData == agNULL)
4563   {
4564     DM_DBG1(("dmRegisterDevice: oneDeviceData is NULL!!!\n"));
4565     return DM_RC_FAILURE;
4566   }
4567   oneDeviceData->agDeviceInfo.devType_S_Rate = dmDeviceInfo->devType_S_Rate;
4568   dm_memcpy(oneDeviceData->agDeviceInfo.sasAddressHi, dmDeviceInfo->sasAddressHi, 4);
4569   dm_memcpy(oneDeviceData->agDeviceInfo.sasAddressLo, dmDeviceInfo->sasAddressLo, 4);
4570   /* finds the type of expanders */
4571   if (DEVINFO_GET_EXT_SMP(dmDeviceInfo))
4572   {
4573     if (DEVINFO_GET_EXT_EXPANDER_TYPE(dmDeviceInfo) == SAS_EDGE_EXPANDER_DEVICE)
4574     {
4575       oneDeviceData->SASSpecDeviceType = SAS_EDGE_EXPANDER_DEVICE;
4576     }
4577     else if (DEVINFO_GET_EXT_EXPANDER_TYPE(dmDeviceInfo) == SAS_FANOUT_EXPANDER_DEVICE)
4578     {
4579       oneDeviceData->SASSpecDeviceType = SAS_FANOUT_EXPANDER_DEVICE;
4580     }
4581     else
4582     {
4583       /* default */
4584       DM_DBG4(("dmRegisterDevice: no expander type. default to edge expander\n"));
4585       oneDeviceData->SASSpecDeviceType = SAS_EDGE_EXPANDER_DEVICE;
4586     }
4587   }
4588   
4589   if (DEVINFO_GET_EXT_MCN(dmDeviceInfo) == 0xF)
4590   {
4591     DM_DBG1(("dmRegisterDevice: directly attached expander\n"));
4592     oneDeviceData->directlyAttached = agTRUE;
4593     oneDeviceData->dmDeviceInfo.ext =  (bit16)(oneDeviceData->dmDeviceInfo.ext | (0xF << 11));
4594   }
4595   else
4596   {
4597     DM_DBG1(("dmRegisterDevice: NOT directly attached expander\n"));
4598     oneDeviceData->directlyAttached = agFALSE;
4599   }      
4600   
4601   if (onePortContext->DiscoveryState == DM_DSTATE_NOT_STARTED)
4602   {
4603     DM_DBG3(("dmRegisterDevice: DM_DSTATE_NOT_STARTED\n"));
4604     /* before the discovery is started */
4605     oneExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, oneDeviceData);
4606     if ( oneExpander != agNULL)
4607     {
4608       oneExpander->agDevHandle = agDevHandle;
4609       /* update SAS address field */
4610       oneExpander->dmDevice->SASAddressID.sasAddressHi = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressHi);
4611       oneExpander->dmDevice->SASAddressID.sasAddressLo = DM_GET_SAS_ADDRESSLO(dmDeviceInfo->sasAddressLo);
4612       DM_DBG3(("dmRegisterDevice: AddrHi 0x%08x AddrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi, oneExpander->dmDevice->SASAddressID.sasAddressLo));
4613       dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);      
4614     }
4615     else
4616     {
4617       DM_DBG1(("dmRegisterDevice: failed to allocate expander !!!\n"));
4618       /* remember that the registration failed so that a discovery can't be started */
4619       onePortContext->RegFailed = agTRUE;
4620       return DM_RC_FAILURE;
4621     }
4622   }
4623   else
4624   {
4625     /*
4626       the discovery has started. Alloc and add have been done.
4627       find an expander using dmDeviceInfo, and update the expander's agDevHandle
4628       call dmExpFind()
4629     */
4630     DM_DBG3(("dmRegisterDevice: NOT DM_DSTATE_NOT_STARTED\n"));
4631     sasAddressHi = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressHi);
4632     sasAddressLo = DM_GET_SAS_ADDRESSLO(dmDeviceInfo->sasAddressLo);
4633     DM_DBG3(("dmRegisterDevice: AddrHi 0x%08x AddrLo 0x%08x\n", sasAddressHi, sasAddressLo));
4634     oneExpander = dmExpFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo);
4635     if ( oneExpander != agNULL)
4636     {
4637       oneExpander->agDevHandle = agDevHandle;
4638     }
4639     else
4640     {
4641       DM_DBG1(("dmRegisterDevice: not allowed case, wrong !!!\n"));
4642       return DM_RC_FAILURE;
4643     }
4644   }
4645
4646   return DM_RC_SUCCESS;
4647 }                                
4648
4649 osGLOBAL dmExpander_t *
4650 dmDiscoveringExpanderAlloc(
4651                            dmRoot_t                 *dmRoot,
4652                            dmIntPortContext_t       *onePortContext,
4653                            dmDeviceData_t           *oneDeviceData
4654                           )
4655 {
4656   dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
4657   dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
4658   dmExpander_t              *oneExpander = agNULL;
4659   dmList_t                  *ExpanderList;
4660   
4661   DM_DBG3(("dmDiscoveringExpanderAlloc: start\n"));
4662   DM_DBG3(("dmDiscoveringExpanderAlloc: did %d\n", oneDeviceData->id));
4663   DM_DBG3(("dmDiscoveringExpanderAlloc: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
4664   DM_DBG3(("dmDiscoveringExpanderAlloc: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
4665
4666   if (onePortContext->valid == agFALSE)
4667   {
4668     DM_DBG1(("dmDiscoveringExpanderAlloc: invalid port!!!\n"));
4669     return agNULL;
4670   }
4671   
4672  
4673   /* check exitence in dmAllShared->mainExpanderList */
4674   oneExpander = dmExpMainListFind(dmRoot, 
4675                                   onePortContext, 
4676                                   oneDeviceData->SASAddressID.sasAddressHi, 
4677                                   oneDeviceData->SASAddressID.sasAddressLo); 
4678   
4679   if (oneExpander == agNULL)
4680   {
4681     tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
4682     if (DMLIST_EMPTY(&(dmAllShared->freeExpanderList)))
4683     {
4684       DM_DBG1(("dmDiscoveringExpanderAlloc: no free expanders pid %d!!!\n", onePortContext->id));
4685       tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4686       return agNULL;
4687     }
4688     else
4689     {
4690       tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4691     }
4692   
4693     tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
4694     DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(dmAllShared->freeExpanderList));
4695     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4696   
4697     oneExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
4698   }
4699   
4700   if (oneExpander != agNULL)
4701   {
4702     DM_DBG1(("dmDiscoveringExpanderAlloc: pid %d exp id %d \n", onePortContext->id, oneExpander->id));
4703
4704     tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
4705     DMLIST_DEQUEUE_THIS(&(oneExpander->linkNode));
4706     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4707      
4708     oneExpander->dmDevice = oneDeviceData;
4709     oneExpander->dmUpStreamExpander = agNULL;
4710     oneExpander->dmCurrentDownStreamExpander = agNULL;
4711     oneExpander->dmReturnginExpander = agNULL;
4712     oneExpander->hasUpStreamDevice = agFALSE;
4713     oneExpander->numOfUpStreamPhys = 0;
4714     oneExpander->currentUpStreamPhyIndex = 0;
4715     oneExpander->discoveringPhyId = 0;    
4716     oneExpander->underDiscovering = agFALSE; 
4717     dm_memset( &(oneExpander->currentIndex), 0, sizeof(oneExpander->currentIndex));
4718     
4719     oneDeviceData->dmExpander = oneExpander;
4720     DM_DBG3(("dmDiscoveringExpanderAlloc: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
4721     DM_DBG3(("dmDiscoveringExpanderAlloc: oneExpander %p did %d\n",  oneDeviceData->dmExpander,  oneDeviceData->dmExpander->id));
4722     
4723   }
4724   
4725   return oneExpander;
4726 }
4727
4728 osGLOBAL void
4729 dmDiscoveringExpanderAdd(
4730                          dmRoot_t                 *dmRoot,
4731                          dmIntPortContext_t       *onePortContext,
4732                          dmExpander_t             *oneExpander
4733                         )
4734 {
4735   DM_DBG3(("dmDiscoveringExpanderAdd: start\n"));
4736   DM_DBG3(("dmDiscoveringExpanderAdd: expander id %d\n", oneExpander->id));
4737   DM_DBG3(("dmDiscoveringExpanderAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4738   DM_DBG3(("dmDiscoveringExpanderAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));  
4739   
4740   if (onePortContext->valid == agFALSE)
4741   {
4742     DM_DBG1(("dmDiscoveringExpanderAdd: invalid port!!!\n"));
4743     return;
4744   }
4745   if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
4746   {
4747     DM_DBG3(("dmDiscoveringExpanderAdd: UPSTREAM\n"));
4748   }
4749   else if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
4750   {
4751     DM_DBG3(("dmDiscoveringExpanderAdd: DOWNSTREAM\n"));
4752   }
4753   else
4754   {
4755     DM_DBG3(("dmDiscoveringExpanderAdd: status %d\n", onePortContext->discovery.status));
4756   }
4757
4758   if ( oneExpander->underDiscovering == agFALSE)
4759   {
4760     DM_DBG3(("dmDiscoveringExpanderAdd: ADDED \n"));
4761   
4762     oneExpander->underDiscovering = agTRUE;
4763     tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
4764     DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));
4765     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4766   }
4767   
4768   return;
4769 }                 
4770
4771 osGLOBAL dmExpander_t *
4772 dmFindConfigurableExp(
4773                       dmRoot_t                  *dmRoot,
4774                       dmIntPortContext_t        *onePortContext,
4775                       dmExpander_t              *oneExpander
4776                      )
4777 {
4778   dmExpander_t            *tempExpander;
4779   dmIntPortContext_t      *tmpOnePortContext = onePortContext;
4780   dmExpander_t            *ret = agNULL;
4781   DM_DBG3(("dmFindConfigurableExp: start\n"));
4782   
4783   if (oneExpander == agNULL)
4784   {
4785     DM_DBG3(("dmFindConfigurableExp: NULL expander\n"));
4786     return agNULL;
4787   }
4788   
4789   DM_DBG3(("dmFindConfigurableExp: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4790   DM_DBG3(("dmFindConfigurableExp: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));    
4791   
4792   tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
4793   if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
4794   {
4795     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4796     DM_DBG3(("dmFindConfigurableExp: empty UpdiscoveringExpanderList\n"));
4797     return agNULL;
4798   }
4799   else
4800   {
4801     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4802   }
4803   tempExpander = oneExpander->dmUpStreamExpander;
4804   while (tempExpander)
4805   {
4806     DM_DBG3(("dmFindConfigurableExp: loop exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
4807     DM_DBG3(("dmFindConfigurableExp: loop exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
4808     if (tempExpander->configRouteTable)
4809     {
4810       DM_DBG3(("dmFindConfigurableExp: found configurable expander\n"));
4811       ret = tempExpander;
4812       break;
4813     }
4814    tempExpander = tempExpander->dmUpStreamExpander;
4815   }
4816   
4817   return ret;
4818 }
4819
4820 osGLOBAL bit32
4821 dmDuplicateConfigSASAddr(
4822                          dmRoot_t                 *dmRoot,
4823                          dmExpander_t             *oneExpander,
4824                          bit32                    configSASAddressHi,
4825                          bit32                    configSASAddressLo
4826                         )
4827 {
4828   bit32 i;
4829   bit32 ret = agFALSE;
4830   DM_DBG3(("dmDuplicateConfigSASAddr: start\n"));
4831   
4832   if (oneExpander == agNULL)
4833   {
4834     DM_DBG3(("dmDuplicateConfigSASAddr: NULL expander\n"));
4835     return agTRUE;
4836   }  
4837   
4838   if (oneExpander->dmDevice->SASAddressID.sasAddressHi == configSASAddressHi &&
4839       oneExpander->dmDevice->SASAddressID.sasAddressLo == configSASAddressLo
4840      )
4841   {
4842     DM_DBG3(("dmDuplicateConfigSASAddr: unnecessary\n"));
4843     return agTRUE;
4844   }     
4845
4846   DM_DBG3(("dmDuplicateConfigSASAddr: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4847   DM_DBG3(("dmDuplicateConfigSASAddr: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
4848   DM_DBG3(("dmDuplicateConfigSASAddr: configsasAddressHi 0x%08x\n", configSASAddressHi));
4849   DM_DBG3(("dmDuplicateConfigSASAddr: configsasAddressLo 0x%08x\n", configSASAddressLo));
4850   DM_DBG3(("dmDuplicateConfigSASAddr: configSASAddrTableIndex %d\n", oneExpander->configSASAddrTableIndex));            
4851   for(i=0;i<oneExpander->configSASAddrTableIndex;i++)
4852   {
4853     if (oneExpander->configSASAddressHiTable[i] == configSASAddressHi &&
4854         oneExpander->configSASAddressLoTable[i] == configSASAddressLo
4855         )
4856     {
4857       DM_DBG3(("dmDuplicateConfigSASAddr: FOUND\n"));
4858       ret = agTRUE;
4859       break;
4860     }
4861   }
4862   /* new one; let's add it */
4863   if (ret == agFALSE)
4864   {
4865     DM_DBG3(("dmDuplicateConfigSASAddr: adding configSAS Addr\n"));
4866     DM_DBG3(("dmDuplicateConfigSASAddr: configSASAddrTableIndex %d\n", oneExpander->configSASAddrTableIndex));   
4867     oneExpander->configSASAddressHiTable[oneExpander->configSASAddrTableIndex] = configSASAddressHi;
4868     oneExpander->configSASAddressLoTable[oneExpander->configSASAddrTableIndex] = configSASAddressLo;
4869     oneExpander->configSASAddrTableIndex++;
4870   }
4871   
4872   return ret;
4873 }
4874
4875 osGLOBAL bit16
4876 dmFindCurrentDownStreamPhyIndex(
4877                                 dmRoot_t          *dmRoot,
4878                                 dmExpander_t      *oneExpander
4879                                 )
4880 {
4881   dmExpander_t       *DownStreamExpander;
4882   bit16              index = 0;
4883   bit16              i;
4884   bit8               phyId = 0;
4885   
4886   DM_DBG3(("dmFindCurrentDownStreamPhyIndex: start\n"));
4887   
4888   if (oneExpander == agNULL)
4889   {
4890     DM_DBG1(("dmFindCurrentDownStreamPhyIndex: wrong, oneExpander is NULL!!!\n"));
4891     return 0;
4892   }
4893   
4894   DownStreamExpander = oneExpander->dmCurrentDownStreamExpander;
4895   
4896   if (DownStreamExpander == agNULL)
4897   {
4898     DM_DBG1(("dmFindCurrentDownStreamPhyIndex: wrong, DownStreamExpander is NULL!!!\n"));
4899     return 0;
4900   }
4901   
4902   DM_DBG3(("dmFindCurrentDownStreamPhyIndex: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4903   DM_DBG3(("dmFindCurrentDownStreamPhyIndex: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
4904   DM_DBG3(("dmFindCurrentDownStreamPhyIndex: downstream exp addrHi 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressHi));
4905   DM_DBG3(("dmFindCurrentDownStreamPhyIndex: downstream exp addrLo 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressLo));
4906   DM_DBG3(("dmFindCurrentDownStreamPhyIndex: numOfDownStreamPhys %d\n", oneExpander->numOfDownStreamPhys));
4907   
4908   phyId = DownStreamExpander->upStreamPhys[0];
4909   
4910   DM_DBG3(("dmFindCurrentDownStreamPhyIndex: phyId %d\n", phyId));
4911   
4912   for (i=0; i<oneExpander->numOfDownStreamPhys;i++)
4913   {
4914     if (oneExpander->downStreamPhys[i] == phyId)
4915     {
4916       index = i;
4917       break;
4918     }
4919   }
4920   DM_DBG3(("dmFindCurrentDownStreamPhyIndex: index %d\n", index));
4921   return index;
4922 }
4923
4924 osGLOBAL bit32
4925 dmFindDiscoveringExpander(
4926                           dmRoot_t                  *dmRoot,
4927                           dmIntPortContext_t        *onePortContext,
4928                           dmExpander_t              *oneExpander
4929                          )
4930 {
4931   dmList_t                *ExpanderList;
4932   dmExpander_t            *tempExpander;
4933   dmIntPortContext_t      *tmpOnePortContext = onePortContext;
4934   bit32                   ret = agFALSE;
4935   
4936   
4937   DM_DBG3(("dmFindDiscoveringExpander: start\n"));
4938   
4939   DM_DBG3(("dmFindDiscoveringExpander: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4940   DM_DBG3(("dmFindDiscoveringExpander: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
4941
4942   if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
4943   {
4944     DM_DBG3(("dmFindDiscoveringExpander: empty discoveringExpanderList\n"));
4945     return ret;
4946   }
4947   ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
4948   while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
4949   {
4950     tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
4951     if (tempExpander == oneExpander)
4952     {
4953       if (tempExpander != agNULL)
4954       {
4955         DM_DBG3(("dmFindDiscoveringExpander: match, expander id %d\n", tempExpander->id));
4956         DM_DBG3(("dmFindDiscoveringExpander: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
4957         DM_DBG3(("dmFindDiscoveringExpander: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
4958       }
4959       ret = agTRUE;
4960       break;
4961     }
4962     
4963     ExpanderList = ExpanderList->flink;
4964   }     
4965   
4966   
4967   return ret;
4968 }                        
4969
4970
4971 osGLOBAL void
4972 dmDiscoveringExpanderRemove(
4973                             dmRoot_t                 *dmRoot,
4974                             dmIntPortContext_t       *onePortContext,
4975                             dmExpander_t             *oneExpander
4976                            )
4977 {
4978   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
4979   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
4980   
4981   DM_DBG3(("dmDiscoveringExpanderRemove: start\n"));
4982   DM_DBG3(("dmDiscoveringExpanderRemove: expander id %d\n", oneExpander->id));
4983   DM_DBG3(("dmDiscoveringExpanderRemove: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4984   DM_DBG3(("dmDiscoveringExpanderRemove: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); 
4985   
4986   DM_DBG3(("dmDiscoveringExpanderRemove: BEFORE\n"));
4987   dmDumpAllExp(dmRoot, onePortContext, oneExpander);
4988   dmDumpAllUpExp(dmRoot, onePortContext, oneExpander);
4989   dmDumpAllFreeExp(dmRoot);
4990   
4991   // if is temporary till smp problem is fixed
4992   if (dmFindDiscoveringExpander(dmRoot, onePortContext, oneExpander) == agTRUE)
4993   {
4994     DM_DBG3(("dmDiscoveringExpanderRemove: oneDeviceData %p did %d\n", oneExpander->dmDevice, oneExpander->dmDevice->id));
4995     DM_DBG3(("dmDiscoveringExpanderRemove: oneExpander %p did %d\n", oneExpander, oneExpander->id));
4996     
4997     if (oneExpander != oneExpander->dmDevice->dmExpander)
4998     {
4999       DM_DBG3(("dmDiscoveringExpanderRemove: before !!! wrong !!!\n"));  
5000     }
5001     oneExpander->underDiscovering = agFALSE;
5002     oneExpander->discoveringPhyId = 0;
5003     tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5004     DMLIST_DEQUEUE_THIS(&(oneExpander->linkNode));
5005     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5006
5007     if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
5008     {
5009       DM_DBG3(("dmDiscoveringExpanderRemove: DISCOVERY_UP_STREAM\n"));
5010       tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5011       DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->upNode), &(onePortContext->discovery.UpdiscoveringExpanderList)); 
5012       tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5013       onePortContext->discovery.NumOfUpExp++;
5014     }
5015     else
5016     {
5017       DM_DBG3(("dmDiscoveringExpanderRemove: Status %d\n", onePortContext->discovery.status));
5018       tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5019       DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(dmAllShared->mainExpanderList));
5020 //      DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(dmAllShared->freeExpanderList));
5021       tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5022     }
5023     // error checking
5024     if (oneExpander != oneExpander->dmDevice->dmExpander)
5025     {
5026       DM_DBG3(("dmDiscoveringExpanderRemove: after !!! wrong !!!\n"));  
5027     }
5028       
5029   } //end temp if
5030   else
5031   {
5032     DM_DBG1(("dmDiscoveringExpanderRemove: !!! problem !!!\n"));
5033   }
5034
5035   DM_DBG3(("dmDiscoveringExpanderRemove: AFTER\n"));
5036   
5037   dmDumpAllExp(dmRoot, onePortContext, oneExpander);
5038   dmDumpAllUpExp(dmRoot, onePortContext, oneExpander);
5039   dmDumpAllFreeExp(dmRoot);
5040   
5041   return;
5042 }
5043
5044 /*
5045   returns an expander with sasAddrLo, sasAddrHi from dmAllShared->mainExpanderList
5046 */
5047 osGLOBAL dmExpander_t *
5048 dmExpMainListFind(
5049                   dmRoot_t            *dmRoot,
5050                   dmIntPortContext_t  *onePortContext,
5051                   bit32               sasAddrHi,
5052                   bit32               sasAddrLo
5053                  )
5054 {
5055   dmIntRoot_t        *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5056   dmIntContext_t     *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5057   dmList_t           *ExpanderList;
5058   dmExpander_t       *tempExpander;
5059
5060   DM_DBG3(("dmExpMainListFind: start\n"));
5061   
5062   tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5063   if (DMLIST_EMPTY(&(dmAllShared->mainExpanderList)))
5064   {
5065     DM_DBG1(("dmExpMainListFind: empty mainExpanderList\n"));
5066     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5067     return agNULL;
5068   }
5069   else
5070   {
5071     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5072   }
5073   ExpanderList = dmAllShared->mainExpanderList.flink;
5074   while (ExpanderList != &(dmAllShared->mainExpanderList))
5075   {
5076     tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
5077     if (tempExpander == agNULL)
5078     {
5079       DM_DBG1(("dmExpMainListFind: tempExpander is NULL!!!\n"));
5080       return agNULL;
5081     }    
5082     DM_DBG3(("dmExpMainListFind: expander id %d\n", tempExpander->id));
5083     DM_DBG3(("dmExpMainListFind: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
5084     DM_DBG3(("dmExpMainListFind: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
5085     if ((tempExpander->dmDevice->SASAddressID.sasAddressHi == sasAddrHi) &&
5086         (tempExpander->dmDevice->SASAddressID.sasAddressLo == sasAddrLo) &&
5087         (tempExpander->dmDevice->dmPortContext == onePortContext)
5088        )
5089     {
5090       DM_DBG3(("dmExpMainListFind: found expander id %d\n", tempExpander->id));
5091       DM_DBG3(("dmExpMainListFind: found exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
5092       DM_DBG3(("dmExpMainListFind: found exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
5093       return tempExpander;
5094     }           
5095     ExpanderList = ExpanderList->flink;
5096   }
5097   return agNULL;
5098
5099 }
5100
5101 /*
5102   returns an expander with sasAddrLo, sasAddrHi from discoveringExpanderList
5103 */
5104 osGLOBAL dmExpander_t *
5105 dmExpFind(
5106           dmRoot_t            *dmRoot,
5107           dmIntPortContext_t  *onePortContext,
5108           bit32               sasAddrHi,
5109           bit32               sasAddrLo
5110          )
5111 {
5112   dmList_t           *ExpanderList;
5113   dmExpander_t       *tempExpander;
5114   dmIntPortContext_t *tmpOnePortContext = onePortContext;
5115   DM_DBG3(("dmExpFind: start\n"));
5116
5117   tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5118   if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
5119   {
5120     DM_DBG3(("dmExpFind tdsaDumpAllExp: empty discoveringExpanderList\n"));
5121     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5122     return agNULL;
5123   }
5124   else
5125   {
5126     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5127   }
5128   ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
5129   while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
5130   {
5131     tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
5132     if (tempExpander == agNULL)
5133     {
5134       DM_DBG1(("dmExpFind: tempExpander is NULL!!!\n"));
5135       return agNULL;
5136     }
5137     DM_DBG3(("dmExpFind: expander id %d\n", tempExpander->id));
5138     DM_DBG3(("dmExpFind: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
5139     DM_DBG3(("dmExpFind: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
5140     if ((tempExpander->dmDevice->SASAddressID.sasAddressHi == sasAddrHi) &&
5141         (tempExpander->dmDevice->SASAddressID.sasAddressLo == sasAddrLo) &&
5142         (tempExpander->dmDevice->dmPortContext == onePortContext)
5143        )
5144     {
5145       DM_DBG3(("dmExpFind: found\n"));
5146       return tempExpander;
5147     }           
5148     ExpanderList = ExpanderList->flink;
5149   }
5150   return agNULL;
5151 }
5152                              
5153 osGLOBAL bit32
5154 dmDiscoverCheck(
5155                 dmRoot_t                *dmRoot, 
5156                 dmIntPortContext_t      *onePortContext 
5157                 )
5158 {
5159   DM_DBG3(("dmDiscoverCheck: start\n"));
5160   
5161   if (onePortContext == agNULL)
5162   {
5163     DM_DBG1(("dmDiscoverCheck: onePortContext is NULL!!!\n"));
5164     return agTRUE;
5165   }
5166   if (onePortContext->valid == agFALSE)
5167   {
5168     DM_DBG1(("dmDiscoverCheck: invalid port!!!\n"));
5169     return agTRUE;
5170   }
5171   if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED ||
5172       onePortContext->discovery.status == DISCOVERY_SAS_DONE  
5173      )
5174   {
5175     DM_DBG1(("dmDiscoverCheck: aborted discovery!!!\n"));
5176     tddmDiscoverCB(
5177                    dmRoot,
5178                    onePortContext->dmPortContext,
5179                    dmDiscAborted
5180                   );
5181     return agTRUE;
5182   }
5183   
5184   return agFALSE;
5185 }
5186
5187 /* ??? needs to handle pending SMPs 
5188    move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList  
5189 */
5190 osGLOBAL void
5191 dmDiscoverAbort(
5192                 dmRoot_t                *dmRoot, 
5193                 dmIntPortContext_t      *onePortContext 
5194                 )
5195 {
5196   DM_DBG1(("dmDiscoverAbort: start\n"));
5197   
5198   if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED ||
5199       onePortContext->discovery.status == DISCOVERY_SAS_DONE)
5200   {
5201     DM_DBG1(("dmDiscoverAbort: not allowed case!!! onePortContext->DiscoveryState 0x%x onePortContext->discovery.status 0x%x\n", 
5202     onePortContext->DiscoveryState, onePortContext->discovery.status));
5203     return;  
5204   }      
5205   
5206   onePortContext->DiscoveryState = DM_DSTATE_COMPLETED;
5207   onePortContext->discovery.status = DISCOVERY_SAS_DONE;                
5208   
5209   /* move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList */
5210   dmCleanAllExp(dmRoot, onePortContext);
5211
5212  
5213   return;
5214
5215                           
5216 }                                                                         
5217
5218 /* move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList */
5219 osGLOBAL void
5220 dmCleanAllExp(
5221               dmRoot_t                 *dmRoot,
5222               dmIntPortContext_t       *onePortContext
5223              )
5224 {
5225   dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5226   dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5227   dmList_t                  *ExpanderList;
5228   dmExpander_t              *tempExpander;
5229   dmExpander_t              *oneExpander = agNULL;
5230   dmIntPortContext_t        *tmpOnePortContext = onePortContext;
5231   
5232   DM_DBG3(("dmCleanAllExp: start\n"));
5233   DM_DBG3(("dmCleanAllExp: pid %d\n", onePortContext->id));
5234   
5235   DM_DBG3(("dmCleanAllExp: before all clean up\n")); 
5236   dmDumpAllFreeExp(dmRoot);
5237   
5238   /* clean up UpdiscoveringExpanderList*/
5239   DM_DBG3(("dmCleanAllExp: clean discoveringExpanderList\n"));
5240   if (!DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
5241   {
5242     ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
5243     while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
5244     {
5245       tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
5246       if (tempExpander == agNULL)
5247       {
5248         DM_DBG1(("dmCleanAllExp: tempExpander is NULL!!!\n"));
5249         return;
5250       }    
5251       DM_DBG3(("dmCleanAllExp: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
5252       DM_DBG3(("dmCleanAllExp: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
5253       DM_DBG3(("dmCleanAllExp: exp id %d\n", tempExpander->id));
5254       
5255       oneExpander = dmExpMainListFind(dmRoot, 
5256                                       tmpOnePortContext, 
5257                                       tempExpander->dmDevice->SASAddressID.sasAddressHi, 
5258                                       tempExpander->dmDevice->SASAddressID.sasAddressLo);      
5259       if (oneExpander == agNULL)
5260       {      
5261         DM_DBG3(("dmCleanAllExp: moving\n"));
5262         DM_DBG3(("dmCleanAllExp: moving, exp id %d\n", tempExpander->id));
5263         /* putting back to the free pool */
5264         tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5265         DMLIST_DEQUEUE_THIS(&(tempExpander->linkNode));
5266 //      DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->freeExpanderList));
5267         DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->mainExpanderList));
5268
5269         if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
5270         {
5271           tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5272           break;
5273         }
5274         else
5275         {
5276           tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);   
5277         }
5278         ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
5279       }
5280       else
5281       {
5282         DM_DBG3(("dmCleanAllExp: in mainExpanderList; skippig\n"));              
5283         ExpanderList =  ExpanderList->flink;    
5284       }                  
5285     }
5286   }
5287   else
5288   {
5289     DM_DBG3(("dmCleanAllExp: empty discoveringExpanderList\n")); 
5290   }
5291   
5292   /* reset discoveringExpanderList */
5293   DMLIST_INIT_HDR(&(tmpOnePortContext->discovery.discoveringExpanderList));    
5294
5295   /* clean up UpdiscoveringExpanderList*/
5296   DM_DBG3(("dmCleanAllExp: clean UpdiscoveringExpanderList\n"));
5297   if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList)))
5298   {
5299     DM_DBG3(("dmCleanAllExp: empty UpdiscoveringExpanderList\n"));
5300     return;
5301   }
5302   ExpanderList = tmpOnePortContext->discovery.UpdiscoveringExpanderList.flink;
5303   while (ExpanderList != &(tmpOnePortContext->discovery.UpdiscoveringExpanderList))
5304   {
5305     tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, upNode, ExpanderList);
5306     if (tempExpander == agNULL)
5307     {
5308       DM_DBG1(("dmCleanAllExp: tempExpander is NULL!!!\n"));
5309       return;
5310     }    
5311     DM_DBG3(("dmCleanAllExp: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
5312     DM_DBG3(("dmCleanAllExp: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
5313     DM_DBG3(("dmCleanAllExp: exp id %d\n", tempExpander->id));
5314     oneExpander = dmExpMainListFind(dmRoot, 
5315                                     tmpOnePortContext, 
5316                                     tempExpander->dmDevice->SASAddressID.sasAddressHi, 
5317                                     tempExpander->dmDevice->SASAddressID.sasAddressLo);      
5318     if (oneExpander == agNULL)
5319     {      
5320       DM_DBG3(("dmCleanAllExp: moving\n"));
5321       DM_DBG3(("dmCleanAllExp: moving exp id %d\n", tempExpander->id));
5322       tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5323       DMLIST_DEQUEUE_THIS(&(tempExpander->upNode));
5324       DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->mainExpanderList));
5325
5326       if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList)))
5327       {
5328         tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5329         break;
5330       }
5331       else
5332       {
5333         tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);   
5334       }
5335       ExpanderList = tmpOnePortContext->discovery.UpdiscoveringExpanderList.flink;
5336     }
5337     else
5338     {
5339       DM_DBG3(("dmCleanAllExp: in mainExpanderList; skippig\n"));              
5340       ExpanderList =  ExpanderList->flink;    
5341     }                
5342   }
5343   
5344   /* reset UpdiscoveringExpanderList */
5345   DMLIST_INIT_HDR(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList));    
5346   
5347   DM_DBG3(("dmCleanAllExp: after all clean up\n")); 
5348   dmDumpAllFreeExp(dmRoot);
5349   
5350   return;
5351 }
5352
5353 osGLOBAL void
5354 dmInternalRemovals(
5355                    dmRoot_t                 *dmRoot,
5356                    dmIntPortContext_t       *onePortContext
5357                    )
5358 {
5359   dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5360   dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5361   dmDeviceData_t            *oneDeviceData = agNULL;
5362   dmList_t                  *DeviceListList;
5363   
5364   
5365   DM_DBG3(("dmInternalRemovals: start\n"));
5366   tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
5367   if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
5368   {
5369     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5370     DM_DBG3(("dmInternalRemovals: empty device list\n"));
5371     return;
5372   }
5373   else
5374   {
5375     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5376   }
5377   
5378   DeviceListList = dmAllShared->MainDeviceList.flink;
5379   while (DeviceListList != &(dmAllShared->MainDeviceList))
5380   {
5381     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
5382     if (oneDeviceData == agNULL)
5383     {
5384       DM_DBG1(("dmInternalRemovals: oneDeviceData is NULL!!!\n"));
5385       return;
5386     }    
5387     DM_DBG3(("dmInternalRemovals: loop did %d\n", oneDeviceData->id));
5388     DM_DBG3(("dmInternalRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
5389     DM_DBG3(("dmInternalRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
5390     DM_DBG3(("dmInternalRemovals: valid %d\n", oneDeviceData->valid));    
5391     DM_DBG3(("dmInternalRemovals: valid2 %d\n", oneDeviceData->valid2));    
5392     DM_DBG3(("dmInternalRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));    
5393     if ( oneDeviceData->dmPortContext == onePortContext)
5394     {
5395       DM_DBG3(("dmInternalRemovals: right portcontext pid %d\n", onePortContext->id));
5396       if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START)
5397       {
5398         DM_DBG3(("dmInternalRemovals: incremental discovery\n"));
5399         oneDeviceData->valid2 = agFALSE;
5400       }
5401       else
5402       {
5403         DM_DBG3(("dmInternalRemovals: full discovery\n"));
5404         oneDeviceData->valid = agFALSE;
5405       }
5406       DeviceListList = DeviceListList->flink;
5407     }    
5408     else
5409     {
5410       if (oneDeviceData->dmPortContext != agNULL)
5411       {
5412         DM_DBG3(("dmInternalRemovals: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id));
5413       }
5414       else
5415       {
5416         DM_DBG3(("dmInternalRemovals: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
5417       }
5418       DeviceListList = DeviceListList->flink;
5419     }  
5420   }
5421   
5422   
5423   return;
5424 }
5425
5426 osGLOBAL void
5427 dmDiscoveryResetProcessed(
5428                           dmRoot_t                 *dmRoot,
5429                           dmIntPortContext_t       *onePortContext
5430                          )
5431 {
5432   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5433   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5434   dmDeviceData_t    *oneDeviceData = agNULL;
5435   dmList_t          *DeviceListList;
5436   
5437   DM_DBG3(("dmDiscoveryResetProcessed: start\n"));
5438   
5439   /* reinitialize the device data belonging to this portcontext */
5440   DeviceListList = dmAllShared->MainDeviceList.flink;
5441   while (DeviceListList != &(dmAllShared->MainDeviceList))
5442   {
5443     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
5444     if (oneDeviceData == agNULL)
5445     {
5446       DM_DBG1(("dmDiscoveryResetProcessed: oneDeviceData is NULL!!!\n"));
5447       return;
5448     }    
5449     DM_DBG3(("dmDiscoveryResetProcessed: loop did %d\n", oneDeviceData->id));
5450     if (oneDeviceData->dmPortContext == onePortContext)
5451     {
5452       DM_DBG3(("dmDiscoveryResetProcessed: resetting procssed flag\n"));
5453       oneDeviceData->processed = agFALSE;
5454     }
5455     DeviceListList = DeviceListList->flink;  
5456   }
5457   
5458   return;
5459 }                        
5460
5461 /*
5462   calls
5463 osGLOBAL void 
5464 tddmDiscoverCB(
5465                dmRoot_t                 *dmRoot,
5466                dmPortContext_t          *dmPortContext,
5467                bit32                    eventStatus
5468               )
5469   
5470 */
5471 osGLOBAL void
5472 dmDiscoverDone(
5473                dmRoot_t                 *dmRoot,
5474                dmIntPortContext_t       *onePortContext,
5475                bit32                    flag
5476               )
5477 {
5478  
5479   DM_DBG3(("dmDiscoverDone: start\n"));
5480   DM_DBG3(("dmDiscoverDone: pid %d\n", onePortContext->id));
5481
5482   /* Set discovery status */
5483   onePortContext->discovery.status = DISCOVERY_SAS_DONE;                
5484   
5485  
5486   /* clean up expanders data strucures; move to free exp when device is cleaned */
5487   dmCleanAllExp(dmRoot, onePortContext);
5488   
5489   dmDumpAllMainExp(dmRoot, onePortContext);
5490
5491   dmDiscoveryResetProcessed(dmRoot, onePortContext);
5492   
5493   dmDiscoveryDumpMCN(dmRoot, onePortContext);
5494   
5495   if (onePortContext->discovery.SeenBC == agTRUE)
5496   {
5497     DM_DBG3(("dmDiscoverDone: broadcast change; discover again\n"));
5498     dmDiscoveryResetMCN(dmRoot, onePortContext);
5499     
5500     dmInternalRemovals(dmRoot, onePortContext);
5501
5502     /* processed broadcast change */
5503     onePortContext->discovery.SeenBC = agFALSE;
5504     if (onePortContext->discovery.ResetTriggerred == agTRUE)
5505     {
5506       DM_DBG3(("dmDiscoverDone: dmBCTimer\n"));
5507       dmBCTimer(dmRoot, onePortContext);
5508     }
5509     else
5510     {
5511
5512       dmIncrementalDiscover(dmRoot, onePortContext, agTRUE);              
5513     }
5514   }
5515   else
5516   {
5517     onePortContext->DiscoveryState = DM_DSTATE_COMPLETED;
5518   
5519     if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
5520     { 
5521       if (flag == DM_RC_SUCCESS)
5522       {
5523
5524        dmResetReported(dmRoot,
5525                        onePortContext
5526                       );
5527                       
5528        dmDiscoveryReportMCN(dmRoot,
5529                             onePortContext
5530                            );
5531                                               
5532
5533        /* call tddmDiscoverCB() */
5534        tddmDiscoverCB(
5535                        dmRoot,
5536                        onePortContext->dmPortContext,
5537                        dmDiscCompleted
5538                       );
5539       }
5540       else if (flag != DM_RC_SUCCESS || onePortContext->discovery.DeferredError == agTRUE)
5541       {
5542         onePortContext->DiscoveryState = DM_DSTATE_COMPLETED_WITH_FAILURE;
5543         DM_DBG1(("dmDiscoverDone: Error; clean up!!!\n"));
5544         
5545         dmDiscoveryInvalidateDevices(dmRoot,
5546                                      onePortContext
5547                                     );
5548                         
5549         tddmDiscoverCB(
5550                        dmRoot,
5551                        onePortContext->dmPortContext,
5552                        dmDiscFailed
5553                       );
5554       }
5555     }
5556     else
5557     {
5558       if (flag == DM_RC_SUCCESS)
5559       { 
5560         dmReportChanges(dmRoot,
5561                         onePortContext
5562                        );
5563         dmDiscoveryReportMCN(dmRoot,
5564                              onePortContext
5565                             );
5566         tddmDiscoverCB(
5567                        dmRoot,
5568                        onePortContext->dmPortContext,
5569                        dmDiscCompleted
5570                       );
5571       }
5572       else if (flag != DM_RC_SUCCESS || onePortContext->discovery.DeferredError == agTRUE)
5573       {
5574         onePortContext->DiscoveryState = DM_DSTATE_COMPLETED_WITH_FAILURE;
5575         dmDiscoveryInvalidateDevices(dmRoot,
5576                                      onePortContext
5577                                     );
5578                 
5579         tddmDiscoverCB(
5580                        dmRoot,
5581                        onePortContext->dmPortContext,
5582                        dmDiscFailed
5583                       );
5584       }                        
5585     }
5586   }
5587   return;
5588 }
5589
5590 /* called by dmDiscoveryErrorRemovals() or dmReportRemovals() on discovery failure */
5591 osGLOBAL void
5592 dmSubReportRemovals(
5593                    dmRoot_t                  *dmRoot,
5594                    dmIntPortContext_t        *onePortContext,
5595                    dmDeviceData_t            *oneDeviceData,
5596                    bit32                     flag
5597                   )
5598 {
5599   dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
5600   DM_DBG3(("dmSubReportRemovals: start\n"));
5601   
5602   DM_DBG3(("dmSubReportRemovals: flag 0x%x\n", flag));
5603   if (flag == dmDeviceRemoval)
5604   {
5605     oneDeviceData->registered = agFALSE;
5606   }
5607   
5608   if (oneDeviceData->ExpDevice != agNULL)
5609   {
5610     DM_DBG3(("dmSubReportRemovals: attached expander case\n"));
5611     oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
5612     tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, flag);
5613   }
5614   else
5615   {
5616     DM_DBG3(("dmSubReportRemovals: NO attached expander case\n"));
5617     tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, flag);
5618   }
5619  
5620   
5621   /* this function is called at the end of discovery; reinitalizes oneDeviceData->reported */
5622   oneDeviceData->reported = agFALSE;
5623   return;
5624 }
5625
5626
5627 /* called by dmReportChanges() on discovery success */
5628 osGLOBAL void
5629 dmSubReportChanges(
5630                    dmRoot_t                  *dmRoot,
5631                    dmIntPortContext_t        *onePortContext,
5632                    dmDeviceData_t            *oneDeviceData,
5633                    bit32                     flag
5634                   )
5635 {
5636   dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
5637   DM_DBG3(("dmSubReportChanges: start\n"));
5638   
5639   DM_DBG3(("dmSubReportChanges: flag 0x%x\n", flag));
5640   if (flag == dmDeviceRemoval)
5641   {
5642     oneDeviceData->registered = agFALSE;
5643   }
5644   if (oneDeviceData->reported == agFALSE)
5645   {
5646     if (oneDeviceData->ExpDevice != agNULL)
5647     {
5648       DM_DBG3(("dmSubReportChanges: attached expander case\n"));
5649       oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
5650       tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, flag);
5651     }
5652     else
5653     {
5654       DM_DBG3(("dmSubReportChanges: NO attached expander case\n"));
5655       tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, flag);
5656     }
5657   }
5658   else
5659   {
5660     DM_DBG3(("dmSubReportChanges: skip; been reported\n"));  
5661   }
5662  
5663   
5664   /* this function is called at the end of discovery; reinitalizes oneDeviceData->reported */
5665   oneDeviceData->reported = agFALSE;
5666   return;
5667 }
5668
5669 /* 
5670  should add or remove be reported per device???
5671 */
5672 osGLOBAL void
5673 dmReportChanges(
5674                 dmRoot_t                  *dmRoot,
5675                 dmIntPortContext_t        *onePortContext
5676                )
5677 {
5678   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5679   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5680   dmDeviceData_t    *oneDeviceData = agNULL;
5681   dmList_t          *DeviceListList;
5682   bit32             added = agFALSE, removed = agFALSE;
5683 //  dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
5684   
5685   DM_DBG3(("dmReportChanges: start\n"));
5686   
5687   tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
5688   if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
5689   {
5690     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5691     DM_DBG3(("dmReportChanges: empty device list\n"));
5692     return;
5693   }
5694   else
5695   {
5696     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5697   }
5698   
5699   DeviceListList = dmAllShared->MainDeviceList.flink;
5700   while (DeviceListList != &(dmAllShared->MainDeviceList))
5701   {
5702     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
5703     if (oneDeviceData == agNULL)
5704     {
5705       DM_DBG1(("dmReportChanges: oneDeviceData is NULL!!!\n"));
5706       return;
5707     }    
5708     DM_DBG3(("dmReportChanges: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
5709     DM_DBG3(("dmReportChanges: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
5710     if ( oneDeviceData->dmPortContext == onePortContext)
5711     {
5712       DM_DBG3(("dmReportChanges: right portcontext\n"));
5713       if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi &&
5714           oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo      
5715          )
5716       {
5717         DM_DBG1(("dmReportChanges: keep, not reporting did 0x%x\n", oneDeviceData->id));
5718         oneDeviceData->valid = agTRUE;
5719         oneDeviceData->valid2 = agFALSE;
5720       }      
5721       else if ( (oneDeviceData->valid == agTRUE) && (oneDeviceData->valid2 == agTRUE) )
5722       {
5723         DM_DBG3(("dmReportChanges: same\n"));
5724         /* reset valid bit */
5725         oneDeviceData->valid = oneDeviceData->valid2;
5726         oneDeviceData->valid2 = agFALSE;      
5727         dmSubReportChanges(dmRoot, onePortContext, oneDeviceData, dmDeviceNoChange);
5728       }
5729       else if ( (oneDeviceData->valid == agTRUE) && (oneDeviceData->valid2 == agFALSE) )
5730       {
5731         DM_DBG3(("dmReportChanges: removed\n"));
5732         removed = agTRUE;
5733         /* reset valid bit */
5734         oneDeviceData->valid = oneDeviceData->valid2;
5735         oneDeviceData->valid2 = agFALSE;
5736       
5737         onePortContext->RegisteredDevNums--;
5738         dmSubReportChanges(dmRoot, onePortContext, oneDeviceData, dmDeviceRemoval);
5739       }
5740       else if ( (oneDeviceData->valid == agFALSE) && (oneDeviceData->valid2 == agTRUE) )
5741       {
5742         DM_DBG3(("dmReportChanges: added\n"));
5743         added = agTRUE;
5744         /* reset valid bit */      
5745         oneDeviceData->valid = oneDeviceData->valid2;
5746         oneDeviceData->valid2 = agFALSE;
5747         dmSubReportChanges(dmRoot, onePortContext, oneDeviceData, dmDeviceArrival);
5748       }
5749       else
5750       {
5751         DM_DBG3(("dmReportChanges: else\n"));
5752       }
5753     }
5754     else
5755     {
5756       DM_DBG3(("dmReportChanges: different portcontext\n"));
5757     }  
5758     DeviceListList = DeviceListList->flink;
5759   }
5760   /*
5761   osGLOBAL void 
5762 tddmReportDevice(
5763                  dmRoot_t               *dmRoot,
5764                  dmPortContext_t        *dmPortContext,
5765                  dmDeviceInfo_t         *dmDeviceInfo,
5766                  dmDeviceInfo_t         *dmExpDeviceInfo,
5767                  bit32                   flag
5768                  
5769                  )
5770
5771   */
5772   
5773   /* arrival or removal at once */
5774   if (added == agTRUE)
5775   {
5776     DM_DBG3(("dmReportChanges: added at the end\n"));
5777 #if 0  /* TBD */  
5778     ostiInitiatorEvent(
5779                          tiRoot,
5780                          onePortContext->tiPortalContext,
5781                          agNULL,
5782                          tiIntrEventTypeDeviceChange,
5783                          tiDeviceArrival,
5784                          agNULL
5785                          );
5786 #endif                   
5787   
5788   }
5789   if (removed == agTRUE)
5790   {
5791     DM_DBG3(("dmReportChanges: removed at the end\n"));
5792 #if 0  /* TBD */  
5793     ostiInitiatorEvent(
5794                        tiRoot,
5795                        onePortContext->tiPortalContext,
5796                        agNULL,
5797                        tiIntrEventTypeDeviceChange,
5798                        tiDeviceRemoval,
5799                        agNULL
5800                        );
5801 #endif  
5802   }
5803   
5804   if (onePortContext->discovery.forcedOK == agTRUE && added == agFALSE && removed == agFALSE)
5805   {
5806     DM_DBG3(("dmReportChanges: missed chance to report. forced to report OK\n"));
5807     onePortContext->discovery.forcedOK = agFALSE;
5808 #if 0  /* TBD */  
5809     ostiInitiatorEvent(
5810                        tiRoot,
5811                        onePortContext->tiPortalContext,
5812                        agNULL,
5813                        tiIntrEventTypeDiscovery, 
5814                        tiDiscOK, 
5815                        agNULL
5816                        );
5817 #endif                     
5818   }
5819   
5820   if (added == agFALSE && removed == agFALSE)
5821   {
5822     DM_DBG3(("dmReportChanges: the same\n"));
5823   }
5824   
5825   return;
5826 }
5827
5828 osGLOBAL void
5829 dmReportRemovals(
5830                  dmRoot_t                  *dmRoot,
5831                  dmIntPortContext_t        *onePortContext,
5832                  bit32                     flag
5833                 )
5834 {
5835   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5836   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5837   dmDeviceData_t    *oneDeviceData = agNULL;
5838   dmList_t          *DeviceListList;
5839   bit32             removed = agFALSE;
5840   
5841   DM_DBG1(("dmReportRemovals: start\n"));
5842   
5843   tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
5844   if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
5845   {
5846     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5847     DM_DBG3(("dmReportRemovals: empty device list\n"));
5848     return;
5849   }
5850   else
5851   {
5852     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5853   }
5854   
5855   DeviceListList = dmAllShared->MainDeviceList.flink;
5856   while (DeviceListList != &(dmAllShared->MainDeviceList))
5857   {
5858     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
5859     if (oneDeviceData == agNULL)
5860     {
5861       DM_DBG1(("dmReportRemovals: oneDeviceData is NULL!!!\n"));
5862       return;
5863     }    
5864     DM_DBG3(("dmReportRemovals: loop did %d\n", oneDeviceData->id));
5865     DM_DBG3(("dmReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
5866     DM_DBG3(("dmReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
5867     DM_DBG3(("dmReportRemovals: valid %d\n", oneDeviceData->valid));    
5868     DM_DBG3(("dmReportRemovals: valid2 %d\n", oneDeviceData->valid2));    
5869     DM_DBG3(("dmReportRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));    
5870     if ( oneDeviceData->dmPortContext == onePortContext)
5871     {
5872       DM_DBG3(("dmReportRemovals: right portcontext pid %d\n", onePortContext->id));
5873       if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi &&
5874           oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo      
5875          )
5876       {
5877         DM_DBG1(("dmReportRemovals: keeping\n"));
5878         oneDeviceData->valid = agTRUE;
5879         oneDeviceData->valid2 = agFALSE;
5880       }
5881       else if (oneDeviceData->valid == agTRUE)
5882       {    
5883         DM_DBG3(("dmReportRemovals: removing\n"));
5884        
5885         /* notify only reported devices to OS layer*/
5886         if ( DEVICE_IS_SSP_TARGET(oneDeviceData) || 
5887              DEVICE_IS_STP_TARGET(oneDeviceData) ||
5888              DEVICE_IS_SATA_DEVICE(oneDeviceData)
5889             )
5890         {
5891           removed = agTRUE;
5892         }
5893
5894         /* all targets except expanders */
5895         DM_DBG3(("dmReportRemovals: did %d\n", oneDeviceData->id));
5896         DM_DBG3(("dmReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
5897         DM_DBG3(("dmReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
5898         onePortContext->RegisteredDevNums--;
5899         dmSubReportRemovals(dmRoot, onePortContext, oneDeviceData, dmDeviceRemoval);
5900
5901         
5902         /* reset valid bit */
5903         oneDeviceData->valid = agFALSE;
5904         oneDeviceData->valid2 = agFALSE;
5905       
5906        
5907       }
5908       /* called by port invalid case */
5909       if (flag == agTRUE)
5910       {
5911         oneDeviceData->dmPortContext = agNULL;
5912       }
5913       DeviceListList = DeviceListList->flink;
5914     }    
5915     else
5916     {
5917       if (oneDeviceData->dmPortContext != agNULL)
5918       {
5919         DM_DBG3(("dmReportRemovals: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id));
5920       }
5921       else
5922       {
5923         DM_DBG3(("dmReportRemovals: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
5924       }
5925       DeviceListList = DeviceListList->flink;
5926     }  
5927   }
5928   
5929   if (removed == agTRUE)
5930   {
5931     DM_DBG3(("dmReportRemovals: removed at the end\n"));
5932 #if 0 /* TBD */      
5933       ostiInitiatorEvent(
5934                          tiRoot,
5935                          onePortContext->tiPortalContext,
5936                          agNULL,
5937                          tiIntrEventTypeDeviceChange,
5938                          tiDeviceRemoval,
5939                          agNULL
5940                          );
5941 #endif    
5942   }
5943   
5944   return;
5945 }
5946
5947 osGLOBAL void
5948 dmResetReported(
5949                 dmRoot_t                  *dmRoot,
5950                 dmIntPortContext_t        *onePortContext
5951                )
5952 {
5953   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5954   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5955   dmDeviceData_t    *oneDeviceData = agNULL;
5956   dmList_t          *DeviceListList;
5957   
5958   DM_DBG3(("dmResetReported: start\n"));
5959
5960   tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
5961   if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
5962   {
5963     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5964     DM_DBG3(("dmResetReported: empty device list\n"));
5965     return;
5966   }
5967   else
5968   {
5969     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5970   }
5971
5972   DeviceListList = dmAllShared->MainDeviceList.flink;
5973   while (DeviceListList != &(dmAllShared->MainDeviceList))
5974   {
5975     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
5976     if (oneDeviceData == agNULL)
5977     {
5978       DM_DBG1(("dmResetReported: oneDeviceData is NULL!!!\n"));
5979       return;
5980     }    
5981     DM_DBG3(("dmResetReported: loop did %d\n", oneDeviceData->id));
5982     DM_DBG3(("dmResetReported: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
5983     DM_DBG3(("dmResetReported: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
5984     DM_DBG3(("dmResetReported: valid %d\n", oneDeviceData->valid));    
5985     DM_DBG3(("dmResetReported: valid2 %d\n", oneDeviceData->valid2));    
5986     DM_DBG3(("dmResetReported: directlyAttached %d\n", oneDeviceData->directlyAttached));    
5987     if ( oneDeviceData->dmPortContext == onePortContext)
5988     {
5989       DM_DBG3(("dmResetReported: right portcontext pid %d\n", onePortContext->id));
5990       oneDeviceData->reported = agFALSE;
5991       DeviceListList = DeviceListList->flink;
5992     }    
5993     else
5994     {
5995       if (oneDeviceData->dmPortContext != agNULL)
5996       {
5997         DM_DBG3(("dmResetReported: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id));
5998       }
5999       else
6000       {
6001         DM_DBG3(("dmResetReported: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
6002       }
6003       DeviceListList = DeviceListList->flink;
6004     }  
6005   }
6006   
6007   return;
6008 }              
6009
6010 /* called on discover failure */
6011 osGLOBAL void
6012 dmDiscoveryInvalidateDevices(
6013                              dmRoot_t                  *dmRoot,
6014                              dmIntPortContext_t        *onePortContext
6015                             )
6016 {
6017   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6018   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6019   dmDeviceData_t    *oneDeviceData = agNULL;
6020   dmList_t          *DeviceListList;
6021   
6022   DM_DBG1(("dmDiscoveryInvalidateDevices: start\n"));
6023   
6024   tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6025   if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
6026   {
6027     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6028     DM_DBG3(("dmDiscoveryInvalidateDevices: empty device list\n"));
6029     return;
6030   }
6031   else
6032   {
6033     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6034   }
6035   DeviceListList = dmAllShared->MainDeviceList.flink;
6036   while (DeviceListList != &(dmAllShared->MainDeviceList))
6037   {
6038     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6039     if (oneDeviceData == agNULL)
6040     {
6041       DM_DBG1(("dmDiscoveryInvalidateDevices: oneDeviceData is NULL!!!\n"));
6042       return;
6043     }    
6044     DM_DBG3(("dmDiscoveryInvalidateDevices: loop did %d\n", oneDeviceData->id));
6045     DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6046     DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6047     DM_DBG3(("dmDiscoveryInvalidateDevices: valid %d\n", oneDeviceData->valid));    
6048     DM_DBG3(("dmDiscoveryInvalidateDevices: valid2 %d\n", oneDeviceData->valid2));    
6049     DM_DBG3(("dmDiscoveryInvalidateDevices: directlyAttached %d\n", oneDeviceData->directlyAttached));    
6050     if ( oneDeviceData->dmPortContext == onePortContext)
6051     {
6052       DM_DBG3(("dmDiscoveryInvalidateDevices: right portcontext pid %d\n", onePortContext->id));
6053       if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi &&
6054           oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo      
6055          )
6056       {
6057         DM_DBG1(("dmDiscoveryInvalidateDevices: keeping\n"));
6058         oneDeviceData->valid = agTRUE;
6059         oneDeviceData->valid2 = agFALSE;
6060       }
6061       else
6062       {            
6063         oneDeviceData->valid = agFALSE;
6064         oneDeviceData->valid2 = agFALSE;
6065         oneDeviceData->registered = agFALSE;
6066         oneDeviceData->reported = agFALSE;
6067         /* all targets other than expanders */
6068         DM_DBG3(("dmDiscoveryInvalidateDevices: did %d\n", oneDeviceData->id));
6069         DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6070         DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6071         onePortContext->RegisteredDevNums--;
6072       }
6073       DeviceListList = DeviceListList->flink;
6074     }    
6075     else
6076     {
6077       if (oneDeviceData->dmPortContext != agNULL)
6078       {
6079         DM_DBG3(("dmDiscoveryInvalidateDevices: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id));
6080       }
6081       else
6082       {
6083         DM_DBG3(("dmDiscoveryInvalidateDevices: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
6084       }
6085       DeviceListList = DeviceListList->flink;
6086     }  
6087   }
6088   
6089   return;
6090 }
6091
6092
6093 /* 
6094  should DM report the device removal to TDM on an error case?
6095  or
6096  DM simply removes the devices
6097  For now, the second option.
6098 */
6099 osGLOBAL void
6100 dmDiscoveryErrorRemovals(
6101                          dmRoot_t                  *dmRoot,
6102                          dmIntPortContext_t        *onePortContext
6103                         )
6104 {
6105   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6106   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6107   dmDeviceData_t    *oneDeviceData = agNULL;
6108   dmList_t          *DeviceListList;
6109   
6110   DM_DBG1(("dmDiscoveryErrorRemovals: start\n"));
6111   
6112   tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6113   if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
6114   {
6115     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6116     DM_DBG3(("dmDiscoveryErrorRemovals: empty device list\n"));
6117     return;
6118   }
6119   else
6120   {
6121     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6122   }
6123   DeviceListList = dmAllShared->MainDeviceList.flink;
6124   while (DeviceListList != &(dmAllShared->MainDeviceList))
6125   {
6126     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6127     if (oneDeviceData == agNULL)
6128     {
6129       DM_DBG1(("dmDiscoveryErrorRemovals: oneDeviceData is NULL!!!\n"));
6130       return;
6131     }    
6132     DM_DBG3(("dmDiscoveryErrorRemovals: loop did %d\n", oneDeviceData->id));
6133     DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6134     DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6135     DM_DBG3(("dmDiscoveryErrorRemovals: valid %d\n", oneDeviceData->valid));    
6136     DM_DBG3(("dmDiscoveryErrorRemovals: valid2 %d\n", oneDeviceData->valid2));    
6137     DM_DBG3(("dmDiscoveryErrorRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));    
6138     if ( oneDeviceData->dmPortContext == onePortContext)
6139     {
6140       DM_DBG3(("dmDiscoveryErrorRemovals: right portcontext pid %d\n", onePortContext->id));
6141       if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi &&
6142           oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo      
6143          )
6144       {
6145         DM_DBG1(("dmDiscoveryErrorRemovals: keeping\n"));
6146         oneDeviceData->valid = agTRUE;
6147         oneDeviceData->valid2 = agFALSE;
6148       }
6149       else
6150       {            
6151         oneDeviceData->valid = agFALSE;
6152         oneDeviceData->valid2 = agFALSE;
6153       
6154         /* all targets other than expanders */
6155         DM_DBG3(("dmDiscoveryErrorRemovals: did %d\n", oneDeviceData->id));
6156         DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6157         DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6158         onePortContext->RegisteredDevNums--;
6159         dmSubReportRemovals(dmRoot, onePortContext, oneDeviceData, dmDeviceRemoval);
6160      
6161       }
6162       DeviceListList = DeviceListList->flink;
6163     }    
6164     else
6165     {
6166       if (oneDeviceData->dmPortContext != agNULL)
6167       {
6168         DM_DBG3(("dmDiscoveryErrorRemovals: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id));
6169       }
6170       else
6171       {
6172         DM_DBG3(("dmDiscoveryErrorRemovals: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
6173       }
6174       DeviceListList = DeviceListList->flink;
6175     }  
6176   }
6177   
6178   return;
6179 }
6180
6181 /* move from dmAllShared->mainExpanderList to dmAllShared->freeExpanderList */
6182 osGLOBAL void
6183 dmDiscoveryExpanderCleanUp(
6184                            dmRoot_t                  *dmRoot,
6185                            dmIntPortContext_t        *onePortContext
6186                           )
6187 {
6188   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6189   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6190   dmExpander_t      *oneExpander = agNULL;
6191   dmList_t          *ExpanderList = agNULL;
6192   dmDeviceData_t    *oneDeviceData = agNULL;
6193   
6194   DM_DBG3(("dmDiscoveryExpanderCleanUp: start\n"));
6195   /*
6196     be sure to call
6197     osGLOBAL void
6198     dmExpanderDeviceDataReInit(
6199                            dmRoot_t         *dmRoot, 
6200                            dmExpander_t     *oneExpander
6201                           );
6202
6203   */
6204   
6205   tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
6206   if (!DMLIST_EMPTY(&(dmAllShared->mainExpanderList)))
6207   {
6208     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6209     ExpanderList = dmAllShared->mainExpanderList.flink;
6210     while (ExpanderList != &(dmAllShared->mainExpanderList))
6211     {
6212       oneExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
6213       if (oneExpander == agNULL)
6214       {
6215         DM_DBG1(("dmDiscoveryExpanderCleanUp: oneExpander is NULL!!!\n"));
6216         return;
6217       }    
6218       oneDeviceData = oneExpander->dmDevice;
6219       DM_DBG3(("dmDiscoveryExpanderCleanUp: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6220       DM_DBG3(("dmDiscoveryExpanderCleanUp: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6221       if ( oneDeviceData->dmPortContext == onePortContext)
6222       {
6223         dmExpanderDeviceDataReInit(dmRoot, oneExpander);
6224         tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
6225         DMLIST_DEQUEUE_THIS(&(oneExpander->linkNode));
6226         DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(dmAllShared->freeExpanderList));
6227         
6228         if (DMLIST_EMPTY(&(dmAllShared->mainExpanderList)))
6229         {
6230           tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6231           break;
6232         }
6233         else
6234         {
6235           tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);   
6236         }
6237         ExpanderList = dmAllShared->mainExpanderList.flink;
6238       }
6239       else
6240       {
6241         ExpanderList = ExpanderList->flink;
6242       }   
6243     }
6244   }
6245   else
6246   {
6247     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6248     DM_DBG3(("dmDiscoveryExpanderCleanUp: empty mainExpanderList\n")); 
6249   }  
6250   return;
6251   
6252 }                       
6253
6254
6255 /* moves all devices from dmAllShared->MainDeviceList to dmAllShared->FreeDeviceList */
6256 osGLOBAL void
6257 dmDiscoveryDeviceCleanUp(
6258                          dmRoot_t                  *dmRoot,
6259                          dmIntPortContext_t        *onePortContext
6260                         )
6261 {
6262   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6263   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6264   dmDeviceData_t    *oneDeviceData = agNULL;
6265   dmList_t          *DeviceListList;
6266   
6267   DM_DBG3(("dmDiscoveryDeviceCleanUp: start\n"));
6268   
6269   tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6270   if (!DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
6271   {
6272     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6273     DeviceListList = dmAllShared->MainDeviceList.flink;
6274     while (DeviceListList != &(dmAllShared->MainDeviceList))
6275     {
6276       oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6277       if (oneDeviceData == agNULL)
6278       {
6279         DM_DBG1(("dmDiscoveryDeviceCleanUp: oneDeviceData is NULL!!!\n"));
6280         return;
6281       }    
6282       DM_DBG3(("dmDiscoveryDeviceCleanUp: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6283       DM_DBG3(("dmDiscoveryDeviceCleanUp: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6284       if ( oneDeviceData->dmPortContext == onePortContext)
6285       {
6286         dmDeviceDataReInit(dmRoot, oneDeviceData);
6287         tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6288         DMLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
6289         DMLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(dmAllShared->FreeDeviceList));
6290         
6291         if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
6292         {
6293           tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6294           break;
6295         }
6296         else
6297         {
6298           tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);   
6299         }
6300         onePortContext->RegisteredDevNums--;
6301         DeviceListList = dmAllShared->MainDeviceList.flink;
6302       }
6303       else
6304       {
6305         DeviceListList = DeviceListList->flink;
6306       }   
6307     }
6308   }
6309   else
6310   {
6311     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6312     DM_DBG3(("dmDiscoveryDeviceCleanUp: empty MainDeviceList\n")); 
6313   }  
6314   return;
6315 }                       
6316                         
6317
6318
6319 osGLOBAL void
6320 dmDumpAllExp(
6321              dmRoot_t                  *dmRoot,
6322              dmIntPortContext_t        *onePortContext,
6323              dmExpander_t              *oneExpander
6324             )
6325 {
6326   DM_DBG3(("dmDumpAllExp: start\n"));
6327   return;
6328 }
6329
6330
6331 osGLOBAL void
6332 dmDumpAllUpExp(
6333                dmRoot_t                  *dmRoot,
6334                dmIntPortContext_t        *onePortContext,
6335                dmExpander_t              *oneExpander
6336               )
6337 {
6338   DM_DBG3(("dmDumpAllUpExp: start\n"));
6339   return;
6340 }
6341                                     
6342 osGLOBAL void
6343 dmDumpAllFreeExp(
6344                  dmRoot_t                  *dmRoot
6345                 )
6346 {
6347   DM_DBG3(("dmDumpAllFreeExp: start\n"));
6348   return;
6349 }
6350
6351 osGLOBAL void
6352 dmDumpAllMainExp(
6353                  dmRoot_t                 *dmRoot,
6354                  dmIntPortContext_t       *onePortContext
6355                 )
6356 {
6357   dmIntRoot_t        *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6358   dmIntContext_t     *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6359   dmList_t           *ExpanderList;
6360   dmExpander_t       *tempExpander;
6361   
6362   DM_DBG3(("dmDumpAllMainExp: start\n"));
6363   
6364   tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
6365   if (DMLIST_EMPTY(&(dmAllShared->mainExpanderList)))
6366   {
6367     DM_DBG3(("dmDumpAllMainExp: empty discoveringExpanderList\n"));
6368     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6369     return;
6370   }
6371   else
6372   {
6373     tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6374   }
6375   
6376   ExpanderList = dmAllShared->mainExpanderList.flink;
6377   while (ExpanderList != &(dmAllShared->mainExpanderList))
6378   {
6379     tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
6380     if (tempExpander == agNULL)
6381     {
6382       DM_DBG1(("dmDumpAllMainExp: tempExpander is NULL!!!\n"));
6383       return;
6384     }    
6385     DM_DBG3(("dmDumpAllMainExp: expander id %d\n", tempExpander->id));
6386     DM_DBG3(("dmDumpAllMainExp: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
6387     DM_DBG3(("dmDumpAllMainExp: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
6388     if ((tempExpander->dmDevice->dmPortContext == onePortContext)
6389        )
6390     {
6391       DM_DBG3(("dmDumpAllMainExp: found expander id %d\n", tempExpander->id));
6392       DM_DBG3(("dmDumpAllMainExp: found exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
6393       DM_DBG3(("dmDumpAllMainExp: found exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
6394     }           
6395     ExpanderList = ExpanderList->flink;
6396   }
6397   return;
6398 }
6399
6400
6401 osGLOBAL void
6402 dmDumpAllMainDevice(
6403                  dmRoot_t                 *dmRoot,
6404                  dmIntPortContext_t       *onePortContext
6405                 )
6406 {
6407   dmIntRoot_t        *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6408   dmIntContext_t     *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6409   dmDeviceData_t     *oneDeviceData = agNULL;
6410   dmList_t           *DeviceListList;
6411   bit32              total = 0, port_total = 0;
6412   
6413   DM_DBG3(("dmDumpAllMainDevice: start\n"));
6414   
6415   tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6416   if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
6417   {
6418     DM_DBG3(("dmDumpAllMainDevice: empty discoveringExpanderList\n"));
6419     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6420     return;
6421   }
6422   else
6423   {
6424     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6425   }
6426   
6427   DeviceListList = dmAllShared->MainDeviceList.flink;
6428   while (DeviceListList != &(dmAllShared->MainDeviceList))
6429   {
6430     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6431     if (oneDeviceData == agNULL)
6432     {
6433       DM_DBG3(("dmDumpAllMainDevice: oneDeviceData is NULL!!!\n"));
6434       return;
6435     }    
6436     DM_DBG3(("dmDumpAllMainDevice: oneDeviceData id %d\n", oneDeviceData->id));
6437     DM_DBG3(("dmDumpAllMainDevice: addrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
6438     DM_DBG3(("dmDumpAllMainDevice: addrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
6439     total++;
6440     if ((oneDeviceData->dmPortContext == onePortContext)
6441        )
6442     {
6443       DM_DBG3(("dmDumpAllMainDevice: found oneDeviceData id %d\n", oneDeviceData->id));
6444       DM_DBG3(("dmDumpAllMainDevice: found addrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
6445       DM_DBG3(("dmDumpAllMainDevice: found addrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
6446       port_total++;
6447     }           
6448     DeviceListList = DeviceListList->flink;
6449   }
6450   DM_DBG3(("dmDumpAllMainDevice: total %d port_totaol %d\n", total, port_total));
6451   
6452   return;
6453 }
6454
6455
6456
6457 osGLOBAL dmDeviceData_t *
6458 dmAddSASToSharedcontext(
6459                          dmRoot_t              *dmRoot,
6460                          dmIntPortContext_t    *onePortContext,
6461                          dmSASSubID_t          *dmSASSubID,
6462                          dmDeviceData_t        *oneExpDeviceData,
6463                          bit8                   phyID
6464                         )
6465 {
6466   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6467   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6468   dmDeviceData_t    *oneDeviceData = agNULL;
6469   dmList_t          *DeviceListList;
6470   bit32             new_device = agTRUE;
6471   
6472   
6473   DM_DBG3(("dmAddSASToSharedcontext: start\n"));
6474   DM_DBG3(("dmAddSASToSharedcontext: oneportContext ID %d\n", onePortContext->id));
6475   
6476   if (oneExpDeviceData != agNULL)
6477   {
6478     DM_DBG3(("dmAddSASToSharedcontext: oneExpDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
6479     oneExpDeviceData->SASAddressID.sasAddressHi, oneExpDeviceData->SASAddressID.sasAddressLo));       
6480   }
6481   else
6482   {
6483     DM_DBG3(("dmAddSASToSharedcontext: oneExpDeviceData is NULL\n"));
6484   }        
6485   /* find a device's existence */
6486   DeviceListList = dmAllShared->MainDeviceList.flink;
6487   while (DeviceListList != &(dmAllShared->MainDeviceList))
6488   {
6489     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6490     if (oneDeviceData == agNULL)
6491     {
6492       DM_DBG1(("dmAddSASToSharedcontext: oneDeviceData is NULL!!!\n"));
6493       return agNULL;
6494     }    
6495     if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) &&
6496         (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) &&
6497         (oneDeviceData->dmPortContext == onePortContext)
6498         )
6499     {
6500       DM_DBG3(("dmAddSASToSharedcontext: pid %d did %d\n", onePortContext->id, oneDeviceData->id));
6501       new_device = agFALSE;
6502       break;
6503     }
6504     DeviceListList = DeviceListList->flink;
6505   }
6506   
6507   /* new device */
6508   if (new_device == agTRUE)
6509   {
6510     DM_DBG3(("dmAddSASToSharedcontext: new device\n"));
6511     DM_DBG3(("dmAddSASToSharedcontext: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
6512     dmSASSubID->sasAddressHi, dmSASSubID->sasAddressLo));         
6513     tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6514     if (!DMLIST_NOT_EMPTY(&(dmAllShared->FreeDeviceList)))
6515     {
6516       tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6517       DM_DBG1(("dmAddSASToSharedcontext: empty DeviceData FreeLink\n"));
6518       dmDumpAllMainDevice(dmRoot, onePortContext); 
6519       return agNULL;
6520     }
6521       
6522     DMLIST_DEQUEUE_FROM_HEAD(&DeviceListList, &(dmAllShared->FreeDeviceList));
6523     tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6524     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, FreeLink, DeviceListList);
6525
6526     if (oneDeviceData != agNULL)
6527     {
6528       DM_DBG3(("dmAddSASToSharedcontext: oneDeviceData %p pid %d did %d\n", oneDeviceData, onePortContext->id, oneDeviceData->id));
6529
6530       onePortContext->Count++;
6531       oneDeviceData->dmRoot = dmRoot;
6532       /* saving sas address */
6533       oneDeviceData->SASAddressID.sasAddressLo = dmSASSubID->sasAddressLo;
6534       oneDeviceData->SASAddressID.sasAddressHi = dmSASSubID->sasAddressHi;
6535       oneDeviceData->initiator_ssp_stp_smp = dmSASSubID->initiator_ssp_stp_smp;
6536       oneDeviceData->target_ssp_stp_smp = dmSASSubID->target_ssp_stp_smp;
6537       oneDeviceData->dmPortContext = onePortContext;
6538       /* handles both SAS target and STP-target, SATA-device */
6539       if (!DEVICE_IS_SATA_DEVICE(oneDeviceData) && !DEVICE_IS_STP_TARGET(oneDeviceData))
6540       {
6541         oneDeviceData->DeviceType = DM_SAS_DEVICE;
6542       }
6543       else
6544       {
6545         oneDeviceData->DeviceType = DM_SATA_DEVICE;
6546       }
6547
6548       if (oneExpDeviceData != agNULL)
6549       {
6550         oneDeviceData->ExpDevice = oneExpDeviceData;
6551       }      
6552     
6553       /* set phyID only when it has initial value of 0xFF */
6554       if (oneDeviceData->phyID == 0xFF)
6555       {
6556         oneDeviceData->phyID = phyID;
6557       }
6558       /* incremental discovery */
6559       /* add device to incremental-related link. Report using this link 
6560          when incremental discovery is done */
6561       if (onePortContext->DiscoveryState == DM_DSTATE_NOT_STARTED)
6562       {
6563         DM_DBG3(("dmAddSASToSharedcontext: DM_DSTATE_NOT_STARTED\n"));
6564         DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6565         DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6566         oneDeviceData->valid = agTRUE;
6567       }
6568       else
6569       {
6570         if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START)
6571         {
6572           DM_DBG3(("dmAddSASToSharedcontext: incremental discovery\n"));
6573           DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6574           DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6575           oneDeviceData->valid2 = agTRUE;
6576         }
6577         else
6578         {
6579           DM_DBG3(("dmAddSASToSharedcontext: full discovery\n"));
6580           DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6581           DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6582          oneDeviceData->valid = agTRUE;
6583         }
6584       }
6585       /* add the devicedata to the portcontext */    
6586       tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6587       DMLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->MainLink), &(dmAllShared->MainDeviceList));
6588       tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6589       DM_DBG3(("dmAddSASToSharedcontext: one case pid %d did %d \n", onePortContext->id, oneDeviceData->id));
6590       DM_DBG3(("dmAddSASToSharedcontext: new case pid %d did %d phyID %d\n", onePortContext->id, oneDeviceData->id, oneDeviceData->phyID));
6591       }
6592   }
6593   else /* old device */
6594   {
6595     DM_DBG3(("dmAddSASToSharedcontext: old device\n"));
6596     DM_DBG3(("dmAddSASToSharedcontext: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
6597     DM_DBG3(("dmAddSASToSharedcontext: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", 
6598     dmSASSubID->sasAddressHi, dmSASSubID->sasAddressLo));         
6599
6600     oneDeviceData->dmRoot = dmRoot;
6601     /* saving sas address */
6602     oneDeviceData->SASAddressID.sasAddressLo = dmSASSubID->sasAddressLo;
6603     oneDeviceData->SASAddressID.sasAddressHi = dmSASSubID->sasAddressHi;
6604     oneDeviceData->initiator_ssp_stp_smp = dmSASSubID->initiator_ssp_stp_smp;
6605     oneDeviceData->target_ssp_stp_smp = dmSASSubID->target_ssp_stp_smp;
6606     oneDeviceData->dmPortContext = onePortContext;
6607     /* handles both SAS target and STP-target, SATA-device */
6608     if (!DEVICE_IS_SATA_DEVICE(oneDeviceData) && !DEVICE_IS_STP_TARGET(oneDeviceData))
6609     {
6610       oneDeviceData->DeviceType = DM_SAS_DEVICE;
6611     }
6612     else
6613     {
6614       oneDeviceData->DeviceType = DM_SATA_DEVICE;
6615     }
6616     
6617     if (oneExpDeviceData != agNULL)
6618     {
6619       oneDeviceData->ExpDevice = oneExpDeviceData;
6620     }      
6621     
6622     /* set phyID only when it has initial value of 0xFF */
6623     if (oneDeviceData->phyID == 0xFF)
6624     {
6625       oneDeviceData->phyID = phyID;
6626     }
6627     
6628     if (onePortContext->DiscoveryState == DM_DSTATE_NOT_STARTED)
6629     {
6630       DM_DBG3(("dmAddSASToSharedcontext: DM_DSTATE_NOT_STARTED\n"));
6631       DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6632       DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6633       oneDeviceData->valid = agTRUE;
6634     }
6635     else
6636     {
6637       if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START)
6638       {
6639         DM_DBG3(("dmAddSASToSharedcontext: incremental discovery\n"));
6640         DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6641         DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6642         oneDeviceData->valid2 = agTRUE;
6643       }
6644       else
6645       {
6646         DM_DBG3(("dmAddSASToSharedcontext: full discovery\n"));
6647         DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6648         DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6649         oneDeviceData->valid = agTRUE;
6650       }
6651     }
6652     DM_DBG3(("dmAddSASToSharedcontext: old case pid %d did %d phyID %d\n", onePortContext->id, oneDeviceData->id, oneDeviceData->phyID));
6653      
6654   }
6655   return oneDeviceData;
6656 }
6657
6658 /* no checking of valid and valid2 */
6659 osGLOBAL dmDeviceData_t *
6660 dmDeviceFind(
6661              dmRoot_t            *dmRoot,
6662              dmIntPortContext_t  *onePortContext,
6663              bit32               sasAddrHi,
6664              bit32               sasAddrLo
6665             )
6666 {
6667   dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6668   dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6669   dmDeviceData_t            *oneDeviceData = agNULL;
6670   dmList_t                  *DeviceListList;
6671   bit32                     found = agFALSE;
6672   
6673   DM_DBG3(("dmDeviceFind: start\n"));
6674   /* find a device's existence */
6675   DeviceListList = dmAllShared->MainDeviceList.flink;
6676   
6677   while (DeviceListList != &(dmAllShared->MainDeviceList))
6678   {
6679     oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6680     if (oneDeviceData == agNULL)
6681     {
6682       DM_DBG1(("dmDeviceFind: oneDeviceData is NULL!!!\n"));
6683       return agNULL;
6684     }    
6685     if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) &&
6686         (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) &&
6687 //        (oneDeviceData->valid == agTRUE) &&
6688         (oneDeviceData->dmPortContext == onePortContext)
6689         )
6690     {
6691       DM_DBG3(("dmDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
6692       DM_DBG3(("dmDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));         
6693       DM_DBG3(("dmDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
6694       found = agTRUE;
6695       break;
6696     }
6697     DeviceListList = DeviceListList->flink;
6698   }
6699   
6700   if (found == agFALSE)
6701   {
6702     DM_DBG3(("dmDeviceFind: end returning NULL\n"));
6703     return agNULL;
6704   }
6705   else
6706   {
6707     DM_DBG3(("dmDeviceFind: end returning NOT NULL\n"));
6708     return oneDeviceData;
6709   }
6710   
6711 }           
6712
6713
6714 osGLOBAL void                          
6715 dmBCTimer(
6716           dmRoot_t                 *dmRoot,
6717           dmIntPortContext_t       *onePortContext
6718          )
6719 {
6720   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6721   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6722   dmDiscovery_t     *discovery;
6723   
6724   DM_DBG3(("dmBCTimer: start\n"));
6725   
6726   discovery = &(onePortContext->discovery);
6727   
6728   tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
6729   if (discovery->BCTimer.timerRunning == agTRUE)
6730   {
6731     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6732     dmKillTimer(
6733                 dmRoot,
6734                 &discovery->BCTimer
6735                );
6736   }
6737   else
6738   {
6739     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6740   }
6741   
6742   if (onePortContext->valid == agTRUE)
6743   {
6744     dmSetTimerRequest(
6745                       dmRoot,
6746                       &discovery->BCTimer,
6747                       BC_TIMER_VALUE/dmAllShared->usecsPerTick,
6748                       dmBCTimerCB,
6749                       onePortContext,
6750                       agNULL,
6751                       agNULL
6752                       );
6753   
6754     dmAddTimer(
6755                dmRoot,
6756                &dmAllShared->timerlist, 
6757                &discovery->BCTimer
6758               );
6759   
6760   }
6761   
6762   
6763   return;
6764 }        
6765
6766
6767 osGLOBAL void
6768 dmBCTimerCB(
6769               dmRoot_t    * dmRoot, 
6770               void        * timerData1,
6771               void        * timerData2,
6772               void        * timerData3
6773               )
6774 {
6775   dmIntPortContext_t        *onePortContext;
6776   dmDiscovery_t             *discovery;
6777   
6778   DM_DBG3(("dmBCTimerCB: start\n"));
6779   
6780   onePortContext = (dmIntPortContext_t *)timerData1;
6781   discovery = &(onePortContext->discovery);
6782
6783   tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
6784   if (discovery->BCTimer.timerRunning == agTRUE)
6785   {
6786     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6787     dmKillTimer(
6788                dmRoot,
6789                &discovery->BCTimer
6790                );
6791   }       
6792   else
6793   {
6794     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6795   }
6796   
6797   discovery->ResetTriggerred = agFALSE;
6798   
6799   if (onePortContext->valid == agTRUE)
6800   {
6801     dmDiscover(dmRoot,
6802                onePortContext->dmPortContext,
6803                DM_DISCOVERY_OPTION_INCREMENTAL_START
6804                );
6805   }  
6806   return;
6807 }             
6808
6809 /* discovery related SMP timers */
6810 osGLOBAL void
6811 dmDiscoverySMPTimer(dmRoot_t                 *dmRoot,
6812                     dmIntPortContext_t       *onePortContext,
6813                     bit32                    functionCode,
6814                     dmSMPRequestBody_t       *dmSMPRequestBody
6815                    )
6816 {
6817   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6818   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6819   dmDiscovery_t     *discovery;
6820   
6821   DM_DBG3(("dmDiscoverySMPTimer: start\n"));
6822   DM_DBG3(("dmDiscoverySMPTimer: pid %d SMPFn 0x%x\n", onePortContext->id, functionCode));
6823   
6824   /* start the SMP timer which works as SMP application timer */
6825   discovery = &(onePortContext->discovery);
6826   
6827   tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
6828   if (discovery->DiscoverySMPTimer.timerRunning == agTRUE)
6829   {
6830     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6831     dmKillTimer(
6832               dmRoot,
6833               &discovery->DiscoverySMPTimer
6834               );
6835   }
6836   else
6837   {
6838     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6839   }
6840   
6841   
6842   dmSetTimerRequest(
6843                     dmRoot,
6844                     &discovery->DiscoverySMPTimer,
6845                     SMP_TIMER_VALUE/dmAllShared->usecsPerTick,
6846                     dmDiscoverySMPTimerCB,
6847                     onePortContext,
6848                     dmSMPRequestBody,
6849                     agNULL
6850                    );
6851   
6852   dmAddTimer (
6853               dmRoot,
6854               &dmAllShared->timerlist, 
6855               &discovery->DiscoverySMPTimer
6856               );
6857   
6858   return;
6859 }
6860
6861
6862 osGLOBAL void
6863 dmDiscoverySMPTimerCB(
6864                         dmRoot_t    * dmRoot, 
6865                         void        * timerData1,
6866                         void        * timerData2,
6867                         void        * timerData3
6868                        )
6869 {
6870   agsaRoot_t                  *agRoot;
6871   dmIntPortContext_t          *onePortContext;
6872   bit8                        SMPFunction;  
6873 #ifndef DIRECT_SMP
6874   dmSMPFrameHeader_t          *dmSMPFrameHeader;
6875   bit8                        smpHeader[4];
6876 #endif  
6877   dmSMPRequestBody_t          *dmSMPRequestBody;
6878   dmDiscovery_t               *discovery;
6879   dmDeviceData_t              *oneDeviceData;
6880   agsaIORequest_t             *agAbortIORequest = agNULL;  
6881   agsaIORequest_t             *agToBeAbortIORequest = agNULL;  
6882   dmIntRoot_t                 *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6883   dmIntContext_t              *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6884   dmExpander_t                *oneExpander = agNULL;
6885   dmSMPRequestBody_t          *dmAbortSMPRequestBody = agNULL;
6886   dmList_t                    *SMPList;
6887   
6888   DM_DBG1(("dmDiscoverySMPTimerCB: start!!!\n"));
6889   
6890   onePortContext = (dmIntPortContext_t *)timerData1;
6891   dmSMPRequestBody = (dmSMPRequestBody_t *)timerData2;
6892   
6893   discovery = &(onePortContext->discovery);
6894   oneDeviceData = dmSMPRequestBody->dmDevice;
6895   agToBeAbortIORequest = &(dmSMPRequestBody->agIORequest);
6896   agRoot = dmAllShared->agRoot;
6897   
6898 #ifdef DIRECT_SMP
6899   SMPFunction = dmSMPRequestBody->smpPayload[1];
6900 #else
6901   saFrameReadBlock(agRoot, dmSMPRequestBody->IndirectSMP, 0, smpHeader, 4);
6902   dmSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader;
6903   SMPFunction = dmSMPFrameHeader->smpFunction;
6904 #endif
6905   
6906   DM_DBG3(("dmDiscoverySMPTimerCB: SMP function 0x%x\n", SMPFunction));
6907   
6908   tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
6909   if (discovery->DiscoverySMPTimer.timerRunning == agTRUE)
6910   {
6911     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6912     dmKillTimer(
6913                   dmRoot,
6914                   &discovery->DiscoverySMPTimer
6915                  );
6916   }
6917   else
6918   {
6919     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6920   }
6921   
6922 //for debugging
6923 //  saGetPendingPICI(agRoot);                
6924   
6925   switch (SMPFunction)
6926   {
6927   case SMP_REPORT_GENERAL: /* fall through */
6928   case SMP_DISCOVER:  /* fall through */
6929   case SMP_CONFIGURE_ROUTING_INFORMATION:  /* fall through */
6930     DM_DBG1(("dmDiscoverySMPTimerCB: failing discovery, SMP function 0x%x !!!\n", SMPFunction));
6931     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
6932     return; /* no more things to do */
6933   case SMP_REPORT_PHY_SATA:
6934     DM_DBG1(("dmDiscoverySMPTimerCB: failing discovery, SMP function SMP_REPORT_PHY_SATA !!!\n"));
6935     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
6936     break;
6937   default:
6938     /* do nothing */
6939     DM_DBG1(("dmDiscoverySMPTimerCB: Error, not allowed case!!!\n"));
6940     break;
6941   }
6942   
6943   if (oneDeviceData->registered == agTRUE && (oneDeviceData->valid == agTRUE || oneDeviceData->valid2 == agTRUE) )
6944   {  
6945     /* call to saSMPAbort(one) */
6946     /* get an smp REQUEST from the free list */
6947     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
6948     if (DMLIST_EMPTY(&(dmAllShared->freeSMPList)))
6949     {
6950       DM_DBG1(("dmDiscoverySMPTimerCB: no free SMP, can't abort SMP!!!\n"));
6951       tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
6952       return;
6953     }
6954     else
6955     {
6956       DMLIST_DEQUEUE_FROM_HEAD(&SMPList, &(dmAllShared->freeSMPList));
6957       tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
6958       dmAbortSMPRequestBody = DMLIST_OBJECT_BASE(dmSMPRequestBody_t, Link, SMPList);
6959       if (dmAbortSMPRequestBody == agNULL)
6960       {
6961         DM_DBG1(("dmDiscoverySMPTimerCB: dmAbortSMPRequestBody is NULL!!!\n"));
6962         return;
6963       }    
6964       DM_DBG5(("dmDiscoverySMPTimerCB: SMP id %d\n", dmAbortSMPRequestBody->id));
6965     }
6966     
6967     dmAbortSMPRequestBody->dmRoot = dmRoot;
6968
6969     agAbortIORequest = &(dmAbortSMPRequestBody->agIORequest);
6970     agAbortIORequest->osData = (void *) dmAbortSMPRequestBody;
6971     agAbortIORequest->sdkData = agNULL; /* SALL takes care of this */
6972                                      
6973     oneExpander = oneDeviceData->dmExpander;
6974                                                                                                      
6975     DM_DBG1(("dmDiscoverySMPTimerCB: calling saSMPAbort!!!\n"));
6976     saSMPAbort(agRoot, 
6977                agAbortIORequest,
6978                0,
6979                oneExpander->agDevHandle,
6980                0, /* abort one */
6981                agToBeAbortIORequest,
6982                dmSMPAbortCB
6983               );
6984   }    
6985   return;
6986 }
6987                        
6988
6989
6990
6991 osGLOBAL void                          
6992 dmSMPBusyTimer(dmRoot_t             *dmRoot,
6993                dmIntPortContext_t   *onePortContext,
6994                dmDeviceData_t       *oneDeviceData,
6995                dmSMPRequestBody_t   *dmSMPRequestBody
6996               )
6997 {
6998   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6999   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7000   dmDiscovery_t     *discovery;
7001   
7002   DM_DBG3(("dmSMPBusyTimer: start\n"));
7003   DM_DBG3(("dmSMPBusyTimer: pid %d\n", onePortContext->id));
7004   
7005   discovery = &(onePortContext->discovery);
7006   
7007   tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7008   if (discovery->SMPBusyTimer.timerRunning == agTRUE)
7009   {
7010     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7011     dmKillTimer(
7012               dmRoot,
7013               &discovery->SMPBusyTimer
7014               );
7015   }
7016   else
7017   {
7018     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7019   }
7020   
7021   dmSetTimerRequest(
7022                     dmRoot,
7023                     &discovery->SMPBusyTimer,
7024                     SMP_BUSY_TIMER_VALUE/dmAllShared->usecsPerTick,
7025                     dmSMPBusyTimerCB,
7026                     onePortContext,
7027                     oneDeviceData, 
7028                     dmSMPRequestBody
7029                     );
7030   
7031   dmAddTimer (
7032               dmRoot,
7033               &dmAllShared->timerlist, 
7034               &discovery->SMPBusyTimer
7035               );
7036   
7037   
7038   return;
7039 }
7040
7041 osGLOBAL void
7042 dmSMPBusyTimerCB(
7043                  dmRoot_t    * dmRoot, 
7044                  void        * timerData1,
7045                  void        * timerData2,
7046                  void        * timerData3
7047                 )
7048 {
7049   dmIntRoot_t                 *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
7050   dmIntContext_t              *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7051   agsaRoot_t                  *agRoot;
7052   dmIntPortContext_t          *onePortContext;
7053   dmDeviceData_t              *oneDeviceData;
7054   dmSMPRequestBody_t          *dmSMPRequestBody;
7055   agsaSASRequestBody_t        *agSASRequestBody;
7056   agsaIORequest_t             *agIORequest;
7057   agsaDevHandle_t             *agDevHandle;
7058   dmDiscovery_t               *discovery;
7059   bit32                       status = AGSA_RC_FAILURE;
7060   dmExpander_t                *oneExpander = agNULL;
7061   
7062   
7063   DM_DBG3(("dmSMPBusyTimerCB: start\n"));
7064   
7065   onePortContext = (dmIntPortContext_t *)timerData1;
7066   oneDeviceData = (dmDeviceData_t *)timerData2;
7067   dmSMPRequestBody = (dmSMPRequestBody_t *)timerData3;
7068   agRoot = dmAllShared->agRoot;
7069   agIORequest = &(dmSMPRequestBody->agIORequest);
7070   oneExpander = oneDeviceData->dmExpander;
7071   agDevHandle = oneExpander->agDevHandle;
7072   agSASRequestBody = &(dmSMPRequestBody->agSASRequestBody);
7073   discovery = &(onePortContext->discovery);
7074
7075   discovery->SMPRetries++;
7076   
7077   if (discovery->SMPRetries < SMP_BUSY_RETRIES)
7078   {    
7079     status = saSMPStart(
7080                          agRoot,
7081                          agIORequest,
7082                          0,             
7083                          agDevHandle,
7084                          AGSA_SMP_INIT_REQ,
7085                          agSASRequestBody,
7086                          &dmsaSMPCompleted
7087                          );
7088   }
7089
7090   if (status == AGSA_RC_SUCCESS)
7091   {
7092     discovery->SMPRetries = 0;
7093     tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7094     if (discovery->SMPBusyTimer.timerRunning == agTRUE)
7095     {
7096       tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7097       dmKillTimer(
7098                     dmRoot,
7099                     &discovery->SMPBusyTimer
7100                    );
7101     }                
7102     else
7103     {
7104       tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7105     }
7106   }                    
7107   else if (status == AGSA_RC_FAILURE)
7108   {  
7109     tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7110     if (discovery->SMPBusyTimer.timerRunning == agTRUE)
7111     {
7112       tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7113       dmKillTimer(
7114                     dmRoot,
7115                     &discovery->SMPBusyTimer
7116                    );
7117     }                
7118     else
7119     {
7120       tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7121     }
7122
7123     discovery->SMPRetries = 0;
7124     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
7125   }
7126   else /* AGSA_RC_BUSY */
7127   {
7128     if (discovery->SMPRetries >= SMP_BUSY_RETRIES)
7129     {
7130       /* done with retris; give up */
7131       DM_DBG3(("dmSMPBusyTimerCB: retries are over\n"));
7132
7133       tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7134       if (discovery->SMPBusyTimer.timerRunning == agTRUE)
7135       {
7136         tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7137         dmKillTimer(
7138                       dmRoot,
7139                       &discovery->SMPBusyTimer
7140                      );
7141       }              
7142       else
7143       {
7144         tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7145       }
7146
7147       discovery->SMPRetries = 0;
7148       dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
7149
7150     }
7151     else
7152     {
7153       /* keep retrying */
7154       dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody);
7155     }
7156   }
7157   
7158   return;
7159 }  
7160
7161
7162 /* expander configuring timer */
7163 osGLOBAL void                          
7164 dmDiscoveryConfiguringTimer(dmRoot_t                 *dmRoot,
7165                             dmIntPortContext_t       *onePortContext,
7166                             dmDeviceData_t           *oneDeviceData
7167                            )
7168 {
7169   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
7170   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7171   dmDiscovery_t     *discovery;
7172   
7173   DM_DBG3(("dmDiscoveryConfiguringTimer: start\n"));
7174   DM_DBG3(("dmDiscoveryConfiguringTimer: pid %d\n", onePortContext->id));
7175   
7176   discovery = &(onePortContext->discovery);
7177  
7178   tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7179   if (discovery->discoveryTimer.timerRunning == agTRUE)
7180   {
7181     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7182     dmKillTimer(
7183               dmRoot,
7184               &discovery->discoveryTimer
7185               );
7186   }
7187   else
7188   {
7189     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7190   }
7191   
7192   DM_DBG3(("dmDiscoveryConfiguringTimer: UsecsPerTick %d\n", dmAllShared->usecsPerTick));
7193   DM_DBG3(("dmDiscoveryConfiguringTimer: Timervalue %d\n", DISCOVERY_CONFIGURING_TIMER_VALUE/dmAllShared->usecsPerTick));
7194   
7195   dmSetTimerRequest(
7196                     dmRoot,
7197                     &discovery->discoveryTimer,
7198                     DISCOVERY_CONFIGURING_TIMER_VALUE/dmAllShared->usecsPerTick,
7199                     dmDiscoveryConfiguringTimerCB,
7200                     onePortContext, 
7201                     oneDeviceData,
7202                     agNULL
7203                    );
7204                    
7205   dmAddTimer (
7206               dmRoot,
7207               &dmAllShared->timerlist, 
7208               &discovery->discoveryTimer
7209               );
7210   
7211   
7212   return;
7213 }
7214
7215                 
7216 osGLOBAL void
7217 dmDiscoveryConfiguringTimerCB(
7218                               dmRoot_t    * dmRoot, 
7219                               void        * timerData1,
7220                               void        * timerData2,
7221                               void        * timerData3
7222                              )
7223 {
7224   dmIntPortContext_t     *onePortContext = agNULL;
7225   dmDiscovery_t          *discovery      = agNULL;
7226   dmDeviceData_t         *oneDeviceData  = agNULL;
7227
7228   onePortContext = (dmIntPortContext_t *)timerData1;
7229   oneDeviceData  = (dmDeviceData_t *)timerData2;
7230   discovery = &(onePortContext->discovery);
7231
7232   DM_DBG3(("dmDiscoveryConfiguringTimerCB: start\n"));  
7233
7234   tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7235   if (discovery->discoveryTimer.timerRunning == agTRUE)
7236   {
7237     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7238     dmKillTimer(
7239                dmRoot,
7240                &discovery->discoveryTimer
7241                );
7242   }       
7243   else
7244   {
7245     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7246   }
7247   
7248   if (oneDeviceData->valid == agTRUE || oneDeviceData->valid2 == agTRUE)
7249   {
7250     dmReportGeneralSend(dmRoot, oneDeviceData);
7251   }
7252   return;
7253 }
7254                                                 
7255 osGLOBAL void                          
7256 dmConfigureRouteTimer(dmRoot_t                 *dmRoot,
7257                       dmIntPortContext_t       *onePortContext,
7258                       dmExpander_t             *oneExpander,
7259                       smpRespDiscover_t        *pdmSMPDiscoverResp,
7260                       smpRespDiscover2_t       *pdmSMPDiscover2Resp
7261                      )
7262 {
7263   dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
7264   dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7265   dmDiscovery_t     *discovery;
7266   
7267   DM_DBG3(("dmConfigureRouteTimer: start\n"));
7268   
7269   DM_DBG3(("dmConfigureRouteTimer: pid %d\n", onePortContext->id));
7270   
7271   discovery = &(onePortContext->discovery);
7272  
7273   DM_DBG3(("dmConfigureRouteTimer: onePortContext %p oneExpander %p pdmSMPDiscoverResp %p\n", onePortContext, oneExpander, pdmSMPDiscoverResp));
7274   
7275   DM_DBG3(("dmConfigureRouteTimer: discovery %p \n", discovery));
7276   
7277   DM_DBG3(("dmConfigureRouteTimer:  pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries));
7278   
7279   DM_DBG3(("dmConfigureRouteTimer: discovery->status %d\n", discovery->status));
7280       
7281   tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7282   if (discovery->configureRouteTimer.timerRunning == agTRUE)
7283   {
7284     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7285     dmKillTimer(
7286               dmRoot,
7287               &discovery->configureRouteTimer
7288               );
7289   }
7290   else
7291   {
7292     tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7293   }
7294   
7295   DM_DBG3(("dmConfigureRouteTimer: UsecsPerTick %d\n", dmAllShared->usecsPerTick));
7296   DM_DBG3(("dmConfigureRouteTimer: Timervalue %d\n", CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick));
7297   
7298   if (oneExpander->SAS2 == 0)
7299   {
7300     /* SAS 1.1 */
7301     dmSetTimerRequest(
7302                       dmRoot,
7303                       &discovery->configureRouteTimer,
7304                       CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick,
7305                       dmConfigureRouteTimerCB,
7306                       (void *)onePortContext, 
7307                       (void *)oneExpander,
7308                       (void *)pdmSMPDiscoverResp
7309                      );
7310   }                   
7311   else
7312   { 
7313     /* SAS 2 */
7314     dmSetTimerRequest(
7315                       dmRoot,
7316                       &discovery->configureRouteTimer,
7317                       CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick,
7318                       dmConfigureRouteTimerCB,
7319                       (void *)onePortContext, 
7320                       (void *)oneExpander,
7321                       (void *)pdmSMPDiscover2Resp
7322                      );
7323   }                  
7324   dmAddTimer (
7325               dmRoot,
7326               &dmAllShared->timerlist, 
7327               &discovery->configureRouteTimer
7328               );
7329    
7330   return;
7331 }
7332
7333
7334 osGLOBAL void
7335 dmConfigureRouteTimerCB(
7336                         dmRoot_t    * dmRoot, 
7337                         void        * timerData1,
7338                         void        * timerData2,
7339                         void        * timerData3
7340                        )
7341 {
7342   dmIntRoot_t         *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
7343   dmIntContext_t      *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7344   dmIntPortContext_t  *onePortContext;
7345   dmExpander_t        *oneExpander;
7346   smpRespDiscover_t   *pdmSMPDiscoverResp = agNULL;
7347   smpRespDiscover2_t  *pdmSMPDiscover2Resp = agNULL;
7348   dmDiscovery_t       *discovery;
7349   
7350   
7351   DM_DBG3(("dmConfigureRouteTimerCB: start\n"));
7352   
7353   onePortContext = (dmIntPortContext_t *)timerData1;
7354   oneExpander = (dmExpander_t *)timerData2;
7355   if (oneExpander->SAS2 == 0)
7356   {
7357     pdmSMPDiscoverResp = (smpRespDiscover_t *)timerData3;
7358   }
7359   else
7360   {
7361     pdmSMPDiscover2Resp = (smpRespDiscover2_t *)timerData3;
7362   }
7363   discovery = &(onePortContext->discovery);
7364   
7365   DM_DBG3(("dmConfigureRouteTimerCB: onePortContext %p oneExpander %p pdmSMPDiscoverResp %p\n", onePortContext, oneExpander, pdmSMPDiscoverResp));
7366   
7367   DM_DBG3(("dmConfigureRouteTimerCB: discovery %p\n", discovery));
7368
7369   DM_DBG3(("dmConfigureRouteTimerCB: pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries));
7370   
7371   DM_DBG3(("dmConfigureRouteTimerCB: discovery.status %d\n", discovery->status));
7372    
7373   discovery->configureRouteRetries++; 
7374   if (discovery->configureRouteRetries >= dmAllShared->MaxRetryDiscovery)
7375   {
7376     DM_DBG3(("dmConfigureRouteTimerCB: retries are over\n"));
7377
7378     tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7379     if (discovery->configureRouteTimer.timerRunning == agTRUE)
7380     {
7381       tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7382       dmKillTimer(
7383                   dmRoot,
7384                   &discovery->configureRouteTimer
7385                   );
7386     }
7387     else
7388     {
7389       tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7390     }
7391
7392     discovery->configureRouteRetries = 0;
7393     /* failed the discovery */
7394     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
7395
7396     return;
7397   }
7398
7399   
7400   if (oneExpander->SAS2 == 0)
7401   {
7402     if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
7403     {
7404       DM_DBG3(("dmConfigureRouteTimerCB: proceed by calling dmDownStreamDiscoverExpanderPhy\n"));
7405       dmhexdump("dmConfigureRouteTimerCB", (bit8*)pdmSMPDiscoverResp, sizeof(smpRespDiscover_t));
7406       discovery->configureRouteRetries = 0;
7407
7408       dmDownStreamDiscoverExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp);  
7409     }
7410     else
7411     {
7412       DM_DBG3(("dmConfigureRouteTimerCB: setting timer again\n"));
7413       /* set the timer again */
7414       dmSetTimerRequest(
7415                         dmRoot,
7416                         &discovery->configureRouteTimer,
7417                         CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick,
7418                         dmConfigureRouteTimerCB,
7419                         (void *)onePortContext, 
7420                         (void *)oneExpander,
7421                         (void *)pdmSMPDiscoverResp
7422                        );
7423                    
7424       dmAddTimer (
7425                   dmRoot,
7426                   &dmAllShared->timerlist, 
7427                   &discovery->configureRouteTimer
7428                   );
7429     }
7430   } /* SAS 1.1 */
7431   else
7432   {
7433     /* SAS 2 */
7434     if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
7435     {
7436       DM_DBG2(("dmConfigureRouteTimerCB: proceed by calling dmDownStreamDiscover2ExpanderPhy\n"));
7437       dmhexdump("dmConfigureRouteTimerCB", (bit8*)pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t));
7438
7439       dmDownStreamDiscover2ExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscover2Resp);  
7440     }
7441     else
7442     {
7443       DM_DBG2(("dmConfigureRouteTimerCB: setting timer again\n"));
7444       /* set the timer again */
7445       dmSetTimerRequest(
7446                         dmRoot,
7447                         &discovery->configureRouteTimer,
7448                         CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick,
7449                         dmConfigureRouteTimerCB,
7450                         (void *)onePortContext, 
7451                         (void *)oneExpander,
7452                         (void *)pdmSMPDiscover2Resp
7453                        );
7454                    
7455       dmAddTimer (
7456                   dmRoot,
7457                   &dmAllShared->timerlist, 
7458                   &discovery->configureRouteTimer
7459                  );
7460     }
7461   }
7462   
7463   return;
7464 }                      
7465 #endif /* FDS_ DM */
7466