xref: /freebsd/sys/dev/pms/RefTisa/discovery/dm/dmdisc.c (revision 39ee7a7a6bdd1557b1c3532abf60d139798ac88b)
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 
7467