dmdisc.c revision 285809
141120Sjdp/*******************************************************************************
2103976Spst**
341120Sjdp*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
441120Sjdp*
541120Sjdp*Redistribution and use in source and binary forms, with or without modification, are permitted provided
641120Sjdp*that the following conditions are met:
741120Sjdp*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
841120Sjdp*following disclaimer.
941120Sjdp*2. Redistributions in binary form must reproduce the above copyright notice,
1041120Sjdp*this list of conditions and the following disclaimer in the documentation and/or other materials provided
1141120Sjdp*with the distribution.
1241120Sjdp*
1341120Sjdp*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
1441120Sjdp*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1541120Sjdp*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1641120Sjdp*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1741120Sjdp*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1841120Sjdp*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1941120Sjdp*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2041120Sjdp*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
2141120Sjdp**
2241120Sjdp********************************************************************************/
2341120Sjdp#include <sys/cdefs.h>
2441120Sjdp__FBSDID("$FreeBSD$");
2541120Sjdp#include <dev/pms/config.h>
2641120Sjdp
2784222Sdillon#include <dev/pms/freebsd/driver/common/osenv.h>
2884222Sdillon#include <dev/pms/freebsd/driver/common/ostypes.h>
2984222Sdillon#include <dev/pms/freebsd/driver/common/osdebug.h>
3041120Sjdp
3141120Sjdp#include <dev/pms/RefTisa/sallsdk/api/sa.h>
3241120Sjdp#include <dev/pms/RefTisa/sallsdk/api/saapi.h>
3341120Sjdp#include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
3441120Sjdp
3541120Sjdp#ifdef FDS_DM
3641120Sjdp#include <dev/pms/RefTisa/discovery/api/dm.h>
3741120Sjdp#include <dev/pms/RefTisa/discovery/api/dmapi.h>
3841120Sjdp#include <dev/pms/RefTisa/discovery/api/tddmapi.h>
3941120Sjdp
4041120Sjdp#include <dev/pms/RefTisa/discovery/dm/dmdefs.h>
4141120Sjdp#include <dev/pms/RefTisa/discovery/dm/dmtypes.h>
4241120Sjdp#include <dev/pms/RefTisa/discovery/dm/dmproto.h>
4341120Sjdp
4441120Sjdp/*****************************************************************************/
4541120Sjdp/*! \brief dmDiscover
4641120Sjdp *
4741120Sjdp *
4841120Sjdp *  Purpose: A discovery is started by this function
4941120Sjdp *
5041120Sjdp *  \param   dmRoot:              DM context handle.
5141120Sjdp *  \param   dmPortContext:       Pointer to this instance of port context
5241120Sjdp *  \param   option:              Discovery option
5341120Sjdp *
54103976Spst *  \return:
5541120Sjdp *          DM_RC_SUCCESS
5641120Sjdp *          DM_RC_FAILURE
5741120Sjdp *
5841120Sjdp */
5941120Sjdp/*****************************************************************************/
6041120SjdposGLOBAL bit32
6141120SjdpdmDiscover(
6241120Sjdp           dmRoot_t 		*dmRoot,
6341120Sjdp           dmPortContext_t	*dmPortContext,
6441120Sjdp           bit32 		option)
6541120Sjdp{
66103976Spst  dmIntPortContext_t        *onePortContext = agNULL;
67103976Spst  bit32                     ret = DM_RC_FAILURE;
6841120Sjdp
6941120Sjdp  DM_DBG3(("dmDiscover: start\n"));
7041120Sjdp  onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
7141120Sjdp
7241120Sjdp  if (onePortContext == agNULL)
7341120Sjdp  {
7441120Sjdp    DM_DBG1(("dmDiscover: onePortContext is NULL!!!\n"));
7541120Sjdp    return DM_RC_FAILURE;
7641120Sjdp  }
7741120Sjdp
7841120Sjdp  if (onePortContext->valid == agFALSE)
79103976Spst  {
80103976Spst    DM_DBG1(("dmDiscover: invalid port!!!\n"));
8141120Sjdp    return DM_RC_FAILURE;
8241120Sjdp  }
8341120Sjdp
8441120Sjdp  if (onePortContext->RegFailed == agTRUE)
8541120Sjdp  {
8641120Sjdp    DM_DBG1(("dmDiscover: Registration failed!!!\n"));
8741120Sjdp    return DM_RC_FAILURE;
8841120Sjdp  }
8941120Sjdp
9041120Sjdp  switch ( option )
9141120Sjdp  {
9241120Sjdp  case DM_DISCOVERY_OPTION_FULL_START:
9341120Sjdp    DM_DBG3(("dmDiscover: full, pid %d\n", onePortContext->id));
9441120Sjdp    onePortContext->discovery.type = DM_DISCOVERY_OPTION_FULL_START;
9541120Sjdp    dmDiscoveryResetMCN(dmRoot, onePortContext);
9641120Sjdp    ret = dmFullDiscover(dmRoot, onePortContext);
9741120Sjdp    break;
9841120Sjdp  case DM_DISCOVERY_OPTION_INCREMENTAL_START:
9941120Sjdp    DM_DBG3(("dmDiscover: incremental, pid %d\n", onePortContext->id));
10041120Sjdp    onePortContext->discovery.type = DM_DISCOVERY_OPTION_INCREMENTAL_START;
10141120Sjdp    dmDiscoveryResetMCN(dmRoot, onePortContext);
10241120Sjdp    ret = dmIncrementalDiscover(dmRoot, onePortContext, agFALSE);
10341120Sjdp    break;
10441120Sjdp  case DM_DISCOVERY_OPTION_ABORT:
10541120Sjdp    DM_DBG3(("dmDiscover: abort\n"));
10641120Sjdp    if (onePortContext->DiscoveryState != DM_DSTATE_COMPLETED)
10741120Sjdp    {
10841120Sjdp      if (onePortContext->discovery.pendingSMP == 0)
10941120Sjdp      {
11041120Sjdp        dmDiscoverAbort(dmRoot, onePortContext);
11141120Sjdp        tddmDiscoverCB(
11241120Sjdp                       dmRoot,
11341120Sjdp                       onePortContext->dmPortContext,
11441120Sjdp                       dmDiscAborted
11541120Sjdp                       );
11641120Sjdp      }
11741120Sjdp      else
11841120Sjdp      {
11941120Sjdp        DM_DBG3(("dmDiscover: abortInProgress\n"));
12041120Sjdp        onePortContext->DiscoveryAbortInProgress = agTRUE;
12141120Sjdp        tddmDiscoverCB(
12241120Sjdp                       dmRoot,
12341120Sjdp                       dmPortContext,
12441120Sjdp                       dmDiscAbortInProgress
12541120Sjdp                       );
12641120Sjdp      }
12741120Sjdp    }
12841120Sjdp    else
12941120Sjdp    {
13041120Sjdp      DM_DBG3(("dmDiscover: no discovery to abort\n"));
13141120Sjdp      tddmDiscoverCB(
13241120Sjdp                     dmRoot,
13341120Sjdp                     dmPortContext,
13441120Sjdp                     dmDiscAbortInvalid
13541120Sjdp                     );
13641120Sjdp    }
13741120Sjdp    ret = DM_RC_SUCCESS;
13841120Sjdp    break;
13941120Sjdp  default:
14041120Sjdp    break;
14141120Sjdp  }
14241120Sjdp  return ret;
143103976Spst}
14441120Sjdp
145103976SpstosGLOBAL bit32
14641120SjdpdmFullDiscover(
147103976Spst               dmRoot_t 	    	*dmRoot,
148103976Spst               dmIntPortContext_t       *onePortContext
149103976Spst              )
150103976Spst{
151103976Spst  dmExpander_t              *oneExpander = agNULL;
152103976Spst  dmSASSubID_t              dmSASSubID;
15341120Sjdp  dmDeviceData_t            *oneExpDeviceData = agNULL;
154103976Spst
155103976Spst  DM_DBG1(("dmFullDiscover: start\n"));
156103976Spst
157103976Spst  if (onePortContext->valid == agFALSE)
158103976Spst  {
159103976Spst    DM_DBG1(("dmFullDiscover: invalid port!!!\n"));
16041120Sjdp    return DM_RC_FAILURE;
161103976Spst  }
162103976Spst
16341120Sjdp  if (onePortContext->DiscoveryState == DM_DSTATE_STARTED)
164103976Spst  {
165103976Spst    DM_DBG1(("dmFullDiscover: no two instances of discovery allowed!!!\n"));
16641120Sjdp    return DM_RC_FAILURE;
167103976Spst  }
168103976Spst
169103976Spst  onePortContext->DiscoveryState = DM_DSTATE_STARTED;
170103976Spst
17141120Sjdp  dmSASSubID.sasAddressHi = onePortContext->sasRemoteAddressHi;
172103976Spst  dmSASSubID.sasAddressLo = onePortContext->sasRemoteAddressLo;
17341120Sjdp
174103976Spst  /* check OnePortContext->discovery.discoveringExpanderList */
175103976Spst  oneExpander = dmExpFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
17641120Sjdp  if (oneExpander != agNULL)
177103976Spst  {
178103976Spst    oneExpDeviceData = oneExpander->dmDevice;
179103976Spst  }
180103976Spst  else
181103976Spst  {
182103976Spst    /* check dmAllShared->mainExpanderList */
183103976Spst    oneExpander = dmExpMainListFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
184103976Spst    if (oneExpander != agNULL)
185103976Spst    {
186103976Spst      oneExpDeviceData = oneExpander->dmDevice;
187103976Spst    }
188103976Spst  }
189103976Spst
190103976Spst  if (oneExpDeviceData != agNULL)
191103976Spst  {
192103976Spst    dmSASSubID.initiator_ssp_stp_smp = oneExpDeviceData->initiator_ssp_stp_smp;
193103976Spst    dmSASSubID.target_ssp_stp_smp = oneExpDeviceData->target_ssp_stp_smp;
194103976Spst    oneExpDeviceData->registered = agTRUE;
195103976Spst    dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, oneExpDeviceData, 0xFF);
196103976Spst  }
197103976Spst  else
198103976Spst  {
199103976Spst    DM_DBG1(("dmFullDiscover:oneExpDeviceData is NULL!!!\n"));
200103976Spst    return DM_RC_FAILURE;
201103976Spst  }
202103976Spst
203103976Spst  dmUpStreamDiscoverStart(dmRoot, onePortContext);
204103976Spst
205103976Spst  return DM_RC_SUCCESS;
206103976Spst}
207103976Spst
208103976SpstosGLOBAL bit32
209103976SpstdmIncrementalDiscover(
21041120Sjdp                      dmRoot_t 	    	      *dmRoot,
211103976Spst                      dmIntPortContext_t      *onePortContext,
212103976Spst		      bit32                   flag
21341120Sjdp                     )
214200399Ssyrinx{
215200399Ssyrinx  dmExpander_t              *oneExpander = agNULL;
21641120Sjdp  dmSASSubID_t              dmSASSubID;
217103976Spst  dmDeviceData_t            *oneExpDeviceData = agNULL;
218103976Spst
219103976Spst  DM_DBG1(("dmIncrementalDiscover: start\n"));
22041120Sjdp
221103976Spst  if (onePortContext->valid == agFALSE)
22241120Sjdp  {
22341120Sjdp    DM_DBG1(("dmIncrementalDiscover: invalid port!!!\n"));
224103976Spst    return DM_RC_FAILURE;
22541120Sjdp  }
22641120Sjdp
22741120Sjdp  /* TDM triggerred; let go DM triggerred */
22841120Sjdp  if (flag == agFALSE)
22941120Sjdp  {
23041120Sjdp    if (onePortContext->DiscoveryState == DM_DSTATE_STARTED)
23141120Sjdp    {
23241120Sjdp      DM_DBG1(("dmIncrementalDiscover: no two instances of discovery allowed!!!\n"));
23341120Sjdp      return DM_RC_FAILURE;
23441120Sjdp    }
23541120Sjdp  }
23641120Sjdp
23741120Sjdp  onePortContext->DiscoveryState = DM_DSTATE_STARTED;
23841120Sjdp  onePortContext->discovery.type = DM_DISCOVERY_OPTION_INCREMENTAL_START;
23941120Sjdp
24041120Sjdp  dmSASSubID.sasAddressHi = onePortContext->sasRemoteAddressHi;
24141120Sjdp  dmSASSubID.sasAddressLo = onePortContext->sasRemoteAddressLo;
24241120Sjdp
24341120Sjdp  /* check OnePortContext->discovery.discoveringExpanderList */
24441120Sjdp  oneExpander = dmExpFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
24541120Sjdp  if (oneExpander != agNULL)
24641120Sjdp  {
24741120Sjdp    oneExpDeviceData = oneExpander->dmDevice;
24841120Sjdp  }
24941120Sjdp  else
25041120Sjdp  {
25141120Sjdp    /* check dmAllShared->mainExpanderList */
25241120Sjdp    oneExpander = dmExpMainListFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
25341120Sjdp    if (oneExpander != agNULL)
25441120Sjdp    {
25541120Sjdp      oneExpDeviceData = oneExpander->dmDevice;
25641120Sjdp    }
25741120Sjdp  }
25841120Sjdp
25941120Sjdp  if (oneExpDeviceData != agNULL)
26041120Sjdp  {
261141918Sstefanf    dmSASSubID.initiator_ssp_stp_smp = oneExpDeviceData->initiator_ssp_stp_smp;
26241120Sjdp    dmSASSubID.target_ssp_stp_smp = oneExpDeviceData->target_ssp_stp_smp;
26341120Sjdp    oneExpDeviceData->registered = agTRUE;
26441120Sjdp    dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, oneExpDeviceData, 0xFF);
26541120Sjdp  }
26641120Sjdp  else
26741120Sjdp  {
26841120Sjdp    DM_DBG1(("dmIncrementalDiscover:oneExpDeviceData is NULL!!!\n"));
26941120Sjdp    return DM_RC_FAILURE;
27041120Sjdp  }
27141120Sjdp
27241120Sjdp  dmUpStreamDiscoverStart(dmRoot, onePortContext);
27341120Sjdp
27441120Sjdp  return DM_RC_SUCCESS;
27541120Sjdp}
27641120Sjdp
27741120SjdposGLOBAL void
27841120SjdpdmUpStreamDiscoverStart(
27941120Sjdp                        dmRoot_t             *dmRoot,
28041120Sjdp                        dmIntPortContext_t   *onePortContext
28141120Sjdp                       )
28241120Sjdp{
28341120Sjdp//  dmExpander_t              *oneExpander = agNULL;
28441120Sjdp  bit32                     sasAddressHi, sasAddressLo;
28541120Sjdp  dmDeviceData_t            *oneDeviceData;
28641120Sjdp  dmExpander_t              *oneExpander = agNULL;
28741120Sjdp
28841120Sjdp  DM_DBG3(("dmUpStreamDiscoverStart: start\n"));
28941120Sjdp  if (onePortContext->valid == agFALSE)
29041120Sjdp  {
29141120Sjdp    DM_DBG1(("dmUpStreamDiscoverStart: invalid port!!!\n"));
29241120Sjdp    return;
29341120Sjdp  }
29441120Sjdp  /*
29541120Sjdp    at this point, the 1st expander should have been registered.
29641120Sjdp    find an expander from onePortContext
29741120Sjdp  */
29841120Sjdp  sasAddressHi = onePortContext->sasRemoteAddressHi;
29941120Sjdp  sasAddressLo = onePortContext->sasRemoteAddressLo;
30041120Sjdp  DM_DBG3(("dmUpStreamDiscoverStart: Port Remote AddrHi 0x%08x Remote AddrLo 0x%08x\n", sasAddressHi, sasAddressLo));
30141120Sjdp
30241120Sjdp  oneDeviceData = dmDeviceFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo);
30341120Sjdp
30441120Sjdp//  oneDeviceData = oneExpander->dmDevice;
30541120Sjdp// start here
30641120Sjdp  onePortContext->discovery.status = DISCOVERY_UP_STREAM;
30741120Sjdp  if (oneDeviceData == agNULL)
30841120Sjdp  {
30941120Sjdp    DM_DBG1(("dmUpStreamDiscoverStart: oneExpander is NULL, wrong!!!\n"));
31041120Sjdp    return;
31141120Sjdp  }
31241120Sjdp  else
31341120Sjdp  {
31441120Sjdp    if ( (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
31541120Sjdp         ||
31641120Sjdp         (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE)
31741120Sjdp	 ||
31841120Sjdp	 DEVICE_IS_SMP_TARGET(oneDeviceData)
31941120Sjdp        )
32041120Sjdp    {
32141120Sjdp#if 1  /* for incremental discovery */
32241120Sjdp      /* start here: if not on discoveringExpanderList, alloc and add
32341120Sjdp      dmNewEXPorNot()
32441120Sjdp      */
32541120Sjdp      oneExpander = dmExpFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo);
32641120Sjdp      if ( oneExpander == agNULL)
32741120Sjdp      {
32841120Sjdp        /* alloc and add */
32941120Sjdp        oneExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, oneDeviceData);
33041120Sjdp        if ( oneExpander != agNULL)
33141120Sjdp        {
33241120Sjdp          dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);
33341120Sjdp        }
33441120Sjdp        else
33541120Sjdp	{
33641120Sjdp          DM_DBG1(("dmUpStreamDiscoverStart: failed to allocate expander or discovey aborted!!!\n"));
33741120Sjdp          return;
33841120Sjdp	}
33941120Sjdp      }
34041120Sjdp#endif
34141120Sjdp
34241120Sjdp      dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
34341120Sjdp    }
34441120Sjdp    else
34541120Sjdp    {
34641120Sjdp      DM_DBG1(("dmUpStreamDiscoverStart: oneDeviceData is not an Expander did %d, wrong!!!\n", oneDeviceData->id));
34741120Sjdp      return;
34841120Sjdp    }
34941120Sjdp  }
35041120Sjdp  return;
35141120Sjdp}
35241120Sjdp
35341120Sjdp/* sends report general */
35441120SjdposGLOBAL void
35541120SjdpdmUpStreamDiscovering(
35641120Sjdp                      dmRoot_t              *dmRoot,
35741120Sjdp                      dmIntPortContext_t    *onePortContext,
35841120Sjdp                      dmDeviceData_t        *oneDeviceData
35941120Sjdp                     )
36041120Sjdp{
36141120Sjdp  dmList_t          *ExpanderList;
36241120Sjdp  dmExpander_t      *oneNextExpander = agNULL;
36341120Sjdp
36441120Sjdp  DM_DBG3(("dmUpStreamDiscovering: start\n"));
36541120Sjdp
36641120Sjdp  if (onePortContext->valid == agFALSE)
36741120Sjdp  {
36841120Sjdp    DM_DBG1(("dmUpStreamDiscovering: invalid port!!!\n"));
36941120Sjdp    return;
37041120Sjdp  }
37141120Sjdp
37241120Sjdp  tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
37341120Sjdp  if (DMLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList)))
37441120Sjdp  {
37541120Sjdp    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
37641120Sjdp    DM_DBG3(("dmUpStreamDiscovering: should be the end\n"));
37741120Sjdp    oneNextExpander = agNULL;
37841120Sjdp  }
37941120Sjdp  else
38041120Sjdp  {
38141120Sjdp    DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList));
38241120Sjdp    oneNextExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
38341120Sjdp    if ( oneNextExpander != agNULL)
38441120Sjdp    {
38541120Sjdp      DMLIST_ENQUEUE_AT_HEAD(&(oneNextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));
38641120Sjdp      DM_DBG3(("dmUpStreamDiscovering tdsaSASUpStreamDiscovering: dequeue head\n"));
38741120Sjdp      DM_DBG3(("dmUpStreamDiscovering: expander id %d\n", oneNextExpander->id));
38841120Sjdp    }
38941120Sjdp    else
39041120Sjdp    {
39141120Sjdp      DM_DBG1(("dmUpStreamDiscovering: oneNextExpander is NULL!!!\n"));
39241120Sjdp    }
39341120Sjdp    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
39441120Sjdp
39541120Sjdp  }
39641120Sjdp
39741120Sjdp  if (oneNextExpander != agNULL)
39841120Sjdp  {
39941120Sjdp    dmReportGeneralSend(dmRoot, oneNextExpander->dmDevice);
40041120Sjdp  }
40141120Sjdp  else
40241120Sjdp  {
40341120Sjdp    DM_DBG3(("dmUpStreamDiscovering: No more expander list\n"));
40441120Sjdp    dmDownStreamDiscoverStart(dmRoot, onePortContext, oneDeviceData);
40541120Sjdp  }
40641120Sjdp
40741120Sjdp  return;
40841120Sjdp}
40941120Sjdp
41041120SjdposGLOBAL void
41141120SjdpdmDownStreamDiscoverStart(
41241120Sjdp                          dmRoot_t              *dmRoot,
41341120Sjdp                          dmIntPortContext_t    *onePortContext,
41441120Sjdp                          dmDeviceData_t        *oneDeviceData
41541120Sjdp                         )
41641120Sjdp{
41741120Sjdp  dmExpander_t        *UpStreamExpander;
41841120Sjdp  dmExpander_t        *oneExpander;
41941120Sjdp
42041120Sjdp  DM_DBG3(("dmDownStreamDiscoverStart: start\n"));
42141120Sjdp
42241120Sjdp  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
42341120Sjdp  {
42441120Sjdp    DM_DBG1(("dmDownStreamDiscoverStart: invalid port or aborted discovery!!!\n"));
42541120Sjdp    return;
42641120Sjdp  }
42741120Sjdp
42841120Sjdp  /* set discovery status */
42941120Sjdp  onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
43041120Sjdp
43141120Sjdp  /* If it's an expander */
43241120Sjdp  if ( (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
43341120Sjdp       || (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE)
43441120Sjdp       || DEVICE_IS_SMP_TARGET(oneDeviceData)
43541120Sjdp       )
43641120Sjdp  {
43741120Sjdp    oneExpander = oneDeviceData->dmExpander;
43841120Sjdp    UpStreamExpander = oneExpander->dmUpStreamExpander;
43941120Sjdp
44041120Sjdp    /* If the two expanders are the root of two edge sets; sub-to-sub */
44141120Sjdp    if ( (UpStreamExpander != agNULL) && ( UpStreamExpander->dmUpStreamExpander == oneExpander ) )
44241120Sjdp    {
44341120Sjdp      DM_DBG3(("dmDownStreamDiscoverStart: Root found pExpander=%p pUpStreamExpander=%p\n",
44441120Sjdp               oneExpander, UpStreamExpander));
445103976Spst      //Saves the root expander
446103976Spst      onePortContext->discovery.RootExp = oneExpander;
447103976Spst      DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
448103976Spst      DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
449103976Spst
450103976Spst      /* reset up stream inform for pExpander */
451103976Spst      oneExpander->dmUpStreamExpander = agNULL;
452103976Spst      /* Add the pExpander to discovering list */
45341120Sjdp      dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);
45441120Sjdp
45541120Sjdp      /* reset up stream inform for oneExpander */
45641120Sjdp      UpStreamExpander->dmUpStreamExpander = agNULL;
45741120Sjdp      /* Add the UpStreamExpander to discovering list */
45841120Sjdp      dmDiscoveringExpanderAdd(dmRoot, onePortContext, UpStreamExpander);
459103976Spst    }
460103976Spst    /* If the two expanders are not the root of two edge sets. eg) one root */
46141120Sjdp    else
46241120Sjdp    {
463103976Spst      //Saves the root expander
464103976Spst      onePortContext->discovery.RootExp = oneExpander;
465103976Spst
46641120Sjdp      DM_DBG3(("dmDownStreamDiscoverStart: NO Root pExpander=%p\n", oneExpander));
46741120Sjdp      DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
46841120Sjdp      DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
46941120Sjdp
47041120Sjdp      /* (2.2.2.1) Add the pExpander to discovering list */
47141120Sjdp      dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);
47241120Sjdp    }
47341120Sjdp  }
47441120Sjdp
47541120Sjdp  /* Continue down stream discovering */
47641120Sjdp  dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
47741120Sjdp
47841120Sjdp  return;
47941120Sjdp}
48041120Sjdp
48141120SjdposGLOBAL void
48241120SjdpdmDownStreamDiscovering(
48341120Sjdp                        dmRoot_t              *dmRoot,
48441120Sjdp                        dmIntPortContext_t    *onePortContext,
48541120Sjdp                        dmDeviceData_t        *oneDeviceData
48641120Sjdp                       )
48741120Sjdp{
48841120Sjdp  dmExpander_t      *NextExpander = agNULL;
48941120Sjdp  dmList_t          *ExpanderList;
49041120Sjdp
49141120Sjdp  DM_DBG3(("dmDownStreamDiscovering: start\n"));
49241120Sjdp
49341120Sjdp  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
49441120Sjdp  {
49541120Sjdp    DM_DBG1(("dmDownStreamDiscovering: invalid port or aborted discovery!!!\n"));
49641120Sjdp    return;
49741120Sjdp  }
49841120Sjdp
49941120Sjdp  tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
50041120Sjdp  if (DMLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList)))
50141120Sjdp  {
50241120Sjdp    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
50341120Sjdp    DM_DBG3(("dmDownStreamDiscovering: should be the end\n"));
50441120Sjdp    NextExpander = agNULL;
50541120Sjdp  }
50641120Sjdp  else
50741120Sjdp  {
50841120Sjdp    DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList));;
50941120Sjdp    NextExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
51041120Sjdp    if ( NextExpander != agNULL)
51141120Sjdp    {
51241120Sjdp      DMLIST_ENQUEUE_AT_HEAD(&(NextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));;
51341120Sjdp      DM_DBG3(("dmDownStreamDiscovering tdsaSASDownStreamDiscovering: dequeue head\n"));
51441120Sjdp      DM_DBG3(("dmDownStreamDiscovering: expander id %d\n", NextExpander->id));
51541120Sjdp    }
51641120Sjdp    else
51741120Sjdp    {
51841120Sjdp     DM_DBG1(("dmDownStreamDiscovering: NextExpander is NULL!!!\n"));
51941120Sjdp    }
52041120Sjdp    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
52141120Sjdp
52241120Sjdp  }
52341120Sjdp
52441120Sjdp  /* If there is an expander for continue discoving */
52541120Sjdp  if ( NextExpander != agNULL)
52641120Sjdp  {
52741120Sjdp    DM_DBG3(("dmDownStreamDiscovering: Found pNextExpander=%p discoveryStatus=0x%x\n",
52841120Sjdp             NextExpander, onePortContext->discovery.status));
52941120Sjdp
53041120Sjdp    switch (onePortContext->discovery.status)
53141120Sjdp    {
53241120Sjdp      /* If the discovery status is DISCOVERY_DOWN_STREAM */
53341120Sjdp    case DISCOVERY_DOWN_STREAM:
53441120Sjdp      /* Send report general for the next expander */
53541120Sjdp      DM_DBG3(("dmDownStreamDiscovering: DownStream pNextExpander=%p\n", NextExpander));
53641120Sjdp      DM_DBG3(("dmDownStreamDiscovering: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
53741120Sjdp      DM_DBG3(("dmDownStreamDiscovering: oneExpander %p did %d\n", oneDeviceData->dmExpander, oneDeviceData->dmExpander->id));
53841120Sjdp
53941120Sjdp      DM_DBG3(("dmDownStreamDiscovering: 2nd oneDeviceData %p did %d\n", NextExpander->dmDevice, NextExpander->dmDevice->id));
54041120Sjdp      DM_DBG3(("dmDownStreamDiscovering: 2nd oneExpander %p did %d\n", NextExpander, NextExpander->id));
54141120Sjdp      DM_DBG3(("dmDownStreamDiscovering: 2nd used oneExpander %p did %d\n", NextExpander->dmDevice->dmExpander, NextExpander->dmDevice->dmExpander->id));
54241120Sjdp
54341120Sjdp      if (NextExpander != NextExpander->dmDevice->dmExpander)
54441120Sjdp      {
54541120Sjdp        DM_DBG3(("dmDownStreamDiscovering: wrong!!!\n"));
54641120Sjdp      }
54741120Sjdp
54841120Sjdp
54941120Sjdp      dmReportGeneralSend(dmRoot, NextExpander->dmDevice);
550103976Spst      break;
55141120Sjdp      /* If the discovery status is DISCOVERY_CONFIG_ROUTING */
55241120Sjdp    case DISCOVERY_CONFIG_ROUTING:
55341120Sjdp    case DISCOVERY_REPORT_PHY_SATA:
55441120Sjdp
55541120Sjdp      /* set discovery status */
55641120Sjdp      onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
55741120Sjdp
55841120Sjdp      DM_DBG3(("dmDownStreamDiscovering: pPort->discovery.status=DISCOVERY_CONFIG_ROUTING, make it DOWN_STREAM\n"));
55941120Sjdp      /* If not the last phy */
56041120Sjdp      if ( NextExpander->discoveringPhyId < NextExpander->dmDevice->numOfPhys )
56141120Sjdp      {
56241120Sjdp        DM_DBG3(("dmDownStreamDiscovering: pNextExpander->discoveringPhyId=0x%x pNextExpander->numOfPhys=0x%x.  Send More Discover\n",
56341120Sjdp                 NextExpander->discoveringPhyId, NextExpander->dmDevice->numOfPhys));
56441120Sjdp        /* Send discover for the next expander */
565103976Spst        dmDiscoverSend(dmRoot, NextExpander->dmDevice);
566103976Spst        }
567103976Spst      /* If it's the last phy */
56841120Sjdp      else
56941120Sjdp      {
57041120Sjdp        DM_DBG3(("dmDownStreamDiscovering: Last Phy, remove expander%p  start DownStream=%p\n",
57141120Sjdp                 NextExpander, NextExpander->dmDevice));
572103976Spst        dmDiscoveringExpanderRemove(dmRoot, onePortContext, NextExpander);
573103976Spst        dmDownStreamDiscovering(dmRoot, onePortContext, NextExpander->dmDevice);
57441120Sjdp      }
57541120Sjdp      break;
57641120Sjdp
577103976Spst    default:
578103976Spst      DM_DBG3(("dmDownStreamDiscovering: *** Unknown pPort->discovery.status=0x%x\n", onePortContext->discovery.status));
579103976Spst    }
58041120Sjdp  }
58141120Sjdp  /* If no expander for continue discoving */
58241120Sjdp  else
58341120Sjdp  {
58441120Sjdp    DM_DBG3(("dmDownStreamDiscovering: No more expander DONE\n"));
58541120Sjdp    /* discover done */
58641120Sjdp    dmDiscoverDone(dmRoot, onePortContext, DM_RC_SUCCESS);
58741120Sjdp  }
58841120Sjdp
58941120Sjdp
59041120Sjdp  return;
59141120Sjdp}
59241120Sjdp
59341120SjdposGLOBAL void
59441120SjdpdmUpStreamDiscoverExpanderPhy(
59541120Sjdp                              dmRoot_t              *dmRoot,
59641120Sjdp                              dmIntPortContext_t    *onePortContext,
59741120Sjdp                              dmExpander_t          *oneExpander,
59841120Sjdp                              smpRespDiscover_t     *pDiscoverResp
59941120Sjdp                             )
60041120Sjdp{
60141120Sjdp  agsaSASIdentify_t       sasIdentify;
60241120Sjdp  dmSASSubID_t            dmSASSubID;
60341120Sjdp  bit32                   attachedSasHi, attachedSasLo;
60441120Sjdp  dmExpander_t            *AttachedExpander = agNULL;
60541120Sjdp  bit8                    connectionRate;
60641120Sjdp  dmDeviceData_t          *oneDeviceData = agNULL;
60741120Sjdp  dmDeviceData_t          *AttachedDevice = agNULL;
60841120Sjdp  dmIntRoot_t             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
60941120Sjdp  dmIntContext_t          *dmAllShared  = (dmIntContext_t *)&dmIntRoot->dmAllShared;
61041120Sjdp
61141120Sjdp
61241120Sjdp  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: start\n"));
61341120Sjdp
61441120Sjdp  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
61541120Sjdp  {
61641120Sjdp    DM_DBG1(("dmUpStreamDiscoverExpanderPhy: invalid port or aborted discovery!!!\n"));
61741120Sjdp    return;
61841120Sjdp  }
61941120Sjdp
62041120Sjdp  if (oneExpander != oneExpander->dmDevice->dmExpander)
62141120Sjdp  {
62241120Sjdp    DM_DBG1(("dmUpStreamDiscoverExpanderPhy: wrong!!!\n"));
62341120Sjdp  }
62441120Sjdp
62541120Sjdp  dm_memset(&sasIdentify, 0, sizeof(agsaSASIdentify_t));
62641120Sjdp
62741120Sjdp  oneDeviceData = oneExpander->dmDevice;
62841120Sjdp
62941120Sjdp  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n",
630103976Spst           oneExpander->discoveringPhyId,
631103976Spst           oneDeviceData->SASAddressID.sasAddressHi,
632103976Spst           oneDeviceData->SASAddressID.sasAddressLo));
63341120Sjdp
63441120Sjdp  DM_DBG3(("   Attached device: %s\n",
63541120Sjdp           ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" :
63641120Sjdp             (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" :
63741120Sjdp              (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
63841120Sjdp
63941120Sjdp
64041120Sjdp  if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
64141120Sjdp  {
64241120Sjdp    DM_DBG3(("   SAS address    : %08x-%08x\n",
64341120Sjdp      DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp),
64441120Sjdp              DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
64541120Sjdp    DM_DBG3(("   SSP Target     : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
64641120Sjdp    DM_DBG3(("   STP Target     : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
64741120Sjdp    DM_DBG3(("   SMP Target     : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
64841120Sjdp    DM_DBG3(("   SATA DEVICE    : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
64941120Sjdp    DM_DBG3(("   SSP Initiator  : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
65041120Sjdp    DM_DBG3(("   STP Initiator  : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
65141120Sjdp    DM_DBG3(("   SMP Initiator  : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
65241120Sjdp    DM_DBG3(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
65341120Sjdp    DM_DBG3(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
65441120Sjdp  }
65541120Sjdp
65641120Sjdp  /* for debugging */
65741120Sjdp  if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
65841120Sjdp  {
65941120Sjdp    DM_DBG1(("dmUpStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n"));
66041120Sjdp    DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d !!!\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
66141120Sjdp    dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
66241120Sjdp    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
66341120Sjdp    return;
66441120Sjdp  }
66541120Sjdp
66641120Sjdp  /* saving routing attribute for non self-configuring expanders */
66741120Sjdp  oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = (bit8)DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
66841120Sjdp
66941120Sjdp  if ( oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE )
67041120Sjdp  {
67141120Sjdp    DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_FANOUT_EXPANDER\n"));
67241120Sjdp    if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
67341120Sjdp    {
67441120Sjdp      DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing on fanout expander device!!!\n"));
67541120Sjdp
67641120Sjdp      /* discovery error */
67741120Sjdp      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
67841120Sjdp        = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
67941120Sjdp      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
68041120Sjdp        = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
68141120Sjdp      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
68241120Sjdp      DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
68341120Sjdp                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
68441120Sjdp                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
68541120Sjdp                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
68641120Sjdp
68741120Sjdp      /* (2.1.3) discovery done */
68841120Sjdp      dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
68941120Sjdp      return;
69041120Sjdp    }
69141120Sjdp  }
69241120Sjdp  else
69341120Sjdp  {
69441120Sjdp    DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_EDGE_EXPANDER\n"));
69541120Sjdp    if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
69641120Sjdp    {
69741120Sjdp      /* Setup sasIdentify for the attached device */
69841120Sjdp      sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
69941120Sjdp      sasIdentify.deviceType_addressFrameType = (bit8)(pDiscoverResp->attachedDeviceType & 0x70);
70041120Sjdp      sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
70141120Sjdp      sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
70241120Sjdp      *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
70341120Sjdp      *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
70441120Sjdp
70541120Sjdp      /* incremental discovery */
70641120Sjdp      dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
70741120Sjdp      dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
70841120Sjdp      dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
70941120Sjdp      dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
71041120Sjdp
71141120Sjdp      attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
71241120Sjdp      attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
71341120Sjdp
71441120Sjdp      /* If the phy has subtractive routing attribute */
71541120Sjdp      if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
71641120Sjdp      {
71741120Sjdp        DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_ROUTING_SUBTRACTIVE\n"));
71841120Sjdp        /* Setup upstream phys */
71941120Sjdp        dmExpanderUpStreamPhyAdd(dmRoot, oneExpander, (bit8) pDiscoverResp->attachedPhyIdentifier);
72041120Sjdp        /* If the expander already has an upsteam device set up */
72141120Sjdp        if (oneExpander->hasUpStreamDevice == agTRUE)
72241120Sjdp        {
72341120Sjdp          /* just to update MCN */
72441120Sjdp          dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
72541120Sjdp          /* If the sas address doesn't match */
72641120Sjdp          if ( ((oneExpander->upStreamSASAddressHi != attachedSasHi) ||
72741120Sjdp                (oneExpander->upStreamSASAddressLo != attachedSasLo)) &&
72841120Sjdp               (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
72941120Sjdp                DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
73041120Sjdp              )
73141120Sjdp          {
73241120Sjdp            /* TODO: discovery error, callback */
73341120Sjdp            DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n"));
73441120Sjdp            /* call back to notify discovery error */
73541120Sjdp            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
73641120Sjdp              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
73741120Sjdp            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
73841120Sjdp              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
73941120Sjdp            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
74041120Sjdp            DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
74141120Sjdp                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
74241120Sjdp                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
74341120Sjdp                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
74441120Sjdp            /* discovery done */
74541120Sjdp            dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
74641120Sjdp          }
74741120Sjdp        }
74841120Sjdp        else
74941120Sjdp        {
75041120Sjdp          /* Setup SAS address for up stream device */
75141120Sjdp          oneExpander->hasUpStreamDevice = agTRUE;
75241120Sjdp          oneExpander->upStreamSASAddressHi = attachedSasHi;
75341120Sjdp          oneExpander->upStreamSASAddressLo = attachedSasLo;
75441120Sjdp          if ( (onePortContext->sasLocalAddressHi != attachedSasHi)
75541120Sjdp              || (onePortContext->sasLocalAddressLo != attachedSasLo) )
75641120Sjdp          {
75741120Sjdp            /* Find the device from the discovered list */
75841120Sjdp            AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
75941120Sjdp            /* New device, If the device has been discovered before */
76041120Sjdp            if ( AttachedDevice != agNULL) /* old device */
76141120Sjdp            {
76241120Sjdp              DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Seen This Device Before\n"));
76341120Sjdp              /* If attached device is an edge expander */
76441120Sjdp              if ( AttachedDevice->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
76541120Sjdp              {
76641120Sjdp                /* The attached device is an expander */
76741120Sjdp                AttachedExpander = AttachedDevice->dmExpander;
76841120Sjdp                /* If the two expanders are the root of the two edge expander sets */
76941120Sjdp                if ( (AttachedExpander->upStreamSASAddressHi ==
77056141Sjdp                      DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
77141120Sjdp                     && (AttachedExpander->upStreamSASAddressLo ==
77241120Sjdp                        DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)) )
77341120Sjdp                {
77441120Sjdp                  /* Setup upstream expander for the pExpander */
77541120Sjdp                  oneExpander->dmUpStreamExpander = AttachedExpander;
77641120Sjdp                }
77741120Sjdp                /* If the two expanders are not the root of the two edge expander sets */
77841120Sjdp                else
77941120Sjdp                {
78041120Sjdp                  /* TODO: loop found, discovery error, callback */
78141120Sjdp                  DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error loop detection!!!\n"));
78241120Sjdp                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
78341120Sjdp                    = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
78441120Sjdp                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
78541120Sjdp                    = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
78641120Sjdp                  onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
78741120Sjdp                  DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
78841120Sjdp                           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
78941120Sjdp                           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
79041120Sjdp                           onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
79141120Sjdp		                /* discovery done */
79241120Sjdp                  dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
79341120Sjdp                }
79441120Sjdp              }
79541120Sjdp              /* If attached device is not an edge expander */
79641120Sjdp              else
79741120Sjdp              {
79841120Sjdp                /*TODO: should not happen, ASSERT */
79941120Sjdp                DM_DBG3(("dmUpStreamDiscoverExpanderPhy, *** Attached Device is not Edge. Confused!!!\n"));
800103976Spst              }
80141120Sjdp            } /* AttachedExpander != agNULL */
80241120Sjdp            /* New device, If the device has not been discovered before */
80341120Sjdp            else /* new device */
80441120Sjdp            {
80541120Sjdp              /* Add the device */
80641120Sjdp              DM_DBG3(("dmUpStreamDiscoverExpanderPhy: New device\n"));
80741120Sjdp              /* read minimum rate from the configuration
80841120Sjdp                 onePortContext->LinkRate is SPC's local link rate
80941120Sjdp              */
81041120Sjdp              connectionRate = (bit8)MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp));
81141120Sjdp              DM_DBG3(("dmUpStreamDiscoverExpanderPhy: link rate 0x%x\n", onePortContext->LinkRate));
81241120Sjdp              DM_DBG3(("dmUpStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp)));
81341120Sjdp              DM_DBG3(("dmUpStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate));
814103976Spst              if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
815103976Spst              {
816103976Spst                /* incremental discovery */
817103976Spst                if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
818103976Spst                {
81941120Sjdp                  AttachedDevice = dmPortSASDeviceAdd(
82041120Sjdp                                                    dmRoot,
82141120Sjdp                                                    onePortContext,
82241120Sjdp                                                    sasIdentify,
82341120Sjdp                                                    agFALSE,
82441120Sjdp                                                    connectionRate,
82541120Sjdp                                                    dmAllShared->itNexusTimeout,
82641120Sjdp                                                    0,
82741120Sjdp                                                    STP_DEVICE_TYPE,
82841120Sjdp                                                    oneDeviceData,
82941120Sjdp                                                    oneExpander,
83041120Sjdp                                                    pDiscoverResp->phyIdentifier
83141120Sjdp                                                    );
83241120Sjdp                }
83341120Sjdp                else
83441120Sjdp                {
83541120Sjdp                  /* incremental discovery */
83641120Sjdp                  AttachedDevice = dmFindRegNValid(
83741120Sjdp                                                     dmRoot,
83841120Sjdp                                                     onePortContext,
83941120Sjdp                                                     &dmSASSubID
84041120Sjdp                                                     );
84141120Sjdp                  /* not registered and not valid; add this*/
84241120Sjdp                  if (AttachedDevice == agNULL)
84365222Sache                  {
84441120Sjdp                    AttachedDevice = dmPortSASDeviceAdd(
84541120Sjdp                                                    dmRoot,
84641120Sjdp                                                    onePortContext,
84741120Sjdp                                                    sasIdentify,
84841120Sjdp                                                    agFALSE,
84941120Sjdp                                                    connectionRate,
85041120Sjdp                                                    dmAllShared->itNexusTimeout,
85141120Sjdp                                                    0,
85241120Sjdp                                                    STP_DEVICE_TYPE,
85341120Sjdp                                                    oneDeviceData,
85441120Sjdp                                                    oneExpander,
85541120Sjdp                                                    pDiscoverResp->phyIdentifier
85641120Sjdp                                                    );
857103976Spst                  }
85841120Sjdp                }
85941120Sjdp              } /* DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp) */
86041120Sjdp              else
86141120Sjdp              {
86241120Sjdp                /* incremental discovery */
86341120Sjdp                if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
86441120Sjdp                {
86541120Sjdp                  AttachedDevice = dmPortSASDeviceAdd(
86641120Sjdp                                                    dmRoot,
86741120Sjdp                                                    onePortContext,
86841120Sjdp                                                    sasIdentify,
86941120Sjdp                                                    agFALSE,
87041120Sjdp                                                    connectionRate,
87141120Sjdp                                                    dmAllShared->itNexusTimeout,
87241120Sjdp                                                    0,
87341120Sjdp                                                    SAS_DEVICE_TYPE,
87441120Sjdp                                                    oneDeviceData,
87541120Sjdp                                                    oneExpander,
87641120Sjdp                                                    pDiscoverResp->phyIdentifier
87741120Sjdp                                                    );
87841120Sjdp                }
87941120Sjdp                else
88041120Sjdp                {
88141120Sjdp                  /* incremental discovery */
88241120Sjdp                  AttachedDevice = dmFindRegNValid(
88341120Sjdp                                                     dmRoot,
88441120Sjdp                                                     onePortContext,
88541120Sjdp                                                     &dmSASSubID
88641120Sjdp                                                     );
88741120Sjdp                  /* not registered and not valid; add this*/
88841120Sjdp                  if (AttachedDevice == agNULL)
88965222Sache                  {
89065222Sache                    AttachedDevice = dmPortSASDeviceAdd(
89165222Sache                                                    dmRoot,
89241120Sjdp                                                    onePortContext,
89341120Sjdp                                                    sasIdentify,
89441120Sjdp                                                    agFALSE,
89541120Sjdp                                                    connectionRate,
89641120Sjdp                                                    dmAllShared->itNexusTimeout,
89741120Sjdp                                                    0,
89841120Sjdp                                                    SAS_DEVICE_TYPE,
89941120Sjdp                                                    oneDeviceData,
90041120Sjdp                                                    oneExpander,
90141120Sjdp                                                    pDiscoverResp->phyIdentifier
90241120Sjdp                                                    );
90341120Sjdp                  }
90441120Sjdp                }
90541120Sjdp              }
90641120Sjdp               /* If the device is added successfully */
90741120Sjdp              if ( AttachedDevice != agNULL)
90841120Sjdp              {
90941120Sjdp
91041120Sjdp                 /* (3.1.2.3.2.3.2.1) callback about new device */
91141120Sjdp                if ( DISCRSP_IS_SSP_TARGET(pDiscoverResp)
91241120Sjdp                    || DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)
91341120Sjdp                    || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)
91441120Sjdp                    || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) )
91541120Sjdp                {
91641120Sjdp                  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found SSP/SMP SAS %08x-%08x\n",
91741120Sjdp                      attachedSasHi, attachedSasLo));
91841120Sjdp                }
91941120Sjdp                else
92041120Sjdp                {
92141120Sjdp                  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found a SAS STP device.\n"));
92241120Sjdp                }
92341120Sjdp                 /* If the attached device is an expander */
92441120Sjdp                if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
92541120Sjdp                    || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) )
92641120Sjdp                {
92741120Sjdp                  /* Allocate an expander data structure */
92841120Sjdp                  AttachedExpander = dmDiscoveringExpanderAlloc(
92941120Sjdp                                                                dmRoot,
93041120Sjdp                                                                onePortContext,
93141120Sjdp                                                                AttachedDevice
93241120Sjdp								                                                       );
93341120Sjdp
93441120Sjdp                  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found expander=%p\n", AttachedExpander));
93541120Sjdp                  /* If allocate successfully */
93641120Sjdp                  if ( AttachedExpander != agNULL)
93741120Sjdp                  {
93841120Sjdp                    /* Add the pAttachedExpander to discovering list */
93941120Sjdp                    dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
94041120Sjdp                    /* Setup upstream expander for the pExpander */
94141120Sjdp                    oneExpander->dmUpStreamExpander = AttachedExpander;
94241120Sjdp                  }
94341120Sjdp                  /* If failed to allocate */
94441120Sjdp                  else
945103976Spst                  {
94641120Sjdp                    DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Failed to allocate expander data structure!!!\n"));
947103976Spst                    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
94841120Sjdp                  }
94941120Sjdp                }
95041120Sjdp                /* If the attached device is an end device */
95141120Sjdp                else
95241120Sjdp                {
953103976Spst                  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found end device\n"));
954103976Spst                  /* LP2006-05-26 added upstream device to the newly found device */
955103976Spst                  AttachedDevice->dmExpander = oneExpander;
956103976Spst                  oneExpander->dmUpStreamExpander = agNULL;
957103976Spst                }
958103976Spst              }
959103976Spst              else
960103976Spst              {
961103976Spst                DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Failed to add a device!!!\n"));
962103976Spst                dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
963103976Spst              }
964103976Spst
965103976Spst
966103976Spst
967103976Spst            } /* else, new device */
968103976Spst          } /* onePortContext->sasLocalAddressLo != attachedSasLo */
969103976Spst        } /* else */
970103976Spst      } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE */
971103976Spst    } /* DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE */
972200399Ssyrinx  } /* big else */
973200399Ssyrinx
974200399Ssyrinx
975200399Ssyrinx
976200399Ssyrinx   oneExpander->discoveringPhyId ++;
977200399Ssyrinx   if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
978200399Ssyrinx     {
979200399Ssyrinx       if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
980200399Ssyrinx       {
981200399Ssyrinx         DM_DBG3(("dmUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM find more ...\n"));
982200399Ssyrinx         /* continue discovery for the next phy */
983200399Ssyrinx         dmDiscoverSend(dmRoot, oneDeviceData);
984200399Ssyrinx       }
985200399Ssyrinx       else
986200399Ssyrinx       {
987200399Ssyrinx         DM_DBG3(("dmUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM last phy continue upstream..\n"));
988200399Ssyrinx
989103976Spst         /* for MCN */
990103976Spst         dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
991103976Spst         /* remove the expander from the discovering list */
992103976Spst         dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
993103976Spst         /* continue upstream discovering */
994103976Spst         dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
995103976Spst       }
996103976Spst   }
997103976Spst   else
998103976Spst   {
999103976Spst      DM_DBG3(("dmUpStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));
1000103976Spst
1001103976Spst   }
100241120Sjdp
100341120Sjdp  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
100441120Sjdp
100541120Sjdp  return;
100641120Sjdp}
100741120Sjdp
1008103976SpstosGLOBAL void
1009103976SpstdmUpStreamDiscover2ExpanderPhy(
101041120Sjdp                              dmRoot_t              *dmRoot,
101141120Sjdp                              dmIntPortContext_t    *onePortContext,
101241120Sjdp                              dmExpander_t          *oneExpander,
101341120Sjdp                              smpRespDiscover2_t    *pDiscoverResp
101441120Sjdp                              )
101541120Sjdp{
101641120Sjdp  dmDeviceData_t          *oneDeviceData;
101741120Sjdp  dmDeviceData_t          *AttachedDevice = agNULL;
101841120Sjdp  dmExpander_t            *AttachedExpander;
101941120Sjdp  agsaSASIdentify_t       sasIdentify;
102041120Sjdp  bit8                    connectionRate;
1021103976Spst  bit32                   attachedSasHi, attachedSasLo;
102241120Sjdp  dmSASSubID_t            dmSASSubID;
102341120Sjdp  dmIntRoot_t             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
102441120Sjdp  dmIntContext_t          *dmAllShared  = (dmIntContext_t *)&dmIntRoot->dmAllShared;
102541120Sjdp
102641120Sjdp  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: start\n"));
102741120Sjdp
102841120Sjdp  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
102941120Sjdp  {
103041120Sjdp    DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: invalid port or aborted discovery!!!\n"));
103141120Sjdp    return;
1032103976Spst  }
103341120Sjdp
103441120Sjdp  if (oneExpander != oneExpander->dmDevice->dmExpander)
103541120Sjdp  {
103641120Sjdp    DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: wrong!!!\n"));
103741120Sjdp  }
103841120Sjdp
103941120Sjdp  dm_memset(&sasIdentify, 0, sizeof(agsaSASIdentify_t));
104041120Sjdp
104141120Sjdp  oneDeviceData = oneExpander->dmDevice;
104241120Sjdp
104341120Sjdp  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Phy #%d of SAS %08x-%08x\n",
104441120Sjdp           oneExpander->discoveringPhyId,
104541120Sjdp           oneDeviceData->SASAddressID.sasAddressHi,
1046103976Spst           oneDeviceData->SASAddressID.sasAddressLo));
1047103976Spst
1048103976Spst  DM_DBG2(("   Attached device: %s\n",
1049103976Spst           ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" :
105041120Sjdp             (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" :
105141120Sjdp              (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
105241120Sjdp
105341120Sjdp
105441120Sjdp  if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
105541120Sjdp  {
105641120Sjdp    DM_DBG2(("   SAS address    : %08x-%08x\n",
105741120Sjdp      SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp),
105841120Sjdp              SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
105941120Sjdp    DM_DBG2(("   SSP Target     : %d\n", SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
106041120Sjdp    DM_DBG2(("   STP Target     : %d\n", SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
106141120Sjdp    DM_DBG2(("   SMP Target     : %d\n", SAS2_DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
1062103976Spst    DM_DBG2(("   SATA DEVICE    : %d\n", SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
1063103976Spst    DM_DBG2(("   SSP Initiator  : %d\n", SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
1064103976Spst    DM_DBG2(("   STP Initiator  : %d\n", SAS2_DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
106541120Sjdp    DM_DBG2(("   SMP Initiator  : %d\n", SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
106641120Sjdp    DM_DBG2(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
106741120Sjdp    DM_DBG2(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
106841120Sjdp  }
106941120Sjdp
107041120Sjdp  if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
107141120Sjdp  {
107241120Sjdp    DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: !!! Incorrect SMP response !!!\n"));
107341120Sjdp    DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
107441120Sjdp    dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover2_t));
107541120Sjdp    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
107641120Sjdp    return;
107741120Sjdp  }
107841120Sjdp
107941120Sjdp  /* saving routing attribute for non self-configuring expanders */
108041120Sjdp  oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
108141120Sjdp
108241120Sjdp  if ( oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE )
108341120Sjdp  {
108441120Sjdp    DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_DEV_TYPE_FANOUT_EXPANDER\n"));
108541120Sjdp    if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
108641120Sjdp    {
108741120Sjdp      DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing on fanout expander device!!!\n"));
108841120Sjdp
108941120Sjdp      /* discovery error */
109041120Sjdp      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
109141120Sjdp        = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
109241120Sjdp      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
109341120Sjdp        = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
109441120Sjdp      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1095103976Spst      DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1096103976Spst                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
109741120Sjdp                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
109841120Sjdp                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
109941120Sjdp
110041120Sjdp      /* (2.1.3) discovery done */
110141120Sjdp      dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
110241120Sjdp      return;
110341120Sjdp    }
110441120Sjdp  }
110541120Sjdp  else
110641120Sjdp  {
110741120Sjdp    DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_DEV_TYPE_EDGE_EXPANDER\n"));
110841120Sjdp
110941120Sjdp    if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
1110103976Spst    {
1111103976Spst      /* Setup sasIdentify for the attached device */
1112103976Spst      sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
1113103976Spst      sasIdentify.deviceType_addressFrameType = pDiscoverResp->attachedDeviceTypeReason & 0x70;
1114103976Spst      sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
1115103976Spst      sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
1116103976Spst      *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
1117103976Spst      *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
1118103976Spst
1119103976Spst      /* incremental discovery */
1120103976Spst      dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
1121103976Spst      dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
1122103976Spst      dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
1123103976Spst      dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
1124103976Spst
1125103976Spst      attachedSasHi = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
1126103976Spst      attachedSasLo = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
1127103976Spst
1128103976Spst      /* If the phy has subtractive routing attribute */
1129103976Spst      if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
1130103976Spst      {
1131103976Spst        DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_ROUTING_SUBTRACTIVE\n"));
1132103976Spst        /* Setup upstream phys */
1133103976Spst        dmExpanderUpStreamPhyAdd(dmRoot, oneExpander, (bit8) pDiscoverResp->attachedPhyIdentifier);
1134103976Spst        /* If the expander already has an upsteam device set up */
1135103976Spst        if (oneExpander->hasUpStreamDevice == agTRUE)
1136103976Spst        {
1137103976Spst          /* just to update MCN */
1138103976Spst          dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
1139103976Spst          /* If the sas address doesn't match */
1140103976Spst          if ( ((oneExpander->upStreamSASAddressHi != attachedSasHi) ||
1141103976Spst                (oneExpander->upStreamSASAddressLo != attachedSasLo)) &&
1142103976Spst               (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
1143103976Spst                SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1144103976Spst              )
1145103976Spst          {
1146103976Spst            /* TODO: discovery error, callback */
1147103976Spst            DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n"));
1148103976Spst            /* call back to notify discovery error */
1149103976Spst            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1150103976Spst              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1151103976Spst            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1152103976Spst              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1153103976Spst            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1154103976Spst            DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1155103976Spst                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1156103976Spst                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1157103976Spst                      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1158103976Spst            /* discovery done */
1159103976Spst            dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1160103976Spst          }
1161103976Spst        }
1162103976Spst        else
1163103976Spst        {
1164103976Spst          /* Setup SAS address for up stream device */
1165103976Spst          oneExpander->hasUpStreamDevice = agTRUE;
1166103976Spst          oneExpander->upStreamSASAddressHi = attachedSasHi;
1167103976Spst          oneExpander->upStreamSASAddressLo = attachedSasLo;
1168103976Spst
1169103976Spst          if ( (onePortContext->sasLocalAddressHi != attachedSasHi)
1170103976Spst              || (onePortContext->sasLocalAddressLo != attachedSasLo) )
1171103976Spst          {
1172103976Spst            /* Find the device from the discovered list */
1173103976Spst            AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
1174103976Spst            /* If the device has been discovered before */
1175103976Spst            if ( AttachedDevice != agNULL)
1176103976Spst            {
1177103976Spst              DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Seen This Device Before\n"));
1178103976Spst              /* If attached device is an edge expander */
1179103976Spst              if ( AttachedDevice->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
1180200399Ssyrinx              {
1181200399Ssyrinx                /* The attached device is an expander */
1182200399Ssyrinx                AttachedExpander = AttachedDevice->dmExpander;
1183200399Ssyrinx                /* If the two expanders are the root of the two edge expander sets */
1184200399Ssyrinx                if ( (AttachedExpander->upStreamSASAddressHi ==
1185200399Ssyrinx                      DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
1186200399Ssyrinx                     && (AttachedExpander->upStreamSASAddressLo ==
1187200399Ssyrinx                        DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)) )
1188200399Ssyrinx                {
1189200399Ssyrinx                  /* Setup upstream expander for the pExpander */
1190200399Ssyrinx                  oneExpander->dmUpStreamExpander = AttachedExpander;
1191200399Ssyrinx                }
1192200399Ssyrinx                /* If the two expanders are not the root of the two edge expander sets */
1193200399Ssyrinx                else
1194200399Ssyrinx                {
1195200399Ssyrinx                  /* TODO: loop found, discovery error, callback */
1196200399Ssyrinx                  DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error loop detection!!!\n"));
1197200399Ssyrinx                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1198200399Ssyrinx                    = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1199200399Ssyrinx                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1200200399Ssyrinx                    = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1201200399Ssyrinx                  onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1202200399Ssyrinx                  DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1203200399Ssyrinx                            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1204200399Ssyrinx                            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1205200399Ssyrinx                            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1206200399Ssyrinx                  /* discovery done */
1207200399Ssyrinx                  dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1208200399Ssyrinx                }
1209200399Ssyrinx              }
1210200399Ssyrinx              /* If attached device is not an edge expander */
1211200399Ssyrinx              else
1212200399Ssyrinx              {
1213200399Ssyrinx                /*TODO: should not happen, ASSERT */
1214200399Ssyrinx                DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, *** Attached Device is not Edge. Confused!!!\n"));
1215200399Ssyrinx              }
1216200399Ssyrinx            }
1217200399Ssyrinx            /* If the device has not been discovered before */
1218200399Ssyrinx            else
1219200399Ssyrinx            {
1220200399Ssyrinx              /* Add the device */
1221200399Ssyrinx              DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: New device\n"));
1222200399Ssyrinx              /* read minimum rate from the configuration
122341120Sjdp                 onePortContext->LinkRate is SPC's local link rate
122441120Sjdp              */
122541120Sjdp              connectionRate = MIN(onePortContext->LinkRate, SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pDiscoverResp));
122641120Sjdp              DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: link rate 0x%x\n", onePortContext->LinkRate));
122741120Sjdp              DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: negotiatedPhyLinkRate 0x%x\n", SAS2_DISCRSP_GET_LINKRATE(pDiscoverResp)));
122841120Sjdp              DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: connectionRate 0x%x\n", connectionRate));
122941120Sjdp              //hhhhhhhh
123041120Sjdp              if (SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
123141120Sjdp              {
123241120Sjdp                /* incremental discovery */
123341120Sjdp                if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
123441120Sjdp                {
123541120Sjdp                  AttachedDevice = dmPortSASDeviceAdd(
123641120Sjdp                                                    dmRoot,
123741120Sjdp                                                    onePortContext,
123841120Sjdp                                                    sasIdentify,
123941120Sjdp                                                    agFALSE,
124041120Sjdp                                                    connectionRate,
124141120Sjdp                                                    dmAllShared->itNexusTimeout,
124241120Sjdp                                                    0,
124341120Sjdp                                                    STP_DEVICE_TYPE,
124441120Sjdp                                                    oneDeviceData,
124541120Sjdp                                                    oneExpander,
124641120Sjdp                                                    pDiscoverResp->phyIdentifier
124741120Sjdp                                                    );
124841120Sjdp                }
124941120Sjdp                else
125041120Sjdp                {
125141120Sjdp                  /* incremental discovery */
125241120Sjdp                  AttachedDevice = dmFindRegNValid(
125341120Sjdp                                                     dmRoot,
125441120Sjdp                                                     onePortContext,
125541120Sjdp                                                     &dmSASSubID
125641120Sjdp                                                     );
125741120Sjdp                  /* not registered and not valid; add this*/
125841120Sjdp                  if (AttachedDevice == agNULL)
125941120Sjdp                  {
126041120Sjdp                    AttachedDevice = dmPortSASDeviceAdd(
126141120Sjdp                                                    dmRoot,
126241120Sjdp                                                    onePortContext,
1263103976Spst                                                    sasIdentify,
1264103976Spst                                                    agFALSE,
1265103976Spst                                                    connectionRate,
1266103976Spst                                                    dmAllShared->itNexusTimeout,
1267103976Spst                                                    0,
1268103976Spst                                                    STP_DEVICE_TYPE,
1269103976Spst                                                    oneDeviceData,
1270103976Spst                                                    oneExpander,
1271103976Spst                                                    pDiscoverResp->phyIdentifier
1272103976Spst                                                    );
1273103976Spst                  }
1274103976Spst                }
1275103976Spst              }
1276103976Spst              else
1277103976Spst              {
1278103976Spst                /* incremental discovery */
1279103976Spst                if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
1280103976Spst                {
1281103976Spst                  AttachedDevice = dmPortSASDeviceAdd(
1282103976Spst                                                    dmRoot,
1283103976Spst                                                    onePortContext,
1284103976Spst                                                    sasIdentify,
1285103976Spst                                                    agFALSE,
1286103976Spst                                                    connectionRate,
1287103976Spst                                                    dmAllShared->itNexusTimeout,
1288103976Spst                                                    0,
1289103976Spst                                                    SAS_DEVICE_TYPE,
1290103976Spst                                                    oneDeviceData,
1291103976Spst                                                    oneExpander,
1292103976Spst                                                    pDiscoverResp->phyIdentifier
1293103976Spst                                                    );
1294103976Spst                }
1295103976Spst                else
1296103976Spst                {
1297103976Spst                  /* incremental discovery */
1298103976Spst                  AttachedDevice = dmFindRegNValid(
1299103976Spst                                                     dmRoot,
1300103976Spst                                                     onePortContext,
1301103976Spst                                                     &dmSASSubID
1302103976Spst                                                     );
1303103976Spst                  /* not registered and not valid; add this*/
1304103976Spst                  if (AttachedDevice == agNULL)
1305103976Spst                  {
1306103976Spst                    AttachedDevice = dmPortSASDeviceAdd(
1307103976Spst                                                    dmRoot,
1308103976Spst                                                    onePortContext,
1309103976Spst                                                    sasIdentify,
1310103976Spst                                                    agFALSE,
1311103976Spst                                                    connectionRate,
1312103976Spst                                                    dmAllShared->itNexusTimeout,
1313103976Spst                                                    0,
1314103976Spst                                                    SAS_DEVICE_TYPE,
1315103976Spst                                                    oneDeviceData,
1316103976Spst                                                    oneExpander,
1317103976Spst                                                    pDiscoverResp->phyIdentifier
1318103976Spst                                                    );
1319103976Spst                  }
1320103976Spst                }
1321103976Spst              }
1322103976Spst              /* If the device is added successfully */
1323103976Spst              if ( AttachedDevice != agNULL)
1324103976Spst              {
1325103976Spst
1326103976Spst                 /* (3.1.2.3.2.3.2.1) callback about new device */
1327103976Spst                if ( SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp)
1328199802Sattilio                    || SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)
1329199802Sattilio                    || SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)
1330199802Sattilio                    || SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) )
1331199802Sattilio                {
1332202751Semaste                  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found SSP/SMP SAS %08x-%08x\n",
1333103976Spst                      attachedSasHi, attachedSasLo));
1334199802Sattilio                }
1335103976Spst                else
1336103976Spst                {
1337103976Spst                  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found a SAS STP device.\n"));
1338103976Spst                }
1339103976Spst                 /* If the attached device is an expander */
1340103976Spst                if ( (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
1341103976Spst                    || (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) )
1342103976Spst                {
1343103976Spst                  /* Allocate an expander data structure */
1344103976Spst                  AttachedExpander = dmDiscoveringExpanderAlloc(
1345103976Spst                                                                dmRoot,
1346103976Spst                                                                onePortContext,
1347103976Spst                                                                AttachedDevice
1348103976Spst                                                               );
1349103976Spst
1350103976Spst                  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found expander=%p\n", AttachedExpander));
1351103976Spst                  /* If allocate successfully */
1352103976Spst                  if ( AttachedExpander != agNULL)
1353103976Spst                  {
1354103976Spst                    /* Add the pAttachedExpander to discovering list */
1355103976Spst                    dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
1356103976Spst                    /* Setup upstream expander for the pExpander */
1357103976Spst                    oneExpander->dmUpStreamExpander = AttachedExpander;
1358103976Spst                  }
1359103976Spst                  /* If failed to allocate */
1360103976Spst                  else
136141120Sjdp                  {
136241120Sjdp                    DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, Failed to allocate expander data structure!!!\n"));
136341120Sjdp                    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
136441120Sjdp                  }
136541120Sjdp                }
136641120Sjdp                /* If the attached device is an end device */
136741120Sjdp                else
136841120Sjdp                {
136941120Sjdp                  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found end device\n"));
137041120Sjdp                  /* LP2006-05-26 added upstream device to the newly found device */
137141120Sjdp                  AttachedDevice->dmExpander = oneExpander;
137241120Sjdp                  oneExpander->dmUpStreamExpander = agNULL;
137341120Sjdp                }
137441120Sjdp              }
137541120Sjdp              else
137641120Sjdp              {
137741120Sjdp                DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, Failed to add a device!!!\n"));
137841120Sjdp                dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
137941120Sjdp              }
138041120Sjdp            }
138141120Sjdp          }
138241120Sjdp        }
138341120Sjdp      } /* substractive routing */
138441120Sjdp    }
138541120Sjdp  }
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
1420osGLOBAL void
1421dmDownStreamDiscoverExpanderPhy(
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*/
2159osGLOBAL bit32
2160dmSAS2SAS11ErrorCheck(
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
2231osGLOBAL void
2232dmDownStreamDiscover2ExpanderPhy(
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
3044osGLOBAL void
3045dmDiscoveringUndoAdd(
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
3101osGLOBAL void
3102dmHandleZoneViolation(
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
3142osGLOBAL void
3143dmUpStreamDiscoverExpanderPhySkip(
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
3190osGLOBAL void
3191dmUpStreamDiscover2ExpanderPhySkip(
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
3234osGLOBAL void
3235dmDownStreamDiscoverExpanderPhySkip(
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
3284osGLOBAL void
3285dmDownStreamDiscover2ExpanderPhySkip(
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
3330osGLOBAL void
3331dmExpanderUpStreamPhyAdd(
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
3369osGLOBAL void
3370dmExpanderDownStreamPhyAdd(
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
3408osGLOBAL void
3409dmDiscoveryReportMCN(
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
3498osGLOBAL void
3499dmDiscoveryDumpMCN(
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
3533osGLOBAL void
3534dmDiscoveryResetMCN(
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/*
3579do min(oneDeviceData, found-one) in all upstream and downstream
3580find ajcanent expanders and mark it done; sees only ajcacent targets
3581*/
3582osGLOBAL void
3583dmUpdateAllAdjacent(
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
3638osGLOBAL void
3639dmUpdateMCN(
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 ??? */
3702osGLOBAL dmDeviceData_t *
3703dmPortSASDeviceFind(
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
3787bit32
3788dmNewEXPorNot(
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
3830bit32
3831dmNewSASorNot(
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/*
3871call
3872osGLOBAL bit32
3873tddmReportDevice(
3874                 dmRoot_t 		*dmRoot,
3875                 dmPortContext_t	*dmPortContext,
3876                 dmDeviceInfo_t		*dmDeviceInfo
3877                 )
3878if not reported, report Device to TDM
3879*/
3880osGLOBAL dmDeviceData_t *
3881dmPortSASDeviceAdd(
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
4236osGLOBAL dmDeviceData_t *
4237dmFindRegNValid(
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
4320osGLOBAL void
4321dmNotifyBC(
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 */
4375osGLOBAL void
4376dmNotifyBC(
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
4433osGLOBAL bit32
4434dmResetFailedDiscovery(
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
4463osGLOBAL bit32
4464dmQueryDiscovery(
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*/
4501osGLOBAL bit32
4502dmRegisterDevice(
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()
4534osGLOBAL void
4535tdssAddSASToSharedcontext(
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                          );
4544from discovery
4545osGLOBAL tdsaDeviceData_t *
4546tdssNewAddSASToSharedcontext(
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
4649osGLOBAL dmExpander_t *
4650dmDiscoveringExpanderAlloc(
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
4728osGLOBAL void
4729dmDiscoveringExpanderAdd(
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
4771osGLOBAL dmExpander_t *
4772dmFindConfigurableExp(
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
4820osGLOBAL bit32
4821dmDuplicateConfigSASAddr(
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
4875osGLOBAL bit16
4876dmFindCurrentDownStreamPhyIndex(
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
4924osGLOBAL bit32
4925dmFindDiscoveringExpander(
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
4971osGLOBAL void
4972dmDiscoveringExpanderRemove(
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*/
5047osGLOBAL dmExpander_t *
5048dmExpMainListFind(
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*/
5104osGLOBAL dmExpander_t *
5105dmExpFind(
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
5153osGLOBAL bit32
5154dmDiscoverCheck(
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*/
5190osGLOBAL void
5191dmDiscoverAbort(
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 */
5219osGLOBAL void
5220dmCleanAllExp(
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
5353osGLOBAL void
5354dmInternalRemovals(
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
5426osGLOBAL void
5427dmDiscoveryResetProcessed(
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
5463osGLOBAL void
5464tddmDiscoverCB(
5465               dmRoot_t 		*dmRoot,
5466               dmPortContext_t		*dmPortContext,
5467               bit32			eventStatus
5468              )
5469
5470*/
5471osGLOBAL void
5472dmDiscoverDone(
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 */
5591osGLOBAL void
5592dmSubReportRemovals(
5593                   dmRoot_t                  *dmRoot,
5594                   dmIntPortContext_t        *onePortContext,
5595                   dmDeviceData_t            *oneDeviceData,
5596                   bit32                     flag
5597                  )
5598{
5599  dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
5600  DM_DBG3(("dmSubReportRemovals: start\n"));
5601
5602  DM_DBG3(("dmSubReportRemovals: flag 0x%x\n", flag));
5603  if (flag == dmDeviceRemoval)
5604  {
5605    oneDeviceData->registered = agFALSE;
5606  }
5607
5608  if (oneDeviceData->ExpDevice != agNULL)
5609  {
5610    DM_DBG3(("dmSubReportRemovals: attached expander case\n"));
5611    oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
5612    tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, flag);
5613  }
5614  else
5615  {
5616    DM_DBG3(("dmSubReportRemovals: NO attached expander case\n"));
5617    tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, flag);
5618  }
5619
5620
5621  /* this function is called at the end of discovery; reinitalizes oneDeviceData->reported */
5622  oneDeviceData->reported = agFALSE;
5623  return;
5624}
5625
5626
5627/* called by dmReportChanges() on discovery success */
5628osGLOBAL void
5629dmSubReportChanges(
5630                   dmRoot_t                  *dmRoot,
5631                   dmIntPortContext_t        *onePortContext,
5632		   dmDeviceData_t            *oneDeviceData,
5633                   bit32                     flag
5634                  )
5635{
5636  dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
5637  DM_DBG3(("dmSubReportChanges: start\n"));
5638
5639  DM_DBG3(("dmSubReportChanges: flag 0x%x\n", flag));
5640  if (flag == dmDeviceRemoval)
5641  {
5642    oneDeviceData->registered = agFALSE;
5643  }
5644  if (oneDeviceData->reported == agFALSE)
5645  {
5646    if (oneDeviceData->ExpDevice != agNULL)
5647    {
5648      DM_DBG3(("dmSubReportChanges: attached expander case\n"));
5649      oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
5650      tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, flag);
5651    }
5652    else
5653    {
5654      DM_DBG3(("dmSubReportChanges: NO attached expander case\n"));
5655      tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, flag);
5656    }
5657  }
5658  else
5659  {
5660    DM_DBG3(("dmSubReportChanges: skip; been reported\n"));
5661  }
5662
5663
5664  /* this function is called at the end of discovery; reinitalizes oneDeviceData->reported */
5665  oneDeviceData->reported = agFALSE;
5666  return;
5667}
5668
5669/*
5670 should add or remove be reported per device???
5671*/
5672osGLOBAL void
5673dmReportChanges(
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
5762tddmReportDevice(
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
5828osGLOBAL void
5829dmReportRemovals(
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
5947osGLOBAL void
5948dmResetReported(
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 */
6011osGLOBAL void
6012dmDiscoveryInvalidateDevices(
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*/
6099osGLOBAL void
6100dmDiscoveryErrorRemovals(
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 */
6182osGLOBAL void
6183dmDiscoveryExpanderCleanUp(
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 */
6256osGLOBAL void
6257dmDiscoveryDeviceCleanUp(
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
6319osGLOBAL void
6320dmDumpAllExp(
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
6331osGLOBAL void
6332dmDumpAllUpExp(
6333               dmRoot_t                  *dmRoot,
6334               dmIntPortContext_t        *onePortContext,
6335               dmExpander_t              *oneExpander
6336              )
6337{
6338  DM_DBG3(("dmDumpAllUpExp: start\n"));
6339  return;
6340}
6341
6342osGLOBAL void
6343dmDumpAllFreeExp(
6344                 dmRoot_t                  *dmRoot
6345                )
6346{
6347  DM_DBG3(("dmDumpAllFreeExp: start\n"));
6348  return;
6349}
6350
6351osGLOBAL void
6352dmDumpAllMainExp(
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
6401osGLOBAL void
6402dmDumpAllMainDevice(
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
6457osGLOBAL dmDeviceData_t *
6458dmAddSASToSharedcontext(
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 */
6659osGLOBAL dmDeviceData_t *
6660dmDeviceFind(
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
6714osGLOBAL void
6715dmBCTimer(
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
6767osGLOBAL void
6768dmBCTimerCB(
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 */
6810osGLOBAL void
6811dmDiscoverySMPTimer(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
6862osGLOBAL void
6863dmDiscoverySMPTimerCB(
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
6991osGLOBAL void
6992dmSMPBusyTimer(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
7041osGLOBAL void
7042dmSMPBusyTimerCB(
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 */
7163osGLOBAL void
7164dmDiscoveryConfiguringTimer(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
7216osGLOBAL void
7217dmDiscoveryConfiguringTimerCB(
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
7255osGLOBAL void
7256dmConfigureRouteTimer(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
7334osGLOBAL void
7335dmConfigureRouteTimerCB(
7336                        dmRoot_t    * dmRoot,
7337                        void        * timerData1,
7338                        void        * timerData2,
7339                        void        * timerData3
7340                       )
7341{
7342  dmIntRoot_t         *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
7343  dmIntContext_t      *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7344  dmIntPortContext_t  *onePortContext;
7345  dmExpander_t        *oneExpander;
7346  smpRespDiscover_t   *pdmSMPDiscoverResp = agNULL;
7347  smpRespDiscover2_t  *pdmSMPDiscover2Resp = agNULL;
7348  dmDiscovery_t       *discovery;
7349
7350
7351  DM_DBG3(("dmConfigureRouteTimerCB: start\n"));
7352
7353  onePortContext = (dmIntPortContext_t *)timerData1;
7354  oneExpander = (dmExpander_t *)timerData2;
7355  if (oneExpander->SAS2 == 0)
7356  {
7357    pdmSMPDiscoverResp = (smpRespDiscover_t *)timerData3;
7358  }
7359  else
7360  {
7361    pdmSMPDiscover2Resp = (smpRespDiscover2_t *)timerData3;
7362  }
7363  discovery = &(onePortContext->discovery);
7364
7365  DM_DBG3(("dmConfigureRouteTimerCB: onePortContext %p oneExpander %p pdmSMPDiscoverResp %p\n", onePortContext, oneExpander, pdmSMPDiscoverResp));
7366
7367  DM_DBG3(("dmConfigureRouteTimerCB: discovery %p\n", discovery));
7368
7369  DM_DBG3(("dmConfigureRouteTimerCB: pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries));
7370
7371  DM_DBG3(("dmConfigureRouteTimerCB: discovery.status %d\n", discovery->status));
7372
7373  discovery->configureRouteRetries++;
7374  if (discovery->configureRouteRetries >= dmAllShared->MaxRetryDiscovery)
7375  {
7376    DM_DBG3(("dmConfigureRouteTimerCB: retries are over\n"));
7377
7378    tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7379    if (discovery->configureRouteTimer.timerRunning == agTRUE)
7380    {
7381      tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7382      dmKillTimer(
7383                  dmRoot,
7384                  &discovery->configureRouteTimer
7385                  );
7386    }
7387    else
7388    {
7389      tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7390    }
7391
7392    discovery->configureRouteRetries = 0;
7393    /* failed the discovery */
7394    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
7395
7396    return;
7397  }
7398
7399
7400  if (oneExpander->SAS2 == 0)
7401  {
7402    if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
7403    {
7404      DM_DBG3(("dmConfigureRouteTimerCB: proceed by calling dmDownStreamDiscoverExpanderPhy\n"));
7405      dmhexdump("dmConfigureRouteTimerCB", (bit8*)pdmSMPDiscoverResp, sizeof(smpRespDiscover_t));
7406      discovery->configureRouteRetries = 0;
7407
7408      dmDownStreamDiscoverExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp);
7409    }
7410    else
7411    {
7412      DM_DBG3(("dmConfigureRouteTimerCB: setting timer again\n"));
7413      /* set the timer again */
7414      dmSetTimerRequest(
7415                        dmRoot,
7416                        &discovery->configureRouteTimer,
7417                        CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick,
7418                        dmConfigureRouteTimerCB,
7419                        (void *)onePortContext,
7420                        (void *)oneExpander,
7421                        (void *)pdmSMPDiscoverResp
7422                       );
7423
7424      dmAddTimer (
7425                  dmRoot,
7426                  &dmAllShared->timerlist,
7427                  &discovery->configureRouteTimer
7428                  );
7429    }
7430  } /* SAS 1.1 */
7431  else
7432  {
7433    /* SAS 2 */
7434    if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
7435    {
7436      DM_DBG2(("dmConfigureRouteTimerCB: proceed by calling dmDownStreamDiscover2ExpanderPhy\n"));
7437      dmhexdump("dmConfigureRouteTimerCB", (bit8*)pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t));
7438
7439      dmDownStreamDiscover2ExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscover2Resp);
7440    }
7441    else
7442    {
7443      DM_DBG2(("dmConfigureRouteTimerCB: setting timer again\n"));
7444      /* set the timer again */
7445      dmSetTimerRequest(
7446                        dmRoot,
7447                        &discovery->configureRouteTimer,
7448                        CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick,
7449                        dmConfigureRouteTimerCB,
7450                        (void *)onePortContext,
7451                        (void *)oneExpander,
7452                        (void *)pdmSMPDiscover2Resp
7453                       );
7454
7455      dmAddTimer (
7456                  dmRoot,
7457                  &dmAllShared->timerlist,
7458                  &discovery->configureRouteTimer
7459                 );
7460    }
7461  }
7462
7463  return;
7464}
7465#endif /* FDS_ DM */
7466
7467