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 /*******************************************************************************/
23 /** \file
24 *
25 * This file contains initiator discover related functions
26 *
27 */
28 #include <sys/cdefs.h>
29 #include <dev/pms/config.h>
30
31 #include <dev/pms/freebsd/driver/common/osenv.h>
32 #include <dev/pms/freebsd/driver/common/ostypes.h>
33 #include <dev/pms/freebsd/driver/common/osdebug.h>
34
35 #include <dev/pms/RefTisa/sallsdk/api/sa.h>
36 #include <dev/pms/RefTisa/sallsdk/api/saapi.h>
37 #include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
38
39 #include <dev/pms/RefTisa/tisa/api/titypes.h>
40 #include <dev/pms/RefTisa/tisa/api/ostiapi.h>
41 #include <dev/pms/RefTisa/tisa/api/tiapi.h>
42 #include <dev/pms/RefTisa/tisa/api/tiglobal.h>
43
44 #ifdef FDS_SM
45 #include <dev/pms/RefTisa/sat/api/sm.h>
46 #include <dev/pms/RefTisa/sat/api/smapi.h>
47 #include <dev/pms/RefTisa/sat/api/tdsmapi.h>
48 #endif
49
50 #ifdef FDS_DM
51 #include <dev/pms/RefTisa/discovery/api/dm.h>
52 #include <dev/pms/RefTisa/discovery/api/dmapi.h>
53 #include <dev/pms/RefTisa/discovery/api/tddmapi.h>
54 #endif
55
56 #include <dev/pms/RefTisa/tisa/sassata/sas/common/tdtypes.h>
57 #include <dev/pms/freebsd/driver/common/osstring.h>
58 #include <dev/pms/RefTisa/tisa/sassata/common/tdutil.h>
59
60 #ifdef INITIATOR_DRIVER
61 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdtypes.h>
62 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itddefs.h>
63 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdglobl.h>
64 #endif
65
66 #ifdef TARGET_DRIVER
67 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdglobl.h>
68 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdxchg.h>
69 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdtypes.h>
70 #endif
71
72 #include <dev/pms/RefTisa/tisa/sassata/common/tdsatypes.h>
73 #include <dev/pms/RefTisa/tisa/sassata/common/tdproto.h>
74
75 /*****************************************************************************
76 *! \brief tiINIDiscoverTargets
77 *
78 * Purpose: This function is called to send a transport dependent discovery
79 * request. An implicit login will be started following the
80 * completion of discovery.
81 *
82 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
83 * instance.
84 * \param portalContext: Pointer to the portal context instance.
85 * \param option: This is a bit field option on how the session is to be
86 * created
87 * \return:
88 * tiSuccess Discovery initiated.
89 * tiBusy Discovery could not be initiated at this time.
90 *
91 * \note:
92 *
93 *****************************************************************************/
94 osGLOBAL bit32
tiINIDiscoverTargets(tiRoot_t * tiRoot,tiPortalContext_t * portalContext,bit32 option)95 tiINIDiscoverTargets(
96 tiRoot_t *tiRoot,
97 tiPortalContext_t *portalContext,
98 bit32 option
99 )
100 {
101 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
102 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
103 tdList_t *PortContextList;
104 tdsaPortContext_t *onePortContext = agNULL;
105 bit32 found = agFALSE;
106
107 #ifdef FDS_DM
108 dmRoot_t *dmRoot = &(tdsaAllShared->dmRoot);
109 dmPortContext_t *dmPortContext = agNULL;
110 #endif
111 /*
112 this function is called after LINK_UP by ossaHWCB()
113 Therefore, tdsaportcontext is ready at this point
114 */
115
116 TI_DBG3(("tiINIDiscoverTargets: start\n"));
117
118 /* find a right tdsaPortContext using tiPortalContext
119 then, check the status of tdsaPortContext
120 then, if status is right, start the discovery
121 */
122
123 TI_DBG6(("tiINIDiscoverTargets: portalContext %p\n", portalContext));
124 tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
125 if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
126 {
127 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
128 TI_DBG1(("tiINIDiscoverTargets: No tdsaPortContext\n"));
129 return tiError;
130 }
131 else
132 {
133 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
134 }
135
136 /* find a right portcontext */
137 PortContextList = tdsaAllShared->MainPortContextList.flink;
138 if (PortContextList == agNULL)
139 {
140 TI_DBG1(("tiINIDiscoverTargets: PortContextList is NULL\n"));
141 return tiError;
142 }
143 while (PortContextList != &(tdsaAllShared->MainPortContextList))
144 {
145 onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
146 if (onePortContext == agNULL)
147 {
148 TI_DBG1(("tiINIDiscoverTargets: onePortContext is NULL, PortContextList = %p\n", PortContextList));
149 return tiError;
150 }
151 if (onePortContext->tiPortalContext == portalContext && onePortContext->valid == agTRUE)
152 {
153 TI_DBG6(("tiINIDiscoverTargets: found; oneportContext ID %d\n", onePortContext->id));
154 found = agTRUE;
155 break;
156 }
157 PortContextList = PortContextList->flink;
158 }
159
160 if (found == agFALSE)
161 {
162 TI_DBG1(("tiINIDiscoverTargets: No corresponding tdsaPortContext\n"));
163 return tiError;
164 }
165
166 TI_DBG2(("tiINIDiscoverTargets: pid %d\n", onePortContext->id));
167 if (onePortContext->DiscoveryState == ITD_DSTATE_NOT_STARTED)
168 {
169 TI_DBG6(("tiINIDiscoverTargets: calling Discovery\n"));
170 /* start SAS discovery */
171 #ifdef FDS_DM
172 if (onePortContext->UseDM == agTRUE)
173 {
174 TI_DBG1(("tiINIDiscoverTargets: calling dmDiscover, pid %d\n", onePortContext->id));
175 onePortContext->DiscoveryState = ITD_DSTATE_STARTED;
176 dmPortContext = &(onePortContext->dmPortContext);
177 dmDiscover(dmRoot, dmPortContext, DM_DISCOVERY_OPTION_FULL_START);
178 }
179 else
180 {
181 /* complete discovery */
182 onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
183 ostiInitiatorEvent(
184 tiRoot,
185 portalContext,
186 agNULL,
187 tiIntrEventTypeDiscovery,
188 tiDiscOK,
189 agNULL
190 );
191
192 return tiSuccess;
193 }
194
195 #else
196
197 #ifdef TD_DISCOVER
198 tdsaDiscover(
199 tiRoot,
200 onePortContext,
201 AG_SA_DISCOVERY_TYPE_SAS,
202 TDSA_DISCOVERY_OPTION_FULL_START
203 );
204 #else
205 saDiscover(onePortContext->agRoot, onePortContext->agPortContext, AG_SA_DISCOVERY_TYPE_SAS, onePortContext->discoveryOptions);
206
207
208
209 #endif
210 #endif /* FDS_DM */
211 }
212 else
213 {
214 TI_DBG1(("tiINIDiscoverTargets: Discovery has started or incorrect initialization; state %d pid 0x%x\n",
215 onePortContext->DiscoveryState,
216 onePortContext->id));
217 return tiError;
218 }
219
220 return tiSuccess;
221 }
222
223 /*****************************************************************************
224 *! \brief tiINIGetDeviceHandles
225 *
226 * Purpose: This routine is called to to return the device handles for each
227 * device currently available.
228 *
229 * \param tiRoot: Pointer to driver Instance.
230 * \param tiPortalContext: Pointer to the portal context instance.
231 * \param agDev[]: Array to receive pointers to the device handles.
232 * \param maxDevs: Number of device handles which will fit in array pointed
233 * by agDev.
234 * \return:
235 * Number of device handle slots present (however, only maxDevs
236 * are copied into tiDev[]) which may be greater than the number of
237 * handles actually present. In short, returns the number of devices that
238 * were found.
239 *
240 * \note:
241 *
242 *****************************************************************************/
243 osGLOBAL bit32
tiINIGetDeviceHandles(tiRoot_t * tiRoot,tiPortalContext_t * tiPortalContext,tiDeviceHandle_t * tiDev[],bit32 maxDevs)244 tiINIGetDeviceHandles(
245 tiRoot_t * tiRoot,
246 tiPortalContext_t * tiPortalContext,
247 tiDeviceHandle_t * tiDev[],
248 bit32 maxDevs
249 )
250 {
251 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
252 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
253 tdList_t *PortContextList;
254 tdsaPortContext_t *onePortContext = agNULL;
255 tdsaDeviceData_t *oneDeviceData = agNULL;
256 tdList_t *DeviceListList;
257 bit32 i;
258 bit32 FoundDevices = 0;
259 bit32 DeviceIndex = 0;
260 bit32 found = agFALSE;
261 #ifdef TD_DEBUG_ENABLE
262 satDeviceData_t *pSatDevData;
263 #endif
264 #ifdef FDS_DM
265 dmRoot_t *dmRoot = &(tdsaAllShared->dmRoot);
266 #endif
267
268 TI_DBG2(("tiINIGetDeviceHandles: start\n"));
269 TI_DBG2(("tiINIGetDeviceHandles: tiPortalContext %p\n", tiPortalContext));
270
271
272 if (maxDevs == 0)
273 {
274 TI_DBG1(("tiINIGetDeviceHandles: maxDevs is 0\n"));
275 TI_DBG1(("tiINIGetDeviceHandles: first, returning 0\n"));
276 /* nullify all device handles */
277 for (i = 0 ; i < maxDevs ; i++)
278 {
279 tiDev[i] = agNULL;
280 }
281 return 0;
282 }
283
284 tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
285 if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
286 {
287 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
288 TI_DBG1(("tiINIGetDeviceHandles: No available tdsaPortContext\n"));
289 TI_DBG1(("tiINIGetDeviceHandles: second, returning 0\n"));
290 /* nullify all device handles */
291 for (i = 0 ; i < maxDevs ; i++)
292 {
293 tiDev[i] = agNULL;
294 }
295 return 0;
296 }
297 else
298 {
299 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
300 }
301 /* find a corresponding portcontext */
302 PortContextList = tdsaAllShared->MainPortContextList.flink;
303 while (PortContextList != &(tdsaAllShared->MainPortContextList))
304 {
305 onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
306 if(onePortContext == agNULL) continue;
307
308 TI_DBG3(("tiINIGetDeviceHandles: oneportContext pid %d\n", onePortContext->id));
309 if (onePortContext->tiPortalContext == tiPortalContext && onePortContext->valid == agTRUE)
310 {
311 TI_DBG3(("tiINIGetDeviceHandles: found; oneportContext pid %d\n", onePortContext->id));
312 found = agTRUE;
313 break;
314 }
315 PortContextList = PortContextList->flink;
316 }
317
318 if (found == agFALSE)
319 {
320 TI_DBG1(("tiINIGetDeviceHandles: First, No corresponding tdsaPortContext\n"));
321 TI_DBG1(("tiINIGetDeviceHandles: third, returning 0\n"));
322 /* nullify all device handles */
323 for (i = 0 ; i < maxDevs ; i++)
324 {
325 tiDev[i] = agNULL;
326 }
327 return 0;
328 }
329
330 if (onePortContext == agNULL)
331 {
332 TI_DBG1(("tiINIGetDeviceHandles: Second, No corressponding tdsaPortContext\n"));
333 TI_DBG1(("tiINIGetDeviceHandles: fourth, returning 0\n"));
334 /* nullify all device handles */
335 for (i = 0 ; i < maxDevs ; i++)
336 {
337 tiDev[i] = agNULL;
338 }
339 return 0;
340 }
341
342 if (onePortContext->valid == agFALSE)
343 {
344 TI_DBG1(("tiINIGetDeviceHandles: Third, tdsaPortContext is invalid, pid %d\n", onePortContext->id));
345 TI_DBG1(("tiINIGetDeviceHandles: fifth, returning 0\n"));
346 /* nullify all device handles */
347 for (i = 0 ; i < maxDevs ; i++)
348 {
349 tiDev[i] = agNULL;
350 }
351 return 0;
352 }
353
354 if (onePortContext->DiscoveryState == ITD_DSTATE_COMPLETED && onePortContext->DMDiscoveryState == dmDiscFailed)
355 {
356 TI_DBG1(("tiINIGetDeviceHandles: forth, discovery failed, pid %d\n", onePortContext->id));
357 TI_DBG1(("tiINIGetDeviceHandles: sixth, returning 0\n"));
358 /* nullify all device handles */
359 for (i = 0 ; i < maxDevs ; i++)
360 {
361 tiDev[i] = agNULL;
362 }
363 return 0;
364 }
365
366 if (onePortContext->DiscoveryState != ITD_DSTATE_COMPLETED)
367 {
368 TI_DBG1(("tiINIGetDeviceHandles: discovery not completed\n"));
369 TI_DBG1(("tiINIGetDeviceHandles: sixth, returning DISCOVERY_IN_PROGRESS, pid %d\n", onePortContext->id));
370 onePortContext->discovery.forcedOK = agTRUE;
371 return DISCOVERY_IN_PROGRESS;
372 }
373
374 TI_DBG2(("tiINIGetDeviceHandles: pid %d\n", onePortContext->id));
375
376 #ifdef FDS_DM
377 tdsaUpdateMCN(dmRoot, onePortContext);
378 #endif
379
380 /* nullify all device handles */
381 for (i = 0 ; i < maxDevs ; i++)
382 {
383 tiDev[i] = agNULL;
384 }
385
386 /*
387 From the device list, returns only valid devices
388 */
389 DeviceListList = tdsaAllShared->MainDeviceList.flink;
390
391 TD_ASSERT(DeviceListList, "DeviceListList NULL");
392 if (DeviceListList == agNULL )
393 {
394 TI_DBG1(("tiINIGetDeviceHandles: DeviceListList == agNULL\n"));
395 TI_DBG1(("tiINIGetDeviceHandles: seventh, returning not found, pid %d\n", onePortContext->id));
396 return 0;
397 }
398
399 while ((DeviceIndex < maxDevs) &&
400 DeviceListList != &(tdsaAllShared->MainDeviceList))
401 {
402 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
403 #ifdef TD_DEBUG_ENABLE
404 pSatDevData = (satDeviceData_t *)&(oneDeviceData->satDevData);
405 if (pSatDevData != agNULL)
406 {
407 TI_DBG3(("tiINIGetDeviceHandles: device %p satPendingIO %d satNCQMaxIO %d\n",pSatDevData, pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO ));
408 TI_DBG3(("tiINIGetDeviceHandles: device %p satPendingNCQIO %d satPendingNONNCQIO %d\n",pSatDevData, pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO));
409 }
410 #endif
411 TI_DBG3(("tiINIGetDeviceHandles: pid %d did %d\n", onePortContext->id, oneDeviceData->id));
412 TI_DBG3(("tiINIGetDeviceHandles: device AddrHi 0x%08x AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
413
414 TI_DBG6(("tiINIGetDeviceHandles: handle %p\n", &(oneDeviceData->tiDeviceHandle)));
415 if (oneDeviceData->tdPortContext != onePortContext)
416 {
417 TI_DBG3(("tiINIGetDeviceHandles: different port\n"));
418 DeviceListList = DeviceListList->flink;
419 }
420 else
421 {
422 #ifdef SATA_ENABLE
423 if ((oneDeviceData->valid == agTRUE) &&
424 (oneDeviceData->registered == agTRUE) &&
425 (oneDeviceData->tdPortContext == onePortContext) &&
426 ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData)
427 || DEVICE_IS_SATA_DEVICE(oneDeviceData) )
428 )
429 #else
430 if ((oneDeviceData->valid == agTRUE) &&
431 (oneDeviceData->registered == agTRUE) &&
432 (oneDeviceData->tdPortContext == onePortContext) &&
433 ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData) )
434 )
435 #endif
436 {
437 if (DEVICE_IS_SSP_TARGET(oneDeviceData))
438 {
439 TI_DBG2(("tiINIGetDeviceHandles: SSP DeviceIndex %d tiDeviceHandle %p\n", DeviceIndex, &(oneDeviceData->tiDeviceHandle)));
440 tiDev[DeviceIndex] = &(oneDeviceData->tiDeviceHandle);
441 FoundDevices++;
442 }
443 else if ( (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
444 &&
445 oneDeviceData->satDevData.IDDeviceValid == agTRUE )
446 {
447 TI_DBG2(("tiINIGetDeviceHandles: SATA DeviceIndex %d tiDeviceHandle %p\n", DeviceIndex, &(oneDeviceData->tiDeviceHandle)));
448 tiDev[DeviceIndex] = &(oneDeviceData->tiDeviceHandle);
449 FoundDevices++;
450 }
451 else
452 {
453 TI_DBG3(("tiINIGetDeviceHandles: skip case !!!\n"));
454 TI_DBG3(("tiINIGetDeviceHandles: valid %d SSP target %d STP target %d SATA device %d\n", oneDeviceData->valid, DEVICE_IS_SSP_TARGET(oneDeviceData), DEVICE_IS_STP_TARGET(oneDeviceData), DEVICE_IS_SATA_DEVICE(oneDeviceData)));
455 TI_DBG3(("tiINIGetDeviceHandles: oneDeviceData->satDevData.IDDeviceValid %d\n", oneDeviceData->satDevData.IDDeviceValid));
456 TI_DBG3(("tiINIGetDeviceHandles: registered %d right port %d \n", oneDeviceData->registered, (oneDeviceData->tdPortContext == onePortContext)));
457 TI_DBG3(("tiINIGetDeviceHandles: oneDeviceData->tdPortContext %p onePortContext %p\n", oneDeviceData->tdPortContext, onePortContext));
458 }
459 TI_DBG3(("tiINIGetDeviceHandles: valid FoundDevices %d\n", FoundDevices));
460 TI_DBG3(("tiINIGetDeviceHandles: agDevHandle %p\n", oneDeviceData->agDevHandle));
461 }
462 else
463 {
464 TI_DBG3(("tiINIGetDeviceHandles: valid %d SSP target %d STP target %d SATA device %d\n", oneDeviceData->valid, DEVICE_IS_SSP_TARGET(oneDeviceData), DEVICE_IS_STP_TARGET(oneDeviceData), DEVICE_IS_SATA_DEVICE(oneDeviceData)));
465 TI_DBG3(("tiINIGetDeviceHandles: registered %d right port %d \n", oneDeviceData->registered, (oneDeviceData->tdPortContext == onePortContext)));
466 TI_DBG3(("tiINIGetDeviceHandles: oneDeviceData->tdPortContext %p onePortContext %p\n", oneDeviceData->tdPortContext, onePortContext));
467 }
468 DeviceIndex++;
469 DeviceListList = DeviceListList->flink;
470 } /* else */
471 }
472
473 if (DeviceIndex > maxDevs)
474 {
475 TI_DBG1(("tiINIGetDeviceHandles: DeviceIndex(%d) >= maxDevs(%d)\n", DeviceIndex, maxDevs));
476 FoundDevices = maxDevs;
477 }
478
479 TI_DBG1(("tiINIGetDeviceHandles: returning %d found devices, pid %d\n", FoundDevices, onePortContext->id));
480
481 return FoundDevices;
482 }
483
484 /*****************************************************************************
485 *! \brief tiINIGetDeviceHandlesForWinIOCTL
486 *
487 * Purpose: This routine is called to to return the device handles for each
488 * device currently available, this routine is only for Win IOCTL to display SAS topology.
489 *
490 * \param tiRoot: Pointer to driver Instance.
491 * \param tiPortalContext: Pointer to the portal context instance.
492 * \param agDev[]: Array to receive pointers to the device handles.
493 * \param maxDevs: Number of device handles which will fit in array pointed
494 * by agDev.
495 * \return:
496 * Number of device handle slots present (however, only maxDevs
497 * are copied into tiDev[]) which may be greater than the number of
498 * handles actually present. In short, returns the number of devices that
499 * were found.
500 *
501 * \note:
502 *
503 *****************************************************************************/
504 osGLOBAL bit32
tiINIGetDeviceHandlesForWinIOCTL(tiRoot_t * tiRoot,tiPortalContext_t * tiPortalContext,tiDeviceHandle_t * tiDev[],bit32 maxDevs)505 tiINIGetDeviceHandlesForWinIOCTL(
506 tiRoot_t * tiRoot,
507 tiPortalContext_t * tiPortalContext,
508 tiDeviceHandle_t * tiDev[],
509 bit32 maxDevs
510 )
511 {
512 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
513 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
514 tdList_t *PortContextList;
515 tdsaPortContext_t *onePortContext = agNULL;
516 tdsaDeviceData_t *oneDeviceData = agNULL;
517 tdList_t *DeviceListList;
518 bit32 i;
519 bit32 FoundDevices = 0;
520 bit32 DeviceIndex = 0;
521 bit32 found = agFALSE;
522 #ifdef TD_DEBUG_ENABLE
523 satDeviceData_t *pSatDevData;
524 #endif
525 #ifdef FDS_DM
526 dmRoot_t *dmRoot = &(tdsaAllShared->dmRoot);
527 #endif
528
529 TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: start\n"));
530 TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: tiPortalContext %p\n", tiPortalContext));
531
532
533 if (maxDevs == 0)
534 {
535 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: maxDevs is 0\n"));
536 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: first, returning 0\n"));
537 /* nullify all device handles */
538 for (i = 0 ; i < maxDevs ; i++)
539 {
540 tiDev[i] = agNULL;
541 }
542 return 0;
543 }
544
545 tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
546 if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
547 {
548 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
549 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: No available tdsaPortContext\n"));
550 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: second, returning 0\n"));
551 /* nullify all device handles */
552 for (i = 0 ; i < maxDevs ; i++)
553 {
554 tiDev[i] = agNULL;
555 }
556 return 0;
557 }
558 else
559 {
560 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
561 }
562 /* find a corresponding portcontext */
563 PortContextList = tdsaAllShared->MainPortContextList.flink;
564 while (PortContextList != &(tdsaAllShared->MainPortContextList))
565 {
566 onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
567 if(onePortContext == agNULL) continue;
568
569 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: oneportContext pid %d\n", onePortContext->id));
570 if (onePortContext->tiPortalContext == tiPortalContext && onePortContext->valid == agTRUE)
571 {
572 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: found; oneportContext pid %d\n", onePortContext->id));
573 found = agTRUE;
574 break;
575 }
576 PortContextList = PortContextList->flink;
577 }
578
579 if (found == agFALSE)
580 {
581 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: First, No corresponding tdsaPortContext\n"));
582 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: third, returning 0\n"));
583 /* nullify all device handles */
584 for (i = 0 ; i < maxDevs ; i++)
585 {
586 tiDev[i] = agNULL;
587 }
588 return 0;
589 }
590
591 if (onePortContext == agNULL)
592 {
593 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: Second, No corressponding tdsaPortContext\n"));
594 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: fourth, returning 0\n"));
595 /* nullify all device handles */
596 for (i = 0 ; i < maxDevs ; i++)
597 {
598 tiDev[i] = agNULL;
599 }
600 return 0;
601 }
602
603 if (onePortContext->valid == agFALSE)
604 {
605 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: Third, tdsaPortContext is invalid, pid %d\n", onePortContext->id));
606 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: fifth, returning 0\n"));
607 /* nullify all device handles */
608 for (i = 0 ; i < maxDevs ; i++)
609 {
610 tiDev[i] = agNULL;
611 }
612 return 0;
613 }
614
615 if (onePortContext->DiscoveryState == ITD_DSTATE_COMPLETED && onePortContext->DMDiscoveryState == dmDiscFailed)
616 {
617 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: forth, discovery failed, pid %d\n", onePortContext->id));
618 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: sixth, returning 0\n"));
619 /* nullify all device handles */
620 for (i = 0 ; i < maxDevs ; i++)
621 {
622 tiDev[i] = agNULL;
623 }
624 return 0;
625 }
626
627 if (onePortContext->DiscoveryState != ITD_DSTATE_COMPLETED)
628 {
629 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: discovery not completed\n"));
630 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: sixth, returning DISCOVERY_IN_PROGRESS, pid %d\n", onePortContext->id));
631 onePortContext->discovery.forcedOK = agTRUE;
632 return DISCOVERY_IN_PROGRESS;
633 }
634
635 TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: pid %d\n", onePortContext->id));
636
637 #ifdef FDS_DM
638 tdsaUpdateMCN(dmRoot, onePortContext);
639 #endif
640
641 /* nullify all device handles */
642 for (i = 0 ; i < maxDevs ; i++)
643 {
644 tiDev[i] = agNULL;
645 }
646
647 /*
648 From the device list, returns only valid devices
649 */
650 DeviceListList = tdsaAllShared->MainDeviceList.flink;
651
652 TD_ASSERT(DeviceListList, "DeviceListList NULL");
653 if (DeviceListList == agNULL )
654 {
655 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: DeviceListList == agNULL\n"));
656 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: seventh, returning not found, pid %d\n", onePortContext->id));
657 return 0;
658 }
659
660 while ((DeviceIndex < maxDevs) &&
661 DeviceListList != &(tdsaAllShared->MainDeviceList))
662 {
663 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
664 if(oneDeviceData == agNULL)
665 {
666 TI_DBG3(("tiINIGetDeviceHandles: OneDeviceData is NULL\n"));
667 return 0;
668 }
669 #ifdef TD_DEBUG_ENABLE
670 pSatDevData = (satDeviceData_t *)&(oneDeviceData->satDevData);
671 if (pSatDevData != agNULL)
672 {
673 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: device %p satPendingIO %d satNCQMaxIO %d\n",pSatDevData, pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO ));
674 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: device %p satPendingNCQIO %d satPendingNONNCQIO %d\n",pSatDevData, pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO));
675 }
676 #endif
677 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: pid %d did %d\n", onePortContext->id, oneDeviceData->id));
678 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: device AddrHi 0x%08x AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
679
680 TI_DBG6(("tiINIGetDeviceHandlesForWinIOCTL: handle %p\n", &(oneDeviceData->tiDeviceHandle)));
681 if (oneDeviceData->tdPortContext != onePortContext)
682 {
683 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: different port\n"));
684 DeviceListList = DeviceListList->flink;
685 }
686 else
687 {
688 #ifdef SATA_ENABLE
689 if ((oneDeviceData->valid == agTRUE) &&
690 (oneDeviceData->registered == agTRUE) &&
691 (oneDeviceData->tdPortContext == onePortContext) &&
692 ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData)
693 || DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_SMP_TARGET(oneDeviceData))
694 )
695 #else
696 if ((oneDeviceData->valid == agTRUE) &&
697 (oneDeviceData->registered == agTRUE) &&
698 (oneDeviceData->tdPortContext == onePortContext) &&
699 ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
700 )
701 #endif
702 {
703 if (DEVICE_IS_SSP_TARGET(oneDeviceData))
704 {
705 TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: SSP DeviceIndex %d tiDeviceHandle %p\n", DeviceIndex, &(oneDeviceData->tiDeviceHandle)));
706 tiDev[DeviceIndex] = &(oneDeviceData->tiDeviceHandle);
707 DeviceIndex++;
708 FoundDevices++;
709 }
710 else if ( (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
711 &&
712 oneDeviceData->satDevData.IDDeviceValid == agTRUE )
713 {
714 TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: SATA DeviceIndex %d tiDeviceHandle %p\n", DeviceIndex, &(oneDeviceData->tiDeviceHandle)));
715 tiDev[DeviceIndex] = &(oneDeviceData->tiDeviceHandle);
716 DeviceIndex++;
717 FoundDevices++;
718 }
719 else if (DEVICE_IS_SMP_TARGET(oneDeviceData))
720 {
721 TI_DBG2(("tiINIGetDeviceHandlesForWinIOCTL: SMP DeviceIndex %d tiDeviceHandle %p\n", DeviceIndex, &(oneDeviceData->tiDeviceHandle)));
722 tiDev[DeviceIndex] = &(oneDeviceData->tiDeviceHandle);
723 DeviceIndex++;
724 FoundDevices++;
725 }
726 else
727 {
728 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: skip case !!!\n"));
729 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: valid %d SSP target %d STP target %d SATA device %d\n", oneDeviceData->valid, DEVICE_IS_SSP_TARGET(oneDeviceData), DEVICE_IS_STP_TARGET(oneDeviceData), DEVICE_IS_SATA_DEVICE(oneDeviceData)));
730 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: oneDeviceData->satDevData.IDDeviceValid %d\n", oneDeviceData->satDevData.IDDeviceValid));
731 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: registered %d right port %d \n", oneDeviceData->registered, (oneDeviceData->tdPortContext == onePortContext)));
732 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: oneDeviceData->tdPortContext %p onePortContext %p\n", oneDeviceData->tdPortContext, onePortContext));
733 }
734 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: valid FoundDevices %d\n", FoundDevices));
735 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: agDevHandle %p\n", oneDeviceData->agDevHandle));
736 }
737 else
738 {
739 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: valid %d SSP target %d STP target %d SATA device %d\n", oneDeviceData->valid, DEVICE_IS_SSP_TARGET(oneDeviceData), DEVICE_IS_STP_TARGET(oneDeviceData), DEVICE_IS_SATA_DEVICE(oneDeviceData)));
740 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: registered %d right port %d \n", oneDeviceData->registered, (oneDeviceData->tdPortContext == onePortContext)));
741 TI_DBG3(("tiINIGetDeviceHandlesForWinIOCTL: oneDeviceData->tdPortContext %p onePortContext %p\n", oneDeviceData->tdPortContext, onePortContext));
742 }
743 //DeviceIndex++;
744 DeviceListList = DeviceListList->flink;
745 } /* else */
746 }
747
748 if (DeviceIndex > maxDevs)
749 {
750 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: DeviceIndex(%d) >= maxDevs(%d)\n", DeviceIndex, maxDevs));
751 FoundDevices = maxDevs;
752 }
753
754 TI_DBG1(("tiINIGetDeviceHandlesForWinIOCTL: returning %d found devices, pid %d\n", FoundDevices, onePortContext->id));
755
756 return FoundDevices;
757 }
758
759
760 /*****************************************************************************
761 *! \brief tiINIGetDeviceInfo
762 *
763 * Purpose: This routine is called by the OS Layer find out
764 * the name associated with the device and where
765 * it is mapped (address1 and address2).
766 *
767 * \param tiRoot: Pointer to driver Instance.
768 * \param tiDeviceHandle: device handle associated with the device
769 * \param tiDeviceInfo: pointer to structure where the information
770 * needs to be copied.
771 * \return:
772 * tiSuccess - successful
773 * tiInvalidHandle - device handle passed is not a valid handle.
774 *
775 * \note:
776 *
777 *****************************************************************************/
778 osGLOBAL bit32
tiINIGetDeviceInfo(tiRoot_t * tiRoot,tiDeviceHandle_t * tiDeviceHandle,tiDeviceInfo_t * tiDeviceInfo)779 tiINIGetDeviceInfo(
780 tiRoot_t *tiRoot,
781 tiDeviceHandle_t *tiDeviceHandle,
782 tiDeviceInfo_t *tiDeviceInfo)
783 {
784 tdsaDeviceData_t *oneDeviceData = agNULL;
785 satDeviceData_t *pSatDevData = agNULL;
786 bit8 id_limit[5];
787 bit8 SN_id_limit[25];
788 agsaRoot_t *agRoot = agNULL;
789
790 TI_DBG6(("tiINIGetDeviceInfo: start \n"));
791
792 if (tiDeviceHandle == agNULL)
793 {
794 TI_DBG6(("tiINIGetDeviceInfo: tiDeviceHandle NULL\n"));
795 return tiInvalidHandle;
796 }
797
798 if (tiDeviceHandle->tdData == agNULL)
799 {
800 TI_DBG6(("tiINIGetDeviceInfo: ^^^^^^^^^ tiDeviceHandle->tdData NULL\n"));
801 return tiInvalidHandle;
802 }
803 else
804 {
805
806 oneDeviceData = (tdsaDeviceData_t *)(tiDeviceHandle->tdData);
807 agRoot = oneDeviceData->agRoot;
808 TI_DBG6(("tiINIGetDeviceInfo: ^^^^^^^^^ tiDeviceHandle->tdData NOT NULL\n"));
809 }
810 if (oneDeviceData == agNULL)
811 {
812 TI_DBG6(("tiINIGetDeviceInfo: ^^^^^^^^^ oneDeviceData NULL\n"));
813 return tiInvalidHandle;
814 }
815
816
817 /* filling in the link rate */
818 if (oneDeviceData->registered == agTRUE)
819 {
820 tiDeviceInfo->info.devType_S_Rate = oneDeviceData->agDeviceInfo.devType_S_Rate;
821 }
822 else
823 {
824 tiDeviceInfo->info.devType_S_Rate = (bit8)(oneDeviceData->agDeviceInfo.devType_S_Rate & 0x0f);
825 }
826
827 /* just returning local and remote SAS address; doesn't have a name for SATA device, returns identify device data */
828 if (DEVICE_IS_SATA_DEVICE(oneDeviceData) && (oneDeviceData->directlyAttached == agTRUE))
829 {
830 osti_memset(&id_limit, 0, sizeof(id_limit));
831 osti_memset(&SN_id_limit, 0, sizeof(SN_id_limit));
832
833 /* SATA signature 0xABCD */
834 id_limit[0] = 0xA;
835 id_limit[1] = 0xB;
836 id_limit[2] = 0xC;
837 id_limit[3] = 0xD;
838
839 pSatDevData = &(oneDeviceData->satDevData);
840 if (pSatDevData->satNCQ == agTRUE)
841 {
842 id_limit[4] = (bit8)pSatDevData->satNCQMaxIO;
843 }
844 else
845 {
846 /* no NCQ */
847 id_limit[4] = 1;
848 }
849
850 osti_memcpy(&SN_id_limit, &(oneDeviceData->satDevData.satIdentifyData.serialNumber), 20);
851 osti_memcpy(&(SN_id_limit[20]), &id_limit, 5);
852 osti_memcpy(oneDeviceData->satDevData.SN_id_limit, SN_id_limit, 25);
853 /* serialNumber, 20 bytes + ABCD + NCQ LENGTH ; modelNumber, 40 bytes */
854 // tiDeviceInfo->remoteName = (char *)&(oneDeviceData->satDevData.satIdentifyData.serialNumber);
855 tiDeviceInfo->remoteName = (char *)oneDeviceData->satDevData.SN_id_limit;
856 tiDeviceInfo->remoteAddress = (char *)&(oneDeviceData->satDevData.satIdentifyData.modelNumber);
857 // TI_DBG1(("tiINIGetDeviceInfo: SATA device remote hi 0x%08x lo 0x%08x\n", oneDeviceData->tdPortContext->sasRemoteAddressHi, oneDeviceData->tdPortContext->sasRemoteAddressLo));
858 // tdhexdump("tiINIGetDeviceInfo remotename", (bit8 *)&(oneDeviceData->satDevData.satIdentifyData.serialNumber), 20);
859 // tdhexdump("tiINIGetDeviceInfo new name", (bit8 *)&(SN_id_limit), sizeof(SN_id_limit));
860 // tdhexdump("tiINIGetDeviceInfo remoteaddress", (bit8 *)&(oneDeviceData->satDevData.satIdentifyData.modelNumber),40);
861 tiDeviceInfo->osAddress1 = 25;
862 tiDeviceInfo->osAddress2 = 40;
863
864 }
865 else if (DEVICE_IS_STP_TARGET(oneDeviceData))
866 {
867 /* serialNumber, 20 bytes; modelNumber, 40 bytes */
868 tiDeviceInfo->remoteName = (char *)&(oneDeviceData->satDevData.satIdentifyData.serialNumber);
869 tiDeviceInfo->remoteAddress = (char *)&(oneDeviceData->satDevData.satIdentifyData.modelNumber);
870 // TI_DBG1(("tiINIGetDeviceInfo: SATA device remote hi 0x%08x lo 0x%08x\n", oneDeviceData->tdPortContext->sasRemoteAddressHi, oneDeviceData->tdPortContext->sasRemoteAddressLo));
871 // tdhexdump("tiINIGetDeviceInfo remotename", (bit8 *)&(oneDeviceData->satDevData.satIdentifyData.serialNumber), 20);
872 // tdhexdump("tiINIGetDeviceInfo remoteaddress", (bit8 *)&(oneDeviceData->satDevData.satIdentifyData.modelNumber),40);
873 tiDeviceInfo->osAddress1 = 20;
874 tiDeviceInfo->osAddress2 = 40;
875 }
876 else
877 {
878 tiDeviceInfo->remoteName = (char *)&(oneDeviceData->SASAddressID.sasAddressHi);
879 tiDeviceInfo->remoteAddress = (char *)&(oneDeviceData->SASAddressID.sasAddressLo);
880 TI_DBG1(("tiINIGetDeviceInfo: SAS device remote hi 0x%08x lo 0x%08x\n", oneDeviceData->tdPortContext->sasRemoteAddressHi, oneDeviceData->tdPortContext->sasRemoteAddressLo));
881 tiDeviceInfo->osAddress1 = 4;
882 tiDeviceInfo->osAddress2 = 4;
883 }
884
885 tiDeviceInfo->localName = (char *)&(oneDeviceData->tdPortContext->sasLocalAddressHi);
886 tiDeviceInfo->localAddress = (char *)&(oneDeviceData->tdPortContext->sasLocalAddressLo);
887
888 TI_DBG6(("tiINIGetDeviceInfo: local hi 0x%08x lo 0x%08x\n", oneDeviceData->tdPortContext->sasLocalAddressHi, oneDeviceData->tdPortContext->sasLocalAddressLo));
889
890 if (oneDeviceData->agDevHandle == agNULL)
891 {
892 TI_DBG1(("tiINIGetDeviceInfo: Error! oneDeviceData->agDevHandle is NULL"));
893 return tiError;
894 }
895 else
896 {
897 saGetDeviceInfo(agRoot, agNULL, 0, 0,oneDeviceData->agDevHandle);
898 }
899
900
901 return tiSuccess;
902 }
903
904 /*****************************************************************************
905 *! \brief tiINILogin
906 *
907 * Purpose: This function is called to request that the Transport Dependent
908 * Layer initiates login for a specific target.
909 *
910 * \param tiRoot: Pointer to driver Instance.
911 * \param tiDeviceHandle: Pointer to a target device handle discovered
912 * following the discovery.
913 *
914 * \return:
915 * tiSuccess Login initiated.
916 * tiError Login failed.
917 * tiBusy Login can not be initiated at this time.
918 * tiNotSupported This API is currently not supported by this
919 * Transport Layer
920 *
921 *
922 *****************************************************************************/
923 osGLOBAL bit32
tiINILogin(tiRoot_t * tiRoot,tiDeviceHandle_t * tiDeviceHandle)924 tiINILogin(
925 tiRoot_t *tiRoot,
926 tiDeviceHandle_t *tiDeviceHandle
927 )
928 {
929 TI_DBG6(("tiINILogin: start\n"));
930 return tiNotSupported;
931 }
932
933 /*****************************************************************************
934 *! \brief tiINILogout
935 *
936 * Purpose: This function is called to request that the Transport Dependent
937 * Layer initiates logout for a specific target from the previously
938 * successful login through tiINILogin() call.
939 *
940 * \param tiRoot : Pointer to the OS Specific module allocated tiRoot_t
941 * instance.
942 * \param tiDeviceHandle: Pointer to a target device handle.
943 *
944 * \return:
945 * tiSuccess Logout initiated.
946 * tiError Logout failed.
947 * tiBusy Logout can not be initiated at this time.
948 * tiNotSupported This API is currently not supported by this
949 * Transport Layer
950 *
951 *
952 *****************************************************************************/
953 osGLOBAL bit32
tiINILogout(tiRoot_t * tiRoot,tiDeviceHandle_t * tiDeviceHandle)954 tiINILogout(
955 tiRoot_t *tiRoot,
956 tiDeviceHandle_t *tiDeviceHandle
957 )
958 {
959 TI_DBG6(("tiINILogout: start\n"));
960 return tiNotSupported;
961 }
962 /*****************************************************************************
963 *! \brief tiINIGetExpander
964 *
965 *
966 * \note:
967 *
968 *****************************************************************************/
969 osGLOBAL bit32
tiINIGetExpander(tiRoot_t * tiRoot,tiPortalContext_t * tiPortalContext,tiDeviceHandle_t * tiDev,tiDeviceHandle_t ** tiExp)970 tiINIGetExpander(
971 tiRoot_t * tiRoot,
972 tiPortalContext_t * tiPortalContext,
973 tiDeviceHandle_t * tiDev,
974 tiDeviceHandle_t ** tiExp
975 )
976 {
977 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
978 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
979 tdList_t *PortContextList;
980 tdsaPortContext_t *onePortContext = agNULL;
981 tdsaDeviceData_t *oneDeviceData = agNULL;
982 tdList_t *DeviceListList;
983 tdsaDeviceData_t *oneTargetDeviceData = agNULL;
984 tdsaDeviceData_t *oneExpanderDeviceData = agNULL;
985 bit32 found = agFALSE;
986 oneTargetDeviceData = (tdsaDeviceData_t *)tiDev->tdData;
987 if (oneTargetDeviceData == agNULL)
988 {
989 TI_DBG1(("tiINIGetExpander: oneTargetDeviceData is NULL\n"));
990 return tiError;
991 }
992 tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
993 if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
994 {
995 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
996 TI_DBG1(("tiINIGetExpander: No available tdsaPortContext\n"));
997 TI_DBG1(("tiINIGetExpander: second, returning 0\n"));
998 return tiError;
999 }
1000 else
1001 {
1002 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
1003 }
1004 /* find a corresponding portcontext */
1005 PortContextList = tdsaAllShared->MainPortContextList.flink;
1006 while (PortContextList != &(tdsaAllShared->MainPortContextList))
1007 {
1008 onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
1009 TI_DBG3(("tiINIGetExpander: oneportContext pid %d\n", onePortContext->id));
1010 if (onePortContext->tiPortalContext == tiPortalContext && onePortContext->valid == agTRUE)
1011 {
1012 TI_DBG3(("tiINIGetExpander: found; oneportContext pid %d\n", onePortContext->id));
1013 found = agTRUE;
1014 break;
1015 }
1016 PortContextList = PortContextList->flink;
1017 }
1018 if (found == agFALSE)
1019 {
1020 TI_DBG1(("tiINIGetExpander: First, No corresponding tdsaPortContext\n"));
1021 TI_DBG1(("tiINIGetExpander: third, returning 0\n"));
1022 return tiError;
1023 }
1024 if (onePortContext == agNULL)
1025 {
1026 TI_DBG1(("tiINIGetExpander: Second, No corressponding tdsaPortContext\n"));
1027 TI_DBG1(("tiINIGetExpander: fourth, returning 0\n"));
1028 return tiError;
1029 }
1030 if (onePortContext->valid == agFALSE)
1031 {
1032 TI_DBG1(("tiINIGetExpander: Third, tdsaPortContext is invalid, pid %d\n", onePortContext->id));
1033 TI_DBG1(("tiINIGetExpander: fifth, returning 0\n"));
1034 return tiError;
1035 }
1036 DeviceListList = tdsaAllShared->MainDeviceList.flink;
1037 while ( DeviceListList != &(tdsaAllShared->MainDeviceList) )
1038 {
1039 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
1040 if (oneDeviceData->tdPortContext != onePortContext)
1041 {
1042 TI_DBG3(("tiINIGetExpander: different port\n"));
1043 DeviceListList = DeviceListList->flink;
1044 }
1045 else
1046 {
1047 if (oneDeviceData == oneTargetDeviceData)
1048 {
1049 oneExpanderDeviceData = oneDeviceData->ExpDevice;
1050 if (oneExpanderDeviceData == agNULL)
1051 {
1052 TI_DBG1(("tiINIGetExpander: oneExpanderDeviceData is NULL\n"));
1053 return tiError;
1054 }
1055 *tiExp = &(oneExpanderDeviceData->tiDeviceHandle);
1056 return tiSuccess;
1057 }
1058 DeviceListList = DeviceListList->flink;
1059 }
1060 }
1061 return tiError;
1062 }
1063
1064
tiIniGetDirectSataSasAddr(tiRoot_t * tiRoot,bit32 phyId,bit8 ** sasAddressHi,bit8 ** sasAddressLo)1065 osGLOBAL void tiIniGetDirectSataSasAddr(tiRoot_t * tiRoot, bit32 phyId, bit8 **sasAddressHi, bit8 **sasAddressLo)
1066 {
1067 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
1068 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1069 agsaRoot_t *agRoot = &tdsaAllShared->agRootInt;
1070 tiIOCTLPayload_wwn_t agIoctlPayload;
1071 bit8 nvmDev;
1072 bit32 status;
1073 int i;
1074 agIoctlPayload.Length = 4096;
1075 agIoctlPayload.Reserved = 0;
1076 agIoctlPayload.MinorFunction = IOCTL_MN_NVMD_GET_CONFIG;
1077 agIoctlPayload.MajorFunction = IOCTL_MJ_NVMD_GET;
1078 tiCOMDelayedInterruptHandler(tiRoot, 0,1, tiNonInterruptContext);
1079 if(tiIS_SPC(agRoot))
1080 {
1081 nvmDev = 4;
1082 status = tdsaNVMDGetIoctl(tiRoot, (tiIOCTLPayload_t *)&agIoctlPayload, agNULL, agNULL, &nvmDev);
1083 }
1084 else
1085 {
1086 nvmDev = 1;
1087 status = tdsaNVMDGetIoctl(tiRoot, (tiIOCTLPayload_t *)&agIoctlPayload, agNULL, agNULL, &nvmDev);
1088 }
1089 if(status == IOCTL_CALL_FAIL)
1090 {
1091 #if !(defined(__FreeBSD__))
1092 printk("Error getting Adapter WWN\n");
1093 #else
1094 printf("Error getting Adapter WWN\n");
1095 #endif
1096 return;
1097 }
1098 for(i=0; i< TD_MAX_NUM_PHYS; i++)
1099 {
1100 *(bit32 *)(tdsaAllShared->Ports[i].SASID.sasAddressHi) = *(bit32 *)&agIoctlPayload.FunctionSpecificArea[0];
1101 *(bit32 *)(tdsaAllShared->Ports[i].SASID.sasAddressLo) = *(bit32 *)&agIoctlPayload.FunctionSpecificArea[4];
1102 TI_DBG3(("SAS AddressHi is 0x%x\n", *(bit32 *)(tdsaAllShared->Ports[i].SASID.sasAddressHi)));
1103 TI_DBG3(("SAS AddressLo is 0x%x\n", *(bit32 *)(tdsaAllShared->Ports[i].SASID.sasAddressLo)));
1104 }
1105 *sasAddressHi = tdsaAllShared->Ports[phyId].SASID.sasAddressHi;
1106 *sasAddressLo = tdsaAllShared->Ports[phyId].SASID.sasAddressLo;
1107 }
1108 osGLOBAL tiDeviceHandle_t *
tiINIGetExpDeviceHandleBySasAddress(tiRoot_t * tiRoot,tiPortalContext_t * tiPortalContext,bit32 sas_addr_hi,bit32 sas_addr_lo,bit32 maxDevs)1109 tiINIGetExpDeviceHandleBySasAddress(
1110 tiRoot_t * tiRoot,
1111 tiPortalContext_t * tiPortalContext,
1112 bit32 sas_addr_hi,
1113 bit32 sas_addr_lo,
1114 bit32 maxDevs
1115 )
1116
1117 {
1118 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
1119 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1120 tdList_t *PortContextList;
1121 tdsaPortContext_t *onePortContext = agNULL;
1122 tdsaDeviceData_t *oneDeviceData = agNULL;
1123 tdList_t *DeviceListList;
1124 //bit32 i;
1125 //bit32 FoundDevices = 0;
1126 bit32 DeviceIndex = 0;
1127 bit32 found = agFALSE;
1128
1129
1130 TI_DBG2(("tiINIGetExpDeviceHandleBySasAddress: start\n"));
1131 TI_DBG2(("tiINIGetExpDeviceHandleBySasAddress: tiPortalContext %p\n", tiPortalContext));
1132
1133
1134 if (maxDevs == 0)
1135 {
1136 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: maxDevs is 0\n"));
1137
1138 return agNULL;
1139 }
1140
1141 tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
1142 if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
1143 {
1144 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
1145 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: No available tdsaPortContext\n"));
1146 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: second, returning 0\n"));
1147 return agNULL;
1148 }
1149 else
1150 {
1151 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
1152 }
1153 /* find a corresponding portcontext */
1154 PortContextList = tdsaAllShared->MainPortContextList.flink;
1155
1156 if(PortContextList == agNULL)
1157 {
1158 TI_DBG6(("tiINIGetExpDeviceHandleBySasAddress: PortContextList is NULL!!\n"));
1159 return agNULL;
1160 }
1161
1162 while (PortContextList != &(tdsaAllShared->MainPortContextList))
1163 {
1164 onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
1165
1166 if(onePortContext == agNULL)
1167 {
1168 TI_DBG6(("tiINIGetExpDeviceHandleBySasAddress: onePortContext is NULL!!\n"));
1169 return agNULL;
1170 }
1171
1172 TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: oneportContext pid %d\n", onePortContext->id));
1173 if (onePortContext->tiPortalContext == tiPortalContext && onePortContext->valid == agTRUE)
1174 {
1175 TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: found; oneportContext pid %d\n", onePortContext->id));
1176 found = agTRUE;
1177 break;
1178 }
1179
1180 if(PortContextList != agNULL)
1181 {
1182 PortContextList = PortContextList->flink;
1183 }
1184
1185 }
1186
1187 if (found == agFALSE)
1188 {
1189 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: First, No corresponding tdsaPortContext\n"));
1190 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: third, returning 0\n"));
1191 /* nullify all device handles */
1192 return agNULL;
1193 }
1194
1195 if (onePortContext == agNULL)
1196 {
1197 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: Second, No corressponding tdsaPortContext\n"));
1198 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: fourth, returning 0\n"));
1199 /* nullify all device handles */
1200 return agNULL;
1201 }
1202
1203 if (onePortContext->valid == agFALSE)
1204 {
1205 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: Third, tdsaPortContext is invalid, pid %d\n", onePortContext->id));
1206 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: fifth, returning 0\n"));
1207 return agNULL;
1208 }
1209
1210
1211 TI_DBG2(("tiINIGetExpDeviceHandleBySasAddress: pid %d\n", onePortContext->id));
1212
1213
1214 /* to do: check maxdev and length of Mainlink */
1215 /*
1216 From the device list, returns only valid devices
1217 */
1218 DeviceListList = tdsaAllShared->MainDeviceList.flink;
1219
1220 if(DeviceListList == agNULL)
1221 {
1222 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: DeviceListList == agNULL\n"));
1223 TI_DBG1(("tiINIGetExpDeviceHandleBySasAddress: seventh, returning not found, pid %d\n", onePortContext->id));
1224 return agNULL;
1225 }
1226
1227 while ((DeviceIndex < maxDevs) &&
1228 DeviceListList != &(tdsaAllShared->MainDeviceList))
1229 {
1230 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
1231
1232 if(oneDeviceData == agNULL)
1233 {
1234 TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: oneDeviceData is NULL!!\n"));
1235 return agNULL;
1236 }
1237
1238
1239 TI_DBG6(("tiINIGetExpDeviceHandleBySasAddress: handle %p\n", &(oneDeviceData->tiDeviceHandle)));
1240 if (oneDeviceData->tdPortContext != onePortContext)
1241 {
1242 TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: different port\n"));
1243
1244 if(DeviceListList != agNULL)
1245 {
1246 DeviceListList = DeviceListList->flink;
1247 }
1248
1249 }
1250 else
1251 {
1252
1253 if ((oneDeviceData->valid == agTRUE) &&
1254 (oneDeviceData->registered == agTRUE) &&
1255 (oneDeviceData->tdPortContext == onePortContext) &&
1256 (
1257 (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE) ||
1258 (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE) ||
1259 DEVICE_IS_SMP_TARGET(oneDeviceData)
1260 )
1261 )
1262
1263 {
1264
1265 if(oneDeviceData->SASAddressID.sasAddressLo == sas_addr_lo && oneDeviceData->SASAddressID.sasAddressHi == sas_addr_hi)
1266 {
1267 //TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: valid FoundDevices %d\n", FoundDevices));
1268 TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: agDevHandle %p\n", oneDeviceData->agDevHandle));
1269 TI_DBG3(("tiINIGetExpDeviceHandleBySasAddress: Matched sas address: low %x and high %x\n", oneDeviceData->SASAddressID.sasAddressLo, oneDeviceData->SASAddressID.sasAddressHi));
1270 return &(oneDeviceData->tiDeviceHandle);
1271 }
1272 }
1273 DeviceIndex++;
1274 DeviceListList = DeviceListList->flink;
1275 } /* else */
1276 }
1277
1278 return agNULL;
1279 }
1280
1281
1282
1283
1284 #ifdef TD_DISCOVER
1285 /*****************************************************************************
1286 *! \brief tdsaDiscover
1287 *
1288 * Purpose: This function is called to trigger topology discovery within a
1289 * portcontext.
1290 *
1291 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1292 * instance.
1293 * \param onePortContext: Pointer to the portal context instance.
1294 * \param type: Type of discovery. It can be SAS or SATA.
1295 * \param option: discovery option. It can be Full or Incremental discovery.
1296 *
1297 * \return:
1298 * tiSuccess Discovery initiated.
1299 * tiError Discovery could not be initiated at this time.
1300 *
1301 * \note:
1302 *
1303 *****************************************************************************/
1304 osGLOBAL bit32
tdsaDiscover(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,bit32 type,bit32 option)1305 tdsaDiscover(
1306 tiRoot_t *tiRoot,
1307 tdsaPortContext_t *onePortContext,
1308 bit32 type,
1309 bit32 option
1310 )
1311
1312 {
1313 bit32 ret = tiError;
1314 TI_DBG3(("tdsaDiscover: start\n"));
1315
1316 if (onePortContext->valid == agFALSE)
1317 {
1318 TI_DBG1(("tdsaDiscover: aborting discovery\n"));
1319 tdsaSASDiscoverAbort(tiRoot, onePortContext);
1320 return ret;
1321 }
1322
1323 switch ( option )
1324 {
1325 case TDSA_DISCOVERY_OPTION_FULL_START:
1326 TI_DBG3(("tdsaDiscover: full\n"));
1327 onePortContext->discovery.type = TDSA_DISCOVERY_OPTION_FULL_START;
1328 if ( type == TDSA_DISCOVERY_TYPE_SAS )
1329 {
1330 ret = tdsaSASFullDiscover(tiRoot, onePortContext);
1331 }
1332 #ifdef SATA_ENABLE
1333 else if ( type == TDSA_DISCOVERY_TYPE_SATA )
1334 {
1335 if (onePortContext->discovery.status == DISCOVERY_SAS_DONE)
1336 {
1337 ret = tdsaSATAFullDiscover(tiRoot, onePortContext);
1338 }
1339 }
1340 #endif
1341 break;
1342 case TDSA_DISCOVERY_OPTION_INCREMENTAL_START:
1343 TI_DBG3(("tdsaDiscover: incremental\n"));
1344 onePortContext->discovery.type = TDSA_DISCOVERY_OPTION_INCREMENTAL_START;
1345 if ( type == TDSA_DISCOVERY_TYPE_SAS )
1346 {
1347 TI_DBG3(("tdsaDiscover: incremental SAS\n"));
1348 ret = tdsaSASIncrementalDiscover(tiRoot, onePortContext);
1349 }
1350 #ifdef SATA_ENABLE
1351 else if ( type == TDSA_DISCOVERY_TYPE_SATA )
1352 {
1353 if (onePortContext->discovery.status == DISCOVERY_SAS_DONE)
1354 {
1355 TI_DBG3(("tdsaDiscover: incremental SATA\n"));
1356 ret = tdsaSATAIncrementalDiscover(tiRoot, onePortContext);
1357 }
1358 }
1359 #endif
1360 break;
1361 case TDSA_DISCOVERY_OPTION_ABORT:
1362 TI_DBG1(("tdsaDiscover: abort\n"));
1363 break;
1364 default:
1365 break;
1366
1367 }
1368 if (ret != tiSuccess)
1369 {
1370 TI_DBG1(("tdsaDiscover: fail, error 0x%x\n", ret));
1371 }
1372 return ret;
1373 }
1374
1375 /*****************************************************************************
1376 *! \brief tdsaSASFullDiscover
1377 *
1378 * Purpose: This function is called to trigger full SAS topology discovery
1379 * within a portcontext.
1380 *
1381 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1382 * instance.
1383 * \param onePortContext: Pointer to the portal context instance.
1384 *
1385 * \return:
1386 * tiSuccess Discovery initiated.
1387 * tiError Discovery could not be initiated at this time.
1388 *
1389 * \note:
1390 *
1391 *****************************************************************************/
1392 osGLOBAL bit32
tdsaSASFullDiscover(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext)1393 tdsaSASFullDiscover(
1394 tiRoot_t *tiRoot,
1395 tdsaPortContext_t *onePortContext
1396 )
1397 {
1398 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
1399 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1400 tdsaDeviceData_t *oneDeviceData = agNULL;
1401 tdList_t *DeviceListList;
1402 int i, j;
1403 bit8 portMaxRate;
1404 TI_DBG3(("tdsaSASFullDiscover: start\n"));
1405 if (onePortContext->valid == agFALSE)
1406 {
1407 TI_DBG1(("tdsaSASFullDiscover: aborting discovery\n"));
1408 tdsaSASDiscoverAbort(tiRoot, onePortContext);
1409 return tiError;
1410 }
1411 /*
1412 1. abort all IO; may need a new LL API since TD does not queue IO's
1413 2. initializes(or invalidate) devices belonging to the port
1414 3. onePortContext->DiscoveryState == ITD_DSTATE_STARTED
1415 4. add directly connected one; if directed-SAS, spin-up
1416 5. tdsaSASUpStreamDiscoverStart(agRoot, pPort, pDevice)
1417 */
1418 /*
1419 invalidate all devices belonging to the portcontext except direct attached SAS/SATA
1420 */
1421 DeviceListList = tdsaAllShared->MainDeviceList.flink;
1422 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
1423 {
1424 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
1425 TI_DBG3(("tdsaSASFullDiscover: STARTED loop id %d\n", oneDeviceData->id));
1426 TI_DBG3(("tdsaSASFullDiscover: STARTED loop sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
1427 TI_DBG3(("tdsaSASFullDiscover: STARTED loop sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
1428 if (oneDeviceData->tdPortContext == onePortContext &&
1429 (onePortContext->nativeSATAMode == agFALSE && onePortContext->directAttatchedSAS == agFALSE) )
1430
1431 {
1432 TI_DBG3(("tdsaSASFullDiscover: invalidate\n"));
1433 oneDeviceData->valid = agFALSE;
1434 oneDeviceData->processed = agFALSE;
1435 }
1436 else
1437 {
1438 TI_DBG3(("tdsaSASFullDiscover: not invalidate\n"));
1439 /* no changes */
1440 }
1441 DeviceListList = DeviceListList->flink;
1442 }
1443
1444 onePortContext->DiscoveryState = ITD_DSTATE_STARTED;
1445 /* nativeSATAMode is set in ossaHwCB() in link up */
1446 if (onePortContext->nativeSATAMode == agFALSE) /* default: SAS and SAS/SATA mode */
1447 {
1448 if (SA_IDFRM_GET_DEVICETTYPE(&onePortContext->sasIDframe) == SAS_END_DEVICE &&
1449 SA_IDFRM_IS_SSP_TARGET(&onePortContext->sasIDframe) )
1450 {
1451 for(i=0;i<TD_MAX_NUM_PHYS;i++)
1452 {
1453 if (onePortContext->PhyIDList[i] == agTRUE)
1454 {
1455
1456 for (j=0;j<TD_MAX_NUM_NOTIFY_SPINUP;j++)
1457 {
1458 saLocalPhyControl(onePortContext->agRoot, agNULL, tdsaRotateQnumber(tiRoot, agNULL), i, AGSA_PHY_NOTIFY_ENABLE_SPINUP, agNULL);
1459 }
1460 break;
1461 }
1462 }
1463 }
1464 /*
1465 add the device
1466 1. add device in TD layer
1467 2. call saRegisterNewDevice
1468 3. update agDevHandle in ossaDeviceRegistrationCB()
1469 */
1470 portMaxRate = onePortContext->LinkRate;
1471 oneDeviceData = tdsaPortSASDeviceAdd(
1472 tiRoot,
1473 onePortContext,
1474 onePortContext->sasIDframe,
1475 agFALSE,
1476 portMaxRate,
1477 IT_NEXUS_TIMEOUT,
1478 0,
1479 SAS_DEVICE_TYPE,
1480 agNULL,
1481 0xFF
1482 );
1483 if (oneDeviceData)
1484 {
1485 if (oneDeviceData->registered == agFALSE)
1486 {
1487 /*
1488 set the timer and wait till the device(directly attached. eg Expander) to be registered.
1489 Then, in tdsaDeviceRegistrationTimerCB(), tdsaSASUpStreamDiscoverStart() is called
1490 */
1491 tdsaDeviceRegistrationTimer(tiRoot, onePortContext, oneDeviceData);
1492 }
1493 else
1494 {
1495 tdsaSASUpStreamDiscoverStart(tiRoot, onePortContext, oneDeviceData);
1496 }
1497 }
1498 #ifdef REMOVED
1499 // temp testing code
1500 tdsaReportManInfoSend(tiRoot, oneDeviceData);
1501 //end temp testing code
1502 #endif
1503 }
1504 else /* SATAOnlyMode*/
1505 {
1506 tdsaSASDiscoverDone(tiRoot, onePortContext, tiSuccess);
1507 }
1508
1509 return tiSuccess;
1510 }
1511
1512 /*****************************************************************************
1513 *! \brief tdsaSASUpStreamDiscoverStart
1514 *
1515 * Purpose: This function is called to trigger upstream traverse in topology
1516 * within a portcontext.
1517 *
1518 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1519 * instance.
1520 * \param onePortContext: Pointer to the portal context instance.
1521 * \param oneDeviceData: Pointer to the device data.
1522 *
1523 * \return:
1524 * None
1525 *
1526 * \note:
1527 *
1528 *****************************************************************************/
1529 osGLOBAL void
tdsaSASUpStreamDiscoverStart(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaDeviceData_t * oneDeviceData)1530 tdsaSASUpStreamDiscoverStart(
1531 tiRoot_t *tiRoot,
1532 tdsaPortContext_t *onePortContext,
1533 tdsaDeviceData_t *oneDeviceData
1534 )
1535 {
1536 tdsaExpander_t *oneExpander;
1537
1538 TI_DBG3(("tdsaSASUpStreamDiscoverStart: start\n"));
1539
1540 if (onePortContext->valid == agFALSE)
1541 {
1542 TI_DBG1(("tdsaSASUpStreamDiscoverStart: aborting discovery\n"));
1543 tdsaSASDiscoverAbort(tiRoot, onePortContext);
1544 return;
1545 }
1546
1547 /*
1548 1. update discovery state to UP_STREAM
1549 2. if (expander) add it
1550 3. tdsaSASUpStreamDiscovering
1551
1552 */
1553 onePortContext->discovery.status = DISCOVERY_UP_STREAM;
1554 if (
1555 (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
1556 ||
1557 (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE)
1558 )
1559 {
1560 oneExpander = tdssSASDiscoveringExpanderAlloc(tiRoot, onePortContext, oneDeviceData);
1561 if ( oneExpander != agNULL)
1562 {
1563 /* (2.2.1) Add to discovering list */
1564 tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, oneExpander);
1565 }
1566 else
1567 {
1568 TI_DBG1(("tdsaSASUpStreamDiscoverStart: failed to allocate expander or discovey aborted\n"));
1569 return;
1570 }
1571 }
1572
1573 tdsaSASUpStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
1574
1575 return;
1576 }
1577
1578 /*****************************************************************************
1579 *! \brief tdsaSASUpStreamDiscovering
1580 *
1581 * Purpose: For each expander in the expander list, this function sends SMP to
1582 * find information for discovery and calls
1583 * tdsaSASDownStreamDiscoverStart() function.
1584 *
1585 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1586 * instance.
1587 * \param onePortContext: Pointer to the portal context instance.
1588 * \param oneDeviceData: Pointer to the device data.
1589 *
1590 * \return:
1591 * None
1592 *
1593 * \note:
1594 *
1595 *****************************************************************************/
1596 osGLOBAL void
tdsaSASUpStreamDiscovering(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaDeviceData_t * oneDeviceData)1597 tdsaSASUpStreamDiscovering(
1598 tiRoot_t *tiRoot,
1599 tdsaPortContext_t *onePortContext,
1600 tdsaDeviceData_t *oneDeviceData
1601 )
1602 {
1603 tdList_t *ExpanderList;
1604 tdsaExpander_t *oneNextExpander = agNULL;
1605
1606 TI_DBG3(("tdsaSASUpStreamDiscovering: start\n"));
1607 if (onePortContext->valid == agFALSE)
1608 {
1609 TI_DBG1(("tdsaSASUpStreamDiscovering: aborting discovery\n"));
1610 tdsaSASDiscoverAbort(tiRoot, onePortContext);
1611 return;
1612 }
1613 /*
1614 1. find the next expander
1615 2. if (there is next expander) send report general with saSMPStart
1616 else tdsaSASDownStreamDiscoverStart
1617
1618 */
1619 tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1620 if (TDLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList)))
1621 {
1622 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1623 TI_DBG3(("tdsaSASUpStreamDiscovering: should be the end\n"));
1624 oneNextExpander = agNULL;
1625 }
1626 else
1627 {
1628 TDLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList));
1629 oneNextExpander = TDLIST_OBJECT_BASE(tdsaExpander_t, linkNode, ExpanderList);
1630 TDLIST_ENQUEUE_AT_HEAD(&(oneNextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));
1631 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1632
1633 TI_DBG3(("tdssSASDiscoveringExpander tdsaSASUpStreamDiscovering: dequeue head\n"));
1634 TI_DBG3(("tdsaSASUpStreamDiscovering: expander id %d\n", oneNextExpander->id));
1635 }
1636
1637 if (oneNextExpander != agNULL)
1638 {
1639 tdsaReportGeneralSend(tiRoot, oneNextExpander->tdDevice);
1640 }
1641 else
1642 {
1643 TI_DBG3(("tdsaSASUpStreamDiscovering: No more expander list\n"));
1644 tdsaSASDownStreamDiscoverStart(tiRoot, onePortContext, oneDeviceData);
1645 }
1646
1647 return;
1648 }
1649
1650 /*****************************************************************************
1651 *! \brief tdsaSASDownStreamDiscoverStart
1652 *
1653 * Purpose: This function is called to trigger downstream traverse in topology
1654 * within a portcontext.
1655 *
1656 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1657 * instance.
1658 * \param onePortContext: Pointer to the portal context instance.
1659 * \param oneDeviceData: Pointer to the device data.
1660 *
1661 * \return:
1662 * None
1663 *
1664 * \note:
1665 *
1666 *****************************************************************************/
1667 osGLOBAL void
tdsaSASDownStreamDiscoverStart(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaDeviceData_t * oneDeviceData)1668 tdsaSASDownStreamDiscoverStart(
1669 tiRoot_t *tiRoot,
1670 tdsaPortContext_t *onePortContext,
1671 tdsaDeviceData_t *oneDeviceData
1672 )
1673 {
1674 tdsaExpander_t *oneExpander;
1675 tdsaExpander_t *UpStreamExpander;
1676 TI_DBG3(("tdsaSASDownStreamDiscoverStart: start\n"));
1677
1678 if (onePortContext->valid == agFALSE)
1679 {
1680 TI_DBG1(("tdsaSASDownStreamDiscoverStart: aborting discovery\n"));
1681 tdsaSASDiscoverAbort(tiRoot, onePortContext);
1682 return;
1683 }
1684 /*
1685 1. update discover state
1686 2. if (expander is root) add it
1687 else just add it
1688 3. tdsaSASDownStreamDiscovering
1689
1690 */
1691 /* set discovery status */
1692 onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
1693
1694 TI_DBG3(("tdsaSASDownStreamDiscoverStart: pPort=%p pDevice=%p\n", onePortContext, oneDeviceData));
1695
1696 /* If it's an expander */
1697 if ( (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
1698 || (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE))
1699 {
1700 oneExpander = oneDeviceData->tdExpander;
1701 UpStreamExpander = oneExpander->tdUpStreamExpander;
1702
1703 /* If the two expanders are the root of two edge sets; sub-to-sub */
1704 if ( (UpStreamExpander != agNULL) && ( UpStreamExpander->tdUpStreamExpander == oneExpander ) )
1705 {
1706 TI_DBG3(("tdsaSASDownStreamDiscoverStart: Root found pExpander=%p pUpStreamExpander=%p\n",
1707 oneExpander, UpStreamExpander));
1708 //Saves the root expander
1709 onePortContext->discovery.RootExp = oneExpander;
1710 TI_DBG3(("tdsaSASDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
1711 TI_DBG3(("tdsaSASDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
1712
1713 /* reset up stream inform for pExpander */
1714 oneExpander->tdUpStreamExpander = agNULL;
1715 /* Add the pExpander to discovering list */
1716 tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, oneExpander);
1717
1718 /* reset up stream inform for oneExpander */
1719 UpStreamExpander->tdUpStreamExpander = agNULL;
1720 /* Add the UpStreamExpander to discovering list */
1721 tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, UpStreamExpander);
1722 }
1723 /* If the two expanders are not the root of two edge sets. eg) one root */
1724 else
1725 {
1726 //Saves the root expander
1727 onePortContext->discovery.RootExp = oneExpander;
1728
1729 TI_DBG3(("tdsaSASDownStreamDiscoverStart: NO Root pExpander=%p\n", oneExpander));
1730 TI_DBG3(("tdsaSASDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
1731 TI_DBG3(("tdsaSASDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
1732
1733 /* (2.2.2.1) Add the pExpander to discovering list */
1734 tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, oneExpander);
1735 }
1736 }
1737
1738 /* Continue down stream discovering */
1739 tdsaSASDownStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
1740
1741 return;
1742 }
1743
1744 /*****************************************************************************
1745 *! \brief tdsaSASDownStreamDiscovering
1746 *
1747 * Purpose: For each expander in the expander list, this function sends SMP to
1748 * find information for discovery and calls
1749 * tdsaSASDownStreamDiscoverStart() function.
1750 *
1751 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1752 * instance.
1753 * \param onePortContext: Pointer to the portal context instance.
1754 * \param oneDeviceData: Pointer to the device data.
1755 *
1756 * \return:
1757 * None
1758 *
1759 * \note:
1760 *
1761 *****************************************************************************/
1762 osGLOBAL void
tdsaSASDownStreamDiscovering(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaDeviceData_t * oneDeviceData)1763 tdsaSASDownStreamDiscovering(
1764 tiRoot_t *tiRoot,
1765 tdsaPortContext_t *onePortContext,
1766 tdsaDeviceData_t *oneDeviceData
1767 )
1768 {
1769 tdsaExpander_t *NextExpander = agNULL;
1770 tdList_t *ExpanderList;
1771
1772 TI_DBG3(("tdsaSASDownStreamDiscovering: start\n"));
1773
1774 TI_DBG3(("tdsaSASDownStreamDiscovering: pPort=%p pDevice=%p\n", onePortContext, oneDeviceData));
1775
1776 if (onePortContext->valid == agFALSE)
1777 {
1778 TI_DBG1(("tdsaSASDownStreamDiscovering: aborting discovery\n"));
1779 tdsaSASDiscoverAbort(tiRoot, onePortContext);
1780 return;
1781 }
1782
1783 tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1784 if (TDLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList)))
1785 {
1786 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1787 TI_DBG3(("tdsaSASDownStreamDiscovering: should be the end\n"));
1788 NextExpander = agNULL;
1789 }
1790 else
1791 {
1792 TDLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList));
1793 NextExpander = TDLIST_OBJECT_BASE(tdsaExpander_t, linkNode, ExpanderList);
1794 TDLIST_ENQUEUE_AT_HEAD(&(NextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList));
1795 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1796 TI_DBG3(("tdssSASDiscoveringExpander tdsaSASDownStreamDiscovering: dequeue head\n"));
1797 TI_DBG3(("tdsaSASDownStreamDiscovering: expander id %d\n", NextExpander->id));
1798
1799 }
1800
1801 /* If there is an expander for continue discoving */
1802 if ( NextExpander != agNULL)
1803 {
1804 TI_DBG3(("tdsaSASDownStreamDiscovering: Found pNextExpander=%p\n, discoveryStatus=0x%x",
1805 NextExpander, onePortContext->discovery.status));
1806
1807 switch (onePortContext->discovery.status)
1808 {
1809 /* If the discovery status is DISCOVERY_DOWN_STREAM */
1810 case DISCOVERY_DOWN_STREAM:
1811 /* Send report general for the next expander */
1812 TI_DBG3(("tdsaSASDownStreamDiscovering: DownStream pNextExpander->pDevice=%p\n", NextExpander->tdDevice));
1813 tdsaReportGeneralSend(tiRoot, NextExpander->tdDevice);
1814 break;
1815 /* If the discovery status is DISCOVERY_CONFIG_ROUTING */
1816 case DISCOVERY_CONFIG_ROUTING:
1817 case DISCOVERY_REPORT_PHY_SATA:
1818
1819 /* set discovery status */
1820 onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
1821
1822 TI_DBG3(("tdsaSASDownStreamDiscovering: pPort->discovery.status=DISCOVERY_CONFIG_ROUTING, nake it DOWN_STREAM\n"));
1823 /* If not the last phy */
1824 if ( NextExpander->discoveringPhyId < NextExpander->tdDevice->numOfPhys )
1825 {
1826 TI_DBG3(("tdsaSASDownStreamDiscovering: pNextExpander->discoveringPhyId=0x%x pNextExpander->pDevice->numOfPhys=0x%x. Send More Discover\n",
1827 NextExpander->discoveringPhyId, NextExpander->tdDevice->numOfPhys));
1828 /* Send discover for the next expander */
1829 tdsaDiscoverSend(tiRoot, NextExpander->tdDevice);
1830 }
1831 /* If it's the last phy */
1832 else
1833 {
1834 TI_DBG3(("tdsaSASDownStreamDiscovering: Last Phy, remove expander%p start DownStream=%p\n",
1835 NextExpander, NextExpander->tdDevice));
1836 tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, NextExpander);
1837 tdsaSASDownStreamDiscovering(tiRoot, onePortContext, NextExpander->tdDevice);
1838 }
1839 break;
1840
1841 default:
1842 TI_DBG3(("tdsaSASDownStreamDiscovering: *** Unknown pPort->discovery.status=0x%x\n", onePortContext->discovery.status));
1843 }
1844 }
1845 /* If no expander for continue discoving */
1846 else
1847 {
1848 TI_DBG3(("tdsaSASDownStreamDiscovering: No more expander DONE\n"));
1849 /* discover done */
1850 tdsaSASDiscoverDone(tiRoot, onePortContext, tiSuccess);
1851 }
1852
1853 return;
1854 }
1855
1856 /*****************************************************************************
1857 *! \brief tdsaCleanAllExp
1858 *
1859 * Purpose: This function cleans up expander data structures after discovery
1860 * is complete.
1861 *
1862 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1863 * instance.
1864 * \param onePortContext: Pointer to the portal context instance.
1865 *
1866 * \return:
1867 * None
1868 *
1869 * \note:
1870 *
1871 *****************************************************************************/
1872 osGLOBAL void
tdsaCleanAllExp(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext)1873 tdsaCleanAllExp(
1874 tiRoot_t *tiRoot,
1875 tdsaPortContext_t *onePortContext
1876 )
1877 {
1878 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
1879 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1880 tdList_t *ExpanderList;
1881 tdsaExpander_t *tempExpander;
1882 tdsaPortContext_t *tmpOnePortContext = onePortContext;
1883
1884 TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: start\n"));
1885
1886 TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: before all clean up\n"));
1887 tdsaDumpAllFreeExp(tiRoot);
1888
1889 /* clean up UpdiscoveringExpanderList*/
1890 TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: clean discoveringExpanderList\n"));
1891 tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1892 if (!TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
1893 {
1894 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1895 ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
1896 while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
1897 {
1898 tempExpander = TDLIST_OBJECT_BASE(tdsaExpander_t, linkNode, ExpanderList);
1899 TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: exp addrHi 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressHi));
1900 TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: exp addrLo 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressLo));
1901 /* putting back to the free pool */
1902 tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1903 TDLIST_DEQUEUE_THIS(&(tempExpander->linkNode));
1904 TDLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(tdsaAllShared->freeExpanderList));
1905
1906 if (TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
1907 {
1908 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1909 break;
1910 }
1911 else
1912 {
1913 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1914 }
1915 ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
1916
1917 // ExpanderList = ExpanderList->flink;
1918 }
1919 }
1920 else
1921 {
1922 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1923 TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: empty discoveringExpanderList\n"));
1924 }
1925
1926 /* reset UpdiscoveringExpanderList */
1927 TDLIST_INIT_HDR(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList));
1928
1929 TI_DBG3(("tdssSASDiscoveringExpander tdsaCleanAllExp: after all clean up\n"));
1930 tdsaDumpAllFreeExp(tiRoot);
1931
1932 return;
1933 }
1934
1935 /*****************************************************************************
1936 *! \brief tdsaFreeAllExp
1937 *
1938 * Purpose: This function frees up expander data structures as a part of
1939 * soft reset.
1940 *
1941 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
1942 * instance.
1943 * \param onePortContext: Pointer to the portal context instance.
1944 *
1945 * \return:
1946 * None
1947 *
1948 * \note:
1949 *
1950 *****************************************************************************/
1951 osGLOBAL void
tdsaFreeAllExp(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext)1952 tdsaFreeAllExp(
1953 tiRoot_t *tiRoot,
1954 tdsaPortContext_t *onePortContext
1955 )
1956 {
1957 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
1958 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1959 tdList_t *ExpanderList;
1960 tdsaExpander_t *tempExpander;
1961 tdsaPortContext_t *tmpOnePortContext = onePortContext;
1962
1963 TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: start\n"));
1964
1965 TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: before all clean up\n"));
1966 tdsaDumpAllFreeExp(tiRoot);
1967
1968 /* clean up UpdiscoveringExpanderList*/
1969 TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: clean discoveringExpanderList\n"));
1970 tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1971 if (!TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
1972 {
1973 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1974 ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
1975 while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
1976 {
1977 tempExpander = TDLIST_OBJECT_BASE(tdsaExpander_t, linkNode, ExpanderList);
1978 TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: exp addrHi 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressHi));
1979 TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: exp addrLo 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressLo));
1980 /* putting back to the free pool */
1981 tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
1982 TDLIST_DEQUEUE_THIS(&(tempExpander->linkNode));
1983 TDLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(tdsaAllShared->freeExpanderList));
1984
1985 if (TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
1986 {
1987 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1988 break;
1989 }
1990 else
1991 {
1992 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
1993 }
1994 ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
1995
1996 // ExpanderList = ExpanderList->flink;
1997 }
1998 }
1999 else
2000 {
2001 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
2002 TI_DBG3(("tdssSASDiscoveringExpander tdsaFreeAllExp: empty discoveringExpanderList\n"));
2003 }
2004
2005 /* reset UpdiscoveringExpanderList */
2006 TDLIST_INIT_HDR(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList));
2007
2008 return;
2009 }
2010 /*****************************************************************************
2011 *! \brief tdsaResetValidDeviceData
2012 *
2013 * Purpose: This function resets valid and valid2 field for discovered devices
2014 * in the device list. This is used only in incremental discovery.
2015 *
2016 * \param agRoot : Pointer to chip/driver Instance.
2017 * \param onePortContext: Pointer to the portal context instance.
2018 * \param oneDeviceData: Pointer to the device data.
2019 *
2020 * \return:
2021 * None
2022 *
2023 * \note:
2024 *
2025 *****************************************************************************/
2026 osGLOBAL void
tdsaResetValidDeviceData(agsaRoot_t * agRoot,tdsaPortContext_t * onePortContext)2027 tdsaResetValidDeviceData(
2028 agsaRoot_t *agRoot,
2029 tdsaPortContext_t *onePortContext
2030 )
2031 {
2032 tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData;
2033 tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot;
2034 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
2035 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2036 tdList_t *DeviceListList;
2037 tdsaDeviceData_t *oneDeviceData;
2038
2039 TI_DBG3(("tdsaResetValidDeviceData: start\n"));
2040
2041 tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2042 if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2043 {
2044 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2045 TI_DBG1(("tdsaResetValidDeviceData: empty device list\n"));
2046 }
2047 else
2048 {
2049 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2050 DeviceListList = tdsaAllShared->MainDeviceList.flink;
2051 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2052 {
2053 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2054 oneDeviceData->valid = oneDeviceData->valid2;
2055 oneDeviceData->valid2 = agFALSE;
2056 DeviceListList = DeviceListList->flink;
2057 TI_DBG3(("tdsaResetValidDeviceData: valid %d valid2 %d\n", oneDeviceData->valid, oneDeviceData->valid2));
2058 }
2059 }
2060
2061 return;
2062 }
2063
2064 /*****************************************************************************
2065 *! \brief tdssReportChanges
2066 *
2067 * Purpose: This function goes throuhg device list and finds out whether
2068 * a device is removed and newly added. Based on the findings,
2069 * this function notifies OS layer of the change.
2070 *
2071 * \param agRoot : Pointer to chip/driver Instance.
2072 * \param onePortContext: Pointer to the portal context instance.
2073 *
2074 * \return:
2075 * None
2076 *
2077 * \note:
2078 *
2079 *****************************************************************************/
2080 osGLOBAL void
tdssReportChanges(agsaRoot_t * agRoot,tdsaPortContext_t * onePortContext)2081 tdssReportChanges(
2082 agsaRoot_t *agRoot,
2083 tdsaPortContext_t *onePortContext
2084 )
2085 {
2086 tdsaDeviceData_t *oneDeviceData = agNULL;
2087 tdList_t *DeviceListList;
2088 tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData;
2089 tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot;
2090 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
2091 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2092 bit32 added = agFALSE, removed = agFALSE;
2093
2094 TI_DBG1(("tdssReportChanges: start\n"));
2095
2096 tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2097 if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2098 {
2099 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2100 TI_DBG1(("tdssReportChanges: empty device list\n"));
2101 return;
2102 }
2103 else
2104 {
2105 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2106 }
2107 DeviceListList = tdsaAllShared->MainDeviceList.flink;
2108 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2109 {
2110 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2111 TI_DBG3(("tdssReportChanges: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2112 TI_DBG3(("tdssReportChanges: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2113 if ( oneDeviceData->tdPortContext == onePortContext)
2114 {
2115 TI_DBG3(("tdssReportChanges: right portcontext\n"));
2116 if ( (oneDeviceData->valid == agTRUE) && (oneDeviceData->valid2 == agTRUE) )
2117 {
2118 TI_DBG3(("tdssReportChanges: same\n"));
2119 /* reset valid bit */
2120 oneDeviceData->valid = oneDeviceData->valid2;
2121 oneDeviceData->valid2 = agFALSE;
2122 }
2123 else if ( (oneDeviceData->valid == agTRUE) && (oneDeviceData->valid2 == agFALSE) )
2124 {
2125 TI_DBG3(("tdssReportChanges: removed\n"));
2126 removed = agTRUE;
2127 /* reset valid bit */
2128 oneDeviceData->valid = oneDeviceData->valid2;
2129 oneDeviceData->valid2 = agFALSE;
2130 /* reset NumOfFCA */
2131 oneDeviceData->satDevData.NumOfFCA = 0;
2132
2133 if ( (oneDeviceData->registered == agTRUE) &&
2134 ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData)
2135 || DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_SMP_TARGET(oneDeviceData) )
2136 )
2137 {
2138 tdsaAbortAll(tiRoot, agRoot, oneDeviceData);
2139 }
2140 else if (oneDeviceData->registered == agTRUE)
2141 {
2142 TI_DBG1(("tdssReportChanges: calling saDeregisterDeviceHandle, did %d\n", oneDeviceData->id));
2143 saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, 0);
2144 }
2145
2146 oneDeviceData->registered = agFALSE;
2147
2148 #ifdef REMOVED /* don't remove device from the device list. May screw up ordering of report */
2149 TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
2150 TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList));
2151 #endif
2152 }
2153 else if ( (oneDeviceData->valid == agFALSE) && (oneDeviceData->valid2 == agTRUE) )
2154 {
2155 TI_DBG3(("tdssReportChanges: added\n"));
2156 added = agTRUE;
2157 /* reset valid bit */
2158 oneDeviceData->valid = oneDeviceData->valid2;
2159 oneDeviceData->valid2 = agFALSE;
2160 }
2161 else
2162 {
2163 TI_DBG6(("tdssReportChanges: else\n"));
2164 }
2165 }
2166 else
2167 {
2168 TI_DBG1(("tdssReportChanges: different portcontext\n"));
2169 }
2170 DeviceListList = DeviceListList->flink;
2171 }
2172 /* arrival or removal at once */
2173 if (added == agTRUE)
2174 {
2175 TI_DBG3(("tdssReportChanges: added at the end\n"));
2176 #ifdef AGTIAPI_CTL
2177 if (tdsaAllShared->SASConnectTimeLimit)
2178 tdsaCTLSet(tiRoot, onePortContext, tiIntrEventTypeDeviceChange,
2179 tiDeviceArrival);
2180 else
2181 #endif
2182 ostiInitiatorEvent(
2183 tiRoot,
2184 onePortContext->tiPortalContext,
2185 agNULL,
2186 tiIntrEventTypeDeviceChange,
2187 tiDeviceArrival,
2188 agNULL
2189 );
2190
2191 }
2192 if (removed == agTRUE)
2193 {
2194 TI_DBG3(("tdssReportChanges: removed at the end\n"));
2195 ostiInitiatorEvent(
2196 tiRoot,
2197 onePortContext->tiPortalContext,
2198 agNULL,
2199 tiIntrEventTypeDeviceChange,
2200 tiDeviceRemoval,
2201 agNULL
2202 );
2203 }
2204
2205 if (onePortContext->discovery.forcedOK == agTRUE && added == agFALSE && removed == agFALSE)
2206 {
2207 TI_DBG1(("tdssReportChanges: missed chance to report. forced to report OK\n"));
2208 onePortContext->discovery.forcedOK = agFALSE;
2209 ostiInitiatorEvent(
2210 tiRoot,
2211 onePortContext->tiPortalContext,
2212 agNULL,
2213 tiIntrEventTypeDiscovery,
2214 tiDiscOK,
2215 agNULL
2216 );
2217 }
2218
2219 if (added == agFALSE && removed == agFALSE)
2220 {
2221 TI_DBG3(("tdssReportChanges: the same\n"));
2222 }
2223 return;
2224 }
2225 /*****************************************************************************
2226 *! \brief tdssReportRemovals
2227 *
2228 * Purpose: This function goes through device list and removes all devices
2229 * belong to the portcontext. This function also deregiters those
2230 * devices. This function is called in case of incremental discovery
2231 * failure.
2232 *
2233 * \param agRoot : Pointer to chip/driver Instance.
2234 * \param onePortContext: Pointer to the portal context instance.
2235 * \param oneDeviceData: Pointer to the device data.
2236 *
2237 * \return:
2238 * None
2239 *
2240 * \note:
2241 *
2242 *****************************************************************************/
2243 osGLOBAL void
tdssReportRemovals(agsaRoot_t * agRoot,tdsaPortContext_t * onePortContext,bit32 flag)2244 tdssReportRemovals(
2245 agsaRoot_t *agRoot,
2246 tdsaPortContext_t *onePortContext,
2247 bit32 flag
2248 )
2249 {
2250 tdsaDeviceData_t *oneDeviceData = agNULL;
2251 tdList_t *DeviceListList;
2252 tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData;
2253 tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot;
2254 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
2255 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2256 bit32 removed = agFALSE;
2257 agsaEventSource_t *eventSource;
2258 bit32 PhyID;
2259 bit32 HwAckSatus;
2260 agsaDevHandle_t *agDevHandle = agNULL;
2261
2262 TI_DBG2(("tdssReportRemovals: start\n"));
2263 /* in case nothing was registered */
2264 PhyID = onePortContext->eventPhyID;
2265 if (tdsaAllShared->eventSource[PhyID].EventValid == agTRUE &&
2266 onePortContext->RegisteredDevNums == 0 &&
2267 PhyID != 0xFF
2268 )
2269 {
2270 TI_DBG2(("tdssReportRemovals: calling saHwEventAck\n"));
2271 eventSource = &(tdsaAllShared->eventSource[PhyID].Source);
2272 HwAckSatus = saHwEventAck(
2273 agRoot,
2274 agNULL, /* agContext */
2275 0,
2276 eventSource, /* agsaEventSource_t */
2277 0,
2278 0
2279 );
2280 if ( HwAckSatus != AGSA_RC_SUCCESS)
2281 {
2282 TI_DBG1(("tdssReportRemovals: failing in saHwEventAck; status %d\n", HwAckSatus));
2283 }
2284
2285 /* toggle */
2286 tdsaAllShared->eventSource[PhyID].EventValid = agFALSE;
2287 if (onePortContext->valid == agFALSE)
2288 {
2289 /* put device belonging to the port to freedevice list */
2290 DeviceListList = tdsaAllShared->MainDeviceList.flink;
2291 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2292 {
2293 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2294 if (oneDeviceData->tdPortContext == onePortContext)
2295 {
2296 osti_memset(&(oneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t));
2297 tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2298 TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
2299 TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList));
2300 if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2301 {
2302 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2303 break;
2304 }
2305 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2306 DeviceListList = tdsaAllShared->MainDeviceList.flink;
2307 }
2308 else
2309 {
2310 DeviceListList = DeviceListList->flink;
2311 }
2312 } /* while */
2313
2314 tdsaPortContextReInit(tiRoot, onePortContext);
2315 /*
2316 put all devices belonging to the onePortContext
2317 back to the free link
2318 */
2319 tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
2320 TDLIST_DEQUEUE_THIS(&(onePortContext->MainLink));
2321 TDLIST_ENQUEUE_AT_TAIL(&(onePortContext->FreeLink), &(tdsaAllShared->FreePortContextList));
2322 tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
2323 }
2324 }
2325
2326 else
2327 {
2328 tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2329 if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2330 {
2331 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2332 TI_DBG1(("tdssReportRemovals: 1st empty device list\n"));
2333 return;
2334 }
2335 else
2336 {
2337 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2338 }
2339 DeviceListList = tdsaAllShared->MainDeviceList.flink;
2340 /* needs to clean up devices which were not removed in ossaDeregisterDeviceHandleCB() since port was in valid (discovery error) */
2341 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2342 {
2343 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2344 if (oneDeviceData == agNULL)
2345 {
2346 TI_DBG1(("tdssReportRemovals: oneDeviceData is NULL!!!\n"));
2347 return;
2348 }
2349 TI_DBG2(("tdssReportRemovals: 1st loop did %d\n", oneDeviceData->id));
2350 TI_DBG2(("tdssReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2351 TI_DBG2(("tdssReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2352 TI_DBG2(("tdssReportRemovals: valid %d\n", oneDeviceData->valid));
2353 TI_DBG2(("tdssReportRemovals: valid2 %d\n", oneDeviceData->valid2));
2354 TI_DBG2(("tdssReportRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
2355 TI_DBG2(("tdssReportRemovals: registered %d\n", oneDeviceData->registered));
2356 if ( oneDeviceData->tdPortContext == onePortContext && oneDeviceData->valid == agFALSE &&
2357 oneDeviceData->valid2 == agFALSE && oneDeviceData->registered == agFALSE
2358 )
2359 {
2360 /* remove oneDevice from MainLink */
2361 TI_DBG2(("tdssReportRemovals: delete from MainLink\n"));
2362 agDevHandle = oneDeviceData->agDevHandle;
2363 tdsaDeviceDataReInit(tiRoot, oneDeviceData);
2364 //save agDevHandle and tdPortContext
2365 oneDeviceData->agDevHandle = agDevHandle;
2366 oneDeviceData->tdPortContext = onePortContext;
2367 osti_memset(&(oneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t));
2368 tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2369 TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
2370 TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList));
2371 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2372 DeviceListList = tdsaAllShared->MainDeviceList.flink;
2373 tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2374 if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2375 {
2376 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2377 break;
2378 }
2379 else
2380 {
2381 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2382 }
2383 }
2384 else
2385 {
2386 DeviceListList = DeviceListList->flink;
2387 }
2388 } /* while */
2389
2390
2391 tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2392 if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2393 {
2394 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2395 TI_DBG1(("tdssReportRemovals: 2nd empty device list\n"));
2396 return;
2397 }
2398 else
2399 {
2400 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2401 }
2402 DeviceListList = tdsaAllShared->MainDeviceList.flink;
2403 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2404 {
2405 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2406 if (oneDeviceData == agNULL)
2407 {
2408 TI_DBG1(("tdssReportRemovals: oneDeviceData is NULL!!!\n"));
2409 return;
2410 }
2411 TI_DBG2(("tdssReportRemovals: loop did %d\n", oneDeviceData->id));
2412 TI_DBG2(("tdssReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2413 TI_DBG2(("tdssReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2414 TI_DBG2(("tdssReportRemovals: valid %d\n", oneDeviceData->valid));
2415 TI_DBG2(("tdssReportRemovals: valid2 %d\n", oneDeviceData->valid2));
2416 TI_DBG2(("tdssReportRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
2417 TI_DBG2(("tdssReportRemovals: registered %d\n", oneDeviceData->registered));
2418 if ( oneDeviceData->tdPortContext == onePortContext)
2419 {
2420 TI_DBG2(("tdssReportRemovals: right portcontext pid %d\n", onePortContext->id));
2421 if (oneDeviceData->valid == agTRUE && oneDeviceData->registered == agTRUE)
2422 {
2423 TI_DBG2(("tdssReportRemovals: removing\n"));
2424
2425 /* notify only reported devices to OS layer*/
2426 if ( DEVICE_IS_SSP_TARGET(oneDeviceData) ||
2427 DEVICE_IS_STP_TARGET(oneDeviceData) ||
2428 DEVICE_IS_SATA_DEVICE(oneDeviceData)
2429 )
2430 {
2431 removed = agTRUE;
2432 }
2433
2434 if ( (oneDeviceData->registered == agTRUE) &&
2435 ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData)
2436 || DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_SMP_TARGET(oneDeviceData) )
2437 )
2438 {
2439 /* all targets except expanders */
2440 TI_DBG2(("tdssReportRemovals: calling tdsaAbortAll\n"));
2441 TI_DBG2(("tdssReportRemovals: did %d\n", oneDeviceData->id));
2442 TI_DBG2(("tdssReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2443 TI_DBG2(("tdssReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2444 tdsaAbortAll(tiRoot, agRoot, oneDeviceData);
2445 }
2446 else if (oneDeviceData->registered == agTRUE)
2447 {
2448 /* expanders */
2449 TI_DBG1(("tdssReportRemovals: calling saDeregisterDeviceHandle, did %d\n", oneDeviceData->id));
2450 TI_DBG2(("tdssReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2451 TI_DBG2(("tdssReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2452 saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, 0);
2453 }
2454
2455 /* reset valid bit */
2456 oneDeviceData->valid = agFALSE;
2457 oneDeviceData->valid2 = agFALSE;
2458 oneDeviceData->registered = agFALSE;
2459 /* reset NumOfFCA */
2460 oneDeviceData->satDevData.NumOfFCA = 0;
2461
2462 }
2463 /* called by port invalid case */
2464 if (flag == agTRUE)
2465 {
2466 oneDeviceData->tdPortContext = agNULL;
2467 TI_DBG1(("tdssReportRemovals: nulling-out tdPortContext; oneDeviceData did %d\n", oneDeviceData->id));
2468 }
2469 #ifdef REMOVED /* removed */
2470 /* directly attached SATA -> always remove it */
2471 if (oneDeviceData->DeviceType == TD_SATA_DEVICE &&
2472 oneDeviceData->directlyAttached == agTRUE)
2473 {
2474 TI_DBG1(("tdssReportRemovals: device did %d\n", oneDeviceData->id));
2475 TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
2476 TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceLis));
2477 DeviceListList = tdsaAllShared->MainDeviceList.flink;
2478 if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2479 {
2480 break;
2481 }
2482 }
2483 else
2484 {
2485 DeviceListList = DeviceListList->flink;
2486 }
2487 #endif /* REMOVED */
2488 DeviceListList = DeviceListList->flink;
2489 }
2490 else
2491 {
2492 if (oneDeviceData->tdPortContext != agNULL)
2493 {
2494 TI_DBG2(("tdssReportRemovals: different portcontext; oneDeviceData->tdPortContext pid %d oneportcontext pid %d oneDeviceData did %d\n",
2495 oneDeviceData->tdPortContext->id, onePortContext->id, oneDeviceData->id));
2496 }
2497 else
2498 {
2499 TI_DBG1(("tdssReportRemovals: different portcontext; oneDeviceData->tdPortContext pid NULL oneportcontext pid %d oneDeviceData did %d\n",
2500 onePortContext->id, oneDeviceData->id));
2501 }
2502 DeviceListList = DeviceListList->flink;
2503 }
2504 }
2505
2506 if (removed == agTRUE)
2507 {
2508 TI_DBG2(("tdssReportRemovals: removed at the end\n"));
2509 ostiInitiatorEvent(
2510 tiRoot,
2511 onePortContext->tiPortalContext,
2512 agNULL,
2513 tiIntrEventTypeDeviceChange,
2514 tiDeviceRemoval,
2515 agNULL
2516 );
2517 }
2518 } /* big else */
2519 return;
2520 }
2521
2522 /*
2523 changes valid and valid2 based on discovery type
2524 */
2525 osGLOBAL void
tdssInternalRemovals(agsaRoot_t * agRoot,tdsaPortContext_t * onePortContext)2526 tdssInternalRemovals(
2527 agsaRoot_t *agRoot,
2528 tdsaPortContext_t *onePortContext
2529 )
2530 {
2531 tdsaDeviceData_t *oneDeviceData = agNULL;
2532 tdList_t *DeviceListList;
2533 tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData;
2534 tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot;
2535 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
2536 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2537
2538 TI_DBG2(("tdssInternalRemovals: start\n"));
2539
2540 tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2541 if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2542 {
2543 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2544 TI_DBG1(("tdssInternalRemovals: empty device list\n"));
2545 return;
2546 }
2547 else
2548 {
2549 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2550 }
2551 DeviceListList = tdsaAllShared->MainDeviceList.flink;
2552 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2553 {
2554 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2555 TI_DBG3(("tdssInternalRemovals: loop did %d\n", oneDeviceData->id));
2556 TI_DBG3(("tdssInternalRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2557 TI_DBG3(("tdssInternalRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2558 TI_DBG3(("tdssInternalRemovals: valid %d\n", oneDeviceData->valid));
2559 TI_DBG3(("tdssInternalRemovals: valid2 %d\n", oneDeviceData->valid2));
2560 TI_DBG3(("tdssInternalRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
2561 TI_DBG3(("tdssInternalRemovals: registered %d\n", oneDeviceData->registered));
2562 if ( oneDeviceData->tdPortContext == onePortContext)
2563 {
2564 TI_DBG3(("tdssInternalRemovals: right portcontext pid %d\n", onePortContext->id));
2565 if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_INCREMENTAL_START)
2566 {
2567 TI_DBG3(("tdssInternalRemovals: incremental discovery\n"));
2568 oneDeviceData->valid2 = agFALSE;
2569 }
2570 else
2571 {
2572 TI_DBG3(("tdssInternalRemovals: full discovery\n"));
2573 oneDeviceData->valid = agFALSE;
2574 }
2575 DeviceListList = DeviceListList->flink;
2576 }
2577 else
2578 {
2579 if (oneDeviceData->tdPortContext != agNULL)
2580 {
2581 TI_DBG3(("tdssInternalRemovals: different portcontext; oneDeviceData->tdPortContext pid %d oneportcontext pid %d\n", oneDeviceData->tdPortContext->id, onePortContext->id));
2582 }
2583 else
2584 {
2585 TI_DBG3(("tdssInternalRemovals: different portcontext; oneDeviceData->tdPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
2586 }
2587 DeviceListList = DeviceListList->flink;
2588 }
2589 }
2590
2591
2592 return;
2593 }
2594
2595 /* resets all valid and valid2 */
2596 osGLOBAL void
tdssDiscoveryErrorRemovals(agsaRoot_t * agRoot,tdsaPortContext_t * onePortContext)2597 tdssDiscoveryErrorRemovals(
2598 agsaRoot_t *agRoot,
2599 tdsaPortContext_t *onePortContext
2600 )
2601 {
2602 tdsaDeviceData_t *oneDeviceData = agNULL;
2603 tdList_t *DeviceListList;
2604 tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData;
2605 tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot;
2606 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
2607 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2608
2609 TI_DBG1(("tdssDiscoveryErrorRemovals: start\n"));
2610
2611 tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
2612 if (TDLIST_EMPTY(&(tdsaAllShared->MainDeviceList)))
2613 {
2614 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2615 TI_DBG1(("tdssDiscoveryErrorRemovals: empty device list\n"));
2616 return;
2617 }
2618 else
2619 {
2620 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
2621 }
2622 DeviceListList = tdsaAllShared->MainDeviceList.flink;
2623 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
2624 {
2625 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
2626 TI_DBG2(("tdssDiscoveryErrorRemovals: loop did %d\n", oneDeviceData->id));
2627 TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2628 TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2629 TI_DBG2(("tdssDiscoveryErrorRemovals: valid %d\n", oneDeviceData->valid));
2630 TI_DBG2(("tdssDiscoveryErrorRemovals: valid2 %d\n", oneDeviceData->valid2));
2631 TI_DBG2(("tdssDiscoveryErrorRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached));
2632 TI_DBG2(("tdssDiscoveryErrorRemovals: registered %d\n", oneDeviceData->registered));
2633 if ( oneDeviceData->tdPortContext == onePortContext)
2634 {
2635 TI_DBG2(("tdssDiscoveryErrorRemovals: right portcontext pid %d\n", onePortContext->id));
2636 oneDeviceData->valid = agFALSE;
2637 oneDeviceData->valid2 = agFALSE;
2638 /* reset NumOfFCA */
2639 oneDeviceData->satDevData.NumOfFCA = 0;
2640
2641 if ( (oneDeviceData->registered == agTRUE) &&
2642 ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData)
2643 || DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_SMP_TARGET(oneDeviceData) )
2644 )
2645 {
2646 /* all targets other than expanders */
2647 TI_DBG2(("tdssDiscoveryErrorRemovals: calling tdsaAbortAll\n"));
2648 TI_DBG2(("tdssDiscoveryErrorRemovals: did %d\n", oneDeviceData->id));
2649 TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2650 TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2651 tdsaAbortAll(tiRoot, agRoot, oneDeviceData);
2652 }
2653 else if (oneDeviceData->registered == agTRUE)
2654 {
2655 /* expanders */
2656 TI_DBG2(("tdssDiscoveryErrorRemovals: calling saDeregisterDeviceHandle\n"));
2657 TI_DBG2(("tdssDiscoveryErrorRemovals: did %d\n", oneDeviceData->id));
2658 TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi));
2659 TI_DBG2(("tdssDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo));
2660 saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, 0);
2661 }
2662
2663 oneDeviceData->registered = agFALSE;
2664 DeviceListList = DeviceListList->flink;
2665 }
2666 else
2667 {
2668 if (oneDeviceData->tdPortContext != agNULL)
2669 {
2670 TI_DBG2(("tdssDiscoveryErrorRemovals: different portcontext; oneDeviceData->tdPortContext pid %d oneportcontext pid %d\n", oneDeviceData->tdPortContext->id, onePortContext->id));
2671 }
2672 else
2673 {
2674 TI_DBG2(("tdssDiscoveryErrorRemovals: different portcontext; oneDeviceData->tdPortContext pid NULL oneportcontext pid %d\n", onePortContext->id));
2675 }
2676 DeviceListList = DeviceListList->flink;
2677 }
2678 }
2679
2680
2681 return;
2682 }
2683
2684 /*****************************************************************************
2685 *! \brief tdsaSASDiscoverAbort
2686 *
2687 * Purpose: This function aborts on-going discovery.
2688 *
2689 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
2690 * instance.
2691 * \param onePortContext: Pointer to the portal context instance.
2692 *
2693 * \return:
2694 * None
2695 *
2696 * \note:
2697 *
2698 *****************************************************************************/
2699 /* this called when discovery is aborted
2700 aborted by whom
2701 */
2702 osGLOBAL void
tdsaSASDiscoverAbort(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext)2703 tdsaSASDiscoverAbort(
2704 tiRoot_t *tiRoot,
2705 tdsaPortContext_t *onePortContext
2706 )
2707 {
2708
2709 TI_DBG2(("tdsaSASDiscoverAbort: start\n"));
2710 TI_DBG2(("tdsaSASDiscoverAbort: pPort=%p DONE\n", onePortContext));
2711 TI_DBG2(("tdsaSASDiscoverAbort: DiscoveryState %d\n", onePortContext->DiscoveryState));
2712
2713 onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
2714 /* clean up expanders data strucures; move to free exp when device is cleaned */
2715 tdsaCleanAllExp(tiRoot, onePortContext);
2716
2717 /* unregister devices */
2718 tdssReportRemovals(onePortContext->agRoot,
2719 onePortContext,
2720 agFALSE
2721 );
2722 }
2723
2724 #ifdef AGTIAPI_CTL
2725
2726 STATIC void
2727 tdsaCTLNextDevice(
2728 tiRoot_t *tiRoot,
2729 tdsaPortContext_t *onePortContext,
2730 tdIORequest_t *tdIORequest,
2731 tdList_t *DeviceList);
2732
2733 STATIC void
tdsaCTLIOCompleted(agsaRoot_t * agRoot,agsaIORequest_t * agIORequest,bit32 agIOStatus,bit32 agIOInfoLen,void * agParam,bit16 sspTag,bit32 agOtherInfo)2734 tdsaCTLIOCompleted(
2735 agsaRoot_t *agRoot,
2736 agsaIORequest_t *agIORequest,
2737 bit32 agIOStatus,
2738 bit32 agIOInfoLen,
2739 void *agParam,
2740 bit16 sspTag,
2741 bit32 agOtherInfo)
2742 {
2743 tiRoot_t *tiRoot = (tiRoot_t*)
2744 ((tdsaRootOsData_t*)agRoot->osData)->tiRoot;
2745 tdIORequestBody_t *tdIORequestBody;
2746 tdIORequest_t *tdIORequest;
2747 tdsaDeviceData_t *oneDeviceData;
2748
2749 tdIORequest = (tdIORequest_t *)agIORequest->osData;
2750 tdIORequestBody = &tdIORequest->tdIORequestBody;
2751 tdIORequestBody->ioCompleted = agTRUE;
2752 tdIORequestBody->ioStarted = agFALSE;
2753 oneDeviceData = (tdsaDeviceData_t *)tdIORequestBody->tiDevHandle->tdData;
2754
2755 TI_DBG6(("tdsaCTLIOCompleted: stat x%x len %d id %d\n", agIOStatus,
2756 agIOInfoLen, oneDeviceData->id));
2757
2758 //if ((agIOStatus == OSSA_IO_SUCCESS) && (agIOInfoLen == 0))
2759 /* SCSI command was completed OK, this is the normal path. */
2760 if (agIOInfoLen)
2761 {
2762 TI_DBG6(("tdsaCTLIOCompleted: SASDevAddr 0x%x / 0x%x PhyId 0x%x WARN "
2763 "setting CTL\n",
2764 oneDeviceData->SASAddressID.sasAddressHi,
2765 oneDeviceData->SASAddressID.sasAddressLo,
2766 oneDeviceData->SASAddressID.phyIdentifier));
2767 tdhexdump("tdsaCTLIOCompleted: response", (bit8 *)agParam, agIOInfoLen);
2768 }
2769
2770 tdsaCTLNextDevice(tiRoot, oneDeviceData->tdPortContext, tdIORequest,
2771 oneDeviceData->MainLink.flink);
2772 } /* tdsaCTLIOCompleted */
2773
2774 STATIC int
tdsaCTLModeSelect(tiRoot_t * tiRoot,tiDeviceHandle_t * tiDeviceHandle,tdIORequest_t * tdIORequest)2775 tdsaCTLModeSelect(
2776 tiRoot_t *tiRoot,
2777 tiDeviceHandle_t *tiDeviceHandle,
2778 tdIORequest_t *tdIORequest)
2779 {
2780 tiIORequest_t *tiIORequest;
2781 tdsaDeviceData_t *oneDeviceData;
2782 agsaRoot_t *agRoot = agNULL;
2783 tdsaRoot_t *tdsaRoot = (tdsaRoot_t*)tiRoot->tdData;
2784 tdsaContext_t *tdsaAllShared = (tdsaContext_t*)
2785 &tdsaRoot->tdsaAllShared;
2786 agsaIORequest_t *agIORequest = agNULL;
2787 agsaDevHandle_t *agDevHandle = agNULL;
2788 agsaSASRequestBody_t *agSASRequestBody = agNULL;
2789 bit32 tiStatus;
2790 bit32 saStatus;
2791 tdIORequestBody_t *tdIORequestBody;
2792 agsaSSPInitiatorRequest_t *agSSPInitiatorRequest;
2793 unsigned char *virtAddr;
2794 tiSgl_t agSgl;
2795 static unsigned char cdb[6] =
2796 {
2797 MODE_SELECT,
2798 PAGE_FORMAT,
2799 0,
2800 0,
2801 DR_MODE_PG_SZ
2802 };
2803
2804 virtAddr = (unsigned char*)tdIORequest->virtAddr;
2805 virtAddr[0] = DR_MODE_PG_CODE; /* Disconnect-Reconnect mode page code */
2806 virtAddr[1] = DR_MODE_PG_LENGTH; /* DR Mode pg length */
2807 virtAddr[8] = tdsaAllShared->SASConnectTimeLimit >> 8;
2808 virtAddr[9] = tdsaAllShared->SASConnectTimeLimit & 0xff;
2809
2810 oneDeviceData = (tdsaDeviceData_t*)tiDeviceHandle->tdData;
2811 TI_DBG4(("tdsaCTLModeSelect: id %d\n", oneDeviceData->id));
2812
2813 agRoot = oneDeviceData->agRoot;
2814 agDevHandle = oneDeviceData->agDevHandle;
2815 tiIORequest = &tdIORequest->tiIORequest;
2816
2817 tdIORequestBody = &tdIORequest->tdIORequestBody;
2818
2819 //tdIORequestBody->IOCompletionFunc = tdsaCTLIOCompleted;//itdssIOCompleted;
2820 tdIORequestBody->tiDevHandle = tiDeviceHandle;
2821 tdIORequestBody->IOType.InitiatorRegIO.expDataLength = DR_MODE_PG_SZ;
2822
2823 agIORequest = &tdIORequestBody->agIORequest;
2824 agIORequest->sdkData = agNULL; /* LL takes care of this */
2825
2826 agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody);
2827 agSSPInitiatorRequest = &(agSASRequestBody->sspInitiatorReq);
2828
2829 osti_memcpy(agSSPInitiatorRequest->sspCmdIU.cdb, cdb, 6);
2830 agSSPInitiatorRequest->dataLength = DR_MODE_PG_SZ;
2831
2832 agSSPInitiatorRequest->firstBurstSize = 0;
2833
2834 tdIORequestBody->agRequestType = AGSA_SSP_INIT_WRITE;
2835 tdIORequestBody->ioStarted = agTRUE;
2836 tdIORequestBody->ioCompleted = agFALSE;
2837
2838 agSgl.lower = BIT32_TO_LEBIT32(tdIORequest->physLower32);
2839 #if (BITS_PER_LONG > 32)
2840 agSgl.upper = BIT32_TO_LEBIT32(tdIORequest->physUpper32);
2841 #else
2842 agSgl1.upper = 0;
2843 #endif
2844 agSgl.type = BIT32_TO_LEBIT32(tiSgl);
2845 agSgl.len = BIT32_TO_LEBIT32(DR_MODE_PG_SZ);
2846
2847 /* initializes "agsaSgl_t agSgl" of "agsaDifSSPInitiatorRequest_t" */
2848 tiStatus = itdssIOPrepareSGL(tiRoot, tdIORequestBody, &agSgl,
2849 tdIORequest->virtAddr);
2850 if (tiStatus != tiSuccess)
2851 {
2852 TI_DBG1(("tdsaCTLModeSelect: can't get SGL\n"));
2853 ostiFreeMemory(tiRoot, tdIORequest->osMemHandle2, DR_MODE_PG_SZ);
2854 ostiFreeMemory(tiRoot, tdIORequest->osMemHandle, sizeof(*tdIORequest));
2855 return tiError;
2856 }
2857
2858 saStatus = saSSPStart(agRoot, agIORequest,
2859 tdsaRotateQnumber(tiRoot, oneDeviceData), agDevHandle,
2860 AGSA_SSP_INIT_WRITE, agSASRequestBody, agNULL,
2861 &tdsaCTLIOCompleted);
2862 if (saStatus == AGSA_RC_SUCCESS)
2863 {
2864 tiStatus = tiSuccess;
2865 TI_DBG4(("tdsaCTLModeSelect: saSSPStart OK\n"));
2866 }
2867 else
2868 {
2869 tdIORequestBody->ioStarted = agFALSE;
2870 tdIORequestBody->ioCompleted = agTRUE;
2871 if (saStatus == AGSA_RC_BUSY)
2872 {
2873 tiStatus = tiBusy;
2874 TI_DBG4(("tdsaCTLModeSelect: saSSPStart busy\n"));
2875 }
2876 else
2877 {
2878 tiStatus = tiError;
2879 TI_DBG4(("tdsaCTLModeSelect: saSSPStart Error\n"));
2880 }
2881 tdsaCTLNextDevice(tiRoot, oneDeviceData->tdPortContext, tdIORequest,
2882 oneDeviceData->MainLink.flink);
2883 }
2884 return tiStatus;
2885 } /* tdsaCTLModeSelect */
2886
2887 STATIC void
tdsaCTLNextDevice(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdIORequest_t * tdIORequest,tdList_t * DeviceList)2888 tdsaCTLNextDevice(
2889 tiRoot_t *tiRoot,
2890 tdsaPortContext_t *onePortContext,
2891 tdIORequest_t *tdIORequest,
2892 tdList_t *DeviceList)
2893 {
2894 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *)tiRoot->tdData;
2895 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2896 tdsaDeviceData_t *oneDeviceData;
2897 tiIntrEventType_t eventType;
2898 bit32 eventStatus;
2899 int rc;
2900
2901 /*
2902 * From the device list, returns only valid devices
2903 */
2904 for (; DeviceList && DeviceList != &(tdsaAllShared->MainDeviceList);
2905 DeviceList = DeviceList->flink)
2906 {
2907 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceList);
2908 TI_DBG6(("tdsaCTLNextDevice: devHandle %p\n",
2909 &(oneDeviceData->tiDeviceHandle)));
2910 if (oneDeviceData->tdPortContext != onePortContext)
2911 continue;
2912 if ((oneDeviceData->discovered == agFALSE) &&
2913 (oneDeviceData->registered == agTRUE) &&
2914 DEVICE_IS_SSP_TARGET(oneDeviceData) &&
2915 !DEVICE_IS_SSP_INITIATOR(oneDeviceData))
2916 {
2917 oneDeviceData->discovered = agTRUE;
2918 rc = tdsaCTLModeSelect(tiRoot, &oneDeviceData->tiDeviceHandle,
2919 tdIORequest);
2920 TI_DBG1(("tdsaCTLNextDevice: ModeSelect ret %d\n", rc));
2921 return;
2922 }
2923 }
2924 TI_DBG2(("tdsaCTLNextDevice: no more devices found\n"));
2925
2926 eventType = tdIORequest->eventType;
2927 eventStatus = tdIORequest->eventStatus;
2928
2929 /* no more devices, free the memory */
2930 ostiFreeMemory(tiRoot, tdIORequest->osMemHandle2, DR_MODE_PG_SZ);
2931 ostiFreeMemory(tiRoot, tdIORequest->osMemHandle, sizeof(*tdIORequest));
2932
2933 /* send Discovery Done event */
2934 ostiInitiatorEvent(tiRoot, onePortContext->tiPortalContext, agNULL,
2935 eventType, eventStatus, agNULL);
2936 } /* tdsaCTLNextDevice */
2937
2938 osGLOBAL void
tdsaCTLSet(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tiIntrEventType_t eventType,bit32 eventStatus)2939 tdsaCTLSet(
2940 tiRoot_t *tiRoot,
2941 tdsaPortContext_t *onePortContext,
2942 tiIntrEventType_t eventType,
2943 bit32 eventStatus)
2944 {
2945 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *)tiRoot->tdData;
2946 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
2947 tdIORequest_t *tdIORequest;
2948 tdIORequestBody_t *tdIORequestBody;
2949 tiIORequest_t *tiIORequest;
2950 bit32 memAllocStatus;
2951 void *osMemHandle;
2952 bit32 physUpper32;
2953 bit32 physLower32;
2954
2955 TI_DBG2(("tdsaCTLSet: tiPortalContext pid %d etyp %x stat %x\n",
2956 onePortContext->id, eventType, eventStatus));
2957
2958 if (onePortContext->DiscoveryState != ITD_DSTATE_COMPLETED)
2959 {
2960 TI_DBG1(("tdsaCTLSet: discovery not completed\n"));
2961 return;
2962 }
2963
2964 /* use the same memory for all valid devices */
2965 memAllocStatus = ostiAllocMemory(tiRoot, &osMemHandle, (void **)&tdIORequest,
2966 &physUpper32, &physLower32, 8,
2967 sizeof(*tdIORequest), agTRUE);
2968 if (memAllocStatus != tiSuccess || tdIORequest == agNULL)
2969 {
2970 TI_DBG1(("tdsaCTLSet: ostiAllocMemory failed\n"));
2971 return;// tiError;
2972 }
2973 osti_memset(tdIORequest, 0, sizeof(*tdIORequest));
2974
2975 tdIORequest->osMemHandle = osMemHandle;
2976 tdIORequest->eventType = eventType;
2977 tdIORequest->eventStatus = eventStatus;
2978
2979 tiIORequest = &tdIORequest->tiIORequest;
2980 tdIORequestBody = &tdIORequest->tdIORequestBody;
2981 /* save context if we need to abort later */
2982 tiIORequest->tdData = tdIORequestBody;
2983
2984 tdIORequestBody->IOCompletionFunc = NULL;//itdssIOCompleted;
2985 tdIORequestBody->tiIORequest = tiIORequest;
2986 tdIORequestBody->IOType.InitiatorRegIO.expDataLength = 16;
2987
2988 tdIORequestBody->agIORequest.osData = (void *)tdIORequest; //tdIORequestBody;
2989
2990 memAllocStatus = ostiAllocMemory(tiRoot, &tdIORequest->osMemHandle2,
2991 (void **)&tdIORequest->virtAddr,
2992 &tdIORequest->physUpper32,
2993 &tdIORequest->physLower32,
2994 8, DR_MODE_PG_SZ, agFALSE);
2995 if (memAllocStatus != tiSuccess || tdIORequest == agNULL)
2996 {
2997 TI_DBG1(("tdsaCTLSet: ostiAllocMemory noncached failed\n"));
2998 ostiFreeMemory(tiRoot, tdIORequest->osMemHandle, sizeof(*tdIORequest));
2999 return;// tiError;
3000 }
3001
3002 osti_memset(tdIORequest->virtAddr, 0, DR_MODE_PG_SZ);
3003 tdsaCTLNextDevice(tiRoot, onePortContext, tdIORequest,
3004 tdsaAllShared->MainDeviceList.flink);
3005 } /* tdsaCTLSet*/
3006 #endif
3007
3008 /*****************************************************************************
3009 *! \brief tdsaSASDiscoverDone
3010 *
3011 * Purpose: This function called to finish up SAS discovery.
3012 *
3013 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3014 * instance.
3015 * \param onePortContext: Pointer to the portal context instance.
3016 *
3017 * \return:
3018 * None
3019 *
3020 * \note:
3021 *
3022 *****************************************************************************/
3023 osGLOBAL void
tdsaSASDiscoverDone(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,bit32 flag)3024 tdsaSASDiscoverDone(
3025 tiRoot_t *tiRoot,
3026 tdsaPortContext_t *onePortContext,
3027 bit32 flag
3028 )
3029 {
3030 #ifndef SATA_ENABLE
3031 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *)tiRoot->tdData;
3032 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
3033 #endif
3034
3035 TI_DBG3(("tdsaSASDiscoverDone: start\n"));
3036 TI_DBG3(("tdsaSASDiscoverDone: pPort=%p DONE\n", onePortContext));
3037 TI_DBG3(("tdsaSASDiscoverDone: pid %d\n", onePortContext->id));
3038
3039 /* Set discovery status */
3040 onePortContext->discovery.status = DISCOVERY_SAS_DONE;
3041
3042 #ifdef TD_INTERNAL_DEBUG /* debugging only */
3043 TI_DBG3(("tdsaSASDiscoverDone: BEFORE\n"));
3044 tdsaDumpAllExp(tiRoot, onePortContext, agNULL);
3045 tdsaDumpAllUpExp(tiRoot, onePortContext, agNULL);
3046 #endif
3047
3048 /* clean up expanders data strucures; move to free exp when device is cleaned */
3049 tdsaCleanAllExp(tiRoot, onePortContext);
3050
3051 #ifdef TD_INTERNAL_DEBUG /* debugging only */
3052 TI_DBG3(("tdsaSASDiscoverDone: AFTER\n"));
3053 tdsaDumpAllExp(tiRoot, onePortContext, agNULL);
3054 tdsaDumpAllUpExp(tiRoot, onePortContext, agNULL);
3055 #endif
3056
3057
3058 /* call back to notify discovery is done */
3059 /* SATA is NOT enbled */
3060 #ifndef SATA_ENABLE
3061 if (onePortContext->discovery.SeenBC == agTRUE)
3062 {
3063 TI_DBG3(("tdsaSASDiscoverDone: broadcast change; discover again\n"));
3064 tdssInternalRemovals(onePortContext->agRoot,
3065 onePortContext
3066 );
3067
3068 /* processed broadcast change */
3069 onePortContext->discovery.SeenBC = agFALSE;
3070 if (tdsaAllShared->ResetInDiscovery != 0 &&
3071 onePortContext->discovery.ResetTriggerred == agTRUE)
3072 {
3073 TI_DBG2(("tdsaSASDiscoverDone: tdsaBCTimer\n"));
3074 tdsaBCTimer(tiRoot, onePortContext);
3075 }
3076 else
3077 {
3078 tdsaDiscover(
3079 tiRoot,
3080 onePortContext,
3081 TDSA_DISCOVERY_TYPE_SAS,
3082 TDSA_DISCOVERY_OPTION_INCREMENTAL_START
3083 );
3084 }
3085 }
3086 else
3087 {
3088 onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
3089
3090 if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
3091 {
3092 if (flag == tiSuccess)
3093 {
3094 #ifdef AGTIAPI_CTL
3095 if (tdsaAllShared->SASConnectTimeLimit)
3096 tdsaCTLSet(tiRoot, onePortContext, tiIntrEventTypeDiscovery,
3097 tiDiscOK);
3098 else
3099 #endif
3100 ostiInitiatorEvent(
3101 tiRoot,
3102 onePortContext->tiPortalContext,
3103 agNULL,
3104 tiIntrEventTypeDiscovery,
3105 tiDiscOK,
3106 agNULL
3107 );
3108 }
3109 else
3110 {
3111 TI_DBG1(("tdsaSASDiscoverDone: discovery failed\n"));
3112 tdssDiscoveryErrorRemovals(onePortContext->agRoot,
3113 onePortContext
3114 );
3115
3116 ostiInitiatorEvent(
3117 tiRoot,
3118 onePortContext->tiPortalContext,
3119 agNULL,
3120 tiIntrEventTypeDiscovery,
3121 tiDiscFailed,
3122 agNULL
3123 );
3124 }
3125 }
3126 else
3127 {
3128 if (flag == tiSuccess)
3129 {
3130 tdssReportChanges(onePortContext->agRoot,
3131 onePortContext
3132 );
3133 }
3134 else
3135 {
3136 tdssReportRemovals(onePortContext->agRoot,
3137 onePortContext,
3138 agFALSE
3139 );
3140 }
3141 }
3142 }
3143 #ifdef TBD
3144 /* ACKing BC */
3145 tdsaAckBC(tiRoot, onePortContext);
3146 #endif
3147
3148 #endif
3149
3150 #ifdef SATA_ENABLE
3151
3152 if (flag == tiSuccess)
3153 {
3154 TI_DBG3(("tdsaSASDiscoverDone: calling SATA discovery\n"));
3155 /*
3156 tdsaSATAFullDiscover() or tdsaincrementalDiscover()
3157 call sata discover
3158 when sata discover is done, call ostiInitiatorEvent
3159 */
3160 if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
3161 {
3162 TI_DBG3(("tdsaSASDiscoverDone: calling FULL SATA discovery\n"));
3163 tdsaDiscover(
3164 tiRoot,
3165 onePortContext,
3166 AG_SA_DISCOVERY_TYPE_SATA,
3167 TDSA_DISCOVERY_OPTION_FULL_START
3168 );
3169 }
3170 else
3171 {
3172 TI_DBG3(("tdsaSASDiscoverDone: calling INCREMENTAL SATA discovery\n"));
3173 tdsaDiscover(
3174 tiRoot,
3175 onePortContext,
3176 AG_SA_DISCOVERY_TYPE_SATA,
3177 TDSA_DISCOVERY_OPTION_INCREMENTAL_START
3178 );
3179 }
3180 }
3181 else
3182 {
3183 /* error case */
3184 TI_DBG1(("tdsaSASDiscoverDone: Error; clean up\n"));
3185 tdssDiscoveryErrorRemovals(onePortContext->agRoot,
3186 onePortContext
3187 );
3188
3189 onePortContext->discovery.SeenBC = agFALSE;
3190 onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
3191 ostiInitiatorEvent(
3192 tiRoot,
3193 onePortContext->tiPortalContext,
3194 agNULL,
3195 tiIntrEventTypeDiscovery,
3196 tiDiscFailed,
3197 agNULL
3198 );
3199 }
3200 #endif
3201 return;
3202 }
3203
3204 //temp only for testing
3205 osGLOBAL void
tdsaReportManInfoSend(tiRoot_t * tiRoot,tdsaDeviceData_t * oneDeviceData)3206 tdsaReportManInfoSend(
3207 tiRoot_t *tiRoot,
3208 tdsaDeviceData_t *oneDeviceData
3209 )
3210 {
3211 agsaRoot_t *agRoot;
3212
3213 agRoot = oneDeviceData->agRoot;
3214
3215 TI_DBG2(("tdsaReportManInfoSend: start\n"));
3216
3217 tdSMPStart(
3218 tiRoot,
3219 agRoot,
3220 oneDeviceData,
3221 SMP_REPORT_MANUFACTURE_INFORMATION,
3222 agNULL,
3223 0,
3224 AGSA_SMP_INIT_REQ,
3225 agNULL,
3226 0
3227 );
3228
3229 return;
3230 }
3231
3232
3233 osGLOBAL void
tdsaReportManInfoRespRcvd(tiRoot_t * tiRoot,agsaRoot_t * agRoot,tdsaDeviceData_t * oneDeviceData,tdssSMPFrameHeader_t * frameHeader,agsaFrameHandle_t frameHandle)3234 tdsaReportManInfoRespRcvd(
3235 tiRoot_t *tiRoot,
3236 agsaRoot_t *agRoot,
3237 tdsaDeviceData_t *oneDeviceData,
3238 tdssSMPFrameHeader_t *frameHeader,
3239 agsaFrameHandle_t frameHandle
3240 )
3241 {
3242 tdsaPortContext_t *onePortContext;
3243 tdsaDiscovery_t *discovery;
3244
3245 TI_DBG2(("tdsaReportManInfoRespRcvd: start\n"));
3246 TI_DBG2(("tdsaReportManInfoRespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3247 TI_DBG2(("tdsaReportManInfoRespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3248
3249 onePortContext = oneDeviceData->tdPortContext;
3250 discovery = &(onePortContext->discovery);
3251
3252 if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
3253 {
3254 TI_DBG2(("tdsaReportManInfoRespRcvd: SMP accepted\n"));
3255 }
3256 else
3257 {
3258 TI_DBG1(("tdsaReportManInfoRespRcvd: SMP NOT accepted; fn result 0x%x\n", frameHeader->smpFunctionResult));
3259 }
3260
3261 TI_DBG2(("tdsaReportManInfoRespRcvd: discovery retries %d\n", discovery->retries));
3262 discovery->retries++;
3263
3264 if (discovery->retries >= DISCOVERY_RETRIES)
3265 {
3266 TI_DBG1(("tdsaReportManInfoRespRcvd: retries are over\n"));
3267 discovery->retries = 0;
3268 /* failed the discovery */
3269 }
3270 else
3271 {
3272 TI_DBG1(("tdsaReportManInfoRespRcvd: keep retrying\n"));
3273 // start timer
3274 tdsaDiscoveryTimer(tiRoot, onePortContext, oneDeviceData);
3275 }
3276
3277 return;
3278 }
3279
3280 //end temp only for testing
3281
3282 /*****************************************************************************
3283 *! \brief tdsaReportGeneralSend
3284 *
3285 * Purpose: This function sends Report General SMP to a device.
3286 *
3287 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3288 * instance.
3289 * \param oneDeviceData: Pointer to the device data.
3290 *
3291 * \return:
3292 * None
3293 *
3294 * \note:
3295 *
3296 *****************************************************************************/
3297 osGLOBAL void
tdsaReportGeneralSend(tiRoot_t * tiRoot,tdsaDeviceData_t * oneDeviceData)3298 tdsaReportGeneralSend(
3299 tiRoot_t *tiRoot,
3300 tdsaDeviceData_t *oneDeviceData
3301 )
3302 {
3303 agsaRoot_t *agRoot;
3304
3305 agRoot = oneDeviceData->agRoot;
3306
3307 TI_DBG3(("tdsaReportGeneralSend: start\n"));
3308
3309 tdSMPStart(
3310 tiRoot,
3311 agRoot,
3312 oneDeviceData,
3313 SMP_REPORT_GENERAL,
3314 agNULL,
3315 0,
3316 AGSA_SMP_INIT_REQ,
3317 agNULL,
3318 0
3319 );
3320
3321 return;
3322 }
3323
3324 /*****************************************************************************
3325 *! \brief tdsaReportGeneralRespRcvd
3326 *
3327 * Purpose: This function processes Report General response.
3328 *
3329 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3330 * instance.
3331 * \param agRoot: Pointer to chip/driver Instance.
3332 * \param oneDeviceData: Pointer to the device data.
3333 * \param frameHeader: Pointer to SMP frame header.
3334 * \param frameHandle: A Handle used to refer to the response frame
3335 *
3336 * \return:
3337 * None
3338 *
3339 * \note:
3340 *
3341 *****************************************************************************/
3342 osGLOBAL void
tdsaReportGeneralRespRcvd(tiRoot_t * tiRoot,agsaRoot_t * agRoot,agsaIORequest_t * agIORequest,tdsaDeviceData_t * oneDeviceData,tdssSMPFrameHeader_t * frameHeader,agsaFrameHandle_t frameHandle)3343 tdsaReportGeneralRespRcvd(
3344 tiRoot_t *tiRoot,
3345 agsaRoot_t *agRoot,
3346 agsaIORequest_t *agIORequest,
3347 tdsaDeviceData_t *oneDeviceData,
3348 tdssSMPFrameHeader_t *frameHeader,
3349 agsaFrameHandle_t frameHandle
3350 )
3351 {
3352 smpRespReportGeneral_t tdSMPReportGeneralResp;
3353 smpRespReportGeneral_t *ptdSMPReportGeneralResp;
3354 tdsaExpander_t *oneExpander;
3355 tdsaPortContext_t *onePortContext;
3356 tdsaDiscovery_t *discovery;
3357 #ifdef REMOVED
3358 bit32 i;
3359 #endif
3360 #ifndef DIRECT_SMP
3361 tdssSMPRequestBody_t *tdSMPRequestBody;
3362 tdSMPRequestBody = (tdssSMPRequestBody_t *)agIORequest->osData;
3363 #endif
3364
3365 TI_DBG3(("tdsaReportGeneralRespRcvd: start\n"));
3366 TI_DBG3(("tdsaReportGeneralRespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3367 TI_DBG3(("tdsaReportGeneralRespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3368 ptdSMPReportGeneralResp = &tdSMPReportGeneralResp;
3369 osti_memset(&tdSMPReportGeneralResp, 0, sizeof(smpRespReportGeneral_t));
3370 #ifdef DIRECT_SMP
3371 saFrameReadBlock(agRoot, frameHandle, 4, ptdSMPReportGeneralResp, sizeof(smpRespReportGeneral_t));
3372 #else
3373 saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 4, ptdSMPReportGeneralResp, sizeof(smpRespReportGeneral_t));
3374 #endif
3375
3376 //tdhexdump("tdsaReportGeneralRespRcvd", (bit8 *)ptdSMPReportGeneralResp, sizeof(smpRespReportGeneral_t));
3377 #ifndef DIRECT_SMP
3378 ostiFreeMemory(
3379 tiRoot,
3380 tdSMPRequestBody->IndirectSMPReqosMemHandle,
3381 tdSMPRequestBody->IndirectSMPReqLen
3382 );
3383 ostiFreeMemory(
3384 tiRoot,
3385 tdSMPRequestBody->IndirectSMPResposMemHandle,
3386 tdSMPRequestBody->IndirectSMPRespLen
3387 );
3388 #endif
3389
3390 onePortContext = oneDeviceData->tdPortContext;
3391 discovery = &(onePortContext->discovery);
3392
3393 if (onePortContext->valid == agFALSE)
3394 {
3395 TI_DBG1(("tdsaReportGeneralRespRcvd: aborting discovery\n"));
3396 tdsaSASDiscoverAbort(tiRoot, onePortContext);
3397 return;
3398 }
3399 if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
3400 {
3401 oneDeviceData->numOfPhys = (bit8) ptdSMPReportGeneralResp->numOfPhys;
3402 oneExpander = oneDeviceData->tdExpander;
3403 oneExpander->routingIndex = (bit16) REPORT_GENERAL_GET_ROUTEINDEXES(ptdSMPReportGeneralResp);
3404 #ifdef REMOVED
3405 for ( i = 0; i < oneDeviceData->numOfPhys; i++ )
3406 {
3407 oneExpander->currentIndex[i] = 0;
3408 }
3409 #endif
3410 oneExpander->configReserved = 0;
3411 oneExpander->configRouteTable = REPORT_GENERAL_IS_CONFIGURABLE(ptdSMPReportGeneralResp) ? 1 : 0;
3412 oneExpander->configuring = REPORT_GENERAL_IS_CONFIGURING(ptdSMPReportGeneralResp) ? 1 : 0;
3413 TI_DBG3(("tdsaReportGeneralRespRcvd: oneExpander=%p numberofPhys=0x%x RoutingIndex=0x%x\n",
3414 oneExpander, oneDeviceData->numOfPhys, oneExpander->routingIndex));
3415 TI_DBG3(("tdsaReportGeneralRespRcvd: configRouteTable=%d configuring=%d\n",
3416 oneExpander->configRouteTable, oneExpander->configuring));
3417 if (oneExpander->configuring == 1)
3418 {
3419 discovery->retries++;
3420 if (discovery->retries >= DISCOVERY_RETRIES)
3421 {
3422 TI_DBG1(("tdsaReportGeneralRespRcvd: retries are over\n"));
3423 discovery->retries = 0;
3424 /* failed the discovery */
3425 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3426 }
3427 else
3428 {
3429 TI_DBG1(("tdsaReportGeneralRespRcvd: keep retrying\n"));
3430 // start timer for sending ReportGeneral
3431 tdsaDiscoveryTimer(tiRoot, onePortContext, oneDeviceData);
3432 }
3433 }
3434 else
3435 {
3436 discovery->retries = 0;
3437 tdsaDiscoverSend(tiRoot, oneDeviceData);
3438 }
3439 }
3440 else
3441 {
3442 TI_DBG1(("tdsaReportGeneralRespRcvd: SMP failed; fn result 0x%x; stopping discovery\n", frameHeader->smpFunctionResult));
3443 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3444 }
3445 return;
3446 }
3447
3448
3449 /*****************************************************************************
3450 *! \brief tdsaDiscoverSend
3451 *
3452 * Purpose: This function sends Discovery SMP to a device.
3453 *
3454 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3455 * instance.
3456 * \param oneDeviceData: Pointer to the device data.
3457 *
3458 * \return:
3459 * None
3460 *
3461 * \note:
3462 *
3463 *****************************************************************************/
3464 osGLOBAL void
tdsaDiscoverSend(tiRoot_t * tiRoot,tdsaDeviceData_t * oneDeviceData)3465 tdsaDiscoverSend(
3466 tiRoot_t *tiRoot,
3467 tdsaDeviceData_t *oneDeviceData
3468 )
3469 {
3470 agsaRoot_t *agRoot;
3471 tdsaExpander_t *oneExpander;
3472 smpReqDiscover_t smpDiscoverReq;
3473
3474 TI_DBG3(("tdsaDiscoverSend: start\n"));
3475 TI_DBG3(("tdsaDiscoverSend: device %p did %d\n", oneDeviceData, oneDeviceData->id));
3476 agRoot = oneDeviceData->agRoot;
3477 oneExpander = oneDeviceData->tdExpander;
3478 TI_DBG3(("tdsaDiscoverSend: phyID 0x%x\n", oneExpander->discoveringPhyId));
3479
3480
3481 osti_memset(&smpDiscoverReq, 0, sizeof(smpReqDiscover_t));
3482
3483 smpDiscoverReq.reserved1 = 0;
3484 smpDiscoverReq.reserved2 = 0;
3485 smpDiscoverReq.phyIdentifier = oneExpander->discoveringPhyId;
3486 smpDiscoverReq.reserved3 = 0;
3487
3488
3489 tdSMPStart(
3490 tiRoot,
3491 agRoot,
3492 oneDeviceData,
3493 SMP_DISCOVER,
3494 (bit8 *)&smpDiscoverReq,
3495 sizeof(smpReqDiscover_t),
3496 AGSA_SMP_INIT_REQ,
3497 agNULL,
3498 0
3499 );
3500 return;
3501 }
3502
3503
3504 /*****************************************************************************
3505 *! \brief tdsaDiscoverRespRcvd
3506 *
3507 * Purpose: This function processes Discovery response.
3508 *
3509 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3510 * instance.
3511 * \param agRoot: Pointer to chip/driver Instance.
3512 * \param oneDeviceData: Pointer to the device data.
3513 * \param frameHeader: Pointer to SMP frame header.
3514 * \param frameHandle: A Handle used to refer to the response frame
3515 *
3516 * \return:
3517 * None
3518 *
3519 * \note:
3520 *
3521 *****************************************************************************/
3522 osGLOBAL void
tdsaDiscoverRespRcvd(tiRoot_t * tiRoot,agsaRoot_t * agRoot,agsaIORequest_t * agIORequest,tdsaDeviceData_t * oneDeviceData,tdssSMPFrameHeader_t * frameHeader,agsaFrameHandle_t frameHandle)3523 tdsaDiscoverRespRcvd(
3524 tiRoot_t *tiRoot,
3525 agsaRoot_t *agRoot,
3526 agsaIORequest_t *agIORequest,
3527 tdsaDeviceData_t *oneDeviceData,
3528 tdssSMPFrameHeader_t *frameHeader,
3529 agsaFrameHandle_t frameHandle
3530 )
3531 {
3532 smpRespDiscover_t *ptdSMPDiscoverResp;
3533 tdsaPortContext_t *onePortContext;
3534 tdsaExpander_t *oneExpander;
3535 tdsaDiscovery_t *discovery;
3536 #ifndef DIRECT_SMP
3537 tdssSMPRequestBody_t *tdSMPRequestBody;
3538 #endif
3539
3540 TI_DBG3(("tdsaDiscoverRespRcvd: start\n"));
3541 TI_DBG3(("tdsaDiscoverRespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
3542 TI_DBG3(("tdsaDiscoverRespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
3543
3544
3545 onePortContext = oneDeviceData->tdPortContext;
3546 oneExpander = oneDeviceData->tdExpander;
3547 discovery = &(onePortContext->discovery);
3548 #ifndef DIRECT_SMP
3549 tdSMPRequestBody = (tdssSMPRequestBody_t *)agIORequest->osData;
3550 #endif
3551
3552 if (onePortContext->valid == agFALSE)
3553 {
3554 TI_DBG1(("tdsaDiscoverRespRcvd: aborting discovery\n"));
3555 tdsaSASDiscoverAbort(tiRoot, onePortContext);
3556 return;
3557 }
3558 ptdSMPDiscoverResp = &(discovery->SMPDiscoverResp);
3559 #ifdef DIRECT_SMP
3560 saFrameReadBlock(agRoot, frameHandle, 4, ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
3561 #else
3562 saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 4, ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
3563 #endif
3564 //tdhexdump("tdsaDiscoverRespRcvd", (bit8 *)ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
3565
3566 #ifndef DIRECT_SMP
3567 ostiFreeMemory(
3568 tiRoot,
3569 tdSMPRequestBody->IndirectSMPReqosMemHandle,
3570 tdSMPRequestBody->IndirectSMPReqLen
3571 );
3572 ostiFreeMemory(
3573 tiRoot,
3574 tdSMPRequestBody->IndirectSMPResposMemHandle,
3575 tdSMPRequestBody->IndirectSMPRespLen
3576 );
3577 #endif
3578
3579 if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
3580 {
3581 if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3582 {
3583 tdsaSASUpStreamDiscoverExpanderPhy(tiRoot, onePortContext, oneExpander, ptdSMPDiscoverResp);
3584 }
3585 else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
3586 {
3587 tdsaSASDownStreamDiscoverExpanderPhy(tiRoot, onePortContext, oneExpander, ptdSMPDiscoverResp);
3588 }
3589 else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING)
3590 {
3591 /* not done with configuring routing
3592 1. set the timer
3593 2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy()
3594 */
3595 TI_DBG2(("tdsaDiscoverRespRcvd: still configuring routing; setting timer\n"));
3596 TI_DBG2(("tdsaDiscoverRespRcvd: onePortContext %p oneDeviceData %p ptdSMPDiscoverResp %p\n", onePortContext, oneDeviceData, ptdSMPDiscoverResp));
3597 tdhexdump("tdsaDiscoverRespRcvd", (bit8*)ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
3598
3599 tdsaConfigureRouteTimer(tiRoot, onePortContext, oneExpander, ptdSMPDiscoverResp);
3600 }
3601 else
3602 {
3603 /* nothing */
3604 }
3605 }
3606 else if (frameHeader->smpFunctionResult == PHY_VACANT)
3607 {
3608 TI_DBG3(("tdsaDiscoverRespRcvd: smpFunctionResult is PHY_VACANT, phyid %d\n",
3609 oneExpander->discoveringPhyId));
3610 if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM)
3611 {
3612 tdsaSASUpStreamDiscoverExpanderPhySkip(tiRoot, onePortContext, oneExpander);
3613 }
3614 else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
3615 {
3616 tdsaSASDownStreamDiscoverExpanderPhySkip(tiRoot, onePortContext, oneExpander);
3617 }
3618 else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING)
3619 {
3620 /* not done with configuring routing
3621 1. set the timer
3622 2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy()
3623 */
3624 TI_DBG1(("tdsaDiscoverRespRcvd: still configuring routing; setting timer\n"));
3625 TI_DBG1(("tdsaDiscoverRespRcvd: onePortContext %p oneDeviceData %p ptdSMPDiscoverResp %p\n", onePortContext, oneDeviceData, ptdSMPDiscoverResp));
3626 tdhexdump("tdsaDiscoverRespRcvd", (bit8*)ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
3627
3628 tdsaConfigureRouteTimer(tiRoot, onePortContext, oneExpander, ptdSMPDiscoverResp);
3629 }
3630 }
3631 else
3632 {
3633 TI_DBG1(("tdsaDiscoverRespRcvd: Discovery Error SMP function return result error=%x\n",
3634 frameHeader->smpFunctionResult));
3635 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3636 }
3637 return;
3638 }
3639
3640 /*****************************************************************************
3641 *! \brief tdsaSASUpStreamDiscoverExpanderPhy
3642 *
3643 * Purpose: This function actully does upstream traverse and finds out detailed
3644 * information about topology.
3645 *
3646 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
3647 * instance.
3648 * \param onePortContext: Pointer to the portal context instance.
3649 * \param oneExpander: Pointer to the expander data.
3650 * \param pDiscoverResp: Pointer to the Discovery SMP respsonse.
3651 *
3652 * \return:
3653 * None
3654 *
3655 * \note:
3656 *
3657 *****************************************************************************/
3658 osGLOBAL void
tdsaSASUpStreamDiscoverExpanderPhy(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaExpander_t * oneExpander,smpRespDiscover_t * pDiscoverResp)3659 tdsaSASUpStreamDiscoverExpanderPhy(
3660 tiRoot_t *tiRoot,
3661 tdsaPortContext_t *onePortContext,
3662 tdsaExpander_t *oneExpander,
3663 smpRespDiscover_t *pDiscoverResp
3664 )
3665 {
3666 tdsaDeviceData_t *oneDeviceData;
3667 tdsaDeviceData_t *AttachedDevice = agNULL;
3668 tdsaExpander_t *AttachedExpander;
3669 agsaSASIdentify_t sasIdentify;
3670 bit8 connectionRate;
3671 bit32 attachedSasHi, attachedSasLo;
3672 tdsaSASSubID_t agSASSubID;
3673
3674 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: start\n"));
3675 if (onePortContext->valid == agFALSE)
3676 {
3677 TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: aborting discovery\n"));
3678 tdsaSASDiscoverAbort(tiRoot, onePortContext);
3679 return;
3680 }
3681
3682 oneDeviceData = oneExpander->tdDevice;
3683 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n",
3684 oneExpander->discoveringPhyId,
3685 oneDeviceData->SASAddressID.sasAddressHi,
3686 oneDeviceData->SASAddressID.sasAddressLo));
3687 TI_DBG3((" Attached device: %s\n",
3688 ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" :
3689 (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" :
3690 (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
3691
3692 if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
3693 {
3694 TI_DBG3((" SAS address : %08x-%08x\n",
3695 DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp),
3696 DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
3697 TI_DBG3((" SSP Target : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
3698 TI_DBG3((" STP Target : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
3699 TI_DBG3((" SMP Target : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
3700 TI_DBG3((" SATA DEVICE : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
3701 TI_DBG3((" SSP Initiator : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
3702 TI_DBG3((" STP Initiator : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
3703 TI_DBG3((" SMP Initiator : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
3704 TI_DBG3((" Phy ID : %d\n", pDiscoverResp->phyIdentifier));
3705 TI_DBG3((" Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
3706 }
3707 /* end for debugging */
3708
3709 /* for debugging */
3710 if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
3711 {
3712 TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n"));
3713 TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
3714 tdhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
3715 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3716 return;
3717 }
3718
3719 /* saving routing attribute for non self-configuring expanders */
3720 oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
3721
3722 /* for debugging */
3723 // dumpRoutingAttributes(tiRoot, oneExpander, pDiscoverResp->phyIdentifier);
3724
3725 if ( oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE )
3726 {
3727 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_FANOUT_EXPANDER\n"));
3728 if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
3729 {
3730 TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing on fanout expander device\n"));
3731
3732 /* discovery error */
3733 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
3734 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
3735 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
3736 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
3737 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
3738
3739 /* (2.1.3) discovery done */
3740 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3741 return;
3742 }
3743 }
3744 else
3745 {
3746 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_EDGE_EXPANDER\n"));
3747
3748 if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
3749 {
3750 /* Setup sasIdentify for the attached device */
3751 sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
3752 sasIdentify.deviceType_addressFrameType = (bit8)(pDiscoverResp->attachedDeviceType & 0x70);
3753 sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
3754 sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
3755 *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
3756 *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
3757
3758 /* incremental discovery */
3759 agSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
3760 agSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
3761 agSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
3762 agSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
3763
3764 attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
3765 attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
3766
3767 /* If the phy has subtractive routing attribute */
3768 if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
3769 {
3770 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: SA_SAS_ROUTING_SUBTRACTIVE\n"));
3771 /* Setup upstream phys */
3772 tdsaSASExpanderUpStreamPhyAdd(tiRoot, oneExpander, (bit8) pDiscoverResp->attachedPhyIdentifier);
3773 /* If the expander already has an upsteam device set up */
3774 if (oneExpander->hasUpStreamDevice == agTRUE)
3775 {
3776 /* If the sas address doesn't match */
3777 if ( ((oneExpander->upStreamSASAddressHi != attachedSasHi) ||
3778 (oneExpander->upStreamSASAddressLo != attachedSasLo)) &&
3779 (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
3780 DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
3781 )
3782 {
3783 /* TODO: discovery error, callback */
3784 TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address\n"));
3785 /* call back to notify discovery error */
3786 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
3787 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
3788 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
3789 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
3790 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
3791 /* discovery done */
3792 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3793 }
3794 }
3795 else
3796 {
3797 /* Setup SAS address for up stream device */
3798 oneExpander->hasUpStreamDevice = agTRUE;
3799 oneExpander->upStreamSASAddressHi = attachedSasHi;
3800 oneExpander->upStreamSASAddressLo = attachedSasLo;
3801
3802 if ( (onePortContext->sasLocalAddressHi != attachedSasHi)
3803 || (onePortContext->sasLocalAddressLo != attachedSasLo) )
3804 {
3805 /* Find the device from the discovered list */
3806 AttachedDevice = tdsaPortSASDeviceFind(tiRoot, onePortContext, attachedSasLo, attachedSasHi);
3807 /* If the device has been discovered before */
3808 if ( AttachedDevice != agNULL)
3809 {
3810 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Seen This Device Before\n"));
3811 /* If attached device is an edge expander */
3812 if ( AttachedDevice->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE)
3813 {
3814 /* The attached device is an expander */
3815 AttachedExpander = AttachedDevice->tdExpander;
3816 /* If the two expanders are the root of the two edge expander sets */
3817 if ( (AttachedExpander->upStreamSASAddressHi ==
3818 DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
3819 && (AttachedExpander->upStreamSASAddressLo ==
3820 DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)) )
3821 {
3822 /* Setup upstream expander for the pExpander */
3823 oneExpander->tdUpStreamExpander = AttachedExpander;
3824 }
3825 /* If the two expanders are not the root of the two edge expander sets */
3826 else
3827 {
3828 /* TODO: loop found, discovery error, callback */
3829 TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy: **** Topology Error loop detection\n"));
3830 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
3831 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
3832 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
3833 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
3834 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
3835 /* discovery done */
3836 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3837 }
3838 }
3839 /* If attached device is not an edge expander */
3840 else
3841 {
3842 /*TODO: should not happen, ASSERT */
3843 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy, *** Attached Device is not Edge. Confused!!\n"));
3844 }
3845 }
3846 /* If the device has not been discovered before */
3847 else
3848 {
3849 /* Add the device */
3850 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: New device\n"));
3851 /* read minimum rate from the configuration
3852 onePortContext->LinkRate is SPC's local link rate
3853 */
3854 connectionRate = (bit8)(MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)));
3855 TI_DBG3(("siSASUpStreamDiscoverExpanderPhy: link rate 0x%x\n", onePortContext->LinkRate));
3856 TI_DBG3(("siSASUpStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp)));
3857 TI_DBG3(("siSASUpStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate));
3858 //hhhhhhhh
3859 if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
3860 {
3861 /* incremental discovery */
3862 if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
3863 {
3864 AttachedDevice = tdsaPortSASDeviceAdd(
3865 tiRoot,
3866 onePortContext,
3867 sasIdentify,
3868 agFALSE,
3869 connectionRate,
3870 IT_NEXUS_TIMEOUT,
3871 0,
3872 STP_DEVICE_TYPE,
3873 oneDeviceData,
3874 pDiscoverResp->phyIdentifier
3875 );
3876 }
3877 else
3878 {
3879 /* incremental discovery */
3880 AttachedDevice = tdsaFindRegNValid(
3881 onePortContext->agRoot,
3882 onePortContext,
3883 &agSASSubID
3884 );
3885 /* not registered and not valid; add this*/
3886 if (AttachedDevice == agNULL)
3887 {
3888 AttachedDevice = tdsaPortSASDeviceAdd(
3889 tiRoot,
3890 onePortContext,
3891 sasIdentify,
3892 agFALSE,
3893 connectionRate,
3894 IT_NEXUS_TIMEOUT,
3895 0,
3896 STP_DEVICE_TYPE,
3897 oneDeviceData,
3898 pDiscoverResp->phyIdentifier
3899 );
3900 }
3901 }
3902 }
3903 else
3904 {
3905 /* incremental discovery */
3906 if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
3907 {
3908 AttachedDevice = tdsaPortSASDeviceAdd(
3909 tiRoot,
3910 onePortContext,
3911 sasIdentify,
3912 agFALSE,
3913 connectionRate,
3914 IT_NEXUS_TIMEOUT,
3915 0,
3916 SAS_DEVICE_TYPE,
3917 oneDeviceData,
3918 pDiscoverResp->phyIdentifier
3919 );
3920 }
3921 else
3922 {
3923 /* incremental discovery */
3924 AttachedDevice = tdsaFindRegNValid(
3925 onePortContext->agRoot,
3926 onePortContext,
3927 &agSASSubID
3928 );
3929 /* not registered and not valid; add this*/
3930 if (AttachedDevice == agNULL)
3931 {
3932 AttachedDevice = tdsaPortSASDeviceAdd(
3933 tiRoot,
3934 onePortContext,
3935 sasIdentify,
3936 agFALSE,
3937 connectionRate,
3938 IT_NEXUS_TIMEOUT,
3939 0,
3940 SAS_DEVICE_TYPE,
3941 oneDeviceData,
3942 pDiscoverResp->phyIdentifier
3943 );
3944 }
3945 }
3946 }
3947 /* If the device is added successfully */
3948 if ( AttachedDevice != agNULL)
3949 {
3950
3951 /* (3.1.2.3.2.3.2.1) callback about new device */
3952 if ( DISCRSP_IS_SSP_TARGET(pDiscoverResp)
3953 || DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)
3954 || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)
3955 || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) )
3956 {
3957 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Found SSP/SMP SAS %08x-%08x\n",
3958 attachedSasHi, attachedSasLo));
3959 }
3960 else
3961 {
3962 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Found a SAS STP device.\n"));
3963 }
3964 /* If the attached device is an expander */
3965 if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
3966 || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) )
3967 {
3968 /* Allocate an expander data structure */
3969 AttachedExpander = tdssSASDiscoveringExpanderAlloc(
3970 tiRoot,
3971 onePortContext,
3972 AttachedDevice
3973 );
3974
3975 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Found expander=%p\n", AttachedExpander));
3976 /* If allocate successfully */
3977 if ( AttachedExpander != agNULL)
3978 {
3979 /* Add the pAttachedExpander to discovering list */
3980 tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, AttachedExpander);
3981 /* Setup upstream expander for the pExpander */
3982 oneExpander->tdUpStreamExpander = AttachedExpander;
3983 }
3984 /* If failed to allocate */
3985 else
3986 {
3987 TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy, Failed to allocate expander data structure\n"));
3988 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
3989 }
3990 }
3991 /* If the attached device is an end device */
3992 else
3993 {
3994 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: Found end device\n"));
3995 /* LP2006-05-26 added upstream device to the newly found device */
3996 AttachedDevice->tdExpander = oneExpander;
3997 oneExpander->tdUpStreamExpander = agNULL;
3998 }
3999 }
4000 else
4001 {
4002 TI_DBG1(("tdsaSASUpStreamDiscoverExpanderPhy, Failed to add a device\n"));
4003 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4004 }
4005 }
4006 }
4007 }
4008 } /* substractive routing */
4009 }
4010 }
4011
4012
4013 oneExpander->discoveringPhyId ++;
4014 if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
4015 {
4016 if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
4017 {
4018 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM find more ...\n"));
4019 /* continue discovery for the next phy */
4020 tdsaDiscoverSend(tiRoot, oneDeviceData);
4021 }
4022 else
4023 {
4024 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM last phy continue upstream..\n"));
4025
4026 /* remove the expander from the discovering list */
4027 tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, oneExpander);
4028 /* continue upstream discovering */
4029 tdsaSASUpStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
4030 }
4031 }
4032 else
4033 {
4034 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));
4035
4036 }
4037
4038 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
4039
4040 return;
4041 }
4042
4043 // for debugging only
4044 osGLOBAL tdsaExpander_t *
tdsaFindUpStreamConfigurableExp(tiRoot_t * tiRoot,tdsaExpander_t * oneExpander)4045 tdsaFindUpStreamConfigurableExp(tiRoot_t *tiRoot,
4046 tdsaExpander_t *oneExpander)
4047 {
4048 tdsaExpander_t *ret=agNULL;
4049 tdsaExpander_t *UpsreamExpander = oneExpander->tdUpStreamExpander;
4050
4051 TI_DBG3(("tdsaFindUpStreamConfigurableExp: start\n"));
4052 TI_DBG3(("tdsaFindUpStreamConfigurableExp: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4053 TI_DBG3(("tdsaFindUpStreamConfigurableExp: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4054
4055
4056 if (UpsreamExpander)
4057 {
4058 TI_DBG3(("tdsaFindUpStreamConfigurableExp: NO upsream expander\n"));
4059 }
4060 else
4061 {
4062 while (UpsreamExpander)
4063 {
4064 TI_DBG3(("tdsaFindUpStreamConfigurableExp: exp addrHi 0x%08x\n", UpsreamExpander->tdDevice->SASAddressID.sasAddressHi));
4065 TI_DBG3(("tdsaFindUpStreamConfigurableExp: exp addrLo 0x%08x\n", UpsreamExpander->tdDevice->SASAddressID.sasAddressLo));
4066
4067 UpsreamExpander = UpsreamExpander->tdUpStreamExpander;
4068 }
4069 }
4070 return ret;
4071 }
4072
4073 /*****************************************************************************
4074 *! \brief tdsaSASUpStreamDiscoverExpanderPhySkip
4075 *
4076 * Purpose: This function skips a phy which returned PHY_VACANT in SMP
4077 * response in upstream
4078 *
4079 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4080 * instance.
4081 * \param onePortContext: Pointer to the portal context instance.
4082 * \param oneExpander: Pointer to the expander data.
4083 *
4084 * \return:
4085 * None
4086 *
4087 * \note:
4088 *
4089 *****************************************************************************/
4090 osGLOBAL void
tdsaSASUpStreamDiscoverExpanderPhySkip(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaExpander_t * oneExpander)4091 tdsaSASUpStreamDiscoverExpanderPhySkip(
4092 tiRoot_t *tiRoot,
4093 tdsaPortContext_t *onePortContext,
4094 tdsaExpander_t *oneExpander
4095 )
4096 {
4097 tdsaDeviceData_t *oneDeviceData;
4098 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: start\n"));
4099 oneDeviceData = oneExpander->tdDevice;
4100
4101 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
4102 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
4103
4104 oneExpander->discoveringPhyId ++;
4105 if (onePortContext->discovery.status == DISCOVERY_UP_STREAM)
4106 {
4107 if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
4108 {
4109 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: More Phys to discover\n"));
4110 /* continue discovery for the next phy */
4111 tdsaDiscoverSend(tiRoot, oneDeviceData);
4112 }
4113 else
4114 {
4115 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: No More Phys\n"));
4116
4117 /* remove the expander from the discovering list */
4118 tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, oneExpander);
4119 /* continue upstream discovering */
4120 tdsaSASUpStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
4121 }
4122 }
4123 else
4124 {
4125 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status));
4126
4127 }
4128
4129 TI_DBG3(("tdsaSASUpStreamDiscoverExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
4130
4131
4132 return;
4133 }
4134
4135
4136 // for debugging only
4137 osGLOBAL tdsaExpander_t *
tdsaFindDownStreamConfigurableExp(tiRoot_t * tiRoot,tdsaExpander_t * oneExpander)4138 tdsaFindDownStreamConfigurableExp(tiRoot_t *tiRoot,
4139 tdsaExpander_t *oneExpander)
4140 {
4141 tdsaExpander_t *ret=agNULL;
4142 tdsaExpander_t *DownsreamExpander = oneExpander->tdCurrentDownStreamExpander;
4143
4144 TI_DBG3(("tdsaFindDownStreamConfigurableExp: start\n"));
4145 TI_DBG3(("tdsaFindDownStreamConfigurableExp: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4146 TI_DBG3(("tdsaFindDownStreamConfigurableExp: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4147
4148
4149 if (DownsreamExpander)
4150 {
4151 TI_DBG3(("tdsaFindDownStreamConfigurableExp: NO downsream expander\n"));
4152 }
4153 else
4154 {
4155 while (DownsreamExpander)
4156 {
4157 TI_DBG3(("tdsaFindDownStreamConfigurableExp: exp addrHi 0x%08x\n", DownsreamExpander->tdDevice->SASAddressID.sasAddressHi));
4158 TI_DBG3(("tdsaFindDownStreamConfigurableExp: exp addrLo 0x%08x\n", DownsreamExpander->tdDevice->SASAddressID.sasAddressLo));
4159
4160 DownsreamExpander = DownsreamExpander->tdCurrentDownStreamExpander;
4161 }
4162 }
4163 return ret;
4164 }
4165
4166 // for debugging only
4167 osGLOBAL void
dumpRoutingAttributes(tiRoot_t * tiRoot,tdsaExpander_t * oneExpander,bit8 phyID)4168 dumpRoutingAttributes(
4169 tiRoot_t *tiRoot,
4170 tdsaExpander_t *oneExpander,
4171 bit8 phyID
4172 )
4173 {
4174 bit32 i;
4175
4176 TI_DBG3(("dumpRoutingAttributes: start\n"));
4177 TI_DBG3(("dumpRoutingAttributes: phyID %d\n", phyID));
4178 TI_DBG3(("dumpRoutingAttributes: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4179 TI_DBG3(("dumpRoutingAttributes: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4180
4181 for(i=0;i <= ((bit32)phyID + 1); i++)
4182 {
4183 TI_DBG3(("dumpRoutingAttributes: index %d routing attribute %d\n", i, oneExpander->routingAttribute[i]));
4184 }
4185 return;
4186 }
4187
4188 /*****************************************************************************
4189 *! \brief tdsaDumpAllExp
4190 *
4191 * Purpose: This function prints out all expanders seen by discovery.
4192 *
4193 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4194 * instance.
4195 * \param onePortContext: Pointer to the portal context instance.
4196 * \param oneExpander: Pointer to the expander data.
4197 *
4198 * \return:
4199 * None
4200 *
4201 * \note: For debugging only
4202 *
4203 *****************************************************************************/
4204 osGLOBAL void
tdsaDumpAllExp(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaExpander_t * oneExpander)4205 tdsaDumpAllExp(
4206 tiRoot_t *tiRoot,
4207 tdsaPortContext_t *onePortContext,
4208 tdsaExpander_t *oneExpander
4209 )
4210 {
4211 #if 0 /* for debugging only */
4212 tdList_t *ExpanderList;
4213 tdsaExpander_t *tempExpander;
4214 tdsaExpander_t *UpsreamExpander;
4215 tdsaExpander_t *DownsreamExpander;
4216 tdsaPortContext_t *tmpOnePortContext = onePortContext;
4217
4218 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: start\n"));
4219 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: onePortcontext %p oneExpander %p\n", onePortContext, oneExpander));
4220
4221 /* debugging */
4222 tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
4223 if (TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
4224 {
4225 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
4226 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: empty discoveringExpanderList\n"));
4227 return;
4228 }
4229 else
4230 {
4231 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
4232 }
4233 ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink;
4234 while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList))
4235 {
4236 tempExpander = TDLIST_OBJECT_BASE(tdsaExpander_t, linkNode, ExpanderList);
4237 UpsreamExpander = tempExpander->tdUpStreamExpander;
4238 DownsreamExpander = tempExpander->tdCurrentDownStreamExpander;
4239 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: expander id %d\n", tempExpander->id));
4240 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: exp addrHi 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressHi));
4241 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: exp addrLo 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressLo));
4242 if (UpsreamExpander)
4243 {
4244 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: Up exp addrHi 0x%08x\n", UpsreamExpander->tdDevice->SASAddressID.sasAddressHi));
4245 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: Up exp addrLo 0x%08x\n", UpsreamExpander->tdDevice->SASAddressID.sasAddressLo));
4246 }
4247 else
4248 {
4249 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: No Upstream expander\n"));
4250 }
4251 if (DownsreamExpander)
4252 {
4253 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: Down exp addrHi 0x%08x\n", DownsreamExpander->tdDevice->SASAddressID.sasAddressHi));
4254 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: Down exp addrLo 0x%08x\n", DownsreamExpander->tdDevice->SASAddressID.sasAddressLo));
4255 }
4256 else
4257 {
4258 TI_DBG3(("tdssSASDiscoveringExpander tdsaDumpAllExp: No Downstream expander\n"));
4259 }
4260
4261 ExpanderList = ExpanderList->flink;
4262 }
4263 #endif
4264 return;
4265
4266 }
4267
4268 /*****************************************************************************
4269 *! \brief tdsaDumpAllUpExp
4270 *
4271 * Purpose: This function prints out all upstream expanders seen by discovery.
4272 *
4273 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4274 * instance.
4275 * \param onePortContext: Pointer to the portal context instance.
4276 * \param oneExpander: Pointer to the expander data.
4277 *
4278 * \return:
4279 * None
4280 *
4281 * \note: For debugging only
4282 *
4283 *****************************************************************************/
4284 osGLOBAL void
tdsaDumpAllUpExp(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaExpander_t * oneExpander)4285 tdsaDumpAllUpExp(
4286 tiRoot_t *tiRoot,
4287 tdsaPortContext_t *onePortContext,
4288 tdsaExpander_t *oneExpander
4289 )
4290 {
4291 return;
4292
4293 }
4294
4295 /*****************************************************************************
4296 *! \brief tdsaDumpAllFreeExp
4297 *
4298 * Purpose: This function prints out all free expanders.
4299 *
4300 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4301 * instance.
4302 * \return:
4303 * None
4304 *
4305 * \note: For debugging only
4306 *
4307 *****************************************************************************/
4308 osGLOBAL void
tdsaDumpAllFreeExp(tiRoot_t * tiRoot)4309 tdsaDumpAllFreeExp(
4310 tiRoot_t *tiRoot
4311 )
4312 {
4313
4314 return;
4315 }
4316
4317 /*****************************************************************************
4318 *! \brief tdsaDuplicateConfigSASAddr
4319 *
4320 * Purpose: This function finds whether SAS address has added to the routing
4321 * table of expander or not.
4322 *
4323 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4324 * instance.
4325 * \param oneExpander: Pointer to the expander data.
4326 * \param configSASAddressHi: Upper 4 byte of SAS address.
4327 * \param configSASAddressLo: Lower 4 byte of SAS address.
4328 *
4329 * \return:
4330 * agTRUE No need to add configSASAddress.
4331 * agFALSE Need to add configSASAddress.
4332 *
4333 * \note:
4334 *
4335 *****************************************************************************/
4336 osGLOBAL bit32
tdsaDuplicateConfigSASAddr(tiRoot_t * tiRoot,tdsaExpander_t * oneExpander,bit32 configSASAddressHi,bit32 configSASAddressLo)4337 tdsaDuplicateConfigSASAddr(
4338 tiRoot_t *tiRoot,
4339 tdsaExpander_t *oneExpander,
4340 bit32 configSASAddressHi,
4341 bit32 configSASAddressLo
4342 )
4343 {
4344 bit32 i;
4345 bit32 ret = agFALSE;
4346 TI_DBG3(("tdsaDuplicateConfigSASAddr: start\n"));
4347
4348 if (oneExpander == agNULL)
4349 {
4350 TI_DBG3(("tdsaDuplicateConfigSASAddr: NULL expander\n"));
4351 return agTRUE;
4352 }
4353
4354 if (oneExpander->tdDevice->SASAddressID.sasAddressHi == configSASAddressHi &&
4355 oneExpander->tdDevice->SASAddressID.sasAddressLo == configSASAddressLo
4356 )
4357 {
4358 TI_DBG3(("tdsaDuplicateConfigSASAddr: unnecessary\n"));
4359 return agTRUE;
4360 }
4361
4362 TI_DBG3(("tdsaDuplicateConfigSASAddr: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4363 TI_DBG3(("tdsaDuplicateConfigSASAddr: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4364 TI_DBG3(("tdsaDuplicateConfigSASAddr: configsasAddressHi 0x%08x\n", configSASAddressHi));
4365 TI_DBG3(("tdsaDuplicateConfigSASAddr: configsasAddressLo 0x%08x\n", configSASAddressLo));
4366 TI_DBG3(("tdsaDuplicateConfigSASAddr: configSASAddrTableIndex %d\n", oneExpander->configSASAddrTableIndex));
4367 for(i=0;i<oneExpander->configSASAddrTableIndex;i++)
4368 {
4369 if (oneExpander->configSASAddressHiTable[i] == configSASAddressHi &&
4370 oneExpander->configSASAddressLoTable[i] == configSASAddressLo
4371 )
4372 {
4373 TI_DBG3(("tdsaDuplicateConfigSASAddr: FOUND!!!\n"));
4374 ret = agTRUE;
4375 break;
4376 }
4377 }
4378 /* new one; let's add it */
4379 if (ret == agFALSE)
4380 {
4381 TI_DBG3(("tdsaDuplicateConfigSASAddr: adding configSAS Addr!!!\n"));
4382 TI_DBG3(("tdsaDuplicateConfigSASAddr: configSASAddrTableIndex %d\n", oneExpander->configSASAddrTableIndex));
4383 oneExpander->configSASAddressHiTable[oneExpander->configSASAddrTableIndex] = configSASAddressHi;
4384 oneExpander->configSASAddressLoTable[oneExpander->configSASAddrTableIndex] = configSASAddressLo;
4385 oneExpander->configSASAddrTableIndex++;
4386 }
4387
4388 return ret;
4389 }
4390 /*****************************************************************************
4391 *! \brief tdsaFindConfigurableExp
4392 *
4393 * Purpose: This function finds whether there is a configurable expander in
4394 * the upstream expander list.
4395 *
4396 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4397 * instance.
4398 * \param onePortContext: Pointer to the portal context instance.
4399 * \param oneExpander: Pointer to the expander data.
4400 *
4401 * \return:
4402 * agTRUE There is configurable expander.
4403 * agFALSE There is not configurable expander.
4404 *
4405 * \note:
4406 *
4407 *****************************************************************************/
4408 osGLOBAL tdsaExpander_t *
tdsaFindConfigurableExp(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaExpander_t * oneExpander)4409 tdsaFindConfigurableExp(
4410 tiRoot_t *tiRoot,
4411 tdsaPortContext_t *onePortContext,
4412 tdsaExpander_t *oneExpander
4413 )
4414 {
4415 tdsaExpander_t *tempExpander;
4416 tdsaPortContext_t *tmpOnePortContext = onePortContext;
4417 tdsaExpander_t *ret = agNULL;
4418
4419 TI_DBG3(("tdsaFindConfigurableExp: start\n"));
4420
4421 if (oneExpander == agNULL)
4422 {
4423 TI_DBG3(("tdsaFindConfigurableExp: NULL expander\n"));
4424 return agNULL;
4425 }
4426
4427 TI_DBG3(("tdsaFindConfigurableExp: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4428 TI_DBG3(("tdsaFindConfigurableExp: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4429
4430 tdsaSingleThreadedEnter(tiRoot, TD_DISC_LOCK);
4431 if (TDLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList)))
4432 {
4433 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
4434 TI_DBG3(("tdsaFindConfigurableExp: empty UpdiscoveringExpanderList\n"));
4435 return agNULL;
4436 }
4437 else
4438 {
4439 tdsaSingleThreadedLeave(tiRoot, TD_DISC_LOCK);
4440 }
4441 tempExpander = oneExpander->tdUpStreamExpander;
4442 while (tempExpander)
4443 {
4444 TI_DBG3(("tdsaFindConfigurableExp: loop exp addrHi 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressHi));
4445 TI_DBG3(("tdsaFindConfigurableExp: loop exp addrLo 0x%08x\n", tempExpander->tdDevice->SASAddressID.sasAddressLo));
4446 if (tempExpander->configRouteTable)
4447 {
4448 TI_DBG3(("tdsaFindConfigurableExp: found configurable expander\n"));
4449 ret = tempExpander;
4450 break;
4451 }
4452 tempExpander = tempExpander->tdUpStreamExpander;
4453 }
4454
4455 return ret;
4456 }
4457
4458 /*****************************************************************************
4459 *! \brief tdsaSASDownStreamDiscoverExpanderPhy
4460 *
4461 * Purpose: This function actully does downstream traverse and finds out detailed
4462 * information about topology.
4463 *
4464 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
4465 * instance.
4466 * \param onePortContext: Pointer to the portal context instance.
4467 * \param oneExpander: Pointer to the expander data.
4468 * \param pDiscoverResp: Pointer to the Discovery SMP respsonse.
4469 *
4470 * \return:
4471 * None
4472 *
4473 * \note:
4474 *
4475 *****************************************************************************/
4476 osGLOBAL void
tdsaSASDownStreamDiscoverExpanderPhy(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaExpander_t * oneExpander,smpRespDiscover_t * pDiscoverResp)4477 tdsaSASDownStreamDiscoverExpanderPhy(
4478 tiRoot_t *tiRoot,
4479 tdsaPortContext_t *onePortContext,
4480 tdsaExpander_t *oneExpander,
4481 smpRespDiscover_t *pDiscoverResp
4482 )
4483 {
4484 tdsaDeviceData_t *oneDeviceData;
4485 tdsaExpander_t *UpStreamExpander;
4486 tdsaDeviceData_t *AttachedDevice = agNULL;
4487 tdsaExpander_t *AttachedExpander;
4488 agsaSASIdentify_t sasIdentify;
4489 bit8 connectionRate;
4490 bit32 attachedSasHi, attachedSasLo;
4491 tdsaSASSubID_t agSASSubID;
4492 tdsaExpander_t *ConfigurableExpander = agNULL;
4493 bit32 dupConfigSASAddr = agFALSE;
4494 bit32 configSASAddressHi;
4495 bit32 configSASAddressLo;
4496
4497 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: start\n"));
4498 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
4499 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
4500
4501 TD_ASSERT(tiRoot, "(tdsaSASDownStreamDiscoverExpanderPhy) agRoot NULL");
4502 TD_ASSERT(onePortContext, "(tdsaSASDownStreamDiscoverExpanderPhy) pPort NULL");
4503 TD_ASSERT(oneExpander, "(tdsaSASDownStreamDiscoverExpanderPhy) pExpander NULL");
4504 TD_ASSERT(pDiscoverResp, "(tdsaSASDownStreamDiscoverExpanderPhy) pDiscoverResp NULL");
4505
4506 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: onePortContxt=%p oneExpander=%p oneDeviceData=%p\n", onePortContext, oneExpander, oneExpander->tdDevice));
4507
4508 if (onePortContext->valid == agFALSE)
4509 {
4510 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: aborting discovery\n"));
4511 tdsaSASDiscoverAbort(tiRoot, onePortContext);
4512 return;
4513 }
4514 #ifdef TD_INTERNAL_DEBUG
4515 tdsaDumpAllExp(tiRoot, onePortContext, oneExpander);
4516 tdsaFindUpStreamConfigurableExp(tiRoot, oneExpander);
4517 tdsaFindDownStreamConfigurableExp(tiRoot, oneExpander);
4518 #endif
4519 /* (1) Find the device structure of the expander */
4520 oneDeviceData = oneExpander->tdDevice;
4521 TD_ASSERT(oneDeviceData, "(tdsaSASDownStreamDiscoverExpanderPhy) pDevice NULL");
4522
4523 /* for debugging */
4524 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n",
4525 oneExpander->discoveringPhyId,
4526 oneDeviceData->SASAddressID.sasAddressHi,
4527 oneDeviceData->SASAddressID.sasAddressLo));
4528 TI_DBG3((" Attached device: %s\n",
4529 ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" :
4530 (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" :
4531 (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander")))));
4532 /* for debugging */
4533 if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier)
4534 {
4535 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n"));
4536 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier));
4537 tdhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
4538 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4539 return;
4540 }
4541
4542 #ifdef TD_INTERNAL_DEBUG /* debugging only */
4543 if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_NO_DEVICE)
4544 {
4545 tdhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t));
4546 }
4547 #endif
4548 if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
4549 {
4550 TI_DBG3((" SAS address : %08x-%08x\n",
4551 DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp),
4552 DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp)));
4553 TI_DBG3((" SSP Target : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0));
4554 TI_DBG3((" STP Target : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0));
4555 TI_DBG3((" SMP Target : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0));
4556 TI_DBG3((" SATA DEVICE : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0));
4557 TI_DBG3((" SSP Initiator : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0));
4558 TI_DBG3((" STP Initiator : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0));
4559 TI_DBG3((" SMP Initiator : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0));
4560 TI_DBG3((" Phy ID : %d\n", pDiscoverResp->phyIdentifier));
4561 TI_DBG3((" Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier));
4562
4563 }
4564 /* end for debugging */
4565
4566 /* saving routing attribute for non self-configuring expanders */
4567 oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp);
4568
4569 /* for debugging */
4570 // dumpRoutingAttributes(tiRoot, oneExpander, pDiscoverResp->phyIdentifier);
4571
4572 oneExpander->discoverSMPAllowed = agTRUE;
4573
4574 /* If a device is attached */
4575 if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE)
4576 {
4577 /* Setup sasIdentify for the attached device */
4578 sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier;
4579 sasIdentify.deviceType_addressFrameType = (bit8)(pDiscoverResp->attachedDeviceType & 0x70);
4580 sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator;
4581 sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target;
4582 *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi;
4583 *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo;
4584
4585 /* incremental discovery */
4586 agSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
4587 agSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
4588 agSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
4589 agSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
4590
4591 attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp);
4592 attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp);
4593
4594 /* If it's a direct routing */
4595 if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_DIRECT)
4596 {
4597 /* If the attached device is an expander */
4598 if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
4599 || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) )
4600
4601 {
4602 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error direct routing can't connect to expander\n"));
4603 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4604 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4605 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4606 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4607 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4608
4609 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4610
4611 return;
4612 }
4613 }
4614
4615 /* If the expander's attached device is not myself */
4616 if ( (attachedSasHi != onePortContext->sasLocalAddressHi)
4617 || (attachedSasLo != onePortContext->sasLocalAddressLo) )
4618 {
4619 /* Find the attached device from discovered list */
4620 AttachedDevice = tdsaPortSASDeviceFind(tiRoot, onePortContext, attachedSasLo, attachedSasHi);
4621 /* If the device has not been discovered before */
4622 if ( AttachedDevice == agNULL) //11
4623 {
4624 /* If the phy has subtractive routing attribute */
4625 if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE &&
4626 (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE ||
4627 DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
4628 )
4629 {
4630 /* TODO: discovery error, callback */
4631 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address\n"));
4632 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4633 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4634 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4635 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4636 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4637 /* discovery done */
4638 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4639 }
4640 else
4641 {
4642 /* Add the device */
4643 /* read minimum rate from the configuration
4644 onePortContext->LinkRate is SPC's local link rate
4645 */
4646 connectionRate = (bit8)(MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)));
4647 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: link rate 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo)));
4648 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp)));
4649 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate));
4650
4651 if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
4652 {
4653 if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
4654 {
4655 AttachedDevice = tdsaPortSASDeviceAdd(
4656 tiRoot,
4657 onePortContext,
4658 sasIdentify,
4659 agFALSE,
4660 connectionRate,
4661 IT_NEXUS_TIMEOUT,
4662 0,
4663 STP_DEVICE_TYPE,
4664 oneDeviceData,
4665 pDiscoverResp->phyIdentifier
4666 );
4667 }
4668 else
4669 {
4670 /* incremental discovery */
4671 AttachedDevice = tdsaFindRegNValid(
4672 onePortContext->agRoot,
4673 onePortContext,
4674 &agSASSubID
4675 );
4676 /* not registered and not valid; add this*/
4677 if (AttachedDevice == agNULL)
4678 {
4679 AttachedDevice = tdsaPortSASDeviceAdd(
4680 tiRoot,
4681 onePortContext,
4682 sasIdentify,
4683 agFALSE,
4684 connectionRate,
4685 IT_NEXUS_TIMEOUT,
4686 0,
4687 STP_DEVICE_TYPE,
4688 oneDeviceData,
4689 pDiscoverResp->phyIdentifier
4690 );
4691 }
4692 }
4693 }
4694 else
4695 {
4696 if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
4697 {
4698 AttachedDevice = tdsaPortSASDeviceAdd(
4699 tiRoot,
4700 onePortContext,
4701 sasIdentify,
4702 agFALSE,
4703 connectionRate,
4704 IT_NEXUS_TIMEOUT,
4705 0,
4706 SAS_DEVICE_TYPE,
4707 oneDeviceData,
4708 pDiscoverResp->phyIdentifier
4709 );
4710 }
4711 else
4712 {
4713 /* incremental discovery */
4714 AttachedDevice = tdsaFindRegNValid(
4715 onePortContext->agRoot,
4716 onePortContext,
4717 &agSASSubID
4718 );
4719 /* not registered and not valid; add this*/
4720 if (AttachedDevice == agNULL)
4721 {
4722 AttachedDevice = tdsaPortSASDeviceAdd(
4723 tiRoot,
4724 onePortContext,
4725 sasIdentify,
4726 agFALSE,
4727 connectionRate,
4728 IT_NEXUS_TIMEOUT,
4729 0,
4730 SAS_DEVICE_TYPE,
4731 oneDeviceData,
4732 pDiscoverResp->phyIdentifier
4733 );
4734 }
4735 }
4736 }
4737 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: newDevice pDevice=%p\n", AttachedDevice));
4738 /* If the device is added successfully */
4739 if ( AttachedDevice != agNULL)
4740 {
4741 if ( SA_IDFRM_IS_SSP_TARGET(&sasIdentify)
4742 || SA_IDFRM_IS_SMP_TARGET(&sasIdentify)
4743 || SA_IDFRM_IS_SSP_INITIATOR(&sasIdentify)
4744 || SA_IDFRM_IS_SMP_INITIATOR(&sasIdentify) )
4745 {
4746 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Report a new SAS device !!\n"));
4747
4748 }
4749 else
4750 {
4751 if ( SA_IDFRM_IS_STP_TARGET(&sasIdentify) ||
4752 SA_IDFRM_IS_SATA_DEVICE(&sasIdentify) )
4753 {
4754
4755 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Found an STP or SATA device.\n"));
4756 }
4757 else
4758 {
4759 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Found Other type of device.\n"));
4760 }
4761 }
4762
4763 /* LP2006-05-26 added upstream device to the newly found device */
4764 AttachedDevice->tdExpander = oneExpander;
4765
4766 /* If the phy has table routing attribute */
4767 if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
4768 {
4769 /* If the attached device is a fan out expander */
4770 if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
4771 {
4772 /* TODO: discovery error, callback */
4773 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys are connected\n"));
4774 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4775 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4776 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4777 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4778 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4779 /* discovery done */
4780 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4781 }
4782 else if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
4783 {
4784 /* Allocate an expander data structure */
4785 AttachedExpander = tdssSASDiscoveringExpanderAlloc(tiRoot, onePortContext, AttachedDevice);
4786
4787 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Found a EDGE exp device.%p\n", AttachedExpander));
4788 /* If allocate successfully */
4789 if ( AttachedExpander != agNULL)
4790 {
4791 /* set up downstream information on configurable expander */
4792 if (oneExpander->configRouteTable)
4793 {
4794 tdsaSASExpanderDownStreamPhyAdd(tiRoot, oneExpander, (bit8) oneExpander->discoveringPhyId);
4795 }
4796 /* Setup upstream information */
4797 tdsaSASExpanderUpStreamPhyAdd(tiRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
4798 AttachedExpander->hasUpStreamDevice = agTRUE;
4799 AttachedExpander->upStreamSASAddressHi
4800 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4801 AttachedExpander->upStreamSASAddressLo
4802 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4803 AttachedExpander->tdUpStreamExpander = oneExpander;
4804 /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */
4805 tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, AttachedExpander);
4806 }
4807 /* If failed to allocate */
4808 else
4809 {
4810 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy, Failed to allocate expander data structure\n"));
4811 /* discovery done */
4812 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4813 }
4814 }
4815 }
4816 /* If status is still DISCOVERY_DOWN_STREAM */
4817 if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
4818 {
4819 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 1st before\n"));
4820 tdsaDumpAllUpExp(tiRoot, onePortContext, oneExpander);
4821 UpStreamExpander = oneExpander->tdUpStreamExpander;
4822 ConfigurableExpander = tdsaFindConfigurableExp(tiRoot, onePortContext, oneExpander);
4823 configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
4824 configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
4825 if (ConfigurableExpander)
4826 {
4827 if ( (ConfigurableExpander->tdDevice->SASAddressID.sasAddressHi
4828 == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
4829 (ConfigurableExpander->tdDevice->SASAddressID.sasAddressLo
4830 == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
4831 )
4832 { /* directly attached between oneExpander and ConfigurableExpander */
4833 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 1st before loc 1\n"));
4834 configSASAddressHi = oneExpander->tdDevice->SASAddressID.sasAddressHi;
4835 configSASAddressLo = oneExpander->tdDevice->SASAddressID.sasAddressLo;
4836 }
4837 else
4838 {
4839 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 1st before loc 2\n"));
4840 configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
4841 configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
4842 }
4843 } /* if !ConfigurableExpander */
4844 dupConfigSASAddr = tdsaDuplicateConfigSASAddr(tiRoot,
4845 ConfigurableExpander,
4846 configSASAddressHi,
4847 configSASAddressLo
4848 );
4849
4850
4851 if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
4852 {
4853 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 1st q123\n"));
4854 UpStreamExpander->tdCurrentDownStreamExpander = oneExpander;
4855 ConfigurableExpander->currentDownStreamPhyIndex =
4856 tdsaFindCurrentDownStreamPhyIndex(tiRoot, ConfigurableExpander);
4857 ConfigurableExpander->tdReturnginExpander = oneExpander;
4858 tdsaSASRoutingEntryAdd(tiRoot,
4859 ConfigurableExpander,
4860 ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
4861 configSASAddressHi,
4862 configSASAddressLo
4863 );
4864 }
4865 }
4866 }
4867 /* If fail to add the device */
4868 else
4869 {
4870 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy, Failed to add a device\n"));
4871 /* discovery done */
4872 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4873 }
4874 }
4875 }
4876 /* If the device has been discovered before */
4877 else /* haha discovered before */
4878 {
4879 /* If the phy has subtractive routing attribute */
4880 if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE)
4881 {
4882 /* If the expander doesn't have up stream device */
4883 if ( oneExpander->hasUpStreamDevice == agFALSE)
4884 {
4885 /* TODO: discovery error, callback */
4886 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error loop, or end device connects to two expanders\n"));
4887 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4888 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4889 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4890 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4891 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4892 /* discovery done */
4893 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4894 }
4895 /* If the expander has up stream device */
4896 else
4897 {
4898 /* If sas address doesn't match */
4899 if ( (oneExpander->upStreamSASAddressHi != attachedSasHi)
4900 || (oneExpander->upStreamSASAddressLo != attachedSasLo) )
4901 {
4902 /* TODO: discovery error, callback */
4903 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error two subtractive phys\n"));
4904 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4905 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4906 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4907 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4908 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4909 /* discovery done */
4910 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4911 }
4912 }
4913 }
4914 /* If the phy has table routing attribute */
4915 else if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE)
4916 {
4917 /* If the attached device is a fan out expander */
4918 if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE)
4919 {
4920 /* (2.3.3.2.1.1) TODO: discovery error, callback */
4921 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error fan out expander to routing table phy\n"));
4922 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4923 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4924 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4925 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4926 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4927 /* discovery done */
4928 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4929 }
4930 /* If the attached device is an edge expander */
4931 else if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE)
4932 {
4933 /* Setup up stream inform */
4934 AttachedExpander = AttachedDevice->tdExpander;
4935 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Found edge expander=%p\n", AttachedExpander));
4936 //hhhhhh
4937 /* If the attached expander has up stream device */
4938 if ( AttachedExpander->hasUpStreamDevice == agTRUE)
4939 {
4940 /* compare the sas address */
4941 if ( (AttachedExpander->upStreamSASAddressHi
4942 != DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo))
4943 || (AttachedExpander->upStreamSASAddressLo
4944 != DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)))
4945 {
4946 /* TODO: discovery error, callback */
4947 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys connected (1)\n"));
4948 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4949 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4950 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4951 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4952 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4953 /* discovery done */
4954 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4955 }
4956 else
4957 {
4958 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Add edge expander=%p\n", AttachedExpander));
4959 /* set up downstream information on configurable expander */
4960 if (oneExpander->configRouteTable)
4961 {
4962 tdsaSASExpanderDownStreamPhyAdd(tiRoot, oneExpander, (bit8) oneExpander->discoveringPhyId);
4963 }
4964 /* haha */
4965 tdsaSASExpanderUpStreamPhyAdd(tiRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId);
4966 /* Add the pAttachedExpander to discovering list */
4967 tdssSASDiscoveringExpanderAdd(tiRoot, onePortContext, AttachedExpander);
4968 }
4969 }
4970 /* If the attached expander doesn't have up stream device */
4971 else
4972 {
4973 /* TODO: discovery error, callback */
4974 TI_DBG1(("tdsaSASDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys connected (2)\n"));
4975 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo
4976 = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo);
4977 onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi
4978 = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo);
4979 onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId;
4980 /* discovery done */
4981 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
4982 }
4983 }
4984 } /* for else if (DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE) */
4985
4986 /* do this regradless of sub or table */
4987 /* If status is still DISCOVERY_DOWN_STREAM */
4988 if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
4989 {
4990 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 2nd before\n"));
4991 tdsaDumpAllUpExp(tiRoot, onePortContext, oneExpander);
4992
4993 UpStreamExpander = oneExpander->tdUpStreamExpander;
4994 ConfigurableExpander = tdsaFindConfigurableExp(tiRoot, onePortContext, oneExpander);
4995 configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
4996 configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
4997 if (ConfigurableExpander)
4998 {
4999 if ( (ConfigurableExpander->tdDevice->SASAddressID.sasAddressHi
5000 == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) &&
5001 (ConfigurableExpander->tdDevice->SASAddressID.sasAddressLo
5002 == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo))
5003 )
5004 { /* directly attached between oneExpander and ConfigurableExpander */
5005 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 2nd before loc 1\n"));
5006 configSASAddressHi = oneExpander->tdDevice->SASAddressID.sasAddressHi;
5007 configSASAddressLo = oneExpander->tdDevice->SASAddressID.sasAddressLo;
5008 }
5009 else
5010 {
5011 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 2nd before loc 2\n"));
5012 configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo);
5013 configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo);
5014 }
5015 } /* if !ConfigurableExpander */
5016 dupConfigSASAddr = tdsaDuplicateConfigSASAddr(tiRoot,
5017 ConfigurableExpander,
5018 configSASAddressHi,
5019 configSASAddressLo
5020 );
5021
5022 if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
5023 {
5024 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 2nd q123 \n"));
5025 UpStreamExpander->tdCurrentDownStreamExpander = oneExpander;
5026 ConfigurableExpander->currentDownStreamPhyIndex =
5027 tdsaFindCurrentDownStreamPhyIndex(tiRoot, ConfigurableExpander);
5028 ConfigurableExpander->tdReturnginExpander = oneExpander;
5029 tdsaSASRoutingEntryAdd(tiRoot,
5030 ConfigurableExpander,
5031 ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
5032 configSASAddressHi,
5033 configSASAddressLo
5034 );
5035 }
5036 } /* if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) */
5037 /* incremental discovery */
5038 if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_INCREMENTAL_START)
5039 {
5040 connectionRate = (bit8)(MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)));
5041
5042 if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp))
5043 {
5044 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: incremental SATA_STP\n"));
5045
5046 tdsaPortSASDeviceAdd(
5047 tiRoot,
5048 onePortContext,
5049 sasIdentify,
5050 agFALSE,
5051 connectionRate,
5052 IT_NEXUS_TIMEOUT,
5053 0,
5054 STP_DEVICE_TYPE,
5055 oneDeviceData,
5056 pDiscoverResp->phyIdentifier
5057 );
5058 }
5059 else
5060 {
5061 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: incremental SAS\n"));
5062
5063 tdsaPortSASDeviceAdd(
5064 tiRoot,
5065 onePortContext,
5066 sasIdentify,
5067 agFALSE,
5068 connectionRate,
5069 IT_NEXUS_TIMEOUT,
5070 0,
5071 SAS_DEVICE_TYPE,
5072 oneDeviceData,
5073 pDiscoverResp->phyIdentifier
5074 );
5075
5076 }
5077 }
5078
5079
5080 }/* else; existing devce */
5081 } /* not attached to myself */
5082 /* If the attached device is myself */
5083 else
5084 {
5085 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: Found Self\n"));
5086 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 3rd before\n"));
5087 tdsaDumpAllUpExp(tiRoot, onePortContext, oneExpander);
5088
5089 UpStreamExpander = oneExpander->tdUpStreamExpander;
5090 ConfigurableExpander = tdsaFindConfigurableExp(tiRoot, onePortContext, oneExpander);
5091 dupConfigSASAddr = tdsaDuplicateConfigSASAddr(tiRoot,
5092 ConfigurableExpander,
5093 onePortContext->sasLocalAddressHi,
5094 onePortContext->sasLocalAddressLo
5095 );
5096
5097 if ( ConfigurableExpander && dupConfigSASAddr == agFALSE)
5098 {
5099 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: 3rd q123 Setup routing table\n"));
5100 UpStreamExpander->tdCurrentDownStreamExpander = oneExpander;
5101 ConfigurableExpander->currentDownStreamPhyIndex =
5102 tdsaFindCurrentDownStreamPhyIndex(tiRoot, ConfigurableExpander);
5103 ConfigurableExpander->tdReturnginExpander = oneExpander;
5104 tdsaSASRoutingEntryAdd(tiRoot,
5105 ConfigurableExpander,
5106 ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
5107 onePortContext->sasLocalAddressHi,
5108 onePortContext->sasLocalAddressLo
5109 );
5110 }
5111 }
5112 }
5113 /* If no device is attached */
5114 else
5115 {
5116 }
5117
5118
5119 /* Increment the discovering phy id */
5120 oneExpander->discoveringPhyId ++;
5121
5122 /* If the discovery status is DISCOVERY_DOWN_STREAM */
5123 if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
5124 {
5125 /* If not the last phy */
5126 if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
5127 {
5128 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: More Phys to discover\n"));
5129 /* continue discovery for the next phy */
5130 tdsaDiscoverSend(tiRoot, oneDeviceData);
5131 }
5132 /* If the last phy */
5133 else
5134 {
5135 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: No More Phys\n"));
5136
5137 /* remove the expander from the discovering list */
5138 tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, oneExpander);
5139 /* continue downstream discovering */
5140 tdsaSASDownStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
5141 }
5142 }
5143 else
5144 {
5145 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));
5146 }
5147 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
5148
5149 return;
5150 }
5151
5152 /*****************************************************************************
5153 *! \brief tdsaSASDownStreamDiscoverExpanderPhySkip
5154 *
5155 * Purpose: This function skips a phy which returned PHY_VACANT in SMP
5156 * response in downstream
5157 *
5158 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5159 * instance.
5160 * \param onePortContext: Pointer to the portal context instance.
5161 * \param oneExpander: Pointer to the expander data.
5162 *
5163 * \return:
5164 * None
5165 *
5166 * \note:
5167 *
5168 *****************************************************************************/
5169 osGLOBAL void
tdsaSASDownStreamDiscoverExpanderPhySkip(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaExpander_t * oneExpander)5170 tdsaSASDownStreamDiscoverExpanderPhySkip(
5171 tiRoot_t *tiRoot,
5172 tdsaPortContext_t *onePortContext,
5173 tdsaExpander_t *oneExpander
5174 )
5175 {
5176 tdsaDeviceData_t *oneDeviceData;
5177 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: start\n"));
5178 oneDeviceData = oneExpander->tdDevice;
5179
5180 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
5181 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
5182
5183 /* Increment the discovering phy id */
5184 oneExpander->discoveringPhyId ++;
5185
5186 /* If the discovery status is DISCOVERY_DOWN_STREAM */
5187 if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM )
5188 {
5189 /* If not the last phy */
5190 if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys )
5191 {
5192 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: More Phys to discover\n"));
5193 /* continue discovery for the next phy */
5194 tdsaDiscoverSend(tiRoot, oneDeviceData);
5195 }
5196 /* If the last phy */
5197 else
5198 {
5199 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: No More Phys\n"));
5200
5201 /* remove the expander from the discovering list */
5202 tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, oneExpander);
5203 /* continue downstream discovering */
5204 tdsaSASDownStreamDiscovering(tiRoot, onePortContext, oneDeviceData);
5205 }
5206 }
5207 else
5208 {
5209 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status));
5210 }
5211 TI_DBG3(("tdsaSASDownStreamDiscoverExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1));
5212
5213 return;
5214 }
5215
5216 /*****************************************************************************
5217 *! \brief tdsaSASRoutingEntryAdd
5218 *
5219 * Purpose: This function adds a routing entry in the configurable expander.
5220 *
5221 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5222 * instance.
5223 * \param oneExpander: Pointer to the expander data.
5224 * \param phyId: Phy identifier.
5225 * \param configSASAddressHi: Upper 4 byte of SAS address.
5226 * \param configSASAddressLo: Lower 4 byte of SAS address.
5227 *
5228 * \return:
5229 * agTRUE Routing entry is added successfully
5230 * agFALSE Routing entry is not added successfully
5231 *
5232 * \note:
5233 *
5234 *****************************************************************************/
5235 osGLOBAL bit32
tdsaSASRoutingEntryAdd(tiRoot_t * tiRoot,tdsaExpander_t * oneExpander,bit32 phyId,bit32 configSASAddressHi,bit32 configSASAddressLo)5236 tdsaSASRoutingEntryAdd(
5237 tiRoot_t *tiRoot,
5238 tdsaExpander_t *oneExpander,
5239 bit32 phyId,
5240 bit32 configSASAddressHi,
5241 bit32 configSASAddressLo
5242 )
5243 {
5244 bit32 ret = agTRUE;
5245 smpReqConfigureRouteInformation_t confRoutingInfo;
5246 tdsaPortContext_t *onePortContext;
5247 bit32 i;
5248 agsaRoot_t *agRoot;
5249
5250 TI_DBG3(("tdsaSASRoutingEntryAdd: start\n"));
5251 TI_DBG3(("tdsaSASRoutingEntryAdd: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
5252 TI_DBG3(("tdsaSASRoutingEntryAdd: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
5253 TI_DBG3(("tdsaSASRoutingEntryAdd: phyid %d\n", phyId));
5254
5255 /* needs to compare the location of oneExpander and configSASAddress
5256 add only if
5257 oneExpander
5258 |
5259 configSASaddress
5260
5261 */
5262 if (oneExpander->tdDevice->SASAddressID.sasAddressHi == configSASAddressHi &&
5263 oneExpander->tdDevice->SASAddressID.sasAddressLo == configSASAddressLo
5264 )
5265 {
5266 TI_DBG3(("tdsaSASRoutingEntryAdd: unnecessary\n"));
5267 return ret;
5268 }
5269 if (oneExpander->routingAttribute[phyId] != SAS_ROUTING_TABLE)
5270 {
5271 TI_DBG3(("tdsaSASRoutingEntryAdd: not table routing, routing is %d\n", oneExpander->routingAttribute[phyId]));
5272 return ret;
5273 }
5274
5275 agRoot = oneExpander->tdDevice->agRoot;
5276 onePortContext = oneExpander->tdDevice->tdPortContext;
5277
5278 onePortContext->discovery.status = DISCOVERY_CONFIG_ROUTING;
5279
5280 /* reset smpReqConfigureRouteInformation_t */
5281 osti_memset(&confRoutingInfo, 0, sizeof(smpReqConfigureRouteInformation_t));
5282 if ( oneExpander->currentIndex[phyId] < oneExpander->routingIndex )
5283 {
5284 TI_DBG3(("tdsaSASRoutingEntryAdd: adding sasAddressHi 0x%08x\n", configSASAddressHi));
5285 TI_DBG3(("tdsaSASRoutingEntryAdd: adding sasAddressLo 0x%08x\n", configSASAddressLo));
5286 TI_DBG3(("tdsaSASRoutingEntryAdd: phyid %d currentIndex[phyid] %d\n", phyId, oneExpander->currentIndex[phyId]));
5287
5288 oneExpander->configSASAddressHi = configSASAddressHi;
5289 oneExpander->configSASAddressLo = configSASAddressLo;
5290 confRoutingInfo.reserved1[0] = 0;
5291 confRoutingInfo.reserved1[1] = 0;
5292 OSSA_WRITE_BE_16(agRoot, confRoutingInfo.expanderRouteIndex, 0, (oneExpander->currentIndex[phyId]));
5293 confRoutingInfo.reserved2 = 0;
5294 confRoutingInfo.phyIdentifier = (bit8)phyId;
5295 confRoutingInfo.reserved3[0] = 0;
5296 confRoutingInfo.reserved3[1] = 0;
5297 confRoutingInfo.disabledBit_reserved4 = 0;
5298 confRoutingInfo.reserved5[0] = 0;
5299 confRoutingInfo.reserved5[1] = 0;
5300 confRoutingInfo.reserved5[2] = 0;
5301 OSSA_WRITE_BE_32(agRoot, confRoutingInfo.routedSasAddressHi, 0, configSASAddressHi);
5302 OSSA_WRITE_BE_32(agRoot, confRoutingInfo.routedSasAddressLo, 0, configSASAddressLo);
5303 for ( i = 0; i < 16; i ++ )
5304 {
5305 confRoutingInfo.reserved6[i] = 0;
5306 }
5307 tdSMPStart(tiRoot, agRoot, oneExpander->tdDevice, SMP_CONFIGURE_ROUTING_INFORMATION, (bit8 *)&confRoutingInfo, sizeof(smpReqConfigureRouteInformation_t), AGSA_SMP_INIT_REQ, agNULL, 0);
5308
5309 oneExpander->currentIndex[phyId] ++;
5310 }
5311 else
5312 {
5313 TI_DBG1(("tdsaSASRoutingEntryAdd: Discovery Error routing index overflow for currentIndex=%d, routingIndex=%d\n", oneExpander->currentIndex[phyId], oneExpander->routingIndex));
5314 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
5315
5316 ret = agFALSE;
5317 }
5318
5319
5320 return ret;
5321 }
5322 /*****************************************************************************
5323 *! \brief tdsaConfigRoutingInfoRespRcvd
5324 *
5325 * Purpose: This function processes Configure Routing Information response.
5326 *
5327 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5328 * instance.
5329 * \param agRoot: Pointer to chip/driver Instance.
5330 * \param oneDeviceData: Pointer to the device data.
5331 * \param frameHeader: Pointer to SMP frame header.
5332 * \param frameHandle: A Handle used to refer to the response frame
5333 *
5334 * \return:
5335 * None
5336 *
5337 * \note:
5338 *
5339 *****************************************************************************/
5340 /* needs to traverse only upstream not downstream */
5341 osGLOBAL void
tdsaConfigRoutingInfoRespRcvd(tiRoot_t * tiRoot,agsaRoot_t * agRoot,agsaIORequest_t * agIORequest,tdsaDeviceData_t * oneDeviceData,tdssSMPFrameHeader_t * frameHeader,agsaFrameHandle_t frameHandle)5342 tdsaConfigRoutingInfoRespRcvd(
5343 tiRoot_t *tiRoot,
5344 agsaRoot_t *agRoot,
5345 agsaIORequest_t *agIORequest,
5346 tdsaDeviceData_t *oneDeviceData,
5347 tdssSMPFrameHeader_t *frameHeader,
5348 agsaFrameHandle_t frameHandle
5349 )
5350 {
5351 tdsaExpander_t *oneExpander = oneDeviceData->tdExpander;
5352 tdsaExpander_t *UpStreamExpander;
5353 tdsaExpander_t *DownStreamExpander;
5354 tdsaExpander_t *ReturningExpander;
5355 tdsaExpander_t *ConfigurableExpander;
5356
5357 tdsaPortContext_t *onePortContext;
5358 tdsaDeviceData_t *ReturningExpanderDeviceData;
5359 bit32 dupConfigSASAddr = agFALSE;
5360
5361 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: start\n"));
5362 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
5363 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
5364
5365 onePortContext = oneDeviceData->tdPortContext;
5366
5367 if (onePortContext->valid == agFALSE)
5368 {
5369 TI_DBG1(("tdsaConfigRoutingInfoRespRcvd: aborting discovery\n"));
5370 tdsaSASDiscoverAbort(tiRoot, onePortContext);
5371 return;
5372 }
5373
5374 if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ||
5375 frameHeader->smpFunctionResult == PHY_VACANT
5376 )
5377 {
5378 DownStreamExpander = oneExpander->tdCurrentDownStreamExpander;
5379 if (DownStreamExpander != agNULL)
5380 {
5381 DownStreamExpander->currentUpStreamPhyIndex ++;
5382 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex));
5383 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander->numOfUpStreamPhys %d\n", DownStreamExpander->numOfUpStreamPhys));
5384 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander addrHi 0x%08x\n", DownStreamExpander->tdDevice->SASAddressID.sasAddressHi));
5385 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander addrLo 0x%08x\n", DownStreamExpander->tdDevice->SASAddressID.sasAddressLo));
5386
5387 }
5388
5389 oneExpander->currentDownStreamPhyIndex++;
5390 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: oneExpander->currentDownStreamPhyIndex %d oneExpander->numOfDownStreamPhys %d\n", oneExpander->currentDownStreamPhyIndex, oneExpander->numOfDownStreamPhys));
5391
5392 if ( DownStreamExpander != agNULL)
5393 {
5394 if (DownStreamExpander->currentUpStreamPhyIndex < DownStreamExpander->numOfUpStreamPhys)
5395 {
5396 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: first if\n"));
5397 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex));
5398
5399 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: DownStreamExpander->upStreamPhys[] %d\n", DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex]));
5400
5401 tdsaSASRoutingEntryAdd(tiRoot,
5402 oneExpander,
5403 DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex],
5404 oneExpander->configSASAddressHi,
5405 oneExpander->configSASAddressLo
5406 );
5407 }
5408 else
5409 {
5410 /* traversing up till discovery Root onePortContext->discovery.RootExp */
5411 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: else\n"));
5412
5413 UpStreamExpander = oneExpander->tdUpStreamExpander;
5414 ConfigurableExpander = tdsaFindConfigurableExp(tiRoot, onePortContext, oneExpander);
5415 if (UpStreamExpander != agNULL)
5416 {
5417 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: UpStreamExpander addrHi 0x%08x\n", UpStreamExpander->tdDevice->SASAddressID.sasAddressHi));
5418 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: UpStreamExpander addrLo 0x%08x\n", UpStreamExpander->tdDevice->SASAddressID.sasAddressLo));
5419 dupConfigSASAddr = tdsaDuplicateConfigSASAddr(tiRoot,
5420 ConfigurableExpander,
5421 oneExpander->configSASAddressHi,
5422 oneExpander->configSASAddressLo
5423 );
5424
5425 if ( ConfigurableExpander != agNULL && dupConfigSASAddr == agFALSE)
5426 {
5427 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: else if\n"));
5428
5429 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ConfigurableExpander addrHi 0x%08x\n", ConfigurableExpander->tdDevice->SASAddressID.sasAddressHi));
5430 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ConfigurableExpander addrLo 0x%08x\n", ConfigurableExpander->tdDevice->SASAddressID.sasAddressLo));
5431
5432 UpStreamExpander->tdCurrentDownStreamExpander = oneExpander;
5433 ConfigurableExpander->currentDownStreamPhyIndex =
5434 tdsaFindCurrentDownStreamPhyIndex(tiRoot, ConfigurableExpander);
5435 ConfigurableExpander->tdReturnginExpander = oneExpander->tdReturnginExpander;
5436 DownStreamExpander->currentUpStreamPhyIndex = 0;
5437 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ConfigurableExpander->currentDownStreamPhyIndex %d\n", ConfigurableExpander->currentDownStreamPhyIndex));
5438
5439 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ConfigurableExpander->downStreamPhys[] %d\n", ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex]));
5440 tdsaSASRoutingEntryAdd(tiRoot,
5441 ConfigurableExpander,
5442 ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
5443 oneExpander->configSASAddressHi,
5444 oneExpander->configSASAddressLo
5445 );
5446 }
5447 else
5448 {
5449 /* going back to where it was */
5450 /* ConfigRoutingInfo is done for a target */
5451 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: $$$$$$ my change $$$$$ \n"));
5452 ReturningExpander = oneExpander->tdReturnginExpander;
5453 DownStreamExpander->currentUpStreamPhyIndex = 0;
5454 /* debugging */
5455 if (ReturningExpander != agNULL)
5456 {
5457 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ReturningExpander addrHi 0x%08x\n", ReturningExpander->tdDevice->SASAddressID.sasAddressHi));
5458 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ReturningExpander addrLo 0x%08x\n", ReturningExpander->tdDevice->SASAddressID.sasAddressLo));
5459
5460 ReturningExpanderDeviceData = ReturningExpander->tdDevice;
5461
5462 /* No longer in DISCOVERY_CONFIG_ROUTING */
5463 onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
5464
5465 /* If not the last phy */
5466 if ( ReturningExpander->discoveringPhyId < ReturningExpanderDeviceData->numOfPhys )
5467 {
5468 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: More Phys to discover\n"));
5469 /* continue discovery for the next phy */
5470 /* needs to send only one Discovery not multiple times */
5471 if (ReturningExpander->discoverSMPAllowed == agTRUE)
5472 {
5473 tdsaDiscoverSend(tiRoot, ReturningExpanderDeviceData);
5474 }
5475 ReturningExpander->discoverSMPAllowed = agFALSE;
5476 }
5477 /* If the last phy */
5478 else
5479 {
5480 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: No More Phys\n"));
5481 ReturningExpander->discoverSMPAllowed = agTRUE;
5482
5483 /* remove the expander from the discovering list */
5484 tdssSASDiscoveringExpanderRemove(tiRoot, onePortContext, ReturningExpander);
5485 /* continue downstream discovering */
5486 tdsaSASDownStreamDiscovering(tiRoot, onePortContext, ReturningExpanderDeviceData);
5487
5488 //DownStreamExpander
5489 }
5490 }
5491 else
5492 {
5493 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: ReturningExpander is NULL\n"));
5494 }
5495 }
5496 }
5497 else
5498 {
5499 TI_DBG3(("tdsaConfigRoutingInfoRespRcvd: UpStreamExpander is NULL\n"));
5500 }
5501 }
5502 }
5503 }
5504 else
5505 {
5506 TI_DBG1(("tdsaConfigRoutingInfoRespRcvd: Discovery Error SMP function return result error=%x\n", frameHeader->smpFunctionResult));
5507 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
5508 }
5509 return;
5510 }
5511
5512 /*****************************************************************************
5513 *! \brief tdsaReportPhySataSend
5514 *
5515 * Purpose: This function sends Report Phy SATA to a device.
5516 *
5517 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5518 * instance.
5519 * \param oneDeviceData: Pointer to the device data.
5520 * \param phyId: Phy Identifier.
5521 *
5522 * \return:
5523 * None
5524 *
5525 * \note:
5526 *
5527 *****************************************************************************/
5528 osGLOBAL void
tdsaReportPhySataSend(tiRoot_t * tiRoot,tdsaDeviceData_t * oneDeviceData,bit8 phyId)5529 tdsaReportPhySataSend(
5530 tiRoot_t *tiRoot,
5531 tdsaDeviceData_t *oneDeviceData,
5532 bit8 phyId
5533 )
5534 {
5535 agsaRoot_t *agRoot;
5536 tdsaExpander_t *oneExpander;
5537 tdsaPortContext_t *onePortContext;
5538 smpReqReportPhySata_t smpReportPhySataReq;
5539
5540 TI_DBG3(("tdsaReportPhySataSend: start\n"));
5541
5542 agRoot = oneDeviceData->agRoot;
5543 onePortContext = oneDeviceData->tdPortContext;
5544 oneExpander = oneDeviceData->tdExpander;
5545
5546 if (onePortContext == agNULL)
5547 {
5548 TI_DBG1(("tdsaReportPhySataSend: Error!!! portcontext is NULL\n"));
5549 }
5550
5551 if (oneExpander == agNULL)
5552 {
5553 TI_DBG1(("tdsaReportPhySataSend: Error!!! expander is NULL\n"));
5554 return;
5555 }
5556 TI_DBG3(("tdsaReportPhySataSend: device %p did %d\n", oneDeviceData, oneDeviceData->id));
5557 TI_DBG3(("tdsaReportPhySataSend: phyid %d\n", phyId));
5558
5559 oneExpander->tdDeviceToProcess = oneDeviceData;
5560
5561 osti_memset(&smpReportPhySataReq, 0, sizeof(smpReqReportPhySata_t));
5562
5563 smpReportPhySataReq.phyIdentifier = phyId;
5564
5565
5566 tdSMPStart(
5567 tiRoot,
5568 agRoot,
5569 oneExpander->tdDevice,
5570 SMP_REPORT_PHY_SATA,
5571 (bit8 *)&smpReportPhySataReq,
5572 sizeof(smpReqReportPhySata_t),
5573 AGSA_SMP_INIT_REQ,
5574 agNULL,
5575 0
5576 );
5577
5578 return;
5579 }
5580
5581 /*****************************************************************************
5582 *! \brief tdsaReportPhySataRcvd
5583 *
5584 * Purpose: This function processes Report Phy SATA response.
5585 *
5586 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5587 * instance.
5588 * \param agRoot: Pointer to chip/driver Instance.
5589 * \param oneDeviceData: Pointer to the device data.
5590 * \param frameHeader: Pointer to SMP frame header.
5591 * \param frameHandle: A Handle used to refer to the response frame
5592 *
5593 * \return:
5594 * None
5595 *
5596 * \note:
5597 *
5598 *****************************************************************************/
5599 osGLOBAL void
tdsaReportPhySataRcvd(tiRoot_t * tiRoot,agsaRoot_t * agRoot,agsaIORequest_t * agIORequest,tdsaDeviceData_t * oneDeviceData,tdssSMPFrameHeader_t * frameHeader,agsaFrameHandle_t frameHandle)5600 tdsaReportPhySataRcvd(
5601 tiRoot_t *tiRoot,
5602 agsaRoot_t *agRoot,
5603 agsaIORequest_t *agIORequest,
5604 tdsaDeviceData_t *oneDeviceData,
5605 tdssSMPFrameHeader_t *frameHeader,
5606 agsaFrameHandle_t frameHandle
5607 )
5608 {
5609 smpRespReportPhySata_t SMPreportPhySataResp;
5610 smpRespReportPhySata_t *pSMPReportPhySataResp;
5611 tdsaExpander_t *oneExpander = oneDeviceData->tdExpander;
5612 tdsaPortContext_t *onePortContext;
5613 agsaFisRegDeviceToHost_t *fis;
5614 tdsaDeviceData_t *SataDevice;
5615 #ifndef DIRECT_SMP
5616 tdssSMPRequestBody_t *tdSMPRequestBody;
5617 #endif
5618
5619 TI_DBG3(("tdsaReportPhySataRcvd: start\n"));
5620 TI_DBG3(("tdsaReportPhySataRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
5621 TI_DBG3(("tdsaReportPhySataRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
5622 #ifndef DIRECT_SMP
5623 tdSMPRequestBody = (tdssSMPRequestBody_t *)agIORequest->osData;
5624 #endif
5625 /* get the current sata device hanlde stored in the expander structure */
5626 SataDevice = oneExpander->tdDeviceToProcess;
5627 pSMPReportPhySataResp = &SMPreportPhySataResp;
5628 #ifdef DIRECT_SMP
5629 saFrameReadBlock(agRoot, frameHandle, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));
5630 #else
5631 saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));
5632 #endif
5633
5634 //tdhexdump("tdsaReportPhySataRcvd", (bit8 *)pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));
5635
5636 #ifndef DIRECT_SMP
5637 ostiFreeMemory(
5638 tiRoot,
5639 tdSMPRequestBody->IndirectSMPReqosMemHandle,
5640 tdSMPRequestBody->IndirectSMPReqLen
5641 );
5642 ostiFreeMemory(
5643 tiRoot,
5644 tdSMPRequestBody->IndirectSMPResposMemHandle,
5645 tdSMPRequestBody->IndirectSMPRespLen
5646 );
5647 #endif
5648
5649 onePortContext = oneDeviceData->tdPortContext;
5650
5651 if (onePortContext->valid == agFALSE)
5652 {
5653 TI_DBG1(("tdsaReportPhySataRcvd: aborting discovery\n"));
5654 tdsaSASDiscoverAbort(tiRoot, onePortContext);
5655 return;
5656 }
5657 if (SataDevice == agNULL)
5658 {
5659 TI_DBG1(("tdsaReportPhySataRcvd: SataDevice is NULL, wrong\n"));
5660 tdsaSASDiscoverAbort(tiRoot, onePortContext);
5661 return;
5662 }
5663 if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ||
5664 frameHeader->smpFunctionResult == PHY_VACANT
5665 )
5666 {
5667 fis = (agsaFisRegDeviceToHost_t*) &SMPreportPhySataResp.regDevToHostFis;
5668 if (fis->h.fisType == REG_DEV_TO_HOST_FIS)
5669 {
5670 /* save signature */
5671 TI_DBG3(("tdsaReportPhySataRcvd: saves the signature\n"));
5672 /* saves signature */
5673 SataDevice->satDevData.satSignature[0] = fis->d.sectorCount;
5674 SataDevice->satDevData.satSignature[1] = fis->d.lbaLow;
5675 SataDevice->satDevData.satSignature[2] = fis->d.lbaMid;
5676 SataDevice->satDevData.satSignature[3] = fis->d.lbaHigh;
5677 SataDevice->satDevData.satSignature[4] = fis->d.device;
5678 SataDevice->satDevData.satSignature[5] = 0;
5679 SataDevice->satDevData.satSignature[6] = 0;
5680 SataDevice->satDevData.satSignature[7] = 0;
5681
5682 TI_DBG3(("tdsaReportPhySataRcvd: SATA Signature = %02x %02x %02x %02x %02x\n",
5683 SataDevice->satDevData.satSignature[0],
5684 SataDevice->satDevData.satSignature[1],
5685 SataDevice->satDevData.satSignature[2],
5686 SataDevice->satDevData.satSignature[3],
5687 SataDevice->satDevData.satSignature[4]));
5688 /*
5689 no longer, discovery sends sata identify device command
5690 tdsaSATAIdentifyDeviceCmdSend(tiRoot, SataDevice);
5691 */
5692 SataDevice = tdsaFindRightDevice(tiRoot, onePortContext, SataDevice);
5693 tdsaDiscoveringStpSATADevice(tiRoot, onePortContext, SataDevice);
5694 }
5695 else
5696 {
5697 TI_DBG3(("tdsaReportPhySataRcvd: getting next stp bride\n"));
5698 SataDevice = tdsaFindRightDevice(tiRoot, onePortContext, SataDevice);
5699 tdsaDiscoveringStpSATADevice(tiRoot, onePortContext, SataDevice);
5700 }
5701 }
5702 else
5703 {
5704 TI_DBG3(("tdsaReportPhySataRcvd: siReportPhySataRcvd SMP function return result %x\n",
5705 frameHeader->smpFunctionResult));
5706 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
5707 }
5708 return;
5709 }
5710
5711 /*****************************************************************************
5712 *! \brief tdsaSASExpanderUpStreamPhyAdd
5713 *
5714 * Purpose: This function adds upstream expander to a specfic phy.
5715 *
5716 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5717 * instance.
5718 * \param oneExpander: Pointer to the expander data.
5719 * \param phyId: Phy Identifier.
5720 *
5721 * \return:
5722 * None
5723 *
5724 * \note:
5725 *
5726 *****************************************************************************/
5727 osGLOBAL void
tdsaSASExpanderUpStreamPhyAdd(tiRoot_t * tiRoot,tdsaExpander_t * oneExpander,bit8 phyId)5728 tdsaSASExpanderUpStreamPhyAdd(
5729 tiRoot_t *tiRoot,
5730 tdsaExpander_t *oneExpander,
5731 bit8 phyId
5732 )
5733 {
5734 bit32 i;
5735 bit32 hasSet = agFALSE;
5736
5737 TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: start, phyid %d\n", phyId));
5738 TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
5739 TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
5740 TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: phyid %d numOfUpStreamPhys %d\n", phyId, oneExpander->numOfUpStreamPhys));
5741
5742 for ( i = 0; i < oneExpander->numOfUpStreamPhys; i ++ )
5743 {
5744 if ( oneExpander->upStreamPhys[i] == phyId )
5745 {
5746 hasSet = agTRUE;
5747 break;
5748 }
5749 }
5750
5751 if ( hasSet == agFALSE )
5752 {
5753 oneExpander->upStreamPhys[oneExpander->numOfUpStreamPhys ++] = phyId;
5754 }
5755
5756 TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: AFTER phyid %d numOfUpStreamPhys %d\n", phyId, oneExpander->numOfUpStreamPhys));
5757
5758 /* for debugging */
5759 for ( i = 0; i < oneExpander->numOfUpStreamPhys; i ++ )
5760 {
5761 TI_DBG3(("tdsaSASExpanderUpStreamPhyAdd: index %d upstream[index] %d\n", i, oneExpander->upStreamPhys[i]));
5762 }
5763 return;
5764 }
5765
5766 /*
5767 just add phys in downstream in configurable expnader
5768 */
5769 /*****************************************************************************
5770 *! \brief tdsaSASExpanderDownStreamPhyAdd
5771 *
5772 * Purpose: This function adds downstream expander to a specfic phy.
5773 *
5774 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5775 * instance.
5776 * \param oneExpander: Pointer to the expander data.
5777 * \param phyId: Phy Identifier.
5778 *
5779 * \return:
5780 * None
5781 *
5782 * \note:
5783 *
5784 *****************************************************************************/
5785 osGLOBAL void
tdsaSASExpanderDownStreamPhyAdd(tiRoot_t * tiRoot,tdsaExpander_t * oneExpander,bit8 phyId)5786 tdsaSASExpanderDownStreamPhyAdd(
5787 tiRoot_t *tiRoot,
5788 tdsaExpander_t *oneExpander,
5789 bit8 phyId
5790 )
5791 {
5792 bit32 i;
5793 bit32 hasSet = agFALSE;
5794
5795 TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: start, phyid %d\n", phyId));
5796 TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
5797 TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
5798 TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: phyid %d numOfDownStreamPhys %d\n", phyId, oneExpander->numOfDownStreamPhys));
5799
5800 for ( i = 0; i < oneExpander->numOfDownStreamPhys; i ++ )
5801 {
5802 if ( oneExpander->downStreamPhys[i] == phyId )
5803 {
5804 hasSet = agTRUE;
5805 break;
5806 }
5807 }
5808
5809 if ( hasSet == agFALSE )
5810 {
5811 oneExpander->downStreamPhys[oneExpander->numOfDownStreamPhys ++] = phyId;
5812 }
5813
5814 TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: AFTER phyid %d numOfDownStreamPhys %d\n", phyId, oneExpander->numOfDownStreamPhys));
5815
5816 /* for debugging */
5817 for ( i = 0; i < oneExpander->numOfDownStreamPhys; i ++ )
5818 {
5819 TI_DBG3(("tdsaSASExpanderDownStreamPhyAdd: index %d downstream[index] %d\n", i, oneExpander->downStreamPhys[i]));
5820 }
5821 return;
5822 }
5823
5824 /* oneExpander is the configurable expander of interest
5825 phyId is the first phyID in upStreamPhys[0] of downExpander
5826 */
5827 /*****************************************************************************
5828 *! \brief tdsaFindCurrentDownStreamPhyIndex
5829 *
5830 * Purpose: This function finds CurrentDownStreamPhyIndex from a configurable
5831 * expander.
5832 *
5833 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5834 * instance.
5835 * \param oneExpander: Pointer to the configuralbe expander data.
5836 *
5837 * \return:
5838 * CurrentDownStreamPhyIndex
5839 *
5840 *
5841 *****************************************************************************/
5842 osGLOBAL bit16
tdsaFindCurrentDownStreamPhyIndex(tiRoot_t * tiRoot,tdsaExpander_t * oneExpander)5843 tdsaFindCurrentDownStreamPhyIndex(
5844 tiRoot_t *tiRoot,
5845 tdsaExpander_t *oneExpander
5846 )
5847 {
5848 tdsaExpander_t *DownStreamExpander;
5849 bit16 index = 0;
5850 bit16 i;
5851 bit8 phyId = 0;
5852
5853 TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: start\n"));
5854
5855 if (oneExpander == agNULL)
5856 {
5857 TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: wrong!!! oneExpander is NULL\n"));
5858 return 0;
5859 }
5860
5861 DownStreamExpander = oneExpander->tdCurrentDownStreamExpander;
5862
5863 if (DownStreamExpander == agNULL)
5864 {
5865 TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: wrong!!! DownStreamExpander is NULL\n"));
5866 return 0;
5867 }
5868
5869 TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: exp addrHi 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressHi));
5870 TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: exp addrLo 0x%08x\n", oneExpander->tdDevice->SASAddressID.sasAddressLo));
5871 TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: downstream exp addrHi 0x%08x\n", DownStreamExpander->tdDevice->SASAddressID.sasAddressHi));
5872 TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: downstream exp addrLo 0x%08x\n", DownStreamExpander->tdDevice->SASAddressID.sasAddressLo));
5873 TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: numOfDownStreamPhys %d\n", oneExpander->numOfDownStreamPhys));
5874
5875 phyId = DownStreamExpander->upStreamPhys[0];
5876
5877 TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: phyId %d\n", phyId));
5878
5879 for (i=0; i<oneExpander->numOfDownStreamPhys;i++)
5880 {
5881 if (oneExpander->downStreamPhys[i] == phyId)
5882 {
5883 index = i;
5884 break;
5885 }
5886 }
5887 TI_DBG3(("tdsaFindCurrentDownStreamPhyIndex: index %d\n", index));
5888 return index;
5889 }
5890 /*****************************************************************************
5891 *! \brief tdsaPortSASDeviceFind
5892 *
5893 * Purpose: Given SAS address, this function finds a device with that SAS address
5894 * in the device list.
5895 *
5896 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5897 * instance.
5898 * \param onePortContext: Pointer to the portal context instance.
5899 * \param sasAddrLo: Lower 4 byte of SAS address.
5900 * \param sasAddrHi: Upper 4 byte of SAS address.
5901 *
5902 * \return:
5903 * agNULL When no device found
5904 * Pointer to device When device is found
5905 *
5906 * \note:
5907 *
5908 *****************************************************************************/
5909 osGLOBAL tdsaDeviceData_t *
tdsaPortSASDeviceFind(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,bit32 sasAddrLo,bit32 sasAddrHi)5910 tdsaPortSASDeviceFind(
5911 tiRoot_t *tiRoot,
5912 tdsaPortContext_t *onePortContext,
5913 bit32 sasAddrLo,
5914 bit32 sasAddrHi
5915 )
5916 {
5917 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
5918 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
5919 tdsaDeviceData_t *oneDeviceData, *RetDeviceData=agNULL;
5920 tdList_t *DeviceListList;
5921
5922 TI_DBG3(("tdsaPortSASDeviceFind: start\n"));
5923
5924 TD_ASSERT((agNULL != tiRoot), "");
5925 TD_ASSERT((agNULL != onePortContext), "");
5926
5927 tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
5928
5929 /* find a device's existence */
5930 DeviceListList = tdsaAllShared->MainDeviceList.flink;
5931 if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
5932 {
5933 TI_DBG3(("tdsaPortSASDeviceFind: Full discovery\n"));
5934 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
5935 {
5936 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
5937 if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) &&
5938 (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) &&
5939 (oneDeviceData->valid == agTRUE) &&
5940 (oneDeviceData->tdPortContext == onePortContext)
5941 )
5942 {
5943 TI_DBG3(("tdsaPortSASDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
5944 TI_DBG3(("tdsaPortSASDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
5945 TI_DBG3(("tdsaPortSASDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
5946 RetDeviceData = oneDeviceData;
5947 break;
5948 }
5949 DeviceListList = DeviceListList->flink;
5950 }
5951 }
5952 else
5953 {
5954 /* incremental discovery */
5955 TI_DBG3(("tdsaPortSASDeviceFind: Incremental discovery\n"));
5956 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
5957 {
5958 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
5959 if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) &&
5960 (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) &&
5961 (oneDeviceData->valid2 == agTRUE) &&
5962 (oneDeviceData->tdPortContext == onePortContext)
5963 )
5964 {
5965 TI_DBG3(("tdsaPortSASDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id));
5966 TI_DBG3(("tdsaPortSASDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
5967 TI_DBG3(("tdsaPortSASDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
5968
5969 RetDeviceData = oneDeviceData;
5970 break;
5971 }
5972 DeviceListList = DeviceListList->flink;
5973 }
5974 }
5975
5976 tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
5977
5978 return RetDeviceData;
5979 }
5980
5981 /* include both sas and stp-sata targets*/
5982 /*****************************************************************************
5983 *! \brief tdsaPortSASDeviceAdd
5984 *
5985 * Purpose: This function adds the SAS device to the device list.
5986 *
5987 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
5988 * instance.
5989 * \param onePortContext: Pointer to the portal context instance.
5990 * \param sasIdentify: SAS identify address frame.
5991 * \param sasInitiator: SAS initiator.
5992 * \param connectionRate: Connection Rate.
5993 * \param itNexusTimeout: IT NEXUS timeout value.
5994 * \param firstBurstSize: First Burst Size.
5995 * \param deviceType: Device Type.
5996 *
5997 * \return:
5998 * Pointer to device data.
5999 *
6000 * \note:
6001 *
6002 *****************************************************************************/
6003 GLOBAL tdsaDeviceData_t *
tdsaPortSASDeviceAdd(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,agsaSASIdentify_t sasIdentify,bit32 sasInitiator,bit8 connectionRate,bit32 itNexusTimeout,bit32 firstBurstSize,bit32 deviceType,tdsaDeviceData_t * oneExpDeviceData,bit8 phyID)6004 tdsaPortSASDeviceAdd(
6005 tiRoot_t *tiRoot,
6006 tdsaPortContext_t *onePortContext,
6007 agsaSASIdentify_t sasIdentify,
6008 bit32 sasInitiator,
6009 bit8 connectionRate,
6010 bit32 itNexusTimeout,
6011 bit32 firstBurstSize,
6012 bit32 deviceType,
6013 tdsaDeviceData_t *oneExpDeviceData,
6014 bit8 phyID
6015 )
6016 {
6017 tdsaDeviceData_t *oneDeviceData = agNULL;
6018 bit8 dev_s_rate = 0;
6019 bit8 sasorsata = 1;
6020 // bit8 devicetype;
6021 tdsaSASSubID_t agSASSubID;
6022 tdsaDeviceData_t *oneAttachedExpDeviceData = agNULL;
6023
6024 TI_DBG3(("tdsaPortSASDeviceAdd: start\n"));
6025 TI_DBG3(("tdsaPortSASDeviceAdd: connectionRate %d\n", connectionRate));
6026
6027 agSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify);
6028 agSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify);
6029 agSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
6030 agSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
6031
6032 /* old device and already registered to LL; added by link-up event */
6033 if ( agFALSE == tdssNewSASorNot(
6034 onePortContext->agRoot,
6035 onePortContext,
6036 &agSASSubID
6037 )
6038 )
6039 {
6040 /* old device and already registered to LL; added by link-up event */
6041 TI_DBG3(("tdsaPortSASDeviceAdd: OLD qqqq initiator_ssp_stp_smp %d target_ssp_stp_smp %d\n", agSASSubID.initiator_ssp_stp_smp, agSASSubID.target_ssp_stp_smp));
6042 /* find the old device */
6043 oneDeviceData = tdssNewAddSASToSharedcontext(
6044 onePortContext->agRoot,
6045 onePortContext,
6046 &agSASSubID,
6047 oneExpDeviceData,
6048 phyID
6049 );
6050
6051 if (oneDeviceData == agNULL)
6052 {
6053 TI_DBG1(("tdsaPortSASDeviceAdd: no more device!!! oneDeviceData is null\n"));
6054 }
6055
6056 /* If a device is allocated */
6057 if ( oneDeviceData != agNULL )
6058 {
6059
6060 TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify)));
6061 TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify)));
6062
6063 oneDeviceData->sasIdentify = sasIdentify;
6064
6065 TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
6066 TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
6067
6068 /* parse sasIDframe to fill in agDeviceInfo */
6069 DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT);
6070 DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)itNexusTimeout);
6071 DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, (bit16)firstBurstSize);
6072 DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 1);
6073
6074 oneDeviceData->SASSpecDeviceType = (bit8)(SA_IDFRM_GET_DEVICETTYPE(&sasIdentify));
6075
6076 /* adjusting connectionRate */
6077 oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
6078 if (oneAttachedExpDeviceData != agNULL)
6079 {
6080 connectionRate = (bit8)(MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6081 TI_DBG3(("tdsaPortSASDeviceAdd: 1st connectionRate 0x%x DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n",
6082 connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6083 }
6084 else
6085 {
6086 TI_DBG3(("tdsaPortSASDeviceAdd: 1st oneAttachedExpDeviceData is NULL\n"));
6087 }
6088
6089 /* Device Type, SAS or SATA, connection rate; bit7 --- bit0 */
6090 sasorsata = (bit8)deviceType;
6091 /* sTSDK spec device typ */
6092 dev_s_rate = (bit8)(dev_s_rate | (sasorsata << 4));
6093 dev_s_rate = (bit8)(dev_s_rate | connectionRate);
6094 DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate);
6095
6096
6097 DEVINFO_PUT_SAS_ADDRESSLO(
6098 &oneDeviceData->agDeviceInfo,
6099 SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)
6100 );
6101 DEVINFO_PUT_SAS_ADDRESSHI(
6102 &oneDeviceData->agDeviceInfo,
6103 SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)
6104 );
6105 oneDeviceData->agContext.osData = oneDeviceData;
6106 oneDeviceData->agContext.sdkData = agNULL;
6107
6108 }
6109 return oneDeviceData;
6110 } /* old device */
6111
6112 /* new device */
6113
6114 TI_DBG3(("tdsaPortSASDeviceAdd: NEW qqqq initiator_ssp_stp_smp %d target_ssp_stp_smp %d\n", agSASSubID.initiator_ssp_stp_smp, agSASSubID.target_ssp_stp_smp));
6115
6116 /* allocate a new device and set the valid bit */
6117 oneDeviceData = tdssNewAddSASToSharedcontext(
6118 onePortContext->agRoot,
6119 onePortContext,
6120 &agSASSubID,
6121 oneExpDeviceData,
6122 phyID
6123 );
6124
6125 if (oneDeviceData == agNULL)
6126 {
6127 TI_DBG1(("tdsaPortSASDeviceAdd: no more device!!! oneDeviceData is null\n"));
6128 }
6129
6130 /* If a device is allocated */
6131 if ( oneDeviceData != agNULL )
6132 {
6133
6134 TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify)));
6135 TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify)));
6136
6137 oneDeviceData->sasIdentify = sasIdentify;
6138
6139 TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
6140 TI_DBG3(("tdsaPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
6141
6142
6143 /* parse sasIDframe to fill in agDeviceInfo */
6144 DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT);
6145 DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)itNexusTimeout);
6146 DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, (bit16)firstBurstSize);
6147 DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 1);
6148
6149 oneDeviceData->SASSpecDeviceType = (bit8)(SA_IDFRM_GET_DEVICETTYPE(&sasIdentify));
6150
6151 /* adjusting connectionRate */
6152 oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
6153 if (oneAttachedExpDeviceData != agNULL)
6154 {
6155 connectionRate = (bit8)(MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6156 TI_DBG3(("tdsaPortSASDeviceAdd: 2nd connectionRate 0x%x DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n",
6157 connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6158 }
6159 else
6160 {
6161 TI_DBG3(("tdsaPortSASDeviceAdd: 2nd oneAttachedExpDeviceData is NULL\n"));
6162 }
6163
6164 /* Device Type, SAS or SATA, connection rate; bit7 --- bit0 */
6165 sasorsata = (bit8)deviceType;
6166 dev_s_rate = (bit8)(dev_s_rate | (sasorsata << 4));
6167 dev_s_rate = (bit8)(dev_s_rate | connectionRate);
6168 DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate);
6169
6170
6171 DEVINFO_PUT_SAS_ADDRESSLO(
6172 &oneDeviceData->agDeviceInfo,
6173 SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)
6174 );
6175 DEVINFO_PUT_SAS_ADDRESSHI(
6176 &oneDeviceData->agDeviceInfo,
6177 SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)
6178 );
6179 oneDeviceData->agContext.osData = oneDeviceData;
6180 oneDeviceData->agContext.sdkData = agNULL;
6181
6182 TI_DBG3(("tdsaPortSASDeviceAdd: did %d\n", oneDeviceData->id));
6183
6184 /* don't add and register initiator for T2D */
6185 if ( (((sasIdentify.initiator_ssp_stp_smp & DEVICE_SSP_BIT) == DEVICE_SSP_BIT) &&
6186 ((sasIdentify.target_ssp_stp_smp & DEVICE_SSP_BIT) != DEVICE_SSP_BIT))
6187 ||
6188 (((sasIdentify.initiator_ssp_stp_smp & DEVICE_STP_BIT) == DEVICE_STP_BIT) &&
6189 ((sasIdentify.target_ssp_stp_smp & DEVICE_SSP_BIT) != DEVICE_SSP_BIT))
6190 )
6191 {
6192 TI_DBG1(("tdsaPortSASDeviceAdd: initiator. no add and registration\n"));
6193 TI_DBG1(("tdsaPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
6194 TI_DBG1(("tdsaPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
6195
6196 }
6197 else
6198 {
6199 if (oneDeviceData->registered == agFALSE)
6200 {
6201 TI_DBG2(("tdsaPortSASDeviceAdd: did %d\n", oneDeviceData->id));
6202 saRegisterNewDevice( /* tdsaPortSASDeviceAdd */
6203 onePortContext->agRoot,
6204 &oneDeviceData->agContext,
6205 tdsaRotateQnumber(tiRoot, oneDeviceData),
6206 &oneDeviceData->agDeviceInfo,
6207 onePortContext->agPortContext,
6208 0
6209 );
6210 }
6211 }
6212 }
6213
6214 return oneDeviceData;
6215 }
6216
6217 /*****************************************************************************
6218 *! \brief tdsaDiscoveryResetProcessed
6219 *
6220 * Purpose: This function called to reset "processed flag" of device belong to
6221 * a specified port.
6222 *
6223 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6224 * instance.
6225 * \param onePortContext: Pointer to the portal context instance.
6226 *
6227 * \return:
6228 * None
6229 *
6230 * \note:
6231 *
6232 *****************************************************************************/
6233
6234 osGLOBAL void
tdsaDiscoveryResetProcessed(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext)6235 tdsaDiscoveryResetProcessed(
6236 tiRoot_t *tiRoot,
6237 tdsaPortContext_t *onePortContext
6238 )
6239 {
6240 tdsaDeviceData_t *oneDeviceData = agNULL;
6241 tdList_t *DeviceListList;
6242 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
6243 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
6244
6245 TI_DBG6(("tdsaDiscoveryResetProcessed: start\n"));
6246
6247 /* reinitialize the device data belonging to this portcontext */
6248 DeviceListList = tdsaAllShared->MainDeviceList.flink;
6249 while (DeviceListList != &(tdsaAllShared->MainDeviceList))
6250 {
6251 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6252 TI_DBG6(("tdsaDiscoveryResetProcessed: loop did %d\n", oneDeviceData->id));
6253 if (oneDeviceData->tdPortContext == onePortContext)
6254 {
6255 TI_DBG6(("tdsaDiscoveryResetProcessed: resetting procssed flag\n"));
6256 oneDeviceData->processed = agFALSE;
6257 }
6258 DeviceListList = DeviceListList->flink;
6259 }
6260
6261 return;
6262 }
6263
6264 /*****************************************************************************
6265 *! \brief tdsaSATADiscoverDone
6266 *
6267 * Purpose: This function called to finish up SATA discovery.
6268 *
6269 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6270 * instance.
6271 * \param onePortContext: Pointer to the portal context instance.
6272 * \param flag: status of discovery (success or failure).
6273 *
6274 * \return:
6275 * None
6276 *
6277 * \note:
6278 *
6279 *****************************************************************************/
6280 osGLOBAL void
tdsaSATADiscoverDone(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,bit32 flag)6281 tdsaSATADiscoverDone(
6282 tiRoot_t *tiRoot,
6283 tdsaPortContext_t *onePortContext,
6284 bit32 flag
6285 )
6286 {
6287 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
6288 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
6289 TI_DBG3(("tdsaSATADiscoverDone: start\n"));
6290 tdsaDiscoveryResetProcessed(tiRoot, onePortContext);
6291
6292 if (onePortContext->discovery.SeenBC == agTRUE)
6293 {
6294 TI_DBG3(("tdsaSATADiscoverDone: broadcast change; discover again\n"));
6295 tdssInternalRemovals(onePortContext->agRoot,
6296 onePortContext
6297 );
6298
6299 /* processed broadcast change */
6300 onePortContext->discovery.SeenBC = agFALSE;
6301 if (tdsaAllShared->ResetInDiscovery != 0 &&
6302 onePortContext->discovery.ResetTriggerred == agTRUE)
6303 {
6304 TI_DBG1(("tdsaSATADiscoverDone: tdsaBCTimer\n"));
6305 tdsaBCTimer(tiRoot, onePortContext);
6306 }
6307 else
6308 {
6309 tdsaDiscover(
6310 tiRoot,
6311 onePortContext,
6312 TDSA_DISCOVERY_TYPE_SAS,
6313 TDSA_DISCOVERY_OPTION_INCREMENTAL_START
6314 );
6315 }
6316 }
6317 else
6318 {
6319 onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
6320
6321 if (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START)
6322 {
6323 if (flag == tiSuccess)
6324 {
6325 #ifdef AGTIAPI_CTL
6326 tdsaContext_t *tdsaAllShared =
6327 &((tdsaRoot_t*)tiRoot->tdData)->tdsaAllShared;
6328
6329 if (tdsaAllShared->SASConnectTimeLimit)
6330 tdsaCTLSet(tiRoot, onePortContext, tiIntrEventTypeDiscovery,
6331 tiDiscOK);
6332 else
6333 #endif
6334 ostiInitiatorEvent(
6335 tiRoot,
6336 onePortContext->tiPortalContext,
6337 agNULL,
6338 tiIntrEventTypeDiscovery,
6339 tiDiscOK,
6340 agNULL
6341 );
6342 }
6343 else
6344 {
6345 TI_DBG1(("tdsaSATADiscoverDone: Error; clean up\n"));
6346 tdssDiscoveryErrorRemovals(onePortContext->agRoot,
6347 onePortContext
6348 );
6349
6350 ostiInitiatorEvent(
6351 tiRoot,
6352 onePortContext->tiPortalContext,
6353 agNULL,
6354 tiIntrEventTypeDiscovery,
6355 tiDiscFailed,
6356 agNULL
6357 );
6358 }
6359 }
6360 else
6361 {
6362 if (flag == tiSuccess)
6363 {
6364 tdssReportChanges(onePortContext->agRoot,
6365 onePortContext
6366 );
6367 }
6368 else
6369 {
6370 tdssReportRemovals(onePortContext->agRoot,
6371 onePortContext,
6372 agFALSE
6373 );
6374 }
6375 }
6376 }
6377 #ifdef TBD
6378 /* ACKing BC */
6379 tdsaAckBC(tiRoot, onePortContext);
6380 #endif
6381 return;
6382 }
6383
6384 osGLOBAL void
tdsaAckBC(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext)6385 tdsaAckBC(
6386 tiRoot_t *tiRoot,
6387 tdsaPortContext_t *onePortContext
6388 )
6389 {
6390 #ifdef TBD /* not yet */
6391 agsaEventSource_t eventSource[TD_MAX_NUM_PHYS];
6392 bit32 HwAckSatus = AGSA_RC_SUCCESS;
6393 int i;
6394 TI_DBG3(("tdsaAckBC: start\n"));
6395
6396 for (i=0;i<TD_MAX_NUM_PHYS;i++)
6397 {
6398 if (onePortContext->BCPhyID[i] == agTRUE)
6399 {
6400 /* saHwEventAck() */
6401 eventSource[i].agPortContext = onePortContext->agPortContext;
6402 eventSource[i].event = OSSA_HW_EVENT_BROADCAST_CHANGE;
6403 /* phy ID */
6404 eventSource[i].param = i;
6405 HwAckSatus = saHwEventAck(
6406 onePortContext->agRoot,
6407 agNULL, /* agContext */
6408 0,
6409 &eventSource[i], /* agsaEventSource_t */
6410 0,
6411 0
6412 );
6413 TI_DBG3(("tdsaAckBC: calling saHwEventAck\n"));
6414
6415 if ( HwAckSatus != AGSA_RC_SUCCESS)
6416 {
6417 TI_DBG1(("tdsaAckBC: failing in saHwEventAck; status %d\n", HwAckSatus));
6418 return;
6419 }
6420 }
6421 onePortContext->BCPhyID[i] = agFALSE;
6422 }
6423 #endif
6424 }
6425
6426 #ifdef SATA_ENABLE
6427
6428 /*****************************************************************************
6429 *! \brief tdsaSATAFullDiscover
6430 *
6431 * Purpose: This function is called to trigger full SATA topology discovery
6432 * within a portcontext.
6433 *
6434 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6435 * instance.
6436 * \param onePortContext: Pointer to the portal context instance.
6437 *
6438 * \return:
6439 * tiSuccess Discovery initiated.
6440 * tiError Discovery could not be initiated at this time.
6441 *
6442 * \note:
6443 *
6444 *****************************************************************************/
6445 osGLOBAL bit32
tdsaSATAFullDiscover(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext)6446 tdsaSATAFullDiscover(
6447 tiRoot_t *tiRoot,
6448 tdsaPortContext_t *onePortContext
6449 )
6450 {
6451 bit32 ret = tiSuccess;
6452 tdsaDeviceData_t *oneDeviceData = agNULL;
6453 bit32 deviceType;
6454 bit8 phyRate = SAS_CONNECTION_RATE_3_0G;
6455 bit32 i;
6456 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
6457 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
6458 // tdsaDeviceData_t *tdsaDeviceData = (tdsaDeviceData_t *)tdsaAllShared->DeviceMem;
6459 tdsaDeviceData_t *tdsaDeviceData;
6460 tdList_t *DeviceListList;
6461
6462 TI_DBG3(("tdsaSATAFullDiscover: start\n"));
6463 if (onePortContext->valid == agFALSE)
6464 {
6465 TI_DBG1(("tdsaSATAFullDiscover: aborting discovery\n"));
6466 tdsaSASDiscoverAbort(tiRoot, onePortContext);
6467 return tiError;
6468 }
6469 phyRate = onePortContext->LinkRate;
6470 DeviceListList = tdsaAllShared->MainDeviceList.flink;
6471 tdsaDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6472 /* If port is SATA mode */
6473 /*
6474 Native SATA mode is decided in ossaHWCB() SAS_LINK_UP or SATA_LINK_UP
6475 */
6476 if (onePortContext->nativeSATAMode == agTRUE)
6477 {
6478 /* Decode device type */
6479 deviceType = tdssSATADeviceTypeDecode(onePortContext->remoteSignature);
6480 /* Create a device descriptor for the SATA device attached to the port */
6481 if ( deviceType == SATA_PM_DEVICE)
6482 {
6483 TI_DBG3(("tdsaSATAFullDiscover: Found a PM device\n"));
6484 oneDeviceData = tdsaPortSATADeviceAdd(
6485 tiRoot,
6486 onePortContext,
6487 agNULL,
6488 onePortContext->remoteSignature,
6489 agTRUE,
6490 0xF,
6491 phyRate,
6492 agNULL,
6493 0xFF
6494 );
6495 }
6496 else
6497 {
6498 /* already added in ossahwcb() in SATA link up */
6499 TI_DBG3(("tdsaSATAFullDiscover: Found a DIRECT SATA device\n"));
6500 }
6501
6502 /* Process for different device type */
6503 switch ( deviceType )
6504 {
6505 /* if it's PM */
6506 case SATA_PM_DEVICE:
6507 {
6508
6509 TI_DBG3(("tdsaSATAFullDiscover: Process a PM device\n"));
6510 /* For each port of the PM */
6511 for ( i = 0; i < SATA_MAX_PM_PORTS; i ++ )
6512 {
6513 /* Read the signature */
6514 /* Decode the device type */
6515 /* Create device descriptor */
6516 /* Callback with the discovered devices */
6517 }
6518 break;
6519 }
6520 /* if it's ATA device */
6521 case SATA_ATA_DEVICE:
6522 case SATA_ATAPI_DEVICE:
6523 {
6524 TI_DBG3(("tdsaSATAFullDiscover: Process an ATA device. Sending Identify Device cmd\n"));
6525
6526 /* to-check: for this direct attached one, already added and do nothing */
6527 /* no longer, discovery sends sata identify device command */
6528 //tdsaSATAIdentifyDeviceCmdSend(tiRoot, oneDeviceData);
6529 tdsaSATADiscoverDone(tiRoot, onePortContext, tiSuccess);
6530 break;
6531 }
6532 /* Other devices */
6533 default:
6534 {
6535 /* callback */
6536 TI_DBG3(("siSATAFullDiscover: Process OTHER SATA device. Just report the device\n"));
6537 break;
6538 }
6539 }
6540 }
6541 /* If port is SAS mode */
6542 else
6543 {
6544 TI_DBG3(("tdsaSATAFullDiscover: Discovering attached STP devices starts....\n"));
6545 oneDeviceData = tdsaFindRightDevice(tiRoot, onePortContext, tdsaDeviceData);
6546 tdsaDiscoveringStpSATADevice(tiRoot, onePortContext, oneDeviceData);
6547 }
6548 return ret;
6549 }
6550
6551 /* adding only direct attached SATA such as PM
6552 Other directly attached SATA device such as disk is reported by ossahwcb() in link up
6553 used in sata native mode
6554 */
6555 /*****************************************************************************
6556 *! \brief tdsaPortSATADeviceAdd
6557 *
6558 * Purpose: This function adds the SATA device to the device list.
6559 *
6560 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6561 * instance.
6562 * \param onePortContext: Pointer to the portal context instance.
6563 * \param oneSTPBridge: STP bridge.
6564 * \param Signature: SATA signature.
6565 * \param pm: Port Multiplier.
6566 * \param pmField: Port Multiplier field.
6567 * \param connectionRate: Connection Rate.
6568 *
6569 * \return:
6570 * Pointer to device data.
6571 *
6572 * \note:
6573 *
6574 *****************************************************************************/
6575 GLOBAL tdsaDeviceData_t *
tdsaPortSATADeviceAdd(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaDeviceData_t * oneSTPBridge,bit8 * Signature,bit8 pm,bit8 pmField,bit8 connectionRate,tdsaDeviceData_t * oneExpDeviceData,bit8 phyID)6576 tdsaPortSATADeviceAdd(
6577 tiRoot_t *tiRoot,
6578 tdsaPortContext_t *onePortContext,
6579 tdsaDeviceData_t *oneSTPBridge,
6580 bit8 *Signature,
6581 bit8 pm,
6582 bit8 pmField,
6583 bit8 connectionRate,
6584 tdsaDeviceData_t *oneExpDeviceData,
6585 bit8 phyID
6586 )
6587 {
6588 tdsaDeviceData_t *oneDeviceData = agNULL;
6589 agsaRoot_t *agRoot = onePortContext->agRoot;
6590 bit8 dev_s_rate = 0;
6591 bit8 sasorsata = SATA_DEVICE_TYPE;
6592 // bit8 devicetype = 0;
6593 bit8 flag = 0;
6594 bit8 TLR = 0;
6595 tdsaDeviceData_t *oneAttachedExpDeviceData = agNULL;
6596
6597 TI_DBG3(("tdsaPortSATADeviceAdd: start\n"));
6598
6599 /* sanity check */
6600 TD_ASSERT((agNULL != tiRoot), "");
6601 TD_ASSERT((agNULL != agRoot), "");
6602 TD_ASSERT((agNULL != onePortContext), "");
6603 TD_ASSERT((agNULL != Signature), "");
6604
6605 oneDeviceData = tdssNewAddSATAToSharedcontext(
6606 tiRoot,
6607 agRoot,
6608 onePortContext,
6609 agNULL,
6610 Signature,
6611 pm,
6612 pmField,
6613 connectionRate,
6614 oneExpDeviceData,
6615 phyID
6616 );
6617 if (oneDeviceData == agNULL)
6618 {
6619 TI_DBG1(("tdsaPortSATADeviceAdd: no more device!!! oneDeviceData is null\n"));
6620 return agNULL;
6621 }
6622
6623 flag = (bit8)((phyID << 4) | TLR);
6624 DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT);
6625 DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, 0xFFF);
6626 DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, 0);
6627 DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, flag);
6628
6629 /* adjusting connectionRate */
6630 oneAttachedExpDeviceData = oneDeviceData->ExpDevice;
6631 if (oneAttachedExpDeviceData != agNULL)
6632 {
6633 connectionRate = (bit8)(MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6634 TI_DBG3(("tdsaPortSATADeviceAdd: 1st connectionRate 0x%x DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n",
6635 connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)));
6636 }
6637 else
6638 {
6639 TI_DBG3(("tdsaPortSATADeviceAdd: 1st oneAttachedExpDeviceData is NULL\n"));
6640 }
6641
6642 /* Device Type, SAS or SATA, connection rate; bit7 --- bit0*/
6643 // dev_s_rate = dev_s_rate | (devicetype << 6);
6644 dev_s_rate = (bit8)(dev_s_rate | (sasorsata << 4));
6645 dev_s_rate = (bit8)(dev_s_rate | connectionRate);
6646 DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate);
6647
6648 osti_memset(&oneDeviceData->agDeviceInfo.sasAddressHi, 0, 4);
6649 osti_memset(&oneDeviceData->agDeviceInfo.sasAddressLo, 0, 4);
6650
6651 oneDeviceData->agContext.osData = oneDeviceData;
6652 oneDeviceData->agContext.sdkData = agNULL;
6653
6654 TI_DBG1(("tdsaPortSATADeviceAdd: did %d\n", oneDeviceData->id));
6655 if (oneDeviceData->registered == agFALSE)
6656 {
6657 TI_DBG2(("tdsaPortSATADeviceAdd: did %d\n", oneDeviceData->id));
6658 saRegisterNewDevice( /* tdsaPortSATADeviceAdd */
6659 onePortContext->agRoot,
6660 &oneDeviceData->agContext,
6661 tdsaRotateQnumber(tiRoot, oneDeviceData),
6662 &oneDeviceData->agDeviceInfo,
6663 onePortContext->agPortContext,
6664 0
6665 );
6666 }
6667
6668 return oneDeviceData;
6669 }
6670 #endif
6671
6672 /*****************************************************************************
6673 *! \brief tdsaFindRightDevice
6674 *
6675 * Purpose: This function returns device-to-be processed.
6676 *
6677 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6678 * instance.
6679 * \param onePortContext: Pointer to the portal context instance.
6680 * \param tdsaDeviceData: Pointer to the starting device data.
6681 *
6682 * \return:
6683 * Pointer to device data.
6684 *
6685 * \note:
6686 *
6687 *****************************************************************************/
6688 osGLOBAL tdsaDeviceData_t *
tdsaFindRightDevice(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaDeviceData_t * tdsaDeviceData)6689 tdsaFindRightDevice(
6690 tiRoot_t *tiRoot,
6691 tdsaPortContext_t *onePortContext,
6692 tdsaDeviceData_t *tdsaDeviceData
6693 )
6694 {
6695 tdList_t *DeviceListList;
6696 tdsaDeviceData_t *oneDeviceData = agNULL;
6697 bit32 found = agFALSE;
6698
6699 TI_DBG3(("tdsaFindHeadDevice: start\n"));
6700
6701 DeviceListList = tdsaDeviceData->MainLink.flink;
6702
6703 while (DeviceListList != &(tdsaDeviceData->MainLink))
6704 {
6705 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6706 TI_DBG3(("tdsaFindRightDevice: did %d STP %d SATA %d \n", onePortContext->id, DEVICE_IS_STP_TARGET(oneDeviceData), DEVICE_IS_SATA_DEVICE(oneDeviceData)));
6707 DeviceListList = DeviceListList->flink;
6708 }
6709
6710 DeviceListList = tdsaDeviceData->MainLink.flink;
6711
6712 while (DeviceListList != &(tdsaDeviceData->MainLink))
6713 {
6714 oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6715 if ((oneDeviceData->registered == agTRUE) &&
6716 (oneDeviceData->tdPortContext == onePortContext) &&
6717 (oneDeviceData->processed == agFALSE) &&
6718 (SA_IDFRM_IS_STP_TARGET(&oneDeviceData->sasIdentify) ||
6719 SA_IDFRM_IS_SATA_DEVICE(&oneDeviceData->sasIdentify))
6720 )
6721 {
6722 TI_DBG3(("tdsaFindRightDevice: pid %d did %d\n", onePortContext->id, oneDeviceData->id));
6723 oneDeviceData->processed = agTRUE;
6724 found = agTRUE;
6725 break;
6726 }
6727 DeviceListList = DeviceListList->flink;
6728 }
6729
6730 if (found == agTRUE)
6731 {
6732 return oneDeviceData;
6733 }
6734 else
6735 {
6736 return agNULL;
6737 }
6738 }
6739
6740
6741
6742 // tdsaDeviceData is head of list
6743 /*****************************************************************************
6744 *! \brief tdsaDiscoveringStpSATADevice
6745 *
6746 * Purpose: For each device in the device list, this function peforms
6747 * SATA discovery.
6748 *
6749 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6750 * instance.
6751 * \param onePortContext: Pointer to the portal context instance.
6752 * \param oneDeviceData: Pointer to the heade of device list.
6753 *
6754 * \return:
6755 * None
6756 *
6757 * \note:
6758 *
6759 *****************************************************************************/
6760 osGLOBAL void
tdsaDiscoveringStpSATADevice(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaDeviceData_t * oneDeviceData)6761 tdsaDiscoveringStpSATADevice(
6762 tiRoot_t *tiRoot,
6763 tdsaPortContext_t *onePortContext,
6764 tdsaDeviceData_t *oneDeviceData
6765 )
6766 {
6767 bit32 status;
6768 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
6769 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
6770 // tdsaDeviceData_t *tdsaDeviceData = (tdsaDeviceData_t *)tdsaAllShared->DeviceMem;
6771 tdsaDeviceData_t *tdsaDeviceData;
6772 tdList_t *DeviceListList;
6773
6774 TI_DBG3(("tdsaDiscoveringStpSATADevice: start\n"));
6775
6776 DeviceListList = tdsaAllShared->MainDeviceList.flink;
6777 tdsaDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6778
6779 if (oneDeviceData)
6780 {
6781 TI_DBG3(("tdsaDiscoveringStpSATADevice: Found STP-SATA Device=%p\n", oneDeviceData));
6782 if ((SA_IDFRM_IS_SATA_DEVICE(&oneDeviceData->sasIdentify) || SA_IDFRM_IS_STP_TARGET(&oneDeviceData->sasIdentify))
6783 &&
6784 ((onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_FULL_START &&
6785 oneDeviceData->valid == agTRUE) ||
6786 (onePortContext->discovery.type == TDSA_DISCOVERY_OPTION_INCREMENTAL_START &&
6787 oneDeviceData->valid2 == agTRUE)) &&
6788 (oneDeviceData->tdPortContext == onePortContext)
6789 )
6790 {
6791 /* if found an STP bridges */
6792 /* in order to get sata signature and etc */
6793 TI_DBG3(("tdsaDiscoveringStpSATADevice: sending report phy sata\n"));
6794 tdsaReportPhySataSend(tiRoot, oneDeviceData, oneDeviceData->sasIdentify.phyIdentifier);
6795 //send ID in every discovery? No
6796 if (oneDeviceData->satDevData.IDDeviceValid == agFALSE)
6797 {
6798 TI_DBG3(("tdsaDiscoveringStpSATADevice: sending identify device data\n"));
6799 /* all internal */
6800 status = tdsaDiscoveryStartIDDev(tiRoot,
6801 agNULL,
6802 &(oneDeviceData->tiDeviceHandle),
6803 agNULL,
6804 oneDeviceData);
6805
6806 if (status != tiSuccess)
6807 {
6808 /* identify device data is not valid */
6809 TI_DBG1(("tdsaDiscoveringStpSATADevice: fail or busy %d\n", status));
6810 oneDeviceData->satDevData.IDDeviceValid = agFALSE;
6811 }
6812 }
6813 }
6814 else
6815 {
6816 TI_DBG2(("tdsaDiscoveringStpSATADevice: moving to the next\n"));
6817 oneDeviceData = tdsaFindRightDevice(tiRoot, onePortContext, tdsaDeviceData);
6818 tdsaDiscoveringStpSATADevice(tiRoot, onePortContext, oneDeviceData);
6819 }
6820 }
6821 else
6822 {
6823 /* otherwise, there is no more SATA device found */
6824 TI_DBG3(("tdsaDiscoveringStpSATADevice: No More Device; SATA discovery finished\n"));
6825
6826 tdsaSATADiscoverDone(tiRoot, onePortContext, tiSuccess);
6827 }
6828
6829 return;
6830 }
6831
6832 /*****************************************************************************
6833 *! \brief tdsaSASIncrementalDiscover
6834 *
6835 * Purpose: This function is called to trigger incremental SAS topology discovery
6836 * within a portcontext.
6837 *
6838 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6839 * instance.
6840 * \param onePortContext: Pointer to the portal context instance.
6841 *
6842 * \return:
6843 * tiSuccess Discovery initiated.
6844 * tiError Discovery could not be initiated at this time.
6845 *
6846 * \note:
6847 *
6848 *****************************************************************************/
6849 osGLOBAL bit32
tdsaSASIncrementalDiscover(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext)6850 tdsaSASIncrementalDiscover(
6851 tiRoot_t *tiRoot,
6852 tdsaPortContext_t *onePortContext
6853 )
6854 {
6855 tdsaDeviceData_t *oneDeviceData = agNULL;
6856 int i,j;
6857 bit8 portMaxRate;
6858
6859 TI_DBG3(("tdsaSASIncrementalDiscover: start\n"));
6860
6861 if (onePortContext->valid == agFALSE)
6862 {
6863 TI_DBG1(("tdsaSASIncrementalDiscover: aborting discovery\n"));
6864 tdsaSASDiscoverAbort(tiRoot, onePortContext);
6865 return tiError;
6866 }
6867
6868 onePortContext->DiscoveryState = ITD_DSTATE_STARTED;
6869
6870 /* nativeSATAMode is set in ossaHwCB() in link up */
6871 if (onePortContext->nativeSATAMode == agFALSE) /* default: SAS and SAS/SATA mode */
6872 {
6873 if (SA_IDFRM_GET_DEVICETTYPE(&onePortContext->sasIDframe) == SAS_END_DEVICE &&
6874 SA_IDFRM_IS_SSP_TARGET(&onePortContext->sasIDframe) )
6875 {
6876 for(i=0;i<TD_MAX_NUM_PHYS;i++)
6877 {
6878 if (onePortContext->PhyIDList[i] == agTRUE)
6879 {
6880
6881 for (j=0;j<TD_MAX_NUM_NOTIFY_SPINUP;j++)
6882 {
6883 saLocalPhyControl(onePortContext->agRoot, agNULL, tdsaRotateQnumber(tiRoot, agNULL), i, AGSA_PHY_NOTIFY_ENABLE_SPINUP, agNULL);
6884 }
6885 break;
6886 }
6887 }
6888 }
6889 /*
6890 add the device
6891 1. add device in TD layer
6892 2. call saRegisterNewDevice
6893 3. update agDevHandle in ossaDeviceRegistrationCB()
6894 */
6895 portMaxRate = onePortContext->LinkRate;
6896 oneDeviceData = tdsaPortSASDeviceAdd(
6897 tiRoot,
6898 onePortContext,
6899 onePortContext->sasIDframe,
6900 agFALSE,
6901 portMaxRate,
6902 IT_NEXUS_TIMEOUT,
6903 0,
6904 SAS_DEVICE_TYPE,
6905 agNULL,
6906 0xFF
6907 );
6908 if (oneDeviceData)
6909 {
6910 if (oneDeviceData->registered == agFALSE)
6911 {
6912 /*
6913 set the timer and wait till the device(directly attached. eg Expander) to be registered.
6914 Then, in tdsaDeviceRegistrationTimerCB(), tdsaSASUpStreamDiscoverStart() is called
6915 */
6916 tdsaDeviceRegistrationTimer(tiRoot, onePortContext, oneDeviceData);
6917 }
6918 else
6919 {
6920 tdsaSASUpStreamDiscoverStart(tiRoot, onePortContext, oneDeviceData);
6921 }
6922 }
6923 }
6924 else /* SATAOnlyMode*/
6925 {
6926 tdsaSASDiscoverDone(tiRoot, onePortContext, tiSuccess);
6927 }
6928 return tiSuccess;
6929 }
6930
6931 #ifdef SATA_ENABLE
6932 /* For the sake of completness; this is the same as tdsaSATAFullDiscover*/
6933 /*****************************************************************************
6934 *! \brief tdsaSATAIncrementalDiscover
6935 *
6936 * Purpose: This function is called to trigger incremental SATA topology discovery
6937 * within a portcontext.
6938 *
6939 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
6940 * instance.
6941 * \param onePortContext: Pointer to the portal context instance.
6942 *
6943 * \return:
6944 * tiSuccess Discovery initiated.
6945 * tiError Discovery could not be initiated at this time.
6946 *
6947 * \note:
6948 *
6949 *****************************************************************************/
6950 osGLOBAL bit32
tdsaSATAIncrementalDiscover(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext)6951 tdsaSATAIncrementalDiscover(
6952 tiRoot_t *tiRoot,
6953 tdsaPortContext_t *onePortContext
6954 )
6955 {
6956 bit32 ret = tiSuccess;
6957 tdsaDeviceData_t *oneDeviceData = agNULL;
6958 bit32 deviceType;
6959 bit8 phyRate = SAS_CONNECTION_RATE_3_0G;
6960 bit32 i;
6961 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
6962 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
6963 // tdsaDeviceData_t *tdsaDeviceData = (tdsaDeviceData_t *)tdsaAllShared->DeviceMem;
6964 tdsaDeviceData_t *tdsaDeviceData;
6965 tdList_t *DeviceListList;
6966
6967 TI_DBG3(("tdsaSATAIncrementalDiscover: start\n"));
6968
6969 if (onePortContext->valid == agFALSE)
6970 {
6971 TI_DBG1(("tdsaSATAIncrementalDiscover: aborting discovery\n"));
6972 tdsaSASDiscoverAbort(tiRoot, onePortContext);
6973 return tiError;
6974 }
6975
6976 DeviceListList = tdsaAllShared->MainDeviceList.flink;
6977 tdsaDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
6978
6979 /* If port is SATA mode */
6980 /*
6981 Native SATA mode is decided in ossaHWCB() SAS_LINK_UP or SATA_LINK_UP
6982 */
6983 if (onePortContext->nativeSATAMode == agTRUE)
6984 {
6985 /* Decode device type */
6986 deviceType = tdssSATADeviceTypeDecode(onePortContext->remoteSignature);
6987 /* Create a device descriptor for the SATA device attached to the port */
6988 if ( deviceType == SATA_PM_DEVICE)
6989 {
6990 TI_DBG3(("tdsaSATAIncrementalDiscover: Found a PM device\n"));
6991 oneDeviceData = tdsaPortSATADeviceAdd(
6992 tiRoot,
6993 onePortContext,
6994 agNULL,
6995 onePortContext->remoteSignature,
6996 agTRUE,
6997 0xF,
6998 phyRate,
6999 agNULL,
7000 0xFF);
7001 }
7002 else
7003 {
7004 /* already added in ossahwcb() in SATA link up */
7005 TI_DBG3(("tdsaSATAIncrementalDiscover: Found a DIRECT SATA device\n"));
7006 }
7007
7008 /* Process for different device type */
7009 switch ( deviceType )
7010 {
7011 /* if it's PM */
7012 case SATA_PM_DEVICE:
7013 {
7014
7015 TI_DBG3(("tdsaSATAIncrementalDiscover: Process a PM device\n"));
7016 /* For each port of the PM */
7017 for ( i = 0; i < SATA_MAX_PM_PORTS; i ++ )
7018 {
7019 /* Read the signature */
7020 /* Decode the device type */
7021 /* Create device descriptor */
7022 /* Callback with the discovered devices */
7023 }
7024 break;
7025 }
7026 /* if it's ATA device */
7027 case SATA_ATA_DEVICE:
7028 case SATA_ATAPI_DEVICE:
7029 {
7030 TI_DBG3(("tdsaSATAIncrementalDiscover: Process an ATA device. Sending Identify Device cmd\n"));
7031
7032 /* to-check: for this direct attached one, already added and do nothing */
7033 /* no longer, discovery sends sata identify device command */
7034 //tdsaSATAIdentifyDeviceCmdSend(tiRoot, oneDeviceData);
7035
7036 tdsaSATADiscoverDone(tiRoot, onePortContext, tiSuccess);
7037
7038 break;
7039 }
7040 /* Other devices */
7041 default:
7042 {
7043 /* callback */
7044 TI_DBG3(("siSATAIncrementalDiscover: Process OTHER SATA device. Just report the device\n"));
7045
7046 break;
7047 }
7048 }
7049 }
7050 /* If port is SAS mode */
7051 else
7052 {
7053 TI_DBG3(("tdsaSATAIncrementalDiscover: Discovering attached STP devices starts....\n"));
7054 oneDeviceData = tdsaFindRightDevice(tiRoot, onePortContext, tdsaDeviceData);
7055
7056 tdsaDiscoveringStpSATADevice(tiRoot, onePortContext, oneDeviceData);
7057 }
7058 return ret;
7059
7060 }
7061 #endif
7062
7063
7064 /******************** SMP *******************************/
7065
7066 /*****************************************************************************
7067 *! \brief tdSMPStart
7068 *
7069 * Purpose: This function sends SMP request.
7070 *
7071 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7072 * instance.
7073 * \param agRoot: Pointer to chip/driver Instance.
7074 * \param oneDeviceData: Pointer to the device data.
7075 * \param functionCode: SMP function code.
7076 * \param pSmpBody: Pointer to SMP payload.
7077 * \param smpBodySize: Size of SMP request without SMP header.
7078 * \param agRequestType: SPC-specfic request type
7079 *
7080 * \return:
7081 * tiSuccess SMP is sent successfully
7082 * tiError SMP is not sent successfully
7083 *
7084 * \note:
7085 *
7086 *****************************************************************************/
7087 osGLOBAL bit32
tdSMPStart(tiRoot_t * tiRoot,agsaRoot_t * agRoot,tdsaDeviceData_t * oneDeviceData,bit32 functionCode,bit8 * pSmpBody,bit32 smpBodySize,bit32 agRequestType,tiIORequest_t * CurrentTaskTag,bit32 queueNumber)7088 tdSMPStart(
7089 tiRoot_t *tiRoot,
7090 agsaRoot_t *agRoot,
7091 tdsaDeviceData_t *oneDeviceData,
7092 bit32 functionCode,
7093 bit8 *pSmpBody, /* smp payload itself w/o first 4 bytes(header) */
7094 bit32 smpBodySize, /* smp payload size w/o first 4 bytes(header) */
7095 bit32 agRequestType,
7096 tiIORequest_t *CurrentTaskTag,
7097 bit32 queueNumber
7098 )
7099 {
7100 void *osMemHandle;
7101 bit32 PhysUpper32;
7102 bit32 PhysLower32;
7103 bit32 memAllocStatus;
7104 bit32 expectedRspLen = 0;
7105
7106 #ifdef REMOVED
7107 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
7108 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared);
7109 #endif
7110 tdssSMPRequestBody_t *tdSMPRequestBody;
7111 agsaSASRequestBody_t *agSASRequestBody;
7112 agsaSMPFrame_t *agSMPFrame;
7113 agsaIORequest_t *agIORequest;
7114 agsaDevHandle_t *agDevHandle;
7115 tdssSMPFrameHeader_t tdSMPFrameHeader;
7116 tdsaPortContext_t *onePortContext = agNULL;
7117 bit32 status;
7118
7119 #ifndef DIRECT_SMP
7120 void *IndirectSMPReqosMemHandle;
7121 bit32 IndirectSMPReqPhysUpper32;
7122 bit32 IndirectSMPReqPhysLower32;
7123 bit32 IndirectSMPReqmemAllocStatus;
7124 bit8 *IndirectSMPReq;
7125
7126 void *IndirectSMPResposMemHandle;
7127 bit32 IndirectSMPRespPhysUpper32;
7128 bit32 IndirectSMPRespPhysLower32;
7129 bit32 IndirectSMPRespmemAllocStatus;
7130 bit8 *IndirectSMPResp;
7131 #endif
7132
7133 TI_DBG3(("tdSMPStart: start\n"));
7134 TI_DBG3(("tdSMPStart: oneDeviceData %p\n", oneDeviceData));
7135 TI_DBG3(("tdSMPStart: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify)));
7136 TI_DBG3(("tdSMPStart: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify)));
7137 TI_DBG3(("tdSMPStart: 2nd sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
7138 TI_DBG3(("tdSMPStart: 2nd sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
7139
7140 onePortContext = oneDeviceData->tdPortContext;
7141
7142 if (onePortContext != agNULL)
7143 {
7144 TI_DBG3(("tdSMPStart: pid %d\n", onePortContext->id));
7145 /* increment the number of pending SMP */
7146 onePortContext->discovery.pendingSMP++;
7147 }
7148 else
7149 {
7150 TI_DBG1(("tdSMPStart: Wrong!!! onePortContext is NULL\n"));
7151 return tiError;
7152 }
7153
7154
7155
7156 memAllocStatus = ostiAllocMemory(
7157 tiRoot,
7158 &osMemHandle,
7159 (void **)&tdSMPRequestBody,
7160 &PhysUpper32,
7161 &PhysLower32,
7162 8,
7163 sizeof(tdssSMPRequestBody_t),
7164 agTRUE
7165 );
7166
7167 if (memAllocStatus != tiSuccess)
7168 {
7169 TI_DBG1(("tdSMPStart: ostiAllocMemory failed...\n"));
7170 return tiError;
7171 }
7172
7173 if (tdSMPRequestBody == agNULL)
7174 {
7175 TI_DBG1(("tdSMPStart: ostiAllocMemory returned NULL tdSMPRequestBody\n"));
7176 return tiError;
7177 }
7178 /* saves mem handle for freeing later */
7179 tdSMPRequestBody->osMemHandle = osMemHandle;
7180
7181 /* saves tdsaDeviceData */
7182 tdSMPRequestBody->tdDevice = oneDeviceData;
7183
7184 /* saving port id */
7185 tdSMPRequestBody->tdPortContext = onePortContext;
7186
7187
7188 agDevHandle = oneDeviceData->agDevHandle;
7189
7190 /* save the callback funtion */
7191 tdSMPRequestBody->SMPCompletionFunc = itdssSMPCompleted; /* in itdcb.c */
7192
7193 /* for simulate warm target reset */
7194 tdSMPRequestBody->CurrentTaskTag = CurrentTaskTag;
7195
7196 /* initializes the number of SMP retries */
7197 tdSMPRequestBody->retries = 0;
7198
7199 #ifdef TD_INTERNAL_DEBUG /* debugging */
7200 TI_DBG4(("tdSMPStart: SMPRequestbody %p\n", tdSMPRequestBody));
7201 TI_DBG4(("tdSMPStart: callback fn %p\n", tdSMPRequestBody->SMPCompletionFunc));
7202 #endif
7203
7204 agIORequest = &(tdSMPRequestBody->agIORequest);
7205 agIORequest->osData = (void *) tdSMPRequestBody;
7206 agIORequest->sdkData = agNULL; /* SALL takes care of this */
7207
7208
7209 agSASRequestBody = &(tdSMPRequestBody->agSASRequestBody);
7210 agSMPFrame = &(agSASRequestBody->smpFrame);
7211
7212 TI_DBG3(("tdSMPStart: agIORequest %p\n", agIORequest));
7213 TI_DBG3(("tdSMPStart: SMPRequestbody %p\n", tdSMPRequestBody));
7214
7215 /*
7216 depending on functionCode, set expectedRspLen in smp
7217 */
7218 switch (functionCode)
7219 {
7220 case SMP_REPORT_GENERAL:
7221 expectedRspLen = sizeof(smpRespReportGeneral_t) + 4;
7222 break;
7223 case SMP_REPORT_MANUFACTURE_INFORMATION:
7224 expectedRspLen = sizeof(smpRespReportManufactureInfo_t) + 4;
7225 break;
7226 case SMP_DISCOVER:
7227 expectedRspLen = sizeof(smpRespDiscover_t) + 4;
7228 break;
7229 case SMP_REPORT_PHY_ERROR_LOG:
7230 expectedRspLen = 32 - 4;
7231 break;
7232 case SMP_REPORT_PHY_SATA:
7233 expectedRspLen = sizeof(smpRespReportPhySata_t) + 4;
7234 break;
7235 case SMP_REPORT_ROUTING_INFORMATION:
7236 expectedRspLen = sizeof(smpRespReportRouteTable_t) + 4;
7237 break;
7238 case SMP_CONFIGURE_ROUTING_INFORMATION:
7239 expectedRspLen = 4;
7240 break;
7241 case SMP_PHY_CONTROL:
7242 expectedRspLen = 4;
7243 break;
7244 case SMP_PHY_TEST_FUNCTION:
7245 expectedRspLen = 4;
7246 break;
7247 case SMP_PMC_SPECIFIC:
7248 expectedRspLen = 4;
7249 break;
7250 default:
7251 expectedRspLen = 0;
7252 TI_DBG1(("tdSMPStart: error!!! undefined or unused smp function code 0x%x\n", functionCode));
7253 return tiError;
7254 }
7255
7256 if (tiIS_SPC(agRoot))
7257 {
7258 #ifdef DIRECT_SMP /* direct SMP with 48 or less payload */
7259 if ( (smpBodySize + 4) <= SMP_DIRECT_PAYLOAD_LIMIT) /* 48 */
7260 {
7261 TI_DBG3(("tdSMPStart: DIRECT smp payload\n"));
7262 osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t));
7263 osti_memset(tdSMPRequestBody->smpPayload, 0, SMP_DIRECT_PAYLOAD_LIMIT);
7264
7265 /* SMP header */
7266 tdSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
7267 tdSMPFrameHeader.smpFunction = (bit8)functionCode;
7268 tdSMPFrameHeader.smpFunctionResult = 0;
7269 tdSMPFrameHeader.smpReserved = 0;
7270
7271 osti_memcpy(tdSMPRequestBody->smpPayload, &tdSMPFrameHeader, 4);
7272 // osti_memcpy((tdSMPRequestBody->smpPayload)+4, pSmpBody, smpBodySize);
7273 osti_memcpy(&(tdSMPRequestBody->smpPayload[4]), pSmpBody, smpBodySize);
7274
7275 /* direct SMP payload eg) REPORT_GENERAL, DISCOVER etc */
7276 agSMPFrame->outFrameBuf = tdSMPRequestBody->smpPayload;
7277 agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */
7278 /* to specify DIRECT SMP response */
7279 agSMPFrame->inFrameLen = 0;
7280
7281 /* temporary solution for T2D Combo*/
7282 #if defined (INITIATOR_DRIVER) && defined (TARGET_DRIVER)
7283 /* force smp repsonse to be direct */
7284 agSMPFrame->expectedRespLen = 0;
7285 #else
7286 agSMPFrame->expectedRespLen = expectedRspLen;
7287 #endif
7288 // tdhexdump("tdSMPStart", (bit8*)agSMPFrame->outFrameBuf, agSMPFrame->outFrameLen);
7289 // tdhexdump("tdSMPStart new", (bit8*)tdSMPRequestBody->smpPayload, agSMPFrame->outFrameLen);
7290 // tdhexdump("tdSMPStart - tdSMPRequestBody", (bit8*)tdSMPRequestBody, sizeof(tdssSMPRequestBody_t));
7291 }
7292 else
7293 {
7294 TI_DBG3(("tdSMPStart: INDIRECT smp payload\n"));
7295 }
7296
7297 #else
7298
7299 /* indirect SMP */
7300 /* allocate Direct SMP request payload */
7301 IndirectSMPReqmemAllocStatus = ostiAllocMemory(
7302 tiRoot,
7303 &IndirectSMPReqosMemHandle,
7304 (void **)&IndirectSMPReq,
7305 &IndirectSMPReqPhysUpper32,
7306 &IndirectSMPReqPhysLower32,
7307 8,
7308 smpBodySize + 4,
7309 agFALSE
7310 );
7311
7312 if (IndirectSMPReqmemAllocStatus != tiSuccess)
7313 {
7314 TI_DBG1(("tdSMPStart: ostiAllocMemory failed for indirect SMP request...\n"));
7315 return tiError;
7316 }
7317
7318 if (IndirectSMPReq == agNULL)
7319 {
7320 TI_DBG1(("tdSMPStart: ostiAllocMemory returned NULL IndirectSMPReq\n"));
7321 return tiError;
7322 }
7323
7324 /* allocate indirect SMP response payload */
7325 IndirectSMPRespmemAllocStatus = ostiAllocMemory(
7326 tiRoot,
7327 &IndirectSMPResposMemHandle,
7328 (void **)&IndirectSMPResp,
7329 &IndirectSMPRespPhysUpper32,
7330 &IndirectSMPRespPhysLower32,
7331 8,
7332 expectedRspLen,
7333 agFALSE
7334 );
7335
7336 if (IndirectSMPRespmemAllocStatus != tiSuccess)
7337 {
7338 TI_DBG1(("tdSMPStart: ostiAllocMemory failed for indirect SMP reponse...\n"));
7339 return tiError;
7340 }
7341
7342 if (IndirectSMPResp == agNULL)
7343 {
7344 TI_DBG1(("tdSMPStart: ostiAllocMemory returned NULL IndirectSMPResp\n"));
7345 return tiError;
7346 }
7347
7348 /* saves mem handle for freeing later */
7349 tdSMPRequestBody->IndirectSMPReqosMemHandle = IndirectSMPReqosMemHandle;
7350 tdSMPRequestBody->IndirectSMPResposMemHandle = IndirectSMPResposMemHandle;
7351
7352 /* saves Indirect SMP request/repsonse pointer and length for free them later */
7353 tdSMPRequestBody->IndirectSMPReq = IndirectSMPReq;
7354 tdSMPRequestBody->IndirectSMPResp = IndirectSMPResp;
7355 tdSMPRequestBody->IndirectSMPReqLen = smpBodySize + 4;
7356 tdSMPRequestBody->IndirectSMPRespLen = expectedRspLen;
7357
7358 /* fill in indirect SMP request fields */
7359 TI_DBG3(("tdSMPStart: INDIRECT smp payload\n"));
7360
7361 /* SMP request and response initialization */
7362 osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t));
7363 osti_memset(IndirectSMPReq, 0, smpBodySize + 4);
7364 osti_memset(IndirectSMPResp, 0, expectedRspLen);
7365
7366 /* SMP request header */
7367 tdSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
7368 tdSMPFrameHeader.smpFunction = (bit8)functionCode;
7369 tdSMPFrameHeader.smpFunctionResult = 0;
7370 tdSMPFrameHeader.smpReserved = 0;
7371
7372 osti_memcpy(IndirectSMPReq, &tdSMPFrameHeader, 4);
7373 osti_memcpy(IndirectSMPReq+4, pSmpBody, smpBodySize);
7374
7375 /* Indirect SMP request */
7376 agSMPFrame->outFrameBuf = agNULL;
7377 agSMPFrame->outFrameAddrUpper32 = IndirectSMPReqPhysUpper32;
7378 agSMPFrame->outFrameAddrLower32 = IndirectSMPReqPhysLower32;
7379 agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */
7380
7381 /* Indirect SMP response */
7382 agSMPFrame->expectedRespLen = expectedRspLen;
7383 agSMPFrame->inFrameLen = expectedRspLen; /* without last 4 byte crc */
7384 agSMPFrame->inFrameAddrUpper32 = IndirectSMPRespPhysUpper32;
7385 agSMPFrame->inFrameAddrLower32 = IndirectSMPRespPhysLower32;
7386 #endif
7387 }
7388 else /* SPCv controller */
7389 {
7390 /* only direct mode for both request and response */
7391 TI_DBG3(("tdSMPStart: DIRECT smp payload\n"));
7392 agSMPFrame->flag = 0;
7393 osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t));
7394 osti_memset(tdSMPRequestBody->smpPayload, 0, SMP_DIRECT_PAYLOAD_LIMIT);
7395
7396 /* SMP header */
7397 tdSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
7398 tdSMPFrameHeader.smpFunction = (bit8)functionCode;
7399 tdSMPFrameHeader.smpFunctionResult = 0;
7400 tdSMPFrameHeader.smpReserved = 0;
7401
7402 osti_memcpy(tdSMPRequestBody->smpPayload, &tdSMPFrameHeader, 4);
7403 // osti_memcpy((tdSMPRequestBody->smpPayload)+4, pSmpBody, smpBodySize);
7404 osti_memcpy(&(tdSMPRequestBody->smpPayload[4]), pSmpBody, smpBodySize);
7405
7406 /* direct SMP payload eg) REPORT_GENERAL, DISCOVER etc */
7407 agSMPFrame->outFrameBuf = tdSMPRequestBody->smpPayload;
7408 agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */
7409 /* to specify DIRECT SMP response */
7410 agSMPFrame->inFrameLen = 0;
7411
7412 /* temporary solution for T2D Combo*/
7413 #if defined (INITIATOR_DRIVER) && defined (TARGET_DRIVER)
7414 /* force smp repsonse to be direct */
7415 agSMPFrame->expectedRespLen = 0;
7416 #else
7417 agSMPFrame->expectedRespLen = expectedRspLen;
7418 #endif
7419 // tdhexdump("tdSMPStart", (bit8*)agSMPFrame->outFrameBuf, agSMPFrame->outFrameLen);
7420 // tdhexdump("tdSMPStart new", (bit8*)tdSMPRequestBody->smpPayload, agSMPFrame->outFrameLen);
7421 // tdhexdump("tdSMPStart - tdSMPRequestBody", (bit8*)tdSMPRequestBody, sizeof(tdssSMPRequestBody_t));
7422 }
7423
7424
7425 if (agDevHandle == agNULL)
7426 {
7427 TI_DBG1(("tdSMPStart: !!! agDevHandle is NULL !!! \n"));
7428 return tiError;
7429 }
7430
7431 tdSMPRequestBody->queueNumber = queueNumber;
7432 status = saSMPStart(
7433 agRoot,
7434 agIORequest,
7435 queueNumber, //tdsaAllShared->SMPQNum, //tdsaRotateQnumber(tiRoot, oneDeviceData),
7436 agDevHandle,
7437 agRequestType,
7438 agSASRequestBody,
7439 &ossaSMPCompleted
7440 );
7441
7442 if (status == AGSA_RC_SUCCESS)
7443 {
7444 /* start SMP timer */
7445 if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER ||
7446 functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION
7447 )
7448 {
7449 tdsaDiscoverySMPTimer(tiRoot, onePortContext, functionCode, tdSMPRequestBody);
7450 }
7451 return tiSuccess;
7452 }
7453 else if (status == AGSA_RC_BUSY)
7454 {
7455 /* set timer */
7456 if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER ||
7457 functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION)
7458 {
7459 /* only for discovery related SMPs*/
7460 tdsaSMPBusyTimer(tiRoot, onePortContext, oneDeviceData, tdSMPRequestBody);
7461 return tiSuccess;
7462 }
7463 else if (functionCode == SMP_PHY_CONTROL)
7464 {
7465 ostiFreeMemory(
7466 tiRoot,
7467 osMemHandle,
7468 sizeof(tdssSMPRequestBody_t)
7469 );
7470 return tiBusy;
7471 }
7472 else
7473 {
7474 ostiFreeMemory(
7475 tiRoot,
7476 osMemHandle,
7477 sizeof(tdssSMPRequestBody_t)
7478 );
7479 return tiBusy;
7480 }
7481 }
7482 else /* AGSA_RC_FAILURE */
7483 {
7484 /* discovery failure or task management failure */
7485 if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER ||
7486 functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION)
7487 {
7488 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
7489 }
7490 ostiFreeMemory(
7491 tiRoot,
7492 osMemHandle,
7493 sizeof(tdssSMPRequestBody_t)
7494 );
7495
7496 return tiError;
7497 }
7498 }
7499
7500 #ifdef REMOVED
7501 /*****************************************************************************
7502 *! \brief tdsaFindLocalLinkRate
7503 *
7504 * Purpose: This function finds local link rate.
7505 *
7506 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7507 * instance.
7508 * \param tdsaPortStartInfo: Pointer to the port start information.
7509 *
7510 * \return:
7511 * None
7512 *
7513 * \note:
7514 *
7515 *****************************************************************************/
7516 osGLOBAL bit8
tdsaFindLocalLinkRate(tiRoot_t * tiRoot,tdsaPortStartInfo_t * tdsaPortStartInfo)7517 tdsaFindLocalLinkRate(
7518 tiRoot_t *tiRoot,
7519 tdsaPortStartInfo_t *tdsaPortStartInfo
7520 )
7521 {
7522 bit8 ans = SAS_CONNECTION_RATE_3_0G; /* default */
7523 bit32 phyProperties;
7524
7525 phyProperties = tdsaPortStartInfo->agPhyConfig.phyProperties;
7526
7527 TI_DBG3(("tdsaFindLocalLinkRate: start\n"));
7528 if (phyProperties & 0x4)
7529 {
7530 ans = SAS_CONNECTION_RATE_6_0G;
7531 }
7532 if (phyProperties & 0x2)
7533 {
7534 ans = SAS_CONNECTION_RATE_3_0G;
7535 }
7536 if (phyProperties & 0x1)
7537 {
7538 ans = SAS_CONNECTION_RATE_1_5G;
7539 }
7540 TI_DBG3(("tdsaFindLocalLinkRate: ans 0x%x\n", ans));
7541 return ans;
7542 }
7543 #endif
7544 /*****************************************************************************
7545 *! \brief tdsaConfigureRouteTimer
7546 *
7547 * Purpose: This function sets timers for configuring routing of discovery and
7548 * its callback function.
7549 *
7550 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7551 * instance.
7552 * \param onePortContext: Pointer to the portal context instance.
7553 * \param oneExpander: Pointer to the expander.
7554 * \param ptdSMPDiscoverResp: Pointer to SMP discover repsonse data.
7555 *
7556 * \return:
7557 * None
7558 *
7559 * \note: called by tdsaDiscoverRespRcvd()
7560 *
7561 *****************************************************************************/
7562 osGLOBAL void
tdsaConfigureRouteTimer(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaExpander_t * oneExpander,smpRespDiscover_t * ptdSMPDiscoverResp)7563 tdsaConfigureRouteTimer(tiRoot_t *tiRoot,
7564 tdsaPortContext_t *onePortContext,
7565 tdsaExpander_t *oneExpander,
7566 smpRespDiscover_t *ptdSMPDiscoverResp
7567 )
7568 {
7569 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
7570 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
7571 itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
7572 tdsaDiscovery_t *discovery;
7573
7574 TI_DBG1(("tdsaConfigureRouteTimer: start\n"));
7575 TI_DBG1(("tdsaConfigureRouteTimer: pid %d\n", onePortContext->id));
7576
7577 discovery = &(onePortContext->discovery);
7578
7579 TI_DBG1(("tdsaConfigureRouteTimer: onePortContext %p oneExpander %p ptdSMPDiscoverResp %p\n", onePortContext, oneExpander, ptdSMPDiscoverResp));
7580
7581 TI_DBG1(("tdsaConfigureRouteTimer: discovery %p \n", discovery));
7582
7583 TI_DBG1(("tdsaConfigureRouteTimer: pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries));
7584
7585 TI_DBG1(("tdsaConfigureRouteTimer: discovery->status %d\n", discovery->status));
7586
7587 if (discovery->configureRouteTimer.timerRunning == agTRUE)
7588 {
7589 tdsaKillTimer(
7590 tiRoot,
7591 &discovery->configureRouteTimer
7592 );
7593 }
7594
7595 TI_DBG1(("tdsaConfigureRouteTimer: UsecsPerTick %d\n", Initiator->OperatingOption.UsecsPerTick));
7596 TI_DBG1(("tdsaConfigureRouteTimer: Timervalue %d\n", CONFIGURE_ROUTE_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick));
7597
7598 tdsaSetTimerRequest(
7599 tiRoot,
7600 &discovery->configureRouteTimer,
7601 CONFIGURE_ROUTE_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
7602 tdsaConfigureRouteTimerCB,
7603 (void *)onePortContext,
7604 (void *)oneExpander,
7605 (void *)ptdSMPDiscoverResp
7606 );
7607
7608 tdsaAddTimer (
7609 tiRoot,
7610 &Initiator->timerlist,
7611 &discovery->configureRouteTimer
7612 );
7613
7614 return;
7615 }
7616
7617 /*****************************************************************************
7618 *! \brief tdsaConfigureRouteTimerCB
7619 *
7620 * Purpose: This function is callback function for tdsaConfigureRouteTimer.
7621 *
7622 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7623 * instance.
7624 * \param timerData1: Pointer to timer-related data structure
7625 * \param timerData2: Pointer to timer-related data structure
7626 * \param timerData3: Pointer to timer-related data structure
7627 *
7628 * \return:
7629 * None
7630 *
7631 * \note:
7632 *
7633 *****************************************************************************/
7634 osGLOBAL void
tdsaConfigureRouteTimerCB(tiRoot_t * tiRoot,void * timerData1,void * timerData2,void * timerData3)7635 tdsaConfigureRouteTimerCB(
7636 tiRoot_t * tiRoot,
7637 void * timerData1,
7638 void * timerData2,
7639 void * timerData3
7640 )
7641 {
7642 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
7643 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
7644 itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
7645 tdsaPortContext_t *onePortContext;
7646 tdsaExpander_t *oneExpander;
7647 smpRespDiscover_t *ptdSMPDiscoverResp;
7648 tdsaDiscovery_t *discovery;
7649
7650 TI_DBG1(("tdsaConfigureRouteTimerCB: start\n"));
7651
7652 onePortContext = (tdsaPortContext_t *)timerData1;
7653 oneExpander = (tdsaExpander_t *)timerData2;
7654 ptdSMPDiscoverResp = (smpRespDiscover_t *)timerData3;
7655
7656 discovery = &(onePortContext->discovery);
7657
7658 TI_DBG1(("tdsaConfigureRouteTimerCB: onePortContext %p oneExpander %p ptdSMPDiscoverResp %p\n", onePortContext, oneExpander, ptdSMPDiscoverResp));
7659
7660 TI_DBG1(("tdsaConfigureRouteTimerCB: discovery %p\n", discovery));
7661
7662 TI_DBG1(("tdsaConfigureRouteTimerCB: pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries));
7663
7664 TI_DBG1(("tdsaConfigureRouteTimerCB: discovery.status %d\n", discovery->status));
7665
7666 discovery->configureRouteRetries++;
7667 if (discovery->configureRouteRetries >= DISCOVERY_RETRIES)
7668 {
7669 TI_DBG1(("tdsaConfigureRouteTimerCB: retries are over\n"));
7670 discovery->configureRouteRetries = 0;
7671 /* failed the discovery */
7672 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
7673 if (discovery->configureRouteTimer.timerRunning == agTRUE)
7674 {
7675 tdsaKillTimer(
7676 tiRoot,
7677 &discovery->configureRouteTimer
7678 );
7679 }
7680 return;
7681 }
7682
7683
7684 if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
7685 {
7686 TI_DBG1(("tdsaConfigureRouteTimerCB: proceed by calling tdsaSASDownStreamDiscoverExpanderPhy\n"));
7687 tdhexdump("tdsaConfigureRouteTimerCB", (bit8*)ptdSMPDiscoverResp, sizeof(smpRespDiscover_t));
7688 discovery->configureRouteRetries = 0;
7689
7690 tdsaSASDownStreamDiscoverExpanderPhy(tiRoot, onePortContext, oneExpander, ptdSMPDiscoverResp);
7691 }
7692 else
7693 {
7694 TI_DBG1(("tdsaConfigureRouteTimerCB: setting timer again\n"));
7695 /* set the timer again */
7696 tdsaSetTimerRequest(
7697 tiRoot,
7698 &discovery->configureRouteTimer,
7699 CONFIGURE_ROUTE_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
7700 tdsaConfigureRouteTimerCB,
7701 (void *)onePortContext,
7702 (void *)oneExpander,
7703 (void *)ptdSMPDiscoverResp
7704 );
7705
7706 tdsaAddTimer (
7707 tiRoot,
7708 &Initiator->timerlist,
7709 &discovery->configureRouteTimer
7710 );
7711 }
7712 // tdsaReportGeneralSend(tiRoot, oneDeviceData);
7713 return;
7714 }
7715
7716 /*****************************************************************************
7717 *! \brief tdsaDiscoveryTimer
7718 *
7719 * Purpose: This function sets timers for discovery and its callback
7720 * function.
7721 *
7722 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7723 * instance.
7724 * \param onePortContext: Pointer to the portal context instance.
7725 * \param oneDeviceData: Pointer to the device data.
7726 *
7727 * \return:
7728 * None
7729 *
7730 * \note:
7731 *
7732 *****************************************************************************/
7733 osGLOBAL void
tdsaDiscoveryTimer(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaDeviceData_t * oneDeviceData)7734 tdsaDiscoveryTimer(tiRoot_t *tiRoot,
7735 tdsaPortContext_t *onePortContext,
7736 tdsaDeviceData_t *oneDeviceData
7737 )
7738 {
7739 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
7740 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
7741 itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
7742 tdsaDiscovery_t *discovery;
7743
7744 TI_DBG1(("tdsaDiscoveryTimer: start\n"));
7745 TI_DBG1(("tdsaDiscoveryTimer: pid %d\n", onePortContext->id));
7746
7747 discovery = &(onePortContext->discovery);
7748
7749 if (discovery->discoveryTimer.timerRunning == agTRUE)
7750 {
7751 tdsaKillTimer(
7752 tiRoot,
7753 &discovery->discoveryTimer
7754 );
7755 }
7756
7757 TI_DBG1(("tdsaDiscoveryTimer: UsecsPerTick %d\n", Initiator->OperatingOption.UsecsPerTick));
7758 TI_DBG1(("tdsaDiscoveryTimer: Timervalue %d\n", DISCOVERY_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick));
7759
7760 tdsaSetTimerRequest(
7761 tiRoot,
7762 &discovery->discoveryTimer,
7763 DISCOVERY_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
7764 tdsaDiscoveryTimerCB,
7765 oneDeviceData,
7766 agNULL,
7767 agNULL
7768 );
7769
7770 tdsaAddTimer (
7771 tiRoot,
7772 &Initiator->timerlist,
7773 &discovery->discoveryTimer
7774 );
7775
7776 return;
7777 }
7778
7779 /*****************************************************************************
7780 *! \brief tdsaDiscoveryTimerCB
7781 *
7782 * Purpose: This function is callback function for discovery timer.
7783 *
7784 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7785 * instance.
7786 * \param timerData1: Pointer to timer-related data structure
7787 * \param timerData2: Pointer to timer-related data structure
7788 * \param timerData3: Pointer to timer-related data structure
7789 *
7790 * \return:
7791 * None
7792 *
7793 * \note:
7794 *
7795 *****************************************************************************/
7796 osGLOBAL void
tdsaDiscoveryTimerCB(tiRoot_t * tiRoot,void * timerData1,void * timerData2,void * timerData3)7797 tdsaDiscoveryTimerCB(
7798 tiRoot_t * tiRoot,
7799 void * timerData1,
7800 void * timerData2,
7801 void * timerData3
7802 )
7803 {
7804 tdsaDeviceData_t *oneDeviceData;
7805 oneDeviceData = (tdsaDeviceData_t *)timerData1;
7806
7807 TI_DBG1(("tdsaDiscoveryTimerCB: start\n"));
7808
7809 if (oneDeviceData->registered == agTRUE)
7810 {
7811 TI_DBG1(("tdsaDiscoveryTimerCB: resumes discovery\n"));
7812 tdsaReportGeneralSend(tiRoot, oneDeviceData);
7813 }
7814
7815 return;
7816 }
7817
7818 /*****************************************************************************
7819 *! \brief tdsaDeviceRegistrationTimer
7820 *
7821 * Purpose: This function sets timers for device registration in discovery
7822 *
7823 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7824 * instance.
7825 * \param onePortContext: Pointer to the portal context instance.
7826 * \param oneDeviceData: Pointer to the device data.
7827 * \return:
7828 * None
7829 *
7830 * \note: called by tdsaSASFullDiscover() or tdsaSASIncrementalDiscover()
7831 * or tdsaDeviceRegistrationTimerCB()
7832 *
7833 *****************************************************************************/
7834 osGLOBAL void
tdsaDeviceRegistrationTimer(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaDeviceData_t * oneDeviceData)7835 tdsaDeviceRegistrationTimer(tiRoot_t *tiRoot,
7836 tdsaPortContext_t *onePortContext,
7837 tdsaDeviceData_t *oneDeviceData
7838 )
7839 {
7840 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
7841 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
7842 itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
7843 tdsaDiscovery_t *discovery;
7844
7845 TI_DBG1(("tdsaDeviceRegistrationTimer: start\n"));
7846 TI_DBG1(("tdsaDeviceRegistrationTimer: pid %d\n", onePortContext->id));
7847
7848 discovery = &(onePortContext->discovery);
7849
7850 if (discovery->deviceRegistrationTimer.timerRunning == agTRUE)
7851 {
7852 tdsaKillTimer(
7853 tiRoot,
7854 &discovery->deviceRegistrationTimer
7855 );
7856 }
7857
7858 TI_DBG1(("tdsaDeviceRegistrationTimer: UsecsPerTick %d\n", Initiator->OperatingOption.UsecsPerTick));
7859 TI_DBG1(("tdsaDeviceRegistrationTimer: Timervalue %d\n", DEVICE_REGISTRATION_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick));
7860
7861 tdsaSetTimerRequest(
7862 tiRoot,
7863 &discovery->deviceRegistrationTimer,
7864 DEVICE_REGISTRATION_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
7865 tdsaDeviceRegistrationTimerCB,
7866 onePortContext,
7867 oneDeviceData,
7868 agNULL
7869 );
7870
7871 tdsaAddTimer (
7872 tiRoot,
7873 &Initiator->timerlist,
7874 &discovery->deviceRegistrationTimer
7875 );
7876 return;
7877 }
7878
7879 /*****************************************************************************
7880 *! \brief tdsaDeviceRegistrationTimerCB
7881 *
7882 * Purpose: This function is callback function for tdsaDeviceRegistrationTimer.
7883 *
7884 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7885 * instance.
7886 * \param timerData1: Pointer to timer-related data structure
7887 * \param timerData2: Pointer to timer-related data structure
7888 * \param timerData3: Pointer to timer-related data structure
7889 *
7890 * \return:
7891 * None
7892 *
7893 * \note:
7894 *
7895 *****************************************************************************/
7896 osGLOBAL void
tdsaDeviceRegistrationTimerCB(tiRoot_t * tiRoot,void * timerData1,void * timerData2,void * timerData3)7897 tdsaDeviceRegistrationTimerCB(
7898 tiRoot_t * tiRoot,
7899 void * timerData1,
7900 void * timerData2,
7901 void * timerData3
7902 )
7903 {
7904 tdsaPortContext_t *onePortContext;
7905 tdsaDeviceData_t *oneDeviceData;
7906 tdsaDiscovery_t *discovery;
7907
7908 TI_DBG1(("tdsaDeviceRegistrationTimerCB: start\n"));
7909
7910 onePortContext = (tdsaPortContext_t *)timerData1;
7911 oneDeviceData = (tdsaDeviceData_t *)timerData2;
7912 discovery = &(onePortContext->discovery);
7913
7914 if (oneDeviceData->registered == agFALSE)
7915 {
7916 discovery->deviceRetistrationRetries++;
7917 if (discovery->deviceRetistrationRetries >= DISCOVERY_RETRIES)
7918 {
7919 TI_DBG1(("tdsaDeviceRegistrationTimerCB: retries are over\n"));
7920 discovery->deviceRetistrationRetries = 0;
7921 /* failed the discovery */
7922 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
7923 if (discovery->deviceRegistrationTimer.timerRunning == agTRUE)
7924 {
7925 tdsaKillTimer(
7926 tiRoot,
7927 &discovery->deviceRegistrationTimer
7928 );
7929 }
7930 }
7931 else
7932 {
7933 TI_DBG1(("tdsaDeviceRegistrationTimerCB: keep retrying\n"));
7934 /* start timer for device registration */
7935 tdsaDeviceRegistrationTimer(tiRoot, onePortContext, oneDeviceData);
7936 }
7937 }
7938 else
7939 {
7940 /* go ahead; continue the discovery */
7941 discovery->deviceRetistrationRetries = 0;
7942 tdsaSASUpStreamDiscoverStart(tiRoot, onePortContext, oneDeviceData);
7943 }
7944 }
7945
7946 /*****************************************************************************
7947 *! \brief tdsaSMPBusyTimer
7948 *
7949 * Purpose: This function sets timers for busy of saSMPStart.
7950 *
7951 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
7952 * instance.
7953 * \param onePortContext: Pointer to the portal context instance.
7954 * \param oneDeviceData: Pointer to the device data.
7955 * \param tdSMPRequestBody: Pointer to the SMP request body.
7956 *
7957 * \return:
7958 * None
7959 *
7960 * \note:
7961 *
7962 *****************************************************************************/
7963 osGLOBAL void
tdsaSMPBusyTimer(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,tdsaDeviceData_t * oneDeviceData,tdssSMPRequestBody_t * tdSMPRequestBody)7964 tdsaSMPBusyTimer(tiRoot_t *tiRoot,
7965 tdsaPortContext_t *onePortContext,
7966 tdsaDeviceData_t *oneDeviceData,
7967 tdssSMPRequestBody_t *tdSMPRequestBody
7968 )
7969 {
7970 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
7971 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
7972 itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
7973 tdsaDiscovery_t *discovery;
7974
7975 TI_DBG1(("tdsaSMPBusyTimer: start\n"));
7976 TI_DBG1(("tdsaSMPBusyTimer: pid %d\n", onePortContext->id));
7977
7978 discovery = &(onePortContext->discovery);
7979
7980 if (discovery->SMPBusyTimer.timerRunning == agTRUE)
7981 {
7982 tdsaKillTimer(
7983 tiRoot,
7984 &discovery->SMPBusyTimer
7985 );
7986 }
7987
7988 tdsaSetTimerRequest(
7989 tiRoot,
7990 &discovery->SMPBusyTimer,
7991 SMP_BUSY_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
7992 tdsaSMPBusyTimerCB,
7993 onePortContext,
7994 oneDeviceData,
7995 tdSMPRequestBody
7996 );
7997
7998 tdsaAddTimer (
7999 tiRoot,
8000 &Initiator->timerlist,
8001 &discovery->SMPBusyTimer
8002 );
8003 return;
8004 }
8005
8006 /*****************************************************************************
8007 *! \brief tdsaSMPBusyTimerCB
8008 *
8009 * Purpose: This function is callback function for SMP busy timer.
8010 *
8011 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8012 * instance.
8013 * \param timerData1: Pointer to timer-related data structure
8014 * \param timerData2: Pointer to timer-related data structure
8015 * \param timerData3: Pointer to timer-related data structure
8016 *
8017 * \return:
8018 * None
8019 *
8020 * \note:
8021 *
8022 *****************************************************************************/
8023 osGLOBAL void
tdsaSMPBusyTimerCB(tiRoot_t * tiRoot,void * timerData1,void * timerData2,void * timerData3)8024 tdsaSMPBusyTimerCB(
8025 tiRoot_t * tiRoot,
8026 void * timerData1,
8027 void * timerData2,
8028 void * timerData3
8029 )
8030 {
8031 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
8032 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared);
8033 agsaRoot_t *agRoot;
8034 tdsaPortContext_t *onePortContext;
8035 tdsaDeviceData_t *oneDeviceData;
8036 tdssSMPRequestBody_t *tdSMPRequestBody;
8037 agsaSASRequestBody_t *agSASRequestBody;
8038 agsaIORequest_t *agIORequest;
8039 agsaDevHandle_t *agDevHandle;
8040 tdsaDiscovery_t *discovery;
8041 bit32 status = AGSA_RC_FAILURE;
8042
8043 TI_DBG1(("tdsaSMPBusyTimerCB: start\n"));
8044
8045 onePortContext = (tdsaPortContext_t *)timerData1;
8046 oneDeviceData = (tdsaDeviceData_t *)timerData2;
8047 tdSMPRequestBody = (tdssSMPRequestBody_t *)timerData3;
8048 agRoot = oneDeviceData->agRoot;
8049 agIORequest = &(tdSMPRequestBody->agIORequest);
8050 agDevHandle = oneDeviceData->agDevHandle;
8051 agSASRequestBody = &(tdSMPRequestBody->agSASRequestBody);
8052 discovery = &(onePortContext->discovery);
8053
8054 discovery->SMPRetries++;
8055
8056 if (discovery->SMPRetries < SMP_BUSY_RETRIES)
8057 {
8058 status = saSMPStart(
8059 agRoot,
8060 agIORequest,
8061 tdsaAllShared->SMPQNum, //tdsaRotateQnumber(tiRoot, oneDeviceData),
8062 agDevHandle,
8063 AGSA_SMP_INIT_REQ,
8064 agSASRequestBody,
8065 &ossaSMPCompleted
8066 );
8067 }
8068
8069 if (status == AGSA_RC_SUCCESS)
8070 {
8071 discovery->SMPRetries = 0;
8072 if (discovery->SMPBusyTimer.timerRunning == agTRUE)
8073 {
8074 tdsaKillTimer(
8075 tiRoot,
8076 &discovery->SMPBusyTimer
8077 );
8078 }
8079 }
8080 else if (status == AGSA_RC_FAILURE)
8081 {
8082 discovery->SMPRetries = 0;
8083 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
8084 if (discovery->SMPBusyTimer.timerRunning == agTRUE)
8085 {
8086 tdsaKillTimer(
8087 tiRoot,
8088 &discovery->SMPBusyTimer
8089 );
8090 }
8091 }
8092 else /* AGSA_RC_BUSY */
8093 {
8094 if (discovery->SMPRetries >= SMP_BUSY_RETRIES)
8095 {
8096 /* done with retris; give up */
8097 TI_DBG1(("tdsaSMPBusyTimerCB: retries are over\n"));
8098 discovery->SMPRetries = 0;
8099 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
8100 if (discovery->SMPBusyTimer.timerRunning == agTRUE)
8101 {
8102 tdsaKillTimer(
8103 tiRoot,
8104 &discovery->SMPBusyTimer
8105 );
8106 }
8107 }
8108 else
8109 {
8110 /* keep retrying */
8111 tdsaSMPBusyTimer(tiRoot, onePortContext, oneDeviceData, tdSMPRequestBody);
8112 }
8113 }
8114
8115 return;
8116 }
8117
8118 /*****************************************************************************
8119 *! \brief tdsaBCTimer
8120 *
8121 * Purpose: This function sets timers for sending ID device data only for
8122 * directly attached SATA device.
8123 *
8124 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8125 * instance.
8126 * \param onePortContext: Pointer to the portal context instance.
8127 * \param oneDeviceData: Pointer to the device data.
8128 * \param tdSMPRequestBody: Pointer to the SMP request body.
8129 *
8130 * \return:
8131 * None
8132 *
8133 * \note:
8134 *
8135 *****************************************************************************/
8136 osGLOBAL void
tdsaBCTimer(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext)8137 tdsaBCTimer(tiRoot_t *tiRoot,
8138 tdsaPortContext_t *onePortContext
8139 )
8140 {
8141 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
8142 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
8143 itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
8144 tdsaDiscovery_t *discovery;
8145
8146
8147 TI_DBG1(("tdsaBCTimer: start\n"));
8148
8149 discovery = &(onePortContext->discovery);
8150
8151 if (discovery->BCTimer.timerRunning == agTRUE)
8152 {
8153 tdsaKillTimer(
8154 tiRoot,
8155 &discovery->BCTimer
8156 );
8157 }
8158
8159 if (onePortContext->valid == agTRUE)
8160 {
8161 tdsaSetTimerRequest(
8162 tiRoot,
8163 &discovery->BCTimer,
8164 BC_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
8165 tdsaBCTimerCB,
8166 onePortContext,
8167 agNULL,
8168 agNULL
8169 );
8170
8171 tdsaAddTimer(
8172 tiRoot,
8173 &Initiator->timerlist,
8174 &discovery->BCTimer
8175 );
8176
8177 }
8178
8179 return;
8180 }
8181
8182 /*****************************************************************************
8183 *! \brief tdsaBCTimerCB
8184 *
8185 * Purpose: This function is callback function for SATA ID device data.
8186 *
8187 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8188 * instance.
8189 * \param timerData1: Pointer to timer-related data structure
8190 * \param timerData2: Pointer to timer-related data structure
8191 * \param timerData3: Pointer to timer-related data structure
8192 *
8193 * \return:
8194 * None
8195 *
8196 * \note:
8197 *
8198 *****************************************************************************/
8199 osGLOBAL void
tdsaBCTimerCB(tiRoot_t * tiRoot,void * timerData1,void * timerData2,void * timerData3)8200 tdsaBCTimerCB(
8201 tiRoot_t * tiRoot,
8202 void * timerData1,
8203 void * timerData2,
8204 void * timerData3
8205 )
8206 {
8207 tdsaPortContext_t *onePortContext;
8208 tdsaDiscovery_t *discovery;
8209
8210 TI_DBG1(("tdsaBCTimerCB: start\n"));
8211
8212 onePortContext = (tdsaPortContext_t *)timerData1;
8213 discovery = &(onePortContext->discovery);
8214
8215 discovery->ResetTriggerred = agFALSE;
8216
8217 if (onePortContext->valid == agTRUE)
8218 {
8219 tdsaDiscover(
8220 tiRoot,
8221 onePortContext,
8222 TDSA_DISCOVERY_TYPE_SAS,
8223 TDSA_DISCOVERY_OPTION_INCREMENTAL_START
8224 );
8225 }
8226 if (discovery->BCTimer.timerRunning == agTRUE)
8227 {
8228 tdsaKillTimer(
8229 tiRoot,
8230 &discovery->BCTimer
8231 );
8232 }
8233
8234 return;
8235 }
8236
8237 /*****************************************************************************
8238 *! \brief tdsaDiscoverySMPTimer
8239 *
8240 * Purpose: This function sets timers for sending discovery-related SMP
8241 *
8242 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8243 * instance.
8244 * \param onePortContext: Pointer to the portal context instance.
8245 * \param functionCode: SMP function.
8246 * \param tdSMPRequestBody: Pointer to the SMP request body.
8247 *
8248 * \return:
8249 * None
8250 *
8251 * \note:
8252 *
8253 *****************************************************************************/
8254 osGLOBAL void
tdsaDiscoverySMPTimer(tiRoot_t * tiRoot,tdsaPortContext_t * onePortContext,bit32 functionCode,tdssSMPRequestBody_t * tdSMPRequestBody)8255 tdsaDiscoverySMPTimer(tiRoot_t *tiRoot,
8256 tdsaPortContext_t *onePortContext,
8257 bit32 functionCode, /* smp function code */
8258 tdssSMPRequestBody_t *tdSMPRequestBody
8259 )
8260 {
8261 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
8262 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
8263 itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
8264 tdsaDiscovery_t *discovery;
8265
8266 TI_DBG3(("tdsaDiscoverySMPTimer: start\n"));
8267 TI_DBG3(("tdsaDiscoverySMPTimer: pid %d SMPFn 0x%x\n", onePortContext->id, functionCode));
8268
8269 /* start the SMP timer which works as SMP application timer */
8270 discovery = &(onePortContext->discovery);
8271
8272 if (discovery->DiscoverySMPTimer.timerRunning == agTRUE)
8273 {
8274 tdsaKillTimer(
8275 tiRoot,
8276 &discovery->DiscoverySMPTimer
8277 );
8278 }
8279 tdsaSetTimerRequest(
8280 tiRoot,
8281 &discovery->DiscoverySMPTimer,
8282 SMP_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
8283 tdsaDiscoverySMPTimerCB,
8284 onePortContext,
8285 tdSMPRequestBody,
8286 agNULL
8287 );
8288
8289 tdsaAddTimer (
8290 tiRoot,
8291 &Initiator->timerlist,
8292 &discovery->DiscoverySMPTimer
8293 );
8294
8295 return;
8296 }
8297
8298 /*****************************************************************************
8299 *! \brief tdsaDiscoverySMPTimerCB
8300 *
8301 * Purpose: This function is callback function for tdsaDiscoverySMPTimer.
8302 *
8303 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8304 * instance.
8305 * \param timerData1: Pointer to timer-related data structure
8306 * \param timerData2: Pointer to timer-related data structure
8307 * \param timerData3: Pointer to timer-related data structure
8308 *
8309 * \return:
8310 * None
8311 *
8312 * \note:
8313 *
8314 *****************************************************************************/
8315 osGLOBAL void
tdsaDiscoverySMPTimerCB(tiRoot_t * tiRoot,void * timerData1,void * timerData2,void * timerData3)8316 tdsaDiscoverySMPTimerCB(
8317 tiRoot_t * tiRoot,
8318 void * timerData1,
8319 void * timerData2,
8320 void * timerData3
8321 )
8322 {
8323 agsaRoot_t *agRoot;
8324 tdsaPortContext_t *onePortContext;
8325 bit8 SMPFunction;
8326 #ifndef DIRECT_SMP
8327 tdssSMPFrameHeader_t *tdSMPFrameHeader;
8328 bit8 smpHeader[4];
8329 #endif
8330 tdssSMPRequestBody_t *tdSMPRequestBody;
8331 tdsaDiscovery_t *discovery;
8332 tdsaDeviceData_t *oneDeviceData;
8333 agsaIORequest_t *agAbortIORequest = agNULL;
8334 tdIORequestBody_t *tdAbortIORequestBody = agNULL;
8335 bit32 PhysUpper32;
8336 bit32 PhysLower32;
8337 bit32 memAllocStatus;
8338 void *osMemHandle;
8339 agsaIORequest_t *agToBeAbortIORequest = agNULL;
8340
8341 TI_DBG1(("tdsaDiscoverySMPTimerCB: start\n"));
8342
8343 /* no retry
8344 if discovery related SMP, fail the discovery
8345 else ....
8346 be sure to abort SMP
8347 */
8348 onePortContext = (tdsaPortContext_t *)timerData1;
8349 tdSMPRequestBody = (tdssSMPRequestBody_t *)timerData2;
8350
8351 discovery = &(onePortContext->discovery);
8352 oneDeviceData = tdSMPRequestBody->tdDevice;
8353 agToBeAbortIORequest = &(tdSMPRequestBody->agIORequest);
8354 agRoot = oneDeviceData->agRoot;
8355
8356 #ifdef DIRECT_SMP
8357 SMPFunction = tdSMPRequestBody->smpPayload[1];
8358 #else
8359 saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 0, smpHeader, 4);
8360 tdSMPFrameHeader = (tdssSMPFrameHeader_t *)smpHeader;
8361 SMPFunction = tdSMPFrameHeader->smpFunction;
8362 #endif
8363
8364 TI_DBG1(("tdsaDiscoverySMPTimerCB: SMP function 0x%x\n", SMPFunction));
8365
8366 if (discovery->DiscoverySMPTimer.timerRunning == agTRUE)
8367 {
8368 tdsaKillTimer(
8369 tiRoot,
8370 &discovery->DiscoverySMPTimer
8371 );
8372 }
8373 switch (SMPFunction)
8374 {
8375 case SMP_REPORT_GENERAL: /* fall through */
8376 case SMP_DISCOVER: /* fall through */
8377 case SMP_CONFIGURE_ROUTING_INFORMATION: /* fall through */
8378 TI_DBG1(("tdsaDiscoverySMPTimerCB: failing discovery, SMP function 0x%x\n", SMPFunction));
8379 tdsaSASDiscoverDone(tiRoot, onePortContext, tiError);
8380 return;
8381 case SMP_REPORT_PHY_SATA:
8382 TI_DBG1(("tdsaDiscoverySMPTimerCB: failing discovery, SMP function SMP_REPORT_PHY_SATA\n"));
8383 tdsaSATADiscoverDone(tiRoot, onePortContext, tiError);
8384 break;
8385 default:
8386 /* do nothing */
8387 TI_DBG1(("tdsaDiscoverySMPTimerCB: Error!!!! not allowed case\n"));
8388 break;
8389 }
8390
8391 if (onePortContext->discovery.SeenBC == agTRUE)
8392 {
8393 /* allocating agIORequest for abort itself */
8394 memAllocStatus = ostiAllocMemory(
8395 tiRoot,
8396 &osMemHandle,
8397 (void **)&tdAbortIORequestBody,
8398 &PhysUpper32,
8399 &PhysLower32,
8400 8,
8401 sizeof(tdIORequestBody_t),
8402 agTRUE
8403 );
8404 if (memAllocStatus != tiSuccess)
8405 {
8406 /* let os process IO */
8407 TI_DBG1(("tdsaDiscoverySMPTimerCB: ostiAllocMemory failed...\n"));
8408 return;
8409 }
8410
8411 if (tdAbortIORequestBody == agNULL)
8412 {
8413 /* let os process IO */
8414 TI_DBG1(("tdsaDiscoverySMPTimerCB: ostiAllocMemory returned NULL tdAbortIORequestBody\n"));
8415 return;
8416 }
8417
8418 /* setup task management structure */
8419 tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle;
8420 /* setting callback */
8421 tdAbortIORequestBody->IOCompletionFunc = itdssIOAbortedHandler;
8422
8423 tdAbortIORequestBody->tiDevHandle = (tiDeviceHandle_t *)&(oneDeviceData->tiDeviceHandle);
8424
8425 /* initialize agIORequest */
8426 agAbortIORequest = &(tdAbortIORequestBody->agIORequest);
8427 agAbortIORequest->osData = (void *) tdAbortIORequestBody;
8428 agAbortIORequest->sdkData = agNULL; /* LL takes care of this */
8429
8430 /* SMPAbort - abort one */
8431 saSMPAbort(agRoot,
8432 agAbortIORequest,
8433 0,
8434 oneDeviceData->agDevHandle,
8435 0, /* abort one */
8436 agToBeAbortIORequest,
8437 agNULL
8438 );
8439
8440 }
8441 return;
8442 }
8443
8444
8445 /*****************************************************************************
8446 *! \brief tdsaSATAIDDeviceTimer
8447 *
8448 * Purpose: This function sets timers for sending ID device data only for
8449 * directly attached SATA device.
8450 *
8451 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8452 * instance.
8453 * \param onePortContext: Pointer to the portal context instance.
8454 * \param oneDeviceData: Pointer to the device data.
8455 * \param tdSMPRequestBody: Pointer to the SMP request body.
8456 *
8457 * \return:
8458 * None
8459 *
8460 * \note:
8461 *
8462 *****************************************************************************/
8463 osGLOBAL void
tdsaSATAIDDeviceTimer(tiRoot_t * tiRoot,tdsaDeviceData_t * oneDeviceData)8464 tdsaSATAIDDeviceTimer(tiRoot_t *tiRoot,
8465 tdsaDeviceData_t *oneDeviceData
8466 )
8467 {
8468 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
8469 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
8470 itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
8471
8472 TI_DBG1(("tdsaSATAIDDeviceTimer: start\n"));
8473
8474 if (oneDeviceData->SATAIDDeviceTimer.timerRunning == agTRUE)
8475 {
8476 tdsaKillTimer(
8477 tiRoot,
8478 &oneDeviceData->SATAIDDeviceTimer
8479 );
8480 }
8481
8482 tdsaSetTimerRequest(
8483 tiRoot,
8484 &oneDeviceData->SATAIDDeviceTimer,
8485 SATA_ID_DEVICE_DATA_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
8486 tdsaSATAIDDeviceTimerCB,
8487 oneDeviceData,
8488 agNULL,
8489 agNULL
8490 );
8491
8492 tdsaAddTimer (
8493 tiRoot,
8494 &Initiator->timerlist,
8495 &oneDeviceData->SATAIDDeviceTimer
8496 );
8497
8498 return;
8499 }
8500
8501 /*****************************************************************************
8502 *! \brief tdsaSATAIDDeviceTimerCB
8503 *
8504 * Purpose: This function is callback function for SATA ID device data.
8505 *
8506 * \param tiRoot: Pointer to the OS Specific module allocated tiRoot_t
8507 * instance.
8508 * \param timerData1: Pointer to timer-related data structure
8509 * \param timerData2: Pointer to timer-related data structure
8510 * \param timerData3: Pointer to timer-related data structure
8511 *
8512 * \return:
8513 * None
8514 *
8515 * \note:
8516 *
8517 *****************************************************************************/
8518 osGLOBAL void
tdsaSATAIDDeviceTimerCB(tiRoot_t * tiRoot,void * timerData1,void * timerData2,void * timerData3)8519 tdsaSATAIDDeviceTimerCB(
8520 tiRoot_t * tiRoot,
8521 void * timerData1,
8522 void * timerData2,
8523 void * timerData3
8524 )
8525 {
8526 tdsaDeviceData_t *oneDeviceData;
8527
8528 TI_DBG1(("tdsaSATAIDDeviceTimerCB: start\n"));
8529
8530 oneDeviceData = (tdsaDeviceData_t *)timerData1;
8531
8532 /* send identify device data */
8533 tdssSubAddSATAToSharedcontext(tiRoot, oneDeviceData);
8534
8535 if (oneDeviceData->SATAIDDeviceTimer.timerRunning == agTRUE)
8536 {
8537 tdsaKillTimer(
8538 tiRoot,
8539 &oneDeviceData->SATAIDDeviceTimer
8540 );
8541 }
8542
8543 return;
8544 }
8545
8546 #endif /* TD_DISCOVER */
8547