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