1/*******************************************************************************
2*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
3*
4*Redistribution and use in source and binary forms, with or without modification, are permitted provided
5*that the following conditions are met:
6*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7*following disclaimer.
8*2. Redistributions in binary form must reproduce the above copyright notice,
9*this list of conditions and the following disclaimer in the documentation and/or other materials provided
10*with the distribution.
11*
12*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20
21********************************************************************************/
22#include <sys/cdefs.h>
23__FBSDID("$FreeBSD$");
24#include <dev/pms/config.h>
25
26#include <dev/pms/freebsd/driver/common/osenv.h>
27#include <dev/pms/freebsd/driver/common/ostypes.h>
28#include <dev/pms/freebsd/driver/common/osdebug.h>
29
30#include <dev/pms/RefTisa/sallsdk/api/sa.h>
31#include <dev/pms/RefTisa/sallsdk/api/saapi.h>
32#include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
33
34#ifdef FDS_DM
35#include <dev/pms/RefTisa/discovery/api/dm.h>
36#include <dev/pms/RefTisa/discovery/api/dmapi.h>
37#include <dev/pms/RefTisa/discovery/api/tddmapi.h>
38
39#include <dev/pms/RefTisa/discovery/dm/dmdefs.h>
40#include <dev/pms/RefTisa/discovery/dm/dmtypes.h>
41#include <dev/pms/RefTisa/discovery/dm/dmproto.h>
42
43/*****************************************************************************/
44/*! \brief dmCreatePort
45 *
46 *
47 *  Purpose: A port context is created by this function
48 *
49 *  \param   dmRoot:              DM context handle.
50 *  \param   dmPortContext:       Pointer to this instance of port context
51 *
52 *  \return:
53 *          DM_RC_SUCCESS
54 *          DM_RC_FAILURE
55 *
56 */
57/*****************************************************************************/
58osGLOBAL bit32
59dmCreatePort(
60             dmRoot_t        *dmRoot,
61             dmPortContext_t *dmPortContext,
62             dmPortInfo_t    *dmPortInfo)
63{
64  dmIntRoot_t               *dmIntRoot    = agNULL;
65  dmIntContext_t            *dmAllShared = agNULL;
66  dmIntPortContext_t        *onePortContext = agNULL;
67  dmList_t                  *PortContextList = agNULL;
68
69  DM_DBG3(("dmCreatePort: start\n"));
70
71  if (dmRoot == agNULL)
72  {
73    DM_DBG1(("dmCreatePort: dmRoot is NULL, wrong!!!\n"));
74    return DM_RC_FAILURE;
75  }
76
77  if (dmPortContext == agNULL)
78  {
79    DM_DBG1(("dmCreatePort: dmPortContext is NULL, wrong!!!\n"));
80    return DM_RC_FAILURE;
81  }
82
83  /* the duplicacy of a port is checked */
84  if (dmPortContext->dmData != agNULL)
85  {
86    DM_DBG1(("dmCreatePort: dmPortContext->dmData is not NULL, wrong, Already created!!!\n"));
87    return DM_RC_FAILURE;
88  }
89
90  if (dmPortInfo == agNULL)
91  {
92    DM_DBG1(("dmCreatePort: dmPortInfo is NULL, wrong!!!\n"));
93    return DM_RC_FAILURE;
94  }
95
96  dmIntRoot = (dmIntRoot_t *)dmRoot->dmData;
97
98  if (dmIntRoot == agNULL)
99  {
100    DM_DBG1(("dmCreatePort: dmIntRoot is NULL, wrong!!!\n"));
101    return DM_RC_FAILURE;
102  }
103
104  dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
105
106  if (dmAllShared == agNULL)
107  {
108    DM_DBG1(("dmCreatePort: dmAllShared is NULL, wrong!!!\n"));
109    return DM_RC_FAILURE;
110  }
111
112  tddmSingleThreadedEnter(dmRoot, DM_PORT_LOCK);
113  if (DMLIST_NOT_EMPTY(&(dmAllShared->FreePortContextList)))
114  {
115    DMLIST_DEQUEUE_FROM_HEAD(&PortContextList, &(dmAllShared->FreePortContextList));
116    tddmSingleThreadedLeave(dmRoot, DM_PORT_LOCK);
117    onePortContext = DMLIST_OBJECT_BASE(dmIntPortContext_t, FreeLink, PortContextList);
118    if (onePortContext == agNULL)
119    {
120      DM_DBG1(("dmCreatePort: onePortContext is NULL in allocation, wrong!!!\n"));
121      return DM_RC_FAILURE;
122    }
123
124    dmPortContext->dmData =  onePortContext;
125    onePortContext->DiscoveryState = DM_DSTATE_NOT_STARTED;
126    onePortContext->discoveryOptions = DM_DISCOVERY_OPTION_FULL_START;
127
128    onePortContext->dmRoot = dmRoot;
129    onePortContext->dmPortContext = dmPortContext;
130    onePortContext->valid = agTRUE;
131    onePortContext->RegFailed = agFALSE;
132
133    onePortContext->LinkRate = DM_GET_LINK_RATE(dmPortInfo->flag);
134    DM_DBG3(("dmCreatePort: linkrate %0x\n", onePortContext->LinkRate));
135
136    onePortContext->sasRemoteAddressHi = DM_GET_SAS_ADDRESSHI(dmPortInfo->sasRemoteAddressHi);
137    onePortContext->sasRemoteAddressLo = DM_GET_SAS_ADDRESSLO(dmPortInfo->sasRemoteAddressLo);
138    onePortContext->sasLocalAddressHi = DM_GET_SAS_ADDRESSHI(dmPortInfo->sasLocalAddressHi);
139    onePortContext->sasLocalAddressLo = DM_GET_SAS_ADDRESSLO(dmPortInfo->sasLocalAddressLo);
140    DM_DBG3(("dmCreatePort: pid %d\n", onePortContext->id));
141    DM_DBG3(("dmCreatePort: RemoteAddrHi 0x%08x RemoteAddrLo 0x%08x\n", onePortContext->sasRemoteAddressHi, onePortContext->sasRemoteAddressLo));
142    DM_DBG3(("dmCreatePort: LocalAddrHi 0x%08x LocaAddrLo 0x%08x\n", onePortContext->sasLocalAddressHi, onePortContext->sasLocalAddressLo));
143
144    tddmSingleThreadedEnter(dmRoot, DM_PORT_LOCK);
145    DMLIST_ENQUEUE_AT_TAIL(&(onePortContext->MainLink), &(dmAllShared->MainPortContextList));
146    tddmSingleThreadedLeave(dmRoot, DM_PORT_LOCK);
147  }
148  else
149  {
150    tddmSingleThreadedLeave(dmRoot, DM_PORT_LOCK);
151    DM_DBG1(("dmCreatePort: Attention. no more free PortContext!!!\n"));
152    return DM_RC_FAILURE;
153  }
154
155  return DM_RC_SUCCESS;
156}
157
158/*****************************************************************************/
159/*! \brief dmDestroyPort
160 *
161 *
162 *  Purpose: A port context is destroyed by this function
163 *
164 *  \param   dmRoot:              DM context handle.
165 *  \param   dmPortContext:       Pointer to this instance of port context
166 *
167 *  \return:
168 *          DM_RC_SUCCESS
169 *          DM_RC_FAILURE
170 *
171 */
172/*****************************************************************************/
173osGLOBAL bit32
174dmDestroyPort(
175          dmRoot_t        *dmRoot,
176          dmPortContext_t *dmPortContext,
177          dmPortInfo_t    *dmPortInfo)
178{
179  dmIntRoot_t               *dmIntRoot    = agNULL;
180  dmIntContext_t            *dmAllShared = agNULL;
181  dmIntPortContext_t        *onePortContext = agNULL;
182
183  DM_DBG1(("dmDestroyPort: start\n"));
184  if (dmRoot == agNULL)
185  {
186    DM_DBG1(("dmDestroyPort: dmRoot is NULL, wrong!!!\n"));
187    return DM_RC_FAILURE;
188  }
189
190  if (dmPortContext == agNULL)
191  {
192    DM_DBG1(("dmDestroyPort: dmPortContext is NULL, wrong!!!\n"));
193    return DM_RC_FAILURE;
194  }
195
196  if (dmPortInfo == agNULL)
197  {
198    DM_DBG1(("dmDestroyPort: dmPortInfo is NULL, wrong!!!\n"));
199    return DM_RC_FAILURE;
200  }
201
202  dmIntRoot = (dmIntRoot_t *)dmRoot->dmData;
203
204  if (dmIntRoot == agNULL)
205  {
206    DM_DBG1(("dmDestroyPort: dmIntRoot is NULL, wrong!!!\n"));
207    return DM_RC_FAILURE;
208  }
209
210  dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
211
212  if (dmAllShared == agNULL)
213  {
214    DM_DBG1(("dmDestroyPort: dmAllShared is NULL, wrong!!!\n"));
215    return DM_RC_FAILURE;
216  }
217
218  /*
219    no device(expander) to be removed since all devices should
220    be in freelist at the end of discovery
221    But if the discovery is in progress, abort it and clean up
222  */
223  onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
224
225  if (onePortContext == agNULL)
226  {
227    DM_DBG1(("dmDestroyPort: onePortContext is NULL, wrong!!!\n"));
228    return DM_RC_FAILURE;
229  }
230
231#if 1
232  if (onePortContext->DiscoveryState != DM_DSTATE_COMPLETED)
233  {
234    dmDiscoverAbort(dmRoot, onePortContext);
235  }
236  else
237  {
238    /* move devices from dmAllShared->MainDeviceList to dmAllShared->FreeDeviceList; dmDiscoveryDeviceCleanUp()
239       move from dmAllShared->mainExpanderList to dmAllShared->freeExpanderList; dmDiscoveryExpanderCleanUp()
240    */
241  }
242#endif
243
244  if (onePortContext->DiscoveryState != DM_DSTATE_COMPLETED)
245  {
246    /* move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList
247       move from dmAllShared->UpdiscoveringExpanderList to dmAllShared->mainExpanderList
248    */
249    dmCleanAllExp(dmRoot, onePortContext);
250  }
251
252  /* move mainExpanderList then MainDeviceList */
253  DM_DBG3(("dmDestroyPort: before dmDiscoveryExpanderCleanUp\n"));
254  dmDumpAllMainExp(dmRoot, onePortContext);
255
256  /* move from dmAllShared->mainExpanderList to dmAllShared->freeExpanderList */
257  dmDiscoveryExpanderCleanUp(dmRoot, onePortContext);
258
259  DM_DBG3(("dmDestroyPort: after dmDiscoveryExpanderCleanUp\n"));
260  dmDumpAllMainExp(dmRoot, onePortContext);
261
262  DM_DBG3(("dmDestroyPort: before dmDiscoveryDeviceCleanUp\n"));
263  dmDumpAllMainDevice(dmRoot, onePortContext);
264  /* move devices from dmAllShared->MainDeviceList to dmAllShared->FreeDeviceList */
265  dmDiscoveryDeviceCleanUp(dmRoot, onePortContext);
266
267  DM_DBG3(("dmDestroyPort: after dmDiscoveryDeviceCleanUp\n"));
268  dmDumpAllMainDevice(dmRoot, onePortContext);
269
270  dmPortContextReInit(dmRoot, onePortContext);
271
272  tddmSingleThreadedEnter(dmRoot, DM_PORT_LOCK);
273
274  if (DMLIST_NOT_EMPTY(&(onePortContext->MainLink)))
275  {
276    DMLIST_DEQUEUE_THIS(&(onePortContext->MainLink));
277  }
278  else
279  {
280    DM_DBG1(("dmDestroyPort: onePortContext->MainLink is NULL, wrong!!!\n"));
281  }
282
283  if (DMLIST_NOT_EMPTY(&(onePortContext->FreeLink)) && DMLIST_NOT_EMPTY(&(dmAllShared->FreePortContextList)))
284  {
285    DMLIST_ENQUEUE_AT_TAIL(&(onePortContext->FreeLink), &(dmAllShared->FreePortContextList));
286  }
287  else
288  {
289    DM_DBG1(("dmDestroyPort: onePortContext->FreeLink or dmAllShared->FreePortContextList is NULL, wrong!!!\n"));
290  }
291
292  tddmSingleThreadedLeave(dmRoot, DM_PORT_LOCK);
293
294  return DM_RC_SUCCESS;
295}
296#endif /* FDS_ DM */
297
298
299
300
301
302
303
304
305