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#include <dev/pms/config.h>
24
25#include <dev/pms/freebsd/driver/common/osenv.h>
26#include <dev/pms/freebsd/driver/common/ostypes.h>
27#include <dev/pms/freebsd/driver/common/osdebug.h>
28
29#include <dev/pms/RefTisa/sallsdk/api/sa.h>
30#include <dev/pms/RefTisa/sallsdk/api/saapi.h>
31#include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
32
33#ifdef FDS_DM
34#include <dev/pms/RefTisa/discovery/api/dm.h>
35#include <dev/pms/RefTisa/discovery/api/dmapi.h>
36#include <dev/pms/RefTisa/discovery/api/tddmapi.h>
37
38#include <dev/pms/RefTisa/discovery/dm/dmdefs.h>
39#include <dev/pms/RefTisa/discovery/dm/dmtypes.h>
40#include <dev/pms/RefTisa/discovery/dm/dmproto.h>
41
42/*****************************************************************************/
43/*! \brief dmCreatePort
44 *
45 *
46 *  Purpose: A port context is created by this function
47 *
48 *  \param   dmRoot:              DM context handle.
49 *  \param   dmPortContext:       Pointer to this instance of port context
50 *
51 *  \return:
52 *          DM_RC_SUCCESS
53 *          DM_RC_FAILURE
54 *
55 */
56/*****************************************************************************/
57osGLOBAL bit32
58dmCreatePort(
59             dmRoot_t        *dmRoot,
60             dmPortContext_t *dmPortContext,
61             dmPortInfo_t    *dmPortInfo)
62{
63  dmIntRoot_t               *dmIntRoot    = agNULL;
64  dmIntContext_t            *dmAllShared = agNULL;
65  dmIntPortContext_t        *onePortContext = agNULL;
66  dmList_t                  *PortContextList = agNULL;
67
68  DM_DBG3(("dmCreatePort: start\n"));
69
70  if (dmRoot == agNULL)
71  {
72    DM_DBG1(("dmCreatePort: dmRoot is NULL, wrong!!!\n"));
73    return DM_RC_FAILURE;
74  }
75
76  if (dmPortContext == agNULL)
77  {
78    DM_DBG1(("dmCreatePort: dmPortContext is NULL, wrong!!!\n"));
79    return DM_RC_FAILURE;
80  }
81
82  /* the duplicacy of a port is checked */
83  if (dmPortContext->dmData != agNULL)
84  {
85    DM_DBG1(("dmCreatePort: dmPortContext->dmData is not NULL, wrong, Already created!!!\n"));
86    return DM_RC_FAILURE;
87  }
88
89  if (dmPortInfo == agNULL)
90  {
91    DM_DBG1(("dmCreatePort: dmPortInfo is NULL, wrong!!!\n"));
92    return DM_RC_FAILURE;
93  }
94
95  dmIntRoot = (dmIntRoot_t *)dmRoot->dmData;
96
97  if (dmIntRoot == agNULL)
98  {
99    DM_DBG1(("dmCreatePort: dmIntRoot is NULL, wrong!!!\n"));
100    return DM_RC_FAILURE;
101  }
102
103  dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
104
105  if (dmAllShared == agNULL)
106  {
107    DM_DBG1(("dmCreatePort: dmAllShared is NULL, wrong!!!\n"));
108    return DM_RC_FAILURE;
109  }
110
111  tddmSingleThreadedEnter(dmRoot, DM_PORT_LOCK);
112  if (DMLIST_NOT_EMPTY(&(dmAllShared->FreePortContextList)))
113  {
114    DMLIST_DEQUEUE_FROM_HEAD(&PortContextList, &(dmAllShared->FreePortContextList));
115    tddmSingleThreadedLeave(dmRoot, DM_PORT_LOCK);
116    onePortContext = DMLIST_OBJECT_BASE(dmIntPortContext_t, FreeLink, PortContextList);
117    if (onePortContext == agNULL)
118    {
119      DM_DBG1(("dmCreatePort: onePortContext is NULL in allocation, wrong!!!\n"));
120      return DM_RC_FAILURE;
121    }
122
123    dmPortContext->dmData =  onePortContext;
124    onePortContext->DiscoveryState = DM_DSTATE_NOT_STARTED;
125    onePortContext->discoveryOptions = DM_DISCOVERY_OPTION_FULL_START;
126
127    onePortContext->dmRoot = dmRoot;
128    onePortContext->dmPortContext = dmPortContext;
129    onePortContext->valid = agTRUE;
130    onePortContext->RegFailed = agFALSE;
131
132    onePortContext->LinkRate = DM_GET_LINK_RATE(dmPortInfo->flag);
133    DM_DBG3(("dmCreatePort: linkrate %0x\n", onePortContext->LinkRate));
134
135    onePortContext->sasRemoteAddressHi = DM_GET_SAS_ADDRESSHI(dmPortInfo->sasRemoteAddressHi);
136    onePortContext->sasRemoteAddressLo = DM_GET_SAS_ADDRESSLO(dmPortInfo->sasRemoteAddressLo);
137    onePortContext->sasLocalAddressHi = DM_GET_SAS_ADDRESSHI(dmPortInfo->sasLocalAddressHi);
138    onePortContext->sasLocalAddressLo = DM_GET_SAS_ADDRESSLO(dmPortInfo->sasLocalAddressLo);
139    DM_DBG3(("dmCreatePort: pid %d\n", onePortContext->id));
140    DM_DBG3(("dmCreatePort: RemoteAddrHi 0x%08x RemoteAddrLo 0x%08x\n", onePortContext->sasRemoteAddressHi, onePortContext->sasRemoteAddressLo));
141    DM_DBG3(("dmCreatePort: LocalAddrHi 0x%08x LocaAddrLo 0x%08x\n", onePortContext->sasLocalAddressHi, onePortContext->sasLocalAddressLo));
142
143    tddmSingleThreadedEnter(dmRoot, DM_PORT_LOCK);
144    DMLIST_ENQUEUE_AT_TAIL(&(onePortContext->MainLink), &(dmAllShared->MainPortContextList));
145    tddmSingleThreadedLeave(dmRoot, DM_PORT_LOCK);
146  }
147  else
148  {
149    tddmSingleThreadedLeave(dmRoot, DM_PORT_LOCK);
150    DM_DBG1(("dmCreatePort: Attention. no more free PortContext!!!\n"));
151    return DM_RC_FAILURE;
152  }
153
154  return DM_RC_SUCCESS;
155}
156
157/*****************************************************************************/
158/*! \brief dmDestroyPort
159 *
160 *
161 *  Purpose: A port context is destroyed by this function
162 *
163 *  \param   dmRoot:              DM context handle.
164 *  \param   dmPortContext:       Pointer to this instance of port context
165 *
166 *  \return:
167 *          DM_RC_SUCCESS
168 *          DM_RC_FAILURE
169 *
170 */
171/*****************************************************************************/
172osGLOBAL bit32
173dmDestroyPort(
174          dmRoot_t        *dmRoot,
175          dmPortContext_t *dmPortContext,
176          dmPortInfo_t    *dmPortInfo)
177{
178  dmIntRoot_t               *dmIntRoot    = agNULL;
179  dmIntContext_t            *dmAllShared = agNULL;
180  dmIntPortContext_t        *onePortContext = agNULL;
181
182  DM_DBG1(("dmDestroyPort: start\n"));
183  if (dmRoot == agNULL)
184  {
185    DM_DBG1(("dmDestroyPort: dmRoot is NULL, wrong!!!\n"));
186    return DM_RC_FAILURE;
187  }
188
189  if (dmPortContext == agNULL)
190  {
191    DM_DBG1(("dmDestroyPort: dmPortContext is NULL, wrong!!!\n"));
192    return DM_RC_FAILURE;
193  }
194
195  if (dmPortInfo == agNULL)
196  {
197    DM_DBG1(("dmDestroyPort: dmPortInfo is NULL, wrong!!!\n"));
198    return DM_RC_FAILURE;
199  }
200
201  dmIntRoot = (dmIntRoot_t *)dmRoot->dmData;
202
203  if (dmIntRoot == agNULL)
204  {
205    DM_DBG1(("dmDestroyPort: dmIntRoot is NULL, wrong!!!\n"));
206    return DM_RC_FAILURE;
207  }
208
209  dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
210
211  if (dmAllShared == agNULL)
212  {
213    DM_DBG1(("dmDestroyPort: dmAllShared is NULL, wrong!!!\n"));
214    return DM_RC_FAILURE;
215  }
216
217  /*
218    no device(expander) to be removed since all devices should
219    be in freelist at the end of discovery
220    But if the discovery is in progress, abort it and clean up
221  */
222  onePortContext = (dmIntPortContext_t *)dmPortContext->dmData;
223
224  if (onePortContext == agNULL)
225  {
226    DM_DBG1(("dmDestroyPort: onePortContext is NULL, wrong!!!\n"));
227    return DM_RC_FAILURE;
228  }
229
230#if 1
231  if (onePortContext->DiscoveryState != DM_DSTATE_COMPLETED)
232  {
233    dmDiscoverAbort(dmRoot, onePortContext);
234  }
235  else
236  {
237    /* move devices from dmAllShared->MainDeviceList to dmAllShared->FreeDeviceList; dmDiscoveryDeviceCleanUp()
238       move from dmAllShared->mainExpanderList to dmAllShared->freeExpanderList; dmDiscoveryExpanderCleanUp()
239    */
240  }
241#endif
242
243  if (onePortContext->DiscoveryState != DM_DSTATE_COMPLETED)
244  {
245    /* move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList
246       move from dmAllShared->UpdiscoveringExpanderList to dmAllShared->mainExpanderList
247    */
248    dmCleanAllExp(dmRoot, onePortContext);
249  }
250
251  /* move mainExpanderList then MainDeviceList */
252  DM_DBG3(("dmDestroyPort: before dmDiscoveryExpanderCleanUp\n"));
253  dmDumpAllMainExp(dmRoot, onePortContext);
254
255  /* move from dmAllShared->mainExpanderList to dmAllShared->freeExpanderList */
256  dmDiscoveryExpanderCleanUp(dmRoot, onePortContext);
257
258  DM_DBG3(("dmDestroyPort: after dmDiscoveryExpanderCleanUp\n"));
259  dmDumpAllMainExp(dmRoot, onePortContext);
260
261  DM_DBG3(("dmDestroyPort: before dmDiscoveryDeviceCleanUp\n"));
262  dmDumpAllMainDevice(dmRoot, onePortContext);
263  /* move devices from dmAllShared->MainDeviceList to dmAllShared->FreeDeviceList */
264  dmDiscoveryDeviceCleanUp(dmRoot, onePortContext);
265
266  DM_DBG3(("dmDestroyPort: after dmDiscoveryDeviceCleanUp\n"));
267  dmDumpAllMainDevice(dmRoot, onePortContext);
268
269  dmPortContextReInit(dmRoot, onePortContext);
270
271  tddmSingleThreadedEnter(dmRoot, DM_PORT_LOCK);
272
273  if (DMLIST_NOT_EMPTY(&(onePortContext->MainLink)))
274  {
275    DMLIST_DEQUEUE_THIS(&(onePortContext->MainLink));
276  }
277  else
278  {
279    DM_DBG1(("dmDestroyPort: onePortContext->MainLink is NULL, wrong!!!\n"));
280  }
281
282  if (DMLIST_NOT_EMPTY(&(onePortContext->FreeLink)) && DMLIST_NOT_EMPTY(&(dmAllShared->FreePortContextList)))
283  {
284    DMLIST_ENQUEUE_AT_TAIL(&(onePortContext->FreeLink), &(dmAllShared->FreePortContextList));
285  }
286  else
287  {
288    DM_DBG1(("dmDestroyPort: onePortContext->FreeLink or dmAllShared->FreePortContextList is NULL, wrong!!!\n"));
289  }
290
291  tddmSingleThreadedLeave(dmRoot, DM_PORT_LOCK);
292
293  return DM_RC_SUCCESS;
294}
295#endif /* FDS_ DM */
296
297
298
299
300
301
302
303
304