xref: /freebsd/sys/dev/pms/RefTisa/discovery/dm/dmsmp.c (revision eda14cbc264d6969b02f2b1994cef11148e914f1)
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 #include <sys/cdefs.h>
24 __FBSDID("$FreeBSD$");
25 #include <dev/pms/config.h>
26 
27 #include <dev/pms/freebsd/driver/common/osenv.h>
28 #include <dev/pms/freebsd/driver/common/ostypes.h>
29 #include <dev/pms/freebsd/driver/common/osdebug.h>
30 
31 #include <dev/pms/RefTisa/sallsdk/api/sa.h>
32 #include <dev/pms/RefTisa/sallsdk/api/saapi.h>
33 #include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
34 
35 #ifdef FDS_DM
36 #include <dev/pms/RefTisa/discovery/api/dm.h>
37 #include <dev/pms/RefTisa/discovery/api/dmapi.h>
38 #include <dev/pms/RefTisa/discovery/api/tddmapi.h>
39 
40 #include <dev/pms/RefTisa/discovery/dm/dmdefs.h>
41 #include <dev/pms/RefTisa/discovery/dm/dmtypes.h>
42 #include <dev/pms/RefTisa/discovery/dm/dmproto.h>
43 
44 osGLOBAL bit32
45 dmSMPStart(
46            dmRoot_t              *dmRoot,
47            agsaRoot_t            *agRoot,
48            dmDeviceData_t        *oneDeviceData,
49            bit32                 functionCode,
50            bit8                  *pSmpBody,
51            bit32                 smpBodySize,
52            bit32                 agRequestType
53            )
54 {
55   dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
56   dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
57   dmIntPortContext_t        *onePortContext = agNULL;
58   dmSMPRequestBody_t        *dmSMPRequestBody = agNULL;
59 #ifndef DIRECT_SMP
60   dmSMPRequestBody_t        *dmSMPResponseBody = agNULL;
61 #endif
62   agsaSASRequestBody_t      *agSASRequestBody;
63   dmList_t                  *SMPList;
64   agsaDevHandle_t           *agDevHandle;
65   agsaIORequest_t           *agIORequest;
66   agsaSMPFrame_t            *agSMPFrame;
67   bit32                     expectedRspLen = 0;
68   dmSMPFrameHeader_t        dmSMPFrameHeader;
69   dmExpander_t              *oneExpander = agNULL;
70   bit32                     status;
71 
72   DM_DBG5(("dmSMPStart: start\n"));
73   DM_DBG5(("dmSMPStart: 2nd sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
74   DM_DBG5(("dmSMPStart: 2nd sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
75 
76   dm_memset(&dmSMPFrameHeader, 0, sizeof(dmSMPFrameHeader_t));
77 
78   onePortContext = oneDeviceData->dmPortContext;
79 
80   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
81   {
82     DM_DBG1(("dmSMPStart: invalid port or aborted discovery!!!\n"));
83     return DM_RC_FAILURE;
84   }
85 
86   oneExpander = oneDeviceData->dmExpander;
87   if (oneExpander == agNULL)
88   {
89     DM_DBG1(("dmSMPStart: Wrong!!! oneExpander is NULL!!!\n"));
90     return DM_RC_FAILURE;
91   }
92 
93   if (onePortContext != agNULL)
94   {
95     DM_DBG5(("dmSMPStart: pid %d\n", onePortContext->id));
96     /* increment the number of pending SMP */
97     onePortContext->discovery.pendingSMP++;
98   }
99   else
100   {
101     DM_DBG1(("dmSMPStart: Wrong, onePortContext is NULL!!!\n"));
102     return DM_RC_FAILURE;
103   }
104 
105   /* get an smp REQUEST from the free list */
106   tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
107   if (DMLIST_EMPTY(&(dmAllShared->freeSMPList)))
108   {
109     DM_DBG1(("dmSMPStart: no free SMP!!!\n"));
110     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
111     /* undo increment the number of pending SMP */
112     onePortContext->discovery.pendingSMP--;
113     return DM_RC_FAILURE;
114   }
115   else
116   {
117     DMLIST_DEQUEUE_FROM_HEAD(&SMPList, &(dmAllShared->freeSMPList));
118     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
119     dmSMPRequestBody = DMLIST_OBJECT_BASE(dmSMPRequestBody_t, Link, SMPList);
120   }
121 
122   if (dmSMPRequestBody == agNULL)
123   {
124     DM_DBG1(("dmSMPStart: dmSMPRequestBody is NULL, wrong!!!\n"));
125     return DM_RC_FAILURE;
126   }
127   DM_DBG5(("dmSMPStart: SMP id %d\n", dmSMPRequestBody->id));
128 
129   dmSMPRequestBody->dmRoot = dmRoot;
130   dmSMPRequestBody->dmDevice = oneDeviceData;
131   dmSMPRequestBody->dmPortContext = onePortContext;
132 
133   agDevHandle = oneExpander->agDevHandle;
134 
135   /* save the callback funtion */
136   dmSMPRequestBody->SMPCompletionFunc = dmSMPCompleted; /* in dmsmp.c */
137 
138   dmSMPRequestBody->retries = 0;
139 
140   agIORequest = &(dmSMPRequestBody->agIORequest);
141   agIORequest->osData = (void *) dmSMPRequestBody;
142   agIORequest->sdkData = agNULL; /* SALL takes care of this */
143 
144   agSASRequestBody = &(dmSMPRequestBody->agSASRequestBody);
145   agSMPFrame = &(agSASRequestBody->smpFrame);
146 
147   /* sets dmSMPFrameHeader values */
148   if (oneExpander->SAS2 == 0)
149   {
150     DM_DBG5(("dmSMPStart: SAS 1.1\n"));
151     switch (functionCode)
152     {
153     case SMP_REPORT_GENERAL:
154       expectedRspLen = sizeof(smpRespReportGeneral_t) + 4;
155       break;
156     case SMP_REPORT_MANUFACTURE_INFORMATION:
157       expectedRspLen = sizeof(smpRespReportManufactureInfo_t) + 4;
158       break;
159     case SMP_DISCOVER:
160       expectedRspLen = sizeof(smpRespDiscover_t) + 4;
161       break;
162     case SMP_REPORT_PHY_ERROR_LOG:
163       expectedRspLen = 32 - 4;
164       break;
165     case SMP_REPORT_PHY_SATA:
166       expectedRspLen = sizeof(smpRespReportPhySata_t) + 4;
167       break;
168     case SMP_REPORT_ROUTING_INFORMATION:
169       expectedRspLen = sizeof(smpRespReportRouteTable_t) + 4;
170       break;
171     case SMP_CONFIGURE_ROUTING_INFORMATION:
172       expectedRspLen = 4;
173       break;
174     case SMP_PHY_CONTROL:
175       expectedRspLen = 4;
176       break;
177     case SMP_PHY_TEST_FUNCTION:
178       expectedRspLen = 4;
179       break;
180     case SMP_PMC_SPECIFIC:
181       expectedRspLen = 4;
182       break;
183     default:
184       expectedRspLen = 0;
185       DM_DBG1(("dmSMPStart: SAS 1.1 error, undefined or unused smp function code 0x%x !!!\n", functionCode));
186       return DM_RC_FAILURE;
187     }
188     /* SMP 1.1 header */
189     dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
190     dmSMPFrameHeader.smpFunction = (bit8)functionCode;
191     dmSMPFrameHeader.smpFunctionResult = 0;
192     dmSMPFrameHeader.smpReserved = 0;
193   }
194   else /* SAS 2 */
195   {
196     DM_DBG2(("dmSMPStart: SAS 2\n"));
197     switch (functionCode)
198     {
199     case SMP_REPORT_GENERAL:
200       expectedRspLen = sizeof(smpRespReportGeneral2_t) + 4;
201       /* SMP 2.0 header */
202       dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
203       dmSMPFrameHeader.smpFunction = (bit8)functionCode;
204       dmSMPFrameHeader.smpFunctionResult = 0x11;
205       dmSMPFrameHeader.smpReserved = 0;
206       break;
207     case SMP_REPORT_MANUFACTURE_INFORMATION:
208       expectedRspLen = sizeof(smpRespReportManufactureInfo2_t) + 4;
209       break;
210     case SMP_DISCOVER:
211       expectedRspLen = sizeof(smpRespDiscover2_t) + 4;
212       /* SMP 2.0 header */
213       dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
214       dmSMPFrameHeader.smpFunction = (bit8)functionCode;
215 //      dmSMPFrameHeader.smpFunctionResult = 0x6c;
216       dmSMPFrameHeader.smpFunctionResult = 0x1b;
217       dmSMPFrameHeader.smpReserved = 0x02;
218       break;
219     case SMP_REPORT_PHY_ERROR_LOG:
220       expectedRspLen = 32 - 4;
221       break;
222     case SMP_REPORT_PHY_SATA:
223       /* SMP 2.0 header */
224       dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
225       dmSMPFrameHeader.smpFunction = (bit8)functionCode;
226       dmSMPFrameHeader.smpFunctionResult = 0x10;
227       dmSMPFrameHeader.smpReserved = 0x02;
228       expectedRspLen = sizeof(smpRespReportPhySata2_t) + 4;
229       break;
230     case SMP_REPORT_ROUTING_INFORMATION:
231       expectedRspLen = sizeof(smpRespReportRouteTable2_t) + 4;
232       break;
233     case SMP_CONFIGURE_ROUTING_INFORMATION:
234       expectedRspLen = 4;
235       /* SMP 2.0 header */
236       dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
237       dmSMPFrameHeader.smpFunction = (bit8)functionCode;
238       dmSMPFrameHeader.smpFunctionResult = 0;
239       dmSMPFrameHeader.smpReserved = 0x09;
240       break;
241     case SMP_PHY_CONTROL:
242       expectedRspLen = 4;
243       /* SMP 2.0 header */
244       dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
245       dmSMPFrameHeader.smpFunction = (bit8)functionCode;
246       dmSMPFrameHeader.smpFunctionResult = 0;
247       dmSMPFrameHeader.smpReserved = 0x09;
248      break;
249     case SMP_PHY_TEST_FUNCTION:
250       expectedRspLen = 4;
251       break;
252     case SMP_DISCOVER_LIST:
253       expectedRspLen = SMP_MAXIMUM_PAYLOAD; /* 1024 without CRC */
254       /* SMP 2.0 header */
255       dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */
256       dmSMPFrameHeader.smpFunction = (bit8)functionCode;
257       dmSMPFrameHeader.smpFunctionResult = 0xFF;
258       dmSMPFrameHeader.smpReserved = 0x06;
259       break;
260     case SMP_PMC_SPECIFIC:
261       expectedRspLen = 4;
262       break;
263     default:
264       expectedRspLen = 0;
265       DM_DBG1(("dmSMPStart: SAS 2 error!!! undefined or unused smp function code 0x%x!!!\n", functionCode));
266       return DM_RC_FAILURE;
267     }
268   }
269 
270   if (DMIsSPC(agRoot))
271   {
272 #ifdef DIRECT_SMP  /* direct SMP with 48 or less payload */
273   if ( (smpBodySize + 4) <= SMP_DIRECT_PAYLOAD_LIMIT) /* 48 */
274   {
275     DM_DBG5(("dmSMPStart: DIRECT smp payload\n"));
276     dm_memset(dmSMPRequestBody->smpPayload, 0, SMP_DIRECT_PAYLOAD_LIMIT);
277     dm_memcpy(dmSMPRequestBody->smpPayload, &dmSMPFrameHeader, 4);
278     dm_memcpy((dmSMPRequestBody->smpPayload)+4, pSmpBody, smpBodySize);
279 
280     /* direct SMP payload eg) REPORT_GENERAL, DISCOVER etc */
281     agSMPFrame->outFrameBuf = dmSMPRequestBody->smpPayload;
282     agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */
283     /* to specify DIRECT SMP response */
284     agSMPFrame->inFrameLen = 0;
285 
286     /* temporary solution for T2D Combo*/
287 #if defined (INITIATOR_DRIVER) && defined (TARGET_DRIVER)
288     /* force smp repsonse to be direct */
289     agSMPFrame->expectedRespLen = 0;
290 #else
291     agSMPFrame->expectedRespLen = expectedRspLen;
292 #endif
293   }
294   else
295   {
296     DM_DBG5(("dmSMPStart: INDIRECT smp payload, TBD\n"));
297   }
298 
299 #else
300 
301   /*
302      dmSMPRequestBody is SMP request
303      dmSMPResponsebody is SMP response
304   */
305 
306   /* get an smp RESPONSE from the free list */
307   tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
308   if (DMLIST_EMPTY(&(dmAllShared->freeSMPList)))
309   {
310     DM_DBG1(("dmSMPStart: no free SMP!!!\n"));
311     /* puy back dmSMPRequestBody to the freelist ???*/
312 //    DMLIST_DEQUEUE_THIS(&(dmSMPRequestBody->Link));
313     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
314     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
315 
316     /* undo increment the number of pending SMP */
317     onePortContext->discovery.pendingSMP--;
318     return DM_RC_FAILURE;
319   }
320   else
321   {
322     DMLIST_DEQUEUE_FROM_HEAD(&SMPList, &(dmAllShared->freeSMPList));
323     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
324     dmSMPResponseBody = DMLIST_OBJECT_BASE(dmSMPRequestBody_t, Link, SMPList);
325     DM_DBG5(("dmSMPStart: SMP id %d\n", dmSMPResponseBody->id));
326   }
327 
328   if (dmSMPResponseBody == agNULL)
329   {
330     DM_DBG1(("dmSMPStart: dmSMPResponseBody is NULL, wrong!!!\n"));
331     return DM_RC_FAILURE;
332   }
333 
334   /* fill in indirect SMP request fields */
335   DM_DBG5(("dmSMPStart: INDIRECT smp payload\n"));
336 
337   /* save the pointer to SMP response in SMP request */
338   dmSMPRequestBody->IndirectSMPResponse = dmSMPResponseBody;
339   /* SMP request and response initialization */
340   dm_memset(dmSMPRequestBody->IndirectSMP, 0, smpBodySize + 4);
341   dm_memset(dmSMPResponseBody->IndirectSMP, 0, expectedRspLen);
342 
343   dm_memcpy(dmSMPRequestBody->IndirectSMP, &dmSMPFrameHeader, 4);
344   dm_memcpy(dmSMPRequestBody->IndirectSMP+4, pSmpBody, smpBodySize);
345 
346   /* Indirect SMP request */
347   agSMPFrame->outFrameBuf = agNULL;
348   agSMPFrame->outFrameAddrUpper32 = dmSMPRequestBody->IndirectSMPUpper32;
349   agSMPFrame->outFrameAddrLower32 = dmSMPRequestBody->IndirectSMPLower32;
350   agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */
351 
352   /* Indirect SMP response */
353   agSMPFrame->expectedRespLen = expectedRspLen;
354   agSMPFrame->inFrameAddrUpper32 = dmSMPResponseBody->IndirectSMPUpper32;
355   agSMPFrame->inFrameAddrLower32 = dmSMPResponseBody->IndirectSMPLower32;
356   agSMPFrame->inFrameLen = expectedRspLen; /* without last 4 byte crc */
357 
358 #endif
359   }
360   else /* SPCv controller */
361   {
362     /* only direct mode for both request and response */
363     DM_DBG5(("dmSMPStart: DIRECT smp payload\n"));
364     agSMPFrame->flag = 0;
365     dm_memset(dmSMPRequestBody->smpPayload, 0, SMP_DIRECT_PAYLOAD_LIMIT);
366     dm_memcpy(dmSMPRequestBody->smpPayload, &dmSMPFrameHeader, 4);
367     dm_memcpy((dmSMPRequestBody->smpPayload)+4, pSmpBody, smpBodySize);
368 
369     /* direct SMP payload eg) REPORT_GENERAL, DISCOVER etc */
370     agSMPFrame->outFrameBuf = dmSMPRequestBody->smpPayload;
371     agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */
372     /* to specify DIRECT SMP response */
373     agSMPFrame->inFrameLen = 0;
374 
375       /* temporary solution for T2D Combo*/
376 #if defined (INITIATOR_DRIVER) && defined (TARGET_DRIVER)
377     /* force smp repsonse to be direct */
378     agSMPFrame->expectedRespLen = 0;
379 #else
380     agSMPFrame->expectedRespLen = expectedRspLen;
381 #endif
382   //    tdhexdump("tdSMPStart", (bit8*)agSMPFrame->outFrameBuf, agSMPFrame->outFrameLen);
383   //    tdhexdump("tdSMPStart new", (bit8*)tdSMPRequestBody->smpPayload, agSMPFrame->outFrameLen);
384   //    tdhexdump("tdSMPStart - tdSMPRequestBody", (bit8*)tdSMPRequestBody, sizeof(tdssSMPRequestBody_t));
385   }
386 
387   if (agDevHandle == agNULL)
388   {
389     DM_DBG1(("dmSMPStart: !!! agDevHandle is NULL !!! \n"));
390   }
391   else
392   {
393     status = saSMPStart(
394                       agRoot,
395                       agIORequest,
396                       0,
397                       agDevHandle,
398                       agRequestType,
399                       agSASRequestBody,
400                       &dmsaSMPCompleted
401                       );
402 
403     if (status == AGSA_RC_SUCCESS)
404     {
405       /* start SMP timer */
406       if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER ||
407           functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION
408         )
409       {
410         dmDiscoverySMPTimer(dmRoot, onePortContext, functionCode, dmSMPRequestBody);
411       }
412       return DM_RC_SUCCESS;
413     }
414     else if (status == AGSA_RC_BUSY)
415     {
416       /* set timer */
417       if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER ||
418           functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION)
419       {
420         /* only for discovery related SMPs*/
421         dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody);
422         return DM_RC_SUCCESS;
423       }
424       else
425       {
426         DM_DBG1(("dmSMPStart: return DM_RC_BUSY!!! \n"));
427 #ifdef DIRECT_SMP
428         tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
429         DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
430         tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
431 #else
432         tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
433         DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
434         DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
435         tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
436 #endif
437         return DM_RC_BUSY;
438       }
439     }
440     else /* AGSA_RC_FAILURE */
441     {
442       DM_DBG1(("dmSMPStart: return DM_RC_FAILURE!!! \n"));
443       /* discovery failure or task management failure */
444       if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER ||
445           functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION)
446       {
447         dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
448       }
449 #ifdef DIRECT_SMP
450       tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
451       DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
452       tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
453 #else
454       tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
455       DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
456       DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
457       tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
458 #endif
459 
460       return DM_RC_FAILURE;
461     }
462   }
463   return DM_RC_SUCCESS;
464 }
465 
466 osGLOBAL void
467 dmsaSMPCompleted(
468                  agsaRoot_t            *agRoot,
469                  agsaIORequest_t       *agIORequest,
470                  bit32                 agIOStatus,
471                  bit32                 agIOInfoLen,
472                  agsaFrameHandle_t     agFrameHandle
473                  )
474 {
475   dmSMPRequestBody_t   *pSMPRequestBody = (dmSMPRequestBody_t *) agIORequest->osData;
476 
477   /* SPC can't be SMP target */
478 
479   DM_DBG5(("dmsaSMPCompleted: start\n"));
480 
481   if (pSMPRequestBody == agNULL)
482   {
483     DM_DBG1(("dmsaSMPCompleted: pSMPRequestBody is NULL!!! \n"));
484     return;
485   }
486 
487   if (pSMPRequestBody->SMPCompletionFunc == agNULL)
488   {
489     DM_DBG1(("dmsaSMPCompleted: pSMPRequestBody->SMPCompletionFunc is NULL!!!\n"));
490     return;
491   }
492 
493 #ifdef DM_INTERNAL_DEBUG /* debugging */
494   DM_DBG3(("dmsaSMPCompleted: agIOrequest %p\n", agIORequest->osData));
495   DM_DBG3(("dmsaSMPCompleted: sizeof(tdIORequestBody_t) %d 0x%x\n", sizeof(tdIORequestBody_t),
496            sizeof(tdIORequestBody_t)));
497   DM_DBG3(("dmsaSMPCompleted: SMPRequestbody %p\n", pSMPRequestBody));
498   DM_DBG3(("dmsaSMPCompleted: calling callback fn\n"));
499   DM_DBG3(("dmsaSMPCompleted: callback fn %p\n",pSMPRequestBody->SMPCompletionFunc));
500 #endif /* TD_INTERNAL_DEBUG */
501   /*
502     if initiator, calling dmSMPCompleted() in dmsmp.c
503   */
504   pSMPRequestBody->SMPCompletionFunc(
505                                      agRoot,
506                                      agIORequest,
507                                      agIOStatus,
508                                      agIOInfoLen,
509                                      agFrameHandle
510                                      );
511 
512   return;
513 
514 }
515 
516 osGLOBAL bit32
517 dmPhyControlSend(
518                    dmRoot_t             *dmRoot,
519 //                   dmDeviceData_t     *oneDeviceData, /* taget disk */
520                    dmDeviceData_t     *oneExpDeviceData, /* taget disk */
521                    bit8                 phyOp,
522 bit8 phyID // added
523                    )
524 {
525   dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
526   dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
527   agsaRoot_t                *agRoot = dmAllShared->agRoot;
528 //  thenil
529 //  dmDeviceData_t      *oneExpDeviceData;
530   smpReqPhyControl_t    smpPhyControlReq;
531 //  bit8                  phyID;
532   bit32                 status;
533 
534   DM_DBG3(("dmPhyControlSend: start\n"));
535 
536 
537 
538   osti_memset(&smpPhyControlReq, 0, sizeof(smpReqPhyControl_t));
539 
540   /* fill in SMP payload */
541   smpPhyControlReq.phyIdentifier = phyID;
542   smpPhyControlReq.phyOperation = phyOp;
543 
544   status = dmSMPStart(
545                       dmRoot,
546                       agRoot,
547                       oneExpDeviceData,
548                       SMP_PHY_CONTROL,
549                       (bit8 *)&smpPhyControlReq,
550                       sizeof(smpReqPhyControl_t),
551                       AGSA_SMP_INIT_REQ
552                      );
553   return status;
554 }
555 
556 osGLOBAL void
557 dmReportGeneralSend(
558                     dmRoot_t             *dmRoot,
559                     dmDeviceData_t       *oneDeviceData
560                     )
561 {
562   dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
563   dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
564   agsaRoot_t                *agRoot = dmAllShared->agRoot;
565 
566   DM_DBG3(("dmReportGeneralSend: start\n"));
567   DM_DBG3(("dmReportGeneralSend: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
568   DM_DBG3(("dmReportGeneralSend: oneExpander %p did %d\n", oneDeviceData->dmExpander, oneDeviceData->dmExpander->id));
569 
570   if (agRoot == agNULL)
571   {
572     DM_DBG1(("dmReportGeneralSend: agRoot is NULL!!!\n"));
573     return;
574   }
575 
576   dmSMPStart(
577              dmRoot,
578              agRoot,
579              oneDeviceData,
580              SMP_REPORT_GENERAL,
581              agNULL,
582              0,
583              AGSA_SMP_INIT_REQ
584              );
585   return;
586 }
587 osGLOBAL void
588 dmReportGeneralRespRcvd(
589                         dmRoot_t              *dmRoot,
590                         agsaRoot_t            *agRoot,
591                         agsaIORequest_t       *agIORequest,
592                         dmDeviceData_t        *oneDeviceData,
593                         dmSMPFrameHeader_t    *frameHeader,
594                         agsaFrameHandle_t     frameHandle
595                         )
596 {
597   smpRespReportGeneral_t       dmSMPReportGeneralResp;
598   smpRespReportGeneral_t       *pdmSMPReportGeneralResp;
599   dmIntPortContext_t           *onePortContext = agNULL;
600   dmDiscovery_t                *discovery;
601   dmExpander_t                 *oneExpander = agNULL;
602 #ifndef DIRECT_SMP
603   dmSMPRequestBody_t           *dmSMPRequestBody;
604   dmSMPRequestBody_t           *dmSMPResponseBody = agNULL;
605 #endif
606   dmIntRoot_t         *dmIntRoot   = (dmIntRoot_t *)dmRoot->dmData;
607   dmIntContext_t      *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
608 
609   DM_DBG3(("dmReportGeneralRespRcvd: start\n"));
610   DM_DBG3(("dmReportGeneralRespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
611   DM_DBG3(("dmReportGeneralRespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
612 
613 #ifndef DIRECT_SMP
614   dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData;
615 #endif
616   pdmSMPReportGeneralResp = &dmSMPReportGeneralResp;
617 
618   dm_memset(&dmSMPReportGeneralResp, 0, sizeof(smpRespReportGeneral_t));
619 
620 #ifdef DIRECT_SMP
621   saFrameReadBlock(agRoot, frameHandle, 4, pdmSMPReportGeneralResp, sizeof(smpRespReportGeneral_t));
622 #else
623   dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
624   saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 4, pdmSMPReportGeneralResp, sizeof(smpRespReportGeneral_t));
625 #endif
626 
627   onePortContext = oneDeviceData->dmPortContext;
628   discovery = &(onePortContext->discovery);
629 
630   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
631   {
632     DM_DBG1(("dmReportGeneralRespRcvd: invalid port or aborted discovery!!!\n"));
633     return;
634   }
635 
636   if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
637   {
638     oneDeviceData->numOfPhys = (bit8) pdmSMPReportGeneralResp->numOfPhys;
639     oneExpander = oneDeviceData->dmExpander;
640     oneExpander->routingIndex = (bit16) REPORT_GENERAL_GET_ROUTEINDEXES(pdmSMPReportGeneralResp);
641     oneExpander->configReserved = 0;
642     oneExpander->configRouteTable = REPORT_GENERAL_IS_CONFIGURABLE(pdmSMPReportGeneralResp) ? 1 : 0;
643     oneExpander->configuring = REPORT_GENERAL_IS_CONFIGURING(pdmSMPReportGeneralResp) ? 1 : 0;
644     DM_DBG2(("dmReportGeneralRespRcvd: SAS 2 is %d\n", oneExpander->SAS2));
645     DM_DBG3(("dmReportGeneralRespRcvd: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
646     DM_DBG3(("dmReportGeneralRespRcvd: oneExpander %p did %d\n", oneExpander, oneExpander->id));
647 
648     if ( oneExpander->SAS2 == 0 && REPORT_GENERAL_IS_LONG_RESPONSE(pdmSMPReportGeneralResp) == 1)
649     {
650       oneExpander->SAS2 = REPORT_GENERAL_IS_LONG_RESPONSE(pdmSMPReportGeneralResp);
651       DM_DBG2(("dmReportGeneralRespRcvd: SAS 2 Long Response=%d\n", REPORT_GENERAL_IS_LONG_RESPONSE(pdmSMPReportGeneralResp)));
652       dmReportGeneralSend(dmRoot, oneDeviceData);
653       return;
654     }
655 
656     DM_DBG3(("dmReportGeneralRespRcvd: oneExpander=%p numberofPhys=0x%x RoutingIndex=0x%x\n",
657       oneExpander, oneDeviceData->numOfPhys, oneExpander->routingIndex));
658     DM_DBG3(("dmReportGeneralRespRcvd: configRouteTable=%d configuring=%d\n",
659       oneExpander->configRouteTable, oneExpander->configuring));
660 
661     if (oneExpander->configuring == 1)
662     {
663       discovery->retries++;
664       if (discovery->retries >= dmAllShared->MaxRetryDiscovery)
665       {
666         DM_DBG1(("dmReportGeneralRespRcvd: retries are over!!!\n"));
667         DM_DBG1(("dmReportGeneralRespRcvd: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
668         discovery->retries = 0;
669         /* failed the discovery */
670         dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
671       }
672       else
673       {
674         DM_DBG3(("dmReportGeneralRespRcvd: keep retrying\n"));
675         DM_DBG1(("dmReportGeneralRespRcvd: Prep222389 RETRY at %d Maximum Retry is %d\n", discovery->retries, dmAllShared->MaxRetryDiscovery));
676         DM_DBG1(("dmReportGeneralRespRcvd: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
677         // start timer for sending ReportGeneral
678         dmDiscoveryConfiguringTimer(dmRoot, onePortContext, oneDeviceData);
679       }
680     }
681     else
682     {
683       discovery->retries = 0;
684       dmDiscoverSend(dmRoot, oneDeviceData);
685     }
686   }
687   else
688   {
689      DM_DBG1(("dmReportGeneralRespRcvd: SMP failed; fn result 0x%x; stopping discovery !!!\n", frameHeader->smpFunctionResult));
690      dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
691   }
692   return;
693 }
694 
695 osGLOBAL void
696 dmReportGeneral2RespRcvd(
697                         dmRoot_t              *dmRoot,
698                         agsaRoot_t            *agRoot,
699                         agsaIORequest_t       *agIORequest,
700                         dmDeviceData_t        *oneDeviceData,
701                         dmSMPFrameHeader_t    *frameHeader,
702                         agsaFrameHandle_t     frameHandle
703                         )
704 {
705   smpRespReportGeneral2_t      dmSMPReportGeneral2Resp;
706   smpRespReportGeneral2_t      *pdmSMPReportGeneral2Resp;
707   dmExpander_t                 *oneExpander = agNULL;
708   dmIntPortContext_t           *onePortContext = agNULL;
709   dmDiscovery_t                *discovery;
710 #ifndef DIRECT_SMP
711   dmSMPRequestBody_t           *dmSMPRequestBody;
712   dmSMPRequestBody_t           *dmSMPResponseBody = agNULL;
713 #endif
714   bit32                        ConfiguresOthers = agFALSE;
715   dmIntRoot_t         *dmIntRoot   = (dmIntRoot_t *)dmRoot->dmData;
716   dmIntContext_t      *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
717 
718 
719   DM_DBG2(("dmReportGeneral2RespRcvd: start\n"));
720   DM_DBG2(("dmReportGeneral2RespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
721   DM_DBG2(("dmReportGeneral2RespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
722 
723 #ifndef DIRECT_SMP
724   dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData;
725 #endif
726   pdmSMPReportGeneral2Resp = &dmSMPReportGeneral2Resp;
727 
728   dm_memset(&dmSMPReportGeneral2Resp, 0, sizeof(smpRespReportGeneral2_t));
729 
730 #ifdef DIRECT_SMP
731   saFrameReadBlock(agRoot, frameHandle, 4, pdmSMPReportGeneral2Resp, sizeof(smpRespReportGeneral2_t));
732 #else
733   dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
734   saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 4, pdmSMPReportGeneral2Resp, sizeof(smpRespReportGeneral2_t));
735 #endif
736 
737   onePortContext = oneDeviceData->dmPortContext;
738   discovery = &(onePortContext->discovery);
739   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
740   {
741     DM_DBG1(("dmReportGeneral2RespRcvd: invalid port or aborted discovery!!!\n"));
742     return;
743   }
744 
745 /* ??? start here */
746   if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
747   {
748     oneDeviceData->numOfPhys = (bit8) pdmSMPReportGeneral2Resp->numOfPhys;
749     oneExpander = oneDeviceData->dmExpander;
750     oneExpander->routingIndex = (bit16) SAS2_REPORT_GENERAL_GET_ROUTEINDEXES(pdmSMPReportGeneral2Resp);
751     oneExpander->configReserved = 0;
752     oneExpander->configRouteTable = SAS2_REPORT_GENERAL_IS_CONFIGURABLE(pdmSMPReportGeneral2Resp) ? 1 : 0;
753     oneExpander->configuring = SAS2_REPORT_GENERAL_IS_CONFIGURING(pdmSMPReportGeneral2Resp) ? 1 : 0;
754     oneExpander->TTTSupported = SAS2_REPORT_GENERAL_IS_TABLE_TO_TABLE_SUPPORTED(pdmSMPReportGeneral2Resp) ? 1 : 0;
755     ConfiguresOthers = SAS2_REPORT_GENERAL_IS_CONFIGURES_OTHERS(pdmSMPReportGeneral2Resp) ? 1 : 0;
756 
757     DM_DBG2(("dmReportGeneral2RespRcvd: SAS 2 is %d\n", oneExpander->SAS2));
758     DM_DBG3(("dmReportGeneral2RespRcvd: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
759     DM_DBG3(("dmReportGeneral2RespRcvd: oneExpander %p did %d\n", oneExpander, oneExpander->id));
760 
761 
762     DM_DBG2(("dmReportGeneral2RespRcvd: oneExpander=%p numberofPhys=0x%x RoutingIndex=0x%x\n",
763       oneExpander, oneDeviceData->numOfPhys, oneExpander->routingIndex));
764     DM_DBG2(("dmReportGeneral2RespRcvd: configRouteTable=%d configuring=%d\n",
765       oneExpander->configRouteTable, oneExpander->configuring));
766     if (ConfiguresOthers)
767     {
768       DM_DBG2(("dmReportGeneral2RespRcvd: ConfiguresOthers is true\n"));
769       discovery->ConfiguresOthers = agTRUE;
770     }
771     if (oneExpander->configuring == 1)
772     {
773       discovery->retries++;
774       if (discovery->retries >= dmAllShared->MaxRetryDiscovery)
775       {
776         DM_DBG1(("dmReportGeneral2RespRcvd: retries are over!!!\n"));
777         DM_DBG1(("dmReportGeneral2RespRcvd: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
778 
779         discovery->retries = 0;
780         /* failed the discovery */
781         dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
782       }
783       else
784       {
785         DM_DBG2(("dmReportGeneral2RespRcvd: keep retrying\n"));
786         DM_DBG1(("dmReportGeneral2RespRcvd: Prep222389 RETRY at %d Maximum Retry is %d\n", discovery->retries, dmAllShared->MaxRetryDiscovery));
787         DM_DBG1(("dmReportGeneral2RespRcvd: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
788         // start timer for sending ReportGeneral
789         dmDiscoveryConfiguringTimer(dmRoot, onePortContext, oneDeviceData);
790       }
791     }
792     else
793     {
794       discovery->retries = 0;
795       dmDiscoverSend(dmRoot, oneDeviceData);
796     }
797   }
798   else
799   {
800      DM_DBG2(("dmReportGeneral2RespRcvd: SMP failed, stopping discovery\n"));
801      dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
802   }
803 
804   return;
805 }
806 
807 
808 osGLOBAL void
809 dmDiscoverSend(
810                dmRoot_t             *dmRoot,
811                dmDeviceData_t       *oneDeviceData
812               )
813 {
814   dmIntRoot_t               *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
815   dmIntContext_t            *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
816   agsaRoot_t                *agRoot = dmAllShared->agRoot;
817   smpReqDiscover_t          smpDiscoverReq;
818   dmExpander_t              *oneExpander;
819 
820   DM_DBG3(("dmDiscoverSend: start\n"));
821   DM_DBG3(("dmDiscoverSend: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
822   oneExpander = oneDeviceData->dmExpander;
823   DM_DBG3(("dmDiscoverSend: oneExpander %p did %d\n", oneExpander, oneExpander->id));
824   DM_DBG3(("dmDiscoverSend: phyID 0x%x\n", oneExpander->discoveringPhyId));
825 
826   dm_memset(&smpDiscoverReq, 0, sizeof(smpReqDiscover_t));
827 
828   smpDiscoverReq.reserved1 = 0;
829   smpDiscoverReq.reserved2 = 0;
830   smpDiscoverReq.phyIdentifier = oneExpander->discoveringPhyId;
831   smpDiscoverReq.reserved3 = 0;
832 
833   dmSMPStart(
834              dmRoot,
835              agRoot,
836              oneDeviceData,
837              SMP_DISCOVER,
838              (bit8 *)&smpDiscoverReq,
839              sizeof(smpReqDiscover_t),
840              AGSA_SMP_INIT_REQ
841              );
842   return;
843 }
844 
845 osGLOBAL void
846 dmDiscoverRespRcvd(
847                    dmRoot_t              *dmRoot,
848                    agsaRoot_t            *agRoot,
849                    agsaIORequest_t       *agIORequest,
850                    dmDeviceData_t        *oneDeviceData,
851                    dmSMPFrameHeader_t    *frameHeader,
852                    agsaFrameHandle_t     frameHandle
853                   )
854 {
855   dmIntPortContext_t           *onePortContext = agNULL;
856   dmDiscovery_t                *discovery;
857   smpRespDiscover_t            *pdmSMPDiscoverResp;
858 #ifndef DIRECT_SMP
859   dmSMPRequestBody_t           *dmSMPRequestBody;
860   dmSMPRequestBody_t           *dmSMPResponseBody = agNULL;
861 #endif
862   dmExpander_t                 *oneExpander = agNULL;
863 
864   DM_DBG3(("dmDiscoverRespRcvd: start\n"));
865   DM_DBG3(("dmDiscoverRespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
866   DM_DBG3(("dmDiscoverRespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
867 
868   onePortContext = oneDeviceData->dmPortContext;
869   oneExpander = oneDeviceData->dmExpander;
870   discovery = &(onePortContext->discovery);
871 #ifndef DIRECT_SMP
872   dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData;
873 #endif
874   DM_DBG3(("dmDiscoverRespRcvd: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
875   DM_DBG3(("dmDiscoverRespRcvd: oneExpander %p did %d\n", oneExpander, oneExpander->id));
876 
877   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
878   {
879     DM_DBG1(("dmDiscoverRespRcvd: invalid port or aborted discovery!!!\n"));
880     return;
881   }
882 
883   pdmSMPDiscoverResp = &(discovery->SMPDiscoverResp);
884 
885 #ifdef DIRECT_SMP
886   saFrameReadBlock(agRoot, frameHandle, 4, pdmSMPDiscoverResp, sizeof(smpRespDiscover_t));
887 #else
888   dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
889   saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 4, pdmSMPDiscoverResp, sizeof(smpRespDiscover_t));
890 #endif
891 
892   if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
893   {
894     if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM)
895     {
896       dmUpStreamDiscoverExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp);
897     }
898     else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
899     {
900       dmDownStreamDiscoverExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp);
901     }
902     else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING)
903     {
904       /* not done with configuring routing
905          1. set the timer
906          2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy()
907       */
908       DM_DBG3(("dmDiscoverRespRcvd: still configuring routing; setting timer\n"));
909       DM_DBG3(("dmDiscoverRespRcvd: onePortContext %p oneDeviceData %p pdmSMPDiscoverResp %p\n", onePortContext, oneDeviceData, pdmSMPDiscoverResp));
910       dmhexdump("dmDiscoverRespRcvd", (bit8*)pdmSMPDiscoverResp, sizeof(smpRespDiscover_t));
911 
912       dmConfigureRouteTimer(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp, agNULL);
913     }
914     else
915     {
916       /* nothing */
917     }
918   }
919   else if (frameHeader->smpFunctionResult == PHY_VACANT)
920   {
921     DM_DBG3(("dmDiscoverRespRcvd: smpFunctionResult is PHY_VACANT, phyid %d\n", oneExpander->discoveringPhyId));
922     if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM)
923     {
924       dmUpStreamDiscoverExpanderPhySkip(dmRoot, onePortContext, oneExpander);
925     }
926     else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
927     {
928       dmDownStreamDiscoverExpanderPhySkip(dmRoot, onePortContext, oneExpander);
929     }
930     else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING)
931     {
932       /* not done with configuring routing
933          1. set the timer
934          2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy()
935       */
936       DM_DBG3(("dmDiscoverRespRcvd: still configuring routing; setting timer\n"));
937       DM_DBG3(("dmDiscoverRespRcvd: onePortContext %p oneDeviceData %p pdmSMPDiscoverResp %p\n", onePortContext, oneDeviceData, pdmSMPDiscoverResp));
938       dmhexdump("dmDiscoverRespRcvd", (bit8*)pdmSMPDiscoverResp, sizeof(smpRespDiscover_t));
939 
940       dmConfigureRouteTimer(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp, agNULL);
941     }
942   }
943   else
944   {
945      DM_DBG1(("dmDiscoverRespRcvd: Discovery Error SMP function return result error=0x%x !!!\n",
946                frameHeader->smpFunctionResult));
947      dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
948   }
949 
950 
951 
952   return;
953 }
954 
955 osGLOBAL void
956 dmDiscover2RespRcvd(
957                    dmRoot_t              *dmRoot,
958                    agsaRoot_t            *agRoot,
959                    agsaIORequest_t       *agIORequest,
960                    dmDeviceData_t        *oneDeviceData,
961                    dmSMPFrameHeader_t    *frameHeader,
962                    agsaFrameHandle_t     frameHandle
963                   )
964 {
965   dmIntPortContext_t           *onePortContext = agNULL;
966   dmDiscovery_t                *discovery;
967   smpRespDiscover2_t           *pdmSMPDiscover2Resp;
968 #ifndef DIRECT_SMP
969   dmSMPRequestBody_t           *dmSMPRequestBody;
970   dmSMPRequestBody_t           *dmSMPResponseBody = agNULL;
971 #endif
972   dmExpander_t                 *oneExpander = agNULL;
973 
974   DM_DBG2(("dmDiscover2RespRcvd: start\n"));
975   DM_DBG2(("dmDiscover2RespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
976   DM_DBG2(("dmDiscover2RespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
977 
978   onePortContext = oneDeviceData->dmPortContext;
979   oneExpander = oneDeviceData->dmExpander;
980   discovery = &(onePortContext->discovery);
981 #ifndef DIRECT_SMP
982   dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData;
983 #endif
984   DM_DBG3(("dmDiscoverRespRcvd: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
985   DM_DBG3(("dmDiscoverRespRcvd: oneExpander %p did %d\n", oneExpander, oneExpander->id));
986 
987   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
988   {
989     DM_DBG1(("dmDiscover2RespRcvd: invalid port or aborted discovery!!!\n"));
990     return;
991   }
992 
993   pdmSMPDiscover2Resp = &(discovery->SMPDiscover2Resp);
994 
995 #ifdef DIRECT_SMP
996   saFrameReadBlock(agRoot, frameHandle, 4, pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t));
997 #else
998   dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
999   saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 4, pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t));
1000 #endif
1001 
1002   if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED )
1003   {
1004     DM_DBG2(("dmDiscover2RespRcvd: phyIdentifier %d\n", pdmSMPDiscover2Resp->phyIdentifier));
1005     DM_DBG2(("dmDiscover2RespRcvd: NegotiatedSSCHWMuxingSupported %d\n", pdmSMPDiscover2Resp->NegotiatedSSCHWMuxingSupported));
1006     DM_DBG2(("dmDiscover2RespRcvd: SAS2_MUXING_SUPPORTED %d\n", SAS2_DISCRSP_IS_MUXING_SUPPORTED(pdmSMPDiscover2Resp)));
1007     DM_DBG2(("dmDiscover2RespRcvd: NegotiatedLogicalLinkRate %d\n", pdmSMPDiscover2Resp->NegotiatedLogicalLinkRate));
1008     DM_DBG2(("dmDiscover2RespRcvd: ReasonNegotiatedPhysicalLinkRate %d\n", pdmSMPDiscover2Resp->ReasonNegotiatedPhysicalLinkRate));
1009     DM_DBG2(("dmDiscover2RespRcvd: SAS2_DISCRSP_GET_LOGICAL_LINKRATE %d\n", SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pdmSMPDiscover2Resp)));
1010     DM_DBG2(("dmDiscover2RespRcvd: SAS2_DISCRSP_GET_LINKRATE %d\n", SAS2_DISCRSP_GET_LINKRATE(pdmSMPDiscover2Resp)));
1011 
1012 //NegotiatedLogicalLinkRate 13
1013 //ReasonNegotiatedPhysicalLinkRate 94
1014     if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM)
1015     {
1016       dmUpStreamDiscover2ExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscover2Resp);
1017     }
1018     else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
1019     {
1020       dmDownStreamDiscover2ExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscover2Resp);
1021     }
1022     else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING)
1023     {
1024       /* not done with configuring routing
1025          1. set the timer
1026          2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy()
1027       */
1028       DM_DBG2(("dmDiscover2RespRcvd: still configuring routing; setting timer\n"));
1029       DM_DBG2(("dmDiscover2RespRcvd: onePortContext %p oneDeviceData %p pdmSMPDiscover2Resp %p\n", onePortContext, oneDeviceData, pdmSMPDiscover2Resp));
1030       dmhexdump("dmDiscover2RespRcvd", (bit8*)pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t));
1031       dmConfigureRouteTimer(dmRoot, onePortContext, oneExpander, agNULL, pdmSMPDiscover2Resp);
1032     }
1033     else
1034     {
1035       /* nothing */
1036     }
1037   }
1038   else if (frameHeader->smpFunctionResult == PHY_VACANT)
1039   {
1040     DM_DBG2(("dmDiscover2RespRcvd: smpFunctionResult is PHY_VACANT, phyid %d\n", oneExpander->discoveringPhyId));
1041     if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM)
1042     {
1043       dmUpStreamDiscover2ExpanderPhySkip(dmRoot, onePortContext, oneExpander);
1044     }
1045     else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM)
1046     {
1047       dmDownStreamDiscover2ExpanderPhySkip(dmRoot, onePortContext, oneExpander);
1048     }
1049     else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING)
1050     {
1051       /* not done with configuring routing
1052          1. set the timer
1053          2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy()
1054       */
1055       DM_DBG2(("dmDiscover2RespRcvd: still configuring routing; setting timer\n"));
1056       DM_DBG2(("dmDiscover2RespRcvd: onePortContext %p oneDeviceData %p pdmSMPDiscover2Resp %p\n", onePortContext, oneDeviceData, pdmSMPDiscover2Resp));
1057       dmhexdump("dmDiscover2RespRcvd", (bit8*)pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t));
1058       dmConfigureRouteTimer(dmRoot, onePortContext, oneExpander, agNULL, pdmSMPDiscover2Resp);
1059     }
1060     else
1061     {
1062       /* nothing */
1063     }
1064   }
1065   else
1066   {
1067      DM_DBG1(("dmDiscover2RespRcvd: Discovery Error SMP function return result error=0x%x\n",
1068                frameHeader->smpFunctionResult));
1069      dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1070   }
1071   return;
1072 }
1073 
1074 #ifdef NOT_YET
1075 osGLOBAL void
1076 tdsaDiscoverList2Send(
1077                  tiRoot_t             *tiRoot,
1078                  tdsaDeviceData_t     *oneDeviceData
1079                  )
1080 {
1081   agsaRoot_t            *agRoot;
1082   tdsaExpander_t        *oneExpander;
1083   smpReqDiscoverList2_t smpDiscoverListReq;
1084 
1085   DM_DBG1(("tdsaDiscoverList2Send: start\n"));
1086   DM_DBG1(("tdsaDiscoverList2Send: device %p did %d\n", oneDeviceData, oneDeviceData->id));
1087   agRoot = oneDeviceData->agRoot;
1088   oneExpander = oneDeviceData->dmExpander;
1089   DM_DBG1(("tdsaDiscoverList2Send: phyID 0x%x\n", oneExpander->discoveringPhyId));
1090 
1091 
1092   osti_memset(&smpDiscoverListReq, 0, sizeof(smpReqDiscoverList2_t));
1093 
1094   smpDiscoverListReq.reserved1 = 0;
1095   smpDiscoverListReq.StartingPhyID = 0;
1096   smpDiscoverListReq.MaxNumDiscoverDesc = 40; /* 40 for SHORT FORMAT; 8 for Long Format; SAS2 p630 */
1097   smpDiscoverListReq.byte10 = 0x2; /* phy filter; all but "no device attached" */
1098   smpDiscoverListReq.byte11 = 0x1; /* descriptor type; SHORT FORMAT */
1099 
1100 
1101   dmSMPStart(
1102              dmRoot,
1103              agRoot,
1104              oneDeviceData,
1105              SMP_DISCOVER_LIST,
1106              (bit8 *)&smpDiscoverListReq,
1107              sizeof(smpReqDiscoverList2_t),
1108              AGSA_SMP_INIT_REQ,
1109              agNULL
1110              );
1111   return;
1112 }
1113 
1114 osGLOBAL void
1115 tdsaDiscoverList2RespRcvd(
1116                      tiRoot_t              *tiRoot,
1117                      agsaRoot_t            *agRoot,
1118                      tdsaDeviceData_t      *oneDeviceData,
1119                      tdssSMPFrameHeader_t  *frameHeader,
1120                      agsaFrameHandle_t     frameHandle
1121                      )
1122 {
1123   return;
1124 }
1125 #endif /* not yet */
1126 
1127 /*****************************************************************************
1128 *! \brief  dmReportPhySataSend
1129 *
1130 *  Purpose:  This function sends Report Phy SATA to a device.
1131 *
1132 *  \param   dmRoot: Pointer to the OS Specific module allocated dmRoot_t
1133 *                   instance.
1134 *  \param   oneDeviceData: Pointer to the device data.
1135 *  \param   phyId: Phy Identifier.
1136 *
1137 *  \return:
1138 *           None
1139 *
1140 *   \note:
1141 *
1142 *****************************************************************************/
1143 osGLOBAL void
1144 dmReportPhySataSend(
1145                     dmRoot_t           *dmRoot,
1146                     dmDeviceData_t     *oneDeviceData,
1147                     bit8               phyId
1148                     )
1149 {
1150   dmIntRoot_t        *dmIntRoot   = (dmIntRoot_t *)dmRoot->dmData;
1151   dmIntContext_t     *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
1152   agsaRoot_t         *agRoot      = dmAllShared->agRoot;
1153   dmExpander_t       *oneExpander;
1154   smpReqReportPhySata_t  smpReportPhySataReq;
1155 
1156   DM_DBG3(("dmReportPhySataSend: start\n"));
1157   DM_DBG3(("dmReportPhySataSend: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id));
1158   DM_DBG3(("dmReportPhySataSend: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
1159   DM_DBG3(("dmReportPhySataSend: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
1160 
1161   oneExpander = oneDeviceData->dmExpander;
1162 
1163   if (oneExpander == agNULL)
1164   {
1165     DM_DBG1(("dmReportPhySataSend: Error!!! expander is NULL\n"));
1166     return;
1167   }
1168   DM_DBG3(("dmReportPhySataSend: device %p did %d\n", oneDeviceData, oneDeviceData->id));
1169   DM_DBG3(("dmReportPhySataSend: phyid %d\n", phyId));
1170 
1171   dm_memset(&smpReportPhySataReq, 0, sizeof(smpReqReportPhySata_t));
1172 
1173   smpReportPhySataReq.phyIdentifier = phyId;
1174 
1175   dmSMPStart(
1176              dmRoot,
1177              agRoot,
1178              oneExpander->dmDevice,
1179              SMP_REPORT_PHY_SATA,
1180              (bit8 *)&smpReportPhySataReq,
1181              sizeof(smpReqReportPhySata_t),
1182              AGSA_SMP_INIT_REQ
1183              );
1184 
1185   return;
1186 }
1187 /*****************************************************************************
1188 *! \brief  dmReportPhySataRcvd
1189 *
1190 *  Purpose:  This function processes Report Phy SATA response.
1191 *
1192 *  \param   dmRoot_t: Pointer to the OS Specific module allocated dmRoot_t
1193 *                   instance.
1194 *  \param   agRoot: Pointer to chip/driver Instance.
1195 *  \param   oneDeviceData: Pointer to the device data.
1196 *  \param   frameHeader: Pointer to SMP frame header.
1197 *  \param   frameHandle: A Handle used to refer to the response frame
1198 *
1199 *  \return:
1200 *           None
1201 *
1202 *   \note:
1203 *
1204 *****************************************************************************/
1205 
1206 osGLOBAL void
1207 dmReportPhySataRcvd(
1208                     dmRoot_t              *dmRoot,
1209                     agsaRoot_t            *agRoot,
1210                     agsaIORequest_t       *agIORequest,
1211                     dmDeviceData_t        *oneDeviceData,
1212                     dmSMPFrameHeader_t    *frameHeader,
1213                     agsaFrameHandle_t     frameHandle
1214                    )
1215 {
1216   smpRespReportPhySata_t      SMPreportPhySataResp;
1217   smpRespReportPhySata_t      *pSMPReportPhySataResp;
1218   dmExpander_t                *oneExpander = oneDeviceData->dmExpander;
1219   dmIntPortContext_t          *onePortContext = agNULL;
1220   agsaFisRegDeviceToHost_t    *fis;
1221   dmDeviceData_t              *SataDevice = agNULL;
1222 #ifndef DIRECT_SMP
1223   dmSMPRequestBody_t          *tdSMPRequestBody;
1224 #endif
1225   bit8                        sataDeviceType;
1226   bit8                        *bit8fis;
1227   bit8                        i = 0;
1228   bit32                       a = 0;
1229   bit8                        bit8fisarray[20];
1230 
1231   DM_DBG3(("dmReportPhySataRcvd: start\n"));
1232   DM_DBG3(("dmReportPhySataRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
1233   DM_DBG3(("dmReportPhySataRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
1234 
1235 #ifndef DIRECT_SMP
1236   tdSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData;
1237 #endif
1238   /* get the current sata device hanlde stored in the expander structure */
1239   if (oneExpander != agNULL)
1240   {
1241       SataDevice = oneExpander->dmDeviceToProcess;
1242   }
1243 
1244   if (SataDevice != agNULL)
1245   {
1246     DM_DBG3(("dmReportPhySataRcvd: sasAddressHi 0x%08x\n", SataDevice->SASAddressID.sasAddressHi));
1247     DM_DBG3(("dmReportPhySataRcvd: sasAddressLo 0x%08x\n", SataDevice->SASAddressID.sasAddressLo));
1248   }
1249   else
1250   {
1251     DM_DBG3(("dmReportPhySataRcvd: SataDevice is NULL\n"));
1252   }
1253 
1254   pSMPReportPhySataResp = &SMPreportPhySataResp;
1255 
1256 #ifdef DIRECT_SMP
1257   saFrameReadBlock(agRoot, frameHandle, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));
1258 #else
1259   saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));
1260 #endif
1261 
1262   /* tdhexdump("dmReportPhySataRcvd", (bit8 *)pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));*/
1263 
1264 #ifndef DIRECT_SMP
1265   ostiFreeMemory(
1266                  dmRoot,
1267                  tdSMPRequestBody->IndirectSMPReqosMemHandle,
1268                  tdSMPRequestBody->IndirectSMPReqLen
1269                 );
1270   ostiFreeMemory(
1271                  dmRoot,
1272                  tdSMPRequestBody->IndirectSMPResposMemHandle,
1273                  tdSMPRequestBody->IndirectSMPRespLen
1274                 );
1275 #endif
1276 
1277   onePortContext = oneDeviceData->dmPortContext;
1278 
1279   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
1280   {
1281     DM_DBG1(("dmReportPhySataRcvd: invalid port or aborted discovery!!!\n"));
1282     return;
1283   }
1284 
1285   if (SataDevice == agNULL)
1286   {
1287     DM_DBG1(("dmReportPhySataRcvd: SataDevice is NULL, wrong\n"));
1288     dmDiscoverAbort(dmRoot, onePortContext);
1289     return;
1290   }
1291 
1292   if (frameHeader->smpFunctionResult == PHY_VACANT )
1293   {
1294      DM_DBG1(("dmReportPhySataRcvd: smpFunctionResult == PHY_VACANT, wrong\n"));
1295      return;
1296   }
1297 
1298   if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED  )
1299   {
1300     fis = (agsaFisRegDeviceToHost_t*) &SMPreportPhySataResp.regDevToHostFis;
1301     if (fis->h.fisType == REG_DEV_TO_HOST_FIS)
1302     {
1303       /* save signature */
1304       DM_DBG3(("dmReportPhySataRcvd: saves the signature\n"));
1305       /* saves signature */
1306       SataDevice->satSignature[0] = fis->d.sectorCount;
1307       SataDevice->satSignature[1] = fis->d.lbaLow;
1308       SataDevice->satSignature[2] = fis->d.lbaMid;
1309       SataDevice->satSignature[3] = fis->d.lbaHigh;
1310       SataDevice->satSignature[4] = fis->d.device;
1311       SataDevice->satSignature[5] = 0;
1312       SataDevice->satSignature[6] = 0;
1313       SataDevice->satSignature[7] = 0;
1314 
1315       DM_DBG3(("dmReportPhySataRcvd: SATA Signature = %02x %02x %02x %02x %02x\n",
1316        SataDevice->satSignature[0],
1317        SataDevice->satSignature[1],
1318        SataDevice->satSignature[2],
1319        SataDevice->satSignature[3],
1320        SataDevice->satSignature[4]));
1321 
1322        sataDeviceType = tddmSATADeviceTypeDecode(SataDevice->satSignature);
1323        if( sataDeviceType == SATA_ATAPI_DEVICE)
1324        {
1325           SataDevice->agDeviceInfo.flag |=  ATAPI_DEVICE_FLAG;
1326        }
1327        SataDevice->dmDeviceInfo.sataDeviceType = sataDeviceType;
1328     }
1329     /* Handling DataDomain buggy FIS */
1330     else if (fis->h.error == REG_DEV_TO_HOST_FIS)
1331     {
1332       /* needs to flip fis to host order */
1333       bit8fis = (bit8*)fis;
1334       for (i=0;i<5;i++)
1335       {
1336         a = DMA_LEBIT32_TO_BIT32(*(bit32*)bit8fis);
1337         DM_DBG3(("dmReportPhySataRcvd: a 0x%8x\n", a));
1338         bit8fisarray[4*i] = (a & 0xFF000000) >> 24;
1339         bit8fisarray[4*i+1] = (a & 0x00FF0000) >> 16;
1340         bit8fisarray[4*i+2] = (a & 0x0000FF00) >> 8;
1341         bit8fisarray[4*i+3] = (a & 0x000000FF);
1342         bit8fis = bit8fis + 4;
1343       }
1344       fis = (agsaFisRegDeviceToHost_t*) bit8fisarray;
1345       /* save signature */
1346       DM_DBG3(("dmReportPhySataRcvd: DataDomain ATAPI saves the signature\n"));
1347       /* saves signature */
1348       SataDevice->satSignature[0] = fis->d.sectorCount;
1349       SataDevice->satSignature[1] = fis->d.lbaLow;
1350       SataDevice->satSignature[2] = fis->d.lbaMid;
1351       SataDevice->satSignature[3] = fis->d.lbaHigh;
1352       SataDevice->satSignature[4] = fis->d.device;
1353       SataDevice->satSignature[5] = 0;
1354       SataDevice->satSignature[6] = 0;
1355       SataDevice->satSignature[7] = 0;
1356 
1357       DM_DBG3(("dmReportPhySataRcvd: SATA Signature = %02x %02x %02x %02x %02x\n",
1358        SataDevice->satSignature[0],
1359        SataDevice->satSignature[1],
1360        SataDevice->satSignature[2],
1361        SataDevice->satSignature[3],
1362        SataDevice->satSignature[4]));
1363 
1364        sataDeviceType = tddmSATADeviceTypeDecode(SataDevice->satSignature);
1365        if( sataDeviceType == SATA_ATAPI_DEVICE)
1366        {
1367           SataDevice->agDeviceInfo.flag |=  ATAPI_DEVICE_FLAG;
1368        }
1369        SataDevice->dmDeviceInfo.sataDeviceType = sataDeviceType;
1370     }
1371     else
1372     {
1373       DM_DBG3(("dmReportPhySataRcvd: getting next stp bride\n"));
1374     }
1375 
1376     /* Continure to report this STP device to TD*/
1377     if (SataDevice->ExpDevice != agNULL)
1378     {
1379        tddmReportDevice(dmRoot, onePortContext->dmPortContext, &SataDevice->dmDeviceInfo, &SataDevice->ExpDevice->dmDeviceInfo, dmDeviceArrival);
1380     }
1381     else
1382     {
1383        tddmReportDevice(dmRoot, onePortContext->dmPortContext, &SataDevice->dmDeviceInfo, agNULL, dmDeviceArrival);
1384     }
1385   }
1386   else
1387   {
1388     DM_DBG3(("dmReportPhySataRcvd: siReportPhySataRcvd SMP function return result %x\n",
1389              frameHeader->smpFunctionResult));
1390     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1391   }
1392 
1393   return;
1394 }
1395 
1396 /*****************************************************************************
1397 *! \brief  dmReportPhySata2Rcvd
1398 *
1399 *  Purpose:  This function processes SAS2.0 Report Phy SATA response.
1400 *
1401 *  \param   dmRoot_t: Pointer to the OS Specific module allocated dmRoot_t
1402 *                   instance.
1403 *  \param   agRoot: Pointer to chip/driver Instance.
1404 *  \param   oneDeviceData: Pointer to the device data.
1405 *  \param   frameHeader: Pointer to SMP frame header.
1406 *  \param   frameHandle: A Handle used to refer to the response frame
1407 *
1408 *  \return:
1409 *           None
1410 *
1411 *   \note:
1412 *
1413 *****************************************************************************/
1414 osGLOBAL void
1415 dmReportPhySata2Rcvd(
1416                     dmRoot_t              *dmRoot,
1417                     agsaRoot_t            *agRoot,
1418                     agsaIORequest_t       *agIORequest,
1419                     dmDeviceData_t        *oneDeviceData,
1420                     dmSMPFrameHeader_t    *frameHeader,
1421                     agsaFrameHandle_t     frameHandle
1422                    )
1423 {
1424    smpRespReportPhySata2_t      SMPreportPhySataResp;
1425    smpRespReportPhySata2_t      *pSMPReportPhySataResp;
1426    dmExpander_t                *oneExpander = oneDeviceData->dmExpander;
1427    dmIntPortContext_t          *onePortContext = agNULL;
1428    agsaFisRegDeviceToHost_t    *fis;
1429    dmDeviceData_t              *SataDevice = agNULL;
1430 #ifndef DIRECT_SMP
1431    dmSMPRequestBody_t          *tdSMPRequestBody;
1432 #endif
1433    bit8                         sataDeviceType = 0;
1434    bit8                        *bit8fis;
1435    bit8                        i = 0;
1436    bit32                       a = 0;
1437    bit8                        bit8fisarray[20];
1438 
1439    DM_DBG3(("dmReportPhySata2Rcvd: start\n"));
1440    DM_DBG3(("dmReportPhySata2Rcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
1441    DM_DBG3(("dmReportPhySata2Rcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
1442 
1443 #ifndef DIRECT_SMP
1444    tdSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData;
1445 #endif
1446    /* get the current sata device hanlde stored in the expander structure */
1447    if (oneExpander != agNULL)
1448    {
1449      SataDevice = oneExpander->dmDeviceToProcess;
1450    }
1451 
1452    if (SataDevice != agNULL)
1453    {
1454      DM_DBG3(("dmReportPhySata2Rcvd: sasAddressHi 0x%08x\n", SataDevice->SASAddressID.sasAddressHi));
1455      DM_DBG3(("dmReportPhySata2Rcvd: sasAddressLo 0x%08x\n", SataDevice->SASAddressID.sasAddressLo));
1456    }
1457    else
1458    {
1459      DM_DBG3(("dmReportPhySataRcvd: SataDevice is NULL\n"));
1460    }
1461 
1462   pSMPReportPhySataResp = &SMPreportPhySataResp;
1463 
1464 #ifdef DIRECT_SMP
1465    saFrameReadBlock(agRoot, frameHandle, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));
1466 #else
1467    saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));
1468 #endif
1469 
1470    /* tdhexdump("dmReportPhySataRcvd", (bit8 *)pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));*/
1471 
1472 #ifndef DIRECT_SMP
1473    ostiFreeMemory(
1474                   dmRoot,
1475                   tdSMPRequestBody->IndirectSMPReqosMemHandle,
1476                   tdSMPRequestBody->IndirectSMPReqLen
1477                  );
1478    ostiFreeMemory(
1479                   dmRoot,
1480                   tdSMPRequestBody->IndirectSMPResposMemHandle,
1481                   tdSMPRequestBody->IndirectSMPRespLen
1482                  );
1483 #endif
1484 
1485    onePortContext = oneDeviceData->dmPortContext;
1486 
1487    if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
1488    {
1489      DM_DBG1(("dmReportPhySata2Rcvd: invalid port or aborted discovery!!!\n"));
1490      return;
1491    }
1492 
1493    if (SataDevice == agNULL)
1494    {
1495      DM_DBG1(("dmReportPhySata2Rcvd: SataDevice is NULL, wrong\n"));
1496      dmDiscoverAbort(dmRoot, onePortContext);
1497      return;
1498    }
1499 
1500    if ( frameHeader->smpFunctionResult == PHY_VACANT )
1501    {
1502       DM_DBG1(("dmReportPhySata2Rcvd: smpFunctionResult == PHY_VACANT, wrong\n"));
1503       return;
1504    }
1505 
1506    if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED )
1507    {
1508      fis = (agsaFisRegDeviceToHost_t*) &SMPreportPhySataResp.regDevToHostFis;
1509      if (fis->h.fisType == REG_DEV_TO_HOST_FIS)
1510      {
1511        /* save signature */
1512        DM_DBG3(("dmReportPhySata2Rcvd: saves the signature\n"));
1513        /* saves signature */
1514        SataDevice->satSignature[0] = fis->d.sectorCount;
1515        SataDevice->satSignature[1] = fis->d.lbaLow;
1516        SataDevice->satSignature[2] = fis->d.lbaMid;
1517        SataDevice->satSignature[3] = fis->d.lbaHigh;
1518        SataDevice->satSignature[4] = fis->d.device;
1519        SataDevice->satSignature[5] = 0;
1520        SataDevice->satSignature[6] = 0;
1521        SataDevice->satSignature[7] = 0;
1522        DM_DBG3(("dmReportPhySata2Rcvd: SATA Signature = %02x %02x %02x %02x %02x\n",
1523         SataDevice->satSignature[0],
1524         SataDevice->satSignature[1],
1525         SataDevice->satSignature[2],
1526         SataDevice->satSignature[3],
1527         SataDevice->satSignature[4]));
1528        sataDeviceType = tddmSATADeviceTypeDecode(SataDevice->satSignature);
1529        if( sataDeviceType == SATA_ATAPI_DEVICE)
1530        {
1531           SataDevice->agDeviceInfo.flag |=  ATAPI_DEVICE_FLAG;
1532        }
1533        SataDevice->dmDeviceInfo.sataDeviceType = sataDeviceType;
1534     }
1535     /* Handling DataDomain buggy FIS */
1536     else if (fis->h.error == REG_DEV_TO_HOST_FIS)
1537     {
1538       /* needs to flip fis to host order */
1539       bit8fis = (bit8*)fis;
1540       for (i=0;i<5;i++)
1541       {
1542         a = DMA_LEBIT32_TO_BIT32(*(bit32*)bit8fis);
1543         DM_DBG3(("dmReportPhySata2Rcvd: a 0x%8x\n", a));
1544         bit8fisarray[4*i] = (a & 0xFF000000) >> 24;
1545         bit8fisarray[4*i+1] = (a & 0x00FF0000) >> 16;
1546         bit8fisarray[4*i+2] = (a & 0x0000FF00) >> 8;
1547         bit8fisarray[4*i+3] = (a & 0x000000FF);
1548         bit8fis = bit8fis + 4;
1549       }
1550       fis = (agsaFisRegDeviceToHost_t*) bit8fisarray;
1551       /* save signature */
1552       DM_DBG3(("dmReportPhySata2Rcvd: DataDomain ATAPI saves the signature\n"));
1553       /* saves signature */
1554       SataDevice->satSignature[0] = fis->d.sectorCount;
1555       SataDevice->satSignature[1] = fis->d.lbaLow;
1556       SataDevice->satSignature[2] = fis->d.lbaMid;
1557       SataDevice->satSignature[3] = fis->d.lbaHigh;
1558       SataDevice->satSignature[4] = fis->d.device;
1559       SataDevice->satSignature[5] = 0;
1560       SataDevice->satSignature[6] = 0;
1561       SataDevice->satSignature[7] = 0;
1562       DM_DBG3(("dmReportPhySata2Rcvd: SATA Signature = %02x %02x %02x %02x %02x\n",
1563        SataDevice->satSignature[0],
1564        SataDevice->satSignature[1],
1565        SataDevice->satSignature[2],
1566        SataDevice->satSignature[3],
1567        SataDevice->satSignature[4]));
1568 
1569        sataDeviceType = tddmSATADeviceTypeDecode(SataDevice->satSignature);
1570        if( sataDeviceType == SATA_ATAPI_DEVICE)
1571        {
1572           SataDevice->agDeviceInfo.flag |=  ATAPI_DEVICE_FLAG;
1573        }
1574        SataDevice->dmDeviceInfo.sataDeviceType = sataDeviceType;
1575     }
1576     else
1577     {
1578       DM_DBG3(("dmReportPhySata2Rcvd: getting next stp bride\n"));
1579     }
1580 
1581     /* Continue to report this STP device to TD*/
1582     if (SataDevice->ExpDevice != agNULL)
1583     {
1584        tddmReportDevice(dmRoot, onePortContext->dmPortContext, &SataDevice->dmDeviceInfo, &SataDevice->ExpDevice->dmDeviceInfo, dmDeviceArrival);
1585     }
1586     else
1587     {
1588        tddmReportDevice(dmRoot, onePortContext->dmPortContext, &SataDevice->dmDeviceInfo, agNULL, dmDeviceArrival);
1589     }
1590 
1591    }
1592    else
1593    {
1594      DM_DBG3(("dmReportPhySata2Rcvd: siReportPhySataRcvd SMP function return result %x\n",
1595               frameHeader->smpFunctionResult));
1596      dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1597    }
1598 
1599    return;
1600 }
1601 
1602 
1603 
1604 osGLOBAL bit32
1605 dmRoutingEntryAdd(
1606                   dmRoot_t          *dmRoot,
1607                   dmExpander_t      *oneExpander,
1608                   bit32             phyId,
1609                   bit32             configSASAddressHi,
1610                   bit32             configSASAddressLo
1611                  )
1612 {
1613   dmIntRoot_t                             *dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
1614   dmIntContext_t                          *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
1615   agsaRoot_t                              *agRoot = dmAllShared->agRoot;
1616   bit32                                   ret = agTRUE;
1617   dmIntPortContext_t                      *onePortContext;
1618   smpReqConfigureRouteInformation_t       confRoutingInfo;
1619   bit32                                   i;
1620 
1621   DM_DBG3(("dmRoutingEntryAdd: start\n"));
1622   DM_DBG3(("dmRoutingEntryAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
1623   DM_DBG3(("dmRoutingEntryAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
1624   DM_DBG3(("dmRoutingEntryAdd: phyid %d\n", phyId));
1625 
1626   if (oneExpander->dmDevice->SASAddressID.sasAddressHi == configSASAddressHi &&
1627       oneExpander->dmDevice->SASAddressID.sasAddressLo == configSASAddressLo
1628      )
1629   {
1630     DM_DBG3(("dmRoutingEntryAdd: unnecessary\n"));
1631     return ret;
1632   }
1633   if (oneExpander->routingAttribute[phyId] != SAS_ROUTING_TABLE)
1634   {
1635     DM_DBG3(("dmRoutingEntryAdd: not table routing, routing is %d\n", oneExpander->routingAttribute[phyId]));
1636     return ret;
1637   }
1638 
1639   onePortContext = oneExpander->dmDevice->dmPortContext;
1640 
1641   onePortContext->discovery.status = DISCOVERY_CONFIG_ROUTING;
1642 
1643   /* reset smpReqConfigureRouteInformation_t */
1644   dm_memset(&confRoutingInfo, 0, sizeof(smpReqConfigureRouteInformation_t));
1645   if ( oneExpander->currentIndex[phyId] < oneExpander->routingIndex )
1646   {
1647     DM_DBG3(("dmRoutingEntryAdd: adding sasAddressHi 0x%08x\n", configSASAddressHi));
1648     DM_DBG3(("dmRoutingEntryAdd: adding sasAddressLo 0x%08x\n", configSASAddressLo));
1649     DM_DBG3(("dmRoutingEntryAdd: phyid %d currentIndex[phyid] %d\n", phyId, oneExpander->currentIndex[phyId]));
1650 
1651     oneExpander->configSASAddressHi = configSASAddressHi;
1652     oneExpander->configSASAddressLo = configSASAddressLo;
1653     confRoutingInfo.reserved1[0] = 0;
1654     confRoutingInfo.reserved1[1] = 0;
1655     OSSA_WRITE_BE_16(agRoot, confRoutingInfo.expanderRouteIndex, 0, (oneExpander->currentIndex[phyId]));
1656     confRoutingInfo.reserved2 = 0;
1657     confRoutingInfo.phyIdentifier = (bit8)phyId;
1658     confRoutingInfo.reserved3[0] = 0;
1659     confRoutingInfo.reserved3[1] = 0;
1660     confRoutingInfo.disabledBit_reserved4 = 0;
1661     confRoutingInfo.reserved5[0] = 0;
1662     confRoutingInfo.reserved5[1] = 0;
1663     confRoutingInfo.reserved5[2] = 0;
1664     OSSA_WRITE_BE_32(agRoot, confRoutingInfo.routedSasAddressHi, 0, configSASAddressHi);
1665     OSSA_WRITE_BE_32(agRoot, confRoutingInfo.routedSasAddressLo, 0, configSASAddressLo);
1666     for ( i = 0; i < 16; i ++ )
1667     {
1668       confRoutingInfo.reserved6[i] = 0;
1669     }
1670     dmSMPStart(dmRoot, agRoot, oneExpander->dmDevice, SMP_CONFIGURE_ROUTING_INFORMATION, (bit8 *)&confRoutingInfo, sizeof(smpReqConfigureRouteInformation_t), AGSA_SMP_INIT_REQ);
1671 
1672     oneExpander->currentIndex[phyId] ++;
1673   }
1674   else
1675   {
1676     DM_DBG3(("dmRoutingEntryAdd: Discovery Error routing index overflow for currentIndex=%d, routingIndex=%d\n", oneExpander->currentIndex[phyId], oneExpander->routingIndex));
1677     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1678 
1679     ret = agFALSE;
1680   }
1681   return ret;
1682 }
1683 
1684 
1685 osGLOBAL void
1686 dmConfigRoutingInfoRespRcvd(
1687                             dmRoot_t              *dmRoot,
1688                             agsaRoot_t            *agRoot,
1689                             agsaIORequest_t       *agIORequest,
1690                             dmDeviceData_t        *oneDeviceData,
1691                             dmSMPFrameHeader_t    *frameHeader,
1692                             agsaFrameHandle_t     frameHandle
1693                            )
1694 {
1695   dmIntPortContext_t                    *onePortContext;
1696   dmExpander_t                          *oneExpander = oneDeviceData->dmExpander;
1697   dmExpander_t                          *UpStreamExpander;
1698   dmExpander_t                          *DownStreamExpander;
1699   dmExpander_t                          *ReturningExpander;
1700   dmExpander_t                          *ConfigurableExpander;
1701   dmDeviceData_t                        *ReturningExpanderDeviceData = agNULL;
1702   bit32                                 dupConfigSASAddr = agFALSE;
1703 
1704 
1705   DM_DBG3(("dmConfigRoutingInfoRespRcvd: start\n"));
1706   DM_DBG3(("dmConfigRoutingInfoRespRcvd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
1707   DM_DBG3(("dmConfigRoutingInfoRespRcvd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
1708 
1709   onePortContext = oneDeviceData->dmPortContext;
1710 
1711   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
1712   {
1713     DM_DBG1(("dmConfigRoutingInfoRespRcvd: invalid port or aborted discovery!!!\n"));
1714     return;
1715   }
1716 
1717   if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ||
1718        frameHeader->smpFunctionResult == PHY_VACANT
1719      )
1720   {
1721     DownStreamExpander = oneExpander->dmCurrentDownStreamExpander;
1722     if (DownStreamExpander != agNULL)
1723     {
1724       DownStreamExpander->currentUpStreamPhyIndex ++;
1725       DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex));
1726       DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander->numOfUpStreamPhys %d\n", DownStreamExpander->numOfUpStreamPhys));
1727       DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander addrHi 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressHi));
1728       DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander addrLo 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressLo));
1729 
1730     }
1731 
1732     oneExpander->currentDownStreamPhyIndex++;
1733     DM_DBG3(("dmConfigRoutingInfoRespRcvd: oneExpander->currentDownStreamPhyIndex %d oneExpander->numOfDownStreamPhys %d\n", oneExpander->currentDownStreamPhyIndex, oneExpander->numOfDownStreamPhys));
1734 
1735     if ( (DownStreamExpander != agNULL) &&
1736          (DownStreamExpander->currentUpStreamPhyIndex < DownStreamExpander->numOfUpStreamPhys)
1737        )
1738     {
1739       DM_DBG3(("dmConfigRoutingInfoRespRcvd: first if\n"));
1740       DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex));
1741 
1742       DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander->upStreamPhys[] %d\n", DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex]));
1743 
1744       dmRoutingEntryAdd(dmRoot,
1745                            oneExpander,
1746                            DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex],
1747                            oneExpander->configSASAddressHi,
1748                            oneExpander->configSASAddressLo
1749                           );
1750     }
1751     else
1752     {
1753       /* traversing up till discovery Root onePortContext->discovery.RootExp */
1754       DM_DBG3(("dmConfigRoutingInfoRespRcvd: else\n"));
1755 
1756       UpStreamExpander = oneExpander->dmUpStreamExpander;
1757       ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
1758       if (UpStreamExpander != agNULL)
1759       {
1760         DM_DBG3(("dmConfigRoutingInfoRespRcvd: UpStreamExpander addrHi 0x%08x\n", UpStreamExpander->dmDevice->SASAddressID.sasAddressHi));
1761         DM_DBG3(("dmConfigRoutingInfoRespRcvd: UpStreamExpander addrLo 0x%08x\n", UpStreamExpander->dmDevice->SASAddressID.sasAddressLo));
1762       }
1763       else
1764       {
1765         DM_DBG3(("dmConfigRoutingInfoRespRcvd: UpStreamExpander is NULL\n"));
1766       }
1767       dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot,
1768                                                   ConfigurableExpander,
1769                                                   oneExpander->configSASAddressHi,
1770                                                   oneExpander->configSASAddressLo
1771                                                   );
1772 
1773       if ( ConfigurableExpander != agNULL && dupConfigSASAddr == agFALSE)
1774       {
1775         DM_DBG3(("dmConfigRoutingInfoRespRcvd: else if\n"));
1776 
1777         DM_DBG3(("dmConfigRoutingInfoRespRcvd: ConfigurableExpander addrHi 0x%08x\n", ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi));
1778         DM_DBG3(("dmConfigRoutingInfoRespRcvd: ConfigurableExpander addrLo 0x%08x\n", ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo));
1779 
1780         if ( UpStreamExpander != agNULL)
1781         {
1782           UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
1783         }
1784         ConfigurableExpander->currentDownStreamPhyIndex =
1785                 dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
1786         ConfigurableExpander->dmReturnginExpander = oneExpander->dmReturnginExpander;
1787         if ( DownStreamExpander != agNULL)
1788         {
1789           DownStreamExpander->currentUpStreamPhyIndex = 0;
1790         }
1791         DM_DBG3(("dmConfigRoutingInfoRespRcvd: ConfigurableExpander->currentDownStreamPhyIndex %d\n", ConfigurableExpander->currentDownStreamPhyIndex));
1792 
1793         DM_DBG3(("dmConfigRoutingInfoRespRcvd: ConfigurableExpander->downStreamPhys[] %d\n", ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex]));
1794         dmRoutingEntryAdd(dmRoot,
1795                              ConfigurableExpander,
1796                              ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
1797                              oneExpander->configSASAddressHi,
1798                              oneExpander->configSASAddressLo
1799                             );
1800       }
1801       else
1802       {
1803         /* going back to where it was */
1804         /* ConfigRoutingInfo is done for a target */
1805         DM_DBG3(("dmConfigRoutingInfoRespRcvd: $$$$$$ my change $$$$$ \n"));
1806         ReturningExpander = oneExpander->dmReturnginExpander;
1807         if ( DownStreamExpander != agNULL)
1808         {
1809           DownStreamExpander->currentUpStreamPhyIndex = 0;
1810         }
1811         /* debugging */
1812         if (ReturningExpander != agNULL)
1813         {
1814           DM_DBG3(("dmConfigRoutingInfoRespRcvd: ReturningExpander addrHi 0x%08x\n", ReturningExpander->dmDevice->SASAddressID.sasAddressHi));
1815           DM_DBG3(("dmConfigRoutingInfoRespRcvd: ReturningExpander addrLo 0x%08x\n", ReturningExpander->dmDevice->SASAddressID.sasAddressLo));
1816           ReturningExpanderDeviceData = ReturningExpander->dmDevice;
1817         }
1818 
1819         /* No longer in DISCOVERY_CONFIG_ROUTING */
1820         onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
1821 
1822         if (ReturningExpander != agNULL && ReturningExpanderDeviceData != agNULL)
1823         {
1824       /* If not the last phy */
1825           if ( ReturningExpander->discoveringPhyId < ReturningExpanderDeviceData->numOfPhys )
1826           {
1827             DM_DBG3(("dmConfigRoutingInfoRespRcvd: More Phys to discover\n"));
1828             /* continue discovery for the next phy */
1829             /* needs to send only one Discovery not multiple times */
1830             if (ReturningExpander->discoverSMPAllowed == agTRUE)
1831             {
1832               dmDiscoverSend(dmRoot, ReturningExpanderDeviceData);
1833             }
1834             if (ReturningExpander != agNULL)
1835             {
1836               ReturningExpander->discoverSMPAllowed = agFALSE;
1837             }
1838           }
1839           /* If the last phy */
1840           else
1841           {
1842             DM_DBG3(("dmConfigRoutingInfoRespRcvd: No More Phys\n"));
1843             ReturningExpander->discoverSMPAllowed = agTRUE;
1844 
1845             /* remove the expander from the discovering list */
1846             dmDiscoveringExpanderRemove(dmRoot, onePortContext, ReturningExpander);
1847             /* continue downstream discovering */
1848             dmDownStreamDiscovering(dmRoot, onePortContext, ReturningExpanderDeviceData);
1849 
1850             //DownStreamExpander
1851           }
1852     }
1853       }
1854     }
1855   }
1856   else
1857   {
1858     DM_DBG1(("dmConfigRoutingInfoRespRcvd: Discovery Error SMP function return result error=0x%x !!!\n", frameHeader->smpFunctionResult));
1859     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
1860   }
1861   return;
1862 }
1863 
1864 osGLOBAL void
1865 dmConfigRoutingInfo2RespRcvd(
1866                             dmRoot_t              *dmRoot,
1867                             agsaRoot_t            *agRoot,
1868                             agsaIORequest_t       *agIORequest,
1869                             dmDeviceData_t        *oneDeviceData,
1870                             dmSMPFrameHeader_t    *frameHeader,
1871                             agsaFrameHandle_t     frameHandle
1872                            )
1873 {
1874   dmExpander_t                            *oneExpander = oneDeviceData->dmExpander;
1875   dmExpander_t                            *UpStreamExpander;
1876   dmExpander_t                            *DownStreamExpander;
1877   dmExpander_t                            *ReturningExpander;
1878   dmExpander_t                            *ConfigurableExpander;
1879 
1880   dmIntPortContext_t                      *onePortContext;
1881   dmDeviceData_t                          *ReturningExpanderDeviceData = agNULL;
1882   bit32                                   dupConfigSASAddr = agFALSE;
1883 
1884   DM_DBG2(("dmConfigRoutingInfo2RespRcvd: start\n"));
1885   DM_DBG2(("dmConfigRoutingInfo2RespRcvd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi));
1886   DM_DBG2(("dmConfigRoutingInfo2RespRcvd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo));
1887 
1888   onePortContext = oneDeviceData->dmPortContext;
1889 
1890   if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE)
1891   {
1892     DM_DBG1(("dmConfigRoutingInfo2RespRcvd: invalid port or aborted discovery!!!\n"));
1893     return;
1894   }
1895 
1896   if (frameHeader->smpFunctionResult == PHY_VACANT)
1897   {
1898     DM_DBG1(("dmConfigRoutingInfo2RespRcvd: smpFunctionResult is PHY_VACANT\n"));
1899   }
1900 
1901   if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ||
1902        frameHeader->smpFunctionResult == PHY_VACANT
1903      )
1904   {
1905     DownStreamExpander = oneExpander->dmCurrentDownStreamExpander;
1906     if (DownStreamExpander != agNULL)
1907     {
1908       DownStreamExpander->currentUpStreamPhyIndex ++;
1909       DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex));
1910       DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander->numOfUpStreamPhys %d\n", DownStreamExpander->numOfUpStreamPhys));
1911       DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander addrHi 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressHi));
1912       DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander addrLo 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressLo));
1913 
1914     }
1915 
1916     oneExpander->currentDownStreamPhyIndex++;
1917     DM_DBG2(("dmConfigRoutingInfo2RespRcvd: oneExpander->currentDownStreamPhyIndex %d oneExpander->numOfDownStreamPhys %d\n", oneExpander->currentDownStreamPhyIndex, oneExpander->numOfDownStreamPhys));
1918 
1919     if ( (DownStreamExpander != agNULL) &&
1920          (DownStreamExpander->currentUpStreamPhyIndex < DownStreamExpander->numOfUpStreamPhys)
1921        )
1922     {
1923       DM_DBG2(("dmConfigRoutingInfo2RespRcvd: first if\n"));
1924       DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex));
1925 
1926       DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander->upStreamPhys[] %d\n", DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex]));
1927 
1928       dmRoutingEntryAdd(dmRoot,
1929                         oneExpander,
1930                         DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex],
1931                         oneExpander->configSASAddressHi,
1932                         oneExpander->configSASAddressLo
1933                        );
1934     }
1935     else
1936     {
1937       /* traversing up till discovery Root onePortContext->discovery.RootExp */
1938       DM_DBG2(("dmConfigRoutingInfo2RespRcvd: else\n"));
1939 
1940       UpStreamExpander = oneExpander->dmUpStreamExpander;
1941       ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander);
1942       if (UpStreamExpander != agNULL)
1943       {
1944         DM_DBG2(("dmConfigRoutingInfo2RespRcvd: UpStreamExpander addrHi 0x%08x\n", UpStreamExpander->dmDevice->SASAddressID.sasAddressHi));
1945         DM_DBG2(("dmConfigRoutingInfo2RespRcvd: UpStreamExpander addrLo 0x%08x\n", UpStreamExpander->dmDevice->SASAddressID.sasAddressLo));
1946       }
1947       else
1948       {
1949         DM_DBG2(("dmConfigRoutingInfo2RespRcvd: UpStreamExpander is NULL\n"));
1950       }
1951       dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot,
1952                                                   ConfigurableExpander,
1953                                                   oneExpander->configSASAddressHi,
1954                                                   oneExpander->configSASAddressLo
1955                                                   );
1956 
1957       if ( ConfigurableExpander != agNULL && dupConfigSASAddr == agFALSE)
1958       {
1959         DM_DBG2(("dmConfigRoutingInfo2RespRcvd: else if\n"));
1960 
1961         DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ConfigurableExpander addrHi 0x%08x\n", ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi));
1962         DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ConfigurableExpander addrLo 0x%08x\n", ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo));
1963 
1964         if ( UpStreamExpander != agNULL)
1965         {
1966     UpStreamExpander->dmCurrentDownStreamExpander = oneExpander;
1967         }
1968         ConfigurableExpander->currentDownStreamPhyIndex =
1969                 dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander);
1970         ConfigurableExpander->dmReturnginExpander = oneExpander->dmReturnginExpander;
1971         if ( DownStreamExpander != agNULL)
1972         {
1973           DownStreamExpander->currentUpStreamPhyIndex = 0;
1974         }
1975         DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ConfigurableExpander->currentDownStreamPhyIndex %d\n", ConfigurableExpander->currentDownStreamPhyIndex));
1976 
1977         DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ConfigurableExpander->downStreamPhys[] %d\n", ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex]));
1978         dmRoutingEntryAdd(dmRoot,
1979                           ConfigurableExpander,
1980                           ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex],
1981                           oneExpander->configSASAddressHi,
1982                           oneExpander->configSASAddressLo
1983                          );
1984       }
1985       else
1986       {
1987         /* going back to where it was */
1988         /* ConfigRoutingInfo is done for a target */
1989         DM_DBG2(("dmConfigRoutingInfo2RespRcvd: $$$$$$ my change $$$$$ \n"));
1990         ReturningExpander = oneExpander->dmReturnginExpander;
1991         if ( DownStreamExpander != agNULL)
1992         {
1993           DownStreamExpander->currentUpStreamPhyIndex = 0;
1994         }
1995         /* debugging */
1996         if (ReturningExpander != agNULL)
1997         {
1998            DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ReturningExpander addrHi 0x%08x\n", ReturningExpander->dmDevice->SASAddressID.sasAddressHi));
1999            DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ReturningExpander addrLo 0x%08x\n", ReturningExpander->dmDevice->SASAddressID.sasAddressLo));
2000            ReturningExpanderDeviceData = ReturningExpander->dmDevice;
2001         }
2002 
2003         /* No longer in DISCOVERY_CONFIG_ROUTING */
2004         onePortContext->discovery.status = DISCOVERY_DOWN_STREAM;
2005 
2006         if (ReturningExpander != agNULL && ReturningExpanderDeviceData != agNULL)
2007         {
2008       /* If not the last phy */
2009           if ( ReturningExpander->discoveringPhyId < ReturningExpanderDeviceData->numOfPhys )
2010           {
2011             DM_DBG2(("dmConfigRoutingInfo2RespRcvd: More Phys to discover\n"));
2012             /* continue discovery for the next phy */
2013             /* needs to send only one Discovery not multiple times */
2014             if (ReturningExpander->discoverSMPAllowed == agTRUE)
2015             {
2016               dmDiscoverSend(dmRoot, ReturningExpanderDeviceData);
2017             }
2018             if (ReturningExpander != agNULL)
2019             {
2020               ReturningExpander->discoverSMPAllowed = agFALSE;
2021             }
2022           }
2023           /* If the last phy */
2024           else
2025           {
2026             DM_DBG2(("dmConfigRoutingInfo2RespRcvd: No More Phys\n"));
2027             ReturningExpander->discoverSMPAllowed = agTRUE;
2028 
2029             /* remove the expander from the discovering list */
2030             dmDiscoveringExpanderRemove(dmRoot, onePortContext, ReturningExpander);
2031             /* continue downstream discovering */
2032             dmDownStreamDiscovering(dmRoot, onePortContext, ReturningExpanderDeviceData);
2033 
2034             //DownStreamExpander
2035           }
2036         }
2037       }
2038     }
2039   }
2040   else
2041   {
2042     DM_DBG1(("dmConfigRoutingInfo2RespRcvd: Discovery Error SMP function return result error=0x%x!!!\n", frameHeader->smpFunctionResult));
2043     dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2044   }
2045   return;
2046 }
2047 
2048 
2049 /* no task management case here for phyControl*/
2050 
2051 /* no task management case here for phyControl*/
2052 osGLOBAL void
2053 dmPhyControlRespRcvd(
2054                      dmRoot_t              *dmRoot,
2055                      agsaRoot_t            *agRoot,
2056                      agsaIORequest_t       *agIORequest,
2057                      dmDeviceData_t        *oneDeviceData,
2058                      dmSMPFrameHeader_t    *frameHeader,
2059                      agsaFrameHandle_t     frameHandle
2060                     )
2061 {
2062   DM_DBG3(("dmPhyControlRespRcvd: start\n"));
2063   DM_DBG3(("dmPhyControlRespRcvd: expander device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
2064   DM_DBG3(("dmPhyControlRespRcvd: expander device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
2065 
2066   if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
2067   {
2068     DM_DBG3(("dmPhyControlRespRcvd: SMP success\n"));
2069   }
2070   else
2071   {
2072     DM_DBG1(("dmPhyControlRespRcvd: SMP failure; result 0x%x !!!\n", frameHeader->smpFunctionResult));
2073   }
2074 
2075   return;
2076 }
2077 
2078 /* no task management case here for phyControl*/
2079 osGLOBAL void
2080 dmPhyControl2RespRcvd(
2081                      dmRoot_t              *dmRoot,
2082                      agsaRoot_t            *agRoot,
2083                      agsaIORequest_t       *agIORequest,
2084                      dmDeviceData_t        *oneDeviceData,
2085                      dmSMPFrameHeader_t    *frameHeader,
2086                      agsaFrameHandle_t     frameHandle
2087                     )
2088 {
2089   DM_DBG2(("dmPhyControl2RespRcvd: start\n"));
2090   DM_DBG2(("dmPhyControl2RespRcvd: expander device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
2091   DM_DBG2(("dmPhyControl2RespRcvd: expander device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
2092 
2093   if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
2094   {
2095     DM_DBG2(("dmPhyControl2RespRcvd: SMP success\n"));
2096   }
2097   else
2098   {
2099     DM_DBG1(("dmPhyControl2RespRcvd: SMP failure; result 0x%x !!!\n", frameHeader->smpFunctionResult));
2100   }
2101 
2102   return;
2103 }
2104 
2105 osGLOBAL void
2106 dmPhyControlFailureRespRcvd(
2107                             dmRoot_t              *dmRoot,
2108                             agsaRoot_t            *agRoot,
2109                             dmDeviceData_t        *oneDeviceData,
2110                             dmSMPFrameHeader_t    *frameHeader,
2111                             agsaFrameHandle_t     frameHandle
2112                            )
2113 {
2114   DM_DBG1(("dmPhyControlFailureRespRcvd: start\n"));
2115   return;
2116 }
2117 
2118 GLOBAL void dmSetDeviceInfoCB(
2119                                 agsaRoot_t        *agRoot,
2120                                 agsaContext_t     *agContext,
2121                                 agsaDevHandle_t   *agDevHandle,
2122                                 bit32             status,
2123                                 bit32             option,
2124                                 bit32             param
2125                                 )
2126 {
2127   dmRoot_t                  *dmRoot = agNULL;
2128   agsaIORequest_t           *agIORequest;
2129   bit32                     smstatus;
2130   agsaSASRequestBody_t      *agSASRequestBody;
2131   dmSMPRequestBody_t        *dmSMPRequestBody = agNULL;
2132   dmIntPortContext_t        *onePortContext = agNULL;
2133   dmDeviceData_t            *oneDeviceData;
2134   bit8                      SMPRequestFunction;
2135   bit8                      devType_S_Rate;
2136   DM_DBG1(("dmSetDeviceInfoCB: start\n"));
2137   DM_DBG4(("dmSetDeviceInfoCB: status 0x%x\n", status));
2138   DM_DBG4(("dmSetDeviceInfoCB: option 0x%x\n", option));
2139   DM_DBG4(("dmSetDeviceInfoCB: param 0x%x\n", param));
2140   if (status != OSSA_SUCCESS)
2141   {
2142     DM_DBG1(("dmSetDeviceInfoCB: status %d\n", status));
2143     DM_DBG1(("dmSetDeviceInfoCB: option 0x%x\n", option));
2144     DM_DBG1(("dmSetDeviceInfoCB: param 0x%x\n", param));
2145     if (option == 32) /* set connection rate */
2146     {
2147       DM_DBG1(("dmSetDeviceInfoCB: IO failure\n"));
2148       agIORequest = (agsaIORequest_t *)agContext->osData;
2149       dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData;
2150       dmRoot = dmSMPRequestBody->dmRoot;
2151       oneDeviceData = dmSMPRequestBody->dmDevice;
2152       onePortContext = oneDeviceData->dmPortContext;
2153       SMPRequestFunction = dmSMPRequestBody->smpPayload[1];
2154       if (SMPRequestFunction == SMP_REPORT_GENERAL ||
2155           SMPRequestFunction == SMP_DISCOVER ||
2156           SMPRequestFunction == SMP_REPORT_PHY_SATA ||
2157           SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2158         )
2159       {
2160         dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2161       }
2162       else if (SMPRequestFunction == SMP_PHY_CONTROL)
2163       {
2164         /* task management failure */
2165         dmPhyControlFailureRespRcvd(
2166                                     dmRoot,
2167                                     agRoot,
2168                                     oneDeviceData,
2169                                     agNULL,
2170                                     agNULL
2171                                    );
2172       }
2173     }
2174   }
2175   if (agDevHandle == agNULL)
2176   {
2177     DM_DBG1(("dmSetDeviceInfoCB: agDevHandle is NULL\n"));
2178     return;
2179   }
2180 
2181   /* retry SMP */
2182   if (option == 32) /* set connection rate */
2183   {
2184     DM_DBG1(("dmSetDeviceInfoCB: set connection rate option\n"));
2185     agIORequest = (agsaIORequest_t *)agContext->osData;
2186     dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData;
2187     dmRoot = dmSMPRequestBody->dmRoot;
2188     agSASRequestBody = &(dmSMPRequestBody->agSASRequestBody);
2189     oneDeviceData = dmSMPRequestBody->dmDevice;
2190     onePortContext = oneDeviceData->dmPortContext;
2191     devType_S_Rate = oneDeviceData->agDeviceInfo.devType_S_Rate;
2192     devType_S_Rate = (devType_S_Rate & 0xF0) | (param >> 28);
2193     oneDeviceData->agDeviceInfo.devType_S_Rate =  devType_S_Rate;
2194     SMPRequestFunction = dmSMPRequestBody->smpPayload[1];
2195     DM_DBG1(("dmSetDeviceInfoCB: SMPRequestFunction 0x%x\n", SMPRequestFunction));
2196     DM_DBG1(("dmSetDeviceInfoCB: new rate is 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo)));
2197     smstatus = saSMPStart(
2198                           agRoot,
2199                           agIORequest,
2200                           0,
2201                           agDevHandle,
2202                           AGSA_SMP_INIT_REQ,
2203                           agSASRequestBody,
2204                           &dmsaSMPCompleted
2205                          );
2206     if (status == AGSA_RC_SUCCESS)
2207     {
2208       /* increment the number of pending SMP */
2209       onePortContext->discovery.pendingSMP++;
2210 //          dmSMPRequestBody->retries++;
2211       if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER ||
2212           SMPRequestFunction == SMP_REPORT_PHY_SATA ||
2213           SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2214          )
2215       {
2216         /* start discovery-related SMP timer */
2217         dmDiscoverySMPTimer(dmRoot, onePortContext, (bit32)SMPRequestFunction, dmSMPRequestBody);
2218       }
2219       return;
2220     }
2221     else if (status == AGSA_RC_BUSY)
2222     {
2223       onePortContext->discovery.pendingSMP++;
2224 //          dmSMPRequestBody->retries++;
2225       if (SMPRequestFunction == SMP_REPORT_GENERAL ||
2226           SMPRequestFunction == SMP_DISCOVER ||
2227           SMPRequestFunction == SMP_REPORT_PHY_SATA ||
2228           SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2229          )
2230       {
2231         dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody);
2232       }
2233       else if (SMPRequestFunction == SMP_PHY_CONTROL)
2234       {
2235         /* For taskmanagement SMP, let's fail task management failure */
2236         dmPhyControlFailureRespRcvd(
2237                                     dmRoot,
2238                                     agRoot,
2239                                     oneDeviceData,
2240                                     agNULL,
2241                                     agNULL
2242                                    );
2243       }
2244       else
2245       {
2246       }
2247     }
2248     else /* AGSA_RC_FAILURE */
2249     {
2250       if (SMPRequestFunction == SMP_REPORT_GENERAL ||
2251           SMPRequestFunction == SMP_DISCOVER ||
2252           SMPRequestFunction == SMP_REPORT_PHY_SATA ||
2253           SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2254          )
2255       {
2256         dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2257       }
2258       else if (SMPRequestFunction == SMP_PHY_CONTROL)
2259       {
2260         /* task management failure */
2261         dmPhyControlFailureRespRcvd(
2262                                     dmRoot,
2263                                     agRoot,
2264                                     oneDeviceData,
2265                                     agNULL,
2266                                     agNULL
2267                                    );
2268       }
2269       else
2270       {
2271       }
2272     }
2273   }
2274   return;
2275 }
2276 /* smp completion */
2277 osGLOBAL void
2278 dmSMPCompleted(
2279                agsaRoot_t            *agRoot,
2280                agsaIORequest_t       *agIORequest,
2281                bit32                 agIOStatus,
2282                bit32                 agIOInfoLen,
2283                agsaFrameHandle_t     agFrameHandle
2284               )
2285 {
2286   dmIntRoot_t               *dmIntRoot    = agNULL;
2287   dmIntContext_t            *dmAllShared = agNULL;
2288   dmSMPRequestBody_t        *dmSMPRequestBody = agNULL;
2289   agsaSMPFrame_t            *agSMPFrame;
2290   dmRoot_t                  *dmRoot = agNULL;
2291   dmIntPortContext_t        *onePortContext = agNULL;
2292   dmIntPortContext_t        *oldonePortContext;
2293   dmExpander_t              *oneExpander = agNULL;
2294   dmDeviceData_t            *oneDeviceData;
2295   agsaDevHandle_t           *agDevHandle = agNULL;
2296   agsaSASRequestBody_t      *agSASRequestBody;
2297   bit8                      smpHeader[4];
2298   bit8                      SMPRequestFunction;
2299   dmSMPFrameHeader_t        *dmResponseSMPFrameHeader;
2300   dmSMPFrameHeader_t        *dmSMPFrameHeader;
2301   bit8                      *dmSMPPayload;
2302   smpReqPhyControl_t        *smpPhyControlReq;
2303   smpReqPhyControl2_t       *smpPhyControl2Req;
2304 #ifndef DIRECT_SMP
2305   dmSMPRequestBody_t        *dmSMPResponseBody = agNULL;
2306   dmSMPFrameHeader_t        *dmRequestSMPFrameHeader;
2307   bit8                      smpRequestHeader[4];
2308 #endif
2309   bit32                     status;
2310   bit32                     ConnRate = SAS_CONNECTION_RATE_12_0G;
2311   agsaContext_t             *agContext = agNULL;
2312 
2313   DM_DBG3(("dmSMPCompleted: start\n"));
2314 
2315   dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData;
2316 
2317   dmRoot = dmSMPRequestBody->dmRoot;
2318   dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
2319   dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
2320 
2321   oneDeviceData = dmSMPRequestBody->dmDevice;
2322   agSASRequestBody = &(dmSMPRequestBody->agSASRequestBody);
2323   agSMPFrame = &(agSASRequestBody->smpFrame);
2324 
2325   if (oneDeviceData->valid == agFALSE &&
2326       oneDeviceData->valid2 == agFALSE &&
2327       oneDeviceData->dmPortContext == agNULL &&
2328       dmSMPRequestBody->dmPortContext->valid == agFALSE
2329       )
2330   {
2331     DM_DBG3(("dmSMPCompleted: port has been destroyed\n"));
2332     /* all device, port information have been reset
2333        just put smp to freeList
2334     */
2335     /* SMP request */
2336     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2337     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
2338     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2339 
2340 #ifndef DIRECT_SMP
2341     /* SMP response */
2342     dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2343     if (dmSMPResponseBody == agNULL)
2344     {
2345       DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
2346       return;
2347     }
2348     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2349     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
2350     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2351 #endif
2352     return;
2353   }
2354 
2355   onePortContext = oneDeviceData->dmPortContext;
2356   oneExpander = oneDeviceData->dmExpander;
2357   agDevHandle = oneExpander->agDevHandle;
2358 
2359 
2360 #ifdef DIRECT_SMP
2361   SMPRequestFunction = dmSMPRequestBody->smpPayload[1];
2362 #else
2363   saFrameReadBlock(agRoot, dmSMPRequestBody->IndirectSMP, 0, smpRequestHeader, 4);
2364   dmRequestSMPFrameHeader = (dmSMPFrameHeader_t *)smpRequestHeader;
2365   SMPRequestFunction = dmRequestSMPFrameHeader->smpFunction;
2366 #endif
2367 
2368 #ifdef NOT_IN_USE
2369   /* for debugging; dump SMP request payload */
2370   dmhexdump("smp payload",
2371             (bit8 *)agSASRequestBody->smpFrame.outFrameBuf,
2372             agSASRequestBody->smpFrame.outFrameLen
2373            );
2374   dmhexdump("smp payload new",
2375             (bit8 *)dmSMPRequestBody->smpPayload,
2376             agSASRequestBody->smpFrame.outFrameLen
2377            );
2378 #endif
2379 
2380   /* sanity check */
2381   if (onePortContext != agNULL)
2382   {
2383     DM_DBG5(("dmSMPCompleted: pid %d\n", onePortContext->id));
2384   }
2385   else
2386   {
2387     DM_DBG1(("dmSMPCompleted: Wrong, onePortContext is NULL!!!\n"));
2388     /* SMP request */
2389     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2390     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
2391     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2392 
2393 #ifndef DIRECT_SMP
2394     /* SMP response */
2395     dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2396     if (dmSMPResponseBody == agNULL)
2397     {
2398       DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
2399       return;
2400     }
2401     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2402     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
2403     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2404 #endif
2405     return;
2406   }
2407 
2408   oldonePortContext = dmSMPRequestBody->dmPortContext;
2409   if (oldonePortContext != agNULL)
2410   {
2411     DM_DBG5(("dmSMPCompleted: old pid %d\n", oldonePortContext->id));
2412   }
2413   else
2414   {
2415     DM_DBG1(("dmSMPCompleted: Wrong, oldonePortContext is NULL!!!\n"));
2416     /* SMP request */
2417     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2418     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
2419     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2420 
2421 #ifndef DIRECT_SMP
2422     /* SMP response */
2423     dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2424     if (dmSMPResponseBody == agNULL)
2425     {
2426       DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
2427       return;
2428     }
2429     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2430     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
2431     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2432 #endif
2433     return;
2434   }
2435 
2436   /* decrement the number of pending SMP */
2437   onePortContext->discovery.pendingSMP--;
2438 
2439 
2440   /* for port invalid case;
2441      full discovery -> full discovery; incremental discovery -> full discovery
2442    */
2443   if (onePortContext != oldonePortContext)
2444   {
2445     DM_DBG1(("dmSMPCompleted: portcontext has changed!!!\n"));
2446     if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER ||
2447         SMPRequestFunction == SMP_REPORT_PHY_SATA ||
2448         SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2449         )
2450     {
2451       /* stop SMP timer */
2452       tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
2453       if (onePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE)
2454       {
2455         tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2456         dmKillTimer(
2457                       dmRoot,
2458                       &(onePortContext->discovery.DiscoverySMPTimer)
2459                      );
2460       }
2461       else
2462       {
2463         tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2464       }
2465 
2466       tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
2467       if (oldonePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE)
2468       {
2469         tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2470         dmKillTimer(
2471                       dmRoot,
2472                       &(oldonePortContext->discovery.DiscoverySMPTimer)
2473                      );
2474       }
2475       else
2476       {
2477         tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2478       }
2479     }
2480     /* clean up expanders data strucures; move to free exp when device is cleaned */
2481     dmCleanAllExp(dmRoot, oldonePortContext);
2482     /* remove devices */
2483     dmInternalRemovals(dmRoot, oldonePortContext);
2484 
2485     /* SMP request */
2486     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2487     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
2488     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2489 
2490 #ifndef DIRECT_SMP
2491     /* SMP response */
2492     dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2493     if (dmSMPResponseBody == agNULL)
2494     {
2495       DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
2496       return;
2497     }
2498     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2499     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
2500     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2501 #endif
2502 
2503 
2504     return;
2505   }
2506 
2507   if (onePortContext->valid == agFALSE ||
2508       onePortContext->DiscoveryState == DM_DSTATE_COMPLETED ||
2509       onePortContext->discovery.status == DISCOVERY_SAS_DONE  ||
2510       onePortContext->DiscoveryAbortInProgress == agTRUE
2511      )
2512   {
2513     if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER ||
2514         SMPRequestFunction == SMP_REPORT_PHY_SATA ||
2515         SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2516         )
2517     {
2518       /* stop SMP timer */
2519       tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
2520       if (onePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE)
2521       {
2522         tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2523         dmKillTimer(
2524                     dmRoot,
2525                     &(onePortContext->discovery.DiscoverySMPTimer)
2526                    );
2527       }
2528       else
2529       {
2530         tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2531       }
2532 
2533 
2534 
2535       tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
2536       if (oldonePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE)
2537       {
2538         tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2539         dmKillTimer(
2540                     dmRoot,
2541                     &(oldonePortContext->discovery.DiscoverySMPTimer)
2542                    );
2543       }
2544       else
2545       {
2546         tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2547       }
2548     }
2549 
2550     /* SMP request */
2551     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2552     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
2553     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2554 
2555 #ifndef DIRECT_SMP
2556     /* SMP response */
2557     dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2558     if (dmSMPResponseBody == agNULL)
2559     {
2560       DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
2561       return;
2562     }
2563     tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2564     DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
2565     tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2566 #endif
2567 
2568     if (onePortContext->discovery.pendingSMP == 0)
2569     {
2570       DM_DBG1(("dmSMPCompleted: aborting discovery\n"));
2571       if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED ||
2572           onePortContext->discovery.status == DISCOVERY_SAS_DONE ||
2573           onePortContext->DiscoveryAbortInProgress == agTRUE
2574          )
2575       {
2576         onePortContext->DiscoveryAbortInProgress = agFALSE;
2577         onePortContext->DiscoveryState = DM_DSTATE_COMPLETED;
2578         onePortContext->discovery.status = DISCOVERY_SAS_DONE;
2579         dmCleanAllExp(dmRoot, onePortContext);
2580         if ( onePortContext->DiscoveryAbortInProgress == agTRUE)
2581         {
2582           tddmDiscoverCB(
2583                          dmRoot,
2584                          onePortContext->dmPortContext,
2585                          dmDiscAborted
2586                   );
2587         }
2588       }
2589     }
2590     else
2591     {
2592       DM_DBG3(("dmSMPCompleted: not yet abort; non zero pendingSMP %d\n", onePortContext->discovery.pendingSMP));
2593     }
2594     return;
2595   }
2596 
2597   if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER ||
2598       SMPRequestFunction == SMP_REPORT_PHY_SATA ||
2599       SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2600       )
2601   {
2602     /* stop SMP timer */
2603     tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
2604     if (onePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE)
2605     {
2606       tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2607       dmKillTimer(
2608                   dmRoot,
2609                   &(onePortContext->discovery.DiscoverySMPTimer)
2610                  );
2611     }
2612     else
2613     {
2614       tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2615     }
2616 
2617 
2618     tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK);
2619     if (oldonePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE)
2620     {
2621       tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2622       dmKillTimer(
2623                   dmRoot,
2624                   &(oldonePortContext->discovery.DiscoverySMPTimer)
2625                  );
2626     }
2627     else
2628     {
2629       tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK);
2630     }
2631   }
2632 
2633   if (oneExpander->SAS2 == 0)
2634   {
2635     DM_DBG3(("dmSMPCompleted: SAS 1.1\n"));
2636     if (agIOStatus == OSSA_IO_SUCCESS)
2637     {
2638       //tdhexdump("dmSMPCompleted", (bit8*)agFrameHandle, agIOInfoLen);
2639       /* parsing SMP payload */
2640 #ifdef DIRECT_SMP
2641       saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4);
2642 #else
2643       dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2644       saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 0, smpHeader, 4);
2645 #endif
2646       dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader;
2647 
2648       /* SMP function dependent payload */
2649       switch (dmResponseSMPFrameHeader->smpFunction)
2650       {
2651       case SMP_REPORT_GENERAL:
2652         DM_DBG3(("dmSMPCompleted: report general\n"));
2653         if (agIOInfoLen != sizeof(smpRespReportGeneral_t) + 4 &&
2654             dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
2655         {
2656           DM_DBG3(("dmSMPCompleted: mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (unsigned int)sizeof(smpRespReportGeneral_t) + 4));
2657           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2658 
2659           /* SMP request */
2660           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2661           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
2662           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2663 
2664 #ifndef DIRECT_SMP
2665           /* SMP response */
2666           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2667           if (dmSMPResponseBody == agNULL)
2668           {
2669             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
2670             return;
2671           }
2672           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2673           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
2674           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2675 #endif
2676           return;
2677         }
2678         /* start here */
2679         dmReportGeneralRespRcvd(
2680                                 dmRoot,
2681                                 agRoot,
2682                                 agIORequest,
2683                                 oneDeviceData,
2684                                 dmResponseSMPFrameHeader,
2685                                 agFrameHandle
2686                                 );
2687         break;
2688       case SMP_DISCOVER:
2689         DM_DBG3(("dmSMPCompleted: discover\n"));
2690         if (agIOInfoLen != sizeof(smpRespDiscover_t) + 4 &&
2691             dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
2692         {
2693           DM_DBG3(("dmSMPCompleted: mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (unsigned int)sizeof(smpRespDiscover_t) + 4));
2694           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2695           /* SMP request */
2696           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2697           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
2698           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2699 
2700 #ifndef DIRECT_SMP
2701           /* SMP response */
2702           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2703           if (dmSMPResponseBody == agNULL)
2704           {
2705             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
2706             return;
2707           }
2708           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2709           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
2710           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2711 #endif
2712           return;
2713         }
2714         dmDiscoverRespRcvd(
2715                            dmRoot,
2716                            agRoot,
2717                            agIORequest,
2718                            oneDeviceData,
2719                            dmResponseSMPFrameHeader,
2720                            agFrameHandle
2721                            );
2722         break;
2723       case SMP_REPORT_PHY_SATA:
2724         DM_DBG3(("dmSMPCompleted: report phy sata\n"));
2725         if (agIOInfoLen != sizeof(smpRespReportPhySata_t) + 4 &&
2726             dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
2727         {
2728           DM_DBG3(("dmSMPCompleted: mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (unsigned int)sizeof(smpRespReportPhySata_t) + 4));
2729           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2730           /* SMP request */
2731           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2732           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
2733           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2734 
2735 #ifndef DIRECT_SMP
2736           /* SMP response */
2737           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2738           if (dmSMPResponseBody == agNULL)
2739           {
2740             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
2741             return;
2742           }
2743           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2744           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
2745           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2746 #endif
2747           return;
2748         }
2749         dmReportPhySataRcvd(
2750                             dmRoot,
2751                             agRoot,
2752                             agIORequest,
2753                             oneDeviceData,
2754                             dmResponseSMPFrameHeader,
2755                             agFrameHandle
2756                             );
2757         break;
2758       case SMP_CONFIGURE_ROUTING_INFORMATION:
2759         DM_DBG3(("dmSMPCompleted: configure routing information\n"));
2760         if (agIOInfoLen != 4 &&
2761             dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED)
2762         {
2763           DM_DBG3(("dmSMPCompleted: mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, 4));
2764           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2765           /* SMP request */
2766           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2767           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
2768           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2769 
2770 #ifndef DIRECT_SMP
2771           /* SMP response */
2772           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2773           if (dmSMPResponseBody == agNULL)
2774           {
2775             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
2776             return;
2777           }
2778           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2779           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
2780           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2781 #endif
2782           return;
2783         }
2784         dmConfigRoutingInfoRespRcvd(
2785                                     dmRoot,
2786                                     agRoot,
2787                                     agIORequest,
2788                                     oneDeviceData,
2789                                     dmResponseSMPFrameHeader,
2790                                     agFrameHandle
2791                                     );
2792 
2793         break;
2794       case SMP_PHY_CONTROL:
2795         DM_DBG3(("dmSMPCompleted: phy control\n"));
2796         if (agIOInfoLen != 4 &&
2797             dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) /*zero length is expected */
2798         {
2799           DM_DBG3(("dmSMPCompleted: mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, 4));
2800           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2801 
2802           /* SMP request */
2803           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2804           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
2805           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2806 
2807 #ifndef DIRECT_SMP
2808           /* SMP response */
2809           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
2810           if (dmSMPResponseBody == agNULL)
2811           {
2812             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
2813             return;
2814           }
2815           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
2816           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
2817           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
2818 #endif
2819           return;
2820         }
2821         dmPhyControlRespRcvd(
2822                              dmRoot,
2823                              agRoot,
2824                              agIORequest,
2825                              oneDeviceData,
2826                              dmResponseSMPFrameHeader,
2827                              agFrameHandle
2828                             );
2829         break;
2830       case SMP_REPORT_ROUTING_INFORMATION: /* fall through */
2831       case SMP_REPORT_PHY_ERROR_LOG: /* fall through */
2832       case SMP_PHY_TEST_FUNCTION: /* fall through */
2833       case SMP_REPORT_MANUFACTURE_INFORMATION: /* fall through */
2834       case SMP_READ_GPIO_REGISTER: /* fall through */
2835       case SMP_WRITE_GPIO_REGISTER: /* fall through */
2836       default:
2837         DM_DBG1(("dmSMPCompleted: wrong SMP function 0x%x !!!\n", dmResponseSMPFrameHeader->smpFunction));
2838         DM_DBG1(("dmSMPCompleted: smpFrameType 0x%x !!!\n", dmResponseSMPFrameHeader->smpFrameType));
2839         DM_DBG1(("dmSMPCompleted: smpFunctionResult 0x%x !!!\n", dmResponseSMPFrameHeader->smpFunctionResult));
2840         DM_DBG1(("dmSMPCompleted: smpReserved 0x%x !!!\n", dmResponseSMPFrameHeader->smpReserved));
2841         dmhexdump("dmSMPCompleted: SMP payload !!!", (bit8 *)agFrameHandle, agIOInfoLen);
2842         break;
2843       } /* switch */
2844     } /* OSSA_IO_SUCCESS */
2845     else if (agIOStatus == OSSA_IO_ABORTED || agIOStatus == OSSA_IO_INVALID_LENGTH)
2846     {
2847       /* no retry this case */
2848       DM_DBG1(("dmSMPCompleted: OSSA_IO_ABORTED or OSSA_IO_INVALID_LENGTH, status 0x%x\n", agIOStatus));
2849     }
2850     else if (agIOStatus == OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE)
2851     {
2852       DM_DBG3(("dmSMPCompleted: OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE\n"));
2853       saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4);
2854       dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader;
2855 
2856       status = saSMPStart(
2857                  agRoot,
2858                  agIORequest,
2859                  0,
2860                  agDevHandle,
2861                  AGSA_SMP_INIT_REQ,
2862                  agSASRequestBody,
2863                  &dmsaSMPCompleted
2864                  );
2865 
2866       if (status == AGSA_RC_SUCCESS)
2867       {
2868         /* increment the number of pending SMP */
2869         onePortContext->discovery.pendingSMP++;
2870         if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER ||
2871             SMPRequestFunction == SMP_REPORT_PHY_SATA ||
2872             SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2873            )
2874         {
2875           /* start discovery-related SMP timer */
2876           dmDiscoverySMPTimer(dmRoot, onePortContext, (bit32)(dmResponseSMPFrameHeader->smpFunction), dmSMPRequestBody);
2877         }
2878         return;
2879       }
2880       else if (status == AGSA_RC_BUSY)
2881       {
2882         if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL ||
2883             dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER ||
2884             dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA ||
2885             dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2886            )
2887         {
2888           dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody);
2889         }
2890         else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL)
2891         {
2892           /* For taskmanagement SMP, let's fail task management failure */
2893           dmPhyControlFailureRespRcvd(
2894                                       dmRoot,
2895                                       agRoot,
2896                                       oneDeviceData,
2897                                       dmResponseSMPFrameHeader,
2898                                       agFrameHandle
2899                                      );
2900         }
2901         else
2902         {
2903         }
2904       }
2905       else /* AGSA_RC_FAILURE */
2906       {
2907         if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL ||
2908             dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER ||
2909             dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA ||
2910             dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2911            )
2912         {
2913           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2914         }
2915         else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL)
2916         {
2917           /* task management failure */
2918           dmPhyControlFailureRespRcvd(
2919                                       dmRoot,
2920                                       agRoot,
2921                                       oneDeviceData,
2922                                       dmResponseSMPFrameHeader,
2923                                       agFrameHandle
2924                                      );
2925         }
2926         else
2927         {
2928         }
2929       }
2930     }   /* OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE*/
2931     else
2932     {
2933       if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS ||
2934           agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED ||
2935           agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO ||
2936           agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST ||
2937           agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE ||
2938           agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED ||
2939           agIOStatus == OSSA_IO_DS_NON_OPERATIONAL )
2940       {
2941         DM_DBG1(("dmSMPCompleted: setting back to operational\n"));
2942         saSetDeviceState(agRoot, agNULL, 0, agDevHandle, SA_DS_OPERATIONAL);
2943       }
2944       if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED && dmAllShared->RateAdjust)
2945       {
2946         DM_DBG1(("dmSMPCompleted: OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
2947         DM_DBG1(("dmSMPCompleted: SMPRequestFunction 0x%x\n", SMPRequestFunction));
2948         ConnRate = DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo);
2949         if (ConnRate == SAS_CONNECTION_RATE_1_5G)
2950         {
2951           /* no retry; failure ??? */
2952           if (SMPRequestFunction == SMP_REPORT_GENERAL ||
2953               SMPRequestFunction == SMP_DISCOVER ||
2954               SMPRequestFunction == SMP_REPORT_PHY_SATA ||
2955               SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
2956              )
2957           {
2958             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
2959           }
2960           else if (SMPRequestFunction == SMP_PHY_CONTROL)
2961           {
2962             /* task management failure */
2963             dmPhyControlFailureRespRcvd(
2964                                         dmRoot,
2965                                         agRoot,
2966                                         oneDeviceData,
2967                                         agNULL,
2968                                         agNULL
2969                                        );
2970           }
2971           else
2972           {
2973           }
2974         }
2975         else
2976         {
2977           ConnRate = ConnRate - 1;
2978         }
2979         agContext = &(dmSMPRequestBody->agContext);
2980         agContext->osData = agIORequest;
2981         saSetDeviceInfo(agRoot, agContext, 0, agDevHandle, 32, ConnRate << 28, dmSetDeviceInfoCB);
2982       }
2983       else
2984       {
2985         if (dmSMPRequestBody->retries < SMP_RETRIES) /* 5 */
2986         {
2987           /* retry the SMP again */
2988           DM_DBG1(("dmSMPCompleted: failed, but retries %d agIOStatus 0x%x %d agIOInfoLen %d !!!\n",
2989                    dmSMPRequestBody->retries, agIOStatus, agIOStatus, agIOInfoLen));
2990           saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4);
2991           dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader;
2992           status = saSMPStart(
2993                               agRoot,
2994                               agIORequest,
2995                               0,
2996                               agDevHandle,
2997                               AGSA_SMP_INIT_REQ,
2998                               agSASRequestBody,
2999                               &dmsaSMPCompleted
3000                              );
3001           if (status == AGSA_RC_SUCCESS)
3002           {
3003             /* increment the number of pending SMP */
3004             onePortContext->discovery.pendingSMP++;
3005             dmSMPRequestBody->retries++;
3006             if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER ||
3007                 SMPRequestFunction == SMP_REPORT_PHY_SATA ||
3008                 SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3009                )
3010             {
3011               /* start discovery-related SMP timer */
3012               dmDiscoverySMPTimer(dmRoot, onePortContext, (bit32)(dmResponseSMPFrameHeader->smpFunction), dmSMPRequestBody);
3013             }
3014             return;
3015           }
3016           else if (status == AGSA_RC_BUSY)
3017           {
3018             onePortContext->discovery.pendingSMP++;
3019             dmSMPRequestBody->retries++;
3020             if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL ||
3021                 dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER ||
3022                 dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA ||
3023                 dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3024                )
3025             {
3026               dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody);
3027               return;
3028             }
3029             else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL)
3030             {
3031               /* For taskmanagement SMP, let's fail task management failure */
3032               dmPhyControlFailureRespRcvd(
3033                                           dmRoot,
3034                                           agRoot,
3035                                           oneDeviceData,
3036                                           dmResponseSMPFrameHeader,
3037                                           agFrameHandle
3038                                          );
3039             }
3040             else
3041             {
3042             }
3043           }
3044           else /* AGSA_RC_FAILURE */
3045           {
3046             if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL ||
3047                 dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER ||
3048                 dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA ||
3049                 dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3050                )
3051             {
3052               dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3053             }
3054             else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL)
3055             {
3056               /* task management failure */
3057               dmPhyControlFailureRespRcvd(
3058                                           dmRoot,
3059                                           agRoot,
3060                                           oneDeviceData,
3061                                           dmResponseSMPFrameHeader,
3062                                           agFrameHandle
3063                                          );
3064             }
3065             else
3066             {
3067             }
3068           }
3069         }
3070         else
3071         {
3072           dmSMPFrameHeader = (dmSMPFrameHeader_t *)agSMPFrame->outFrameBuf;
3073           dmSMPPayload = (bit8 *)agSMPFrame->outFrameBuf + 4;
3074           DM_DBG1(("dmSMPCompleted: failed. no more retry. agIOStatus 0x%x %d !!!\n", agIOStatus, agIOStatus));
3075           if (agIOStatus == OSSA_IO_DS_NON_OPERATIONAL)
3076           {
3077             DM_DBG1(("dmSMPCompleted: failed, agIOStatus is OSSA_IO_DS_NON_OPERATIONAL!!!\n"));
3078           }
3079           if (agIOStatus == OSSA_IO_DS_IN_RECOVERY)
3080           {
3081             DM_DBG1(("dmSMPCompleted: failed, agIOStatus is OSSA_IO_DS_IN_RECOVERY!!!\n"));
3082           }
3083           if (dmSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL ||
3084               dmSMPFrameHeader->smpFunction == SMP_DISCOVER ||
3085               dmSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA ||
3086               dmSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3087              )
3088           {
3089             /* discovery failure */
3090             DM_DBG1(("dmSMPCompleted: SMP function 0x%x\n", dmSMPFrameHeader->smpFunction));
3091             DM_DBG1(("dmSMPCompleted: discover done with error\n"));
3092             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3093           }
3094           else if (dmSMPFrameHeader->smpFunction == SMP_PHY_CONTROL)
3095           {
3096             DM_DBG3(("dmSMPCompleted: SMP_PHY_CONTROL\n"));
3097             smpPhyControlReq = (smpReqPhyControl_t *)dmSMPPayload;
3098             if (smpPhyControlReq->phyOperation == SMP_PHY_CONTROL_CLEAR_AFFILIATION)
3099             {
3100               DM_DBG3(("dmSMPCompleted: discover done with error\n"));
3101               dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3102             }
3103             else
3104             {
3105               DM_DBG3(("dmSMPCompleted: unknown phy operation 0x%x\n", smpPhyControlReq->phyOperation));
3106             }
3107           } /* SMP_PHY_CONTROL */
3108           else
3109           {
3110             DM_DBG3(("dmSMPCompleted: SMP function 0x%x\n", dmSMPFrameHeader->smpFunction));
3111           }
3112         } /* else */
3113       } /* for RateAdjust */
3114     } /* outer else */
3115   } /* SAS 1.1 */
3116   /************************************     SAS 2     ***********************************************/
3117   else
3118   {
3119     DM_DBG2(("dmSMPCompleted: SAS 2\n"));
3120     if (agIOStatus == OSSA_IO_SUCCESS)
3121     {
3122       //tdhexdump("dmSMPCompleted", (bit8*)agFrameHandle, agIOInfoLen);
3123       /* parsing SMP payload */
3124 #ifdef DIRECT_SMP
3125     saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4);
3126 #else
3127     dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
3128     saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 0, smpHeader, 4);
3129 #endif
3130     dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader;
3131 
3132       /* SMP function dependent payload */
3133       switch (dmResponseSMPFrameHeader->smpFunction)
3134       {
3135       case SMP_REPORT_GENERAL:
3136         DM_DBG2(("dmSMPCompleted: report general\n"));
3137         if ((agIOInfoLen != sizeof(smpRespReportGeneral2_t) + 4) &&
3138              dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED
3139            )
3140         {
3141           DM_DBG1(("dmSMPCompleted: report general mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (int)sizeof(smpRespReportGeneral2_t) + 4));
3142           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3143 
3144           /* SMP request */
3145           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3146           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
3147           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3148 
3149 #ifndef DIRECT_SMP
3150           /* SMP response */
3151           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
3152           if (dmSMPResponseBody == agNULL)
3153           {
3154             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
3155             return;
3156           }
3157           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3158           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
3159           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3160 #endif
3161 
3162           return;
3163         }
3164 
3165         dmReportGeneral2RespRcvd(
3166                                   dmRoot,
3167                                   agRoot,
3168                                   agIORequest,
3169                                   oneDeviceData,
3170                                   dmResponseSMPFrameHeader,
3171                                   agFrameHandle
3172                                   );
3173         break;
3174       case SMP_DISCOVER:
3175         DM_DBG2(("dmSMPCompleted: discover\n"));
3176         if ((agIOInfoLen != sizeof(smpRespDiscover2_t) + 4) &&
3177              dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED
3178            )
3179         {
3180           DM_DBG1(("dmSMPCompleted: discover mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (int)sizeof(smpRespDiscover2_t) + 4));
3181           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3182 
3183           /* SMP request */
3184           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3185           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
3186           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3187 
3188 #ifndef DIRECT_SMP
3189           /* SMP response */
3190           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
3191           if (dmSMPResponseBody == agNULL)
3192           {
3193             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
3194             return;
3195           }
3196           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3197           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
3198           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3199 #endif
3200 
3201           return;
3202         }
3203         dmDiscover2RespRcvd(
3204                              dmRoot,
3205                              agRoot,
3206                              agIORequest,
3207                                 oneDeviceData,
3208                              dmResponseSMPFrameHeader,
3209                              agFrameHandle
3210                              );
3211         break;
3212       case SMP_REPORT_PHY_SATA:
3213         DM_DBG2(("dmSMPCompleted: report phy sata\n"));
3214         if ((agIOInfoLen != sizeof(smpRespReportPhySata2_t) + 4) &&
3215              dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED
3216            )
3217         {
3218           DM_DBG1(("dmSMPCompleted: report phy sata mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (int)sizeof(smpRespReportPhySata2_t) + 4));
3219           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3220 
3221           /* SMP request */
3222           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3223           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
3224           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3225 
3226 #ifndef DIRECT_SMP
3227           /* SMP response */
3228           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
3229           if (dmSMPResponseBody == agNULL)
3230           {
3231             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
3232             return;
3233           }
3234           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3235           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
3236           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3237 #endif
3238 
3239           return;
3240         }
3241         dmReportPhySata2Rcvd(
3242                               dmRoot,
3243                               agRoot,
3244                               agIORequest,
3245                               oneDeviceData,
3246                               dmResponseSMPFrameHeader,
3247                               agFrameHandle
3248                               );
3249         break;
3250       case SMP_CONFIGURE_ROUTING_INFORMATION:
3251         DM_DBG2(("dmSMPCompleted: configure routing information\n"));
3252         if (agIOInfoLen != 4 &&
3253             dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED
3254            )
3255         {
3256           DM_DBG1(("dmSMPCompleted: configure routing information mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, 4));
3257           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3258 
3259           /* SMP request */
3260           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3261           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
3262           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3263 
3264 #ifndef DIRECT_SMP
3265           /* SMP response */
3266           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
3267           if (dmSMPResponseBody == agNULL)
3268           {
3269             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
3270             return;
3271           }
3272           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3273           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
3274           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3275 #endif
3276 
3277           return;
3278         }
3279         dmConfigRoutingInfo2RespRcvd(
3280                                       dmRoot,
3281                                       agRoot,
3282                                       agIORequest,
3283                                       oneDeviceData,
3284                                       dmResponseSMPFrameHeader,
3285                                       agFrameHandle
3286                                       );
3287 
3288         break;
3289       case SMP_PHY_CONTROL:
3290         DM_DBG2(("dmSMPCompleted: phy control\n"));
3291         if (agIOInfoLen != 4 &&
3292             dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED
3293            ) /*zero length is expected */
3294         {
3295           DM_DBG1(("dmSMPCompleted: phy control mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, 4));
3296           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3297 
3298           /* SMP request */
3299           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3300           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
3301           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3302 
3303 #ifndef DIRECT_SMP
3304           /* SMP response */
3305           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
3306           if (dmSMPResponseBody == agNULL)
3307           {
3308             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
3309             return;
3310           }
3311           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3312           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
3313           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3314 #endif
3315 
3316           return;
3317         }
3318         dmPhyControl2RespRcvd(
3319                                dmRoot,
3320                                agRoot,
3321                                agIORequest,
3322              oneDeviceData,
3323                                dmResponseSMPFrameHeader,
3324                                agFrameHandle
3325             );
3326 
3327 
3328         break;
3329 #ifdef NOT_YET
3330       case SMP_DISCOVER_LIST:
3331         DM_DBG1(("dmSMPCompleted: SMP_DISCOVER_LIST\n"));
3332         DM_DBG1(("dmSMPCompleted: agIOInfoLen 0x%x \n", agIOInfoLen));
3333         tdhexdump("dmSMPCompleted", (bit8*)agFrameHandle, agIOInfoLen);
3334         dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3335 
3336           /* SMP request */
3337           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3338           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
3339           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3340 
3341 #ifndef DIRECT_SMP
3342           /* SMP response */
3343           dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
3344           if (dmSMPResponseBody == agNULL)
3345           {
3346             DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
3347             return;
3348           }
3349           tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3350           DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
3351           tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3352 #endif
3353 
3354         return;
3355         break;
3356 #endif
3357       case SMP_REPORT_ROUTING_INFORMATION: /* fall through */
3358       case SMP_REPORT_PHY_ERROR_LOG: /* fall through */
3359       case SMP_PHY_TEST_FUNCTION: /* fall through */
3360       case SMP_REPORT_MANUFACTURE_INFORMATION: /* fall through */
3361       case SMP_READ_GPIO_REGISTER: /* fall through */
3362       case SMP_WRITE_GPIO_REGISTER: /* fall through */
3363       default:
3364         DM_DBG1(("dmSMPCompleted: wrong SMP function 0x%x\n", dmResponseSMPFrameHeader->smpFunction));
3365         DM_DBG1(("dmSMPCompleted: smpFrameType 0x%x\n", dmResponseSMPFrameHeader->smpFrameType));
3366         DM_DBG1(("dmSMPCompleted: smpFunctionResult 0x%x\n", dmResponseSMPFrameHeader->smpFunctionResult));
3367         DM_DBG1(("dmSMPCompleted: smpReserved 0x%x\n", dmResponseSMPFrameHeader->smpReserved));
3368         dmhexdump("dmSMPCompleted: SMP payload", (bit8 *)agFrameHandle, agIOInfoLen);
3369         break;
3370       }
3371     } /* agIOStatus == OSSA_IO_SUCCESS */
3372     else if (agIOStatus == OSSA_IO_ABORTED || agIOStatus == OSSA_IO_INVALID_LENGTH)
3373     {
3374       /* no retry this case */
3375       DM_DBG1(("dmSMPCompleted: OSSA_IO_ABORTED or OSSA_IO_INVALID_LENGTH, status 0x%x\n", agIOStatus));
3376     }
3377     else if (agIOStatus == OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE)
3378     {
3379       DM_DBG1(("dmSMPCompleted: OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE\n"));
3380       saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4);
3381       dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader;
3382 
3383       status = saSMPStart(
3384                           agRoot,
3385                           agIORequest,
3386                           0,
3387                           agDevHandle,
3388                           AGSA_SMP_INIT_REQ,
3389                           agSASRequestBody,
3390                           &dmsaSMPCompleted
3391                          );
3392 
3393 
3394       if (status == AGSA_RC_SUCCESS)
3395       {
3396         /* increment the number of pending SMP */
3397         onePortContext->discovery.pendingSMP++;
3398         if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER ||
3399             SMPRequestFunction == SMP_REPORT_PHY_SATA ||
3400             SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3401            )
3402         {
3403           /* start discovery-related SMP timer */
3404           dmDiscoverySMPTimer(dmRoot, onePortContext, (bit32)(dmResponseSMPFrameHeader->smpFunction), dmSMPRequestBody);
3405         }
3406         return;
3407       }
3408       else if (status == AGSA_RC_BUSY)
3409       {
3410         if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL ||
3411             dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER ||
3412             dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA ||
3413             dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3414            )
3415         {
3416           dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody);
3417         }
3418         else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL)
3419         {
3420           /* For taskmanagement SMP, let's fail task management failure */
3421           dmPhyControlFailureRespRcvd(
3422                                       dmRoot,
3423                                       agRoot,
3424                                       oneDeviceData,
3425                                       dmResponseSMPFrameHeader,
3426                                       agFrameHandle
3427                                      );
3428         }
3429         else
3430         {
3431         }
3432       }
3433       else /* AGSA_RC_FAILURE */
3434       {
3435         if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL ||
3436             dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER ||
3437             dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA ||
3438             dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3439       )
3440         {
3441           dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3442         }
3443         else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL)
3444         {
3445           /* task management failure */
3446           dmPhyControlFailureRespRcvd(
3447                                       dmRoot,
3448                                       agRoot,
3449                                       oneDeviceData,
3450                                       dmResponseSMPFrameHeader,
3451                                       agFrameHandle
3452                                      );
3453         }
3454         else
3455         {
3456         }
3457       }
3458     }
3459     else if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION)
3460     {
3461       DM_DBG1(("dmSMPCompleted: OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
3462       /*
3463          skip to the next expander
3464       */
3465       dmHandleZoneViolation(
3466                            dmRoot,
3467                            agRoot,
3468                            agIORequest,
3469                            oneDeviceData,
3470                            agNULL,
3471                            agFrameHandle
3472                            );
3473     }
3474     else
3475     {
3476       if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS ||
3477           agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED ||
3478           agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO ||
3479           agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST ||
3480           agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE ||
3481           agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED ||
3482           agIOStatus == OSSA_IO_DS_NON_OPERATIONAL )
3483       {
3484         DM_DBG1(("dmSMPCompleted: setting back to operational\n"));
3485         saSetDeviceState(agRoot, agNULL, 0, agDevHandle, SA_DS_OPERATIONAL);
3486       }
3487       if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED && dmAllShared->RateAdjust)
3488       {
3489         DM_DBG1(("dmSMPCompleted: OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
3490         DM_DBG1(("dmSMPCompleted: SMPRequestFunction 0x%x\n", SMPRequestFunction));
3491         ConnRate = DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo);
3492         if (ConnRate == SAS_CONNECTION_RATE_1_5G)
3493         {
3494           /* no retry; failure ??? */
3495           if (SMPRequestFunction == SMP_REPORT_GENERAL ||
3496               SMPRequestFunction == SMP_DISCOVER ||
3497               SMPRequestFunction == SMP_REPORT_PHY_SATA ||
3498               SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3499              )
3500           {
3501             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3502           }
3503           else if (SMPRequestFunction == SMP_PHY_CONTROL)
3504           {
3505             /* task management failure */
3506             dmPhyControlFailureRespRcvd(
3507                                         dmRoot,
3508                                         agRoot,
3509                                         oneDeviceData,
3510                                         agNULL,
3511                                         agNULL
3512                                        );
3513           }
3514           else
3515           {
3516           }
3517         }
3518         else
3519         {
3520           ConnRate = ConnRate - 1;
3521         }
3522         agContext = &(dmSMPRequestBody->agContext);
3523         agContext->osData = agIORequest;
3524         saSetDeviceInfo(agRoot, agContext, 0, agDevHandle, 32, ConnRate << 28, dmSetDeviceInfoCB);
3525       }
3526       else
3527       {
3528         if (dmSMPRequestBody->retries < SMP_RETRIES) /* 5 */
3529         {
3530           /* retry the SMP again */
3531           DM_DBG1(("dmSMPCompleted: failed! but retries %d agIOStatus 0x%x %d agIOInfoLen %d\n",
3532                    dmSMPRequestBody->retries, agIOStatus, agIOStatus, agIOInfoLen));
3533           saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4);
3534           dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader;
3535           status = saSMPStart(
3536                               agRoot,
3537                               agIORequest,
3538                               0,
3539                               agDevHandle,
3540                               AGSA_SMP_INIT_REQ,
3541                               agSASRequestBody,
3542                               &dmsaSMPCompleted
3543                              );
3544 
3545           if (status == AGSA_RC_SUCCESS)
3546           {
3547             /* increment the number of pending SMP */
3548             onePortContext->discovery.pendingSMP++;
3549             dmSMPRequestBody->retries++;
3550             if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER ||
3551                 SMPRequestFunction == SMP_REPORT_PHY_SATA ||
3552                 SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3553                )
3554             {
3555               /* start discovery-related SMP timer */
3556               dmDiscoverySMPTimer(dmRoot, onePortContext, (bit32)(dmResponseSMPFrameHeader->smpFunction), dmSMPRequestBody);
3557             }
3558             return;
3559           }
3560           else if (status == AGSA_RC_BUSY)
3561           {
3562             onePortContext->discovery.pendingSMP++;
3563             dmSMPRequestBody->retries++;
3564             if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL ||
3565                 dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER ||
3566                 dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA ||
3567                 dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3568                )
3569             {
3570               dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody);
3571               return;
3572             }
3573             else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL)
3574             {
3575               /* For taskmanagement SMP, let's fail task management failure */
3576               dmPhyControlFailureRespRcvd(
3577                                           dmRoot,
3578                                           agRoot,
3579                                           oneDeviceData,
3580                                           dmResponseSMPFrameHeader,
3581                                           agFrameHandle
3582                                          );
3583             }
3584             else
3585             {
3586             }
3587           }
3588           else /* AGSA_RC_FAILURE */
3589           {
3590             if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL ||
3591                 dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER ||
3592                 dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA ||
3593                 dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3594                )
3595             {
3596               dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3597             }
3598             else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL)
3599             {
3600               /* task management failure */
3601               dmPhyControlFailureRespRcvd(
3602                                           dmRoot,
3603                                           agRoot,
3604                                           oneDeviceData,
3605                                           dmResponseSMPFrameHeader,
3606                                           agFrameHandle
3607                                          );
3608             }
3609             else
3610             {
3611             }
3612           }
3613         }
3614         else
3615         {
3616           dmSMPFrameHeader = (dmSMPFrameHeader_t *)agSMPFrame->outFrameBuf;
3617           dmSMPPayload = (bit8 *)agSMPFrame->outFrameBuf + 4;
3618           DM_DBG1(("dmSMPCompleted: failed! no more retry! agIOStatus 0x%x %d\n", agIOStatus, agIOStatus));
3619           if (agIOStatus == OSSA_IO_DS_NON_OPERATIONAL)
3620           {
3621             DM_DBG1(("dmSMPCompleted: failed! agIOStatus is OSSA_IO_DS_NON_OPERATIONAL\n"));
3622           }
3623           if (agIOStatus == OSSA_IO_DS_IN_RECOVERY)
3624           {
3625             DM_DBG1(("dmSMPCompleted: failed! agIOStatus is OSSA_IO_DS_IN_RECOVERY\n"));
3626           }
3627           if (dmSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL ||
3628               dmSMPFrameHeader->smpFunction == SMP_DISCOVER ||
3629               dmSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA ||
3630               dmSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION
3631              )
3632           {
3633             /* discovery failure */
3634             DM_DBG1(("dmSMPCompleted: SMP function 0x%x\n", dmSMPFrameHeader->smpFunction));
3635             DM_DBG1(("dmSMPCompleted: discover done with error\n"));
3636             dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3637           }
3638           else if (dmSMPFrameHeader->smpFunction == SMP_PHY_CONTROL)
3639           {
3640             DM_DBG1(("dmSMPCompleted: SMP_PHY_CONTROL\n"));
3641             smpPhyControl2Req = (smpReqPhyControl2_t *)dmSMPPayload;
3642             if (smpPhyControl2Req->phyOperation == SMP_PHY_CONTROL_CLEAR_AFFILIATION)
3643             {
3644               DM_DBG1(("dmSMPCompleted: discover done with error\n"));
3645               dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE);
3646             }
3647             else
3648             {
3649               DM_DBG1(("dmSMPCompleted: unknown phy operation 0x%x\n", smpPhyControl2Req->phyOperation));
3650             }
3651           } /* SMP_PHY_CONTROL */
3652           else
3653           {
3654             DM_DBG1(("dmSMPCompleted: SMP function 0x%x\n", dmSMPFrameHeader->smpFunction));
3655           }
3656         } /* else */
3657       } /* for RateAdjust */
3658     } /* outer else */
3659   } /* SAS 2 else */
3660 
3661   /* SMP request */
3662   tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3663   DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
3664   tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3665 
3666 #ifndef DIRECT_SMP
3667   /* SMP response */
3668   dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse;
3669   if (dmSMPResponseBody == agNULL)
3670   {
3671     DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n"));
3672     return;
3673   }
3674   tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3675   DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList));
3676   tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3677 #endif
3678 
3679   return;
3680 }
3681 
3682 osGLOBAL void
3683 dmSMPAbortCB(
3684              agsaRoot_t           *agRoot,
3685              agsaIORequest_t      *agIORequest,
3686              bit32                flag,
3687              bit32                status)
3688 {
3689   dmRoot_t             *dmRoot = agNULL;
3690   dmIntRoot_t          *dmIntRoot    = agNULL;
3691   dmIntContext_t       *dmAllShared = agNULL;
3692   dmSMPRequestBody_t   *dmSMPRequestBody = (dmSMPRequestBody_t *) agIORequest->osData;
3693 
3694   DM_DBG5(("dmSMPAbortCB: start\n"));
3695 
3696   if (dmSMPRequestBody == agNULL)
3697   {
3698     DM_DBG1(("dmSMPAbortCB: pSMPRequestBody is NULL!!! \n"));
3699     return;
3700   }
3701 
3702   dmRoot = dmSMPRequestBody->dmRoot;
3703   dmIntRoot    = (dmIntRoot_t *)dmRoot->dmData;
3704   dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared;
3705 
3706 
3707   /* put back into free smplist */
3708   tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK);
3709   DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList));
3710   tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK);
3711 
3712   /* start here */
3713   if (flag == 2)
3714   {
3715     /* abort all per port */
3716     DM_DBG1(("dmSMPAbortCB: abort per port; not used!!!\n"));
3717   }
3718   else if (flag == 1)
3719   {
3720     /* abort all */
3721     DM_DBG1(("dmSMPAbortCB: abort all; not used!!!\n"));
3722   }
3723   else if (flag == 0)
3724   {
3725     /* abort one */
3726     DM_DBG1(("ossaSMPAbortCB: abort one\n"));
3727     if (status != OSSA_IO_SUCCESS)
3728     {
3729       DM_DBG1(("dmSMPAbortCB: abort one, status 0x%x\n", status));
3730     }
3731   }
3732   else
3733   {
3734     DM_DBG1(("dmSMPAbortCB: not allowed case, flag 0x%x!!!\n", flag));
3735   }
3736 
3737   return;
3738 }
3739 
3740 
3741 #endif /* FDS_DM */
3742 
3743 
3744