The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pms/RefTisa/discovery/dm/dmdisc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 25601d3f93cfdc50bd2bde937fcfe892


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.