1285809Sscottl/*******************************************************************************
2285809Sscottl**
3285809Sscottl*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
4285809Sscottl*
5285809Sscottl*Redistribution and use in source and binary forms, with or without modification, are permitted provided
6285809Sscottl*that the following conditions are met:
7285809Sscottl*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8285809Sscottl*following disclaimer.
9285809Sscottl*2. Redistributions in binary form must reproduce the above copyright notice,
10285809Sscottl*this list of conditions and the following disclaimer in the documentation and/or other materials provided
11285809Sscottl*with the distribution.
12285809Sscottl*
13285809Sscottl*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
14285809Sscottl*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15285809Sscottl*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16285809Sscottl*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17285809Sscottl*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
18285809Sscottl*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19285809Sscottl*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
20285809Sscottl*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
21285809Sscottl**
22285809Sscottl********************************************************************************/
23285809Sscottl#include <sys/cdefs.h>
24285809Sscottl__FBSDID("$FreeBSD$");
25285809Sscottl#include <dev/pms/config.h>
26285809Sscottl
27285809Sscottl#include <dev/pms/freebsd/driver/common/osenv.h>
28285809Sscottl#include <dev/pms/freebsd/driver/common/ostypes.h>
29285809Sscottl#include <dev/pms/freebsd/driver/common/osdebug.h>
30285809Sscottl
31285809Sscottl#include <dev/pms/RefTisa/sallsdk/api/sa.h>
32285809Sscottl#include <dev/pms/RefTisa/sallsdk/api/saapi.h>
33285809Sscottl#include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
34285809Sscottl
35285809Sscottl#ifdef FDS_DM
36285809Sscottl#include <dev/pms/RefTisa/discovery/api/dm.h>
37285809Sscottl#include <dev/pms/RefTisa/discovery/api/dmapi.h>
38285809Sscottl#include <dev/pms/RefTisa/discovery/api/tddmapi.h>
39285809Sscottl
40285809Sscottl#include <dev/pms/RefTisa/discovery/dm/dmdefs.h>
41285809Sscottl#include <dev/pms/RefTisa/discovery/dm/dmtypes.h>
42285809Sscottl#include <dev/pms/RefTisa/discovery/dm/dmproto.h>
43285809Sscottl
44285809Sscottl/*****************************************************************************/
45285809Sscottl/*! \brief dmDiscover
46285809Sscottl *
47285809Sscottl *
48285809Sscottl *  Purpose: A discovery is started by this function
49285809Sscottl *
50285809Sscottl *  \param   dmRoot:              DM context handle.
51285809Sscottl *  \param   dmPortContext:       Pointer to this instance of port context
52285809Sscottl *  \param   option:              Discovery option
53285809Sscottl *
54285809Sscottl *  \return:
55285809Sscottl *          DM_RC_SUCCESS
56285809Sscottl *          DM_RC_FAILURE
57285809Sscottl *
58285809Sscottl */
59285809Sscottl/*****************************************************************************/
60285809SscottlosGLOBAL bit32
61285809SscottldmDiscover(
62285809Sscottl           dmRoot_t 		*dmRoot,
63285809Sscottl           dmPortContext_t	*dmPortContext,
64285809Sscottl           bit32 		option)
65285809Sscottl{
66285809Sscottl  dmIntPortContext_t        *onePortContext = agNULL;
67285809Sscottl  bit32                     ret = DM_RC_FAILURE;
68285809Sscottl
69285809Sscottl  DM_DBG3(("dmDiscover: start\n"));
70285809Sscottl  onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
71285809Sscottl
72285809Sscottl  if (onePortContext == agNULL)
73285809Sscottl  {
74285809Sscottl    DM_DBG1(("dmDiscover: onePortContext is NULL!!!\n"));
75285809Sscottl    return DM_RC_FAILURE;
76285809Sscottl  }
77285809Sscottl
78285809Sscottl  if (onePortContext->valid == agFALSE)
79285809Sscottl  {
80285809Sscottl    DM_DBG1(("dmDiscover: invalid port!!!\n"));
81285809Sscottl    return DM_RC_FAILURE;
82285809Sscottl  }
83285809Sscottl
84285809Sscottl  if (onePortContext->RegFailed == agTRUE)
85285809Sscottl  {
86285809Sscottl    DM_DBG1(("dmDiscover: Registration failed!!!\n"));
87285809Sscottl    return DM_RC_FAILURE;
88285809Sscottl  }
89285809Sscottl
90285809Sscottl  switch ( option )
91285809Sscottl  {
92285809Sscottl  case DM_DISCOVERY_OPTION_FULL_START:
93285809Sscottl    DM_DBG3(("dmDiscover: full, pid %d\n", onePortContext->id));
94285809Sscottl    onePortContext->discovery.type = DM_DISCOVERY_OPTION_FULL_START;
95285809Sscottl    dmDiscoveryResetMCN(dmRoot, onePortContext);
96285809Sscottl    ret = dmFullDiscover(dmRoot, onePortContext);
97285809Sscottl    break;
98285809Sscottl  case DM_DISCOVERY_OPTION_INCREMENTAL_START:
99285809Sscottl    DM_DBG3(("dmDiscover: incremental, pid %d\n", onePortContext->id));
100285809Sscottl    onePortContext->discovery.type = DM_DISCOVERY_OPTION_INCREMENTAL_START;
101285809Sscottl    dmDiscoveryResetMCN(dmRoot, onePortContext);
102285809Sscottl    ret = dmIncrementalDiscover(dmRoot, onePortContext, agFALSE);
103285809Sscottl    break;
104285809Sscottl  case DM_DISCOVERY_OPTION_ABORT:
105285809Sscottl    DM_DBG3(("dmDiscover: abort\n"));
106285809Sscottl    if (onePortContext->DiscoveryState != DM_DSTATE_COMPLETED)
107285809Sscottl    {
108285809Sscottl      if (onePortContext->discovery.pendingSMP == 0)
109285809Sscottl      {
110285809Sscottl        dmDiscoverAbort(dmRoot, onePortContext);
111285809Sscottl        tddmDiscoverCB(
112285809Sscottl                       dmRoot,
113285809Sscottl                       onePortContext->dmPortContext,
114285809Sscottl                       dmDiscAborted
115285809Sscottl                       );
116285809Sscottl      }
117285809Sscottl      else
118285809Sscottl      {
119285809Sscottl        DM_DBG3(("dmDiscover: abortInProgress\n"));
120285809Sscottl        onePortContext->DiscoveryAbortInProgress = agTRUE;
121285809Sscottl        tddmDiscoverCB(
122285809Sscottl                       dmRoot,
123285809Sscottl                       dmPortContext,
124285809Sscottl                       dmDiscAbortInProgress
125285809Sscottl                       );
126285809Sscottl      }
127285809Sscottl    }
128285809Sscottl    else
129285809Sscottl    {
130285809Sscottl      DM_DBG3(("dmDiscover: no discovery to abort\n"));
131285809Sscottl      tddmDiscoverCB(
132285809Sscottl                     dmRoot,
133285809Sscottl                     dmPortContext,
134285809Sscottl                     dmDiscAbortInvalid
135285809Sscottl                     );
136285809Sscottl    }
137285809Sscottl    ret = DM_RC_SUCCESS;
138285809Sscottl    break;
139285809Sscottl  default:
140285809Sscottl    break;
141285809Sscottl  }
142285809Sscottl  return ret;
143285809Sscottl}
144285809Sscottl
145285809SscottlosGLOBAL bit32
146285809SscottldmFullDiscover(
147285809Sscottl               dmRoot_t 	    	*dmRoot,
148285809Sscottl               dmIntPortContext_t       *onePortContext
149285809Sscottl              )
150285809Sscottl{
151285809Sscottl  dmExpander_t              *oneExpander = agNULL;
152285809Sscottl  dmSASSubID_t              dmSASSubID;
153285809Sscottl  dmDeviceData_t            *oneExpDeviceData = agNULL;
154285809Sscottl
155285809Sscottl  DM_DBG1(("dmFullDiscover: start\n"));
156285809Sscottl
157285809Sscottl  if (onePortContext->valid == agFALSE)
158285809Sscottl  {
159285809Sscottl    DM_DBG1(("dmFullDiscover: invalid port!!!\n"));
160285809Sscottl    return DM_RC_FAILURE;
161285809Sscottl  }
162285809Sscottl
163285809Sscottl  if (onePortContext->DiscoveryState == DM_DSTATE_STARTED)
164285809Sscottl  {
165285809Sscottl    DM_DBG1(("dmFullDiscover: no two instances of discovery allowed!!!\n"));
166285809Sscottl    return DM_RC_FAILURE;
167285809Sscottl  }
168285809Sscottl
169285809Sscottl  onePortContext->DiscoveryState = DM_DSTATE_STARTED;
170285809Sscottl
171285809Sscottl  dmSASSubID.sasAddressHi = onePortContext->sasRemoteAddressHi;
172285809Sscottl  dmSASSubID.sasAddressLo = onePortContext->sasRemoteAddressLo;
173285809Sscottl
174285809Sscottl  /* check OnePortContext->discovery.discoveringExpanderList */
175285809Sscottl  oneExpander = dmExpFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
176285809Sscottl  if (oneExpander != agNULL)
177285809Sscottl  {
178285809Sscottl    oneExpDeviceData = oneExpander->dmDevice;
179285809Sscottl  }
180285809Sscottl  else
181285809Sscottl  {
182285809Sscottl    /* check dmAllShared->mainExpanderList */
183285809Sscottl    oneExpander = dmExpMainListFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
184285809Sscottl    if (oneExpander != agNULL)
185285809Sscottl    {
186285809Sscottl      oneExpDeviceData = oneExpander->dmDevice;
187285809Sscottl    }
188285809Sscottl  }
189285809Sscottl
190285809Sscottl  if (oneExpDeviceData != agNULL)
191285809Sscottl  {
192285809Sscottl    dmSASSubID.initiator_ssp_stp_smp = oneExpDeviceData->initiator_ssp_stp_smp;
193285809Sscottl    dmSASSubID.target_ssp_stp_smp = oneExpDeviceData->target_ssp_stp_smp;
194285809Sscottl    oneExpDeviceData->registered = agTRUE;
195285809Sscottl    dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, oneExpDeviceData, 0xFF);
196285809Sscottl  }
197285809Sscottl  else
198285809Sscottl  {
199285809Sscottl    DM_DBG1(("dmFullDiscover:oneExpDeviceData is NULL!!!\n"));
200285809Sscottl    return DM_RC_FAILURE;
201285809Sscottl  }
202285809Sscottl
203285809Sscottl  dmUpStreamDiscoverStart(dmRoot, onePortContext);
204285809Sscottl
205285809Sscottl  return DM_RC_SUCCESS;
206285809Sscottl}
207285809Sscottl
208285809SscottlosGLOBAL bit32
209285809SscottldmIncrementalDiscover(
210285809Sscottl                      dmRoot_t 	    	      *dmRoot,
211285809Sscottl                      dmIntPortContext_t      *onePortContext,
212285809Sscottl		      bit32                   flag
213285809Sscottl                     )
214285809Sscottl{
215285809Sscottl  dmExpander_t              *oneExpander = agNULL;
216285809Sscottl  dmSASSubID_t              dmSASSubID;
217285809Sscottl  dmDeviceData_t            *oneExpDeviceData = agNULL;
218285809Sscottl
219285809Sscottl  DM_DBG1(("dmIncrementalDiscover: start\n"));
220285809Sscottl
221285809Sscottl  if (onePortContext->valid == agFALSE)
222285809Sscottl  {
223285809Sscottl    DM_DBG1(("dmIncrementalDiscover: invalid port!!!\n"));
224285809Sscottl    return DM_RC_FAILURE;
225285809Sscottl  }
226285809Sscottl
227285809Sscottl  /* TDM triggerred; let go DM triggerred */
228285809Sscottl  if (flag == agFALSE)
229285809Sscottl  {
230285809Sscottl    if (onePortContext->DiscoveryState == DM_DSTATE_STARTED)
231285809Sscottl    {
232285809Sscottl      DM_DBG1(("dmIncrementalDiscover: no two instances of discovery allowed!!!\n"));
233285809Sscottl      return DM_RC_FAILURE;
234285809Sscottl    }
235285809Sscottl  }
236285809Sscottl
237285809Sscottl  onePortContext->DiscoveryState = DM_DSTATE_STARTED;
238285809Sscottl  onePortContext->discovery.type = DM_DISCOVERY_OPTION_INCREMENTAL_START;
239285809Sscottl
240285809Sscottl  dmSASSubID.sasAddressHi = onePortContext->sasRemoteAddressHi;
241285809Sscottl  dmSASSubID.sasAddressLo = onePortContext->sasRemoteAddressLo;
242285809Sscottl
243285809Sscottl  /* check OnePortContext->discovery.discoveringExpanderList */
244285809Sscottl  oneExpander = dmExpFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
245285809Sscottl  if (oneExpander != agNULL)
246285809Sscottl  {
247285809Sscottl    oneExpDeviceData = oneExpander->dmDevice;
248285809Sscottl  }
249285809Sscottl  else
250285809Sscottl  {
251285809Sscottl    /* check dmAllShared->mainExpanderList */
252285809Sscottl    oneExpander = dmExpMainListFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo);
253285809Sscottl    if (oneExpander != agNULL)
254285809Sscottl    {
255285809Sscottl      oneExpDeviceData = oneExpander->dmDevice;
256285809Sscottl    }
257285809Sscottl  }
258285809Sscottl
259285809Sscottl  if (oneExpDeviceData != agNULL)
260285809Sscottl  {
261285809Sscottl    dmSASSubID.initiator_ssp_stp_smp = oneExpDeviceData->initiator_ssp_stp_smp;
262285809Sscottl    dmSASSubID.target_ssp_stp_smp = oneExpDeviceData->target_ssp_stp_smp;
263285809Sscottl    oneExpDeviceData->registered = agTRUE;
264285809Sscottl    dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, oneExpDeviceData, 0xFF);
265285809Sscottl  }
266285809Sscottl  else
267285809Sscottl  {
268285809Sscottl    DM_DBG1(("dmIncrementalDiscover:oneExpDeviceData is NULL!!!\n"));
269285809Sscottl    return DM_RC_FAILURE;
270285809Sscottl  }
271285809Sscottl
272285809Sscottl  dmUpStreamDiscoverStart(dmRoot, onePortContext);
273285809Sscottl
274285809Sscottl  return DM_RC_SUCCESS;
275285809Sscottl}
276285809Sscottl
277285809SscottlosGLOBAL void
278285809SscottldmUpStreamDiscoverStart(
279285809Sscottl                        dmRoot_t             *dmRoot,
280285809Sscottl                        dmIntPortContext_t   *onePortContext
281285809Sscottl                       )
282285809Sscottl{
283285809Sscottl//  dmExpander_t              *oneExpander = agNULL;
284285809Sscottl  bit32                     sasAddressHi, sasAddressLo;
285285809Sscottl  dmDeviceData_t            *oneDeviceData;
286285809Sscottl  dmExpander_t              *oneExpander = agNULL;
287285809Sscottl
288285809Sscottl  DM_DBG3(("dmUpStreamDiscoverStart: start\n"));
289285809Sscottl  if (onePortContext->valid == agFALSE)
290285809Sscottl  {
291285809Sscottl    DM_DBG1(("dmUpStreamDiscoverStart: invalid port!!!\n"));
292285809Sscottl    return;
293285809Sscottl  }
294285809Sscottl  /*
295285809Sscottl    at this point, the 1st expander should have been registered.
296285809Sscottl    find an expander from onePortContext
297285809Sscottl  */
298285809Sscottl  sasAddressHi = onePortContext->sasRemoteAddressHi;
299285809Sscottl  sasAddressLo = onePortContext->sasRemoteAddressLo;
300285809Sscottl  DM_DBG3(("dmUpStreamDiscoverStart: Port Remote AddrHi 0x%08x Remote AddrLo 0x%08x\n", sasAddressHi, sasAddressLo));
301285809Sscottl
302285809Sscottl  oneDeviceData = dmDeviceFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo);
303285809Sscottl
304285809Sscottl//  oneDeviceData = oneExpander->dmDevice;
305285809Sscottl// start here
306285809Sscottl  onePortContext->discovery.status = DISCOVERY_UP_STREAM;
307285809Sscottl  if (oneDeviceData == agNULL)
308285809Sscottl  {
309285809Sscottl    DM_DBG1(("dmUpStreamDiscoverStart: oneExpander is NULL, wrong!!!\n"));
310285809Sscottl    return;
311285809Sscottl  }
312285809Sscottl  else
313285809Sscottl  {
314285809Sscottl    if ( (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
315285809Sscottl         ||
316285809Sscottl         (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE)
317285809Sscottl	 ||
318285809Sscottl	 DEVICE_IS_SMP_TARGET(oneDeviceData)
319285809Sscottl        )
320285809Sscottl    {
321285809Sscottl#if 1  /* for incremental discovery */
322285809Sscottl      /* start here: if not on discoveringExpanderList, alloc and add
323285809Sscottl      dmNewEXPorNot()
324285809Sscottl      */
325285809Sscottl      oneExpander = dmExpFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo);
326285809Sscottl      if ( oneExpander == agNULL)
327285809Sscottl      {
328285809Sscottl        /* alloc and add */
329285809Sscottl        oneExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, oneDeviceData);
330285809Sscottl        if ( oneExpander != agNULL)
331285809Sscottl        {
332285809Sscottl          dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);
333285809Sscottl        }
334285809Sscottl        else
335285809Sscottl	{
336285809Sscottl          DM_DBG1(("dmUpStreamDiscoverStart: failed to allocate expander or discovey aborted!!!\n"));
337285809Sscottl          return;
338285809Sscottl	}
339285809Sscottl      }
340285809Sscottl#endif
341285809Sscottl
342285809Sscottl      dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
343285809Sscottl    }
344285809Sscottl    else
345285809Sscottl    {
346285809Sscottl      DM_DBG1(("dmUpStreamDiscoverStart: oneDeviceData is not an Expander did %d, wrong!!!\n", oneDeviceData->id));
347285809Sscottl      return;
348285809Sscottl    }
349285809Sscottl  }
350285809Sscottl  return;
351285809Sscottl}
352285809Sscottl
353285809Sscottl/* sends report general */
354285809SscottlosGLOBAL void
355285809SscottldmUpStreamDiscovering(
356285809Sscottl                      dmRoot_t              *dmRoot,
357285809Sscottl                      dmIntPortContext_t    *onePortContext,
358285809Sscottl                      dmDeviceData_t        *oneDeviceData
359285809Sscottl                     )
360285809Sscottl{
361285809Sscottl  dmList_t          *ExpanderList;
362285809Sscottl  dmExpander_t      *oneNextExpander = agNULL;
363285809Sscottl
364285809Sscottl  DM_DBG3(("dmUpStreamDiscovering: start\n"));
365285809Sscottl
366285809Sscottl  if (onePortContext->valid == agFALSE)
367285809Sscottl  {
368285809Sscottl    DM_DBG1(("dmUpStreamDiscovering: invalid port!!!\n"));
369285809Sscottl    return;
370285809Sscottl  }
371285809Sscottl
372285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
373285809Sscottl  if (DMLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList)))
374285809Sscottl  {
375285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
376285809Sscottl    DM_DBG3(("dmUpStreamDiscovering: should be the end\n"));
377285809Sscottl    oneNextExpander = agNULL;
378285809Sscottl  }
379285809Sscottl  else
380285809Sscottl  {
381285809Sscottl    DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList));
382285809Sscottl    oneNextExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
383285809Sscottl    if ( oneNextExpander != agNULL)
384285809Sscottl    {
385285809Sscottl      DMLIST_ENQUEUE_AT_HEAD(&(oneNextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));
386285809Sscottl      DM_DBG3(("dmUpStreamDiscovering tdsaSASUpStreamDiscovering: dequeue head\n"));
387285809Sscottl      DM_DBG3(("dmUpStreamDiscovering: expander id %d\n", oneNextExpander->id));
388285809Sscottl    }
389285809Sscottl    else
390285809Sscottl    {
391285809Sscottl      DM_DBG1(("dmUpStreamDiscovering: oneNextExpander is NULL!!!\n"));
392285809Sscottl    }
393285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
394285809Sscottl
395285809Sscottl  }
396285809Sscottl
397285809Sscottl  if (oneNextExpander != agNULL)
398285809Sscottl  {
399285809Sscottl    dmReportGeneralSend(dmRoot, oneNextExpander->dmDevice);
400285809Sscottl  }
401285809Sscottl  else
402285809Sscottl  {
403285809Sscottl    DM_DBG3(("dmUpStreamDiscovering: No more expander list\n"));
404285809Sscottl    dmDownStreamDiscoverStart(dmRoot, onePortContext, oneDeviceData);
405285809Sscottl  }
406285809Sscottl
407285809Sscottl  return;
408285809Sscottl}
409285809Sscottl
410285809SscottlosGLOBAL void
411285809SscottldmDownStreamDiscoverStart(
412285809Sscottl                          dmRoot_t              *dmRoot,
413285809Sscottl                          dmIntPortContext_t    *onePortContext,
414285809Sscottl                          dmDeviceData_t        *oneDeviceData
415285809Sscottl                         )
416285809Sscottl{
417285809Sscottl  dmExpander_t        *UpStreamExpander;
418285809Sscottl  dmExpander_t        *oneExpander;
419285809Sscottl
420285809Sscottl  DM_DBG3(("dmDownStreamDiscoverStart: start\n"));
421285809Sscottl
422285809Sscottl  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
423285809Sscottl  {
424285809Sscottl    DM_DBG1(("dmDownStreamDiscoverStart: invalid port or aborted discovery!!!\n"));
425285809Sscottl    return;
426285809Sscottl  }
427285809Sscottl
428285809Sscottl  /* set discovery status */
429285809Sscottl  onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
430285809Sscottl
431285809Sscottl  /* If it's an expander */
432285809Sscottl  if ( (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
433285809Sscottl       || (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE)
434285809Sscottl       || DEVICE_IS_SMP_TARGET(oneDeviceData)
435285809Sscottl       )
436285809Sscottl  {
437285809Sscottl    oneExpander = oneDeviceData->dmExpander;
438285809Sscottl    UpStreamExpander = oneExpander->dmUpStreamExpander;
439285809Sscottl
440285809Sscottl    /* If the two expanders are the root of two edge sets; sub-to-sub */
441285809Sscottl    if ( (UpStreamExpander != agNULL) && ( UpStreamExpander->dmUpStreamExpander == oneExpander ) )
442285809Sscottl    {
443285809Sscottl      DM_DBG3(("dmDownStreamDiscoverStart: Root found pExpander=%p pUpStreamExpander=%p\n",
444285809Sscottl               oneExpander, UpStreamExpander));
445285809Sscottl      //Saves the root expander
446285809Sscottl      onePortContext->discovery.RootExp = oneExpander;
447285809Sscottl      DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
448285809Sscottl      DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
449285809Sscottl
450285809Sscottl      /* reset up stream inform for pExpander */
451285809Sscottl      oneExpander->dmUpStreamExpander = agNULL;
452285809Sscottl      /* Add the pExpander to discovering list */
453285809Sscottl      dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);
454285809Sscottl
455285809Sscottl      /* reset up stream inform for oneExpander */
456285809Sscottl      UpStreamExpander->dmUpStreamExpander = agNULL;
457285809Sscottl      /* Add the UpStreamExpander to discovering list */
458285809Sscottl      dmDiscoveringExpanderAdd(dmRoot, onePortContext, UpStreamExpander);
459285809Sscottl    }
460285809Sscottl    /* If the two expanders are not the root of two edge sets. eg) one root */
461285809Sscottl    else
462285809Sscottl    {
463285809Sscottl      //Saves the root expander
464285809Sscottl      onePortContext->discovery.RootExp = oneExpander;
465285809Sscottl
466285809Sscottl      DM_DBG3(("dmDownStreamDiscoverStart: NO Root pExpander=%p\n", oneExpander));
467285809Sscottl      DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
468285809Sscottl      DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
469285809Sscottl
470285809Sscottl      /* (2.2.2.1) Add the pExpander to discovering list */
471285809Sscottl      dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);
472285809Sscottl    }
473285809Sscottl  }
474285809Sscottl
475285809Sscottl  /* Continue down stream discovering */
476285809Sscottl  dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
477285809Sscottl
478285809Sscottl  return;
479285809Sscottl}
480285809Sscottl
481285809SscottlosGLOBAL void
482285809SscottldmDownStreamDiscovering(
483285809Sscottl                        dmRoot_t              *dmRoot,
484285809Sscottl                        dmIntPortContext_t    *onePortContext,
485285809Sscottl                        dmDeviceData_t        *oneDeviceData
486285809Sscottl                       )
487285809Sscottl{
488285809Sscottl  dmExpander_t      *NextExpander = agNULL;
489285809Sscottl  dmList_t          *ExpanderList;
490285809Sscottl
491285809Sscottl  DM_DBG3(("dmDownStreamDiscovering: start\n"));
492285809Sscottl
493285809Sscottl  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
494285809Sscottl  {
495285809Sscottl    DM_DBG1(("dmDownStreamDiscovering: invalid port or aborted discovery!!!\n"));
496285809Sscottl    return;
497285809Sscottl  }
498285809Sscottl
499285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
500285809Sscottl  if (DMLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList)))
501285809Sscottl  {
502285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
503285809Sscottl    DM_DBG3(("dmDownStreamDiscovering: should be the end\n"));
504285809Sscottl    NextExpander = agNULL;
505285809Sscottl  }
506285809Sscottl  else
507285809Sscottl  {
508285809Sscottl    DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList));;
509285809Sscottl    NextExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
510285809Sscottl    if ( NextExpander != agNULL)
511285809Sscottl    {
512285809Sscottl      DMLIST_ENQUEUE_AT_HEAD(&(NextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));;
513285809Sscottl      DM_DBG3(("dmDownStreamDiscovering tdsaSASDownStreamDiscovering: dequeue head\n"));
514285809Sscottl      DM_DBG3(("dmDownStreamDiscovering: expander id %d\n", NextExpander->id));
515285809Sscottl    }
516285809Sscottl    else
517285809Sscottl    {
518285809Sscottl     DM_DBG1(("dmDownStreamDiscovering: NextExpander is NULL!!!\n"));
519285809Sscottl    }
520285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
521285809Sscottl
522285809Sscottl  }
523285809Sscottl
524285809Sscottl  /* If there is an expander for continue discoving */
525285809Sscottl  if ( NextExpander != agNULL)
526285809Sscottl  {
527285809Sscottl    DM_DBG3(("dmDownStreamDiscovering: Found pNextExpander=%p discoveryStatus=0x%x\n",
528285809Sscottl             NextExpander, onePortContext->discovery.status));
529285809Sscottl
530285809Sscottl    switch (onePortContext->discovery.status)
531285809Sscottl    {
532285809Sscottl      /* If the discovery status is DISCOVERY_DOWN_STREAM */
533285809Sscottl    case DISCOVERY_DOWN_STREAM:
534285809Sscottl      /* Send report general for the next expander */
535285809Sscottl      DM_DBG3(("dmDownStreamDiscovering: DownStream pNextExpander=%p\n", NextExpander));
536285809Sscottl      DM_DBG3(("dmDownStreamDiscovering: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
537285809Sscottl      DM_DBG3(("dmDownStreamDiscovering: oneExpander %p did %d\n", oneDeviceData->dmExpander, oneDeviceData->dmExpander->id));
538285809Sscottl
539285809Sscottl      DM_DBG3(("dmDownStreamDiscovering: 2nd oneDeviceData %p did %d\n", NextExpander->dmDevice, NextExpander->dmDevice->id));
540285809Sscottl      DM_DBG3(("dmDownStreamDiscovering: 2nd oneExpander %p did %d\n", NextExpander, NextExpander->id));
541285809Sscottl      DM_DBG3(("dmDownStreamDiscovering: 2nd used oneExpander %p did %d\n", NextExpander->dmDevice->dmExpander, NextExpander->dmDevice->dmExpander->id));
542285809Sscottl
543285809Sscottl      if (NextExpander != NextExpander->dmDevice->dmExpander)
544285809Sscottl      {
545285809Sscottl        DM_DBG3(("dmDownStreamDiscovering: wrong!!!\n"));
546285809Sscottl      }
547285809Sscottl
548285809Sscottl
549285809Sscottl      dmReportGeneralSend(dmRoot, NextExpander->dmDevice);
550285809Sscottl      break;
551285809Sscottl      /* If the discovery status is DISCOVERY_CONFIG_ROUTING */
552285809Sscottl    case DISCOVERY_CONFIG_ROUTING:
553285809Sscottl    case DISCOVERY_REPORT_PHY_SATA:
554285809Sscottl
555285809Sscottl      /* set discovery status */
556285809Sscottl      onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
557285809Sscottl
558285809Sscottl      DM_DBG3(("dmDownStreamDiscovering: pPort->discovery.status=DISCOVERY_CONFIG_ROUTING, make it DOWN_STREAM\n"));
559285809Sscottl      /* If not the last phy */
560285809Sscottl      if ( NextExpander->discoveringPhyId < NextExpander->dmDevice->numOfPhys )
561285809Sscottl      {
562285809Sscottl        DM_DBG3(("dmDownStreamDiscovering: pNextExpander->discoveringPhyId=0x%x pNextExpander->numOfPhys=0x%x.  Send More Discover\n",
563285809Sscottl                 NextExpander->discoveringPhyId, NextExpander->dmDevice->numOfPhys));
564285809Sscottl        /* Send discover for the next expander */
565285809Sscottl        dmDiscoverSend(dmRoot, NextExpander->dmDevice);
566285809Sscottl        }
567285809Sscottl      /* If it's the last phy */
568285809Sscottl      else
569285809Sscottl      {
570285809Sscottl        DM_DBG3(("dmDownStreamDiscovering: Last Phy, remove expander%p  start DownStream=%p\n",
571285809Sscottl                 NextExpander, NextExpander->dmDevice));
572285809Sscottl        dmDiscoveringExpanderRemove(dmRoot, onePortContext, NextExpander);
573285809Sscottl        dmDownStreamDiscovering(dmRoot, onePortContext, NextExpander->dmDevice);
574285809Sscottl      }
575285809Sscottl      break;
576285809Sscottl
577285809Sscottl    default:
578285809Sscottl      DM_DBG3(("dmDownStreamDiscovering: *** Unknown pPort->discovery.status=0x%x\n", onePortContext->discovery.status));
579285809Sscottl    }
580285809Sscottl  }
581285809Sscottl  /* If no expander for continue discoving */
582285809Sscottl  else
583285809Sscottl  {
584285809Sscottl    DM_DBG3(("dmDownStreamDiscovering: No more expander DONE\n"));
585285809Sscottl    /* discover done */
586285809Sscottl    dmDiscoverDone(dmRoot, onePortContext, DM_RC_SUCCESS);
587285809Sscottl  }
588285809Sscottl
589285809Sscottl
590285809Sscottl  return;
591285809Sscottl}
592285809Sscottl
593285809SscottlosGLOBAL void
594285809SscottldmUpStreamDiscoverExpanderPhy(
595285809Sscottl                              dmRoot_t              *dmRoot,
596285809Sscottl                              dmIntPortContext_t    *onePortContext,
597285809Sscottl                              dmExpander_t          *oneExpander,
598285809Sscottl                              smpRespDiscover_t     *pDiscoverResp
599285809Sscottl                             )
600285809Sscottl{
601285809Sscottl  agsaSASIdentify_t       sasIdentify;
602285809Sscottl  dmSASSubID_t            dmSASSubID;
603285809Sscottl  bit32                   attachedSasHi, attachedSasLo;
604285809Sscottl  dmExpander_t            *AttachedExpander = agNULL;
605285809Sscottl  bit8                    connectionRate;
606285809Sscottl  dmDeviceData_t          *oneDeviceData = agNULL;
607285809Sscottl  dmDeviceData_t          *AttachedDevice = agNULL;
608285809Sscottl  dmIntRoot_t             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
609285809Sscottl  dmIntContext_t          *dmAllShared  = (dmIntContext_t *)&dmIntRoot->dmAllShared;
610285809Sscottl
611285809Sscottl
612285809Sscottl  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: start\n"));
613285809Sscottl
614285809Sscottl  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
615285809Sscottl  {
616285809Sscottl    DM_DBG1(("dmUpStreamDiscoverExpanderPhy: invalid port or aborted discovery!!!\n"));
617285809Sscottl    return;
618285809Sscottl  }
619285809Sscottl
620285809Sscottl  if (oneExpander != oneExpander->dmDevice->dmExpander)
621285809Sscottl  {
622285809Sscottl    DM_DBG1(("dmUpStreamDiscoverExpanderPhy: wrong!!!\n"));
623285809Sscottl  }
624285809Sscottl
625285809Sscottl  dm_memset(&sasIdentify, 0, sizeof(agsaSASIdentify_t));
626285809Sscottl
627285809Sscottl  oneDeviceData = oneExpander->dmDevice;
628285809Sscottl
629285809Sscottl  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n",
630285809Sscottl           oneExpander->discoveringPhyId,
631285809Sscottl           oneDeviceData->SASAddressID.sasAddressHi,
632285809Sscottl           oneDeviceData->SASAddressID.sasAddressLo));
633285809Sscottl
634285809Sscottl  DM_DBG3(("   Attached device: %s\n",
635285809Sscottl           ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" :
636285809Sscottl             (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" :
637285809Sscottl              (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
638285809Sscottl
639285809Sscottl
640285809Sscottl  if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
641285809Sscottl  {
642285809Sscottl    DM_DBG3(("   SAS address    : %08x-%08x\n",
643285809Sscottl      DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp),
644285809Sscottl              DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
645285809Sscottl    DM_DBG3(("   SSP Target     : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
646285809Sscottl    DM_DBG3(("   STP Target     : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
647285809Sscottl    DM_DBG3(("   SMP Target     : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
648285809Sscottl    DM_DBG3(("   SATA DEVICE    : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
649285809Sscottl    DM_DBG3(("   SSP Initiator  : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
650285809Sscottl    DM_DBG3(("   STP Initiator  : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
651285809Sscottl    DM_DBG3(("   SMP Initiator  : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
652285809Sscottl    DM_DBG3(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
653285809Sscottl    DM_DBG3(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
654285809Sscottl  }
655285809Sscottl
656285809Sscottl  /* for debugging */
657285809Sscottl  if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
658285809Sscottl  {
659285809Sscottl    DM_DBG1(("dmUpStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n"));
660285809Sscottl    DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d !!!\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
661285809Sscottl    dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
662285809Sscottl    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
663285809Sscottl    return;
664285809Sscottl  }
665285809Sscottl
666285809Sscottl  /* saving routing attribute for non self-configuring expanders */
667285809Sscottl  oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = (bit8)DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
668285809Sscottl
669285809Sscottl  if ( oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE )
670285809Sscottl  {
671285809Sscottl    DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_FANOUT_EXPANDER\n"));
672285809Sscottl    if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
673285809Sscottl    {
674285809Sscottl      DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing on fanout expander device!!!\n"));
675285809Sscottl
676285809Sscottl      /* discovery error */
677285809Sscottl      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
678285809Sscottl        = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
679285809Sscottl      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
680285809Sscottl        = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
681285809Sscottl      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
682285809Sscottl      DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
683285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
684285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
685285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
686285809Sscottl
687285809Sscottl      /* (2.1.3) discovery done */
688285809Sscottl      dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
689285809Sscottl      return;
690285809Sscottl    }
691285809Sscottl  }
692285809Sscottl  else
693285809Sscottl  {
694285809Sscottl    DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_EDGE_EXPANDER\n"));
695285809Sscottl    if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
696285809Sscottl    {
697285809Sscottl      /* Setup sasIdentify for the attached device */
698285809Sscottl      sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
699285809Sscottl      sasIdentify.deviceType_addressFrameType = (bit8)(pDiscoverResp->attachedDeviceType & 0x70);
700285809Sscottl      sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
701285809Sscottl      sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
702285809Sscottl      *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
703285809Sscottl      *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
704285809Sscottl
705285809Sscottl      /* incremental discovery */
706285809Sscottl      dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
707285809Sscottl      dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
708285809Sscottl      dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
709285809Sscottl      dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
710285809Sscottl
711285809Sscottl      attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
712285809Sscottl      attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
713285809Sscottl
714285809Sscottl      /* If the phy has subtractive routing attribute */
715285809Sscottl      if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
716285809Sscottl      {
717285809Sscottl        DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_ROUTING_SUBTRACTIVE\n"));
718285809Sscottl        /* Setup upstream phys */
719285809Sscottl        dmExpanderUpStreamPhyAdd(dmRoot, oneExpander, (bit8) pDiscoverResp->attachedPhyIdentifier);
720285809Sscottl        /* If the expander already has an upsteam device set up */
721285809Sscottl        if (oneExpander->hasUpStreamDevice == agTRUE)
722285809Sscottl        {
723285809Sscottl          /* just to update MCN */
724285809Sscottl          dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
725285809Sscottl          /* If the sas address doesn't match */
726285809Sscottl          if ( ((oneExpander->upStreamSASAddressHi != attachedSasHi) ||
727285809Sscottl                (oneExpander->upStreamSASAddressLo != attachedSasLo)) &&
728285809Sscottl               (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
729285809Sscottl                DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
730285809Sscottl              )
731285809Sscottl          {
732285809Sscottl            /* TODO: discovery error, callback */
733285809Sscottl            DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n"));
734285809Sscottl            /* call back to notify discovery error */
735285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
736285809Sscottl              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
737285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
738285809Sscottl              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
739285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
740285809Sscottl            DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
741285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
742285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
743285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
744285809Sscottl            /* discovery done */
745285809Sscottl            dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
746285809Sscottl          }
747285809Sscottl        }
748285809Sscottl        else
749285809Sscottl        {
750285809Sscottl          /* Setup SAS address for up stream device */
751285809Sscottl          oneExpander->hasUpStreamDevice = agTRUE;
752285809Sscottl          oneExpander->upStreamSASAddressHi = attachedSasHi;
753285809Sscottl          oneExpander->upStreamSASAddressLo = attachedSasLo;
754285809Sscottl          if ( (onePortContext->sasLocalAddressHi != attachedSasHi)
755285809Sscottl              || (onePortContext->sasLocalAddressLo != attachedSasLo) )
756285809Sscottl          {
757285809Sscottl            /* Find the device from the discovered list */
758285809Sscottl            AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
759285809Sscottl            /* New device, If the device has been discovered before */
760285809Sscottl            if ( AttachedDevice != agNULL) /* old device */
761285809Sscottl            {
762285809Sscottl              DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Seen This Device Before\n"));
763285809Sscottl              /* If attached device is an edge expander */
764285809Sscottl              if ( AttachedDevice->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
765285809Sscottl              {
766285809Sscottl                /* The attached device is an expander */
767285809Sscottl                AttachedExpander = AttachedDevice->dmExpander;
768285809Sscottl                /* If the two expanders are the root of the two edge expander sets */
769285809Sscottl                if ( (AttachedExpander->upStreamSASAddressHi ==
770285809Sscottl                      DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
771285809Sscottl                     && (AttachedExpander->upStreamSASAddressLo ==
772285809Sscottl                        DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)) )
773285809Sscottl                {
774285809Sscottl                  /* Setup upstream expander for the pExpander */
775285809Sscottl                  oneExpander->dmUpStreamExpander = AttachedExpander;
776285809Sscottl                }
777285809Sscottl                /* If the two expanders are not the root of the two edge expander sets */
778285809Sscottl                else
779285809Sscottl                {
780285809Sscottl                  /* TODO: loop found, discovery error, callback */
781285809Sscottl                  DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error loop detection!!!\n"));
782285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
783285809Sscottl                    = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
784285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
785285809Sscottl                    = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
786285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
787285809Sscottl                  DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
788285809Sscottl                           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
789285809Sscottl                           onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
790285809Sscottl                           onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
791285809Sscottl		                /* discovery done */
792285809Sscottl                  dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
793285809Sscottl                }
794285809Sscottl              }
795285809Sscottl              /* If attached device is not an edge expander */
796285809Sscottl              else
797285809Sscottl              {
798285809Sscottl                /*TODO: should not happen, ASSERT */
799285809Sscottl                DM_DBG3(("dmUpStreamDiscoverExpanderPhy, *** Attached Device is not Edge. Confused!!!\n"));
800285809Sscottl              }
801285809Sscottl            } /* AttachedExpander != agNULL */
802285809Sscottl            /* New device, If the device has not been discovered before */
803285809Sscottl            else /* new device */
804285809Sscottl            {
805285809Sscottl              /* Add the device */
806285809Sscottl              DM_DBG3(("dmUpStreamDiscoverExpanderPhy: New device\n"));
807285809Sscottl              /* read minimum rate from the configuration
808285809Sscottl                 onePortContext->LinkRate is SPC's local link rate
809285809Sscottl              */
810285809Sscottl              connectionRate = (bit8)MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp));
811285809Sscottl              DM_DBG3(("dmUpStreamDiscoverExpanderPhy: link rate 0x%x\n", onePortContext->LinkRate));
812285809Sscottl              DM_DBG3(("dmUpStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp)));
813285809Sscottl              DM_DBG3(("dmUpStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate));
814285809Sscottl              if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
815285809Sscottl              {
816285809Sscottl                /* incremental discovery */
817285809Sscottl                if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
818285809Sscottl                {
819285809Sscottl                  AttachedDevice = dmPortSASDeviceAdd(
820285809Sscottl                                                    dmRoot,
821285809Sscottl                                                    onePortContext,
822285809Sscottl                                                    sasIdentify,
823285809Sscottl                                                    agFALSE,
824285809Sscottl                                                    connectionRate,
825285809Sscottl                                                    dmAllShared->itNexusTimeout,
826285809Sscottl                                                    0,
827285809Sscottl                                                    STP_DEVICE_TYPE,
828285809Sscottl                                                    oneDeviceData,
829285809Sscottl                                                    oneExpander,
830285809Sscottl                                                    pDiscoverResp->phyIdentifier
831285809Sscottl                                                    );
832285809Sscottl                }
833285809Sscottl                else
834285809Sscottl                {
835285809Sscottl                  /* incremental discovery */
836285809Sscottl                  AttachedDevice = dmFindRegNValid(
837285809Sscottl                                                     dmRoot,
838285809Sscottl                                                     onePortContext,
839285809Sscottl                                                     &dmSASSubID
840285809Sscottl                                                     );
841285809Sscottl                  /* not registered and not valid; add this*/
842285809Sscottl                  if (AttachedDevice == agNULL)
843285809Sscottl                  {
844285809Sscottl                    AttachedDevice = dmPortSASDeviceAdd(
845285809Sscottl                                                    dmRoot,
846285809Sscottl                                                    onePortContext,
847285809Sscottl                                                    sasIdentify,
848285809Sscottl                                                    agFALSE,
849285809Sscottl                                                    connectionRate,
850285809Sscottl                                                    dmAllShared->itNexusTimeout,
851285809Sscottl                                                    0,
852285809Sscottl                                                    STP_DEVICE_TYPE,
853285809Sscottl                                                    oneDeviceData,
854285809Sscottl                                                    oneExpander,
855285809Sscottl                                                    pDiscoverResp->phyIdentifier
856285809Sscottl                                                    );
857285809Sscottl                  }
858285809Sscottl                }
859285809Sscottl              } /* DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp) */
860285809Sscottl              else
861285809Sscottl              {
862285809Sscottl                /* incremental discovery */
863285809Sscottl                if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
864285809Sscottl                {
865285809Sscottl                  AttachedDevice = dmPortSASDeviceAdd(
866285809Sscottl                                                    dmRoot,
867285809Sscottl                                                    onePortContext,
868285809Sscottl                                                    sasIdentify,
869285809Sscottl                                                    agFALSE,
870285809Sscottl                                                    connectionRate,
871285809Sscottl                                                    dmAllShared->itNexusTimeout,
872285809Sscottl                                                    0,
873285809Sscottl                                                    SAS_DEVICE_TYPE,
874285809Sscottl                                                    oneDeviceData,
875285809Sscottl                                                    oneExpander,
876285809Sscottl                                                    pDiscoverResp->phyIdentifier
877285809Sscottl                                                    );
878285809Sscottl                }
879285809Sscottl                else
880285809Sscottl                {
881285809Sscottl                  /* incremental discovery */
882285809Sscottl                  AttachedDevice = dmFindRegNValid(
883285809Sscottl                                                     dmRoot,
884285809Sscottl                                                     onePortContext,
885285809Sscottl                                                     &dmSASSubID
886285809Sscottl                                                     );
887285809Sscottl                  /* not registered and not valid; add this*/
888285809Sscottl                  if (AttachedDevice == agNULL)
889285809Sscottl                  {
890285809Sscottl                    AttachedDevice = dmPortSASDeviceAdd(
891285809Sscottl                                                    dmRoot,
892285809Sscottl                                                    onePortContext,
893285809Sscottl                                                    sasIdentify,
894285809Sscottl                                                    agFALSE,
895285809Sscottl                                                    connectionRate,
896285809Sscottl                                                    dmAllShared->itNexusTimeout,
897285809Sscottl                                                    0,
898285809Sscottl                                                    SAS_DEVICE_TYPE,
899285809Sscottl                                                    oneDeviceData,
900285809Sscottl                                                    oneExpander,
901285809Sscottl                                                    pDiscoverResp->phyIdentifier
902285809Sscottl                                                    );
903285809Sscottl                  }
904285809Sscottl                }
905285809Sscottl              }
906285809Sscottl               /* If the device is added successfully */
907285809Sscottl              if ( AttachedDevice != agNULL)
908285809Sscottl              {
909285809Sscottl
910285809Sscottl                 /* (3.1.2.3.2.3.2.1) callback about new device */
911285809Sscottl                if ( DISCRSP_IS_SSP_TARGET(pDiscoverResp)
912285809Sscottl                    || DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)
913285809Sscottl                    || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)
914285809Sscottl                    || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) )
915285809Sscottl                {
916285809Sscottl                  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found SSP/SMP SAS %08x-%08x\n",
917285809Sscottl                      attachedSasHi, attachedSasLo));
918285809Sscottl                }
919285809Sscottl                else
920285809Sscottl                {
921285809Sscottl                  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found a SAS STP device.\n"));
922285809Sscottl                }
923285809Sscottl                 /* If the attached device is an expander */
924285809Sscottl                if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
925285809Sscottl                    || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) )
926285809Sscottl                {
927285809Sscottl                  /* Allocate an expander data structure */
928285809Sscottl                  AttachedExpander = dmDiscoveringExpanderAlloc(
929285809Sscottl                                                                dmRoot,
930285809Sscottl                                                                onePortContext,
931285809Sscottl                                                                AttachedDevice
932285809Sscottl								                                                       );
933285809Sscottl
934285809Sscottl                  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found expander=%p\n", AttachedExpander));
935285809Sscottl                  /* If allocate successfully */
936285809Sscottl                  if ( AttachedExpander != agNULL)
937285809Sscottl                  {
938285809Sscottl                    /* Add the pAttachedExpander to discovering list */
939285809Sscottl                    dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
940285809Sscottl                    /* Setup upstream expander for the pExpander */
941285809Sscottl                    oneExpander->dmUpStreamExpander = AttachedExpander;
942285809Sscottl                  }
943285809Sscottl                  /* If failed to allocate */
944285809Sscottl                  else
945285809Sscottl                  {
946285809Sscottl                    DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Failed to allocate expander data structure!!!\n"));
947285809Sscottl                    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
948285809Sscottl                  }
949285809Sscottl                }
950285809Sscottl                /* If the attached device is an end device */
951285809Sscottl                else
952285809Sscottl                {
953285809Sscottl                  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found end device\n"));
954285809Sscottl                  /* LP2006-05-26 added upstream device to the newly found device */
955285809Sscottl                  AttachedDevice->dmExpander = oneExpander;
956285809Sscottl                  oneExpander->dmUpStreamExpander = agNULL;
957285809Sscottl                }
958285809Sscottl              }
959285809Sscottl              else
960285809Sscottl              {
961285809Sscottl                DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Failed to add a device!!!\n"));
962285809Sscottl                dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
963285809Sscottl              }
964285809Sscottl
965285809Sscottl
966285809Sscottl
967285809Sscottl            } /* else, new device */
968285809Sscottl          } /* onePortContext->sasLocalAddressLo != attachedSasLo */
969285809Sscottl        } /* else */
970285809Sscottl      } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE */
971285809Sscottl    } /* DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE */
972285809Sscottl  } /* big else */
973285809Sscottl
974285809Sscottl
975285809Sscottl
976285809Sscottl   oneExpander->discoveringPhyId ++;
977285809Sscottl   if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
978285809Sscottl     {
979285809Sscottl       if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
980285809Sscottl       {
981285809Sscottl         DM_DBG3(("dmUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM find more ...\n"));
982285809Sscottl         /* continue discovery for the next phy */
983285809Sscottl         dmDiscoverSend(dmRoot, oneDeviceData);
984285809Sscottl       }
985285809Sscottl       else
986285809Sscottl       {
987285809Sscottl         DM_DBG3(("dmUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM last phy continue upstream..\n"));
988285809Sscottl
989285809Sscottl         /* for MCN */
990285809Sscottl         dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
991285809Sscottl         /* remove the expander from the discovering list */
992285809Sscottl         dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
993285809Sscottl         /* continue upstream discovering */
994285809Sscottl         dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
995285809Sscottl       }
996285809Sscottl   }
997285809Sscottl   else
998285809Sscottl   {
999285809Sscottl      DM_DBG3(("dmUpStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));
1000285809Sscottl
1001285809Sscottl   }
1002285809Sscottl
1003285809Sscottl  DM_DBG3(("dmUpStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
1004285809Sscottl
1005285809Sscottl  return;
1006285809Sscottl}
1007285809Sscottl
1008285809SscottlosGLOBAL void
1009285809SscottldmUpStreamDiscover2ExpanderPhy(
1010285809Sscottl                              dmRoot_t              *dmRoot,
1011285809Sscottl                              dmIntPortContext_t    *onePortContext,
1012285809Sscottl                              dmExpander_t          *oneExpander,
1013285809Sscottl                              smpRespDiscover2_t    *pDiscoverResp
1014285809Sscottl                              )
1015285809Sscottl{
1016285809Sscottl  dmDeviceData_t          *oneDeviceData;
1017285809Sscottl  dmDeviceData_t          *AttachedDevice = agNULL;
1018285809Sscottl  dmExpander_t            *AttachedExpander;
1019285809Sscottl  agsaSASIdentify_t       sasIdentify;
1020285809Sscottl  bit8                    connectionRate;
1021285809Sscottl  bit32                   attachedSasHi, attachedSasLo;
1022285809Sscottl  dmSASSubID_t            dmSASSubID;
1023285809Sscottl  dmIntRoot_t             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
1024285809Sscottl  dmIntContext_t          *dmAllShared  = (dmIntContext_t *)&dmIntRoot->dmAllShared;
1025285809Sscottl
1026285809Sscottl  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: start\n"));
1027285809Sscottl
1028285809Sscottl  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
1029285809Sscottl  {
1030285809Sscottl    DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: invalid port or aborted discovery!!!\n"));
1031285809Sscottl    return;
1032285809Sscottl  }
1033285809Sscottl
1034285809Sscottl  if (oneExpander != oneExpander->dmDevice->dmExpander)
1035285809Sscottl  {
1036285809Sscottl    DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: wrong!!!\n"));
1037285809Sscottl  }
1038285809Sscottl
1039285809Sscottl  dm_memset(&sasIdentify, 0, sizeof(agsaSASIdentify_t));
1040285809Sscottl
1041285809Sscottl  oneDeviceData = oneExpander->dmDevice;
1042285809Sscottl
1043285809Sscottl  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Phy #%d of SAS %08x-%08x\n",
1044285809Sscottl           oneExpander->discoveringPhyId,
1045285809Sscottl           oneDeviceData->SASAddressID.sasAddressHi,
1046285809Sscottl           oneDeviceData->SASAddressID.sasAddressLo));
1047285809Sscottl
1048285809Sscottl  DM_DBG2(("   Attached device: %s\n",
1049285809Sscottl           ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" :
1050285809Sscottl             (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" :
1051285809Sscottl              (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
1052285809Sscottl
1053285809Sscottl
1054285809Sscottl  if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
1055285809Sscottl  {
1056285809Sscottl    DM_DBG2(("   SAS address    : %08x-%08x\n",
1057285809Sscottl      SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp),
1058285809Sscottl              SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
1059285809Sscottl    DM_DBG2(("   SSP Target     : %d\n", SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
1060285809Sscottl    DM_DBG2(("   STP Target     : %d\n", SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
1061285809Sscottl    DM_DBG2(("   SMP Target     : %d\n", SAS2_DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
1062285809Sscottl    DM_DBG2(("   SATA DEVICE    : %d\n", SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
1063285809Sscottl    DM_DBG2(("   SSP Initiator  : %d\n", SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
1064285809Sscottl    DM_DBG2(("   STP Initiator  : %d\n", SAS2_DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
1065285809Sscottl    DM_DBG2(("   SMP Initiator  : %d\n", SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
1066285809Sscottl    DM_DBG2(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
1067285809Sscottl    DM_DBG2(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
1068285809Sscottl  }
1069285809Sscottl
1070285809Sscottl  if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
1071285809Sscottl  {
1072285809Sscottl    DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: !!! Incorrect SMP response !!!\n"));
1073285809Sscottl    DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
1074285809Sscottl    dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover2_t));
1075285809Sscottl    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1076285809Sscottl    return;
1077285809Sscottl  }
1078285809Sscottl
1079285809Sscottl  /* saving routing attribute for non self-configuring expanders */
1080285809Sscottl  oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
1081285809Sscottl
1082285809Sscottl  if ( oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE )
1083285809Sscottl  {
1084285809Sscottl    DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_DEV_TYPE_FANOUT_EXPANDER\n"));
1085285809Sscottl    if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
1086285809Sscottl    {
1087285809Sscottl      DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing on fanout expander device!!!\n"));
1088285809Sscottl
1089285809Sscottl      /* discovery error */
1090285809Sscottl      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1091285809Sscottl        = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1092285809Sscottl      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1093285809Sscottl        = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1094285809Sscottl      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1095285809Sscottl      DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1096285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1097285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1098285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1099285809Sscottl
1100285809Sscottl      /* (2.1.3) discovery done */
1101285809Sscottl      dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1102285809Sscottl      return;
1103285809Sscottl    }
1104285809Sscottl  }
1105285809Sscottl  else
1106285809Sscottl  {
1107285809Sscottl    DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_DEV_TYPE_EDGE_EXPANDER\n"));
1108285809Sscottl
1109285809Sscottl    if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
1110285809Sscottl    {
1111285809Sscottl      /* Setup sasIdentify for the attached device */
1112285809Sscottl      sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
1113285809Sscottl      sasIdentify.deviceType_addressFrameType = pDiscoverResp->attachedDeviceTypeReason & 0x70;
1114285809Sscottl      sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
1115285809Sscottl      sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
1116285809Sscottl      *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
1117285809Sscottl      *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
1118285809Sscottl
1119285809Sscottl      /* incremental discovery */
1120285809Sscottl      dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
1121285809Sscottl      dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
1122285809Sscottl      dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
1123285809Sscottl      dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
1124285809Sscottl
1125285809Sscottl      attachedSasHi = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
1126285809Sscottl      attachedSasLo = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
1127285809Sscottl
1128285809Sscottl      /* If the phy has subtractive routing attribute */
1129285809Sscottl      if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
1130285809Sscottl      {
1131285809Sscottl        DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_ROUTING_SUBTRACTIVE\n"));
1132285809Sscottl        /* Setup upstream phys */
1133285809Sscottl        dmExpanderUpStreamPhyAdd(dmRoot, oneExpander, (bit8) pDiscoverResp->attachedPhyIdentifier);
1134285809Sscottl        /* If the expander already has an upsteam device set up */
1135285809Sscottl        if (oneExpander->hasUpStreamDevice == agTRUE)
1136285809Sscottl        {
1137285809Sscottl          /* just to update MCN */
1138285809Sscottl          dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
1139285809Sscottl          /* If the sas address doesn't match */
1140285809Sscottl          if ( ((oneExpander->upStreamSASAddressHi != attachedSasHi) ||
1141285809Sscottl                (oneExpander->upStreamSASAddressLo != attachedSasLo)) &&
1142285809Sscottl               (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
1143285809Sscottl                SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1144285809Sscottl              )
1145285809Sscottl          {
1146285809Sscottl            /* TODO: discovery error, callback */
1147285809Sscottl            DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n"));
1148285809Sscottl            /* call back to notify discovery error */
1149285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1150285809Sscottl              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1151285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1152285809Sscottl              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1153285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1154285809Sscottl            DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1155285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1156285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1157285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1158285809Sscottl            /* discovery done */
1159285809Sscottl            dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1160285809Sscottl          }
1161285809Sscottl        }
1162285809Sscottl        else
1163285809Sscottl        {
1164285809Sscottl          /* Setup SAS address for up stream device */
1165285809Sscottl          oneExpander->hasUpStreamDevice = agTRUE;
1166285809Sscottl          oneExpander->upStreamSASAddressHi = attachedSasHi;
1167285809Sscottl          oneExpander->upStreamSASAddressLo = attachedSasLo;
1168285809Sscottl
1169285809Sscottl          if ( (onePortContext->sasLocalAddressHi != attachedSasHi)
1170285809Sscottl              || (onePortContext->sasLocalAddressLo != attachedSasLo) )
1171285809Sscottl          {
1172285809Sscottl            /* Find the device from the discovered list */
1173285809Sscottl            AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
1174285809Sscottl            /* If the device has been discovered before */
1175285809Sscottl            if ( AttachedDevice != agNULL)
1176285809Sscottl            {
1177285809Sscottl              DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Seen This Device Before\n"));
1178285809Sscottl              /* If attached device is an edge expander */
1179285809Sscottl              if ( AttachedDevice->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
1180285809Sscottl              {
1181285809Sscottl                /* The attached device is an expander */
1182285809Sscottl                AttachedExpander = AttachedDevice->dmExpander;
1183285809Sscottl                /* If the two expanders are the root of the two edge expander sets */
1184285809Sscottl                if ( (AttachedExpander->upStreamSASAddressHi ==
1185285809Sscottl                      DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
1186285809Sscottl                     && (AttachedExpander->upStreamSASAddressLo ==
1187285809Sscottl                        DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)) )
1188285809Sscottl                {
1189285809Sscottl                  /* Setup upstream expander for the pExpander */
1190285809Sscottl                  oneExpander->dmUpStreamExpander = AttachedExpander;
1191285809Sscottl                }
1192285809Sscottl                /* If the two expanders are not the root of the two edge expander sets */
1193285809Sscottl                else
1194285809Sscottl                {
1195285809Sscottl                  /* TODO: loop found, discovery error, callback */
1196285809Sscottl                  DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error loop detection!!!\n"));
1197285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1198285809Sscottl                    = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1199285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1200285809Sscottl                    = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1201285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1202285809Sscottl                  DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1203285809Sscottl                            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1204285809Sscottl                            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1205285809Sscottl                            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1206285809Sscottl                  /* discovery done */
1207285809Sscottl                  dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1208285809Sscottl                }
1209285809Sscottl              }
1210285809Sscottl              /* If attached device is not an edge expander */
1211285809Sscottl              else
1212285809Sscottl              {
1213285809Sscottl                /*TODO: should not happen, ASSERT */
1214285809Sscottl                DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, *** Attached Device is not Edge. Confused!!!\n"));
1215285809Sscottl              }
1216285809Sscottl            }
1217285809Sscottl            /* If the device has not been discovered before */
1218285809Sscottl            else
1219285809Sscottl            {
1220285809Sscottl              /* Add the device */
1221285809Sscottl              DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: New device\n"));
1222285809Sscottl              /* read minimum rate from the configuration
1223285809Sscottl                 onePortContext->LinkRate is SPC's local link rate
1224285809Sscottl              */
1225285809Sscottl              connectionRate = MIN(onePortContext->LinkRate, SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pDiscoverResp));
1226285809Sscottl              DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: link rate 0x%x\n", onePortContext->LinkRate));
1227285809Sscottl              DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: negotiatedPhyLinkRate 0x%x\n", SAS2_DISCRSP_GET_LINKRATE(pDiscoverResp)));
1228285809Sscottl              DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: connectionRate 0x%x\n", connectionRate));
1229285809Sscottl              //hhhhhhhh
1230285809Sscottl              if (SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
1231285809Sscottl              {
1232285809Sscottl                /* incremental discovery */
1233285809Sscottl                if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
1234285809Sscottl                {
1235285809Sscottl                  AttachedDevice = dmPortSASDeviceAdd(
1236285809Sscottl                                                    dmRoot,
1237285809Sscottl                                                    onePortContext,
1238285809Sscottl                                                    sasIdentify,
1239285809Sscottl                                                    agFALSE,
1240285809Sscottl                                                    connectionRate,
1241285809Sscottl                                                    dmAllShared->itNexusTimeout,
1242285809Sscottl                                                    0,
1243285809Sscottl                                                    STP_DEVICE_TYPE,
1244285809Sscottl                                                    oneDeviceData,
1245285809Sscottl                                                    oneExpander,
1246285809Sscottl                                                    pDiscoverResp->phyIdentifier
1247285809Sscottl                                                    );
1248285809Sscottl                }
1249285809Sscottl                else
1250285809Sscottl                {
1251285809Sscottl                  /* incremental discovery */
1252285809Sscottl                  AttachedDevice = dmFindRegNValid(
1253285809Sscottl                                                     dmRoot,
1254285809Sscottl                                                     onePortContext,
1255285809Sscottl                                                     &dmSASSubID
1256285809Sscottl                                                     );
1257285809Sscottl                  /* not registered and not valid; add this*/
1258285809Sscottl                  if (AttachedDevice == agNULL)
1259285809Sscottl                  {
1260285809Sscottl                    AttachedDevice = dmPortSASDeviceAdd(
1261285809Sscottl                                                    dmRoot,
1262285809Sscottl                                                    onePortContext,
1263285809Sscottl                                                    sasIdentify,
1264285809Sscottl                                                    agFALSE,
1265285809Sscottl                                                    connectionRate,
1266285809Sscottl                                                    dmAllShared->itNexusTimeout,
1267285809Sscottl                                                    0,
1268285809Sscottl                                                    STP_DEVICE_TYPE,
1269285809Sscottl                                                    oneDeviceData,
1270285809Sscottl                                                    oneExpander,
1271285809Sscottl                                                    pDiscoverResp->phyIdentifier
1272285809Sscottl                                                    );
1273285809Sscottl                  }
1274285809Sscottl                }
1275285809Sscottl              }
1276285809Sscottl              else
1277285809Sscottl              {
1278285809Sscottl                /* incremental discovery */
1279285809Sscottl                if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
1280285809Sscottl                {
1281285809Sscottl                  AttachedDevice = dmPortSASDeviceAdd(
1282285809Sscottl                                                    dmRoot,
1283285809Sscottl                                                    onePortContext,
1284285809Sscottl                                                    sasIdentify,
1285285809Sscottl                                                    agFALSE,
1286285809Sscottl                                                    connectionRate,
1287285809Sscottl                                                    dmAllShared->itNexusTimeout,
1288285809Sscottl                                                    0,
1289285809Sscottl                                                    SAS_DEVICE_TYPE,
1290285809Sscottl                                                    oneDeviceData,
1291285809Sscottl                                                    oneExpander,
1292285809Sscottl                                                    pDiscoverResp->phyIdentifier
1293285809Sscottl                                                    );
1294285809Sscottl                }
1295285809Sscottl                else
1296285809Sscottl                {
1297285809Sscottl                  /* incremental discovery */
1298285809Sscottl                  AttachedDevice = dmFindRegNValid(
1299285809Sscottl                                                     dmRoot,
1300285809Sscottl                                                     onePortContext,
1301285809Sscottl                                                     &dmSASSubID
1302285809Sscottl                                                     );
1303285809Sscottl                  /* not registered and not valid; add this*/
1304285809Sscottl                  if (AttachedDevice == agNULL)
1305285809Sscottl                  {
1306285809Sscottl                    AttachedDevice = dmPortSASDeviceAdd(
1307285809Sscottl                                                    dmRoot,
1308285809Sscottl                                                    onePortContext,
1309285809Sscottl                                                    sasIdentify,
1310285809Sscottl                                                    agFALSE,
1311285809Sscottl                                                    connectionRate,
1312285809Sscottl                                                    dmAllShared->itNexusTimeout,
1313285809Sscottl                                                    0,
1314285809Sscottl                                                    SAS_DEVICE_TYPE,
1315285809Sscottl                                                    oneDeviceData,
1316285809Sscottl                                                    oneExpander,
1317285809Sscottl                                                    pDiscoverResp->phyIdentifier
1318285809Sscottl                                                    );
1319285809Sscottl                  }
1320285809Sscottl                }
1321285809Sscottl              }
1322285809Sscottl              /* If the device is added successfully */
1323285809Sscottl              if ( AttachedDevice != agNULL)
1324285809Sscottl              {
1325285809Sscottl
1326285809Sscottl                 /* (3.1.2.3.2.3.2.1) callback about new device */
1327285809Sscottl                if ( SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp)
1328285809Sscottl                    || SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)
1329285809Sscottl                    || SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)
1330285809Sscottl                    || SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) )
1331285809Sscottl                {
1332285809Sscottl                  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found SSP/SMP SAS %08x-%08x\n",
1333285809Sscottl                      attachedSasHi, attachedSasLo));
1334285809Sscottl                }
1335285809Sscottl                else
1336285809Sscottl                {
1337285809Sscottl                  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found a SAS STP device.\n"));
1338285809Sscottl                }
1339285809Sscottl                 /* If the attached device is an expander */
1340285809Sscottl                if ( (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
1341285809Sscottl                    || (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) )
1342285809Sscottl                {
1343285809Sscottl                  /* Allocate an expander data structure */
1344285809Sscottl                  AttachedExpander = dmDiscoveringExpanderAlloc(
1345285809Sscottl                                                                dmRoot,
1346285809Sscottl                                                                onePortContext,
1347285809Sscottl                                                                AttachedDevice
1348285809Sscottl                                                               );
1349285809Sscottl
1350285809Sscottl                  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found expander=%p\n", AttachedExpander));
1351285809Sscottl                  /* If allocate successfully */
1352285809Sscottl                  if ( AttachedExpander != agNULL)
1353285809Sscottl                  {
1354285809Sscottl                    /* Add the pAttachedExpander to discovering list */
1355285809Sscottl                    dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
1356285809Sscottl                    /* Setup upstream expander for the pExpander */
1357285809Sscottl                    oneExpander->dmUpStreamExpander = AttachedExpander;
1358285809Sscottl                  }
1359285809Sscottl                  /* If failed to allocate */
1360285809Sscottl                  else
1361285809Sscottl                  {
1362285809Sscottl                    DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, Failed to allocate expander data structure!!!\n"));
1363285809Sscottl                    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1364285809Sscottl                  }
1365285809Sscottl                }
1366285809Sscottl                /* If the attached device is an end device */
1367285809Sscottl                else
1368285809Sscottl                {
1369285809Sscottl                  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found end device\n"));
1370285809Sscottl                  /* LP2006-05-26 added upstream device to the newly found device */
1371285809Sscottl                  AttachedDevice->dmExpander = oneExpander;
1372285809Sscottl                  oneExpander->dmUpStreamExpander = agNULL;
1373285809Sscottl                }
1374285809Sscottl              }
1375285809Sscottl              else
1376285809Sscottl              {
1377285809Sscottl                DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, Failed to add a device!!!\n"));
1378285809Sscottl                dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1379285809Sscottl              }
1380285809Sscottl            }
1381285809Sscottl          }
1382285809Sscottl        }
1383285809Sscottl      } /* substractive routing */
1384285809Sscottl    }
1385285809Sscottl  }
1386285809Sscottl
1387285809Sscottl   oneExpander->discoveringPhyId ++;
1388285809Sscottl   if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
1389285809Sscottl     {
1390285809Sscottl       if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
1391285809Sscottl       {
1392285809Sscottl         DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: DISCOVERY_UP_STREAM find more ...\n"));
1393285809Sscottl         /* continue discovery for the next phy */
1394285809Sscottl         dmDiscoverSend(dmRoot, oneDeviceData);
1395285809Sscottl       }
1396285809Sscottl       else
1397285809Sscottl       {
1398285809Sscottl         DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: DISCOVERY_UP_STREAM last phy continue upstream..\n"));
1399285809Sscottl
1400285809Sscottl         /* for MCN */
1401285809Sscottl         dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
1402285809Sscottl         /* remove the expander from the discovering list */
1403285809Sscottl         dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
1404285809Sscottl         /* continue upstream discovering */
1405285809Sscottl         dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
1406285809Sscottl       }
1407285809Sscottl   }
1408285809Sscottl   else
1409285809Sscottl   {
1410285809Sscottl      DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));
1411285809Sscottl
1412285809Sscottl   }
1413285809Sscottl
1414285809Sscottl  DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
1415285809Sscottl
1416285809Sscottl  return;
1417285809Sscottl}
1418285809Sscottl
1419285809Sscottl
1420285809SscottlosGLOBAL void
1421285809SscottldmDownStreamDiscoverExpanderPhy(
1422285809Sscottl                                dmRoot_t              *dmRoot,
1423285809Sscottl                                dmIntPortContext_t    *onePortContext,
1424285809Sscottl                                dmExpander_t          *oneExpander,
1425285809Sscottl                                smpRespDiscover_t     *pDiscoverResp
1426285809Sscottl                               )
1427285809Sscottl{
1428285809Sscottl  agsaSASIdentify_t       sasIdentify;
1429285809Sscottl  dmSASSubID_t            dmSASSubID;
1430285809Sscottl  bit32                   attachedSasHi, attachedSasLo;
1431285809Sscottl  dmExpander_t            *AttachedExpander;
1432285809Sscottl  dmExpander_t            *UpStreamExpander;
1433285809Sscottl  dmExpander_t            *ConfigurableExpander = agNULL;
1434285809Sscottl  bit8                    connectionRate, negotiatedPhyLinkRate;
1435285809Sscottl  bit32                   configSASAddressHi;
1436285809Sscottl  bit32                   configSASAddressLo;
1437285809Sscottl  bit32                   dupConfigSASAddr = agFALSE;
1438285809Sscottl  dmDeviceData_t          *oneDeviceData;
1439285809Sscottl  dmDeviceData_t          *AttachedDevice = agNULL;
1440285809Sscottl  bit32                   SAS2SAS11Check = agFALSE;
1441285809Sscottl  dmIntRoot_t             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
1442285809Sscottl  dmIntContext_t          *dmAllShared  = (dmIntContext_t *)&dmIntRoot->dmAllShared;
1443285809Sscottl
1444285809Sscottl
1445285809Sscottl
1446285809Sscottl  DM_DBG3(("dmDownStreamDiscoverExpanderPhy: start\n"));
1447285809Sscottl  DM_DBG3(("dmDownStreamDiscoverExpanderPhy: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
1448285809Sscottl  DM_DBG3(("dmDownStreamDiscoverExpanderPhy: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
1449285809Sscottl
1450285809Sscottl  DM_ASSERT(dmRoot, "(dmDownStreamDiscoverExpanderPhy) dmRoot NULL");
1451285809Sscottl  DM_ASSERT(onePortContext, "(dmDownStreamDiscoverExpanderPhy) pPort NULL");
1452285809Sscottl  DM_ASSERT(oneExpander, "(dmDownStreamDiscoverExpanderPhy) pExpander NULL");
1453285809Sscottl  DM_ASSERT(pDiscoverResp, "(dmDownStreamDiscoverExpanderPhy) pDiscoverResp NULL");
1454285809Sscottl
1455285809Sscottl  DM_DBG3(("dmDownStreamDiscoverExpanderPhy: onePortContxt=%p  oneExpander=%p\n", onePortContext, oneExpander));
1456285809Sscottl
1457285809Sscottl  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
1458285809Sscottl  {
1459285809Sscottl    DM_DBG1(("dmDownStreamDiscoverExpanderPhy: invalid port or aborted discovery!!!\n"));
1460285809Sscottl    return;
1461285809Sscottl  }
1462285809Sscottl
1463285809Sscottl  if (oneExpander != oneExpander->dmDevice->dmExpander)
1464285809Sscottl  {
1465285809Sscottl    DM_DBG1(("dmDownStreamDiscoverExpanderPhy: wrong!!!\n"));
1466285809Sscottl  }
1467285809Sscottl
1468285809Sscottl  /* (1) Find the device structure of the expander */
1469285809Sscottl  oneDeviceData = oneExpander->dmDevice;
1470285809Sscottl
1471285809Sscottl  DM_ASSERT(oneDeviceData, "(dmDownStreamDiscoverExpanderPhy) pDevice NULL");
1472285809Sscottl
1473285809Sscottl  /* for debugging */
1474285809Sscottl  DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n",
1475285809Sscottl           oneExpander->discoveringPhyId,
1476285809Sscottl           oneDeviceData->SASAddressID.sasAddressHi,
1477285809Sscottl           oneDeviceData->SASAddressID.sasAddressLo));
1478285809Sscottl
1479285809Sscottl  DM_DBG3(("   Attached device: %s\n",
1480285809Sscottl           ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" :
1481285809Sscottl             (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" :
1482285809Sscottl              (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
1483285809Sscottl
1484285809Sscottl
1485285809Sscottl  /* for debugging */
1486285809Sscottl  if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
1487285809Sscottl  {
1488285809Sscottl    DM_DBG1(("dmDownStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n"));
1489285809Sscottl    DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d !!!\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
1490285809Sscottl    dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
1491285809Sscottl    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1492285809Sscottl    return;
1493285809Sscottl  }
1494285809Sscottl
1495285809Sscottl  if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
1496285809Sscottl  {
1497285809Sscottl    DM_DBG3(("   SAS address    : %08x-%08x\n",
1498285809Sscottl      DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp),
1499285809Sscottl              DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
1500285809Sscottl    DM_DBG3(("   SSP Target     : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
1501285809Sscottl    DM_DBG3(("   STP Target     : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
1502285809Sscottl    DM_DBG3(("   SMP Target     : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
1503285809Sscottl    DM_DBG3(("   SATA DEVICE    : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
1504285809Sscottl    DM_DBG3(("   SSP Initiator  : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
1505285809Sscottl    DM_DBG3(("   STP Initiator  : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
1506285809Sscottl    DM_DBG3(("   SMP Initiator  : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
1507285809Sscottl    DM_DBG3(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
1508285809Sscottl    DM_DBG3(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
1509285809Sscottl
1510285809Sscottl  }
1511285809Sscottl  /* end for debugging */
1512285809Sscottl
1513285809Sscottl  /* saving routing attribute for non self-configuring expanders */
1514285809Sscottl  oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
1515285809Sscottl
1516285809Sscottl  oneExpander->discoverSMPAllowed = agTRUE;
1517285809Sscottl
1518285809Sscottl  /* If a device is attached */
1519285809Sscottl  if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) !=  SAS_NO_DEVICE)
1520285809Sscottl  {
1521285809Sscottl    /* Setup sasIdentify for the attached device */
1522285809Sscottl    sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
1523285809Sscottl    sasIdentify.deviceType_addressFrameType = pDiscoverResp->attachedDeviceType & 0x70;
1524285809Sscottl    sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
1525285809Sscottl    sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
1526285809Sscottl    *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
1527285809Sscottl    *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
1528285809Sscottl
1529285809Sscottl    /* incremental discovery */
1530285809Sscottl    dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
1531285809Sscottl    dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
1532285809Sscottl    dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
1533285809Sscottl    dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
1534285809Sscottl
1535285809Sscottl    attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
1536285809Sscottl    attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
1537285809Sscottl
1538285809Sscottl    /* If it's a direct routing */
1539285809Sscottl    if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_DIRECT)
1540285809Sscottl    {
1541285809Sscottl      /* If the attached device is an expander */
1542285809Sscottl      if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1543285809Sscottl          || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) )
1544285809Sscottl
1545285809Sscottl      {
1546285809Sscottl        DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error direct routing can't connect to expander!!!\n"));
1547285809Sscottl        onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1548285809Sscottl           = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1549285809Sscottl        onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1550285809Sscottl          = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1551285809Sscottl        onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1552285809Sscottl        DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1553285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1554285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1555285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1556285809Sscottl
1557285809Sscottl        dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1558285809Sscottl        return;
1559285809Sscottl      }
1560285809Sscottl    }
1561285809Sscottl
1562285809Sscottl    /* If the expander's attached device is not myself */
1563285809Sscottl    if ( (attachedSasHi != onePortContext->sasLocalAddressHi)
1564285809Sscottl         || (attachedSasLo != onePortContext->sasLocalAddressLo) )
1565285809Sscottl    {
1566285809Sscottl      /* Find the attached device from discovered list */
1567285809Sscottl      AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
1568285809Sscottl      /* If the device has not been discovered before */
1569285809Sscottl      if ( AttachedDevice == agNULL) //11
1570285809Sscottl      {
1571285809Sscottl        /* If the phy has subtractive routing attribute */
1572285809Sscottl        if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE &&
1573285809Sscottl             (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
1574285809Sscottl              DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1575285809Sscottl           )
1576285809Sscottl        {
1577285809Sscottl          /* TODO: discovery error, callback */
1578285809Sscottl          DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Deferred!!! **** Topology Error subtractive routing error - inconsistent SAS address!!!\n"));
1579285809Sscottl          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1580285809Sscottl            = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1581285809Sscottl          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1582285809Sscottl            = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1583285809Sscottl          onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1584285809Sscottl          DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1585285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1586285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1587285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1588285809Sscottl
1589285809Sscottl          onePortContext->discovery.DeferredError = agTRUE;
1590285809Sscottl        }
1591285809Sscottl        else /* 11 */
1592285809Sscottl        {
1593285809Sscottl          /* Add the device */
1594285809Sscottl          /* read minimum rate from the configuration
1595285809Sscottl             onePortContext->LinkRate is SPC's local link rate
1596285809Sscottl          */
1597285809Sscottl          connectionRate = MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp));
1598285809Sscottl          DM_DBG3(("dmDownStreamDiscoverExpanderPhy: link rate 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo)));
1599285809Sscottl          DM_DBG3(("dmDownStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp)));
1600285809Sscottl          DM_DBG3(("dmDownStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate));
1601285809Sscottl          if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
1602285809Sscottl          {
1603285809Sscottl            if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
1604285809Sscottl            {
1605285809Sscottl              AttachedDevice = dmPortSASDeviceAdd(
1606285809Sscottl                                                  dmRoot,
1607285809Sscottl                                                  onePortContext,
1608285809Sscottl                                                  sasIdentify,
1609285809Sscottl                                                  agFALSE,
1610285809Sscottl                                                  connectionRate,
1611285809Sscottl                                                  dmAllShared->itNexusTimeout,
1612285809Sscottl                                                  0,
1613285809Sscottl                                                  STP_DEVICE_TYPE,
1614285809Sscottl                                                  oneDeviceData,
1615285809Sscottl                                                  oneExpander,
1616285809Sscottl                                                  pDiscoverResp->phyIdentifier
1617285809Sscottl                                                  );
1618285809Sscottl            }
1619285809Sscottl            else
1620285809Sscottl            {
1621285809Sscottl              /* incremental discovery */
1622285809Sscottl              AttachedDevice = dmFindRegNValid(
1623285809Sscottl                                                 dmRoot,
1624285809Sscottl                                                 onePortContext,
1625285809Sscottl                                                 &dmSASSubID
1626285809Sscottl                                                 );
1627285809Sscottl              /* not registered and not valid; add this*/
1628285809Sscottl              if (AttachedDevice == agNULL)
1629285809Sscottl              {
1630285809Sscottl                AttachedDevice = dmPortSASDeviceAdd(
1631285809Sscottl                                                    dmRoot,
1632285809Sscottl                                                    onePortContext,
1633285809Sscottl                                                    sasIdentify,
1634285809Sscottl                                                    agFALSE,
1635285809Sscottl                                                    connectionRate,
1636285809Sscottl                                                    dmAllShared->itNexusTimeout,
1637285809Sscottl                                                    0,
1638285809Sscottl                                                    STP_DEVICE_TYPE,
1639285809Sscottl                                                    oneDeviceData,
1640285809Sscottl                                                    oneExpander,
1641285809Sscottl                                                    pDiscoverResp->phyIdentifier
1642285809Sscottl                                                    );
1643285809Sscottl              }
1644285809Sscottl            }
1645285809Sscottl	  } /* DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp) */
1646285809Sscottl          else /* 22 */
1647285809Sscottl          {
1648285809Sscottl            if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
1649285809Sscottl            {
1650285809Sscottl              AttachedDevice = dmPortSASDeviceAdd(
1651285809Sscottl                                                  dmRoot,
1652285809Sscottl                                                  onePortContext,
1653285809Sscottl                                                  sasIdentify,
1654285809Sscottl                                                  agFALSE,
1655285809Sscottl                                                  connectionRate,
1656285809Sscottl                                                  dmAllShared->itNexusTimeout,
1657285809Sscottl                                                  0,
1658285809Sscottl                                                  SAS_DEVICE_TYPE,
1659285809Sscottl                                                  oneDeviceData,
1660285809Sscottl                                                  oneExpander,
1661285809Sscottl                                                  pDiscoverResp->phyIdentifier
1662285809Sscottl                                                  );
1663285809Sscottl            }
1664285809Sscottl            else
1665285809Sscottl            {
1666285809Sscottl              /* incremental discovery */
1667285809Sscottl              AttachedDevice = dmFindRegNValid(
1668285809Sscottl                                              dmRoot,
1669285809Sscottl                                              onePortContext,
1670285809Sscottl                                              &dmSASSubID
1671285809Sscottl                                              );
1672285809Sscottl              /* not registered and not valid; add this*/
1673285809Sscottl              if (AttachedDevice == agNULL)
1674285809Sscottl              {
1675285809Sscottl                AttachedDevice = dmPortSASDeviceAdd(
1676285809Sscottl                                                   dmRoot,
1677285809Sscottl                                                   onePortContext,
1678285809Sscottl                                                   sasIdentify,
1679285809Sscottl                                                   agFALSE,
1680285809Sscottl                                                   connectionRate,
1681285809Sscottl                                                   dmAllShared->itNexusTimeout,
1682285809Sscottl                                                   0,
1683285809Sscottl                                                   SAS_DEVICE_TYPE,
1684285809Sscottl                                                   oneDeviceData,
1685285809Sscottl                                                   oneExpander,
1686285809Sscottl                                                   pDiscoverResp->phyIdentifier
1687285809Sscottl                                                   );
1688285809Sscottl              }
1689285809Sscottl            }
1690285809Sscottl	  } /* else 22 */
1691285809Sscottl          DM_DBG3(("dmDownStreamDiscoverExpanderPhy: newDevice  pDevice=%p\n", AttachedDevice));
1692285809Sscottl          /* If the device is added successfully */
1693285809Sscottl          if ( AttachedDevice != agNULL)
1694285809Sscottl          {
1695285809Sscottl            if ( SA_IDFRM_IS_SSP_TARGET(&sasIdentify)
1696285809Sscottl                 || SA_IDFRM_IS_SMP_TARGET(&sasIdentify)
1697285809Sscottl                 || SA_IDFRM_IS_SSP_INITIATOR(&sasIdentify)
1698285809Sscottl                 || SA_IDFRM_IS_SMP_INITIATOR(&sasIdentify) )
1699285809Sscottl            {
1700285809Sscottl              DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Report a new SAS device !!\n"));
1701285809Sscottl
1702285809Sscottl            }
1703285809Sscottl            else
1704285809Sscottl            {
1705285809Sscottl              if ( SA_IDFRM_IS_STP_TARGET(&sasIdentify) ||
1706285809Sscottl                   SA_IDFRM_IS_SATA_DEVICE(&sasIdentify) )
1707285809Sscottl              {
1708285809Sscottl
1709285809Sscottl                DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found an STP or SATA device.\n"));
1710285809Sscottl              }
1711285809Sscottl              else
1712285809Sscottl              {
1713285809Sscottl                DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found Other type of device.\n"));
1714285809Sscottl              }
1715285809Sscottl            }
1716285809Sscottl
1717285809Sscottl            /* LP2006-05-26 added upstream device to the newly found device */
1718285809Sscottl            AttachedDevice->dmExpander = oneExpander;
1719285809Sscottl            DM_DBG3(("dmDownStreamDiscoverExpanderPhy: AttachedDevice %p did %d\n", AttachedDevice, AttachedDevice->id));
1720285809Sscottl            DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Attached oneExpander %p did %d\n",  AttachedDevice->dmExpander,  AttachedDevice->dmExpander->id));
1721285809Sscottl
1722285809Sscottl            DM_DBG3(("dmDownStreamDiscoverExpanderPhy: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
1723285809Sscottl            DM_DBG3(("dmDownStreamDiscoverExpanderPhy: oneExpander %p did %d\n",  oneDeviceData->dmExpander,  oneDeviceData->dmExpander->id));
1724285809Sscottl
1725285809Sscottl	    /* If the phy has table routing attribute */
1726285809Sscottl            if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
1727285809Sscottl            {
1728285809Sscottl              /* If the attached device is a fan out expander */
1729285809Sscottl              if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1730285809Sscottl              {
1731285809Sscottl                /* TODO: discovery error, callback */
1732285809Sscottl                DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys are connected!!!\n"));
1733285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1734285809Sscottl                  = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1735285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1736285809Sscottl                  = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1737285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1738285809Sscottl                DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1739285809Sscottl                          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1740285809Sscottl                          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1741285809Sscottl                          onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1742285809Sscottl                /* discovery done */
1743285809Sscottl                dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1744285809Sscottl              }
1745285809Sscottl              else if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
1746285809Sscottl              {
1747285809Sscottl                /* Allocate an expander data structure */
1748285809Sscottl                AttachedExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, AttachedDevice);
1749285809Sscottl
1750285809Sscottl                DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found a EDGE exp device.%p\n", AttachedExpander));
1751285809Sscottl                /* If allocate successfully */
1752285809Sscottl                if ( AttachedExpander != agNULL)
1753285809Sscottl                {
1754285809Sscottl                  /* set up downstream information on configurable expander */
1755285809Sscottl                  dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId);
1756285809Sscottl                  /* Setup upstream information */
1757285809Sscottl                  dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
1758285809Sscottl                  AttachedExpander->hasUpStreamDevice = agTRUE;
1759285809Sscottl                  AttachedExpander->upStreamSASAddressHi
1760285809Sscottl                    = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1761285809Sscottl                  AttachedExpander->upStreamSASAddressLo
1762285809Sscottl                    = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1763285809Sscottl                  AttachedExpander->dmUpStreamExpander = oneExpander;
1764285809Sscottl                  /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */
1765285809Sscottl                  dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
1766285809Sscottl                }
1767285809Sscottl                /* If failed to allocate */
1768285809Sscottl                else
1769285809Sscottl                {
1770285809Sscottl                  DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Failed to allocate expander data structure!!!\n"));
1771285809Sscottl                  /*  discovery done */
1772285809Sscottl                  dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1773285809Sscottl                }
1774285809Sscottl              }
1775285809Sscottl	    } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE */
1776285809Sscottl            /* If status is still DISCOVERY_DOWN_STREAM */
1777285809Sscottl            if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
1778285809Sscottl            {
1779285809Sscottl              DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st before\n"));
1780285809Sscottl              dmDumpAllUpExp(dmRoot, onePortContext, oneExpander);
1781285809Sscottl              UpStreamExpander = oneExpander->dmUpStreamExpander;
1782285809Sscottl              ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
1783285809Sscottl              configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
1784285809Sscottl              configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
1785285809Sscottl              if (ConfigurableExpander)
1786285809Sscottl              {
1787285809Sscottl                if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi
1788285809Sscottl                      == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
1789285809Sscottl                     (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo
1790285809Sscottl                      == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
1791285809Sscottl                   )
1792285809Sscottl                { /* directly attached between oneExpander and ConfigurableExpander */
1793285809Sscottl                  DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st before loc 1\n"));
1794285809Sscottl                  configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi;
1795285809Sscottl                  configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo;
1796285809Sscottl                }
1797285809Sscottl                else
1798285809Sscottl                {
1799285809Sscottl                  DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st before loc 2\n"));
1800285809Sscottl                  configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
1801285809Sscottl                  configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
1802285809Sscottl                }
1803285809Sscottl              } /* if !ConfigurableExpander */
1804285809Sscottl
1805285809Sscottl              dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot,
1806285809Sscottl                                                          ConfigurableExpander,
1807285809Sscottl                                                          configSASAddressHi,
1808285809Sscottl                                                          configSASAddressLo
1809285809Sscottl                                                          );
1810285809Sscottl
1811285809Sscottl              if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
1812285809Sscottl              {
1813285809Sscottl                DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st q123\n"));
1814285809Sscottl                UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
1815285809Sscottl                ConfigurableExpander->currentDownStreamPhyIndex =
1816285809Sscottl                        dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
1817285809Sscottl                ConfigurableExpander->dmReturnginExpander = oneExpander;
1818285809Sscottl                dmRoutingEntryAdd(dmRoot,
1819285809Sscottl                                  ConfigurableExpander,
1820285809Sscottl                                  ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
1821285809Sscottl                                  configSASAddressHi,
1822285809Sscottl                                  configSASAddressLo
1823285809Sscottl                                 );
1824285809Sscottl              }
1825285809Sscottl            } /* onePortContext->discovery.status == DISCOVERY_DOWN_STREAM */
1826285809Sscottl          } /* AttachedDevice != agNULL */
1827285809Sscottl          /*  If fail to add the device */
1828285809Sscottl          else
1829285809Sscottl          {
1830285809Sscottl            DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Failed to add a device!!!\n"));
1831285809Sscottl            /*  discovery done */
1832285809Sscottl            dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1833285809Sscottl          }
1834285809Sscottl        } /* else 11 */
1835285809Sscottl      } /* AttachedDevice == agNULL */
1836285809Sscottl      /* If the device has been discovered before */
1837285809Sscottl      else /* haha discovered before 33 */
1838285809Sscottl      {
1839285809Sscottl        /* If the phy has subtractive routing attribute */
1840285809Sscottl        if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
1841285809Sscottl        {
1842285809Sscottl          /* If the expander doesn't have up stream device */
1843285809Sscottl          if ( oneExpander->hasUpStreamDevice == agFALSE)
1844285809Sscottl          {
1845285809Sscottl            /* TODO: discovery error, callback */
1846285809Sscottl            DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error loop, or end device connects to two expanders!!!\n"));
1847285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1848285809Sscottl              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1849285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1850285809Sscottl              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1851285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1852285809Sscottl            DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1853285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1854285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1855285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1856285809Sscottl            /* discovery done */
1857285809Sscottl            dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1858285809Sscottl          }
1859285809Sscottl          /* If the expander has up stream device */
1860285809Sscottl          else /* 44 */
1861285809Sscottl          {
1862285809Sscottl            /* If sas address doesn't match */
1863285809Sscottl            if ( (oneExpander->upStreamSASAddressHi != attachedSasHi)
1864285809Sscottl                 || (oneExpander->upStreamSASAddressLo != attachedSasLo) )
1865285809Sscottl            {
1866285809Sscottl              /* TODO: discovery error, callback */
1867285809Sscottl              DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two subtractive phys!!!\n"));
1868285809Sscottl              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1869285809Sscottl                = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1870285809Sscottl              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1871285809Sscottl                = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1872285809Sscottl              onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1873285809Sscottl              DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1874285809Sscottl                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1875285809Sscottl                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1876285809Sscottl                       onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1877285809Sscottl              /* discovery done */
1878285809Sscottl              dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1879285809Sscottl            }
1880285809Sscottl          } /* else 44 */
1881285809Sscottl        } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE */
1882285809Sscottl        /* If the phy has table routing attribute */
1883285809Sscottl        else if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
1884285809Sscottl        {
1885285809Sscottl          /* If the attached device is a fan out expander */
1886285809Sscottl          if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
1887285809Sscottl          {
1888285809Sscottl            /* (2.3.3.2.1.1) TODO: discovery error, callback */
1889285809Sscottl            DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error fan out expander to routing table phy!!!\n"));
1890285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1891285809Sscottl              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1892285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1893285809Sscottl              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1894285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1895285809Sscottl            DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1896285809Sscottl                     onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1897285809Sscottl                     onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1898285809Sscottl                     onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1899285809Sscottl            /* discovery done */
1900285809Sscottl            dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1901285809Sscottl          }
1902285809Sscottl          /* If the attached device is an edge expander */
1903285809Sscottl          else if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
1904285809Sscottl          {
1905285809Sscottl            /* Setup up stream inform */
1906285809Sscottl            AttachedExpander = AttachedDevice->dmExpander;
1907285809Sscottl            DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found edge expander=%p\n", AttachedExpander));
1908285809Sscottl            /* If the attached expander has up stream device */
1909285809Sscottl            if ( AttachedExpander->hasUpStreamDevice == agTRUE)
1910285809Sscottl            {
1911285809Sscottl              /* compare the sas address */
1912285809Sscottl              if ( (AttachedExpander->upStreamSASAddressHi
1913285809Sscottl                    != DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
1914285809Sscottl                   || (AttachedExpander->upStreamSASAddressLo
1915285809Sscottl                       != DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)))
1916285809Sscottl              {
1917285809Sscottl                /* TODO: discovery error, callback */
1918285809Sscottl                SAS2SAS11Check = dmSAS2SAS11ErrorCheck(dmRoot, onePortContext, AttachedExpander, oneExpander, oneExpander);
1919285809Sscottl                if (SAS2SAS11Check == agTRUE)
1920285809Sscottl                {
1921285809Sscottl                   DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error SAS2 and SAS1.1!!!\n"));
1922285809Sscottl                }
1923285809Sscottl                else
1924285809Sscottl                {
1925285809Sscottl                  DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys connected (1)!!!\n"));
1926285809Sscottl                }
1927285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1928285809Sscottl                  = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1929285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1930285809Sscottl                  = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1931285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1932285809Sscottl                DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1933285809Sscottl                         onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1934285809Sscottl                         onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1935285809Sscottl                         onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1936285809Sscottl                /* discovery done */
1937285809Sscottl                dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1938285809Sscottl              }
1939285809Sscottl              else
1940285809Sscottl              {
1941285809Sscottl                DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Add edge expander=%p\n", AttachedExpander));
1942285809Sscottl                /* set up downstream information on configurable expander */
1943285809Sscottl
1944285809Sscottl                dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId);
1945285809Sscottl                /* haha */
1946285809Sscottl                dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
1947285809Sscottl                /* Add the pAttachedExpander to discovering list */
1948285809Sscottl                dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
1949285809Sscottl              }
1950285809Sscottl            } /* AttachedExpander->hasUpStreamDevice == agTRUE */
1951285809Sscottl            /* If the attached expander doesn't have up stream device */
1952285809Sscottl            else
1953285809Sscottl            {
1954285809Sscottl              /* TODO: discovery error, callback */
1955285809Sscottl              DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys connected (2)!!!\n"));
1956285809Sscottl              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
1957285809Sscottl                = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
1958285809Sscottl              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
1959285809Sscottl                = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
1960285809Sscottl              onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
1961285809Sscottl              DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
1962285809Sscottl                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
1963285809Sscottl                       onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
1964285809Sscottl                       onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
1965285809Sscottl              /* discovery done */
1966285809Sscottl              dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1967285809Sscottl            }
1968285809Sscottl          } /* DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE */
1969285809Sscottl        } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE */
1970285809Sscottl        /* do this regradless of sub or table */
1971285809Sscottl        /* If status is still DISCOVERY_DOWN_STREAM */
1972285809Sscottl        if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
1973285809Sscottl        {
1974285809Sscottl          DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd before\n"));
1975285809Sscottl          dmDumpAllUpExp(dmRoot, onePortContext, oneExpander);
1976285809Sscottl
1977285809Sscottl          UpStreamExpander = oneExpander->dmUpStreamExpander;
1978285809Sscottl          ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
1979285809Sscottl          configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
1980285809Sscottl          configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
1981285809Sscottl          if (ConfigurableExpander)
1982285809Sscottl          {
1983285809Sscottl            if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi
1984285809Sscottl                 == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
1985285809Sscottl                 (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo
1986285809Sscottl                   == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
1987285809Sscottl               )
1988285809Sscottl            { /* directly attached between oneExpander and ConfigurableExpander */
1989285809Sscottl              DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd before loc 1\n"));
1990285809Sscottl              configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi;
1991285809Sscottl              configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo;
1992285809Sscottl            }
1993285809Sscottl            else
1994285809Sscottl            {
1995285809Sscottl              DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd before loc 2\n"));
1996285809Sscottl              configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
1997285809Sscottl              configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
1998285809Sscottl            }
1999285809Sscottl          } /* if !ConfigurableExpander */
2000285809Sscottl          dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot,
2001285809Sscottl                                                      ConfigurableExpander,
2002285809Sscottl                                                      configSASAddressHi,
2003285809Sscottl                                                      configSASAddressLo
2004285809Sscottl                                                      );
2005285809Sscottl          if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
2006285809Sscottl          {
2007285809Sscottl            DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd q123 \n"));
2008285809Sscottl            UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
2009285809Sscottl            ConfigurableExpander->currentDownStreamPhyIndex =
2010285809Sscottl                        dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
2011285809Sscottl            ConfigurableExpander->dmReturnginExpander = oneExpander;
2012285809Sscottl            dmRoutingEntryAdd(dmRoot,
2013285809Sscottl                              ConfigurableExpander,
2014285809Sscottl                              ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
2015285809Sscottl                              configSASAddressHi,
2016285809Sscottl                              configSASAddressLo
2017285809Sscottl                             );
2018285809Sscottl          }
2019285809Sscottl        } /* onePortContext->discovery.status == DISCOVERY_DOWN_STREAM */
2020285809Sscottl        /* incremental discovery */
2021285809Sscottl        if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START)
2022285809Sscottl        {
2023285809Sscottl          connectionRate = MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp));
2024285809Sscottl
2025285809Sscottl          if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
2026285809Sscottl          {
2027285809Sscottl            DM_DBG3(("dmDownStreamDiscoverExpanderPhy: incremental SATA_STP\n"));
2028285809Sscottl
2029285809Sscottl            dmPortSASDeviceAdd(
2030285809Sscottl                              dmRoot,
2031285809Sscottl                              onePortContext,
2032285809Sscottl                              sasIdentify,
2033285809Sscottl                              agFALSE,
2034285809Sscottl                              connectionRate,
2035285809Sscottl                              dmAllShared->itNexusTimeout,
2036285809Sscottl                              0,
2037285809Sscottl                              STP_DEVICE_TYPE,
2038285809Sscottl                              oneDeviceData,
2039285809Sscottl                              oneExpander,
2040285809Sscottl                              pDiscoverResp->phyIdentifier
2041285809Sscottl                              );
2042285809Sscottl          }
2043285809Sscottl          else
2044285809Sscottl          {
2045285809Sscottl            DM_DBG3(("dmDownStreamDiscoverExpanderPhy: incremental SAS\n"));
2046285809Sscottl
2047285809Sscottl
2048285809Sscottl             dmPortSASDeviceAdd(
2049285809Sscottl                               dmRoot,
2050285809Sscottl                               onePortContext,
2051285809Sscottl                               sasIdentify,
2052285809Sscottl                               agFALSE,
2053285809Sscottl                               connectionRate,
2054285809Sscottl                               dmAllShared->itNexusTimeout,
2055285809Sscottl                               0,
2056285809Sscottl                               SAS_DEVICE_TYPE,
2057285809Sscottl                               oneDeviceData,
2058285809Sscottl                               oneExpander,
2059285809Sscottl                               pDiscoverResp->phyIdentifier
2060285809Sscottl                               );
2061285809Sscottl
2062285809Sscottl          }
2063285809Sscottl        } /* onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START */
2064285809Sscottl      } /* else 33 */
2065285809Sscottl    } /* (attachedSasLo != onePortContext->sasLocalAddressLo) */
2066285809Sscottl
2067285809Sscottl    else /* else 44 */
2068285809Sscottl    {
2069285809Sscottl      DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found Self\n"));
2070285809Sscottl      DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 3rd before\n"));
2071285809Sscottl      dmDumpAllUpExp(dmRoot, onePortContext, oneExpander);
2072285809Sscottl
2073285809Sscottl      UpStreamExpander = oneExpander->dmUpStreamExpander;
2074285809Sscottl      ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
2075285809Sscottl      dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot,
2076285809Sscottl                                                  ConfigurableExpander,
2077285809Sscottl                                                  onePortContext->sasLocalAddressHi,
2078285809Sscottl                                                  onePortContext->sasLocalAddressLo
2079285809Sscottl                                                  );
2080285809Sscottl
2081285809Sscottl      if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
2082285809Sscottl      {
2083285809Sscottl        DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 3rd q123 Setup routing table\n"));
2084285809Sscottl        UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
2085285809Sscottl        ConfigurableExpander->currentDownStreamPhyIndex =
2086285809Sscottl                        dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
2087285809Sscottl        ConfigurableExpander->dmReturnginExpander = oneExpander;
2088285809Sscottl        dmRoutingEntryAdd(dmRoot,
2089285809Sscottl                          ConfigurableExpander,
2090285809Sscottl                          ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
2091285809Sscottl                          onePortContext->sasLocalAddressHi,
2092285809Sscottl                          onePortContext->sasLocalAddressLo
2093285809Sscottl                         );
2094285809Sscottl      }
2095285809Sscottl    } /* else 44 */
2096285809Sscottl  } /* DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) !=  SAS_NO_DEVICE */
2097285809Sscottl  /* If no device is attached */
2098285809Sscottl  else
2099285809Sscottl  {
2100285809Sscottl
2101285809Sscottl   DM_DBG2(("!!!!!!!!!!!!!!!!!!!!! SPIN SATA !!!!!!!!!!!!!!!!!!!!!!!!!!!\n"));
2102285809Sscottl   negotiatedPhyLinkRate =	DISCRSP_GET_LINKRATE(pDiscoverResp); // added by thenil
2103285809Sscottl
2104285809Sscottl     if (negotiatedPhyLinkRate == 0x03)
2105285809Sscottl     {
2106285809Sscottl
2107285809Sscottl        DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: SPIN SATA sent reset\n"));
2108285809Sscottl		dmPhyControlSend(dmRoot,
2109285809Sscottl                            oneDeviceData,
2110285809Sscottl                            SMP_PHY_CONTROL_HARD_RESET,
2111285809Sscottl                                                           pDiscoverResp->phyIdentifier
2112285809Sscottl                           );
2113285809Sscottl    }
2114285809Sscottl
2115285809Sscottl    /* do nothing */
2116285809Sscottl  }
2117285809Sscottl
2118285809Sscottl
2119285809Sscottl  /* Increment the discovering phy id */
2120285809Sscottl  oneExpander->discoveringPhyId ++;
2121285809Sscottl
2122285809Sscottl  /* If the discovery status is DISCOVERY_DOWN_STREAM */
2123285809Sscottl  if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
2124285809Sscottl  {
2125285809Sscottl    /* If not the last phy */
2126285809Sscottl    if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
2127285809Sscottl    {
2128285809Sscottl      DM_DBG3(("dmDownStreamDiscoverExpanderPhy: More Phys to discover\n"));
2129285809Sscottl      /* continue discovery for the next phy */
2130285809Sscottl      dmDiscoverSend(dmRoot, oneDeviceData);
2131285809Sscottl    }
2132285809Sscottl    /* If the last phy */
2133285809Sscottl    else
2134285809Sscottl    {
2135285809Sscottl      DM_DBG3(("dmDownStreamDiscoverExpanderPhy: No More Phys\n"));
2136285809Sscottl
2137285809Sscottl      /* for MCN */
2138285809Sscottl      dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
2139285809Sscottl      /* remove the expander from the discovering list */
2140285809Sscottl      dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
2141285809Sscottl      /* continue downstream discovering */
2142285809Sscottl      dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
2143285809Sscottl    }
2144285809Sscottl  }
2145285809Sscottl  else
2146285809Sscottl  {
2147285809Sscottl    DM_DBG3(("dmDownStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));
2148285809Sscottl  }
2149285809Sscottl  DM_DBG3(("dmDownStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
2150285809Sscottl
2151285809Sscottl  return;
2152285809Sscottl}
2153285809Sscottl
2154285809Sscottl
2155285809Sscottl/* works at SAS2 expander (called in dmDownStreamDiscover2ExpanderPhy())
2156285809Sscottl   if currentExpander is SAS2, called in dmDownStreamDiscover2ExpanderPhy()
2157285809Sscottl   if currentExpander is SAS1.1, called in dmDownStreamDiscoverExpanderPhy()
2158285809Sscottl*/
2159285809SscottlosGLOBAL bit32
2160285809SscottldmSAS2SAS11ErrorCheck(
2161285809Sscottl                      dmRoot_t              *dmRoot,
2162285809Sscottl                      dmIntPortContext_t    *onePortContext,
2163285809Sscottl                      dmExpander_t          *topExpander,
2164285809Sscottl                      dmExpander_t          *bottomExpander,
2165285809Sscottl		      dmExpander_t          *currentExpander
2166285809Sscottl                     )
2167285809Sscottl{
2168285809Sscottl  bit32                   result = agFALSE, i = 0;
2169285809Sscottl  bit8                    downStreamPhyID, upStreamPhyID;
2170285809Sscottl
2171285809Sscottl  DM_DBG2(("dmSAS2SAS11ErrorCheck: start\n"));
2172285809Sscottl
2173285809Sscottl  if (topExpander == agNULL)
2174285809Sscottl  {
2175285809Sscottl    DM_DBG2(("dmSAS2SAS11ErrorCheck: topExpander is NULL\n"));
2176285809Sscottl    return result;
2177285809Sscottl  }
2178285809Sscottl  if (bottomExpander == agNULL)
2179285809Sscottl  {
2180285809Sscottl    DM_DBG2(("dmSAS2SAS11ErrorCheck: bottomExpander is NULL\n"));
2181285809Sscottl    return result;
2182285809Sscottl  }
2183285809Sscottl
2184285809Sscottl  if (currentExpander == agNULL)
2185285809Sscottl  {
2186285809Sscottl    DM_DBG2(("dmSAS2SAS11ErrorCheck: currentExpander is NULL\n"));
2187285809Sscottl    return result;
2188285809Sscottl  }
2189285809Sscottl
2190285809Sscottl  DM_DBG2(("dmSAS2SAS11ErrorCheck: topExpander addrHi 0x%08x addrLo 0x%08x\n",
2191285809Sscottl            topExpander->dmDevice->SASAddressID.sasAddressHi, topExpander->dmDevice->SASAddressID.sasAddressLo));
2192285809Sscottl  DM_DBG2(("dmSAS2SAS11ErrorCheck: bottomExpander addrHi 0x%08x addrLo 0x%08x\n",
2193285809Sscottl            bottomExpander->dmDevice->SASAddressID.sasAddressHi, bottomExpander->dmDevice->SASAddressID.sasAddressLo));
2194285809Sscottl  DM_DBG2(("dmSAS2SAS11ErrorCheck: currentExpander addrHi 0x%08x addrLo 0x%08x\n",
2195285809Sscottl            currentExpander->dmDevice->SASAddressID.sasAddressHi, currentExpander->dmDevice->SASAddressID.sasAddressLo));
2196285809Sscottl
2197285809Sscottl  for (i=0;i<DM_MAX_EXPANDER_PHYS;i++)
2198285809Sscottl  {
2199285809Sscottl    downStreamPhyID = topExpander->downStreamPhys[i];
2200285809Sscottl    upStreamPhyID = bottomExpander->upStreamPhys[i];
2201285809Sscottl    if (currentExpander->SAS2 == 1)
2202285809Sscottl    {
2203285809Sscottl      if ( downStreamPhyID ==  upStreamPhyID &&
2204285809Sscottl           topExpander->routingAttribute[downStreamPhyID] == SAS_ROUTING_TABLE &&
2205285809Sscottl           bottomExpander->routingAttribute[i] == SAS_ROUTING_SUBTRACTIVE &&
2206285809Sscottl           topExpander->SAS2 == 0 &&
2207285809Sscottl           bottomExpander->SAS2 == 1
2208285809Sscottl         )
2209285809Sscottl      {
2210285809Sscottl        result = agTRUE;
2211285809Sscottl        break;
2212285809Sscottl      }
2213285809Sscottl    }
2214285809Sscottl    else if (currentExpander->SAS2 == 0)
2215285809Sscottl    {
2216285809Sscottl      if ( downStreamPhyID ==  upStreamPhyID &&
2217285809Sscottl           topExpander->routingAttribute[downStreamPhyID] == SAS_ROUTING_SUBTRACTIVE &&
2218285809Sscottl           bottomExpander->routingAttribute[i] == SAS_ROUTING_TABLE &&
2219285809Sscottl           topExpander->SAS2 == 1 &&
2220285809Sscottl           bottomExpander->SAS2 == 0
2221285809Sscottl         )
2222285809Sscottl      {
2223285809Sscottl        result = agTRUE;
2224285809Sscottl        break;
2225285809Sscottl      }
2226285809Sscottl    }
2227285809Sscottl  }
2228285809Sscottl  return result;
2229285809Sscottl}
2230285809Sscottl
2231285809SscottlosGLOBAL void
2232285809SscottldmDownStreamDiscover2ExpanderPhy(
2233285809Sscottl                                dmRoot_t              *dmRoot,
2234285809Sscottl                                dmIntPortContext_t    *onePortContext,
2235285809Sscottl                                dmExpander_t          *oneExpander,
2236285809Sscottl                                smpRespDiscover2_t     *pDiscoverResp
2237285809Sscottl                                )
2238285809Sscottl{
2239285809Sscottl  dmDeviceData_t          *oneDeviceData;
2240285809Sscottl  dmExpander_t            *UpStreamExpander;
2241285809Sscottl  dmDeviceData_t          *AttachedDevice = agNULL;
2242285809Sscottl  dmExpander_t            *AttachedExpander;
2243285809Sscottl  agsaSASIdentify_t       sasIdentify;
2244285809Sscottl  bit8                    connectionRate;
2245285809Sscottl  bit32                   attachedSasHi, attachedSasLo;
2246285809Sscottl  dmSASSubID_t            dmSASSubID;
2247285809Sscottl  dmExpander_t            *ConfigurableExpander = agNULL;
2248285809Sscottl  bit32                   dupConfigSASAddr = agFALSE;
2249285809Sscottl  bit32                   configSASAddressHi;
2250285809Sscottl  bit32                   configSASAddressLo;
2251285809Sscottl  bit32                   SAS2SAS11Check = agFALSE;
2252285809Sscottl  dmIntRoot_t             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
2253285809Sscottl  dmIntContext_t          *dmAllShared  = (dmIntContext_t *)&dmIntRoot->dmAllShared;
2254285809Sscottl
2255285809Sscottl
2256285809Sscottl  DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: start\n"));
2257285809Sscottl  DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
2258285809Sscottl  DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
2259285809Sscottl
2260285809Sscottl  DM_ASSERT(dmRoot, "(dmDownStreamDiscover2ExpanderPhy) dmRoot NULL");
2261285809Sscottl  DM_ASSERT(onePortContext, "(dmDownStreamDiscover2ExpanderPhy) pPort NULL");
2262285809Sscottl  DM_ASSERT(oneExpander, "(dmDownStreamDiscover2ExpanderPhy) pExpander NULL");
2263285809Sscottl  DM_ASSERT(pDiscoverResp, "(dmDownStreamDiscover2ExpanderPhy) pDiscoverResp NULL");
2264285809Sscottl
2265285809Sscottl  DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: onePortContxt=%p  oneExpander=%p  oneDeviceData=%p\n", onePortContext, oneExpander, oneExpander->dmDevice));
2266285809Sscottl
2267285809Sscottl  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
2268285809Sscottl  {
2269285809Sscottl    DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: invalid port or aborted discovery!!!\n"));
2270285809Sscottl    return;
2271285809Sscottl  }
2272285809Sscottl
2273285809Sscottl  if (oneExpander != oneExpander->dmDevice->dmExpander)
2274285809Sscottl  {
2275285809Sscottl    DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: wrong!!!\n"));
2276285809Sscottl  }
2277285809Sscottl
2278285809Sscottl
2279285809Sscottl  /* (1) Find the device structure of the expander */
2280285809Sscottl  oneDeviceData = oneExpander->dmDevice;
2281285809Sscottl
2282285809Sscottl  DM_ASSERT(oneDeviceData, "(dmDownStreamDiscover2ExpanderPhy) pDevice NULL");
2283285809Sscottl
2284285809Sscottl  /* for debugging */
2285285809Sscottl  DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Phy #%d of SAS %08x-%08x\n",
2286285809Sscottl           oneExpander->discoveringPhyId,
2287285809Sscottl           oneDeviceData->SASAddressID.sasAddressHi,
2288285809Sscottl           oneDeviceData->SASAddressID.sasAddressLo));
2289285809Sscottl
2290285809Sscottl  DM_DBG2(("   Attached device: %s\n",
2291285809Sscottl           ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" :
2292285809Sscottl             (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" :
2293285809Sscottl              (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
2294285809Sscottl
2295285809Sscottl
2296285809Sscottl  /* for debugging */
2297285809Sscottl  if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
2298285809Sscottl  {
2299285809Sscottl    DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: !!! Incorrect SMP response !!!\n"));
2300285809Sscottl    DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
2301285809Sscottl    dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover2_t));
2302285809Sscottl    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2303285809Sscottl    return;
2304285809Sscottl  }
2305285809Sscottl
2306285809Sscottl  if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
2307285809Sscottl  {
2308285809Sscottl    DM_DBG2(("   SAS address    : %08x-%08x\n",
2309285809Sscottl      SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp),
2310285809Sscottl              SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
2311285809Sscottl    DM_DBG2(("   SSP Target     : %d\n", SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
2312285809Sscottl    DM_DBG2(("   STP Target     : %d\n", SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
2313285809Sscottl    DM_DBG2(("   SMP Target     : %d\n", SAS2_DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
2314285809Sscottl    DM_DBG2(("   SATA DEVICE    : %d\n", SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
2315285809Sscottl    DM_DBG2(("   SSP Initiator  : %d\n", SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
2316285809Sscottl    DM_DBG2(("   STP Initiator  : %d\n", SAS2_DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
2317285809Sscottl    DM_DBG2(("   SMP Initiator  : %d\n", SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
2318285809Sscottl    DM_DBG2(("   Phy ID         : %d\n", pDiscoverResp->phyIdentifier));
2319285809Sscottl    DM_DBG2(("   Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
2320285809Sscottl
2321285809Sscottl  }
2322285809Sscottl
2323285809Sscottl    /* saving routing attribute for non self-configuring expanders */
2324285809Sscottl  oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
2325285809Sscottl
2326285809Sscottl
2327285809Sscottl  oneExpander->discoverSMPAllowed = agTRUE;
2328285809Sscottl
2329285809Sscottl  /* If a device is attached */
2330285809Sscottl  if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) !=  SAS_NO_DEVICE)
2331285809Sscottl  {
2332285809Sscottl    /* Setup sasIdentify for the attached device */
2333285809Sscottl    sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
2334285809Sscottl    sasIdentify.deviceType_addressFrameType = pDiscoverResp->attachedDeviceTypeReason & 0x70;
2335285809Sscottl    sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
2336285809Sscottl    sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
2337285809Sscottl    *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
2338285809Sscottl    *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
2339285809Sscottl
2340285809Sscottl    /* incremental discovery */
2341285809Sscottl    dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
2342285809Sscottl    dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
2343285809Sscottl    dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
2344285809Sscottl    dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
2345285809Sscottl
2346285809Sscottl    attachedSasHi = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
2347285809Sscottl    attachedSasLo = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
2348285809Sscottl
2349285809Sscottl    /* If it's a direct routing */
2350285809Sscottl    if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_DIRECT)
2351285809Sscottl    {
2352285809Sscottl      /* If the attached device is an expander */
2353285809Sscottl      if ( (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
2354285809Sscottl          || (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) )
2355285809Sscottl
2356285809Sscottl      {
2357285809Sscottl        DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error direct routing can't connect to expander!!!\n"));
2358285809Sscottl        onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2359285809Sscottl           = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2360285809Sscottl        onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2361285809Sscottl          = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2362285809Sscottl        onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2363285809Sscottl
2364285809Sscottl        DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
2365285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
2366285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2367285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2368285809Sscottl        dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2369285809Sscottl
2370285809Sscottl        return;
2371285809Sscottl      }
2372285809Sscottl    }
2373285809Sscottl
2374285809Sscottl    /* If the expander's attached device is not myself */
2375285809Sscottl    if ( (attachedSasHi != onePortContext->sasLocalAddressHi)
2376285809Sscottl         || (attachedSasLo != onePortContext->sasLocalAddressLo) )
2377285809Sscottl    {
2378285809Sscottl      /* Find the attached device from discovered list */
2379285809Sscottl      AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData);
2380285809Sscottl      /* If the device has not been discovered before */
2381285809Sscottl      if ( AttachedDevice == agNULL) //11
2382285809Sscottl      {
2383285809Sscottl        //qqqqqq
2384285809Sscottl        if (0)
2385285809Sscottl        {
2386285809Sscottl	      DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n"));
2387285809Sscottl          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2388285809Sscottl            = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2389285809Sscottl          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2390285809Sscottl            = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2391285809Sscottl          onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2392285809Sscottl          DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
2393285809Sscottl                    onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
2394285809Sscottl                    onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2395285809Sscottl                    onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2396285809Sscottl          /* discovery done */
2397285809Sscottl          dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2398285809Sscottl        }
2399285809Sscottl        else
2400285809Sscottl        {
2401285809Sscottl          /* Add the device */
2402285809Sscottl          /* read minimum rate from the configuration
2403285809Sscottl             onePortContext->LinkRate is SPC's local link rate
2404285809Sscottl          */
2405285809Sscottl          connectionRate = MIN(onePortContext->LinkRate, SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pDiscoverResp));
2406285809Sscottl          DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: link rate 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo)));
2407285809Sscottl          DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: negotiatedPhyLinkRate 0x%x\n", SAS2_DISCRSP_GET_LINKRATE(pDiscoverResp)));
2408285809Sscottl          DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: connectionRate 0x%x\n", connectionRate));
2409285809Sscottl
2410285809Sscottl          if (SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
2411285809Sscottl          {
2412285809Sscottl            if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
2413285809Sscottl            {
2414285809Sscottl              AttachedDevice = dmPortSASDeviceAdd(
2415285809Sscottl                                                 dmRoot,
2416285809Sscottl                                                 onePortContext,
2417285809Sscottl                                                 sasIdentify,
2418285809Sscottl                                                 agFALSE,
2419285809Sscottl                                                 connectionRate,
2420285809Sscottl                                                 dmAllShared->itNexusTimeout,
2421285809Sscottl                                                 0,
2422285809Sscottl                                                 STP_DEVICE_TYPE,
2423285809Sscottl                                                 oneDeviceData,
2424285809Sscottl                                                 oneExpander,
2425285809Sscottl                                                 pDiscoverResp->phyIdentifier
2426285809Sscottl                                                 );
2427285809Sscottl            }
2428285809Sscottl            else
2429285809Sscottl            {
2430285809Sscottl              /* incremental discovery */
2431285809Sscottl              AttachedDevice = dmFindRegNValid(
2432285809Sscottl                                               dmRoot,
2433285809Sscottl                                               onePortContext,
2434285809Sscottl                                               &dmSASSubID
2435285809Sscottl                                               );
2436285809Sscottl              /* not registered and not valid; add this*/
2437285809Sscottl              if (AttachedDevice == agNULL)
2438285809Sscottl              {
2439285809Sscottl                AttachedDevice = dmPortSASDeviceAdd(
2440285809Sscottl                                                   dmRoot,
2441285809Sscottl                                                   onePortContext,
2442285809Sscottl                                                   sasIdentify,
2443285809Sscottl                                                   agFALSE,
2444285809Sscottl                                                   connectionRate,
2445285809Sscottl                                                   dmAllShared->itNexusTimeout,
2446285809Sscottl                                                   0,
2447285809Sscottl                                                   STP_DEVICE_TYPE,
2448285809Sscottl                                                   oneDeviceData,
2449285809Sscottl                                                   oneExpander,
2450285809Sscottl                                                   pDiscoverResp->phyIdentifier
2451285809Sscottl                                                   );
2452285809Sscottl              }
2453285809Sscottl            }
2454285809Sscottl          }
2455285809Sscottl          else
2456285809Sscottl          {
2457285809Sscottl            if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
2458285809Sscottl            {
2459285809Sscottl              AttachedDevice = dmPortSASDeviceAdd(
2460285809Sscottl                                                 dmRoot,
2461285809Sscottl                                                 onePortContext,
2462285809Sscottl                                                 sasIdentify,
2463285809Sscottl                                                 agFALSE,
2464285809Sscottl                                                 connectionRate,
2465285809Sscottl                                                 dmAllShared->itNexusTimeout,
2466285809Sscottl                                                 0,
2467285809Sscottl                                                 SAS_DEVICE_TYPE,
2468285809Sscottl                                                 oneDeviceData,
2469285809Sscottl                                                 oneExpander,
2470285809Sscottl                                                 pDiscoverResp->phyIdentifier
2471285809Sscottl                                                 );
2472285809Sscottl            }
2473285809Sscottl            else
2474285809Sscottl            {
2475285809Sscottl              /* incremental discovery */
2476285809Sscottl              AttachedDevice = dmFindRegNValid(
2477285809Sscottl                                               dmRoot,
2478285809Sscottl                                               onePortContext,
2479285809Sscottl                                               &dmSASSubID
2480285809Sscottl                                               );
2481285809Sscottl              /* not registered and not valid; add this*/
2482285809Sscottl              if (AttachedDevice == agNULL)
2483285809Sscottl              {
2484285809Sscottl                AttachedDevice = dmPortSASDeviceAdd(
2485285809Sscottl                                                    dmRoot,
2486285809Sscottl                                                    onePortContext,
2487285809Sscottl                                                    sasIdentify,
2488285809Sscottl                                                    agFALSE,
2489285809Sscottl                                                    connectionRate,
2490285809Sscottl                                                    dmAllShared->itNexusTimeout,
2491285809Sscottl                                                    0,
2492285809Sscottl                                                    SAS_DEVICE_TYPE,
2493285809Sscottl                                                    oneDeviceData,
2494285809Sscottl                                                    oneExpander,
2495285809Sscottl                                                    pDiscoverResp->phyIdentifier
2496285809Sscottl                                                    );
2497285809Sscottl              }
2498285809Sscottl            }
2499285809Sscottl          }
2500285809Sscottl          DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: newDevice  pDevice=%p\n", AttachedDevice));
2501285809Sscottl          /* If the device is added successfully */
2502285809Sscottl          if ( AttachedDevice != agNULL)
2503285809Sscottl          {
2504285809Sscottl            if ( SA_IDFRM_IS_SSP_TARGET(&sasIdentify)
2505285809Sscottl                 || SA_IDFRM_IS_SMP_TARGET(&sasIdentify)
2506285809Sscottl                 || SA_IDFRM_IS_SSP_INITIATOR(&sasIdentify)
2507285809Sscottl                 || SA_IDFRM_IS_SMP_INITIATOR(&sasIdentify) )
2508285809Sscottl            {
2509285809Sscottl              DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Report a new SAS device !!\n"));
2510285809Sscottl
2511285809Sscottl            }
2512285809Sscottl            else
2513285809Sscottl            {
2514285809Sscottl              if ( SA_IDFRM_IS_STP_TARGET(&sasIdentify) ||
2515285809Sscottl                   SA_IDFRM_IS_SATA_DEVICE(&sasIdentify) )
2516285809Sscottl              {
2517285809Sscottl
2518285809Sscottl                DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found an STP or SATA device.\n"));
2519285809Sscottl              }
2520285809Sscottl              else
2521285809Sscottl              {
2522285809Sscottl                DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found Other type of device.\n"));
2523285809Sscottl              }
2524285809Sscottl            }
2525285809Sscottl
2526285809Sscottl            /* LP2006-05-26 added upstream device to the newly found device */
2527285809Sscottl            AttachedDevice->dmExpander = oneExpander;
2528285809Sscottl            DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: AttachedDevice %p did %d\n", AttachedDevice, AttachedDevice->id));
2529285809Sscottl            DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: Attached oneExpander %p did %d\n",  AttachedDevice->dmExpander,  AttachedDevice->dmExpander->id));
2530285809Sscottl
2531285809Sscottl            DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
2532285809Sscottl            DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: oneExpander %p did %d\n",  oneDeviceData->dmExpander,  oneDeviceData->dmExpander->id));
2533285809Sscottl
2534285809Sscottl            /* If the phy has table routing attribute */
2535285809Sscottl            if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
2536285809Sscottl            {
2537285809Sscottl              /* If the attached device is a fan out expander */
2538285809Sscottl              if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
2539285809Sscottl              {
2540285809Sscottl                /* TODO: discovery error, callback */
2541285809Sscottl                DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error two table routing phys are connected!!!\n"));
2542285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2543285809Sscottl                  = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2544285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2545285809Sscottl                  = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2546285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2547285809Sscottl                DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
2548285809Sscottl                          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
2549285809Sscottl		          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2550285809Sscottl		          onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2551285809Sscottl                /* discovery done */
2552285809Sscottl                dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2553285809Sscottl              }
2554285809Sscottl              else if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
2555285809Sscottl              {
2556285809Sscottl                /* Allocate an expander data structure */
2557285809Sscottl                AttachedExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, AttachedDevice);
2558285809Sscottl
2559285809Sscottl                DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found a EDGE exp device.%p\n", AttachedExpander));
2560285809Sscottl                /* If allocate successfully */
2561285809Sscottl                if ( AttachedExpander != agNULL)
2562285809Sscottl                {
2563285809Sscottl                  /* set up downstream information on configurable expander */
2564285809Sscottl
2565285809Sscottl                  dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId);
2566285809Sscottl
2567285809Sscottl                  /* Setup upstream information */
2568285809Sscottl                  dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
2569285809Sscottl//qqqqq
2570285809Sscottl                  AttachedExpander->hasUpStreamDevice = agTRUE;
2571285809Sscottl                  AttachedExpander->upStreamSASAddressHi
2572285809Sscottl                    = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2573285809Sscottl                  AttachedExpander->upStreamSASAddressLo
2574285809Sscottl                    = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2575285809Sscottl                  AttachedExpander->dmUpStreamExpander = oneExpander;
2576285809Sscottl                  /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */
2577285809Sscottl                  dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
2578285809Sscottl                }
2579285809Sscottl                /* If failed to allocate */
2580285809Sscottl                else
2581285809Sscottl                {
2582285809Sscottl                  DM_DBG1(("dmDownStreamDiscover2ExpanderPhy, Failed to allocate expander data structure!!!\n"));
2583285809Sscottl                  /*  discovery done */
2584285809Sscottl                  dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2585285809Sscottl                }
2586285809Sscottl              }
2587285809Sscottl            }
2588285809Sscottl	    //qqqqq
2589285809Sscottl	    else if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE &&
2590285809Sscottl                       (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE ||
2591285809Sscottl                        SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
2592285809Sscottl	            )
2593285809Sscottl	    {
2594285809Sscottl              /* Allocate an expander data structure */
2595285809Sscottl              AttachedExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, AttachedDevice);
2596285809Sscottl
2597285809Sscottl              DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found a EDGE/FANOUT exp device.%p\n", AttachedExpander));
2598285809Sscottl              /* If allocate successfully */
2599285809Sscottl              if ( AttachedExpander != agNULL)
2600285809Sscottl              {
2601285809Sscottl                /* set up downstream information on configurable expander */
2602285809Sscottl                dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId);
2603285809Sscottl
2604285809Sscottl                /* Setup upstream information */
2605285809Sscottl                dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
2606285809Sscottl                AttachedExpander->hasUpStreamDevice = agTRUE;
2607285809Sscottl                AttachedExpander->upStreamSASAddressHi
2608285809Sscottl                  = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2609285809Sscottl                AttachedExpander->upStreamSASAddressLo
2610285809Sscottl                  = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2611285809Sscottl                AttachedExpander->dmUpStreamExpander = oneExpander;
2612285809Sscottl                /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */
2613285809Sscottl                dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
2614285809Sscottl              }
2615285809Sscottl              /* If failed to allocate */
2616285809Sscottl              else
2617285809Sscottl              {
2618285809Sscottl                DM_DBG1(("dmDownStreamDiscover2ExpanderPhy, Failed to allocate expander data structure (2)!!!\n"));
2619285809Sscottl                /*  discovery done */
2620285809Sscottl                dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2621285809Sscottl              }
2622285809Sscottl
2623285809Sscottl
2624285809Sscottl	    }
2625285809Sscottl            /* If status is still DISCOVERY_DOWN_STREAM */
2626285809Sscottl            if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM &&
2627285809Sscottl	         onePortContext->discovery.ConfiguresOthers == agFALSE)
2628285809Sscottl            {
2629285809Sscottl              DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st before\n"));
2630285809Sscottl              dmDumpAllUpExp(dmRoot, onePortContext, oneExpander);
2631285809Sscottl              UpStreamExpander = oneExpander->dmUpStreamExpander;
2632285809Sscottl              ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
2633285809Sscottl              configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
2634285809Sscottl              configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
2635285809Sscottl              if (ConfigurableExpander)
2636285809Sscottl              {
2637285809Sscottl                if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi
2638285809Sscottl                      == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
2639285809Sscottl                     (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo
2640285809Sscottl                      == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
2641285809Sscottl                   )
2642285809Sscottl                { /* directly attached between oneExpander and ConfigurableExpander */
2643285809Sscottl                  DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st before loc 1\n"));
2644285809Sscottl                  configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi;
2645285809Sscottl                  configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo;
2646285809Sscottl                }
2647285809Sscottl                else
2648285809Sscottl                {
2649285809Sscottl                  DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st before loc 2\n"));
2650285809Sscottl                  configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
2651285809Sscottl                  configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
2652285809Sscottl                }
2653285809Sscottl              } /* if !ConfigurableExpander */
2654285809Sscottl              dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot,
2655285809Sscottl                                                            ConfigurableExpander,
2656285809Sscottl                                                            configSASAddressHi,
2657285809Sscottl                                                            configSASAddressLo
2658285809Sscottl                                                            );
2659285809Sscottl
2660285809Sscottl
2661285809Sscottl              if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
2662285809Sscottl              {
2663285809Sscottl                DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st q123\n"));
2664285809Sscottl                UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
2665285809Sscottl                ConfigurableExpander->currentDownStreamPhyIndex =
2666285809Sscottl                        dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
2667285809Sscottl                ConfigurableExpander->dmReturnginExpander = oneExpander;
2668285809Sscottl                dmRoutingEntryAdd(dmRoot,
2669285809Sscottl                                  ConfigurableExpander,
2670285809Sscottl                                  ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
2671285809Sscottl                                  configSASAddressHi,
2672285809Sscottl                                  configSASAddressLo
2673285809Sscottl                                 );
2674285809Sscottl              }
2675285809Sscottl            }
2676285809Sscottl          }
2677285809Sscottl          /*  If fail to add the device */
2678285809Sscottl          else
2679285809Sscottl          {
2680285809Sscottl            DM_DBG1(("dmDownStreamDiscover2ExpanderPhy, Failed to add a device!!!\n"));
2681285809Sscottl            /*  discovery done */
2682285809Sscottl            dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2683285809Sscottl          }
2684285809Sscottl        }
2685285809Sscottl      }
2686285809Sscottl      /* If the device has been discovered before */
2687285809Sscottl      else /* discovered before */
2688285809Sscottl      {
2689285809Sscottl        /* If the phy has subtractive routing attribute */
2690285809Sscottl        if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
2691285809Sscottl        {
2692285809Sscottl          /* If the expander doesn't have up stream device */
2693285809Sscottl          if ( oneExpander->hasUpStreamDevice == agFALSE)
2694285809Sscottl          {
2695285809Sscottl            /* TODO: discovery error, callback */
2696285809Sscottl            DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error loop, or end device connects to two expanders!!!\n"));
2697285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2698285809Sscottl              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2699285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2700285809Sscottl              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2701285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2702285809Sscottl            DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
2703285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
2704285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2705285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2706285809Sscottl            /* discovery done */
2707285809Sscottl            dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2708285809Sscottl          }
2709285809Sscottl          /* If the expander has up stream device */
2710285809Sscottl          else
2711285809Sscottl          {
2712285809Sscottl
2713285809Sscottl//qqqqq
2714285809Sscottl            /* If sas address doesn't match */
2715285809Sscottl            if ( (oneExpander->upStreamSASAddressHi != attachedSasHi)
2716285809Sscottl                 || (oneExpander->upStreamSASAddressLo != attachedSasLo) )
2717285809Sscottl            {
2718285809Sscottl              /* TODO: discovery error, callback */
2719285809Sscottl              DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** two subtractive phys!!! Allowed in SAS2!!!\n"));
2720285809Sscottl              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2721285809Sscottl                = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2722285809Sscottl              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2723285809Sscottl                = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2724285809Sscottl              onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2725285809Sscottl	      onePortContext->discovery.DeferredError = agTRUE;
2726285809Sscottl
2727285809Sscottl            }
2728285809Sscottl          }
2729285809Sscottl        }
2730285809Sscottl        /* If the phy has table routing attribute */
2731285809Sscottl        else if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
2732285809Sscottl        {
2733285809Sscottl          /* If the attached device is a fan out expander */
2734285809Sscottl          if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
2735285809Sscottl          {
2736285809Sscottl            /* (2.3.3.2.1.1) TODO: discovery error, callback */
2737285809Sscottl            DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error fan out expander to routing table phy!!!\n"));
2738285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2739285809Sscottl              = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2740285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2741285809Sscottl              = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2742285809Sscottl            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2743285809Sscottl            DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
2744285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
2745285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2746285809Sscottl                      onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2747285809Sscottl            /* discovery done */
2748285809Sscottl            dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2749285809Sscottl          }
2750285809Sscottl          /* If the attached device is an edge expander */
2751285809Sscottl          else if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
2752285809Sscottl          {
2753285809Sscottl            /* Setup up stream inform */
2754285809Sscottl            AttachedExpander = AttachedDevice->dmExpander;
2755285809Sscottl            DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found edge expander=%p\n", AttachedExpander));
2756285809Sscottl            //hhhhhh
2757285809Sscottl            /* If the attached expander has up stream device */
2758285809Sscottl            if ( AttachedExpander->hasUpStreamDevice == agTRUE)
2759285809Sscottl            {
2760285809Sscottl              /* compare the sas address */
2761285809Sscottl              if ( (AttachedExpander->upStreamSASAddressHi
2762285809Sscottl                    != DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
2763285809Sscottl                   || (AttachedExpander->upStreamSASAddressLo
2764285809Sscottl                       != DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)))
2765285809Sscottl              {
2766285809Sscottl	        if (AttachedExpander->TTTSupported && oneExpander->TTTSupported)
2767285809Sscottl		{
2768285809Sscottl                  /*
2769285809Sscottl		     needs further error checking
2770285809Sscottl		     UpstreamExpanderOfAttachedExpander = AttachedExpander->UpStreamExpander
2771285809Sscottl		     for (i=0;i<DM_MAX_EXPANDER_PHYS;i++)
2772285809Sscottl		     {
2773285809Sscottl		       if (UpstreamExpanderOfAttachedExpander->downStreamPhys[i] != 0 &&
2774285809Sscottl		     }
2775285809Sscottl		  */
2776285809Sscottl		  SAS2SAS11Check = dmSAS2SAS11ErrorCheck(dmRoot, onePortContext, AttachedExpander->dmUpStreamExpander, AttachedExpander, oneExpander);
2777285809Sscottl		  if (SAS2SAS11Check == agTRUE)
2778285809Sscottl		  {
2779285809Sscottl
2780285809Sscottl		    DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error SAS2 and SAS1.1!!!\n"));
2781285809Sscottl		    onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2782285809Sscottl                      = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2783285809Sscottl		    onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2784285809Sscottl                      = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2785285809Sscottl		    onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2786285809Sscottl		    DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
2787285809Sscottl                              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
2788285809Sscottl                              onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2789285809Sscottl                              onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2790285809Sscottl		    /* discovery done */
2791285809Sscottl		    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2792285809Sscottl		  }
2793285809Sscottl		  else
2794285809Sscottl		  {
2795285809Sscottl		    DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: Allowed Table to Table (1)\n"));
2796285809Sscottl		    /* move on to the next phys but should be not proceed after oneExpander */
2797285809Sscottl		    oneExpander->UndoDueToTTTSupported = agTRUE;
2798285809Sscottl		    onePortContext->discovery.DeferredError = agFALSE;
2799285809Sscottl		  }
2800285809Sscottl		}
2801285809Sscottl		else
2802285809Sscottl		{
2803285809Sscottl                  /* TODO: discovery error, callback */
2804285809Sscottl                  DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error two table routing phys connected (1)!!!\n"));
2805285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2806285809Sscottl                    = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2807285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2808285809Sscottl                    = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2809285809Sscottl                  onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2810285809Sscottl                  DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
2811285809Sscottl                            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
2812285809Sscottl                            onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2813285809Sscottl                            onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2814285809Sscottl                  /* discovery done */
2815285809Sscottl                  dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2816285809Sscottl		}
2817285809Sscottl              }
2818285809Sscottl              else
2819285809Sscottl              {
2820285809Sscottl                DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Add edge expander=%p\n", AttachedExpander));
2821285809Sscottl                /* set up downstream information on configurable expander */
2822285809Sscottl
2823285809Sscottl                dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId);
2824285809Sscottl                /* haha */
2825285809Sscottl                dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
2826285809Sscottl                /* Add the pAttachedExpander to discovering list */
2827285809Sscottl                dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander);
2828285809Sscottl              }
2829285809Sscottl            }
2830285809Sscottl            /* If the attached expander doesn't have up stream device */
2831285809Sscottl            else
2832285809Sscottl            {
2833285809Sscottl	      if (AttachedExpander->TTTSupported && oneExpander->TTTSupported)
2834285809Sscottl              {
2835285809Sscottl                DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: Allowed Table to Table (2)\n"));
2836285809Sscottl		/* move on to the next phys but should be not proceed after oneExpander */
2837285809Sscottl                oneExpander->UndoDueToTTTSupported = agTRUE;
2838285809Sscottl		onePortContext->discovery.DeferredError = agFALSE;
2839285809Sscottl              }
2840285809Sscottl              else
2841285809Sscottl              {
2842285809Sscottl                /* TODO: discovery error, callback */
2843285809Sscottl                DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error two table routing phys connected (2)!!!\n"));
2844285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
2845285809Sscottl                  = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
2846285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
2847285809Sscottl                  = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
2848285809Sscottl                onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
2849285809Sscottl                DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n",
2850285809Sscottl                          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi,
2851285809Sscottl                          onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo,
2852285809Sscottl                          onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier));
2853285809Sscottl                /* discovery done */
2854285809Sscottl                dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2855285809Sscottl	      }
2856285809Sscottl            }
2857285809Sscottl          }
2858285809Sscottl        } /* for else if (SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE) */
2859285809Sscottl
2860285809Sscottl        /* do this regradless of sub or table */
2861285809Sscottl        /* If status is still DISCOVERY_DOWN_STREAM */
2862285809Sscottl        if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM &&
2863285809Sscottl             onePortContext->discovery.ConfiguresOthers == agFALSE)
2864285809Sscottl        {
2865285809Sscottl          DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd before\n"));
2866285809Sscottl          dmDumpAllUpExp(dmRoot, onePortContext, oneExpander);
2867285809Sscottl
2868285809Sscottl          UpStreamExpander = oneExpander->dmUpStreamExpander;
2869285809Sscottl          ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
2870285809Sscottl          configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
2871285809Sscottl          configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
2872285809Sscottl          if (ConfigurableExpander)
2873285809Sscottl          {
2874285809Sscottl            if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi
2875285809Sscottl                 == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
2876285809Sscottl                 (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo
2877285809Sscottl                   == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
2878285809Sscottl               )
2879285809Sscottl            { /* directly attached between oneExpander and ConfigurableExpander */
2880285809Sscottl              DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd before loc 1\n"));
2881285809Sscottl              configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi;
2882285809Sscottl              configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo;
2883285809Sscottl            }
2884285809Sscottl            else
2885285809Sscottl            {
2886285809Sscottl              DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd before loc 2\n"));
2887285809Sscottl              configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
2888285809Sscottl              configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
2889285809Sscottl            }
2890285809Sscottl          } /* if !ConfigurableExpander */
2891285809Sscottl          dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot,
2892285809Sscottl                                                        ConfigurableExpander,
2893285809Sscottl                                                        configSASAddressHi,
2894285809Sscottl                                                        configSASAddressLo
2895285809Sscottl                                                        );
2896285809Sscottl
2897285809Sscottl          if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
2898285809Sscottl          {
2899285809Sscottl            DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd q123 \n"));
2900285809Sscottl            UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
2901285809Sscottl            ConfigurableExpander->currentDownStreamPhyIndex =
2902285809Sscottl                        dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
2903285809Sscottl            ConfigurableExpander->dmReturnginExpander = oneExpander;
2904285809Sscottl            dmRoutingEntryAdd(dmRoot,
2905285809Sscottl                              ConfigurableExpander,
2906285809Sscottl                              ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
2907285809Sscottl                              configSASAddressHi,
2908285809Sscottl                              configSASAddressLo
2909285809Sscottl                             );
2910285809Sscottl          }
2911285809Sscottl        } /* if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) */
2912285809Sscottl        /* incremental discovery */
2913285809Sscottl        if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START)
2914285809Sscottl        {
2915285809Sscottl          connectionRate = MIN(onePortContext->LinkRate, SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pDiscoverResp));
2916285809Sscottl
2917285809Sscottl          if (SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
2918285809Sscottl          {
2919285809Sscottl            DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: incremental SATA_STP\n"));
2920285809Sscottl
2921285809Sscottl            dmPortSASDeviceAdd(
2922285809Sscottl                              dmRoot,
2923285809Sscottl                              onePortContext,
2924285809Sscottl                              sasIdentify,
2925285809Sscottl                              agFALSE,
2926285809Sscottl                              connectionRate,
2927285809Sscottl                              dmAllShared->itNexusTimeout,
2928285809Sscottl                              0,
2929285809Sscottl                              STP_DEVICE_TYPE,
2930285809Sscottl                              oneDeviceData,
2931285809Sscottl                              oneExpander,
2932285809Sscottl                              pDiscoverResp->phyIdentifier
2933285809Sscottl                              );
2934285809Sscottl          }
2935285809Sscottl          else
2936285809Sscottl          {
2937285809Sscottl            DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: incremental SAS\n"));
2938285809Sscottl
2939285809Sscottl             dmPortSASDeviceAdd(
2940285809Sscottl                               dmRoot,
2941285809Sscottl                               onePortContext,
2942285809Sscottl                               sasIdentify,
2943285809Sscottl                               agFALSE,
2944285809Sscottl                               connectionRate,
2945285809Sscottl                               dmAllShared->itNexusTimeout,
2946285809Sscottl                               0,
2947285809Sscottl                               SAS_DEVICE_TYPE,
2948285809Sscottl                               oneDeviceData,
2949285809Sscottl                               oneExpander,
2950285809Sscottl                               pDiscoverResp->phyIdentifier
2951285809Sscottl                               );
2952285809Sscottl
2953285809Sscottl          }
2954285809Sscottl        }
2955285809Sscottl
2956285809Sscottl
2957285809Sscottl      }/* else; existing devce */
2958285809Sscottl    } /* not attached to myself */
2959285809Sscottl    /* If the attached device is myself */
2960285809Sscottl    else
2961285809Sscottl    {
2962285809Sscottl      DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found Self\n"));
2963285809Sscottl      DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 3rd before\n"));
2964285809Sscottl      dmDumpAllUpExp(dmRoot, onePortContext, oneExpander);
2965285809Sscottl
2966285809Sscottl      if (onePortContext->discovery.ConfiguresOthers == agFALSE)
2967285809Sscottl      {
2968285809Sscottl        UpStreamExpander = oneExpander->dmUpStreamExpander;
2969285809Sscottl        ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
2970285809Sscottl        dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot,
2971285809Sscottl                                                      ConfigurableExpander,
2972285809Sscottl                                                      onePortContext->sasLocalAddressHi,
2973285809Sscottl                                                      onePortContext->sasLocalAddressLo
2974285809Sscottl                                                      );
2975285809Sscottl
2976285809Sscottl        if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
2977285809Sscottl        {
2978285809Sscottl          DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 3rd q123 Setup routing table\n"));
2979285809Sscottl          UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
2980285809Sscottl          ConfigurableExpander->currentDownStreamPhyIndex =
2981285809Sscottl                          dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
2982285809Sscottl          ConfigurableExpander->dmReturnginExpander = oneExpander;
2983285809Sscottl          dmRoutingEntryAdd(dmRoot,
2984285809Sscottl                            ConfigurableExpander,
2985285809Sscottl                            ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
2986285809Sscottl                            onePortContext->sasLocalAddressHi,
2987285809Sscottl                            onePortContext->sasLocalAddressLo
2988285809Sscottl                           );
2989285809Sscottl        }
2990285809Sscottl      }
2991285809Sscottl    }
2992285809Sscottl  }
2993285809Sscottl  /* If no device is attached */
2994285809Sscottl  else
2995285809Sscottl  {
2996285809Sscottl  }
2997285809Sscottl
2998285809Sscottl
2999285809Sscottl  /* Increment the discovering phy id */
3000285809Sscottl  oneExpander->discoveringPhyId ++;
3001285809Sscottl
3002285809Sscottl  /* If the discovery status is DISCOVERY_DOWN_STREAM */
3003285809Sscottl  if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
3004285809Sscottl  {
3005285809Sscottl    /* If not the last phy */
3006285809Sscottl    if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
3007285809Sscottl    {
3008285809Sscottl      DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: More Phys to discover\n"));
3009285809Sscottl      /* continue discovery for the next phy */
3010285809Sscottl      dmDiscoverSend(dmRoot, oneDeviceData);
3011285809Sscottl    }
3012285809Sscottl    /* If the last phy */
3013285809Sscottl    else
3014285809Sscottl    {
3015285809Sscottl      DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: No More Phys\n"));
3016285809Sscottl
3017285809Sscottl      /* for MCN */
3018285809Sscottl      dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
3019285809Sscottl      ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
3020285809Sscottl      if (oneExpander->UndoDueToTTTSupported == agTRUE && ConfigurableExpander != agNULL)
3021285809Sscottl//      if (oneExpander->UndoDueToTTTSupported == agTRUE)
3022285809Sscottl      {
3023285809Sscottl        DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Not sure!!!\n"));
3024285809Sscottl        dmDiscoveringUndoAdd(dmRoot, onePortContext, oneExpander);
3025285809Sscottl        oneExpander->UndoDueToTTTSupported = agFALSE;
3026285809Sscottl      }
3027285809Sscottl
3028285809Sscottl      /* remove the expander from the discovering list */
3029285809Sscottl      dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3030285809Sscottl      /* continue downstream discovering */
3031285809Sscottl      dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3032285809Sscottl    }
3033285809Sscottl  }
3034285809Sscottl  else
3035285809Sscottl  {
3036285809Sscottl    DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));
3037285809Sscottl  }
3038285809Sscottl  DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
3039285809Sscottl
3040285809Sscottl  return;
3041285809Sscottl}
3042285809Sscottl
3043285809Sscottl
3044285809SscottlosGLOBAL void
3045285809SscottldmDiscoveringUndoAdd(
3046285809Sscottl                     dmRoot_t                 *dmRoot,
3047285809Sscottl                     dmIntPortContext_t       *onePortContext,
3048285809Sscottl                     dmExpander_t             *oneExpander
3049285809Sscottl                    )
3050285809Sscottl{
3051285809Sscottl  dmIntRoot_t        *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3052285809Sscottl  dmIntContext_t     *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3053285809Sscottl  dmList_t           *ExpanderList;
3054285809Sscottl  dmExpander_t       *tempExpander;
3055285809Sscottl  dmIntPortContext_t *tmpOnePortContext = onePortContext;
3056285809Sscottl
3057285809Sscottl  DM_DBG2(("dmDiscoveringUndoAdd: start\n"));
3058285809Sscottl  if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
3059285809Sscottl  {
3060285809Sscottl    DM_DBG2(("dmDiscoveringUndoAdd: empty discoveringExpanderList\n"));
3061285809Sscottl    return;
3062285809Sscottl  }
3063285809Sscottl
3064285809Sscottl//  DM_DBG2(("dmDiscoveringUndoAdd: before\n"));
3065285809Sscottl//  dmDumpAllExp(dmRoot, onePortContext, oneExpander);
3066285809Sscottl
3067285809Sscottl  ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
3068285809Sscottl  while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
3069285809Sscottl  {
3070285809Sscottl    tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
3071285809Sscottl    if ( tempExpander == agNULL)
3072285809Sscottl    {
3073285809Sscottl      DM_DBG1(("dmDiscoveringUndoAdd: tempExpander is NULL!!!\n"));
3074285809Sscottl      return;
3075285809Sscottl    }
3076285809Sscottl    if (tempExpander->dmUpStreamExpander == oneExpander)
3077285809Sscottl    {
3078285809Sscottl      DM_DBG2(("dmDiscoveringUndoAdd: match!!! expander id %d\n", tempExpander->id));
3079285809Sscottl      DM_DBG2(("dmDiscoveringUndoAdd: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
3080285809Sscottl      DM_DBG2(("dmDiscoveringUndoAdd: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
3081285809Sscottl      tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
3082285809Sscottl      DMLIST_DEQUEUE_THIS(&(tempExpander->linkNode));
3083285809Sscottl//      DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->freeExpanderList));
3084285809Sscottl      DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->mainExpanderList));
3085285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
3086285809Sscottl      ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
3087285809Sscottl    }
3088285809Sscottl    if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
3089285809Sscottl    {
3090285809Sscottl      DM_DBG2(("dmDiscoveringUndoAdd: hitting break\n"));
3091285809Sscottl      break;
3092285809Sscottl    }
3093285809Sscottl    ExpanderList = ExpanderList->flink;
3094285809Sscottl  }
3095285809Sscottl
3096285809Sscottl//  DM_DBG2(("dmDiscoveringUndoAdd: after\n"));
3097285809Sscottl//  dmDumpAllExp(dmRoot, onePortContext, oneExpander);
3098285809Sscottl  return;
3099285809Sscottl}
3100285809Sscottl
3101285809SscottlosGLOBAL void
3102285809SscottldmHandleZoneViolation(
3103285809Sscottl                      dmRoot_t              *dmRoot,
3104285809Sscottl                      agsaRoot_t            *agRoot,
3105285809Sscottl                      agsaIORequest_t       *agIORequest,
3106285809Sscottl                      dmDeviceData_t        *oneDeviceData,
3107285809Sscottl                      dmSMPFrameHeader_t    *frameHeader,
3108285809Sscottl                      agsaFrameHandle_t     frameHandle
3109285809Sscottl                     )
3110285809Sscottl{
3111285809Sscottl  dmIntPortContext_t           *onePortContext = agNULL;
3112285809Sscottl  dmExpander_t                 *oneExpander = agNULL;
3113285809Sscottl
3114285809Sscottl  DM_DBG1(("dmHandleZoneViolation: start\n"));
3115285809Sscottl  DM_DBG1(("dmHandleZoneViolation: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3116285809Sscottl  DM_DBG1(("dmHandleZoneViolation: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3117285809Sscottl  onePortContext = oneDeviceData->dmPortContext;
3118285809Sscottl  oneExpander = oneDeviceData->dmExpander;
3119285809Sscottl  if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
3120285809Sscottl  {
3121285809Sscottl    DM_DBG1(("dmHandleZoneViolation: invalid port or aborted discovery!!!\n"));
3122285809Sscottl    return;
3123285809Sscottl  }
3124285809Sscottl  /* for MCN */
3125285809Sscottl  dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
3126285809Sscottl  /* remove the expander from the discovering list */
3127285809Sscottl  dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3128285809Sscottl  if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3129285809Sscottl  {
3130285809Sscottl    /* continue upstream discovering */
3131285809Sscottl    dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3132285809Sscottl  }
3133285809Sscottl  else /* DISCOVERY_DOWN_STREAM or DISCOVERY_CONFIG_ROUTING */
3134285809Sscottl  {
3135285809Sscottl    /* continue downstream discovering */
3136285809Sscottl    dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3137285809Sscottl  }
3138285809Sscottl  return;
3139285809Sscottl}
3140285809Sscottl
3141285809Sscottl
3142285809SscottlosGLOBAL void
3143285809SscottldmUpStreamDiscoverExpanderPhySkip(
3144285809Sscottl                                   dmRoot_t              *dmRoot,
3145285809Sscottl                                   dmIntPortContext_t    *onePortContext,
3146285809Sscottl                                   dmExpander_t          *oneExpander
3147285809Sscottl                                   )
3148285809Sscottl
3149285809Sscottl{
3150285809Sscottl  dmDeviceData_t          *oneDeviceData;
3151285809Sscottl  DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: start\n"));
3152285809Sscottl
3153285809Sscottl  oneDeviceData = oneExpander->dmDevice;
3154285809Sscottl  DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3155285809Sscottl  DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3156285809Sscottl
3157285809Sscottl  oneExpander->discoveringPhyId++;
3158285809Sscottl  if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3159285809Sscottl  {
3160285809Sscottl    if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
3161285809Sscottl    {
3162285809Sscottl      DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: More Phys to discover\n"));
3163285809Sscottl      /* continue discovery for the next phy */
3164285809Sscottl      dmDiscoverSend(dmRoot, oneDeviceData);
3165285809Sscottl    }
3166285809Sscottl    else
3167285809Sscottl    {
3168285809Sscottl      DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: No More Phys\n"));
3169285809Sscottl
3170285809Sscottl      /* for MCN */
3171285809Sscottl      dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
3172285809Sscottl      /* remove the expander from the discovering list */
3173285809Sscottl      dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3174285809Sscottl      /* continue upstream discovering */
3175285809Sscottl      dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3176285809Sscottl    }
3177285809Sscottl  }
3178285809Sscottl  else
3179285809Sscottl  {
3180285809Sscottl    DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));
3181285809Sscottl
3182285809Sscottl  }
3183285809Sscottl
3184285809Sscottl  DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
3185285809Sscottl
3186285809Sscottl  return;
3187285809Sscottl}
3188285809Sscottl
3189285809Sscottl
3190285809SscottlosGLOBAL void
3191285809SscottldmUpStreamDiscover2ExpanderPhySkip(
3192285809Sscottl                                   dmRoot_t              *dmRoot,
3193285809Sscottl                                   dmIntPortContext_t    *onePortContext,
3194285809Sscottl                                   dmExpander_t          *oneExpander
3195285809Sscottl                                   )
3196285809Sscottl{
3197285809Sscottl  dmDeviceData_t          *oneDeviceData;
3198285809Sscottl
3199285809Sscottl  DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: start\n"));
3200285809Sscottl  oneDeviceData = oneExpander->dmDevice;
3201285809Sscottl
3202285809Sscottl  oneExpander->discoveringPhyId++;
3203285809Sscottl  if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3204285809Sscottl  {
3205285809Sscottl    if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
3206285809Sscottl    {
3207285809Sscottl      DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: DISCOVERY_UP_STREAM find more ...\n"));
3208285809Sscottl      /* continue discovery for the next phy */
3209285809Sscottl      dmDiscoverSend(dmRoot, oneDeviceData);
3210285809Sscottl    }
3211285809Sscottl    else
3212285809Sscottl    {
3213285809Sscottl      DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: DISCOVERY_UP_STREAM last phy continue upstream..\n"));
3214285809Sscottl
3215285809Sscottl      /* for MCN */
3216285809Sscottl      dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
3217285809Sscottl      /* remove the expander from the discovering list */
3218285809Sscottl      dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3219285809Sscottl      /* continue upstream discovering */
3220285809Sscottl      dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3221285809Sscottl    }
3222285809Sscottl  }
3223285809Sscottl  else
3224285809Sscottl  {
3225285809Sscottl    DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));
3226285809Sscottl  }
3227285809Sscottl
3228285809Sscottl  DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
3229285809Sscottl
3230285809Sscottl
3231285809Sscottl  return;
3232285809Sscottl}
3233285809Sscottl
3234285809SscottlosGLOBAL void
3235285809SscottldmDownStreamDiscoverExpanderPhySkip(
3236285809Sscottl                                     dmRoot_t              *dmRoot,
3237285809Sscottl                                     dmIntPortContext_t    *onePortContext,
3238285809Sscottl                                     dmExpander_t          *oneExpander
3239285809Sscottl                                     )
3240285809Sscottl{
3241285809Sscottl  dmDeviceData_t          *oneDeviceData;
3242285809Sscottl  DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: start\n"));
3243285809Sscottl
3244285809Sscottl  oneDeviceData = oneExpander->dmDevice;
3245285809Sscottl  DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3246285809Sscottl  DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3247285809Sscottl
3248285809Sscottl  /* Increment the discovering phy id */
3249285809Sscottl  oneExpander->discoveringPhyId ++;
3250285809Sscottl
3251285809Sscottl  /* If the discovery status is DISCOVERY_DOWN_STREAM */
3252285809Sscottl  if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
3253285809Sscottl  {
3254285809Sscottl    /* If not the last phy */
3255285809Sscottl    if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
3256285809Sscottl    {
3257285809Sscottl      DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: More Phys to discover\n"));
3258285809Sscottl      /* continue discovery for the next phy */
3259285809Sscottl      dmDiscoverSend(dmRoot, oneDeviceData);
3260285809Sscottl    }
3261285809Sscottl    /* If the last phy */
3262285809Sscottl    else
3263285809Sscottl    {
3264285809Sscottl      DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: No More Phys\n"));
3265285809Sscottl
3266285809Sscottl      /* for MCN */
3267285809Sscottl      dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
3268285809Sscottl      /* remove the expander from the discovering list */
3269285809Sscottl      dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3270285809Sscottl      /* continue downstream discovering */
3271285809Sscottl      dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3272285809Sscottl    }
3273285809Sscottl  }
3274285809Sscottl  else
3275285809Sscottl  {
3276285809Sscottl    DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));
3277285809Sscottl  }
3278285809Sscottl  DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
3279285809Sscottl
3280285809Sscottl
3281285809Sscottl  return;
3282285809Sscottl}
3283285809Sscottl
3284285809SscottlosGLOBAL void
3285285809SscottldmDownStreamDiscover2ExpanderPhySkip(
3286285809Sscottl                                     dmRoot_t              *dmRoot,
3287285809Sscottl                                     dmIntPortContext_t    *onePortContext,
3288285809Sscottl                                     dmExpander_t          *oneExpander
3289285809Sscottl                                     )
3290285809Sscottl{
3291285809Sscottl  dmDeviceData_t          *oneDeviceData;
3292285809Sscottl
3293285809Sscottl  DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: start\n"));
3294285809Sscottl
3295285809Sscottl  oneDeviceData = oneExpander->dmDevice;
3296285809Sscottl  /* Increment the discovering phy id */
3297285809Sscottl  oneExpander->discoveringPhyId ++;
3298285809Sscottl
3299285809Sscottl  /* If the discovery status is DISCOVERY_DOWN_STREAM */
3300285809Sscottl  if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
3301285809Sscottl  {
3302285809Sscottl    /* If not the last phy */
3303285809Sscottl    if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
3304285809Sscottl    {
3305285809Sscottl      DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: More Phys to discover\n"));
3306285809Sscottl      /* continue discovery for the next phy */
3307285809Sscottl      dmDiscoverSend(dmRoot, oneDeviceData);
3308285809Sscottl    }
3309285809Sscottl    /* If the last phy */
3310285809Sscottl    else
3311285809Sscottl    {
3312285809Sscottl      DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: No More Phys\n"));
3313285809Sscottl
3314285809Sscottl      /* for MCN */
3315285809Sscottl      dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData);
3316285809Sscottl      /* remove the expander from the discovering list */
3317285809Sscottl      dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander);
3318285809Sscottl      /* continue downstream discovering */
3319285809Sscottl      dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData);
3320285809Sscottl    }
3321285809Sscottl  }
3322285809Sscottl  else
3323285809Sscottl  {
3324285809Sscottl    DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));
3325285809Sscottl  }
3326285809Sscottl  DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
3327285809Sscottl  return;
3328285809Sscottl}
3329285809Sscottl
3330285809SscottlosGLOBAL void
3331285809SscottldmExpanderUpStreamPhyAdd(
3332285809Sscottl                         dmRoot_t              *dmRoot,
3333285809Sscottl                         dmExpander_t          *oneExpander,
3334285809Sscottl                         bit8                  phyId
3335285809Sscottl                         )
3336285809Sscottl{
3337285809Sscottl  bit32   i;
3338285809Sscottl  bit32   hasSet = agFALSE;
3339285809Sscottl
3340285809Sscottl  DM_DBG3(("dmExpanderUpStreamPhyAdd: start, phyid %d\n", phyId));
3341285809Sscottl  DM_DBG3(("dmExpanderUpStreamPhyAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
3342285809Sscottl  DM_DBG3(("dmExpanderUpStreamPhyAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
3343285809Sscottl  DM_DBG3(("dmExpanderUpStreamPhyAdd: phyid %d  numOfUpStreamPhys %d\n", phyId, oneExpander->numOfUpStreamPhys));
3344285809Sscottl
3345285809Sscottl  for ( i = 0; i < oneExpander->numOfUpStreamPhys; i ++ )
3346285809Sscottl  {
3347285809Sscottl    if ( oneExpander->upStreamPhys[i] == phyId )
3348285809Sscottl    {
3349285809Sscottl      hasSet = agTRUE;
3350285809Sscottl      break;
3351285809Sscottl    }
3352285809Sscottl  }
3353285809Sscottl
3354285809Sscottl  if ( hasSet == agFALSE )
3355285809Sscottl  {
3356285809Sscottl    oneExpander->upStreamPhys[oneExpander->numOfUpStreamPhys ++] = phyId;
3357285809Sscottl  }
3358285809Sscottl
3359285809Sscottl  DM_DBG3(("dmExpanderUpStreamPhyAdd: AFTER phyid %d  numOfUpStreamPhys %d\n", phyId, oneExpander->numOfUpStreamPhys));
3360285809Sscottl
3361285809Sscottl  /* for debugging */
3362285809Sscottl  for ( i = 0; i < oneExpander->numOfUpStreamPhys; i ++ )
3363285809Sscottl  {
3364285809Sscottl    DM_DBG3(("dmExpanderUpStreamPhyAdd: index %d upstream[index] %d\n", i, oneExpander->upStreamPhys[i]));
3365285809Sscottl  }
3366285809Sscottl  return;
3367285809Sscottl}
3368285809Sscottl
3369285809SscottlosGLOBAL void
3370285809SscottldmExpanderDownStreamPhyAdd(
3371285809Sscottl                           dmRoot_t              *dmRoot,
3372285809Sscottl                           dmExpander_t          *oneExpander,
3373285809Sscottl                           bit8                  phyId
3374285809Sscottl                          )
3375285809Sscottl{
3376285809Sscottl  bit32   i;
3377285809Sscottl  bit32   hasSet = agFALSE;
3378285809Sscottl
3379285809Sscottl  DM_DBG3(("dmExpanderDownStreamPhyAdd: start, phyid %d\n", phyId));
3380285809Sscottl  DM_DBG3(("dmExpanderDownStreamPhyAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
3381285809Sscottl  DM_DBG3(("dmExpanderDownStreamPhyAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
3382285809Sscottl  DM_DBG3(("dmExpanderDownStreamPhyAdd: phyid %d  numOfDownStreamPhys %d\n", phyId, oneExpander->numOfDownStreamPhys));
3383285809Sscottl
3384285809Sscottl  for ( i = 0; i < oneExpander->numOfDownStreamPhys; i ++ )
3385285809Sscottl  {
3386285809Sscottl    if ( oneExpander->downStreamPhys[i] == phyId )
3387285809Sscottl    {
3388285809Sscottl      hasSet = agTRUE;
3389285809Sscottl      break;
3390285809Sscottl    }
3391285809Sscottl  }
3392285809Sscottl
3393285809Sscottl  if ( hasSet == agFALSE )
3394285809Sscottl  {
3395285809Sscottl    oneExpander->downStreamPhys[oneExpander->numOfDownStreamPhys ++] = phyId;
3396285809Sscottl  }
3397285809Sscottl
3398285809Sscottl  DM_DBG3(("dmExpanderDownStreamPhyAdd: AFTER phyid %d  numOfDownStreamPhys %d\n", phyId, oneExpander->numOfDownStreamPhys));
3399285809Sscottl
3400285809Sscottl  /* for debugging */
3401285809Sscottl  for ( i = 0; i < oneExpander->numOfDownStreamPhys; i ++ )
3402285809Sscottl  {
3403285809Sscottl     DM_DBG3(("dmExpanderDownStreamPhyAdd: index %d downstream[index] %d\n", i, oneExpander->downStreamPhys[i]));
3404285809Sscottl  }
3405285809Sscottl  return;
3406285809Sscottl}
3407285809Sscottl
3408285809SscottlosGLOBAL void
3409285809SscottldmDiscoveryReportMCN(
3410285809Sscottl                    dmRoot_t                 *dmRoot,
3411285809Sscottl                    dmIntPortContext_t       *onePortContext
3412285809Sscottl                   )
3413285809Sscottl{
3414285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3415285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3416285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
3417285809Sscottl  dmList_t          *DeviceListList;
3418285809Sscottl  bit16             extension = 0;
3419285809Sscottl  dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
3420285809Sscottl
3421285809Sscottl  DM_DBG2(("dmDiscoveryReportMCN: start\n"));
3422285809Sscottl
3423285809Sscottl/*
3424285809Sscottl  if full disocvery, report all devices using MCN
3425285809Sscottl  if incremental discovery,
3426285809Sscottl  1. compare MCN and PrevMCN
3427285809Sscottl  2. report the changed ones; report MCN
3428285809Sscottl  3. set PrevMCN to MCN
3429285809Sscottl     PrevMCN = MCN
3430285809Sscottl*/
3431285809Sscottl
3432285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
3433285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
3434285809Sscottl  {
3435285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3436285809Sscottl    if ( oneDeviceData == agNULL)
3437285809Sscottl    {
3438285809Sscottl      DM_DBG1(("dmDiscoveryReportMCN: oneDeviceData is NULL!!!\n"));
3439285809Sscottl      return;
3440285809Sscottl    }
3441285809Sscottl    DM_DBG3(("dmDiscoveryReportMCN: loop did %d\n", oneDeviceData->id));
3442285809Sscottl    if (oneDeviceData->dmPortContext == onePortContext)
3443285809Sscottl    {
3444285809Sscottl      DM_DBG2(("dmDiscoveryReportMCN: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
3445285809Sscottl      oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
3446285809Sscottl      DM_DBG2(("dmDiscoveryReportMCN: MCN 0x%08x PrevMCN 0x%08x\n", oneDeviceData->MCN, oneDeviceData->PrevMCN));
3447285809Sscottl
3448285809Sscottl      if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
3449285809Sscottl      {
3450285809Sscottl        DM_DBG2(("dmDiscoveryReportMCN: FULL_START\n"));
3451285809Sscottl      }
3452285809Sscottl      else
3453285809Sscottl      {
3454285809Sscottl        DM_DBG2(("dmDiscoveryReportMCN: INCREMENTAL_START\n"));
3455285809Sscottl      }
3456285809Sscottl      /*
3457285809Sscottl        if MCN is 0, the device is removed
3458285809Sscottl      */
3459285809Sscottl      if (oneDeviceData->MCN != oneDeviceData->PrevMCN && oneDeviceData->MCN != 0)
3460285809Sscottl      {
3461285809Sscottl        DM_DBG2(("dmDiscoveryReportMCN: reporting \n"));
3462285809Sscottl        extension = oneDeviceData->dmDeviceInfo.ext;
3463285809Sscottl        /* zero out MCN in extension */
3464285809Sscottl        extension = extension & 0x7FF;
3465285809Sscottl        /* sets MCN in extension */
3466285809Sscottl        extension = extension | (oneDeviceData->MCN << 11);
3467285809Sscottl        DEVINFO_PUT_EXT(&(oneDeviceData->dmDeviceInfo), extension);
3468285809Sscottl        DM_DBG5(("dmDiscoveryReportMCN: MCN 0x%08x PrevMCN 0x%08x\n", DEVINFO_GET_EXT_MCN(&(oneDeviceData->dmDeviceInfo)), oneDeviceData->PrevMCN));
3469285809Sscottl        if (oneDeviceData->ExpDevice != agNULL)
3470285809Sscottl        {
3471285809Sscottl          DM_DBG2(("dmDiscoveryReportMCN: attached expander case\n"));
3472285809Sscottl          oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
3473285809Sscottl          tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, dmDeviceMCNChange);
3474285809Sscottl        }
3475285809Sscottl	else
3476285809Sscottl	{
3477285809Sscottl          DM_DBG2(("dmDiscoveryReportMCN: No attached expander case\n"));
3478285809Sscottl          tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, dmDeviceMCNChange);
3479285809Sscottl	}
3480285809Sscottl        oneDeviceData->PrevMCN = oneDeviceData->MCN;
3481285809Sscottl      }
3482285809Sscottl      else
3483285809Sscottl      {
3484285809Sscottl        DM_DBG2(("dmDiscoveryReportMCN: No change; no reporting \n"));
3485285809Sscottl	if (oneDeviceData->MCN == 0)
3486285809Sscottl	{
3487285809Sscottl          oneDeviceData->PrevMCN = oneDeviceData->MCN;
3488285809Sscottl	}
3489285809Sscottl      }
3490285809Sscottl
3491285809Sscottl    }
3492285809Sscottl    DeviceListList = DeviceListList->flink;
3493285809Sscottl  }
3494285809Sscottl
3495285809Sscottl  return;
3496285809Sscottl}
3497285809Sscottl
3498285809SscottlosGLOBAL void
3499285809SscottldmDiscoveryDumpMCN(
3500285809Sscottl                    dmRoot_t                 *dmRoot,
3501285809Sscottl                    dmIntPortContext_t       *onePortContext
3502285809Sscottl                   )
3503285809Sscottl{
3504285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3505285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3506285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
3507285809Sscottl  dmList_t          *DeviceListList;
3508285809Sscottl
3509285809Sscottl  DM_DBG3(("dmDiscoveryDumpMCN: start\n"));
3510285809Sscottl
3511285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
3512285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
3513285809Sscottl  {
3514285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3515285809Sscottl    if (oneDeviceData == agNULL)
3516285809Sscottl    {
3517285809Sscottl      DM_DBG1(("dmDiscoveryDumpMCN: oneDeviceData is NULL!!!\n"));
3518285809Sscottl      return;
3519285809Sscottl    }
3520285809Sscottl    DM_DBG3(("dmDiscoveryDumpMCN: loop did %d\n", oneDeviceData->id));
3521285809Sscottl    if (oneDeviceData->dmPortContext == onePortContext)
3522285809Sscottl    {
3523285809Sscottl      DM_DBG3(("dmDiscoveryDumpMCN: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
3524285809Sscottl      oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
3525285809Sscottl      DM_DBG3(("dmDiscoveryDumpMCN: MCN 0x%08x PrevMCN 0x%08x\n", oneDeviceData->MCN, oneDeviceData->PrevMCN));
3526285809Sscottl    }
3527285809Sscottl    DeviceListList = DeviceListList->flink;
3528285809Sscottl  }
3529285809Sscottl
3530285809Sscottl  return;
3531285809Sscottl}
3532285809Sscottl
3533285809SscottlosGLOBAL void
3534285809SscottldmDiscoveryResetMCN(
3535285809Sscottl                    dmRoot_t                 *dmRoot,
3536285809Sscottl                    dmIntPortContext_t       *onePortContext
3537285809Sscottl                   )
3538285809Sscottl{
3539285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3540285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3541285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
3542285809Sscottl  dmList_t          *DeviceListList;
3543285809Sscottl
3544285809Sscottl  DM_DBG2(("dmDiscoveryResetMCN: start\n"));
3545285809Sscottl
3546285809Sscottl  /* reinitialize the device data belonging to this portcontext */
3547285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
3548285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
3549285809Sscottl  {
3550285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3551285809Sscottl    if (oneDeviceData == agNULL)
3552285809Sscottl    {
3553285809Sscottl      DM_DBG1(("dmDiscoveryResetMCN: oneDeviceData is NULL!!!\n"));
3554285809Sscottl      return;
3555285809Sscottl    }
3556285809Sscottl    DM_DBG3(("dmDiscoveryResetMCN: loop did %d\n", oneDeviceData->id));
3557285809Sscottl    if (oneDeviceData->dmPortContext == onePortContext)
3558285809Sscottl    {
3559285809Sscottl      if (oneDeviceData->ExpDevice != agNULL)
3560285809Sscottl      {
3561285809Sscottl        DM_DBG2(("dmDiscoveryResetMCN: resetting oneDeviceData->ExpDevice\n"));
3562285809Sscottl        oneDeviceData->ExpDevice = agNULL;
3563285809Sscottl      }
3564285809Sscottl      DM_DBG3(("dmDiscoveryResetMCN: resetting MCN and MCNdone\n"));
3565285809Sscottl      oneDeviceData->MCN = 0;
3566285809Sscottl
3567285809Sscottl      oneDeviceData->MCNDone = agFALSE;
3568285809Sscottl      DM_DBG2(("dmDiscoveryResetMCN: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
3569285809Sscottl      oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
3570285809Sscottl    }
3571285809Sscottl    DeviceListList = DeviceListList->flink;
3572285809Sscottl  }
3573285809Sscottl
3574285809Sscottl  return;
3575285809Sscottl}
3576285809Sscottl
3577285809Sscottl
3578285809Sscottl/*
3579285809Sscottldo min(oneDeviceData, found-one) in all upstream and downstream
3580285809Sscottlfind ajcanent expanders and mark it done; sees only ajcacent targets
3581285809Sscottl*/
3582285809SscottlosGLOBAL void
3583285809SscottldmUpdateAllAdjacent(
3584285809Sscottl                    dmRoot_t            *dmRoot,
3585285809Sscottl                    dmIntPortContext_t  *onePortContext,
3586285809Sscottl                    dmDeviceData_t      *oneDeviceData /* current one */
3587285809Sscottl                   )
3588285809Sscottl{
3589285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3590285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3591285809Sscottl  dmDeviceData_t    *tmponeDeviceData = agNULL;
3592285809Sscottl  dmList_t          *DeviceListList;
3593285809Sscottl
3594285809Sscottl  DM_DBG2(("dmUpdateAllAdjacent: start\n"));
3595285809Sscottl  if (oneDeviceData == agNULL)
3596285809Sscottl  {
3597285809Sscottl    DM_DBG1(("dmUpdateAllAdjacent: oneDeviceData is NULL!!!\n"));
3598285809Sscottl    return;
3599285809Sscottl  }
3600285809Sscottl
3601285809Sscottl  oneDeviceData->MCNDone = agTRUE;
3602285809Sscottl
3603285809Sscottl  DM_DBG2(("dmUpdateAllAdjacent: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
3604285809Sscottl  oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
3605285809Sscottl
3606285809Sscottl
3607285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
3608285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
3609285809Sscottl  {
3610285809Sscottl    tmponeDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3611285809Sscottl    if ( tmponeDeviceData == agNULL)
3612285809Sscottl    {
3613285809Sscottl      DM_DBG1(("dmUpdateAllAdjacent: tmponeDeviceData is NULL!!!\n"));
3614285809Sscottl      return;
3615285809Sscottl    }
3616285809Sscottl    DM_DBG3(("dmUpdateAllAdjacent: loop did %d\n", tmponeDeviceData->id));
3617285809Sscottl    if (tmponeDeviceData->dmPortContext == onePortContext && tmponeDeviceData->ExpDevice == oneDeviceData)
3618285809Sscottl    {
3619285809Sscottl      DM_DBG2(("dmUpdateAllAdjacent: setting MCN DONE\n"));
3620285809Sscottl      DM_DBG2(("dmUpdateAllAdjacent: tmponeDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
3621285809Sscottl      tmponeDeviceData->SASAddressID.sasAddressHi, tmponeDeviceData->SASAddressID.sasAddressLo));
3622285809Sscottl      tmponeDeviceData->MCNDone = agTRUE;
3623285809Sscottl      if (oneDeviceData->directlyAttached == agFALSE)
3624285809Sscottl      {
3625285809Sscottl        DM_DBG2(("dmUpdateAllAdjacent: tmponeDeviceData MCN 0x%x\n", tmponeDeviceData->MCN));
3626285809Sscottl        DM_DBG2(("dmUpdateAllAdjacent: oneDeviceData MCN 0x%x\n", oneDeviceData->MCN));
3627285809Sscottl        tmponeDeviceData->MCN = MIN(oneDeviceData->MCN, tmponeDeviceData->MCN);
3628285809Sscottl      }
3629285809Sscottl
3630285809Sscottl    }
3631285809Sscottl    DeviceListList = DeviceListList->flink;
3632285809Sscottl  }
3633285809Sscottl
3634285809Sscottl  return;
3635285809Sscottl
3636285809Sscottl}
3637285809Sscottl
3638285809SscottlosGLOBAL void
3639285809SscottldmUpdateMCN(
3640285809Sscottl            dmRoot_t            *dmRoot,
3641285809Sscottl            dmIntPortContext_t  *onePortContext,
3642285809Sscottl            dmDeviceData_t      *AdjacentDeviceData, /* adjacent expander */
3643285809Sscottl            dmDeviceData_t      *oneDeviceData /* current one */
3644285809Sscottl           )
3645285809Sscottl{
3646285809Sscottl
3647285809Sscottl  DM_DBG2(("dmUpdateMCN: start\n"));
3648285809Sscottl
3649285809Sscottl  if (AdjacentDeviceData == agNULL)
3650285809Sscottl  {
3651285809Sscottl    DM_DBG1(("dmUpdateMCN: AdjacentDeviceData is NULL!!!\n"));
3652285809Sscottl    return;
3653285809Sscottl  }
3654285809Sscottl
3655285809Sscottl  if (oneDeviceData == agNULL)
3656285809Sscottl  {
3657285809Sscottl    DM_DBG1(("dmUpdateMCN: oneDeviceData is NULL!!!\n"));
3658285809Sscottl    return;
3659285809Sscottl  }
3660285809Sscottl
3661285809Sscottl  DM_DBG2(("dmUpdateMCN: Current sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
3662285809Sscottl  oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
3663285809Sscottl
3664285809Sscottl  DM_DBG2(("dmUpdateMCN: AdjacentDeviceData one sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
3665285809Sscottl  AdjacentDeviceData->SASAddressID.sasAddressHi, AdjacentDeviceData->SASAddressID.sasAddressLo));
3666285809Sscottl
3667285809Sscottl  if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3668285809Sscottl  {
3669285809Sscottl    DM_DBG2(("dmUpdateMCN: DISCOVERY_UP_STREAM\n"));
3670285809Sscottl  }
3671285809Sscottl
3672285809Sscottl  if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
3673285809Sscottl  {
3674285809Sscottl    DM_DBG2(("dmUpdateMCN: DISCOVERY_DOWN_STREAM\n"));
3675285809Sscottl  }
3676285809Sscottl
3677285809Sscottl
3678285809Sscottl  /* MCN */
3679285809Sscottl
3680285809Sscottl  /* directly attached one does not have MCN
3681285809Sscottl     update only adjacent device data
3682285809Sscottl  */
3683285809Sscottl
3684285809Sscottl  if (oneDeviceData->directlyAttached == agTRUE && AdjacentDeviceData->MCNDone == agFALSE)
3685285809Sscottl  {
3686285809Sscottl    AdjacentDeviceData->MCN++;
3687285809Sscottl    DM_DBG2(("dmUpdateMCN: case 1 oneDeviceData MCN 0x%x\n", oneDeviceData->MCN));
3688285809Sscottl    DM_DBG2(("dmUpdateMCN: case 1 AdjacentDeviceData MCN 0x%x\n", AdjacentDeviceData->MCN));
3689285809Sscottl  }
3690285809Sscottl  else if (AdjacentDeviceData->MCNDone == agFALSE)
3691285809Sscottl  {
3692285809Sscottl    AdjacentDeviceData->MCN++;
3693285809Sscottl    AdjacentDeviceData->MCN = MIN(oneDeviceData->MCN, AdjacentDeviceData->MCN);
3694285809Sscottl    DM_DBG2(("dmUpdateMCN: case 2 oneDeviceData MCN 0x%x\n", oneDeviceData->MCN));
3695285809Sscottl    DM_DBG2(("dmUpdateMCN: case 2 AdjacentDeviceData MCN 0x%x\n", AdjacentDeviceData->MCN));
3696285809Sscottl  }
3697285809Sscottl
3698285809Sscottl
3699285809Sscottl  return;
3700285809Sscottl}
3701285809Sscottl/* go through expander list and device list array ??? */
3702285809SscottlosGLOBAL dmDeviceData_t *
3703285809SscottldmPortSASDeviceFind(
3704285809Sscottl                    dmRoot_t            *dmRoot,
3705285809Sscottl                    dmIntPortContext_t  *onePortContext,
3706285809Sscottl                    bit32               sasAddrLo,
3707285809Sscottl                    bit32               sasAddrHi,
3708285809Sscottl                    dmDeviceData_t      *CurrentDeviceData /* current expander */
3709285809Sscottl                    )
3710285809Sscottl{
3711285809Sscottl  dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3712285809Sscottl  dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3713285809Sscottl  dmDeviceData_t            *oneDeviceData, *RetDeviceData=agNULL;
3714285809Sscottl  dmList_t                  *DeviceListList;
3715285809Sscottl
3716285809Sscottl  DM_DBG3(("dmPortSASDeviceFind: start\n"));
3717285809Sscottl  DM_DBG3(("dmPortSASDeviceFind: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", sasAddrHi, sasAddrLo));
3718285809Sscottl
3719285809Sscottl  DM_ASSERT((agNULL != dmRoot), "");
3720285809Sscottl  DM_ASSERT((agNULL != onePortContext), "");
3721285809Sscottl
3722285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
3723285809Sscottl
3724285809Sscottl  /* find a device's existence */
3725285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
3726285809Sscottl  if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
3727285809Sscottl  {
3728285809Sscottl    DM_DBG3(("dmPortSASDeviceFind: Full discovery\n"));
3729285809Sscottl    while (DeviceListList != &(dmAllShared->MainDeviceList))
3730285809Sscottl    {
3731285809Sscottl      oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3732285809Sscottl      if (oneDeviceData == agNULL)
3733285809Sscottl      {
3734285809Sscottl        DM_DBG1(("dmPortSASDeviceFind: oneDeviceData is NULL!!!\n"));
3735285809Sscottl        return agNULL;
3736285809Sscottl      }
3737285809Sscottl      if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) &&
3738285809Sscottl          (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) &&
3739285809Sscottl          (oneDeviceData->valid == agTRUE) &&
3740285809Sscottl          (oneDeviceData->dmPortContext == onePortContext)
3741285809Sscottl        )
3742285809Sscottl      {
3743285809Sscottl        DM_DBG3(("dmPortSASDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
3744285809Sscottl        DM_DBG3(("dmPortSASDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3745285809Sscottl        DM_DBG3(("dmPortSASDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3746285809Sscottl        RetDeviceData = oneDeviceData;
3747285809Sscottl        dmUpdateMCN(dmRoot, onePortContext, RetDeviceData, CurrentDeviceData);
3748285809Sscottl       	break;
3749285809Sscottl      }
3750285809Sscottl      DeviceListList = DeviceListList->flink;
3751285809Sscottl    }
3752285809Sscottl  }
3753285809Sscottl  else
3754285809Sscottl  {
3755285809Sscottl    /* incremental discovery */
3756285809Sscottl    DM_DBG3(("dmPortSASDeviceFind: Incremental discovery\n"));
3757285809Sscottl    while (DeviceListList != &(dmAllShared->MainDeviceList))
3758285809Sscottl    {
3759285809Sscottl      oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3760285809Sscottl      if (oneDeviceData == agNULL)
3761285809Sscottl      {
3762285809Sscottl        DM_DBG1(("dmPortSASDeviceFind: oneDeviceData is NULL!!!\n"));
3763285809Sscottl        return agNULL;
3764285809Sscottl      }
3765285809Sscottl      if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) &&
3766285809Sscottl          (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) &&
3767285809Sscottl          (oneDeviceData->valid2 == agTRUE) &&
3768285809Sscottl          (oneDeviceData->dmPortContext == onePortContext)
3769285809Sscottl          )
3770285809Sscottl      {
3771285809Sscottl        DM_DBG3(("dmPortSASDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
3772285809Sscottl        DM_DBG3(("dmPortSASDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3773285809Sscottl        DM_DBG3(("dmPortSASDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3774285809Sscottl        RetDeviceData = oneDeviceData;
3775285809Sscottl        dmUpdateMCN(dmRoot, onePortContext, RetDeviceData, CurrentDeviceData);
3776285809Sscottl        break;
3777285809Sscottl      }
3778285809Sscottl      DeviceListList = DeviceListList->flink;
3779285809Sscottl    }
3780285809Sscottl  }
3781285809Sscottl
3782285809Sscottl  tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
3783285809Sscottl
3784285809Sscottl  return RetDeviceData;
3785285809Sscottl}
3786285809Sscottl
3787285809Sscottlbit32
3788285809SscottldmNewEXPorNot(
3789285809Sscottl              dmRoot_t              *dmRoot,
3790285809Sscottl              dmIntPortContext_t    *onePortContext,
3791285809Sscottl              dmSASSubID_t          *dmSASSubID
3792285809Sscottl             )
3793285809Sscottl{
3794285809Sscottl//  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3795285809Sscottl//  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3796285809Sscottl  dmExpander_t      *oneExpander = agNULL;
3797285809Sscottl  dmList_t          *ExpanderList;
3798285809Sscottl  bit32             ret = agTRUE;
3799285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
3800285809Sscottl
3801285809Sscottl  DM_DBG3(("dmNewEXPorNot: start\n"));
3802285809Sscottl
3803285809Sscottl  /* find a device's existence */
3804285809Sscottl  ExpanderList = onePortContext->discovery.discoveringExpanderList.flink;
3805285809Sscottl  while (ExpanderList != &(onePortContext->discovery.discoveringExpanderList))
3806285809Sscottl  {
3807285809Sscottl    oneExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
3808285809Sscottl    if ( oneExpander == agNULL)
3809285809Sscottl    {
3810285809Sscottl      DM_DBG1(("dmNewEXPorNot: oneExpander is NULL!!!\n"));
3811285809Sscottl      return agFALSE;
3812285809Sscottl    }
3813285809Sscottl    oneDeviceData = oneExpander->dmDevice;
3814285809Sscottl    if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) &&
3815285809Sscottl        (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) &&
3816285809Sscottl        (oneDeviceData->dmPortContext == onePortContext)
3817285809Sscottl        )
3818285809Sscottl    {
3819285809Sscottl      DM_DBG3(("dmNewEXPorNot: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
3820285809Sscottl      ret = agFALSE;
3821285809Sscottl      break;
3822285809Sscottl    }
3823285809Sscottl    ExpanderList = ExpanderList->flink;
3824285809Sscottl  }
3825285809Sscottl
3826285809Sscottl  return ret;
3827285809Sscottl}
3828285809Sscottl
3829285809Sscottl
3830285809Sscottlbit32
3831285809SscottldmNewSASorNot(
3832285809Sscottl              dmRoot_t              *dmRoot,
3833285809Sscottl              dmIntPortContext_t    *onePortContext,
3834285809Sscottl              dmSASSubID_t          *dmSASSubID
3835285809Sscottl             )
3836285809Sscottl{
3837285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3838285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3839285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
3840285809Sscottl  dmList_t          *DeviceListList;
3841285809Sscottl  bit32             ret = agTRUE;
3842285809Sscottl
3843285809Sscottl  DM_DBG3(("dmNewSASorNot: start\n"));
3844285809Sscottl
3845285809Sscottl  /* find a device's existence */
3846285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
3847285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
3848285809Sscottl  {
3849285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
3850285809Sscottl    if (oneDeviceData == agNULL)
3851285809Sscottl    {
3852285809Sscottl      DM_DBG1(("dmNewSASorNot: oneDeviceData is NULL!!!\n"));
3853285809Sscottl      return agFALSE;
3854285809Sscottl    }
3855285809Sscottl    if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) &&
3856285809Sscottl        (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) &&
3857285809Sscottl        (oneDeviceData->dmPortContext == onePortContext) &&
3858285809Sscottl        (oneDeviceData->registered == agTRUE)
3859285809Sscottl       )
3860285809Sscottl    {
3861285809Sscottl      DM_DBG3(("dmNewSASorNot: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
3862285809Sscottl      ret = agFALSE;
3863285809Sscottl      break;
3864285809Sscottl    }
3865285809Sscottl    DeviceListList = DeviceListList->flink;
3866285809Sscottl  }
3867285809Sscottl
3868285809Sscottl  return ret;
3869285809Sscottl}
3870285809Sscottl/*
3871285809Sscottlcall
3872285809SscottlosGLOBAL bit32
3873285809SscottltddmReportDevice(
3874285809Sscottl                 dmRoot_t 		*dmRoot,
3875285809Sscottl                 dmPortContext_t	*dmPortContext,
3876285809Sscottl                 dmDeviceInfo_t		*dmDeviceInfo
3877285809Sscottl                 )
3878285809Sscottlif not reported, report Device to TDM
3879285809Sscottl*/
3880285809SscottlosGLOBAL dmDeviceData_t *
3881285809SscottldmPortSASDeviceAdd(
3882285809Sscottl                   dmRoot_t            *dmRoot,
3883285809Sscottl                   dmIntPortContext_t  *onePortContext,
3884285809Sscottl                   agsaSASIdentify_t   sasIdentify,
3885285809Sscottl                   bit32               sasInitiator,
3886285809Sscottl                   bit8                connectionRate,
3887285809Sscottl                   bit32               itNexusTimeout,
3888285809Sscottl                   bit32               firstBurstSize,
3889285809Sscottl                   bit32               deviceType,
3890285809Sscottl                   dmDeviceData_t      *oneExpDeviceData,
3891285809Sscottl                   dmExpander_t        *dmExpander,
3892285809Sscottl                   bit8                phyID
3893285809Sscottl                  )
3894285809Sscottl{
3895285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
3896285809Sscottl  bit8              dev_s_rate = 0;
3897285809Sscottl  bit8              sasorsata = 1;
3898285809Sscottl  dmSASSubID_t      dmSASSubID;
3899285809Sscottl  bit8              ExpanderConnectionRate = connectionRate;
3900285809Sscottl  dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
3901285809Sscottl  bit16             extension = 0;
3902285809Sscottl  bit32             current_link_rate = 0;
3903285809Sscottl
3904285809Sscottl  DM_DBG3(("dmPortSASDeviceAdd: start\n"));
3905285809Sscottl  DM_DBG3(("dmPortSASDeviceAdd: connectionRate %d\n", connectionRate));
3906285809Sscottl
3907285809Sscottl  dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
3908285809Sscottl  dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
3909285809Sscottl  dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
3910285809Sscottl  dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
3911285809Sscottl
3912285809Sscottl  if (oneExpDeviceData != agNULL)
3913285809Sscottl  {
3914285809Sscottl    ExpanderConnectionRate =   DEVINFO_GET_LINKRATE(&oneExpDeviceData->agDeviceInfo);
3915285809Sscottl    DM_DBG3(("dmPortSASDeviceAdd: ExpanderConnectionRate 0x%x\n", ExpanderConnectionRate));
3916285809Sscottl  }
3917285809Sscottl  if (oneExpDeviceData != agNULL)
3918285809Sscottl  {
3919285809Sscottl    if (oneExpDeviceData->SASAddressID.sasAddressHi == 0x0 &&
3920285809Sscottl        oneExpDeviceData->SASAddressID.sasAddressLo == 0x0)
3921285809Sscottl    {
3922285809Sscottl      DM_DBG1(("dmPortSASDeviceAdd: 1st Wrong expander!!!\n"));
3923285809Sscottl    }
3924285809Sscottl  }
3925285809Sscottl  /* old device and already reported to TDM */
3926285809Sscottl  if ( agFALSE == dmNewSASorNot(
3927285809Sscottl                                 dmRoot,
3928285809Sscottl                                 onePortContext,
3929285809Sscottl                                 &dmSASSubID
3930285809Sscottl                                )
3931285809Sscottl       ) /* old device */
3932285809Sscottl  {
3933285809Sscottl    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));
3934285809Sscottl    /* allocate a new device and set the valid bit */
3935285809Sscottl    oneDeviceData = dmAddSASToSharedcontext(
3936285809Sscottl                                               dmRoot,
3937285809Sscottl                                               onePortContext,
3938285809Sscottl                                               &dmSASSubID,
3939285809Sscottl                                               oneExpDeviceData,
3940285809Sscottl                                               phyID
3941285809Sscottl                                               );
3942285809Sscottl    if (oneDeviceData == agNULL)
3943285809Sscottl    {
3944285809Sscottl      DM_DBG1(("dmPortSASDeviceAdd: no more device, oneDeviceData is null!!!\n"));
3945285809Sscottl    }
3946285809Sscottl    /* If a device is allocated */
3947285809Sscottl    if ( oneDeviceData != agNULL )
3948285809Sscottl    {
3949285809Sscottl
3950285809Sscottl
3951285809Sscottl      if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3952285809Sscottl      {
3953285809Sscottl        DM_DBG3(("dmPortSASDeviceAdd: OLD, UP_STREAM\n"));
3954285809Sscottl      }
3955285809Sscottl      if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
3956285809Sscottl      {
3957285809Sscottl        DM_DBG3(("dmPortSASDeviceAdd: OLD, DOWN_STREAM\n"));
3958285809Sscottl      }
3959285809Sscottl
3960285809Sscottl      if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
3961285809Sscottl      {
3962285809Sscottl        DM_DBG3(("dmPortSASDeviceAdd: FULL_START\n"));
3963285809Sscottl        oneDeviceData->MCN++;
3964285809Sscottl      }
3965285809Sscottl      else
3966285809Sscottl      {
3967285809Sscottl        /* incremental */
3968285809Sscottl        DM_DBG3(("dmPortSASDeviceAdd: INCREMENTAL_START\n"));
3969285809Sscottl        if (oneDeviceData->MCN == 0 && oneDeviceData->directlyAttached == agFALSE)
3970285809Sscottl        {
3971285809Sscottl          oneDeviceData->MCN++;
3972285809Sscottl        }
3973285809Sscottl      }
3974285809Sscottl
3975285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData MCN 0x%08x\n", oneDeviceData->MCN));
3976285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
3977285809Sscottl      oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
3978285809Sscottl
3979285809Sscottl
3980285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify)));
3981285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify)));
3982285809Sscottl
3983285809Sscottl//      oneDeviceData->sasIdentify = sasIdentify;
3984285809Sscottl      dm_memcpy(&(oneDeviceData->sasIdentify), &sasIdentify, sizeof(agsaSASIdentify_t));
3985285809Sscottl
3986285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
3987285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
3988285809Sscottl
3989285809Sscottl      /* parse sasIDframe to fill in agDeviceInfo */
3990285809Sscottl      DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT);
3991285809Sscottl      DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)itNexusTimeout);
3992285809Sscottl      DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, (bit16)firstBurstSize);
3993285809Sscottl      DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 1);
3994285809Sscottl
3995285809Sscottl      oneDeviceData->SASSpecDeviceType = SA_IDFRM_GET_DEVICETTYPE(&sasIdentify);
3996285809Sscottl
3997285809Sscottl      /* adjusting connectionRate */
3998285809Sscottl      oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
3999285809Sscottl      if (oneAttachedExpDeviceData != agNULL)
4000285809Sscottl      {
4001285809Sscottl        connectionRate = MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo));
4002285809Sscottl        DM_DBG3(("dmPortSASDeviceAdd: 1st connectionRate 0x%x  DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n",
4003285809Sscottl	       connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
4004285809Sscottl      }
4005285809Sscottl      else
4006285809Sscottl      {
4007285809Sscottl       DM_DBG3(("dmPortSASDeviceAdd: 1st oneAttachedExpDeviceData is NULL\n"));
4008285809Sscottl      }
4009285809Sscottl
4010285809Sscottl      /* Device Type, SAS or SATA, connection rate; bit7 --- bit0 */
4011285809Sscottl      sasorsata = (bit8)deviceType;
4012285809Sscottl      /* sTSDK spec device typ */
4013285809Sscottl      dev_s_rate = dev_s_rate | (sasorsata << 4);
4014285809Sscottl      dev_s_rate = dev_s_rate | MIN(connectionRate, ExpanderConnectionRate);
4015285809Sscottl      /* detect link rate change */
4016285809Sscottl      current_link_rate = DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo);
4017285809Sscottl      if (current_link_rate != (bit32)MIN(connectionRate, ExpanderConnectionRate))
4018285809Sscottl      {
4019285809Sscottl        DM_DBG1(("dmPortSASDeviceAdd: link rate changed current 0x%x new 0x%x\n", current_link_rate, MIN(connectionRate, ExpanderConnectionRate)));
4020285809Sscottl        DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->dmDeviceInfo, dev_s_rate);
4021285809Sscottl        if (oneDeviceData->ExpDevice != agNULL)
4022285809Sscottl        {
4023285809Sscottl          oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
4024285809Sscottl          tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, dmDeviceRateChange);
4025285809Sscottl        }
4026285809Sscottl        else
4027285809Sscottl        {
4028285809Sscottl          tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, dmDeviceArrival);
4029285809Sscottl        }
4030285809Sscottl      }
4031285809Sscottl
4032285809Sscottl      DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate);
4033285809Sscottl
4034285809Sscottl
4035285809Sscottl      DEVINFO_PUT_SAS_ADDRESSLO(
4036285809Sscottl                                &oneDeviceData->agDeviceInfo,
4037285809Sscottl                                SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)
4038285809Sscottl                                );
4039285809Sscottl      DEVINFO_PUT_SAS_ADDRESSHI(
4040285809Sscottl                                &oneDeviceData->agDeviceInfo,
4041285809Sscottl                                SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)
4042285809Sscottl                                );
4043285809Sscottl      oneDeviceData->agContext.osData = oneDeviceData;
4044285809Sscottl      oneDeviceData->agContext.sdkData = agNULL;
4045285809Sscottl
4046285809Sscottl
4047285809Sscottl    }
4048285809Sscottl    return oneDeviceData;
4049285809Sscottl  }  /* old device */
4050285809Sscottl
4051285809Sscottl
4052285809Sscottl  /* new device */
4053285809Sscottl
4054285809Sscottl  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));
4055285809Sscottl
4056285809Sscottl  /* allocate a new device and set the valid bit */
4057285809Sscottl  oneDeviceData = dmAddSASToSharedcontext(
4058285809Sscottl                                               dmRoot,
4059285809Sscottl                                               onePortContext,
4060285809Sscottl                                               &dmSASSubID,
4061285809Sscottl                                               oneExpDeviceData,
4062285809Sscottl                                               phyID
4063285809Sscottl                                               );
4064285809Sscottl  if (oneDeviceData == agNULL)
4065285809Sscottl  {
4066285809Sscottl    DM_DBG1(("dmPortSASDeviceAdd: no more device, oneDeviceData is null !!!\n"));
4067285809Sscottl  }
4068285809Sscottl
4069285809Sscottl   /* If a device is allocated */
4070285809Sscottl  if ( oneDeviceData != agNULL )
4071285809Sscottl  {
4072285809Sscottl
4073285809Sscottl//    DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify)));
4074285809Sscottl//    DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify)));
4075285809Sscottl
4076285809Sscottl//    oneDeviceData->sasIdentify = sasIdentify;
4077285809Sscottl    dm_memcpy(&(oneDeviceData->sasIdentify), &sasIdentify, sizeof(agsaSASIdentify_t));
4078285809Sscottl
4079285809Sscottl    if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
4080285809Sscottl    {
4081285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: NEW, UP_STREAM\n"));
4082285809Sscottl    }
4083285809Sscottl    if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
4084285809Sscottl    {
4085285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: NEW, DOWN_STREAM\n"));
4086285809Sscottl    }
4087285809Sscottl
4088285809Sscottl    if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
4089285809Sscottl    {
4090285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: FULL_START\n"));
4091285809Sscottl      oneDeviceData->MCN++;
4092285809Sscottl    }
4093285809Sscottl    else
4094285809Sscottl    {
4095285809Sscottl      /* incremental */
4096285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: INCREMENTAL_START\n"));
4097285809Sscottl      if (oneDeviceData->MCN == 0 && oneDeviceData->directlyAttached == agFALSE)
4098285809Sscottl      {
4099285809Sscottl        oneDeviceData->MCN++;
4100285809Sscottl      }
4101285809Sscottl    }
4102285809Sscottl    DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData MCN 0x%08x\n", oneDeviceData->MCN));
4103285809Sscottl    DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
4104285809Sscottl    oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
4105285809Sscottl
4106285809Sscottl    DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
4107285809Sscottl    DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
4108285809Sscottl
4109285809Sscottl    /* parse sasIDframe to fill in agDeviceInfo */
4110285809Sscottl    DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT);
4111285809Sscottl    DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)itNexusTimeout);
4112285809Sscottl    DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, (bit16)firstBurstSize);
4113285809Sscottl    DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 1);
4114285809Sscottl
4115285809Sscottl    oneDeviceData->SASSpecDeviceType = SA_IDFRM_GET_DEVICETTYPE(&sasIdentify);
4116285809Sscottl
4117285809Sscottl    /* adjusting connectionRate */
4118285809Sscottl    oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
4119285809Sscottl    if (oneAttachedExpDeviceData != agNULL)
4120285809Sscottl    {
4121285809Sscottl      connectionRate = MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo));
4122285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: 2nd connectionRate 0x%x  DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n",
4123285809Sscottl                connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
4124285809Sscottl    }
4125285809Sscottl    else
4126285809Sscottl    {
4127285809Sscottl     DM_DBG3(("dmPortSASDeviceAdd: 2nd oneAttachedExpDeviceData is NULL\n"));
4128285809Sscottl    }
4129285809Sscottl
4130285809Sscottl    /* Device Type, SAS or SATA, connection rate; bit7 --- bit0 */
4131285809Sscottl    sasorsata = (bit8)deviceType;
4132285809Sscottl    dev_s_rate = dev_s_rate | (sasorsata << 4);
4133285809Sscottl    dev_s_rate = dev_s_rate | MIN(connectionRate, ExpanderConnectionRate);
4134285809Sscottl    DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate);
4135285809Sscottl
4136285809Sscottl
4137285809Sscottl    DEVINFO_PUT_SAS_ADDRESSLO(
4138285809Sscottl                              &oneDeviceData->agDeviceInfo,
4139285809Sscottl                              SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)
4140285809Sscottl                              );
4141285809Sscottl    DEVINFO_PUT_SAS_ADDRESSHI(
4142285809Sscottl                              &oneDeviceData->agDeviceInfo,
4143285809Sscottl                              SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)
4144285809Sscottl                              );
4145285809Sscottl    oneDeviceData->agContext.osData = oneDeviceData;
4146285809Sscottl    oneDeviceData->agContext.sdkData = agNULL;
4147285809Sscottl
4148285809Sscottl    DM_DBG3(("dmPortSASDeviceAdd: did %d\n", oneDeviceData->id));
4149285809Sscottl
4150285809Sscottl
4151285809Sscottl    /* reporting to TDM; setting dmDeviceInfo */
4152285809Sscottl    DEVINFO_PUT_SMPTO(&oneDeviceData->dmDeviceInfo, DEFAULT_SMP_TIMEOUT);
4153285809Sscottl    DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->dmDeviceInfo, (bit16)itNexusTimeout);
4154285809Sscottl    DEVINFO_PUT_FBS(&oneDeviceData->dmDeviceInfo, (bit16)firstBurstSize);
4155285809Sscottl    DEVINFO_PUT_FLAG(&oneDeviceData->dmDeviceInfo, 1);
4156285809Sscottl    DEVINFO_PUT_INITIATOR_SSP_STP_SMP(&oneDeviceData->dmDeviceInfo, dmSASSubID.initiator_ssp_stp_smp);
4157285809Sscottl    DEVINFO_PUT_TARGET_SSP_STP_SMP(&oneDeviceData->dmDeviceInfo, dmSASSubID.target_ssp_stp_smp);
4158285809Sscottl    extension = phyID;
4159285809Sscottl
4160285809Sscottl    /* setting 6th bit of dev_s_rate */
4161285809Sscottl    if (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE ||
4162285809Sscottl        oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE )
4163285809Sscottl    {
4164285809Sscottl      extension = (bit16)(extension | (1 << 8));
4165285809Sscottl    }
4166285809Sscottl    DEVINFO_PUT_EXT(&oneDeviceData->dmDeviceInfo, extension);
4167285809Sscottl
4168285809Sscottl    DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->dmDeviceInfo, dev_s_rate);
4169285809Sscottl
4170285809Sscottl    DEVINFO_PUT_SAS_ADDRESSLO(
4171285809Sscottl                              &oneDeviceData->dmDeviceInfo,
4172285809Sscottl                              SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)
4173285809Sscottl                              );
4174285809Sscottl    DEVINFO_PUT_SAS_ADDRESSHI(
4175285809Sscottl                              &oneDeviceData->dmDeviceInfo,
4176285809Sscottl                              SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)
4177285809Sscottl                              );
4178285809Sscottl
4179285809Sscottl    if (oneDeviceData->ExpDevice != agNULL)
4180285809Sscottl    {
4181285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: attached expander case\n"));
4182285809Sscottl      oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
4183285809Sscottl      /*
4184285809Sscottl        Puts attached expander's SAS address into dmDeviceInfo
4185285809Sscottl      */
4186285809Sscottl      DEVINFO_PUT_SAS_ADDRESSLO(
4187285809Sscottl                                &oneAttachedExpDeviceData->dmDeviceInfo,
4188285809Sscottl                                oneAttachedExpDeviceData->SASAddressID.sasAddressLo
4189285809Sscottl                                );
4190285809Sscottl      DEVINFO_PUT_SAS_ADDRESSHI(
4191285809Sscottl                                &oneAttachedExpDeviceData->dmDeviceInfo,
4192285809Sscottl                                oneAttachedExpDeviceData->SASAddressID.sasAddressHi
4193285809Sscottl                                );
4194285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: oneAttachedExpDeviceData addrHi 0x%08x addrLo 0x%08x PhyID 0x%x ext 0x%x\n",
4195285809Sscottl      DM_GET_SAS_ADDRESSHI(oneAttachedExpDeviceData->dmDeviceInfo.sasAddressHi),
4196285809Sscottl      DM_GET_SAS_ADDRESSLO(oneAttachedExpDeviceData->dmDeviceInfo.sasAddressLo),
4197285809Sscottl      phyID, extension));
4198285809Sscottl
4199285809Sscottl      if (oneAttachedExpDeviceData->SASAddressID.sasAddressHi == 0x0 &&
4200285809Sscottl          oneAttachedExpDeviceData->SASAddressID.sasAddressLo == 0x0)
4201285809Sscottl      {
4202285809Sscottl        DM_DBG1(("dmPortSASDeviceAdd: 2nd Wrong expander!!!\n"));
4203285809Sscottl      }
4204285809Sscottl      if (oneDeviceData->reported == agFALSE)
4205285809Sscottl      {
4206285809Sscottl        oneDeviceData->registered = agTRUE;
4207285809Sscottl        oneDeviceData->reported = agTRUE;
4208285809Sscottl        if (deviceType == STP_DEVICE_TYPE)
4209285809Sscottl        {
4210285809Sscottl            /*STP device, DM need send SMP Report Phy SATA to get the SATA device type */
4211285809Sscottl            oneAttachedExpDeviceData->dmExpander->dmDeviceToProcess = oneDeviceData;
4212285809Sscottl            dmReportPhySataSend(dmRoot, oneAttachedExpDeviceData, phyID);
4213285809Sscottl        }
4214285809Sscottl        else
4215285809Sscottl        {
4216285809Sscottl            /* SAS or SMP device */
4217285809Sscottl            tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, dmDeviceArrival);
4218285809Sscottl        }
4219285809Sscottl      }
4220285809Sscottl    }
4221285809Sscottl    else
4222285809Sscottl    {
4223285809Sscottl      DM_DBG3(("dmPortSASDeviceAdd: NO attached expander case\n"));
4224285809Sscottl      if (oneDeviceData->reported == agFALSE)
4225285809Sscottl      {
4226285809Sscottl        oneDeviceData->registered = agTRUE;
4227285809Sscottl        oneDeviceData->reported = agTRUE;
4228285809Sscottl        tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, dmDeviceArrival);
4229285809Sscottl      }
4230285809Sscottl    }
4231285809Sscottl  }
4232285809Sscottl
4233285809Sscottl  return oneDeviceData;
4234285809Sscottl}
4235285809Sscottl
4236285809SscottlosGLOBAL dmDeviceData_t *
4237285809SscottldmFindRegNValid(
4238285809Sscottl                dmRoot_t             *dmRoot,
4239285809Sscottl                dmIntPortContext_t   *onePortContext,
4240285809Sscottl                dmSASSubID_t         *dmSASSubID
4241285809Sscottl               )
4242285809Sscottl{
4243285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
4244285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
4245285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
4246285809Sscottl  dmList_t          *DeviceListList;
4247285809Sscottl  bit32             found = agFALSE;
4248285809Sscottl  DM_DBG3(("dmFindRegNValid: start\n"));
4249285809Sscottl
4250285809Sscottl  /* find a device's existence */
4251285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
4252285809Sscottl  if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
4253285809Sscottl  {
4254285809Sscottl    DM_DBG3(("dmFindRegNValid: Full discovery\n"));
4255285809Sscottl    while (DeviceListList != &(dmAllShared->MainDeviceList))
4256285809Sscottl    {
4257285809Sscottl      oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
4258285809Sscottl      if (oneDeviceData == agNULL)
4259285809Sscottl      {
4260285809Sscottl        DM_DBG1(("dmFindRegNValid: oneDeviceData is NULL!!!\n"));
4261285809Sscottl        return agFALSE;
4262285809Sscottl      }
4263285809Sscottl      if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) &&
4264285809Sscottl          (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) &&
4265285809Sscottl          (oneDeviceData->valid == agTRUE) &&
4266285809Sscottl          (oneDeviceData->dmPortContext == onePortContext)
4267285809Sscottl          )
4268285809Sscottl      {
4269285809Sscottl        DM_DBG3(("dmFindRegNValid: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
4270285809Sscottl        DM_DBG3(("dmFindRegNValid: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
4271285809Sscottl        DM_DBG3(("dmFindRegNValid: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
4272285809Sscottl        found = agTRUE;
4273285809Sscottl        break;
4274285809Sscottl      }
4275285809Sscottl      DeviceListList = DeviceListList->flink;
4276285809Sscottl    }
4277285809Sscottl  }
4278285809Sscottl  else
4279285809Sscottl  {
4280285809Sscottl    /* incremental discovery */
4281285809Sscottl    DM_DBG3(("dmFindRegNValid: Incremental discovery\n"));
4282285809Sscottl    while (DeviceListList != &(dmAllShared->MainDeviceList))
4283285809Sscottl    {
4284285809Sscottl      oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
4285285809Sscottl      if (oneDeviceData == agNULL)
4286285809Sscottl      {
4287285809Sscottl        DM_DBG1(("dmFindRegNValid: oneDeviceData is NULL!!!\n"));
4288285809Sscottl        return agFALSE;
4289285809Sscottl      }
4290285809Sscottl      if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) &&
4291285809Sscottl          (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) &&
4292285809Sscottl          (oneDeviceData->valid2 == agTRUE) &&
4293285809Sscottl          (oneDeviceData->dmPortContext == onePortContext)
4294285809Sscottl          )
4295285809Sscottl      {
4296285809Sscottl        DM_DBG3(("dmFindRegNValid: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
4297285809Sscottl        DM_DBG3(("dmFindRegNValid: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
4298285809Sscottl        DM_DBG3(("dmFindRegNValid: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
4299285809Sscottl        found = agTRUE;
4300285809Sscottl        break;
4301285809Sscottl      }
4302285809Sscottl      DeviceListList = DeviceListList->flink;
4303285809Sscottl    }
4304285809Sscottl  }
4305285809Sscottl
4306285809Sscottl
4307285809Sscottl
4308285809Sscottl  if (found == agFALSE)
4309285809Sscottl  {
4310285809Sscottl    DM_DBG3(("dmFindRegNValid: end returning NULL\n"));
4311285809Sscottl    return agNULL;
4312285809Sscottl  }
4313285809Sscottl  else
4314285809Sscottl  {
4315285809Sscottl    DM_DBG3(("dmFindRegNValid: end returning NOT NULL\n"));
4316285809Sscottl    return oneDeviceData;
4317285809Sscottl  }
4318285809Sscottl}
4319285809Sscottl
4320285809SscottlosGLOBAL void
4321285809SscottldmNotifyBC(
4322285809Sscottl           dmRoot_t			*dmRoot,
4323285809Sscottl           dmPortContext_t		*dmPortContext,
4324285809Sscottl           bit32 			type)
4325285809Sscottl{
4326285809Sscottl  dmIntPortContext_t        *onePortContext = agNULL;
4327285809Sscottl
4328285809Sscottl  onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
4329285809Sscottl
4330285809Sscottl  DM_DBG3(("dmNotifyBC: start\n"));
4331285809Sscottl
4332285809Sscottl  if (onePortContext == agNULL)
4333285809Sscottl  {
4334285809Sscottl    DM_DBG1(("dmNotifyBC: onePortContext is NULL, wrong!!!\n"));
4335285809Sscottl    return;
4336285809Sscottl  }
4337285809Sscottl
4338285809Sscottl  if (type == OSSA_HW_EVENT_BROADCAST_CHANGE)
4339285809Sscottl  {
4340285809Sscottl    if (onePortContext->DiscoveryAbortInProgress == agFALSE)
4341285809Sscottl    {
4342285809Sscottl    if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED)
4343285809Sscottl    {
4344285809Sscottl      DM_DBG3(("dmNotifyBC: BROADCAST_CHANGE\n"));
4345285809Sscottl      onePortContext->DiscoveryState = DM_DSTATE_NOT_STARTED;
4346285809Sscottl      onePortContext->discoveryOptions = DM_DISCOVERY_OPTION_INCREMENTAL_START;
4347285809Sscottl      /* processed broadcast change */
4348285809Sscottl      onePortContext->discovery.SeenBC = agFALSE;
4349285809Sscottl    }
4350285809Sscottl    else
4351285809Sscottl    {
4352285809Sscottl      DM_DBG3(("dmNotifyBC: pid %d BROADCAST_CHANGE; updating SeenBC. Do nothing.\n", onePortContext->id));
4353285809Sscottl      onePortContext->discovery.SeenBC = agTRUE;
4354285809Sscottl    }
4355285809Sscottl    }
4356285809Sscottl  }
4357285809Sscottl  else if (type == OSSA_HW_EVENT_BROADCAST_SES)
4358285809Sscottl  {
4359285809Sscottl    DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_SES\n"));
4360285809Sscottl  }
4361285809Sscottl  else if (type == OSSA_HW_EVENT_BROADCAST_EXP)
4362285809Sscottl  {
4363285809Sscottl    DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_EXP\n"));
4364285809Sscottl  }
4365285809Sscottl  else
4366285809Sscottl  {
4367285809Sscottl    DM_DBG3(("dmNotifyBC: unspecified broadcast type 0x%x\n", type));
4368285809Sscottl  }
4369285809Sscottl  return;
4370285809Sscottl}
4371285809Sscottl
4372285809Sscottl
4373285809Sscottl#ifdef WORKED
4374285809Sscottl/* triggers incremental discovery */
4375285809SscottlosGLOBAL void
4376285809SscottldmNotifyBC(
4377285809Sscottl           dmRoot_t			*dmRoot,
4378285809Sscottl           dmPortContext_t		*dmPortContext,
4379285809Sscottl           bit32 			type)
4380285809Sscottl{
4381285809Sscottl  dmIntPortContext_t        *onePortContext = agNULL;
4382285809Sscottl
4383285809Sscottl  onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
4384285809Sscottl
4385285809Sscottl  DM_DBG3(("dmNotifyBC: start\n"));
4386285809Sscottl
4387285809Sscottl
4388285809Sscottl  if (type == OSSA_HW_EVENT_BROADCAST_CHANGE)
4389285809Sscottl  {
4390285809Sscottl    if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED)
4391285809Sscottl    {
4392285809Sscottl      DM_DBG3(("dmNotifyBC: BROADCAST_CHANGE; does incremental discovery\n"));
4393285809Sscottl      onePortContext->DiscoveryState = DM_DSTATE_NOT_STARTED;
4394285809Sscottl      onePortContext->discoveryOptions = DM_DISCOVERY_OPTION_INCREMENTAL_START;
4395285809Sscottl      /* processed broadcast change */
4396285809Sscottl      onePortContext->discovery.SeenBC = agFALSE;
4397285809Sscottl      if (onePortContext->discovery.ResetTriggerred == agTRUE)
4398285809Sscottl      {
4399285809Sscottl        DM_DBG3(("dmNotifyBC: tdsaBCTimer\n"));
4400285809Sscottl        dmBCTimer(dmRoot, onePortContext);
4401285809Sscottl      }
4402285809Sscottl      else
4403285809Sscottl      {
4404285809Sscottl        dmDiscover(
4405285809Sscottl                   dmRoot,
4406285809Sscottl                   dmPortContext,
4407285809Sscottl                   DM_DISCOVERY_OPTION_INCREMENTAL_START
4408285809Sscottl                  );
4409285809Sscottl      }
4410285809Sscottl    }
4411285809Sscottl    else
4412285809Sscottl    {
4413285809Sscottl      DM_DBG3(("dmNotifyBC: pid %d BROADCAST_CHANGE; updating SeenBC. Do nothing.\n", onePortContext->id));
4414285809Sscottl      onePortContext->discovery.SeenBC = agTRUE;
4415285809Sscottl    }
4416285809Sscottl  }
4417285809Sscottl  else if (type == OSSA_HW_EVENT_BROADCAST_SES)
4418285809Sscottl  {
4419285809Sscottl    DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_SES\n"));
4420285809Sscottl  }
4421285809Sscottl  else if (type == OSSA_HW_EVENT_BROADCAST_EXP)
4422285809Sscottl  {
4423285809Sscottl    DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_EXP\n"));
4424285809Sscottl  }
4425285809Sscottl  else
4426285809Sscottl  {
4427285809Sscottl    DM_DBG3(("dmNotifyBC: unspecified broadcast type 0x%x\n", type));
4428285809Sscottl  }
4429285809Sscottl  return;
4430285809Sscottl}
4431285809Sscottl#endif
4432285809Sscottl
4433285809SscottlosGLOBAL bit32
4434285809SscottldmResetFailedDiscovery(
4435285809Sscottl                 dmRoot_t               *dmRoot,
4436285809Sscottl                 dmPortContext_t        *dmPortContext)
4437285809Sscottl{
4438285809Sscottl  dmIntPortContext_t        *onePortContext = agNULL;
4439285809Sscottl
4440285809Sscottl  DM_DBG1(("dmResetFailedDiscovery: start\n"));
4441285809Sscottl
4442285809Sscottl  onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
4443285809Sscottl
4444285809Sscottl  if (onePortContext == agNULL)
4445285809Sscottl  {
4446285809Sscottl    DM_DBG1(("dmResetFailedDiscovery: onePortContext is NULL, wrong!!!\n"));
4447285809Sscottl    return DM_RC_FAILURE;
4448285809Sscottl  }
4449285809Sscottl
4450285809Sscottl  if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED_WITH_FAILURE)
4451285809Sscottl  {
4452285809Sscottl    onePortContext->DiscoveryState = DM_DSTATE_COMPLETED;
4453285809Sscottl  }
4454285809Sscottl  else
4455285809Sscottl  {
4456285809Sscottl    DM_DBG1(("dmResetFailedDiscovery: discovery is NOT DM_DSTATE_COMPLETED_WITH_FAILURE. It is 0x%x\n", onePortContext->DiscoveryState));
4457285809Sscottl    return DM_RC_FAILURE;
4458285809Sscottl  }
4459285809Sscottl
4460285809Sscottl  return DM_RC_SUCCESS;
4461285809Sscottl}
4462285809Sscottl
4463285809SscottlosGLOBAL bit32
4464285809SscottldmQueryDiscovery(
4465285809Sscottl                 dmRoot_t 		*dmRoot,
4466285809Sscottl                 dmPortContext_t	*dmPortContext)
4467285809Sscottl{
4468285809Sscottl  dmIntPortContext_t        *onePortContext = agNULL;
4469285809Sscottl
4470285809Sscottl  DM_DBG3(("dmQueryDiscovery: start\n"));
4471285809Sscottl
4472285809Sscottl  onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
4473285809Sscottl
4474285809Sscottl  if (onePortContext == agNULL)
4475285809Sscottl  {
4476285809Sscottl    DM_DBG1(("dmQueryDiscovery: onePortContext is NULL, wrong!!!\n"));
4477285809Sscottl    return DM_RC_FAILURE;
4478285809Sscottl  }
4479285809Sscottl
4480285809Sscottl  /* call tddmQueryDiscoveryCB() */
4481285809Sscottl  if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED)
4482285809Sscottl  {
4483285809Sscottl    tddmQueryDiscoveryCB(dmRoot, dmPortContext,  onePortContext->discoveryOptions, dmDiscCompleted);
4484285809Sscottl  }
4485285809Sscottl  else if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED_WITH_FAILURE)
4486285809Sscottl  {
4487285809Sscottl    tddmQueryDiscoveryCB(dmRoot, dmPortContext,  onePortContext->discoveryOptions, dmDiscFailed);
4488285809Sscottl  }
4489285809Sscottl  else
4490285809Sscottl  {
4491285809Sscottl    tddmQueryDiscoveryCB(dmRoot, dmPortContext,  onePortContext->discoveryOptions, dmDiscInProgress);
4492285809Sscottl  }
4493285809Sscottl
4494285809Sscottl  return DM_RC_SUCCESS;
4495285809Sscottl}
4496285809Sscottl
4497285809Sscottl
4498285809Sscottl/*
4499285809Sscottl  should only for an expander
4500285809Sscottl*/
4501285809SscottlosGLOBAL bit32
4502285809SscottldmRegisterDevice(
4503285809Sscottl		 dmRoot_t 		*dmRoot,
4504285809Sscottl		 dmPortContext_t	*dmPortContext,
4505285809Sscottl		 dmDeviceInfo_t		*dmDeviceInfo,
4506285809Sscottl                 agsaDevHandle_t        *agDevHandle
4507285809Sscottl		 )
4508285809Sscottl{
4509285809Sscottl
4510285809Sscottl  dmIntPortContext_t        *onePortContext = agNULL;
4511285809Sscottl  dmExpander_t              *oneExpander = agNULL;
4512285809Sscottl  bit32                     sasAddressHi, sasAddressLo;
4513285809Sscottl  dmDeviceData_t            *oneDeviceData = agNULL;
4514285809Sscottl  dmSASSubID_t              dmSASSubID;
4515285809Sscottl
4516285809Sscottl  DM_DBG3(("dmRegisterDevice: start\n"));
4517285809Sscottl
4518285809Sscottl  onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
4519285809Sscottl  if (onePortContext == agNULL)
4520285809Sscottl  {
4521285809Sscottl    DM_DBG1(("dmRegisterDevice: onePortContext is NULL!!!\n"));
4522285809Sscottl    return DM_RC_FAILURE;
4523285809Sscottl  }
4524285809Sscottl
4525285809Sscottl  if (onePortContext->valid == agFALSE)
4526285809Sscottl  {
4527285809Sscottl    DM_DBG1(("dmRegisterDevice: invalid port!!!\n"));
4528285809Sscottl    return DM_RC_FAILURE;
4529285809Sscottl  }
4530285809Sscottl
4531285809Sscottl  onePortContext->RegFailed = agFALSE;
4532285809Sscottl
4533285809Sscottl  /* tdssAddSASToSharedcontext() from ossaHwCB()
4534285809SscottlosGLOBAL void
4535285809SscottltdssAddSASToSharedcontext(
4536285809Sscottl                          tdsaPortContext_t    *tdsaPortContext_Instance,
4537285809Sscottl                          agsaRoot_t           *agRoot,
4538285809Sscottl                          agsaDevHandle_t      *agDevHandle,
4539285809Sscottl                          tdsaSASSubID_t       *agSASSubID,
4540285809Sscottl                          bit32                registered,
4541285809Sscottl                          bit8                 phyID,
4542285809Sscottl                          bit32                flag
4543285809Sscottl                          );
4544285809Sscottlfrom discovery
4545285809SscottlosGLOBAL tdsaDeviceData_t *
4546285809SscottltdssNewAddSASToSharedcontext(
4547285809Sscottl                                 agsaRoot_t           *agRoot,
4548285809Sscottl                                 tdsaPortContext_t    *onePortContext,
4549285809Sscottl                                 tdsaSASSubID_t       *agSASSubID,
4550285809Sscottl                                 tdsaDeviceData_t     *oneExpDeviceData,
4551285809Sscottl                                 bit8                 phyID
4552285809Sscottl                                 );
4553285809Sscottl
4554285809Sscottl  */
4555285809Sscottl  /* start here */
4556285809Sscottl  dmSASSubID.sasAddressHi = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressHi);
4557285809Sscottl  dmSASSubID.sasAddressLo = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressLo);
4558285809Sscottl  dmSASSubID.initiator_ssp_stp_smp = dmDeviceInfo->initiator_ssp_stp_smp;
4559285809Sscottl  dmSASSubID.target_ssp_stp_smp = dmDeviceInfo->target_ssp_stp_smp;
4560285809Sscottl
4561285809Sscottl  oneDeviceData = dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, agNULL, 0xFF);
4562285809Sscottl  if (oneDeviceData == agNULL)
4563285809Sscottl  {
4564285809Sscottl    DM_DBG1(("dmRegisterDevice: oneDeviceData is NULL!!!\n"));
4565285809Sscottl    return DM_RC_FAILURE;
4566285809Sscottl  }
4567285809Sscottl  oneDeviceData->agDeviceInfo.devType_S_Rate = dmDeviceInfo->devType_S_Rate;
4568285809Sscottl  dm_memcpy(oneDeviceData->agDeviceInfo.sasAddressHi, dmDeviceInfo->sasAddressHi, 4);
4569285809Sscottl  dm_memcpy(oneDeviceData->agDeviceInfo.sasAddressLo, dmDeviceInfo->sasAddressLo, 4);
4570285809Sscottl  /* finds the type of expanders */
4571285809Sscottl  if (DEVINFO_GET_EXT_SMP(dmDeviceInfo))
4572285809Sscottl  {
4573285809Sscottl    if (DEVINFO_GET_EXT_EXPANDER_TYPE(dmDeviceInfo) == SAS_EDGE_EXPANDER_DEVICE)
4574285809Sscottl    {
4575285809Sscottl      oneDeviceData->SASSpecDeviceType = SAS_EDGE_EXPANDER_DEVICE;
4576285809Sscottl    }
4577285809Sscottl    else if (DEVINFO_GET_EXT_EXPANDER_TYPE(dmDeviceInfo) == SAS_FANOUT_EXPANDER_DEVICE)
4578285809Sscottl    {
4579285809Sscottl      oneDeviceData->SASSpecDeviceType = SAS_FANOUT_EXPANDER_DEVICE;
4580285809Sscottl    }
4581285809Sscottl    else
4582285809Sscottl    {
4583285809Sscottl      /* default */
4584285809Sscottl      DM_DBG4(("dmRegisterDevice: no expander type. default to edge expander\n"));
4585285809Sscottl      oneDeviceData->SASSpecDeviceType = SAS_EDGE_EXPANDER_DEVICE;
4586285809Sscottl    }
4587285809Sscottl  }
4588285809Sscottl
4589285809Sscottl  if (DEVINFO_GET_EXT_MCN(dmDeviceInfo) == 0xF)
4590285809Sscottl  {
4591285809Sscottl    DM_DBG1(("dmRegisterDevice: directly attached expander\n"));
4592285809Sscottl    oneDeviceData->directlyAttached = agTRUE;
4593285809Sscottl    oneDeviceData->dmDeviceInfo.ext =  (bit16)(oneDeviceData->dmDeviceInfo.ext | (0xF << 11));
4594285809Sscottl  }
4595285809Sscottl  else
4596285809Sscottl  {
4597285809Sscottl    DM_DBG1(("dmRegisterDevice: NOT directly attached expander\n"));
4598285809Sscottl    oneDeviceData->directlyAttached = agFALSE;
4599285809Sscottl  }
4600285809Sscottl
4601285809Sscottl  if (onePortContext->DiscoveryState == DM_DSTATE_NOT_STARTED)
4602285809Sscottl  {
4603285809Sscottl    DM_DBG3(("dmRegisterDevice: DM_DSTATE_NOT_STARTED\n"));
4604285809Sscottl    /* before the discovery is started */
4605285809Sscottl    oneExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, oneDeviceData);
4606285809Sscottl    if ( oneExpander != agNULL)
4607285809Sscottl    {
4608285809Sscottl      oneExpander->agDevHandle = agDevHandle;
4609285809Sscottl      /* update SAS address field */
4610285809Sscottl      oneExpander->dmDevice->SASAddressID.sasAddressHi = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressHi);
4611285809Sscottl      oneExpander->dmDevice->SASAddressID.sasAddressLo = DM_GET_SAS_ADDRESSLO(dmDeviceInfo->sasAddressLo);
4612285809Sscottl      DM_DBG3(("dmRegisterDevice: AddrHi 0x%08x AddrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi, oneExpander->dmDevice->SASAddressID.sasAddressLo));
4613285809Sscottl      dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander);
4614285809Sscottl    }
4615285809Sscottl    else
4616285809Sscottl    {
4617285809Sscottl      DM_DBG1(("dmRegisterDevice: failed to allocate expander !!!\n"));
4618285809Sscottl      /* remember that the registration failed so that a discovery can't be started */
4619285809Sscottl      onePortContext->RegFailed = agTRUE;
4620285809Sscottl      return DM_RC_FAILURE;
4621285809Sscottl    }
4622285809Sscottl  }
4623285809Sscottl  else
4624285809Sscottl  {
4625285809Sscottl    /*
4626285809Sscottl      the discovery has started. Alloc and add have been done.
4627285809Sscottl      find an expander using dmDeviceInfo, and update the expander's agDevHandle
4628285809Sscottl      call dmExpFind()
4629285809Sscottl    */
4630285809Sscottl    DM_DBG3(("dmRegisterDevice: NOT DM_DSTATE_NOT_STARTED\n"));
4631285809Sscottl    sasAddressHi = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressHi);
4632285809Sscottl    sasAddressLo = DM_GET_SAS_ADDRESSLO(dmDeviceInfo->sasAddressLo);
4633285809Sscottl    DM_DBG3(("dmRegisterDevice: AddrHi 0x%08x AddrLo 0x%08x\n", sasAddressHi, sasAddressLo));
4634285809Sscottl    oneExpander = dmExpFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo);
4635285809Sscottl    if ( oneExpander != agNULL)
4636285809Sscottl    {
4637285809Sscottl      oneExpander->agDevHandle = agDevHandle;
4638285809Sscottl    }
4639285809Sscottl    else
4640285809Sscottl    {
4641285809Sscottl      DM_DBG1(("dmRegisterDevice: not allowed case, wrong !!!\n"));
4642285809Sscottl      return DM_RC_FAILURE;
4643285809Sscottl    }
4644285809Sscottl  }
4645285809Sscottl
4646285809Sscottl  return DM_RC_SUCCESS;
4647285809Sscottl}
4648285809Sscottl
4649285809SscottlosGLOBAL dmExpander_t *
4650285809SscottldmDiscoveringExpanderAlloc(
4651285809Sscottl                           dmRoot_t                 *dmRoot,
4652285809Sscottl                           dmIntPortContext_t       *onePortContext,
4653285809Sscottl                           dmDeviceData_t           *oneDeviceData
4654285809Sscottl                          )
4655285809Sscottl{
4656285809Sscottl  dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
4657285809Sscottl  dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
4658285809Sscottl  dmExpander_t              *oneExpander = agNULL;
4659285809Sscottl  dmList_t                  *ExpanderList;
4660285809Sscottl
4661285809Sscottl  DM_DBG3(("dmDiscoveringExpanderAlloc: start\n"));
4662285809Sscottl  DM_DBG3(("dmDiscoveringExpanderAlloc: did %d\n", oneDeviceData->id));
4663285809Sscottl  DM_DBG3(("dmDiscoveringExpanderAlloc: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
4664285809Sscottl  DM_DBG3(("dmDiscoveringExpanderAlloc: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
4665285809Sscottl
4666285809Sscottl  if (onePortContext->valid == agFALSE)
4667285809Sscottl  {
4668285809Sscottl    DM_DBG1(("dmDiscoveringExpanderAlloc: invalid port!!!\n"));
4669285809Sscottl    return agNULL;
4670285809Sscottl  }
4671285809Sscottl
4672285809Sscottl
4673285809Sscottl  /* check exitence in dmAllShared->mainExpanderList */
4674285809Sscottl  oneExpander = dmExpMainListFind(dmRoot,
4675285809Sscottl                                  onePortContext,
4676285809Sscottl				  oneDeviceData->SASAddressID.sasAddressHi,
4677285809Sscottl				  oneDeviceData->SASAddressID.sasAddressLo);
4678285809Sscottl
4679285809Sscottl  if (oneExpander == agNULL)
4680285809Sscottl  {
4681285809Sscottl    tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
4682285809Sscottl    if (DMLIST_EMPTY(&(dmAllShared->freeExpanderList)))
4683285809Sscottl    {
4684285809Sscottl      DM_DBG1(("dmDiscoveringExpanderAlloc: no free expanders pid %d!!!\n", onePortContext->id));
4685285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4686285809Sscottl      return agNULL;
4687285809Sscottl    }
4688285809Sscottl    else
4689285809Sscottl    {
4690285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4691285809Sscottl    }
4692285809Sscottl
4693285809Sscottl    tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
4694285809Sscottl    DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(dmAllShared->freeExpanderList));
4695285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4696285809Sscottl
4697285809Sscottl    oneExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
4698285809Sscottl  }
4699285809Sscottl
4700285809Sscottl  if (oneExpander != agNULL)
4701285809Sscottl  {
4702285809Sscottl    DM_DBG1(("dmDiscoveringExpanderAlloc: pid %d exp id %d \n", onePortContext->id, oneExpander->id));
4703285809Sscottl
4704285809Sscottl    tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
4705285809Sscottl    DMLIST_DEQUEUE_THIS(&(oneExpander->linkNode));
4706285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4707285809Sscottl
4708285809Sscottl    oneExpander->dmDevice = oneDeviceData;
4709285809Sscottl    oneExpander->dmUpStreamExpander = agNULL;
4710285809Sscottl    oneExpander->dmCurrentDownStreamExpander = agNULL;
4711285809Sscottl    oneExpander->dmReturnginExpander = agNULL;
4712285809Sscottl    oneExpander->hasUpStreamDevice = agFALSE;
4713285809Sscottl    oneExpander->numOfUpStreamPhys = 0;
4714285809Sscottl    oneExpander->currentUpStreamPhyIndex = 0;
4715285809Sscottl    oneExpander->discoveringPhyId = 0;
4716285809Sscottl    oneExpander->underDiscovering = agFALSE;
4717285809Sscottl    dm_memset( &(oneExpander->currentIndex), 0, sizeof(oneExpander->currentIndex));
4718285809Sscottl
4719285809Sscottl    oneDeviceData->dmExpander = oneExpander;
4720285809Sscottl    DM_DBG3(("dmDiscoveringExpanderAlloc: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
4721285809Sscottl    DM_DBG3(("dmDiscoveringExpanderAlloc: oneExpander %p did %d\n",  oneDeviceData->dmExpander,  oneDeviceData->dmExpander->id));
4722285809Sscottl
4723285809Sscottl  }
4724285809Sscottl
4725285809Sscottl  return oneExpander;
4726285809Sscottl}
4727285809Sscottl
4728285809SscottlosGLOBAL void
4729285809SscottldmDiscoveringExpanderAdd(
4730285809Sscottl                         dmRoot_t                 *dmRoot,
4731285809Sscottl                         dmIntPortContext_t       *onePortContext,
4732285809Sscottl                         dmExpander_t             *oneExpander
4733285809Sscottl                        )
4734285809Sscottl{
4735285809Sscottl  DM_DBG3(("dmDiscoveringExpanderAdd: start\n"));
4736285809Sscottl  DM_DBG3(("dmDiscoveringExpanderAdd: expander id %d\n", oneExpander->id));
4737285809Sscottl  DM_DBG3(("dmDiscoveringExpanderAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4738285809Sscottl  DM_DBG3(("dmDiscoveringExpanderAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
4739285809Sscottl
4740285809Sscottl  if (onePortContext->valid == agFALSE)
4741285809Sscottl  {
4742285809Sscottl    DM_DBG1(("dmDiscoveringExpanderAdd: invalid port!!!\n"));
4743285809Sscottl    return;
4744285809Sscottl  }
4745285809Sscottl  if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
4746285809Sscottl  {
4747285809Sscottl    DM_DBG3(("dmDiscoveringExpanderAdd: UPSTREAM\n"));
4748285809Sscottl  }
4749285809Sscottl  else if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
4750285809Sscottl  {
4751285809Sscottl    DM_DBG3(("dmDiscoveringExpanderAdd: DOWNSTREAM\n"));
4752285809Sscottl  }
4753285809Sscottl  else
4754285809Sscottl  {
4755285809Sscottl    DM_DBG3(("dmDiscoveringExpanderAdd: status %d\n", onePortContext->discovery.status));
4756285809Sscottl  }
4757285809Sscottl
4758285809Sscottl  if ( oneExpander->underDiscovering == agFALSE)
4759285809Sscottl  {
4760285809Sscottl    DM_DBG3(("dmDiscoveringExpanderAdd: ADDED \n"));
4761285809Sscottl
4762285809Sscottl    oneExpander->underDiscovering = agTRUE;
4763285809Sscottl    tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
4764285809Sscottl    DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));
4765285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4766285809Sscottl  }
4767285809Sscottl
4768285809Sscottl  return;
4769285809Sscottl}
4770285809Sscottl
4771285809SscottlosGLOBAL dmExpander_t *
4772285809SscottldmFindConfigurableExp(
4773285809Sscottl                      dmRoot_t                  *dmRoot,
4774285809Sscottl                      dmIntPortContext_t        *onePortContext,
4775285809Sscottl                      dmExpander_t              *oneExpander
4776285809Sscottl                     )
4777285809Sscottl{
4778285809Sscottl  dmExpander_t            *tempExpander;
4779285809Sscottl  dmIntPortContext_t      *tmpOnePortContext = onePortContext;
4780285809Sscottl  dmExpander_t            *ret = agNULL;
4781285809Sscottl  DM_DBG3(("dmFindConfigurableExp: start\n"));
4782285809Sscottl
4783285809Sscottl  if (oneExpander == agNULL)
4784285809Sscottl  {
4785285809Sscottl    DM_DBG3(("dmFindConfigurableExp: NULL expander\n"));
4786285809Sscottl    return agNULL;
4787285809Sscottl  }
4788285809Sscottl
4789285809Sscottl  DM_DBG3(("dmFindConfigurableExp: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4790285809Sscottl  DM_DBG3(("dmFindConfigurableExp: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
4791285809Sscottl
4792285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
4793285809Sscottl  if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
4794285809Sscottl  {
4795285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4796285809Sscottl    DM_DBG3(("dmFindConfigurableExp: empty UpdiscoveringExpanderList\n"));
4797285809Sscottl    return agNULL;
4798285809Sscottl  }
4799285809Sscottl  else
4800285809Sscottl  {
4801285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
4802285809Sscottl  }
4803285809Sscottl  tempExpander = oneExpander->dmUpStreamExpander;
4804285809Sscottl  while (tempExpander)
4805285809Sscottl  {
4806285809Sscottl    DM_DBG3(("dmFindConfigurableExp: loop exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
4807285809Sscottl    DM_DBG3(("dmFindConfigurableExp: loop exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
4808285809Sscottl    if (tempExpander->configRouteTable)
4809285809Sscottl    {
4810285809Sscottl      DM_DBG3(("dmFindConfigurableExp: found configurable expander\n"));
4811285809Sscottl      ret = tempExpander;
4812285809Sscottl      break;
4813285809Sscottl    }
4814285809Sscottl   tempExpander = tempExpander->dmUpStreamExpander;
4815285809Sscottl  }
4816285809Sscottl
4817285809Sscottl  return ret;
4818285809Sscottl}
4819285809Sscottl
4820285809SscottlosGLOBAL bit32
4821285809SscottldmDuplicateConfigSASAddr(
4822285809Sscottl                         dmRoot_t                 *dmRoot,
4823285809Sscottl                         dmExpander_t             *oneExpander,
4824285809Sscottl                         bit32                    configSASAddressHi,
4825285809Sscottl                         bit32                    configSASAddressLo
4826285809Sscottl                        )
4827285809Sscottl{
4828285809Sscottl  bit32 i;
4829285809Sscottl  bit32 ret = agFALSE;
4830285809Sscottl  DM_DBG3(("dmDuplicateConfigSASAddr: start\n"));
4831285809Sscottl
4832285809Sscottl  if (oneExpander == agNULL)
4833285809Sscottl  {
4834285809Sscottl    DM_DBG3(("dmDuplicateConfigSASAddr: NULL expander\n"));
4835285809Sscottl    return agTRUE;
4836285809Sscottl  }
4837285809Sscottl
4838285809Sscottl  if (oneExpander->dmDevice->SASAddressID.sasAddressHi == configSASAddressHi &&
4839285809Sscottl      oneExpander->dmDevice->SASAddressID.sasAddressLo == configSASAddressLo
4840285809Sscottl     )
4841285809Sscottl  {
4842285809Sscottl    DM_DBG3(("dmDuplicateConfigSASAddr: unnecessary\n"));
4843285809Sscottl    return agTRUE;
4844285809Sscottl  }
4845285809Sscottl
4846285809Sscottl  DM_DBG3(("dmDuplicateConfigSASAddr: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4847285809Sscottl  DM_DBG3(("dmDuplicateConfigSASAddr: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
4848285809Sscottl  DM_DBG3(("dmDuplicateConfigSASAddr: configsasAddressHi 0x%08x\n", configSASAddressHi));
4849285809Sscottl  DM_DBG3(("dmDuplicateConfigSASAddr: configsasAddressLo 0x%08x\n", configSASAddressLo));
4850285809Sscottl  DM_DBG3(("dmDuplicateConfigSASAddr: configSASAddrTableIndex %d\n", oneExpander->configSASAddrTableIndex));
4851285809Sscottl  for(i=0;i<oneExpander->configSASAddrTableIndex;i++)
4852285809Sscottl  {
4853285809Sscottl    if (oneExpander->configSASAddressHiTable[i] == configSASAddressHi &&
4854285809Sscottl        oneExpander->configSASAddressLoTable[i] == configSASAddressLo
4855285809Sscottl        )
4856285809Sscottl    {
4857285809Sscottl      DM_DBG3(("dmDuplicateConfigSASAddr: FOUND\n"));
4858285809Sscottl      ret = agTRUE;
4859285809Sscottl      break;
4860285809Sscottl    }
4861285809Sscottl  }
4862285809Sscottl  /* new one; let's add it */
4863285809Sscottl  if (ret == agFALSE)
4864285809Sscottl  {
4865285809Sscottl    DM_DBG3(("dmDuplicateConfigSASAddr: adding configSAS Addr\n"));
4866285809Sscottl    DM_DBG3(("dmDuplicateConfigSASAddr: configSASAddrTableIndex %d\n", oneExpander->configSASAddrTableIndex));
4867285809Sscottl    oneExpander->configSASAddressHiTable[oneExpander->configSASAddrTableIndex] = configSASAddressHi;
4868285809Sscottl    oneExpander->configSASAddressLoTable[oneExpander->configSASAddrTableIndex] = configSASAddressLo;
4869285809Sscottl    oneExpander->configSASAddrTableIndex++;
4870285809Sscottl  }
4871285809Sscottl
4872285809Sscottl  return ret;
4873285809Sscottl}
4874285809Sscottl
4875285809SscottlosGLOBAL bit16
4876285809SscottldmFindCurrentDownStreamPhyIndex(
4877285809Sscottl                                dmRoot_t          *dmRoot,
4878285809Sscottl                                dmExpander_t      *oneExpander
4879285809Sscottl                                )
4880285809Sscottl{
4881285809Sscottl  dmExpander_t       *DownStreamExpander;
4882285809Sscottl  bit16              index = 0;
4883285809Sscottl  bit16              i;
4884285809Sscottl  bit8               phyId = 0;
4885285809Sscottl
4886285809Sscottl  DM_DBG3(("dmFindCurrentDownStreamPhyIndex: start\n"));
4887285809Sscottl
4888285809Sscottl  if (oneExpander == agNULL)
4889285809Sscottl  {
4890285809Sscottl    DM_DBG1(("dmFindCurrentDownStreamPhyIndex: wrong, oneExpander is NULL!!!\n"));
4891285809Sscottl    return 0;
4892285809Sscottl  }
4893285809Sscottl
4894285809Sscottl  DownStreamExpander = oneExpander->dmCurrentDownStreamExpander;
4895285809Sscottl
4896285809Sscottl  if (DownStreamExpander == agNULL)
4897285809Sscottl  {
4898285809Sscottl    DM_DBG1(("dmFindCurrentDownStreamPhyIndex: wrong, DownStreamExpander is NULL!!!\n"));
4899285809Sscottl    return 0;
4900285809Sscottl  }
4901285809Sscottl
4902285809Sscottl  DM_DBG3(("dmFindCurrentDownStreamPhyIndex: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4903285809Sscottl  DM_DBG3(("dmFindCurrentDownStreamPhyIndex: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
4904285809Sscottl  DM_DBG3(("dmFindCurrentDownStreamPhyIndex: downstream exp addrHi 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressHi));
4905285809Sscottl  DM_DBG3(("dmFindCurrentDownStreamPhyIndex: downstream exp addrLo 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressLo));
4906285809Sscottl  DM_DBG3(("dmFindCurrentDownStreamPhyIndex: numOfDownStreamPhys %d\n", oneExpander->numOfDownStreamPhys));
4907285809Sscottl
4908285809Sscottl  phyId = DownStreamExpander->upStreamPhys[0];
4909285809Sscottl
4910285809Sscottl  DM_DBG3(("dmFindCurrentDownStreamPhyIndex: phyId %d\n", phyId));
4911285809Sscottl
4912285809Sscottl  for (i=0; i<oneExpander->numOfDownStreamPhys;i++)
4913285809Sscottl  {
4914285809Sscottl    if (oneExpander->downStreamPhys[i] == phyId)
4915285809Sscottl    {
4916285809Sscottl      index = i;
4917285809Sscottl      break;
4918285809Sscottl    }
4919285809Sscottl  }
4920285809Sscottl  DM_DBG3(("dmFindCurrentDownStreamPhyIndex: index %d\n", index));
4921285809Sscottl  return index;
4922285809Sscottl}
4923285809Sscottl
4924285809SscottlosGLOBAL bit32
4925285809SscottldmFindDiscoveringExpander(
4926285809Sscottl                          dmRoot_t                  *dmRoot,
4927285809Sscottl                          dmIntPortContext_t        *onePortContext,
4928285809Sscottl                          dmExpander_t              *oneExpander
4929285809Sscottl                         )
4930285809Sscottl{
4931285809Sscottl  dmList_t                *ExpanderList;
4932285809Sscottl  dmExpander_t            *tempExpander;
4933285809Sscottl  dmIntPortContext_t      *tmpOnePortContext = onePortContext;
4934285809Sscottl  bit32                   ret = agFALSE;
4935285809Sscottl
4936285809Sscottl
4937285809Sscottl  DM_DBG3(("dmFindDiscoveringExpander: start\n"));
4938285809Sscottl
4939285809Sscottl  DM_DBG3(("dmFindDiscoveringExpander: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4940285809Sscottl  DM_DBG3(("dmFindDiscoveringExpander: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
4941285809Sscottl
4942285809Sscottl  if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
4943285809Sscottl  {
4944285809Sscottl    DM_DBG3(("dmFindDiscoveringExpander: empty discoveringExpanderList\n"));
4945285809Sscottl    return ret;
4946285809Sscottl  }
4947285809Sscottl  ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
4948285809Sscottl  while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
4949285809Sscottl  {
4950285809Sscottl    tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
4951285809Sscottl    if (tempExpander == oneExpander)
4952285809Sscottl    {
4953285809Sscottl      if (tempExpander != agNULL)
4954285809Sscottl      {
4955285809Sscottl        DM_DBG3(("dmFindDiscoveringExpander: match, expander id %d\n", tempExpander->id));
4956285809Sscottl        DM_DBG3(("dmFindDiscoveringExpander: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
4957285809Sscottl        DM_DBG3(("dmFindDiscoveringExpander: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
4958285809Sscottl      }
4959285809Sscottl      ret = agTRUE;
4960285809Sscottl      break;
4961285809Sscottl    }
4962285809Sscottl
4963285809Sscottl    ExpanderList = ExpanderList->flink;
4964285809Sscottl  }
4965285809Sscottl
4966285809Sscottl
4967285809Sscottl  return ret;
4968285809Sscottl}
4969285809Sscottl
4970285809Sscottl
4971285809SscottlosGLOBAL void
4972285809SscottldmDiscoveringExpanderRemove(
4973285809Sscottl                            dmRoot_t                 *dmRoot,
4974285809Sscottl                            dmIntPortContext_t       *onePortContext,
4975285809Sscottl                            dmExpander_t             *oneExpander
4976285809Sscottl                           )
4977285809Sscottl{
4978285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
4979285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
4980285809Sscottl
4981285809Sscottl  DM_DBG3(("dmDiscoveringExpanderRemove: start\n"));
4982285809Sscottl  DM_DBG3(("dmDiscoveringExpanderRemove: expander id %d\n", oneExpander->id));
4983285809Sscottl  DM_DBG3(("dmDiscoveringExpanderRemove: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
4984285809Sscottl  DM_DBG3(("dmDiscoveringExpanderRemove: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
4985285809Sscottl
4986285809Sscottl  DM_DBG3(("dmDiscoveringExpanderRemove: BEFORE\n"));
4987285809Sscottl  dmDumpAllExp(dmRoot, onePortContext, oneExpander);
4988285809Sscottl  dmDumpAllUpExp(dmRoot, onePortContext, oneExpander);
4989285809Sscottl  dmDumpAllFreeExp(dmRoot);
4990285809Sscottl
4991285809Sscottl  // if is temporary till smp problem is fixed
4992285809Sscottl  if (dmFindDiscoveringExpander(dmRoot, onePortContext, oneExpander) == agTRUE)
4993285809Sscottl  {
4994285809Sscottl    DM_DBG3(("dmDiscoveringExpanderRemove: oneDeviceData %p did %d\n", oneExpander->dmDevice, oneExpander->dmDevice->id));
4995285809Sscottl    DM_DBG3(("dmDiscoveringExpanderRemove: oneExpander %p did %d\n", oneExpander, oneExpander->id));
4996285809Sscottl
4997285809Sscottl    if (oneExpander != oneExpander->dmDevice->dmExpander)
4998285809Sscottl    {
4999285809Sscottl      DM_DBG3(("dmDiscoveringExpanderRemove: before !!! wrong !!!\n"));
5000285809Sscottl    }
5001285809Sscottl    oneExpander->underDiscovering = agFALSE;
5002285809Sscottl    oneExpander->discoveringPhyId = 0;
5003285809Sscottl    tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5004285809Sscottl    DMLIST_DEQUEUE_THIS(&(oneExpander->linkNode));
5005285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5006285809Sscottl
5007285809Sscottl    if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
5008285809Sscottl    {
5009285809Sscottl      DM_DBG3(("dmDiscoveringExpanderRemove: DISCOVERY_UP_STREAM\n"));
5010285809Sscottl      tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5011285809Sscottl      DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->upNode), &(onePortContext->discovery.UpdiscoveringExpanderList));
5012285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5013285809Sscottl      onePortContext->discovery.NumOfUpExp++;
5014285809Sscottl    }
5015285809Sscottl    else
5016285809Sscottl    {
5017285809Sscottl      DM_DBG3(("dmDiscoveringExpanderRemove: Status %d\n", onePortContext->discovery.status));
5018285809Sscottl      tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5019285809Sscottl      DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(dmAllShared->mainExpanderList));
5020285809Sscottl//      DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(dmAllShared->freeExpanderList));
5021285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5022285809Sscottl    }
5023285809Sscottl    // error checking
5024285809Sscottl    if (oneExpander != oneExpander->dmDevice->dmExpander)
5025285809Sscottl    {
5026285809Sscottl      DM_DBG3(("dmDiscoveringExpanderRemove: after !!! wrong !!!\n"));
5027285809Sscottl    }
5028285809Sscottl
5029285809Sscottl  } //end temp if
5030285809Sscottl  else
5031285809Sscottl  {
5032285809Sscottl    DM_DBG1(("dmDiscoveringExpanderRemove: !!! problem !!!\n"));
5033285809Sscottl  }
5034285809Sscottl
5035285809Sscottl  DM_DBG3(("dmDiscoveringExpanderRemove: AFTER\n"));
5036285809Sscottl
5037285809Sscottl  dmDumpAllExp(dmRoot, onePortContext, oneExpander);
5038285809Sscottl  dmDumpAllUpExp(dmRoot, onePortContext, oneExpander);
5039285809Sscottl  dmDumpAllFreeExp(dmRoot);
5040285809Sscottl
5041285809Sscottl  return;
5042285809Sscottl}
5043285809Sscottl
5044285809Sscottl/*
5045285809Sscottl  returns an expander with sasAddrLo, sasAddrHi from dmAllShared->mainExpanderList
5046285809Sscottl*/
5047285809SscottlosGLOBAL dmExpander_t *
5048285809SscottldmExpMainListFind(
5049285809Sscottl                  dmRoot_t            *dmRoot,
5050285809Sscottl                  dmIntPortContext_t  *onePortContext,
5051285809Sscottl                  bit32               sasAddrHi,
5052285809Sscottl                  bit32               sasAddrLo
5053285809Sscottl                 )
5054285809Sscottl{
5055285809Sscottl  dmIntRoot_t        *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5056285809Sscottl  dmIntContext_t     *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5057285809Sscottl  dmList_t           *ExpanderList;
5058285809Sscottl  dmExpander_t       *tempExpander;
5059285809Sscottl
5060285809Sscottl  DM_DBG3(("dmExpMainListFind: start\n"));
5061285809Sscottl
5062285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5063285809Sscottl  if (DMLIST_EMPTY(&(dmAllShared->mainExpanderList)))
5064285809Sscottl  {
5065285809Sscottl    DM_DBG1(("dmExpMainListFind: empty mainExpanderList\n"));
5066285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5067285809Sscottl    return agNULL;
5068285809Sscottl  }
5069285809Sscottl  else
5070285809Sscottl  {
5071285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5072285809Sscottl  }
5073285809Sscottl  ExpanderList = dmAllShared->mainExpanderList.flink;
5074285809Sscottl  while (ExpanderList != &(dmAllShared->mainExpanderList))
5075285809Sscottl  {
5076285809Sscottl    tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
5077285809Sscottl    if (tempExpander == agNULL)
5078285809Sscottl    {
5079285809Sscottl      DM_DBG1(("dmExpMainListFind: tempExpander is NULL!!!\n"));
5080285809Sscottl      return agNULL;
5081285809Sscottl    }
5082285809Sscottl    DM_DBG3(("dmExpMainListFind: expander id %d\n", tempExpander->id));
5083285809Sscottl    DM_DBG3(("dmExpMainListFind: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
5084285809Sscottl    DM_DBG3(("dmExpMainListFind: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
5085285809Sscottl    if ((tempExpander->dmDevice->SASAddressID.sasAddressHi == sasAddrHi) &&
5086285809Sscottl        (tempExpander->dmDevice->SASAddressID.sasAddressLo == sasAddrLo) &&
5087285809Sscottl        (tempExpander->dmDevice->dmPortContext == onePortContext)
5088285809Sscottl       )
5089285809Sscottl    {
5090285809Sscottl      DM_DBG3(("dmExpMainListFind: found expander id %d\n", tempExpander->id));
5091285809Sscottl      DM_DBG3(("dmExpMainListFind: found exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
5092285809Sscottl      DM_DBG3(("dmExpMainListFind: found exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
5093285809Sscottl      return tempExpander;
5094285809Sscottl    }
5095285809Sscottl    ExpanderList = ExpanderList->flink;
5096285809Sscottl  }
5097285809Sscottl  return agNULL;
5098285809Sscottl
5099285809Sscottl}
5100285809Sscottl
5101285809Sscottl/*
5102285809Sscottl  returns an expander with sasAddrLo, sasAddrHi from discoveringExpanderList
5103285809Sscottl*/
5104285809SscottlosGLOBAL dmExpander_t *
5105285809SscottldmExpFind(
5106285809Sscottl          dmRoot_t            *dmRoot,
5107285809Sscottl          dmIntPortContext_t  *onePortContext,
5108285809Sscottl          bit32               sasAddrHi,
5109285809Sscottl          bit32               sasAddrLo
5110285809Sscottl         )
5111285809Sscottl{
5112285809Sscottl  dmList_t           *ExpanderList;
5113285809Sscottl  dmExpander_t       *tempExpander;
5114285809Sscottl  dmIntPortContext_t *tmpOnePortContext = onePortContext;
5115285809Sscottl  DM_DBG3(("dmExpFind: start\n"));
5116285809Sscottl
5117285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5118285809Sscottl  if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
5119285809Sscottl  {
5120285809Sscottl    DM_DBG3(("dmExpFind tdsaDumpAllExp: empty discoveringExpanderList\n"));
5121285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5122285809Sscottl    return agNULL;
5123285809Sscottl  }
5124285809Sscottl  else
5125285809Sscottl  {
5126285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5127285809Sscottl  }
5128285809Sscottl  ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
5129285809Sscottl  while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
5130285809Sscottl  {
5131285809Sscottl    tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
5132285809Sscottl    if (tempExpander == agNULL)
5133285809Sscottl    {
5134285809Sscottl      DM_DBG1(("dmExpFind: tempExpander is NULL!!!\n"));
5135285809Sscottl      return agNULL;
5136285809Sscottl    }
5137285809Sscottl    DM_DBG3(("dmExpFind: expander id %d\n", tempExpander->id));
5138285809Sscottl    DM_DBG3(("dmExpFind: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
5139285809Sscottl    DM_DBG3(("dmExpFind: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
5140285809Sscottl    if ((tempExpander->dmDevice->SASAddressID.sasAddressHi == sasAddrHi) &&
5141285809Sscottl        (tempExpander->dmDevice->SASAddressID.sasAddressLo == sasAddrLo) &&
5142285809Sscottl        (tempExpander->dmDevice->dmPortContext == onePortContext)
5143285809Sscottl       )
5144285809Sscottl    {
5145285809Sscottl      DM_DBG3(("dmExpFind: found\n"));
5146285809Sscottl      return tempExpander;
5147285809Sscottl    }
5148285809Sscottl    ExpanderList = ExpanderList->flink;
5149285809Sscottl  }
5150285809Sscottl  return agNULL;
5151285809Sscottl}
5152285809Sscottl
5153285809SscottlosGLOBAL bit32
5154285809SscottldmDiscoverCheck(
5155285809Sscottl                dmRoot_t 	    	*dmRoot,
5156285809Sscottl                dmIntPortContext_t      *onePortContext
5157285809Sscottl                )
5158285809Sscottl{
5159285809Sscottl  DM_DBG3(("dmDiscoverCheck: start\n"));
5160285809Sscottl
5161285809Sscottl  if (onePortContext == agNULL)
5162285809Sscottl  {
5163285809Sscottl    DM_DBG1(("dmDiscoverCheck: onePortContext is NULL!!!\n"));
5164285809Sscottl    return agTRUE;
5165285809Sscottl  }
5166285809Sscottl  if (onePortContext->valid == agFALSE)
5167285809Sscottl  {
5168285809Sscottl    DM_DBG1(("dmDiscoverCheck: invalid port!!!\n"));
5169285809Sscottl    return agTRUE;
5170285809Sscottl  }
5171285809Sscottl  if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED ||
5172285809Sscottl      onePortContext->discovery.status == DISCOVERY_SAS_DONE
5173285809Sscottl     )
5174285809Sscottl  {
5175285809Sscottl    DM_DBG1(("dmDiscoverCheck: aborted discovery!!!\n"));
5176285809Sscottl    tddmDiscoverCB(
5177285809Sscottl                   dmRoot,
5178285809Sscottl                   onePortContext->dmPortContext,
5179285809Sscottl                   dmDiscAborted
5180285809Sscottl	          );
5181285809Sscottl    return agTRUE;
5182285809Sscottl  }
5183285809Sscottl
5184285809Sscottl  return agFALSE;
5185285809Sscottl}
5186285809Sscottl
5187285809Sscottl/* ??? needs to handle pending SMPs
5188285809Sscottl   move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList
5189285809Sscottl*/
5190285809SscottlosGLOBAL void
5191285809SscottldmDiscoverAbort(
5192285809Sscottl                dmRoot_t 	    	*dmRoot,
5193285809Sscottl                dmIntPortContext_t      *onePortContext
5194285809Sscottl                )
5195285809Sscottl{
5196285809Sscottl  DM_DBG1(("dmDiscoverAbort: start\n"));
5197285809Sscottl
5198285809Sscottl  if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED ||
5199285809Sscottl      onePortContext->discovery.status == DISCOVERY_SAS_DONE)
5200285809Sscottl  {
5201285809Sscottl    DM_DBG1(("dmDiscoverAbort: not allowed case!!! onePortContext->DiscoveryState 0x%x onePortContext->discovery.status 0x%x\n",
5202285809Sscottl    onePortContext->DiscoveryState, onePortContext->discovery.status));
5203285809Sscottl    return;
5204285809Sscottl  }
5205285809Sscottl
5206285809Sscottl  onePortContext->DiscoveryState = DM_DSTATE_COMPLETED;
5207285809Sscottl  onePortContext->discovery.status = DISCOVERY_SAS_DONE;
5208285809Sscottl
5209285809Sscottl  /* move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList */
5210285809Sscottl  dmCleanAllExp(dmRoot, onePortContext);
5211285809Sscottl
5212285809Sscottl
5213285809Sscottl  return;
5214285809Sscottl
5215285809Sscottl
5216285809Sscottl}
5217285809Sscottl
5218285809Sscottl/* move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList */
5219285809SscottlosGLOBAL void
5220285809SscottldmCleanAllExp(
5221285809Sscottl              dmRoot_t                 *dmRoot,
5222285809Sscottl              dmIntPortContext_t       *onePortContext
5223285809Sscottl             )
5224285809Sscottl{
5225285809Sscottl  dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5226285809Sscottl  dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5227285809Sscottl  dmList_t                  *ExpanderList;
5228285809Sscottl  dmExpander_t              *tempExpander;
5229285809Sscottl  dmExpander_t              *oneExpander = agNULL;
5230285809Sscottl  dmIntPortContext_t        *tmpOnePortContext = onePortContext;
5231285809Sscottl
5232285809Sscottl  DM_DBG3(("dmCleanAllExp: start\n"));
5233285809Sscottl  DM_DBG3(("dmCleanAllExp: pid %d\n", onePortContext->id));
5234285809Sscottl
5235285809Sscottl  DM_DBG3(("dmCleanAllExp: before all clean up\n"));
5236285809Sscottl  dmDumpAllFreeExp(dmRoot);
5237285809Sscottl
5238285809Sscottl  /* clean up UpdiscoveringExpanderList*/
5239285809Sscottl  DM_DBG3(("dmCleanAllExp: clean discoveringExpanderList\n"));
5240285809Sscottl  if (!DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
5241285809Sscottl  {
5242285809Sscottl    ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
5243285809Sscottl    while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
5244285809Sscottl    {
5245285809Sscottl      tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
5246285809Sscottl      if (tempExpander == agNULL)
5247285809Sscottl      {
5248285809Sscottl        DM_DBG1(("dmCleanAllExp: tempExpander is NULL!!!\n"));
5249285809Sscottl        return;
5250285809Sscottl      }
5251285809Sscottl      DM_DBG3(("dmCleanAllExp: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
5252285809Sscottl      DM_DBG3(("dmCleanAllExp: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
5253285809Sscottl      DM_DBG3(("dmCleanAllExp: exp id %d\n", tempExpander->id));
5254285809Sscottl
5255285809Sscottl      oneExpander = dmExpMainListFind(dmRoot,
5256285809Sscottl                                      tmpOnePortContext,
5257285809Sscottl                                      tempExpander->dmDevice->SASAddressID.sasAddressHi,
5258285809Sscottl                                      tempExpander->dmDevice->SASAddressID.sasAddressLo);
5259285809Sscottl      if (oneExpander == agNULL)
5260285809Sscottl      {
5261285809Sscottl        DM_DBG3(("dmCleanAllExp: moving\n"));
5262285809Sscottl        DM_DBG3(("dmCleanAllExp: moving, exp id %d\n", tempExpander->id));
5263285809Sscottl        /* putting back to the free pool */
5264285809Sscottl        tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5265285809Sscottl        DMLIST_DEQUEUE_THIS(&(tempExpander->linkNode));
5266285809Sscottl//      DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->freeExpanderList));
5267285809Sscottl        DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->mainExpanderList));
5268285809Sscottl
5269285809Sscottl        if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
5270285809Sscottl        {
5271285809Sscottl          tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5272285809Sscottl          break;
5273285809Sscottl        }
5274285809Sscottl        else
5275285809Sscottl        {
5276285809Sscottl          tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5277285809Sscottl        }
5278285809Sscottl        ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
5279285809Sscottl      }
5280285809Sscottl      else
5281285809Sscottl      {
5282285809Sscottl        DM_DBG3(("dmCleanAllExp: in mainExpanderList; skippig\n"));
5283285809Sscottl        ExpanderList =  ExpanderList->flink;
5284285809Sscottl      }
5285285809Sscottl    }
5286285809Sscottl  }
5287285809Sscottl  else
5288285809Sscottl  {
5289285809Sscottl    DM_DBG3(("dmCleanAllExp: empty discoveringExpanderList\n"));
5290285809Sscottl  }
5291285809Sscottl
5292285809Sscottl  /* reset discoveringExpanderList */
5293285809Sscottl  DMLIST_INIT_HDR(&(tmpOnePortContext->discovery.discoveringExpanderList));
5294285809Sscottl
5295285809Sscottl  /* clean up UpdiscoveringExpanderList*/
5296285809Sscottl  DM_DBG3(("dmCleanAllExp: clean UpdiscoveringExpanderList\n"));
5297285809Sscottl  if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList)))
5298285809Sscottl  {
5299285809Sscottl    DM_DBG3(("dmCleanAllExp: empty UpdiscoveringExpanderList\n"));
5300285809Sscottl    return;
5301285809Sscottl  }
5302285809Sscottl  ExpanderList = tmpOnePortContext->discovery.UpdiscoveringExpanderList.flink;
5303285809Sscottl  while (ExpanderList != &(tmpOnePortContext->discovery.UpdiscoveringExpanderList))
5304285809Sscottl  {
5305285809Sscottl    tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, upNode, ExpanderList);
5306285809Sscottl    if (tempExpander == agNULL)
5307285809Sscottl    {
5308285809Sscottl      DM_DBG1(("dmCleanAllExp: tempExpander is NULL!!!\n"));
5309285809Sscottl      return;
5310285809Sscottl    }
5311285809Sscottl    DM_DBG3(("dmCleanAllExp: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
5312285809Sscottl    DM_DBG3(("dmCleanAllExp: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
5313285809Sscottl    DM_DBG3(("dmCleanAllExp: exp id %d\n", tempExpander->id));
5314285809Sscottl    oneExpander = dmExpMainListFind(dmRoot,
5315285809Sscottl                                    tmpOnePortContext,
5316285809Sscottl                                    tempExpander->dmDevice->SASAddressID.sasAddressHi,
5317285809Sscottl                                    tempExpander->dmDevice->SASAddressID.sasAddressLo);
5318285809Sscottl    if (oneExpander == agNULL)
5319285809Sscottl    {
5320285809Sscottl      DM_DBG3(("dmCleanAllExp: moving\n"));
5321285809Sscottl      DM_DBG3(("dmCleanAllExp: moving exp id %d\n", tempExpander->id));
5322285809Sscottl      tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
5323285809Sscottl      DMLIST_DEQUEUE_THIS(&(tempExpander->upNode));
5324285809Sscottl      DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->mainExpanderList));
5325285809Sscottl
5326285809Sscottl      if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList)))
5327285809Sscottl      {
5328285809Sscottl        tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5329285809Sscottl        break;
5330285809Sscottl      }
5331285809Sscottl      else
5332285809Sscottl      {
5333285809Sscottl        tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
5334285809Sscottl      }
5335285809Sscottl      ExpanderList = tmpOnePortContext->discovery.UpdiscoveringExpanderList.flink;
5336285809Sscottl    }
5337285809Sscottl    else
5338285809Sscottl    {
5339285809Sscottl      DM_DBG3(("dmCleanAllExp: in mainExpanderList; skippig\n"));
5340285809Sscottl      ExpanderList =  ExpanderList->flink;
5341285809Sscottl    }
5342285809Sscottl  }
5343285809Sscottl
5344285809Sscottl  /* reset UpdiscoveringExpanderList */
5345285809Sscottl  DMLIST_INIT_HDR(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList));
5346285809Sscottl
5347285809Sscottl  DM_DBG3(("dmCleanAllExp: after all clean up\n"));
5348285809Sscottl  dmDumpAllFreeExp(dmRoot);
5349285809Sscottl
5350285809Sscottl  return;
5351285809Sscottl}
5352285809Sscottl
5353285809SscottlosGLOBAL void
5354285809SscottldmInternalRemovals(
5355285809Sscottl                   dmRoot_t                 *dmRoot,
5356285809Sscottl                   dmIntPortContext_t       *onePortContext
5357285809Sscottl                   )
5358285809Sscottl{
5359285809Sscottl  dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5360285809Sscottl  dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5361285809Sscottl  dmDeviceData_t            *oneDeviceData = agNULL;
5362285809Sscottl  dmList_t                  *DeviceListList;
5363285809Sscottl
5364285809Sscottl
5365285809Sscottl  DM_DBG3(("dmInternalRemovals: start\n"));
5366285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
5367285809Sscottl  if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
5368285809Sscottl  {
5369285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5370285809Sscottl    DM_DBG3(("dmInternalRemovals: empty device list\n"));
5371285809Sscottl    return;
5372285809Sscottl  }
5373285809Sscottl  else
5374285809Sscottl  {
5375285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5376285809Sscottl  }
5377285809Sscottl
5378285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
5379285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
5380285809Sscottl  {
5381285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
5382285809Sscottl    if (oneDeviceData == agNULL)
5383285809Sscottl    {
5384285809Sscottl      DM_DBG1(("dmInternalRemovals: oneDeviceData is NULL!!!\n"));
5385285809Sscottl      return;
5386285809Sscottl    }
5387285809Sscottl    DM_DBG3(("dmInternalRemovals: loop did %d\n", oneDeviceData->id));
5388285809Sscottl    DM_DBG3(("dmInternalRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
5389285809Sscottl    DM_DBG3(("dmInternalRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
5390285809Sscottl    DM_DBG3(("dmInternalRemovals: valid %d\n", oneDeviceData->valid));
5391285809Sscottl    DM_DBG3(("dmInternalRemovals: valid2 %d\n", oneDeviceData->valid2));
5392285809Sscottl    DM_DBG3(("dmInternalRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
5393285809Sscottl    if ( oneDeviceData->dmPortContext == onePortContext)
5394285809Sscottl    {
5395285809Sscottl      DM_DBG3(("dmInternalRemovals: right portcontext pid %d\n", onePortContext->id));
5396285809Sscottl      if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START)
5397285809Sscottl      {
5398285809Sscottl        DM_DBG3(("dmInternalRemovals: incremental discovery\n"));
5399285809Sscottl        oneDeviceData->valid2 = agFALSE;
5400285809Sscottl      }
5401285809Sscottl      else
5402285809Sscottl      {
5403285809Sscottl        DM_DBG3(("dmInternalRemovals: full discovery\n"));
5404285809Sscottl        oneDeviceData->valid = agFALSE;
5405285809Sscottl      }
5406285809Sscottl      DeviceListList = DeviceListList->flink;
5407285809Sscottl    }
5408285809Sscottl    else
5409285809Sscottl    {
5410285809Sscottl      if (oneDeviceData->dmPortContext != agNULL)
5411285809Sscottl      {
5412285809Sscottl        DM_DBG3(("dmInternalRemovals: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id));
5413285809Sscottl      }
5414285809Sscottl      else
5415285809Sscottl      {
5416285809Sscottl        DM_DBG3(("dmInternalRemovals: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
5417285809Sscottl      }
5418285809Sscottl      DeviceListList = DeviceListList->flink;
5419285809Sscottl    }
5420285809Sscottl  }
5421285809Sscottl
5422285809Sscottl
5423285809Sscottl  return;
5424285809Sscottl}
5425285809Sscottl
5426285809SscottlosGLOBAL void
5427285809SscottldmDiscoveryResetProcessed(
5428285809Sscottl                          dmRoot_t                 *dmRoot,
5429285809Sscottl                          dmIntPortContext_t       *onePortContext
5430285809Sscottl                         )
5431285809Sscottl{
5432285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5433285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5434285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
5435285809Sscottl  dmList_t          *DeviceListList;
5436285809Sscottl
5437285809Sscottl  DM_DBG3(("dmDiscoveryResetProcessed: start\n"));
5438285809Sscottl
5439285809Sscottl  /* reinitialize the device data belonging to this portcontext */
5440285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
5441285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
5442285809Sscottl  {
5443285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
5444285809Sscottl    if (oneDeviceData == agNULL)
5445285809Sscottl    {
5446285809Sscottl      DM_DBG1(("dmDiscoveryResetProcessed: oneDeviceData is NULL!!!\n"));
5447285809Sscottl      return;
5448285809Sscottl    }
5449285809Sscottl    DM_DBG3(("dmDiscoveryResetProcessed: loop did %d\n", oneDeviceData->id));
5450285809Sscottl    if (oneDeviceData->dmPortContext == onePortContext)
5451285809Sscottl    {
5452285809Sscottl      DM_DBG3(("dmDiscoveryResetProcessed: resetting procssed flag\n"));
5453285809Sscottl      oneDeviceData->processed = agFALSE;
5454285809Sscottl    }
5455285809Sscottl    DeviceListList = DeviceListList->flink;
5456285809Sscottl  }
5457285809Sscottl
5458285809Sscottl  return;
5459285809Sscottl}
5460285809Sscottl
5461285809Sscottl/*
5462285809Sscottl  calls
5463285809SscottlosGLOBAL void
5464285809SscottltddmDiscoverCB(
5465285809Sscottl               dmRoot_t 		*dmRoot,
5466285809Sscottl               dmPortContext_t		*dmPortContext,
5467285809Sscottl               bit32			eventStatus
5468285809Sscottl              )
5469285809Sscottl
5470285809Sscottl*/
5471285809SscottlosGLOBAL void
5472285809SscottldmDiscoverDone(
5473285809Sscottl               dmRoot_t                 *dmRoot,
5474285809Sscottl               dmIntPortContext_t       *onePortContext,
5475285809Sscottl               bit32                    flag
5476285809Sscottl              )
5477285809Sscottl{
5478285809Sscottl
5479285809Sscottl  DM_DBG3(("dmDiscoverDone: start\n"));
5480285809Sscottl  DM_DBG3(("dmDiscoverDone: pid %d\n", onePortContext->id));
5481285809Sscottl
5482285809Sscottl  /* Set discovery status */
5483285809Sscottl  onePortContext->discovery.status = DISCOVERY_SAS_DONE;
5484285809Sscottl
5485285809Sscottl
5486285809Sscottl  /* clean up expanders data strucures; move to free exp when device is cleaned */
5487285809Sscottl  dmCleanAllExp(dmRoot, onePortContext);
5488285809Sscottl
5489285809Sscottl  dmDumpAllMainExp(dmRoot, onePortContext);
5490285809Sscottl
5491285809Sscottl  dmDiscoveryResetProcessed(dmRoot, onePortContext);
5492285809Sscottl
5493285809Sscottl  dmDiscoveryDumpMCN(dmRoot, onePortContext);
5494285809Sscottl
5495285809Sscottl  if (onePortContext->discovery.SeenBC == agTRUE)
5496285809Sscottl  {
5497285809Sscottl    DM_DBG3(("dmDiscoverDone: broadcast change; discover again\n"));
5498285809Sscottl    dmDiscoveryResetMCN(dmRoot, onePortContext);
5499285809Sscottl
5500285809Sscottl    dmInternalRemovals(dmRoot, onePortContext);
5501285809Sscottl
5502285809Sscottl    /* processed broadcast change */
5503285809Sscottl    onePortContext->discovery.SeenBC = agFALSE;
5504285809Sscottl    if (onePortContext->discovery.ResetTriggerred == agTRUE)
5505285809Sscottl    {
5506285809Sscottl      DM_DBG3(("dmDiscoverDone: dmBCTimer\n"));
5507285809Sscottl      dmBCTimer(dmRoot, onePortContext);
5508285809Sscottl    }
5509285809Sscottl    else
5510285809Sscottl    {
5511285809Sscottl
5512285809Sscottl      dmIncrementalDiscover(dmRoot, onePortContext, agTRUE);
5513285809Sscottl    }
5514285809Sscottl  }
5515285809Sscottl  else
5516285809Sscottl  {
5517285809Sscottl    onePortContext->DiscoveryState = DM_DSTATE_COMPLETED;
5518285809Sscottl
5519285809Sscottl    if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START)
5520285809Sscottl    {
5521285809Sscottl      if (flag == DM_RC_SUCCESS)
5522285809Sscottl      {
5523285809Sscottl
5524285809Sscottl       dmResetReported(dmRoot,
5525285809Sscottl                       onePortContext
5526285809Sscottl                      );
5527285809Sscottl
5528285809Sscottl       dmDiscoveryReportMCN(dmRoot,
5529285809Sscottl                            onePortContext
5530285809Sscottl                           );
5531285809Sscottl
5532285809Sscottl
5533285809Sscottl       /* call tddmDiscoverCB() */
5534285809Sscottl       tddmDiscoverCB(
5535285809Sscottl                       dmRoot,
5536285809Sscottl                       onePortContext->dmPortContext,
5537285809Sscottl                       dmDiscCompleted
5538285809Sscottl                      );
5539285809Sscottl      }
5540285809Sscottl      else if (flag != DM_RC_SUCCESS || onePortContext->discovery.DeferredError == agTRUE)
5541285809Sscottl      {
5542285809Sscottl        onePortContext->DiscoveryState = DM_DSTATE_COMPLETED_WITH_FAILURE;
5543285809Sscottl        DM_DBG1(("dmDiscoverDone: Error; clean up!!!\n"));
5544285809Sscottl
5545285809Sscottl        dmDiscoveryInvalidateDevices(dmRoot,
5546285809Sscottl                                     onePortContext
5547285809Sscottl                                    );
5548285809Sscottl
5549285809Sscottl        tddmDiscoverCB(
5550285809Sscottl                       dmRoot,
5551285809Sscottl                       onePortContext->dmPortContext,
5552285809Sscottl                       dmDiscFailed
5553285809Sscottl                      );
5554285809Sscottl      }
5555285809Sscottl    }
5556285809Sscottl    else
5557285809Sscottl    {
5558285809Sscottl      if (flag == DM_RC_SUCCESS)
5559285809Sscottl      {
5560285809Sscottl        dmReportChanges(dmRoot,
5561285809Sscottl                        onePortContext
5562285809Sscottl                       );
5563285809Sscottl        dmDiscoveryReportMCN(dmRoot,
5564285809Sscottl                             onePortContext
5565285809Sscottl                            );
5566285809Sscottl        tddmDiscoverCB(
5567285809Sscottl                       dmRoot,
5568285809Sscottl                       onePortContext->dmPortContext,
5569285809Sscottl                       dmDiscCompleted
5570285809Sscottl                      );
5571285809Sscottl      }
5572285809Sscottl      else if (flag != DM_RC_SUCCESS || onePortContext->discovery.DeferredError == agTRUE)
5573285809Sscottl      {
5574285809Sscottl        onePortContext->DiscoveryState = DM_DSTATE_COMPLETED_WITH_FAILURE;
5575285809Sscottl        dmDiscoveryInvalidateDevices(dmRoot,
5576285809Sscottl                                     onePortContext
5577285809Sscottl                                    );
5578285809Sscottl
5579285809Sscottl        tddmDiscoverCB(
5580285809Sscottl                       dmRoot,
5581285809Sscottl                       onePortContext->dmPortContext,
5582285809Sscottl                       dmDiscFailed
5583285809Sscottl                      );
5584285809Sscottl      }
5585285809Sscottl    }
5586285809Sscottl  }
5587285809Sscottl  return;
5588285809Sscottl}
5589285809Sscottl
5590285809Sscottl/* called by dmDiscoveryErrorRemovals() or dmReportRemovals() on discovery failure */
5591285809SscottlosGLOBAL void
5592285809SscottldmSubReportRemovals(
5593285809Sscottl                   dmRoot_t                  *dmRoot,
5594285809Sscottl                   dmIntPortContext_t        *onePortContext,
5595285809Sscottl                   dmDeviceData_t            *oneDeviceData,
5596285809Sscottl                   bit32                     flag
5597285809Sscottl                  )
5598285809Sscottl{
5599285809Sscottl  dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
5600285809Sscottl  DM_DBG3(("dmSubReportRemovals: start\n"));
5601285809Sscottl
5602285809Sscottl  DM_DBG3(("dmSubReportRemovals: flag 0x%x\n", flag));
5603285809Sscottl  if (flag == dmDeviceRemoval)
5604285809Sscottl  {
5605285809Sscottl    oneDeviceData->registered = agFALSE;
5606285809Sscottl  }
5607285809Sscottl
5608285809Sscottl  if (oneDeviceData->ExpDevice != agNULL)
5609285809Sscottl  {
5610285809Sscottl    DM_DBG3(("dmSubReportRemovals: attached expander case\n"));
5611285809Sscottl    oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
5612285809Sscottl    tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, flag);
5613285809Sscottl  }
5614285809Sscottl  else
5615285809Sscottl  {
5616285809Sscottl    DM_DBG3(("dmSubReportRemovals: NO attached expander case\n"));
5617285809Sscottl    tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, flag);
5618285809Sscottl  }
5619285809Sscottl
5620285809Sscottl
5621285809Sscottl  /* this function is called at the end of discovery; reinitalizes oneDeviceData->reported */
5622285809Sscottl  oneDeviceData->reported = agFALSE;
5623285809Sscottl  return;
5624285809Sscottl}
5625285809Sscottl
5626285809Sscottl
5627285809Sscottl/* called by dmReportChanges() on discovery success */
5628285809SscottlosGLOBAL void
5629285809SscottldmSubReportChanges(
5630285809Sscottl                   dmRoot_t                  *dmRoot,
5631285809Sscottl                   dmIntPortContext_t        *onePortContext,
5632285809Sscottl		   dmDeviceData_t            *oneDeviceData,
5633285809Sscottl                   bit32                     flag
5634285809Sscottl                  )
5635285809Sscottl{
5636285809Sscottl  dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
5637285809Sscottl  DM_DBG3(("dmSubReportChanges: start\n"));
5638285809Sscottl
5639285809Sscottl  DM_DBG3(("dmSubReportChanges: flag 0x%x\n", flag));
5640285809Sscottl  if (flag == dmDeviceRemoval)
5641285809Sscottl  {
5642285809Sscottl    oneDeviceData->registered = agFALSE;
5643285809Sscottl  }
5644285809Sscottl  if (oneDeviceData->reported == agFALSE)
5645285809Sscottl  {
5646285809Sscottl    if (oneDeviceData->ExpDevice != agNULL)
5647285809Sscottl    {
5648285809Sscottl      DM_DBG3(("dmSubReportChanges: attached expander case\n"));
5649285809Sscottl      oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
5650285809Sscottl      tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, flag);
5651285809Sscottl    }
5652285809Sscottl    else
5653285809Sscottl    {
5654285809Sscottl      DM_DBG3(("dmSubReportChanges: NO attached expander case\n"));
5655285809Sscottl      tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, flag);
5656285809Sscottl    }
5657285809Sscottl  }
5658285809Sscottl  else
5659285809Sscottl  {
5660285809Sscottl    DM_DBG3(("dmSubReportChanges: skip; been reported\n"));
5661285809Sscottl  }
5662285809Sscottl
5663285809Sscottl
5664285809Sscottl  /* this function is called at the end of discovery; reinitalizes oneDeviceData->reported */
5665285809Sscottl  oneDeviceData->reported = agFALSE;
5666285809Sscottl  return;
5667285809Sscottl}
5668285809Sscottl
5669285809Sscottl/*
5670285809Sscottl should add or remove be reported per device???
5671285809Sscottl*/
5672285809SscottlosGLOBAL void
5673285809SscottldmReportChanges(
5674285809Sscottl                dmRoot_t                  *dmRoot,
5675285809Sscottl                dmIntPortContext_t        *onePortContext
5676285809Sscottl               )
5677285809Sscottl{
5678285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5679285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5680285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
5681285809Sscottl  dmList_t          *DeviceListList;
5682285809Sscottl  bit32             added = agFALSE, removed = agFALSE;
5683285809Sscottl//  dmDeviceData_t    *oneAttachedExpDeviceData = agNULL;
5684285809Sscottl
5685285809Sscottl  DM_DBG3(("dmReportChanges: start\n"));
5686285809Sscottl
5687285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
5688285809Sscottl  if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
5689285809Sscottl  {
5690285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5691285809Sscottl    DM_DBG3(("dmReportChanges: empty device list\n"));
5692285809Sscottl    return;
5693285809Sscottl  }
5694285809Sscottl  else
5695285809Sscottl  {
5696285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5697285809Sscottl  }
5698285809Sscottl
5699285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
5700285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
5701285809Sscottl  {
5702285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
5703285809Sscottl    if (oneDeviceData == agNULL)
5704285809Sscottl    {
5705285809Sscottl      DM_DBG1(("dmReportChanges: oneDeviceData is NULL!!!\n"));
5706285809Sscottl      return;
5707285809Sscottl    }
5708285809Sscottl    DM_DBG3(("dmReportChanges: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
5709285809Sscottl    DM_DBG3(("dmReportChanges: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
5710285809Sscottl    if ( oneDeviceData->dmPortContext == onePortContext)
5711285809Sscottl    {
5712285809Sscottl      DM_DBG3(("dmReportChanges: right portcontext\n"));
5713285809Sscottl      if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi &&
5714285809Sscottl          oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo
5715285809Sscottl         )
5716285809Sscottl      {
5717285809Sscottl        DM_DBG1(("dmReportChanges: keep, not reporting did 0x%x\n", oneDeviceData->id));
5718285809Sscottl        oneDeviceData->valid = agTRUE;
5719285809Sscottl        oneDeviceData->valid2 = agFALSE;
5720285809Sscottl      }
5721285809Sscottl      else if ( (oneDeviceData->valid == agTRUE) && (oneDeviceData->valid2 == agTRUE) )
5722285809Sscottl      {
5723285809Sscottl        DM_DBG3(("dmReportChanges: same\n"));
5724285809Sscottl        /* reset valid bit */
5725285809Sscottl        oneDeviceData->valid = oneDeviceData->valid2;
5726285809Sscottl        oneDeviceData->valid2 = agFALSE;
5727285809Sscottl        dmSubReportChanges(dmRoot, onePortContext, oneDeviceData, dmDeviceNoChange);
5728285809Sscottl      }
5729285809Sscottl      else if ( (oneDeviceData->valid == agTRUE) && (oneDeviceData->valid2 == agFALSE) )
5730285809Sscottl      {
5731285809Sscottl        DM_DBG3(("dmReportChanges: removed\n"));
5732285809Sscottl        removed = agTRUE;
5733285809Sscottl        /* reset valid bit */
5734285809Sscottl        oneDeviceData->valid = oneDeviceData->valid2;
5735285809Sscottl        oneDeviceData->valid2 = agFALSE;
5736285809Sscottl
5737285809Sscottl        onePortContext->RegisteredDevNums--;
5738285809Sscottl        dmSubReportChanges(dmRoot, onePortContext, oneDeviceData, dmDeviceRemoval);
5739285809Sscottl      }
5740285809Sscottl      else if ( (oneDeviceData->valid == agFALSE) && (oneDeviceData->valid2 == agTRUE) )
5741285809Sscottl      {
5742285809Sscottl        DM_DBG3(("dmReportChanges: added\n"));
5743285809Sscottl        added = agTRUE;
5744285809Sscottl        /* reset valid bit */
5745285809Sscottl        oneDeviceData->valid = oneDeviceData->valid2;
5746285809Sscottl        oneDeviceData->valid2 = agFALSE;
5747285809Sscottl        dmSubReportChanges(dmRoot, onePortContext, oneDeviceData, dmDeviceArrival);
5748285809Sscottl      }
5749285809Sscottl      else
5750285809Sscottl      {
5751285809Sscottl        DM_DBG3(("dmReportChanges: else\n"));
5752285809Sscottl      }
5753285809Sscottl    }
5754285809Sscottl    else
5755285809Sscottl    {
5756285809Sscottl      DM_DBG3(("dmReportChanges: different portcontext\n"));
5757285809Sscottl    }
5758285809Sscottl    DeviceListList = DeviceListList->flink;
5759285809Sscottl  }
5760285809Sscottl  /*
5761285809Sscottl  osGLOBAL void
5762285809SscottltddmReportDevice(
5763285809Sscottl                 dmRoot_t 		*dmRoot,
5764285809Sscottl                 dmPortContext_t	*dmPortContext,
5765285809Sscottl                 dmDeviceInfo_t		*dmDeviceInfo,
5766285809Sscottl                 dmDeviceInfo_t		*dmExpDeviceInfo,
5767285809Sscottl		 bit32                   flag
5768285809Sscottl
5769285809Sscottl                 )
5770285809Sscottl
5771285809Sscottl  */
5772285809Sscottl
5773285809Sscottl  /* arrival or removal at once */
5774285809Sscottl  if (added == agTRUE)
5775285809Sscottl  {
5776285809Sscottl    DM_DBG3(("dmReportChanges: added at the end\n"));
5777285809Sscottl#if 0  /* TBD */
5778285809Sscottl    ostiInitiatorEvent(
5779285809Sscottl                         tiRoot,
5780285809Sscottl                         onePortContext->tiPortalContext,
5781285809Sscottl                         agNULL,
5782285809Sscottl                         tiIntrEventTypeDeviceChange,
5783285809Sscottl                         tiDeviceArrival,
5784285809Sscottl                         agNULL
5785285809Sscottl                         );
5786285809Sscottl#endif
5787285809Sscottl
5788285809Sscottl  }
5789285809Sscottl  if (removed == agTRUE)
5790285809Sscottl  {
5791285809Sscottl    DM_DBG3(("dmReportChanges: removed at the end\n"));
5792285809Sscottl#if 0  /* TBD */
5793285809Sscottl    ostiInitiatorEvent(
5794285809Sscottl                       tiRoot,
5795285809Sscottl                       onePortContext->tiPortalContext,
5796285809Sscottl                       agNULL,
5797285809Sscottl                       tiIntrEventTypeDeviceChange,
5798285809Sscottl                       tiDeviceRemoval,
5799285809Sscottl                       agNULL
5800285809Sscottl                       );
5801285809Sscottl#endif
5802285809Sscottl  }
5803285809Sscottl
5804285809Sscottl  if (onePortContext->discovery.forcedOK == agTRUE && added == agFALSE && removed == agFALSE)
5805285809Sscottl  {
5806285809Sscottl    DM_DBG3(("dmReportChanges: missed chance to report. forced to report OK\n"));
5807285809Sscottl    onePortContext->discovery.forcedOK = agFALSE;
5808285809Sscottl#if 0  /* TBD */
5809285809Sscottl    ostiInitiatorEvent(
5810285809Sscottl                       tiRoot,
5811285809Sscottl                       onePortContext->tiPortalContext,
5812285809Sscottl                       agNULL,
5813285809Sscottl                       tiIntrEventTypeDiscovery,
5814285809Sscottl                       tiDiscOK,
5815285809Sscottl                       agNULL
5816285809Sscottl                       );
5817285809Sscottl#endif
5818285809Sscottl  }
5819285809Sscottl
5820285809Sscottl  if (added == agFALSE && removed == agFALSE)
5821285809Sscottl  {
5822285809Sscottl    DM_DBG3(("dmReportChanges: the same\n"));
5823285809Sscottl  }
5824285809Sscottl
5825285809Sscottl  return;
5826285809Sscottl}
5827285809Sscottl
5828285809SscottlosGLOBAL void
5829285809SscottldmReportRemovals(
5830285809Sscottl                 dmRoot_t                  *dmRoot,
5831285809Sscottl                 dmIntPortContext_t        *onePortContext,
5832285809Sscottl                 bit32                     flag
5833285809Sscottl                )
5834285809Sscottl{
5835285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5836285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5837285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
5838285809Sscottl  dmList_t          *DeviceListList;
5839285809Sscottl  bit32             removed = agFALSE;
5840285809Sscottl
5841285809Sscottl  DM_DBG1(("dmReportRemovals: start\n"));
5842285809Sscottl
5843285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
5844285809Sscottl  if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
5845285809Sscottl  {
5846285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5847285809Sscottl    DM_DBG3(("dmReportRemovals: empty device list\n"));
5848285809Sscottl    return;
5849285809Sscottl  }
5850285809Sscottl  else
5851285809Sscottl  {
5852285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5853285809Sscottl  }
5854285809Sscottl
5855285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
5856285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
5857285809Sscottl  {
5858285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
5859285809Sscottl    if (oneDeviceData == agNULL)
5860285809Sscottl    {
5861285809Sscottl      DM_DBG1(("dmReportRemovals: oneDeviceData is NULL!!!\n"));
5862285809Sscottl      return;
5863285809Sscottl    }
5864285809Sscottl    DM_DBG3(("dmReportRemovals: loop did %d\n", oneDeviceData->id));
5865285809Sscottl    DM_DBG3(("dmReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
5866285809Sscottl    DM_DBG3(("dmReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
5867285809Sscottl    DM_DBG3(("dmReportRemovals: valid %d\n", oneDeviceData->valid));
5868285809Sscottl    DM_DBG3(("dmReportRemovals: valid2 %d\n", oneDeviceData->valid2));
5869285809Sscottl    DM_DBG3(("dmReportRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
5870285809Sscottl    if ( oneDeviceData->dmPortContext == onePortContext)
5871285809Sscottl    {
5872285809Sscottl      DM_DBG3(("dmReportRemovals: right portcontext pid %d\n", onePortContext->id));
5873285809Sscottl      if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi &&
5874285809Sscottl          oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo
5875285809Sscottl         )
5876285809Sscottl      {
5877285809Sscottl        DM_DBG1(("dmReportRemovals: keeping\n"));
5878285809Sscottl        oneDeviceData->valid = agTRUE;
5879285809Sscottl        oneDeviceData->valid2 = agFALSE;
5880285809Sscottl      }
5881285809Sscottl      else if (oneDeviceData->valid == agTRUE)
5882285809Sscottl      {
5883285809Sscottl        DM_DBG3(("dmReportRemovals: removing\n"));
5884285809Sscottl
5885285809Sscottl        /* notify only reported devices to OS layer*/
5886285809Sscottl        if ( DEVICE_IS_SSP_TARGET(oneDeviceData) ||
5887285809Sscottl             DEVICE_IS_STP_TARGET(oneDeviceData) ||
5888285809Sscottl             DEVICE_IS_SATA_DEVICE(oneDeviceData)
5889285809Sscottl            )
5890285809Sscottl        {
5891285809Sscottl          removed = agTRUE;
5892285809Sscottl        }
5893285809Sscottl
5894285809Sscottl        /* all targets except expanders */
5895285809Sscottl        DM_DBG3(("dmReportRemovals: did %d\n", oneDeviceData->id));
5896285809Sscottl        DM_DBG3(("dmReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
5897285809Sscottl        DM_DBG3(("dmReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
5898285809Sscottl        onePortContext->RegisteredDevNums--;
5899285809Sscottl        dmSubReportRemovals(dmRoot, onePortContext, oneDeviceData, dmDeviceRemoval);
5900285809Sscottl
5901285809Sscottl
5902285809Sscottl        /* reset valid bit */
5903285809Sscottl        oneDeviceData->valid = agFALSE;
5904285809Sscottl        oneDeviceData->valid2 = agFALSE;
5905285809Sscottl
5906285809Sscottl
5907285809Sscottl      }
5908285809Sscottl      /* called by port invalid case */
5909285809Sscottl      if (flag == agTRUE)
5910285809Sscottl      {
5911285809Sscottl        oneDeviceData->dmPortContext = agNULL;
5912285809Sscottl      }
5913285809Sscottl      DeviceListList = DeviceListList->flink;
5914285809Sscottl    }
5915285809Sscottl    else
5916285809Sscottl    {
5917285809Sscottl      if (oneDeviceData->dmPortContext != agNULL)
5918285809Sscottl      {
5919285809Sscottl        DM_DBG3(("dmReportRemovals: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id));
5920285809Sscottl      }
5921285809Sscottl      else
5922285809Sscottl      {
5923285809Sscottl        DM_DBG3(("dmReportRemovals: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
5924285809Sscottl      }
5925285809Sscottl      DeviceListList = DeviceListList->flink;
5926285809Sscottl    }
5927285809Sscottl  }
5928285809Sscottl
5929285809Sscottl  if (removed == agTRUE)
5930285809Sscottl  {
5931285809Sscottl    DM_DBG3(("dmReportRemovals: removed at the end\n"));
5932285809Sscottl#if 0 /* TBD */
5933285809Sscottl      ostiInitiatorEvent(
5934285809Sscottl                         tiRoot,
5935285809Sscottl                         onePortContext->tiPortalContext,
5936285809Sscottl                         agNULL,
5937285809Sscottl                         tiIntrEventTypeDeviceChange,
5938285809Sscottl                         tiDeviceRemoval,
5939285809Sscottl                         agNULL
5940285809Sscottl                         );
5941285809Sscottl#endif
5942285809Sscottl  }
5943285809Sscottl
5944285809Sscottl  return;
5945285809Sscottl}
5946285809Sscottl
5947285809SscottlosGLOBAL void
5948285809SscottldmResetReported(
5949285809Sscottl                dmRoot_t                  *dmRoot,
5950285809Sscottl                dmIntPortContext_t        *onePortContext
5951285809Sscottl               )
5952285809Sscottl{
5953285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
5954285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
5955285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
5956285809Sscottl  dmList_t          *DeviceListList;
5957285809Sscottl
5958285809Sscottl  DM_DBG3(("dmResetReported: start\n"));
5959285809Sscottl
5960285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
5961285809Sscottl  if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
5962285809Sscottl  {
5963285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5964285809Sscottl    DM_DBG3(("dmResetReported: empty device list\n"));
5965285809Sscottl    return;
5966285809Sscottl  }
5967285809Sscottl  else
5968285809Sscottl  {
5969285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
5970285809Sscottl  }
5971285809Sscottl
5972285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
5973285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
5974285809Sscottl  {
5975285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
5976285809Sscottl    if (oneDeviceData == agNULL)
5977285809Sscottl    {
5978285809Sscottl      DM_DBG1(("dmResetReported: oneDeviceData is NULL!!!\n"));
5979285809Sscottl      return;
5980285809Sscottl    }
5981285809Sscottl    DM_DBG3(("dmResetReported: loop did %d\n", oneDeviceData->id));
5982285809Sscottl    DM_DBG3(("dmResetReported: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
5983285809Sscottl    DM_DBG3(("dmResetReported: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
5984285809Sscottl    DM_DBG3(("dmResetReported: valid %d\n", oneDeviceData->valid));
5985285809Sscottl    DM_DBG3(("dmResetReported: valid2 %d\n", oneDeviceData->valid2));
5986285809Sscottl    DM_DBG3(("dmResetReported: directlyAttached %d\n", oneDeviceData->directlyAttached));
5987285809Sscottl    if ( oneDeviceData->dmPortContext == onePortContext)
5988285809Sscottl    {
5989285809Sscottl      DM_DBG3(("dmResetReported: right portcontext pid %d\n", onePortContext->id));
5990285809Sscottl      oneDeviceData->reported = agFALSE;
5991285809Sscottl      DeviceListList = DeviceListList->flink;
5992285809Sscottl    }
5993285809Sscottl    else
5994285809Sscottl    {
5995285809Sscottl      if (oneDeviceData->dmPortContext != agNULL)
5996285809Sscottl      {
5997285809Sscottl        DM_DBG3(("dmResetReported: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id));
5998285809Sscottl      }
5999285809Sscottl      else
6000285809Sscottl      {
6001285809Sscottl        DM_DBG3(("dmResetReported: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
6002285809Sscottl      }
6003285809Sscottl      DeviceListList = DeviceListList->flink;
6004285809Sscottl    }
6005285809Sscottl  }
6006285809Sscottl
6007285809Sscottl  return;
6008285809Sscottl}
6009285809Sscottl
6010285809Sscottl/* called on discover failure */
6011285809SscottlosGLOBAL void
6012285809SscottldmDiscoveryInvalidateDevices(
6013285809Sscottl                             dmRoot_t                  *dmRoot,
6014285809Sscottl                             dmIntPortContext_t        *onePortContext
6015285809Sscottl                            )
6016285809Sscottl{
6017285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6018285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6019285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
6020285809Sscottl  dmList_t          *DeviceListList;
6021285809Sscottl
6022285809Sscottl  DM_DBG1(("dmDiscoveryInvalidateDevices: start\n"));
6023285809Sscottl
6024285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6025285809Sscottl  if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
6026285809Sscottl  {
6027285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6028285809Sscottl    DM_DBG3(("dmDiscoveryInvalidateDevices: empty device list\n"));
6029285809Sscottl    return;
6030285809Sscottl  }
6031285809Sscottl  else
6032285809Sscottl  {
6033285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6034285809Sscottl  }
6035285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
6036285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
6037285809Sscottl  {
6038285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6039285809Sscottl    if (oneDeviceData == agNULL)
6040285809Sscottl    {
6041285809Sscottl      DM_DBG1(("dmDiscoveryInvalidateDevices: oneDeviceData is NULL!!!\n"));
6042285809Sscottl      return;
6043285809Sscottl    }
6044285809Sscottl    DM_DBG3(("dmDiscoveryInvalidateDevices: loop did %d\n", oneDeviceData->id));
6045285809Sscottl    DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6046285809Sscottl    DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6047285809Sscottl    DM_DBG3(("dmDiscoveryInvalidateDevices: valid %d\n", oneDeviceData->valid));
6048285809Sscottl    DM_DBG3(("dmDiscoveryInvalidateDevices: valid2 %d\n", oneDeviceData->valid2));
6049285809Sscottl    DM_DBG3(("dmDiscoveryInvalidateDevices: directlyAttached %d\n", oneDeviceData->directlyAttached));
6050285809Sscottl    if ( oneDeviceData->dmPortContext == onePortContext)
6051285809Sscottl    {
6052285809Sscottl      DM_DBG3(("dmDiscoveryInvalidateDevices: right portcontext pid %d\n", onePortContext->id));
6053285809Sscottl      if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi &&
6054285809Sscottl          oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo
6055285809Sscottl         )
6056285809Sscottl      {
6057285809Sscottl        DM_DBG1(("dmDiscoveryInvalidateDevices: keeping\n"));
6058285809Sscottl        oneDeviceData->valid = agTRUE;
6059285809Sscottl        oneDeviceData->valid2 = agFALSE;
6060285809Sscottl      }
6061285809Sscottl      else
6062285809Sscottl      {
6063285809Sscottl        oneDeviceData->valid = agFALSE;
6064285809Sscottl        oneDeviceData->valid2 = agFALSE;
6065285809Sscottl        oneDeviceData->registered = agFALSE;
6066285809Sscottl        oneDeviceData->reported = agFALSE;
6067285809Sscottl        /* all targets other than expanders */
6068285809Sscottl        DM_DBG3(("dmDiscoveryInvalidateDevices: did %d\n", oneDeviceData->id));
6069285809Sscottl        DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6070285809Sscottl        DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6071285809Sscottl        onePortContext->RegisteredDevNums--;
6072285809Sscottl      }
6073285809Sscottl      DeviceListList = DeviceListList->flink;
6074285809Sscottl    }
6075285809Sscottl    else
6076285809Sscottl    {
6077285809Sscottl      if (oneDeviceData->dmPortContext != agNULL)
6078285809Sscottl      {
6079285809Sscottl        DM_DBG3(("dmDiscoveryInvalidateDevices: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id));
6080285809Sscottl      }
6081285809Sscottl      else
6082285809Sscottl      {
6083285809Sscottl        DM_DBG3(("dmDiscoveryInvalidateDevices: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
6084285809Sscottl      }
6085285809Sscottl      DeviceListList = DeviceListList->flink;
6086285809Sscottl    }
6087285809Sscottl  }
6088285809Sscottl
6089285809Sscottl  return;
6090285809Sscottl}
6091285809Sscottl
6092285809Sscottl
6093285809Sscottl/*
6094285809Sscottl should DM report the device removal to TDM on an error case?
6095285809Sscottl or
6096285809Sscottl DM simply removes the devices
6097285809Sscottl For now, the second option.
6098285809Sscottl*/
6099285809SscottlosGLOBAL void
6100285809SscottldmDiscoveryErrorRemovals(
6101285809Sscottl                         dmRoot_t                  *dmRoot,
6102285809Sscottl                         dmIntPortContext_t        *onePortContext
6103285809Sscottl                        )
6104285809Sscottl{
6105285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6106285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6107285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
6108285809Sscottl  dmList_t          *DeviceListList;
6109285809Sscottl
6110285809Sscottl  DM_DBG1(("dmDiscoveryErrorRemovals: start\n"));
6111285809Sscottl
6112285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6113285809Sscottl  if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
6114285809Sscottl  {
6115285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6116285809Sscottl    DM_DBG3(("dmDiscoveryErrorRemovals: empty device list\n"));
6117285809Sscottl    return;
6118285809Sscottl  }
6119285809Sscottl  else
6120285809Sscottl  {
6121285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6122285809Sscottl  }
6123285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
6124285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
6125285809Sscottl  {
6126285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6127285809Sscottl    if (oneDeviceData == agNULL)
6128285809Sscottl    {
6129285809Sscottl      DM_DBG1(("dmDiscoveryErrorRemovals: oneDeviceData is NULL!!!\n"));
6130285809Sscottl      return;
6131285809Sscottl    }
6132285809Sscottl    DM_DBG3(("dmDiscoveryErrorRemovals: loop did %d\n", oneDeviceData->id));
6133285809Sscottl    DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6134285809Sscottl    DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6135285809Sscottl    DM_DBG3(("dmDiscoveryErrorRemovals: valid %d\n", oneDeviceData->valid));
6136285809Sscottl    DM_DBG3(("dmDiscoveryErrorRemovals: valid2 %d\n", oneDeviceData->valid2));
6137285809Sscottl    DM_DBG3(("dmDiscoveryErrorRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
6138285809Sscottl    if ( oneDeviceData->dmPortContext == onePortContext)
6139285809Sscottl    {
6140285809Sscottl      DM_DBG3(("dmDiscoveryErrorRemovals: right portcontext pid %d\n", onePortContext->id));
6141285809Sscottl      if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi &&
6142285809Sscottl          oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo
6143285809Sscottl         )
6144285809Sscottl      {
6145285809Sscottl        DM_DBG1(("dmDiscoveryErrorRemovals: keeping\n"));
6146285809Sscottl        oneDeviceData->valid = agTRUE;
6147285809Sscottl        oneDeviceData->valid2 = agFALSE;
6148285809Sscottl      }
6149285809Sscottl      else
6150285809Sscottl      {
6151285809Sscottl        oneDeviceData->valid = agFALSE;
6152285809Sscottl        oneDeviceData->valid2 = agFALSE;
6153285809Sscottl
6154285809Sscottl        /* all targets other than expanders */
6155285809Sscottl        DM_DBG3(("dmDiscoveryErrorRemovals: did %d\n", oneDeviceData->id));
6156285809Sscottl        DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6157285809Sscottl        DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6158285809Sscottl        onePortContext->RegisteredDevNums--;
6159285809Sscottl        dmSubReportRemovals(dmRoot, onePortContext, oneDeviceData, dmDeviceRemoval);
6160285809Sscottl
6161285809Sscottl      }
6162285809Sscottl      DeviceListList = DeviceListList->flink;
6163285809Sscottl    }
6164285809Sscottl    else
6165285809Sscottl    {
6166285809Sscottl      if (oneDeviceData->dmPortContext != agNULL)
6167285809Sscottl      {
6168285809Sscottl        DM_DBG3(("dmDiscoveryErrorRemovals: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id));
6169285809Sscottl      }
6170285809Sscottl      else
6171285809Sscottl      {
6172285809Sscottl        DM_DBG3(("dmDiscoveryErrorRemovals: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
6173285809Sscottl      }
6174285809Sscottl      DeviceListList = DeviceListList->flink;
6175285809Sscottl    }
6176285809Sscottl  }
6177285809Sscottl
6178285809Sscottl  return;
6179285809Sscottl}
6180285809Sscottl
6181285809Sscottl/* move from dmAllShared->mainExpanderList to dmAllShared->freeExpanderList */
6182285809SscottlosGLOBAL void
6183285809SscottldmDiscoveryExpanderCleanUp(
6184285809Sscottl                           dmRoot_t                  *dmRoot,
6185285809Sscottl                           dmIntPortContext_t        *onePortContext
6186285809Sscottl                          )
6187285809Sscottl{
6188285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6189285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6190285809Sscottl  dmExpander_t      *oneExpander = agNULL;
6191285809Sscottl  dmList_t          *ExpanderList = agNULL;
6192285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
6193285809Sscottl
6194285809Sscottl  DM_DBG3(("dmDiscoveryExpanderCleanUp: start\n"));
6195285809Sscottl  /*
6196285809Sscottl    be sure to call
6197285809Sscottl    osGLOBAL void
6198285809Sscottl    dmExpanderDeviceDataReInit(
6199285809Sscottl                           dmRoot_t 	    *dmRoot,
6200285809Sscottl                           dmExpander_t     *oneExpander
6201285809Sscottl                          );
6202285809Sscottl
6203285809Sscottl  */
6204285809Sscottl
6205285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
6206285809Sscottl  if (!DMLIST_EMPTY(&(dmAllShared->mainExpanderList)))
6207285809Sscottl  {
6208285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6209285809Sscottl    ExpanderList = dmAllShared->mainExpanderList.flink;
6210285809Sscottl    while (ExpanderList != &(dmAllShared->mainExpanderList))
6211285809Sscottl    {
6212285809Sscottl      oneExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
6213285809Sscottl      if (oneExpander == agNULL)
6214285809Sscottl      {
6215285809Sscottl        DM_DBG1(("dmDiscoveryExpanderCleanUp: oneExpander is NULL!!!\n"));
6216285809Sscottl        return;
6217285809Sscottl      }
6218285809Sscottl      oneDeviceData = oneExpander->dmDevice;
6219285809Sscottl      DM_DBG3(("dmDiscoveryExpanderCleanUp: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6220285809Sscottl      DM_DBG3(("dmDiscoveryExpanderCleanUp: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6221285809Sscottl      if ( oneDeviceData->dmPortContext == onePortContext)
6222285809Sscottl      {
6223285809Sscottl        dmExpanderDeviceDataReInit(dmRoot, oneExpander);
6224285809Sscottl        tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
6225285809Sscottl        DMLIST_DEQUEUE_THIS(&(oneExpander->linkNode));
6226285809Sscottl        DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(dmAllShared->freeExpanderList));
6227285809Sscottl
6228285809Sscottl        if (DMLIST_EMPTY(&(dmAllShared->mainExpanderList)))
6229285809Sscottl        {
6230285809Sscottl          tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6231285809Sscottl          break;
6232285809Sscottl        }
6233285809Sscottl        else
6234285809Sscottl        {
6235285809Sscottl          tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6236285809Sscottl        }
6237285809Sscottl        ExpanderList = dmAllShared->mainExpanderList.flink;
6238285809Sscottl      }
6239285809Sscottl      else
6240285809Sscottl      {
6241285809Sscottl        ExpanderList = ExpanderList->flink;
6242285809Sscottl      }
6243285809Sscottl    }
6244285809Sscottl  }
6245285809Sscottl  else
6246285809Sscottl  {
6247285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6248285809Sscottl    DM_DBG3(("dmDiscoveryExpanderCleanUp: empty mainExpanderList\n"));
6249285809Sscottl  }
6250285809Sscottl  return;
6251285809Sscottl
6252285809Sscottl}
6253285809Sscottl
6254285809Sscottl
6255285809Sscottl/* moves all devices from dmAllShared->MainDeviceList to dmAllShared->FreeDeviceList */
6256285809SscottlosGLOBAL void
6257285809SscottldmDiscoveryDeviceCleanUp(
6258285809Sscottl                         dmRoot_t                  *dmRoot,
6259285809Sscottl                         dmIntPortContext_t        *onePortContext
6260285809Sscottl                        )
6261285809Sscottl{
6262285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6263285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6264285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
6265285809Sscottl  dmList_t          *DeviceListList;
6266285809Sscottl
6267285809Sscottl  DM_DBG3(("dmDiscoveryDeviceCleanUp: start\n"));
6268285809Sscottl
6269285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6270285809Sscottl  if (!DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
6271285809Sscottl  {
6272285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6273285809Sscottl    DeviceListList = dmAllShared->MainDeviceList.flink;
6274285809Sscottl    while (DeviceListList != &(dmAllShared->MainDeviceList))
6275285809Sscottl    {
6276285809Sscottl      oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6277285809Sscottl      if (oneDeviceData == agNULL)
6278285809Sscottl      {
6279285809Sscottl        DM_DBG1(("dmDiscoveryDeviceCleanUp: oneDeviceData is NULL!!!\n"));
6280285809Sscottl        return;
6281285809Sscottl      }
6282285809Sscottl      DM_DBG3(("dmDiscoveryDeviceCleanUp: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6283285809Sscottl      DM_DBG3(("dmDiscoveryDeviceCleanUp: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6284285809Sscottl      if ( oneDeviceData->dmPortContext == onePortContext)
6285285809Sscottl      {
6286285809Sscottl        dmDeviceDataReInit(dmRoot, oneDeviceData);
6287285809Sscottl        tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6288285809Sscottl        DMLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
6289285809Sscottl        DMLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(dmAllShared->FreeDeviceList));
6290285809Sscottl
6291285809Sscottl        if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
6292285809Sscottl        {
6293285809Sscottl          tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6294285809Sscottl          break;
6295285809Sscottl        }
6296285809Sscottl        else
6297285809Sscottl        {
6298285809Sscottl          tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6299285809Sscottl        }
6300285809Sscottl	onePortContext->RegisteredDevNums--;
6301285809Sscottl        DeviceListList = dmAllShared->MainDeviceList.flink;
6302285809Sscottl      }
6303285809Sscottl      else
6304285809Sscottl      {
6305285809Sscottl        DeviceListList = DeviceListList->flink;
6306285809Sscottl      }
6307285809Sscottl    }
6308285809Sscottl  }
6309285809Sscottl  else
6310285809Sscottl  {
6311285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6312285809Sscottl    DM_DBG3(("dmDiscoveryDeviceCleanUp: empty MainDeviceList\n"));
6313285809Sscottl  }
6314285809Sscottl  return;
6315285809Sscottl}
6316285809Sscottl
6317285809Sscottl
6318285809Sscottl
6319285809SscottlosGLOBAL void
6320285809SscottldmDumpAllExp(
6321285809Sscottl             dmRoot_t                  *dmRoot,
6322285809Sscottl             dmIntPortContext_t        *onePortContext,
6323285809Sscottl             dmExpander_t              *oneExpander
6324285809Sscottl            )
6325285809Sscottl{
6326285809Sscottl  DM_DBG3(("dmDumpAllExp: start\n"));
6327285809Sscottl  return;
6328285809Sscottl}
6329285809Sscottl
6330285809Sscottl
6331285809SscottlosGLOBAL void
6332285809SscottldmDumpAllUpExp(
6333285809Sscottl               dmRoot_t                  *dmRoot,
6334285809Sscottl               dmIntPortContext_t        *onePortContext,
6335285809Sscottl               dmExpander_t              *oneExpander
6336285809Sscottl              )
6337285809Sscottl{
6338285809Sscottl  DM_DBG3(("dmDumpAllUpExp: start\n"));
6339285809Sscottl  return;
6340285809Sscottl}
6341285809Sscottl
6342285809SscottlosGLOBAL void
6343285809SscottldmDumpAllFreeExp(
6344285809Sscottl                 dmRoot_t                  *dmRoot
6345285809Sscottl                )
6346285809Sscottl{
6347285809Sscottl  DM_DBG3(("dmDumpAllFreeExp: start\n"));
6348285809Sscottl  return;
6349285809Sscottl}
6350285809Sscottl
6351285809SscottlosGLOBAL void
6352285809SscottldmDumpAllMainExp(
6353285809Sscottl                 dmRoot_t                 *dmRoot,
6354285809Sscottl                 dmIntPortContext_t       *onePortContext
6355285809Sscottl                )
6356285809Sscottl{
6357285809Sscottl  dmIntRoot_t        *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6358285809Sscottl  dmIntContext_t     *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6359285809Sscottl  dmList_t           *ExpanderList;
6360285809Sscottl  dmExpander_t       *tempExpander;
6361285809Sscottl
6362285809Sscottl  DM_DBG3(("dmDumpAllMainExp: start\n"));
6363285809Sscottl
6364285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK);
6365285809Sscottl  if (DMLIST_EMPTY(&(dmAllShared->mainExpanderList)))
6366285809Sscottl  {
6367285809Sscottl    DM_DBG3(("dmDumpAllMainExp: empty discoveringExpanderList\n"));
6368285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6369285809Sscottl    return;
6370285809Sscottl  }
6371285809Sscottl  else
6372285809Sscottl  {
6373285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK);
6374285809Sscottl  }
6375285809Sscottl
6376285809Sscottl  ExpanderList = dmAllShared->mainExpanderList.flink;
6377285809Sscottl  while (ExpanderList != &(dmAllShared->mainExpanderList))
6378285809Sscottl  {
6379285809Sscottl    tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList);
6380285809Sscottl    if (tempExpander == agNULL)
6381285809Sscottl    {
6382285809Sscottl      DM_DBG1(("dmDumpAllMainExp: tempExpander is NULL!!!\n"));
6383285809Sscottl      return;
6384285809Sscottl    }
6385285809Sscottl    DM_DBG3(("dmDumpAllMainExp: expander id %d\n", tempExpander->id));
6386285809Sscottl    DM_DBG3(("dmDumpAllMainExp: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
6387285809Sscottl    DM_DBG3(("dmDumpAllMainExp: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
6388285809Sscottl    if ((tempExpander->dmDevice->dmPortContext == onePortContext)
6389285809Sscottl       )
6390285809Sscottl    {
6391285809Sscottl      DM_DBG3(("dmDumpAllMainExp: found expander id %d\n", tempExpander->id));
6392285809Sscottl      DM_DBG3(("dmDumpAllMainExp: found exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi));
6393285809Sscottl      DM_DBG3(("dmDumpAllMainExp: found exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo));
6394285809Sscottl    }
6395285809Sscottl    ExpanderList = ExpanderList->flink;
6396285809Sscottl  }
6397285809Sscottl  return;
6398285809Sscottl}
6399285809Sscottl
6400285809Sscottl
6401285809SscottlosGLOBAL void
6402285809SscottldmDumpAllMainDevice(
6403285809Sscottl                 dmRoot_t                 *dmRoot,
6404285809Sscottl                 dmIntPortContext_t       *onePortContext
6405285809Sscottl                )
6406285809Sscottl{
6407285809Sscottl  dmIntRoot_t        *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6408285809Sscottl  dmIntContext_t     *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6409285809Sscottl  dmDeviceData_t     *oneDeviceData = agNULL;
6410285809Sscottl  dmList_t           *DeviceListList;
6411285809Sscottl  bit32              total = 0, port_total = 0;
6412285809Sscottl
6413285809Sscottl  DM_DBG3(("dmDumpAllMainDevice: start\n"));
6414285809Sscottl
6415285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6416285809Sscottl  if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList)))
6417285809Sscottl  {
6418285809Sscottl    DM_DBG3(("dmDumpAllMainDevice: empty discoveringExpanderList\n"));
6419285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6420285809Sscottl    return;
6421285809Sscottl  }
6422285809Sscottl  else
6423285809Sscottl  {
6424285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6425285809Sscottl  }
6426285809Sscottl
6427285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
6428285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
6429285809Sscottl  {
6430285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6431285809Sscottl    if (oneDeviceData == agNULL)
6432285809Sscottl    {
6433285809Sscottl      DM_DBG3(("dmDumpAllMainDevice: oneDeviceData is NULL!!!\n"));
6434285809Sscottl      return;
6435285809Sscottl    }
6436285809Sscottl    DM_DBG3(("dmDumpAllMainDevice: oneDeviceData id %d\n", oneDeviceData->id));
6437285809Sscottl    DM_DBG3(("dmDumpAllMainDevice: addrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
6438285809Sscottl    DM_DBG3(("dmDumpAllMainDevice: addrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
6439285809Sscottl    total++;
6440285809Sscottl    if ((oneDeviceData->dmPortContext == onePortContext)
6441285809Sscottl       )
6442285809Sscottl    {
6443285809Sscottl      DM_DBG3(("dmDumpAllMainDevice: found oneDeviceData id %d\n", oneDeviceData->id));
6444285809Sscottl      DM_DBG3(("dmDumpAllMainDevice: found addrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
6445285809Sscottl      DM_DBG3(("dmDumpAllMainDevice: found addrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
6446285809Sscottl      port_total++;
6447285809Sscottl    }
6448285809Sscottl    DeviceListList = DeviceListList->flink;
6449285809Sscottl  }
6450285809Sscottl  DM_DBG3(("dmDumpAllMainDevice: total %d port_totaol %d\n", total, port_total));
6451285809Sscottl
6452285809Sscottl  return;
6453285809Sscottl}
6454285809Sscottl
6455285809Sscottl
6456285809Sscottl
6457285809SscottlosGLOBAL dmDeviceData_t *
6458285809SscottldmAddSASToSharedcontext(
6459285809Sscottl                         dmRoot_t              *dmRoot,
6460285809Sscottl                         dmIntPortContext_t    *onePortContext,
6461285809Sscottl                         dmSASSubID_t          *dmSASSubID,
6462285809Sscottl                         dmDeviceData_t        *oneExpDeviceData,
6463285809Sscottl                         bit8                   phyID
6464285809Sscottl                        )
6465285809Sscottl{
6466285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6467285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6468285809Sscottl  dmDeviceData_t    *oneDeviceData = agNULL;
6469285809Sscottl  dmList_t          *DeviceListList;
6470285809Sscottl  bit32             new_device = agTRUE;
6471285809Sscottl
6472285809Sscottl
6473285809Sscottl  DM_DBG3(("dmAddSASToSharedcontext: start\n"));
6474285809Sscottl  DM_DBG3(("dmAddSASToSharedcontext: oneportContext ID %d\n", onePortContext->id));
6475285809Sscottl
6476285809Sscottl  if (oneExpDeviceData != agNULL)
6477285809Sscottl  {
6478285809Sscottl    DM_DBG3(("dmAddSASToSharedcontext: oneExpDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
6479285809Sscottl    oneExpDeviceData->SASAddressID.sasAddressHi, oneExpDeviceData->SASAddressID.sasAddressLo));
6480285809Sscottl  }
6481285809Sscottl  else
6482285809Sscottl  {
6483285809Sscottl    DM_DBG3(("dmAddSASToSharedcontext: oneExpDeviceData is NULL\n"));
6484285809Sscottl  }
6485285809Sscottl  /* find a device's existence */
6486285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
6487285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
6488285809Sscottl  {
6489285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6490285809Sscottl    if (oneDeviceData == agNULL)
6491285809Sscottl    {
6492285809Sscottl      DM_DBG1(("dmAddSASToSharedcontext: oneDeviceData is NULL!!!\n"));
6493285809Sscottl      return agNULL;
6494285809Sscottl    }
6495285809Sscottl    if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) &&
6496285809Sscottl        (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) &&
6497285809Sscottl        (oneDeviceData->dmPortContext == onePortContext)
6498285809Sscottl        )
6499285809Sscottl    {
6500285809Sscottl      DM_DBG3(("dmAddSASToSharedcontext: pid %d did %d\n", onePortContext->id, oneDeviceData->id));
6501285809Sscottl      new_device = agFALSE;
6502285809Sscottl      break;
6503285809Sscottl    }
6504285809Sscottl    DeviceListList = DeviceListList->flink;
6505285809Sscottl  }
6506285809Sscottl
6507285809Sscottl  /* new device */
6508285809Sscottl  if (new_device == agTRUE)
6509285809Sscottl  {
6510285809Sscottl    DM_DBG3(("dmAddSASToSharedcontext: new device\n"));
6511285809Sscottl    DM_DBG3(("dmAddSASToSharedcontext: sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
6512285809Sscottl    dmSASSubID->sasAddressHi, dmSASSubID->sasAddressLo));
6513285809Sscottl    tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6514285809Sscottl    if (!DMLIST_NOT_EMPTY(&(dmAllShared->FreeDeviceList)))
6515285809Sscottl    {
6516285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6517285809Sscottl      DM_DBG1(("dmAddSASToSharedcontext: empty DeviceData FreeLink\n"));
6518285809Sscottl      dmDumpAllMainDevice(dmRoot, onePortContext);
6519285809Sscottl      return agNULL;
6520285809Sscottl    }
6521285809Sscottl
6522285809Sscottl    DMLIST_DEQUEUE_FROM_HEAD(&DeviceListList, &(dmAllShared->FreeDeviceList));
6523285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6524285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, FreeLink, DeviceListList);
6525285809Sscottl
6526285809Sscottl    if (oneDeviceData != agNULL)
6527285809Sscottl    {
6528285809Sscottl      DM_DBG3(("dmAddSASToSharedcontext: oneDeviceData %p pid %d did %d\n", oneDeviceData, onePortContext->id, oneDeviceData->id));
6529285809Sscottl
6530285809Sscottl      onePortContext->Count++;
6531285809Sscottl      oneDeviceData->dmRoot = dmRoot;
6532285809Sscottl      /* saving sas address */
6533285809Sscottl      oneDeviceData->SASAddressID.sasAddressLo = dmSASSubID->sasAddressLo;
6534285809Sscottl      oneDeviceData->SASAddressID.sasAddressHi = dmSASSubID->sasAddressHi;
6535285809Sscottl      oneDeviceData->initiator_ssp_stp_smp = dmSASSubID->initiator_ssp_stp_smp;
6536285809Sscottl      oneDeviceData->target_ssp_stp_smp = dmSASSubID->target_ssp_stp_smp;
6537285809Sscottl      oneDeviceData->dmPortContext = onePortContext;
6538285809Sscottl      /* handles both SAS target and STP-target, SATA-device */
6539285809Sscottl      if (!DEVICE_IS_SATA_DEVICE(oneDeviceData) && !DEVICE_IS_STP_TARGET(oneDeviceData))
6540285809Sscottl      {
6541285809Sscottl        oneDeviceData->DeviceType = DM_SAS_DEVICE;
6542285809Sscottl      }
6543285809Sscottl      else
6544285809Sscottl      {
6545285809Sscottl        oneDeviceData->DeviceType = DM_SATA_DEVICE;
6546285809Sscottl      }
6547285809Sscottl
6548285809Sscottl      if (oneExpDeviceData != agNULL)
6549285809Sscottl      {
6550285809Sscottl        oneDeviceData->ExpDevice = oneExpDeviceData;
6551285809Sscottl      }
6552285809Sscottl
6553285809Sscottl      /* set phyID only when it has initial value of 0xFF */
6554285809Sscottl      if (oneDeviceData->phyID == 0xFF)
6555285809Sscottl      {
6556285809Sscottl        oneDeviceData->phyID = phyID;
6557285809Sscottl      }
6558285809Sscottl      /* incremental discovery */
6559285809Sscottl      /* add device to incremental-related link. Report using this link
6560285809Sscottl         when incremental discovery is done */
6561285809Sscottl      if (onePortContext->DiscoveryState == DM_DSTATE_NOT_STARTED)
6562285809Sscottl      {
6563285809Sscottl        DM_DBG3(("dmAddSASToSharedcontext: DM_DSTATE_NOT_STARTED\n"));
6564285809Sscottl        DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6565285809Sscottl        DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6566285809Sscottl        oneDeviceData->valid = agTRUE;
6567285809Sscottl      }
6568285809Sscottl      else
6569285809Sscottl      {
6570285809Sscottl        if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START)
6571285809Sscottl        {
6572285809Sscottl          DM_DBG3(("dmAddSASToSharedcontext: incremental discovery\n"));
6573285809Sscottl          DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6574285809Sscottl          DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6575285809Sscottl          oneDeviceData->valid2 = agTRUE;
6576285809Sscottl        }
6577285809Sscottl        else
6578285809Sscottl        {
6579285809Sscottl          DM_DBG3(("dmAddSASToSharedcontext: full discovery\n"));
6580285809Sscottl          DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6581285809Sscottl          DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6582285809Sscottl         oneDeviceData->valid = agTRUE;
6583285809Sscottl        }
6584285809Sscottl      }
6585285809Sscottl      /* add the devicedata to the portcontext */
6586285809Sscottl      tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK);
6587285809Sscottl      DMLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->MainLink), &(dmAllShared->MainDeviceList));
6588285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK);
6589285809Sscottl      DM_DBG3(("dmAddSASToSharedcontext: one case pid %d did %d \n", onePortContext->id, oneDeviceData->id));
6590285809Sscottl      DM_DBG3(("dmAddSASToSharedcontext: new case pid %d did %d phyID %d\n", onePortContext->id, oneDeviceData->id, oneDeviceData->phyID));
6591285809Sscottl      }
6592285809Sscottl  }
6593285809Sscottl  else /* old device */
6594285809Sscottl  {
6595285809Sscottl    DM_DBG3(("dmAddSASToSharedcontext: old device\n"));
6596285809Sscottl    DM_DBG3(("dmAddSASToSharedcontext: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
6597285809Sscottl    DM_DBG3(("dmAddSASToSharedcontext: sasAddressHi 0x%08x sasAddressLo 0x%08x\n",
6598285809Sscottl    dmSASSubID->sasAddressHi, dmSASSubID->sasAddressLo));
6599285809Sscottl
6600285809Sscottl    oneDeviceData->dmRoot = dmRoot;
6601285809Sscottl    /* saving sas address */
6602285809Sscottl    oneDeviceData->SASAddressID.sasAddressLo = dmSASSubID->sasAddressLo;
6603285809Sscottl    oneDeviceData->SASAddressID.sasAddressHi = dmSASSubID->sasAddressHi;
6604285809Sscottl    oneDeviceData->initiator_ssp_stp_smp = dmSASSubID->initiator_ssp_stp_smp;
6605285809Sscottl    oneDeviceData->target_ssp_stp_smp = dmSASSubID->target_ssp_stp_smp;
6606285809Sscottl    oneDeviceData->dmPortContext = onePortContext;
6607285809Sscottl    /* handles both SAS target and STP-target, SATA-device */
6608285809Sscottl    if (!DEVICE_IS_SATA_DEVICE(oneDeviceData) && !DEVICE_IS_STP_TARGET(oneDeviceData))
6609285809Sscottl    {
6610285809Sscottl      oneDeviceData->DeviceType = DM_SAS_DEVICE;
6611285809Sscottl    }
6612285809Sscottl    else
6613285809Sscottl    {
6614285809Sscottl      oneDeviceData->DeviceType = DM_SATA_DEVICE;
6615285809Sscottl    }
6616285809Sscottl
6617285809Sscottl    if (oneExpDeviceData != agNULL)
6618285809Sscottl    {
6619285809Sscottl      oneDeviceData->ExpDevice = oneExpDeviceData;
6620285809Sscottl    }
6621285809Sscottl
6622285809Sscottl    /* set phyID only when it has initial value of 0xFF */
6623285809Sscottl    if (oneDeviceData->phyID == 0xFF)
6624285809Sscottl    {
6625285809Sscottl      oneDeviceData->phyID = phyID;
6626285809Sscottl    }
6627285809Sscottl
6628285809Sscottl    if (onePortContext->DiscoveryState == DM_DSTATE_NOT_STARTED)
6629285809Sscottl    {
6630285809Sscottl      DM_DBG3(("dmAddSASToSharedcontext: DM_DSTATE_NOT_STARTED\n"));
6631285809Sscottl      DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6632285809Sscottl      DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6633285809Sscottl      oneDeviceData->valid = agTRUE;
6634285809Sscottl    }
6635285809Sscottl    else
6636285809Sscottl    {
6637285809Sscottl      if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START)
6638285809Sscottl      {
6639285809Sscottl        DM_DBG3(("dmAddSASToSharedcontext: incremental discovery\n"));
6640285809Sscottl        DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6641285809Sscottl        DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6642285809Sscottl        oneDeviceData->valid2 = agTRUE;
6643285809Sscottl      }
6644285809Sscottl      else
6645285809Sscottl      {
6646285809Sscottl        DM_DBG3(("dmAddSASToSharedcontext: full discovery\n"));
6647285809Sscottl        DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
6648285809Sscottl        DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
6649285809Sscottl        oneDeviceData->valid = agTRUE;
6650285809Sscottl      }
6651285809Sscottl    }
6652285809Sscottl    DM_DBG3(("dmAddSASToSharedcontext: old case pid %d did %d phyID %d\n", onePortContext->id, oneDeviceData->id, oneDeviceData->phyID));
6653285809Sscottl
6654285809Sscottl  }
6655285809Sscottl  return oneDeviceData;
6656285809Sscottl}
6657285809Sscottl
6658285809Sscottl/* no checking of valid and valid2 */
6659285809SscottlosGLOBAL dmDeviceData_t *
6660285809SscottldmDeviceFind(
6661285809Sscottl             dmRoot_t            *dmRoot,
6662285809Sscottl             dmIntPortContext_t  *onePortContext,
6663285809Sscottl             bit32               sasAddrHi,
6664285809Sscottl             bit32               sasAddrLo
6665285809Sscottl            )
6666285809Sscottl{
6667285809Sscottl  dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6668285809Sscottl  dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6669285809Sscottl  dmDeviceData_t            *oneDeviceData = agNULL;
6670285809Sscottl  dmList_t                  *DeviceListList;
6671285809Sscottl  bit32                     found = agFALSE;
6672285809Sscottl
6673285809Sscottl  DM_DBG3(("dmDeviceFind: start\n"));
6674285809Sscottl  /* find a device's existence */
6675285809Sscottl  DeviceListList = dmAllShared->MainDeviceList.flink;
6676285809Sscottl
6677285809Sscottl  while (DeviceListList != &(dmAllShared->MainDeviceList))
6678285809Sscottl  {
6679285809Sscottl    oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList);
6680285809Sscottl    if (oneDeviceData == agNULL)
6681285809Sscottl    {
6682285809Sscottl      DM_DBG1(("dmDeviceFind: oneDeviceData is NULL!!!\n"));
6683285809Sscottl      return agNULL;
6684285809Sscottl    }
6685285809Sscottl    if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) &&
6686285809Sscottl        (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) &&
6687285809Sscottl//        (oneDeviceData->valid == agTRUE) &&
6688285809Sscottl        (oneDeviceData->dmPortContext == onePortContext)
6689285809Sscottl        )
6690285809Sscottl    {
6691285809Sscottl      DM_DBG3(("dmDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
6692285809Sscottl      DM_DBG3(("dmDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
6693285809Sscottl      DM_DBG3(("dmDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
6694285809Sscottl      found = agTRUE;
6695285809Sscottl      break;
6696285809Sscottl    }
6697285809Sscottl    DeviceListList = DeviceListList->flink;
6698285809Sscottl  }
6699285809Sscottl
6700285809Sscottl  if (found == agFALSE)
6701285809Sscottl  {
6702285809Sscottl    DM_DBG3(("dmDeviceFind: end returning NULL\n"));
6703285809Sscottl    return agNULL;
6704285809Sscottl  }
6705285809Sscottl  else
6706285809Sscottl  {
6707285809Sscottl    DM_DBG3(("dmDeviceFind: end returning NOT NULL\n"));
6708285809Sscottl    return oneDeviceData;
6709285809Sscottl  }
6710285809Sscottl
6711285809Sscottl}
6712285809Sscottl
6713285809Sscottl
6714285809SscottlosGLOBAL void
6715285809SscottldmBCTimer(
6716285809Sscottl          dmRoot_t                 *dmRoot,
6717285809Sscottl          dmIntPortContext_t       *onePortContext
6718285809Sscottl         )
6719285809Sscottl{
6720285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6721285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6722285809Sscottl  dmDiscovery_t     *discovery;
6723285809Sscottl
6724285809Sscottl  DM_DBG3(("dmBCTimer: start\n"));
6725285809Sscottl
6726285809Sscottl  discovery = &(onePortContext->discovery);
6727285809Sscottl
6728285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
6729285809Sscottl  if (discovery->BCTimer.timerRunning == agTRUE)
6730285809Sscottl  {
6731285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6732285809Sscottl    dmKillTimer(
6733285809Sscottl                dmRoot,
6734285809Sscottl                &discovery->BCTimer
6735285809Sscottl               );
6736285809Sscottl  }
6737285809Sscottl  else
6738285809Sscottl  {
6739285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6740285809Sscottl  }
6741285809Sscottl
6742285809Sscottl  if (onePortContext->valid == agTRUE)
6743285809Sscottl  {
6744285809Sscottl    dmSetTimerRequest(
6745285809Sscottl                      dmRoot,
6746285809Sscottl                      &discovery->BCTimer,
6747285809Sscottl                      BC_TIMER_VALUE/dmAllShared->usecsPerTick,
6748285809Sscottl                      dmBCTimerCB,
6749285809Sscottl                      onePortContext,
6750285809Sscottl                      agNULL,
6751285809Sscottl                      agNULL
6752285809Sscottl                      );
6753285809Sscottl
6754285809Sscottl    dmAddTimer(
6755285809Sscottl               dmRoot,
6756285809Sscottl               &dmAllShared->timerlist,
6757285809Sscottl               &discovery->BCTimer
6758285809Sscottl              );
6759285809Sscottl
6760285809Sscottl  }
6761285809Sscottl
6762285809Sscottl
6763285809Sscottl  return;
6764285809Sscottl}
6765285809Sscottl
6766285809Sscottl
6767285809SscottlosGLOBAL void
6768285809SscottldmBCTimerCB(
6769285809Sscottl              dmRoot_t    * dmRoot,
6770285809Sscottl              void        * timerData1,
6771285809Sscottl              void        * timerData2,
6772285809Sscottl              void        * timerData3
6773285809Sscottl              )
6774285809Sscottl{
6775285809Sscottl  dmIntPortContext_t        *onePortContext;
6776285809Sscottl  dmDiscovery_t             *discovery;
6777285809Sscottl
6778285809Sscottl  DM_DBG3(("dmBCTimerCB: start\n"));
6779285809Sscottl
6780285809Sscottl  onePortContext = (dmIntPortContext_t *)timerData1;
6781285809Sscottl  discovery = &(onePortContext->discovery);
6782285809Sscottl
6783285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
6784285809Sscottl  if (discovery->BCTimer.timerRunning == agTRUE)
6785285809Sscottl  {
6786285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6787285809Sscottl    dmKillTimer(
6788285809Sscottl               dmRoot,
6789285809Sscottl               &discovery->BCTimer
6790285809Sscottl               );
6791285809Sscottl  }
6792285809Sscottl  else
6793285809Sscottl  {
6794285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6795285809Sscottl  }
6796285809Sscottl
6797285809Sscottl  discovery->ResetTriggerred = agFALSE;
6798285809Sscottl
6799285809Sscottl  if (onePortContext->valid == agTRUE)
6800285809Sscottl  {
6801285809Sscottl    dmDiscover(dmRoot,
6802285809Sscottl               onePortContext->dmPortContext,
6803285809Sscottl               DM_DISCOVERY_OPTION_INCREMENTAL_START
6804285809Sscottl               );
6805285809Sscottl  }
6806285809Sscottl  return;
6807285809Sscottl}
6808285809Sscottl
6809285809Sscottl/* discovery related SMP timers */
6810285809SscottlosGLOBAL void
6811285809SscottldmDiscoverySMPTimer(dmRoot_t                 *dmRoot,
6812285809Sscottl                    dmIntPortContext_t       *onePortContext,
6813285809Sscottl                    bit32                    functionCode,
6814285809Sscottl                    dmSMPRequestBody_t       *dmSMPRequestBody
6815285809Sscottl                   )
6816285809Sscottl{
6817285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6818285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6819285809Sscottl  dmDiscovery_t     *discovery;
6820285809Sscottl
6821285809Sscottl  DM_DBG3(("dmDiscoverySMPTimer: start\n"));
6822285809Sscottl  DM_DBG3(("dmDiscoverySMPTimer: pid %d SMPFn 0x%x\n", onePortContext->id, functionCode));
6823285809Sscottl
6824285809Sscottl  /* start the SMP timer which works as SMP application timer */
6825285809Sscottl  discovery = &(onePortContext->discovery);
6826285809Sscottl
6827285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
6828285809Sscottl  if (discovery->DiscoverySMPTimer.timerRunning == agTRUE)
6829285809Sscottl  {
6830285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6831285809Sscottl    dmKillTimer(
6832285809Sscottl              dmRoot,
6833285809Sscottl              &discovery->DiscoverySMPTimer
6834285809Sscottl              );
6835285809Sscottl  }
6836285809Sscottl  else
6837285809Sscottl  {
6838285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6839285809Sscottl  }
6840285809Sscottl
6841285809Sscottl
6842285809Sscottl  dmSetTimerRequest(
6843285809Sscottl                    dmRoot,
6844285809Sscottl                    &discovery->DiscoverySMPTimer,
6845285809Sscottl                    SMP_TIMER_VALUE/dmAllShared->usecsPerTick,
6846285809Sscottl                    dmDiscoverySMPTimerCB,
6847285809Sscottl                    onePortContext,
6848285809Sscottl                    dmSMPRequestBody,
6849285809Sscottl                    agNULL
6850285809Sscottl                   );
6851285809Sscottl
6852285809Sscottl  dmAddTimer (
6853285809Sscottl              dmRoot,
6854285809Sscottl              &dmAllShared->timerlist,
6855285809Sscottl              &discovery->DiscoverySMPTimer
6856285809Sscottl              );
6857285809Sscottl
6858285809Sscottl  return;
6859285809Sscottl}
6860285809Sscottl
6861285809Sscottl
6862285809SscottlosGLOBAL void
6863285809SscottldmDiscoverySMPTimerCB(
6864285809Sscottl                        dmRoot_t    * dmRoot,
6865285809Sscottl                        void        * timerData1,
6866285809Sscottl                        void        * timerData2,
6867285809Sscottl                        void        * timerData3
6868285809Sscottl                       )
6869285809Sscottl{
6870285809Sscottl  agsaRoot_t                  *agRoot;
6871285809Sscottl  dmIntPortContext_t          *onePortContext;
6872285809Sscottl  bit8                        SMPFunction;
6873285809Sscottl#ifndef DIRECT_SMP
6874285809Sscottl  dmSMPFrameHeader_t          *dmSMPFrameHeader;
6875285809Sscottl  bit8                        smpHeader[4];
6876285809Sscottl#endif
6877285809Sscottl  dmSMPRequestBody_t          *dmSMPRequestBody;
6878285809Sscottl  dmDiscovery_t               *discovery;
6879285809Sscottl  dmDeviceData_t              *oneDeviceData;
6880285809Sscottl  agsaIORequest_t             *agAbortIORequest = agNULL;
6881285809Sscottl  agsaIORequest_t             *agToBeAbortIORequest = agNULL;
6882285809Sscottl  dmIntRoot_t                 *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6883285809Sscottl  dmIntContext_t              *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
6884285809Sscottl  dmExpander_t                *oneExpander = agNULL;
6885285809Sscottl  dmSMPRequestBody_t          *dmAbortSMPRequestBody = agNULL;
6886285809Sscottl  dmList_t                    *SMPList;
6887285809Sscottl
6888285809Sscottl  DM_DBG1(("dmDiscoverySMPTimerCB: start!!!\n"));
6889285809Sscottl
6890285809Sscottl  onePortContext = (dmIntPortContext_t *)timerData1;
6891285809Sscottl  dmSMPRequestBody = (dmSMPRequestBody_t *)timerData2;
6892285809Sscottl
6893285809Sscottl  discovery = &(onePortContext->discovery);
6894285809Sscottl  oneDeviceData = dmSMPRequestBody->dmDevice;
6895285809Sscottl  agToBeAbortIORequest = &(dmSMPRequestBody->agIORequest);
6896285809Sscottl  agRoot = dmAllShared->agRoot;
6897285809Sscottl
6898285809Sscottl#ifdef DIRECT_SMP
6899285809Sscottl  SMPFunction = dmSMPRequestBody->smpPayload[1];
6900285809Sscottl#else
6901285809Sscottl  saFrameReadBlock(agRoot, dmSMPRequestBody->IndirectSMP, 0, smpHeader, 4);
6902285809Sscottl  dmSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader;
6903285809Sscottl  SMPFunction = dmSMPFrameHeader->smpFunction;
6904285809Sscottl#endif
6905285809Sscottl
6906285809Sscottl  DM_DBG3(("dmDiscoverySMPTimerCB: SMP function 0x%x\n", SMPFunction));
6907285809Sscottl
6908285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
6909285809Sscottl  if (discovery->DiscoverySMPTimer.timerRunning == agTRUE)
6910285809Sscottl  {
6911285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6912285809Sscottl    dmKillTimer(
6913285809Sscottl                  dmRoot,
6914285809Sscottl                  &discovery->DiscoverySMPTimer
6915285809Sscottl                 );
6916285809Sscottl  }
6917285809Sscottl  else
6918285809Sscottl  {
6919285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
6920285809Sscottl  }
6921285809Sscottl
6922285809Sscottl//for debugging
6923285809Sscottl//  saGetPendingPICI(agRoot);
6924285809Sscottl
6925285809Sscottl  switch (SMPFunction)
6926285809Sscottl  {
6927285809Sscottl  case SMP_REPORT_GENERAL: /* fall through */
6928285809Sscottl  case SMP_DISCOVER:  /* fall through */
6929285809Sscottl  case SMP_CONFIGURE_ROUTING_INFORMATION:  /* fall through */
6930285809Sscottl    DM_DBG1(("dmDiscoverySMPTimerCB: failing discovery, SMP function 0x%x !!!\n", SMPFunction));
6931285809Sscottl    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
6932285809Sscottl    return; /* no more things to do */
6933285809Sscottl  case SMP_REPORT_PHY_SATA:
6934285809Sscottl    DM_DBG1(("dmDiscoverySMPTimerCB: failing discovery, SMP function SMP_REPORT_PHY_SATA !!!\n"));
6935285809Sscottl    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
6936285809Sscottl    break;
6937285809Sscottl  default:
6938285809Sscottl    /* do nothing */
6939285809Sscottl    DM_DBG1(("dmDiscoverySMPTimerCB: Error, not allowed case!!!\n"));
6940285809Sscottl    break;
6941285809Sscottl  }
6942285809Sscottl
6943285809Sscottl  if (oneDeviceData->registered == agTRUE && (oneDeviceData->valid == agTRUE || oneDeviceData->valid2 == agTRUE) )
6944285809Sscottl  {
6945285809Sscottl    /* call to saSMPAbort(one) */
6946285809Sscottl    /* get an smp REQUEST from the free list */
6947285809Sscottl    tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
6948285809Sscottl    if (DMLIST_EMPTY(&(dmAllShared->freeSMPList)))
6949285809Sscottl    {
6950285809Sscottl      DM_DBG1(("dmDiscoverySMPTimerCB: no free SMP, can't abort SMP!!!\n"));
6951285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
6952285809Sscottl      return;
6953285809Sscottl    }
6954285809Sscottl    else
6955285809Sscottl    {
6956285809Sscottl      DMLIST_DEQUEUE_FROM_HEAD(&SMPList, &(dmAllShared->freeSMPList));
6957285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
6958285809Sscottl      dmAbortSMPRequestBody = DMLIST_OBJECT_BASE(dmSMPRequestBody_t, Link, SMPList);
6959285809Sscottl      if (dmAbortSMPRequestBody == agNULL)
6960285809Sscottl      {
6961285809Sscottl        DM_DBG1(("dmDiscoverySMPTimerCB: dmAbortSMPRequestBody is NULL!!!\n"));
6962285809Sscottl        return;
6963285809Sscottl      }
6964285809Sscottl      DM_DBG5(("dmDiscoverySMPTimerCB: SMP id %d\n", dmAbortSMPRequestBody->id));
6965285809Sscottl    }
6966285809Sscottl
6967285809Sscottl    dmAbortSMPRequestBody->dmRoot = dmRoot;
6968285809Sscottl
6969285809Sscottl    agAbortIORequest = &(dmAbortSMPRequestBody->agIORequest);
6970285809Sscottl    agAbortIORequest->osData = (void *) dmAbortSMPRequestBody;
6971285809Sscottl    agAbortIORequest->sdkData = agNULL; /* SALL takes care of this */
6972285809Sscottl
6973285809Sscottl    oneExpander = oneDeviceData->dmExpander;
6974285809Sscottl
6975285809Sscottl    DM_DBG1(("dmDiscoverySMPTimerCB: calling saSMPAbort!!!\n"));
6976285809Sscottl    saSMPAbort(agRoot,
6977285809Sscottl               agAbortIORequest,
6978285809Sscottl               0,
6979285809Sscottl               oneExpander->agDevHandle,
6980285809Sscottl               0, /* abort one */
6981285809Sscottl               agToBeAbortIORequest,
6982285809Sscottl               dmSMPAbortCB
6983285809Sscottl              );
6984285809Sscottl  }
6985285809Sscottl  return;
6986285809Sscottl}
6987285809Sscottl
6988285809Sscottl
6989285809Sscottl
6990285809Sscottl
6991285809SscottlosGLOBAL void
6992285809SscottldmSMPBusyTimer(dmRoot_t             *dmRoot,
6993285809Sscottl               dmIntPortContext_t   *onePortContext,
6994285809Sscottl               dmDeviceData_t       *oneDeviceData,
6995285809Sscottl               dmSMPRequestBody_t   *dmSMPRequestBody
6996285809Sscottl              )
6997285809Sscottl{
6998285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
6999285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7000285809Sscottl  dmDiscovery_t     *discovery;
7001285809Sscottl
7002285809Sscottl  DM_DBG3(("dmSMPBusyTimer: start\n"));
7003285809Sscottl  DM_DBG3(("dmSMPBusyTimer: pid %d\n", onePortContext->id));
7004285809Sscottl
7005285809Sscottl  discovery = &(onePortContext->discovery);
7006285809Sscottl
7007285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7008285809Sscottl  if (discovery->SMPBusyTimer.timerRunning == agTRUE)
7009285809Sscottl  {
7010285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7011285809Sscottl    dmKillTimer(
7012285809Sscottl              dmRoot,
7013285809Sscottl              &discovery->SMPBusyTimer
7014285809Sscottl              );
7015285809Sscottl  }
7016285809Sscottl  else
7017285809Sscottl  {
7018285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7019285809Sscottl  }
7020285809Sscottl
7021285809Sscottl  dmSetTimerRequest(
7022285809Sscottl                    dmRoot,
7023285809Sscottl                    &discovery->SMPBusyTimer,
7024285809Sscottl                    SMP_BUSY_TIMER_VALUE/dmAllShared->usecsPerTick,
7025285809Sscottl                    dmSMPBusyTimerCB,
7026285809Sscottl                    onePortContext,
7027285809Sscottl                    oneDeviceData,
7028285809Sscottl                    dmSMPRequestBody
7029285809Sscottl                    );
7030285809Sscottl
7031285809Sscottl  dmAddTimer (
7032285809Sscottl              dmRoot,
7033285809Sscottl              &dmAllShared->timerlist,
7034285809Sscottl              &discovery->SMPBusyTimer
7035285809Sscottl              );
7036285809Sscottl
7037285809Sscottl
7038285809Sscottl  return;
7039285809Sscottl}
7040285809Sscottl
7041285809SscottlosGLOBAL void
7042285809SscottldmSMPBusyTimerCB(
7043285809Sscottl                 dmRoot_t    * dmRoot,
7044285809Sscottl                 void        * timerData1,
7045285809Sscottl                 void        * timerData2,
7046285809Sscottl                 void        * timerData3
7047285809Sscottl                )
7048285809Sscottl{
7049285809Sscottl  dmIntRoot_t                 *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
7050285809Sscottl  dmIntContext_t              *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7051285809Sscottl  agsaRoot_t                  *agRoot;
7052285809Sscottl  dmIntPortContext_t          *onePortContext;
7053285809Sscottl  dmDeviceData_t              *oneDeviceData;
7054285809Sscottl  dmSMPRequestBody_t          *dmSMPRequestBody;
7055285809Sscottl  agsaSASRequestBody_t        *agSASRequestBody;
7056285809Sscottl  agsaIORequest_t             *agIORequest;
7057285809Sscottl  agsaDevHandle_t             *agDevHandle;
7058285809Sscottl  dmDiscovery_t               *discovery;
7059285809Sscottl  bit32                       status = AGSA_RC_FAILURE;
7060285809Sscottl  dmExpander_t                *oneExpander = agNULL;
7061285809Sscottl
7062285809Sscottl
7063285809Sscottl  DM_DBG3(("dmSMPBusyTimerCB: start\n"));
7064285809Sscottl
7065285809Sscottl  onePortContext = (dmIntPortContext_t *)timerData1;
7066285809Sscottl  oneDeviceData = (dmDeviceData_t *)timerData2;
7067285809Sscottl  dmSMPRequestBody = (dmSMPRequestBody_t *)timerData3;
7068285809Sscottl  agRoot = dmAllShared->agRoot;
7069285809Sscottl  agIORequest = &(dmSMPRequestBody->agIORequest);
7070285809Sscottl  oneExpander = oneDeviceData->dmExpander;
7071285809Sscottl  agDevHandle = oneExpander->agDevHandle;
7072285809Sscottl  agSASRequestBody = &(dmSMPRequestBody->agSASRequestBody);
7073285809Sscottl  discovery = &(onePortContext->discovery);
7074285809Sscottl
7075285809Sscottl  discovery->SMPRetries++;
7076285809Sscottl
7077285809Sscottl  if (discovery->SMPRetries < SMP_BUSY_RETRIES)
7078285809Sscottl  {
7079285809Sscottl    status = saSMPStart(
7080285809Sscottl                         agRoot,
7081285809Sscottl                         agIORequest,
7082285809Sscottl                         0,
7083285809Sscottl                         agDevHandle,
7084285809Sscottl                         AGSA_SMP_INIT_REQ,
7085285809Sscottl                         agSASRequestBody,
7086285809Sscottl                         &dmsaSMPCompleted
7087285809Sscottl                         );
7088285809Sscottl  }
7089285809Sscottl
7090285809Sscottl  if (status == AGSA_RC_SUCCESS)
7091285809Sscottl  {
7092285809Sscottl    discovery->SMPRetries = 0;
7093285809Sscottl    tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7094285809Sscottl    if (discovery->SMPBusyTimer.timerRunning == agTRUE)
7095285809Sscottl    {
7096285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7097285809Sscottl      dmKillTimer(
7098285809Sscottl                    dmRoot,
7099285809Sscottl                    &discovery->SMPBusyTimer
7100285809Sscottl                   );
7101285809Sscottl    }
7102285809Sscottl    else
7103285809Sscottl    {
7104285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7105285809Sscottl    }
7106285809Sscottl  }
7107285809Sscottl  else if (status == AGSA_RC_FAILURE)
7108285809Sscottl  {
7109285809Sscottl    tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7110285809Sscottl    if (discovery->SMPBusyTimer.timerRunning == agTRUE)
7111285809Sscottl    {
7112285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7113285809Sscottl      dmKillTimer(
7114285809Sscottl                    dmRoot,
7115285809Sscottl                    &discovery->SMPBusyTimer
7116285809Sscottl                   );
7117285809Sscottl    }
7118285809Sscottl    else
7119285809Sscottl    {
7120285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7121285809Sscottl    }
7122285809Sscottl
7123285809Sscottl    discovery->SMPRetries = 0;
7124285809Sscottl    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
7125285809Sscottl  }
7126285809Sscottl  else /* AGSA_RC_BUSY */
7127285809Sscottl  {
7128285809Sscottl    if (discovery->SMPRetries >= SMP_BUSY_RETRIES)
7129285809Sscottl    {
7130285809Sscottl      /* done with retris; give up */
7131285809Sscottl      DM_DBG3(("dmSMPBusyTimerCB: retries are over\n"));
7132285809Sscottl
7133285809Sscottl      tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7134285809Sscottl      if (discovery->SMPBusyTimer.timerRunning == agTRUE)
7135285809Sscottl      {
7136285809Sscottl        tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7137285809Sscottl        dmKillTimer(
7138285809Sscottl                      dmRoot,
7139285809Sscottl                      &discovery->SMPBusyTimer
7140285809Sscottl                     );
7141285809Sscottl      }
7142285809Sscottl      else
7143285809Sscottl      {
7144285809Sscottl        tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7145285809Sscottl      }
7146285809Sscottl
7147285809Sscottl      discovery->SMPRetries = 0;
7148285809Sscottl      dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
7149285809Sscottl
7150285809Sscottl    }
7151285809Sscottl    else
7152285809Sscottl    {
7153285809Sscottl      /* keep retrying */
7154285809Sscottl      dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody);
7155285809Sscottl    }
7156285809Sscottl  }
7157285809Sscottl
7158285809Sscottl  return;
7159285809Sscottl}
7160285809Sscottl
7161285809Sscottl
7162285809Sscottl/* expander configuring timer */
7163285809SscottlosGLOBAL void
7164285809SscottldmDiscoveryConfiguringTimer(dmRoot_t                 *dmRoot,
7165285809Sscottl                            dmIntPortContext_t       *onePortContext,
7166285809Sscottl                            dmDeviceData_t           *oneDeviceData
7167285809Sscottl                           )
7168285809Sscottl{
7169285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
7170285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7171285809Sscottl  dmDiscovery_t     *discovery;
7172285809Sscottl
7173285809Sscottl  DM_DBG3(("dmDiscoveryConfiguringTimer: start\n"));
7174285809Sscottl  DM_DBG3(("dmDiscoveryConfiguringTimer: pid %d\n", onePortContext->id));
7175285809Sscottl
7176285809Sscottl  discovery = &(onePortContext->discovery);
7177285809Sscottl
7178285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7179285809Sscottl  if (discovery->discoveryTimer.timerRunning == agTRUE)
7180285809Sscottl  {
7181285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7182285809Sscottl    dmKillTimer(
7183285809Sscottl              dmRoot,
7184285809Sscottl              &discovery->discoveryTimer
7185285809Sscottl              );
7186285809Sscottl  }
7187285809Sscottl  else
7188285809Sscottl  {
7189285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7190285809Sscottl  }
7191285809Sscottl
7192285809Sscottl  DM_DBG3(("dmDiscoveryConfiguringTimer: UsecsPerTick %d\n", dmAllShared->usecsPerTick));
7193285809Sscottl  DM_DBG3(("dmDiscoveryConfiguringTimer: Timervalue %d\n", DISCOVERY_CONFIGURING_TIMER_VALUE/dmAllShared->usecsPerTick));
7194285809Sscottl
7195285809Sscottl  dmSetTimerRequest(
7196285809Sscottl                    dmRoot,
7197285809Sscottl                    &discovery->discoveryTimer,
7198285809Sscottl                    DISCOVERY_CONFIGURING_TIMER_VALUE/dmAllShared->usecsPerTick,
7199285809Sscottl                    dmDiscoveryConfiguringTimerCB,
7200285809Sscottl                    onePortContext,
7201285809Sscottl                    oneDeviceData,
7202285809Sscottl                    agNULL
7203285809Sscottl                   );
7204285809Sscottl
7205285809Sscottl  dmAddTimer (
7206285809Sscottl              dmRoot,
7207285809Sscottl              &dmAllShared->timerlist,
7208285809Sscottl              &discovery->discoveryTimer
7209285809Sscottl              );
7210285809Sscottl
7211285809Sscottl
7212285809Sscottl  return;
7213285809Sscottl}
7214285809Sscottl
7215285809Sscottl
7216285809SscottlosGLOBAL void
7217285809SscottldmDiscoveryConfiguringTimerCB(
7218285809Sscottl                              dmRoot_t    * dmRoot,
7219285809Sscottl                              void        * timerData1,
7220285809Sscottl                              void        * timerData2,
7221285809Sscottl                              void        * timerData3
7222285809Sscottl                             )
7223285809Sscottl{
7224285809Sscottl  dmIntPortContext_t     *onePortContext = agNULL;
7225285809Sscottl  dmDiscovery_t          *discovery      = agNULL;
7226285809Sscottl  dmDeviceData_t         *oneDeviceData  = agNULL;
7227285809Sscottl
7228285809Sscottl  onePortContext = (dmIntPortContext_t *)timerData1;
7229285809Sscottl  oneDeviceData  = (dmDeviceData_t *)timerData2;
7230285809Sscottl  discovery = &(onePortContext->discovery);
7231285809Sscottl
7232285809Sscottl  DM_DBG3(("dmDiscoveryConfiguringTimerCB: start\n"));
7233285809Sscottl
7234285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7235285809Sscottl  if (discovery->discoveryTimer.timerRunning == agTRUE)
7236285809Sscottl  {
7237285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7238285809Sscottl    dmKillTimer(
7239285809Sscottl               dmRoot,
7240285809Sscottl               &discovery->discoveryTimer
7241285809Sscottl               );
7242285809Sscottl  }
7243285809Sscottl  else
7244285809Sscottl  {
7245285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7246285809Sscottl  }
7247285809Sscottl
7248285809Sscottl  if (oneDeviceData->valid == agTRUE || oneDeviceData->valid2 == agTRUE)
7249285809Sscottl  {
7250285809Sscottl    dmReportGeneralSend(dmRoot, oneDeviceData);
7251285809Sscottl  }
7252285809Sscottl  return;
7253285809Sscottl}
7254285809Sscottl
7255285809SscottlosGLOBAL void
7256285809SscottldmConfigureRouteTimer(dmRoot_t                 *dmRoot,
7257285809Sscottl                      dmIntPortContext_t       *onePortContext,
7258285809Sscottl                      dmExpander_t             *oneExpander,
7259285809Sscottl                      smpRespDiscover_t        *pdmSMPDiscoverResp,
7260285809Sscottl                      smpRespDiscover2_t       *pdmSMPDiscover2Resp
7261285809Sscottl                     )
7262285809Sscottl{
7263285809Sscottl  dmIntRoot_t       *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
7264285809Sscottl  dmIntContext_t    *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7265285809Sscottl  dmDiscovery_t     *discovery;
7266285809Sscottl
7267285809Sscottl  DM_DBG3(("dmConfigureRouteTimer: start\n"));
7268285809Sscottl
7269285809Sscottl  DM_DBG3(("dmConfigureRouteTimer: pid %d\n", onePortContext->id));
7270285809Sscottl
7271285809Sscottl  discovery = &(onePortContext->discovery);
7272285809Sscottl
7273285809Sscottl  DM_DBG3(("dmConfigureRouteTimer: onePortContext %p oneExpander %p pdmSMPDiscoverResp %p\n", onePortContext, oneExpander, pdmSMPDiscoverResp));
7274285809Sscottl
7275285809Sscottl  DM_DBG3(("dmConfigureRouteTimer: discovery %p \n", discovery));
7276285809Sscottl
7277285809Sscottl  DM_DBG3(("dmConfigureRouteTimer:  pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries));
7278285809Sscottl
7279285809Sscottl  DM_DBG3(("dmConfigureRouteTimer: discovery->status %d\n", discovery->status));
7280285809Sscottl
7281285809Sscottl  tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7282285809Sscottl  if (discovery->configureRouteTimer.timerRunning == agTRUE)
7283285809Sscottl  {
7284285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7285285809Sscottl    dmKillTimer(
7286285809Sscottl              dmRoot,
7287285809Sscottl              &discovery->configureRouteTimer
7288285809Sscottl              );
7289285809Sscottl  }
7290285809Sscottl  else
7291285809Sscottl  {
7292285809Sscottl    tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7293285809Sscottl  }
7294285809Sscottl
7295285809Sscottl  DM_DBG3(("dmConfigureRouteTimer: UsecsPerTick %d\n", dmAllShared->usecsPerTick));
7296285809Sscottl  DM_DBG3(("dmConfigureRouteTimer: Timervalue %d\n", CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick));
7297285809Sscottl
7298285809Sscottl  if (oneExpander->SAS2 == 0)
7299285809Sscottl  {
7300285809Sscottl    /* SAS 1.1 */
7301285809Sscottl    dmSetTimerRequest(
7302285809Sscottl                      dmRoot,
7303285809Sscottl                      &discovery->configureRouteTimer,
7304285809Sscottl                      CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick,
7305285809Sscottl                      dmConfigureRouteTimerCB,
7306285809Sscottl                      (void *)onePortContext,
7307285809Sscottl                      (void *)oneExpander,
7308285809Sscottl                      (void *)pdmSMPDiscoverResp
7309285809Sscottl                     );
7310285809Sscottl  }
7311285809Sscottl  else
7312285809Sscottl  {
7313285809Sscottl    /* SAS 2 */
7314285809Sscottl    dmSetTimerRequest(
7315285809Sscottl                      dmRoot,
7316285809Sscottl                      &discovery->configureRouteTimer,
7317285809Sscottl                      CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick,
7318285809Sscottl                      dmConfigureRouteTimerCB,
7319285809Sscottl                      (void *)onePortContext,
7320285809Sscottl                      (void *)oneExpander,
7321285809Sscottl                      (void *)pdmSMPDiscover2Resp
7322285809Sscottl                     );
7323285809Sscottl  }
7324285809Sscottl  dmAddTimer (
7325285809Sscottl              dmRoot,
7326285809Sscottl              &dmAllShared->timerlist,
7327285809Sscottl              &discovery->configureRouteTimer
7328285809Sscottl              );
7329285809Sscottl
7330285809Sscottl  return;
7331285809Sscottl}
7332285809Sscottl
7333285809Sscottl
7334285809SscottlosGLOBAL void
7335285809SscottldmConfigureRouteTimerCB(
7336285809Sscottl                        dmRoot_t    * dmRoot,
7337285809Sscottl                        void        * timerData1,
7338285809Sscottl                        void        * timerData2,
7339285809Sscottl                        void        * timerData3
7340285809Sscottl                       )
7341285809Sscottl{
7342285809Sscottl  dmIntRoot_t         *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
7343285809Sscottl  dmIntContext_t      *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
7344285809Sscottl  dmIntPortContext_t  *onePortContext;
7345285809Sscottl  dmExpander_t        *oneExpander;
7346285809Sscottl  smpRespDiscover_t   *pdmSMPDiscoverResp = agNULL;
7347285809Sscottl  smpRespDiscover2_t  *pdmSMPDiscover2Resp = agNULL;
7348285809Sscottl  dmDiscovery_t       *discovery;
7349285809Sscottl
7350285809Sscottl
7351285809Sscottl  DM_DBG3(("dmConfigureRouteTimerCB: start\n"));
7352285809Sscottl
7353285809Sscottl  onePortContext = (dmIntPortContext_t *)timerData1;
7354285809Sscottl  oneExpander = (dmExpander_t *)timerData2;
7355285809Sscottl  if (oneExpander->SAS2 == 0)
7356285809Sscottl  {
7357285809Sscottl    pdmSMPDiscoverResp = (smpRespDiscover_t *)timerData3;
7358285809Sscottl  }
7359285809Sscottl  else
7360285809Sscottl  {
7361285809Sscottl    pdmSMPDiscover2Resp = (smpRespDiscover2_t *)timerData3;
7362285809Sscottl  }
7363285809Sscottl  discovery = &(onePortContext->discovery);
7364285809Sscottl
7365285809Sscottl  DM_DBG3(("dmConfigureRouteTimerCB: onePortContext %p oneExpander %p pdmSMPDiscoverResp %p\n", onePortContext, oneExpander, pdmSMPDiscoverResp));
7366285809Sscottl
7367285809Sscottl  DM_DBG3(("dmConfigureRouteTimerCB: discovery %p\n", discovery));
7368285809Sscottl
7369285809Sscottl  DM_DBG3(("dmConfigureRouteTimerCB: pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries));
7370285809Sscottl
7371285809Sscottl  DM_DBG3(("dmConfigureRouteTimerCB: discovery.status %d\n", discovery->status));
7372285809Sscottl
7373285809Sscottl  discovery->configureRouteRetries++;
7374285809Sscottl  if (discovery->configureRouteRetries >= dmAllShared->MaxRetryDiscovery)
7375285809Sscottl  {
7376285809Sscottl    DM_DBG3(("dmConfigureRouteTimerCB: retries are over\n"));
7377285809Sscottl
7378285809Sscottl    tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
7379285809Sscottl    if (discovery->configureRouteTimer.timerRunning == agTRUE)
7380285809Sscottl    {
7381285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7382285809Sscottl      dmKillTimer(
7383285809Sscottl                  dmRoot,
7384285809Sscottl                  &discovery->configureRouteTimer
7385285809Sscottl                  );
7386285809Sscottl    }
7387285809Sscottl    else
7388285809Sscottl    {
7389285809Sscottl      tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
7390285809Sscottl    }
7391285809Sscottl
7392285809Sscottl    discovery->configureRouteRetries = 0;
7393285809Sscottl    /* failed the discovery */
7394285809Sscottl    dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
7395285809Sscottl
7396285809Sscottl    return;
7397285809Sscottl  }
7398285809Sscottl
7399285809Sscottl
7400285809Sscottl  if (oneExpander->SAS2 == 0)
7401285809Sscottl  {
7402285809Sscottl    if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
7403285809Sscottl    {
7404285809Sscottl      DM_DBG3(("dmConfigureRouteTimerCB: proceed by calling dmDownStreamDiscoverExpanderPhy\n"));
7405285809Sscottl      dmhexdump("dmConfigureRouteTimerCB", (bit8*)pdmSMPDiscoverResp, sizeof(smpRespDiscover_t));
7406285809Sscottl      discovery->configureRouteRetries = 0;
7407285809Sscottl
7408285809Sscottl      dmDownStreamDiscoverExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp);
7409285809Sscottl    }
7410285809Sscottl    else
7411285809Sscottl    {
7412285809Sscottl      DM_DBG3(("dmConfigureRouteTimerCB: setting timer again\n"));
7413285809Sscottl      /* set the timer again */
7414285809Sscottl      dmSetTimerRequest(
7415285809Sscottl                        dmRoot,
7416285809Sscottl                        &discovery->configureRouteTimer,
7417285809Sscottl                        CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick,
7418285809Sscottl                        dmConfigureRouteTimerCB,
7419285809Sscottl                        (void *)onePortContext,
7420285809Sscottl                        (void *)oneExpander,
7421285809Sscottl                        (void *)pdmSMPDiscoverResp
7422285809Sscottl                       );
7423285809Sscottl
7424285809Sscottl      dmAddTimer (
7425285809Sscottl                  dmRoot,
7426285809Sscottl                  &dmAllShared->timerlist,
7427285809Sscottl                  &discovery->configureRouteTimer
7428285809Sscottl                  );
7429285809Sscottl    }
7430285809Sscottl  } /* SAS 1.1 */
7431285809Sscottl  else
7432285809Sscottl  {
7433285809Sscottl    /* SAS 2 */
7434285809Sscottl    if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
7435285809Sscottl    {
7436285809Sscottl      DM_DBG2(("dmConfigureRouteTimerCB: proceed by calling dmDownStreamDiscover2ExpanderPhy\n"));
7437285809Sscottl      dmhexdump("dmConfigureRouteTimerCB", (bit8*)pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t));
7438285809Sscottl
7439285809Sscottl      dmDownStreamDiscover2ExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscover2Resp);
7440285809Sscottl    }
7441285809Sscottl    else
7442285809Sscottl    {
7443285809Sscottl      DM_DBG2(("dmConfigureRouteTimerCB: setting timer again\n"));
7444285809Sscottl      /* set the timer again */
7445285809Sscottl      dmSetTimerRequest(
7446285809Sscottl                        dmRoot,
7447285809Sscottl                        &discovery->configureRouteTimer,
7448285809Sscottl                        CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick,
7449285809Sscottl                        dmConfigureRouteTimerCB,
7450285809Sscottl                        (void *)onePortContext,
7451285809Sscottl                        (void *)oneExpander,
7452285809Sscottl                        (void *)pdmSMPDiscover2Resp
7453285809Sscottl                       );
7454285809Sscottl
7455285809Sscottl      dmAddTimer (
7456285809Sscottl                  dmRoot,
7457285809Sscottl                  &dmAllShared->timerlist,
7458285809Sscottl                  &discovery->configureRouteTimer
7459285809Sscottl                 );
7460285809Sscottl    }
7461285809Sscottl  }
7462285809Sscottl
7463285809Sscottl  return;
7464285809Sscottl}
7465285809Sscottl#endif /* FDS_ DM */
7466285809Sscottl
7467