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