/******************************************************************************* *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved. * *Redistribution and use in source and binary forms, with or without modification, are permitted provided *that the following conditions are met: *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the *following disclaimer. *2. Redistributions in binary form must reproduce the above copyright notice, *this list of conditions and the following disclaimer in the documentation and/or other materials provided *with the distribution. * *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE ** ********************************************************************************/ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #ifdef FDS_DM #include #include #include #include #include #include osGLOBAL bit32 dmSMPStart( dmRoot_t *dmRoot, agsaRoot_t *agRoot, dmDeviceData_t *oneDeviceData, bit32 functionCode, bit8 *pSmpBody, bit32 smpBodySize, bit32 agRequestType ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmIntPortContext_t *onePortContext = agNULL; dmSMPRequestBody_t *dmSMPRequestBody = agNULL; #ifndef DIRECT_SMP dmSMPRequestBody_t *dmSMPResponseBody = agNULL; #endif agsaSASRequestBody_t *agSASRequestBody; dmList_t *SMPList; agsaDevHandle_t *agDevHandle; agsaIORequest_t *agIORequest; agsaSMPFrame_t *agSMPFrame; bit32 expectedRspLen = 0; dmSMPFrameHeader_t dmSMPFrameHeader; dmExpander_t *oneExpander = agNULL; bit32 status; DM_DBG5(("dmSMPStart: start\n")); DM_DBG5(("dmSMPStart: 2nd sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG5(("dmSMPStart: 2nd sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); dm_memset(&dmSMPFrameHeader, 0, sizeof(dmSMPFrameHeader_t)); onePortContext = oneDeviceData->dmPortContext; if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmSMPStart: invalid port or aborted discovery!!!\n")); return DM_RC_FAILURE; } oneExpander = oneDeviceData->dmExpander; if (oneExpander == agNULL) { DM_DBG1(("dmSMPStart: Wrong!!! oneExpander is NULL!!!\n")); return DM_RC_FAILURE; } if (onePortContext != agNULL) { DM_DBG5(("dmSMPStart: pid %d\n", onePortContext->id)); /* increment the number of pending SMP */ onePortContext->discovery.pendingSMP++; } else { DM_DBG1(("dmSMPStart: Wrong, onePortContext is NULL!!!\n")); return DM_RC_FAILURE; } /* get an smp REQUEST from the free list */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); if (DMLIST_EMPTY(&(dmAllShared->freeSMPList))) { DM_DBG1(("dmSMPStart: no free SMP!!!\n")); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); /* undo increment the number of pending SMP */ onePortContext->discovery.pendingSMP--; return DM_RC_FAILURE; } else { DMLIST_DEQUEUE_FROM_HEAD(&SMPList, &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); dmSMPRequestBody = DMLIST_OBJECT_BASE(dmSMPRequestBody_t, Link, SMPList); } if (dmSMPRequestBody == agNULL) { DM_DBG1(("dmSMPStart: dmSMPRequestBody is NULL, wrong!!!\n")); return DM_RC_FAILURE; } DM_DBG5(("dmSMPStart: SMP id %d\n", dmSMPRequestBody->id)); dmSMPRequestBody->dmRoot = dmRoot; dmSMPRequestBody->dmDevice = oneDeviceData; dmSMPRequestBody->dmPortContext = onePortContext; agDevHandle = oneExpander->agDevHandle; /* save the callback funtion */ dmSMPRequestBody->SMPCompletionFunc = dmSMPCompleted; /* in dmsmp.c */ dmSMPRequestBody->retries = 0; agIORequest = &(dmSMPRequestBody->agIORequest); agIORequest->osData = (void *) dmSMPRequestBody; agIORequest->sdkData = agNULL; /* SALL takes care of this */ agSASRequestBody = &(dmSMPRequestBody->agSASRequestBody); agSMPFrame = &(agSASRequestBody->smpFrame); /* sets dmSMPFrameHeader values */ if (oneExpander->SAS2 == 0) { DM_DBG5(("dmSMPStart: SAS 1.1\n")); switch (functionCode) { case SMP_REPORT_GENERAL: expectedRspLen = sizeof(smpRespReportGeneral_t) + 4; break; case SMP_REPORT_MANUFACTURE_INFORMATION: expectedRspLen = sizeof(smpRespReportManufactureInfo_t) + 4; break; case SMP_DISCOVER: expectedRspLen = sizeof(smpRespDiscover_t) + 4; break; case SMP_REPORT_PHY_ERROR_LOG: expectedRspLen = 32 - 4; break; case SMP_REPORT_PHY_SATA: expectedRspLen = sizeof(smpRespReportPhySata_t) + 4; break; case SMP_REPORT_ROUTING_INFORMATION: expectedRspLen = sizeof(smpRespReportRouteTable_t) + 4; break; case SMP_CONFIGURE_ROUTING_INFORMATION: expectedRspLen = 4; break; case SMP_PHY_CONTROL: expectedRspLen = 4; break; case SMP_PHY_TEST_FUNCTION: expectedRspLen = 4; break; case SMP_PMC_SPECIFIC: expectedRspLen = 4; break; default: expectedRspLen = 0; DM_DBG1(("dmSMPStart: SAS 1.1 error, undefined or unused smp function code 0x%x !!!\n", functionCode)); return DM_RC_FAILURE; } /* SMP 1.1 header */ dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */ dmSMPFrameHeader.smpFunction = (bit8)functionCode; dmSMPFrameHeader.smpFunctionResult = 0; dmSMPFrameHeader.smpReserved = 0; } else /* SAS 2 */ { DM_DBG2(("dmSMPStart: SAS 2\n")); switch (functionCode) { case SMP_REPORT_GENERAL: expectedRspLen = sizeof(smpRespReportGeneral2_t) + 4; /* SMP 2.0 header */ dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */ dmSMPFrameHeader.smpFunction = (bit8)functionCode; dmSMPFrameHeader.smpFunctionResult = 0x11; dmSMPFrameHeader.smpReserved = 0; break; case SMP_REPORT_MANUFACTURE_INFORMATION: expectedRspLen = sizeof(smpRespReportManufactureInfo2_t) + 4; break; case SMP_DISCOVER: expectedRspLen = sizeof(smpRespDiscover2_t) + 4; /* SMP 2.0 header */ dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */ dmSMPFrameHeader.smpFunction = (bit8)functionCode; // dmSMPFrameHeader.smpFunctionResult = 0x6c; dmSMPFrameHeader.smpFunctionResult = 0x1b; dmSMPFrameHeader.smpReserved = 0x02; break; case SMP_REPORT_PHY_ERROR_LOG: expectedRspLen = 32 - 4; break; case SMP_REPORT_PHY_SATA: /* SMP 2.0 header */ dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */ dmSMPFrameHeader.smpFunction = (bit8)functionCode; dmSMPFrameHeader.smpFunctionResult = 0x10; dmSMPFrameHeader.smpReserved = 0x02; expectedRspLen = sizeof(smpRespReportPhySata2_t) + 4; break; case SMP_REPORT_ROUTING_INFORMATION: expectedRspLen = sizeof(smpRespReportRouteTable2_t) + 4; break; case SMP_CONFIGURE_ROUTING_INFORMATION: expectedRspLen = 4; /* SMP 2.0 header */ dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */ dmSMPFrameHeader.smpFunction = (bit8)functionCode; dmSMPFrameHeader.smpFunctionResult = 0; dmSMPFrameHeader.smpReserved = 0x09; break; case SMP_PHY_CONTROL: expectedRspLen = 4; /* SMP 2.0 header */ dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */ dmSMPFrameHeader.smpFunction = (bit8)functionCode; dmSMPFrameHeader.smpFunctionResult = 0; dmSMPFrameHeader.smpReserved = 0x09; break; case SMP_PHY_TEST_FUNCTION: expectedRspLen = 4; break; case SMP_DISCOVER_LIST: expectedRspLen = SMP_MAXIMUM_PAYLOAD; /* 1024 without CRC */ /* SMP 2.0 header */ dmSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */ dmSMPFrameHeader.smpFunction = (bit8)functionCode; dmSMPFrameHeader.smpFunctionResult = 0xFF; dmSMPFrameHeader.smpReserved = 0x06; break; case SMP_PMC_SPECIFIC: expectedRspLen = 4; break; default: expectedRspLen = 0; DM_DBG1(("dmSMPStart: SAS 2 error!!! undefined or unused smp function code 0x%x!!!\n", functionCode)); return DM_RC_FAILURE; } } if (DMIsSPC(agRoot)) { #ifdef DIRECT_SMP /* direct SMP with 48 or less payload */ if ( (smpBodySize + 4) <= SMP_DIRECT_PAYLOAD_LIMIT) /* 48 */ { DM_DBG5(("dmSMPStart: DIRECT smp payload\n")); dm_memset(dmSMPRequestBody->smpPayload, 0, SMP_DIRECT_PAYLOAD_LIMIT); dm_memcpy(dmSMPRequestBody->smpPayload, &dmSMPFrameHeader, 4); dm_memcpy((dmSMPRequestBody->smpPayload)+4, pSmpBody, smpBodySize); /* direct SMP payload eg) REPORT_GENERAL, DISCOVER etc */ agSMPFrame->outFrameBuf = dmSMPRequestBody->smpPayload; agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */ /* to specify DIRECT SMP response */ agSMPFrame->inFrameLen = 0; /* temporary solution for T2D Combo*/ #if defined (INITIATOR_DRIVER) && defined (TARGET_DRIVER) /* force smp repsonse to be direct */ agSMPFrame->expectedRespLen = 0; #else agSMPFrame->expectedRespLen = expectedRspLen; #endif } else { DM_DBG5(("dmSMPStart: INDIRECT smp payload, TBD\n")); } #else /* dmSMPRequestBody is SMP request dmSMPResponsebody is SMP response */ /* get an smp RESPONSE from the free list */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); if (DMLIST_EMPTY(&(dmAllShared->freeSMPList))) { DM_DBG1(("dmSMPStart: no free SMP!!!\n")); /* puy back dmSMPRequestBody to the freelist ???*/ // DMLIST_DEQUEUE_THIS(&(dmSMPRequestBody->Link)); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); /* undo increment the number of pending SMP */ onePortContext->discovery.pendingSMP--; return DM_RC_FAILURE; } else { DMLIST_DEQUEUE_FROM_HEAD(&SMPList, &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); dmSMPResponseBody = DMLIST_OBJECT_BASE(dmSMPRequestBody_t, Link, SMPList); DM_DBG5(("dmSMPStart: SMP id %d\n", dmSMPResponseBody->id)); } if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPStart: dmSMPResponseBody is NULL, wrong!!!\n")); return DM_RC_FAILURE; } /* fill in indirect SMP request fields */ DM_DBG5(("dmSMPStart: INDIRECT smp payload\n")); /* save the pointer to SMP response in SMP request */ dmSMPRequestBody->IndirectSMPResponse = dmSMPResponseBody; /* SMP request and response initialization */ dm_memset(dmSMPRequestBody->IndirectSMP, 0, smpBodySize + 4); dm_memset(dmSMPResponseBody->IndirectSMP, 0, expectedRspLen); dm_memcpy(dmSMPRequestBody->IndirectSMP, &dmSMPFrameHeader, 4); dm_memcpy(dmSMPRequestBody->IndirectSMP+4, pSmpBody, smpBodySize); /* Indirect SMP request */ agSMPFrame->outFrameBuf = agNULL; agSMPFrame->outFrameAddrUpper32 = dmSMPRequestBody->IndirectSMPUpper32; agSMPFrame->outFrameAddrLower32 = dmSMPRequestBody->IndirectSMPLower32; agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */ /* Indirect SMP response */ agSMPFrame->expectedRespLen = expectedRspLen; agSMPFrame->inFrameAddrUpper32 = dmSMPResponseBody->IndirectSMPUpper32; agSMPFrame->inFrameAddrLower32 = dmSMPResponseBody->IndirectSMPLower32; agSMPFrame->inFrameLen = expectedRspLen; /* without last 4 byte crc */ #endif } else /* SPCv controller */ { /* only direct mode for both request and response */ DM_DBG5(("dmSMPStart: DIRECT smp payload\n")); agSMPFrame->flag = 0; dm_memset(dmSMPRequestBody->smpPayload, 0, SMP_DIRECT_PAYLOAD_LIMIT); dm_memcpy(dmSMPRequestBody->smpPayload, &dmSMPFrameHeader, 4); dm_memcpy((dmSMPRequestBody->smpPayload)+4, pSmpBody, smpBodySize); /* direct SMP payload eg) REPORT_GENERAL, DISCOVER etc */ agSMPFrame->outFrameBuf = dmSMPRequestBody->smpPayload; agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */ /* to specify DIRECT SMP response */ agSMPFrame->inFrameLen = 0; /* temporary solution for T2D Combo*/ #if defined (INITIATOR_DRIVER) && defined (TARGET_DRIVER) /* force smp repsonse to be direct */ agSMPFrame->expectedRespLen = 0; #else agSMPFrame->expectedRespLen = expectedRspLen; #endif // tdhexdump("tdSMPStart", (bit8*)agSMPFrame->outFrameBuf, agSMPFrame->outFrameLen); // tdhexdump("tdSMPStart new", (bit8*)tdSMPRequestBody->smpPayload, agSMPFrame->outFrameLen); // tdhexdump("tdSMPStart - tdSMPRequestBody", (bit8*)tdSMPRequestBody, sizeof(tdssSMPRequestBody_t)); } if (agDevHandle == agNULL) { DM_DBG1(("dmSMPStart: !!! agDevHandle is NULL !!! \n")); } else { status = saSMPStart( agRoot, agIORequest, 0, agDevHandle, agRequestType, agSASRequestBody, &dmsaSMPCompleted ); if (status == AGSA_RC_SUCCESS) { /* start SMP timer */ if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER || functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmDiscoverySMPTimer(dmRoot, onePortContext, functionCode, dmSMPRequestBody); } return DM_RC_SUCCESS; } else if (status == AGSA_RC_BUSY) { /* set timer */ if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER || functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION) { /* only for discovery related SMPs*/ dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody); return DM_RC_SUCCESS; } else { DM_DBG1(("dmSMPStart: return DM_RC_BUSY!!! \n")); #ifdef DIRECT_SMP tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #else tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return DM_RC_BUSY; } } else /* AGSA_RC_FAILURE */ { DM_DBG1(("dmSMPStart: return DM_RC_FAILURE!!! \n")); /* discovery failure or task management failure */ if (functionCode == SMP_REPORT_GENERAL || functionCode == SMP_DISCOVER || functionCode == SMP_REPORT_PHY_SATA || functionCode == SMP_CONFIGURE_ROUTING_INFORMATION) { dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } #ifdef DIRECT_SMP tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #else tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return DM_RC_FAILURE; } } return DM_RC_SUCCESS; } osGLOBAL void dmsaSMPCompleted( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle ) { dmSMPRequestBody_t *pSMPRequestBody = (dmSMPRequestBody_t *) agIORequest->osData; /* SPC can't be SMP target */ DM_DBG5(("dmsaSMPCompleted: start\n")); if (pSMPRequestBody == agNULL) { DM_DBG1(("dmsaSMPCompleted: pSMPRequestBody is NULL!!! \n")); return; } if (pSMPRequestBody->SMPCompletionFunc == agNULL) { DM_DBG1(("dmsaSMPCompleted: pSMPRequestBody->SMPCompletionFunc is NULL!!!\n")); return; } #ifdef DM_INTERNAL_DEBUG /* debugging */ DM_DBG3(("dmsaSMPCompleted: agIOrequest %p\n", agIORequest->osData)); DM_DBG3(("dmsaSMPCompleted: sizeof(tdIORequestBody_t) %d 0x%x\n", sizeof(tdIORequestBody_t), sizeof(tdIORequestBody_t))); DM_DBG3(("dmsaSMPCompleted: SMPRequestbody %p\n", pSMPRequestBody)); DM_DBG3(("dmsaSMPCompleted: calling callback fn\n")); DM_DBG3(("dmsaSMPCompleted: callback fn %p\n",pSMPRequestBody->SMPCompletionFunc)); #endif /* TD_INTERNAL_DEBUG */ /* if initiator, calling dmSMPCompleted() in dmsmp.c */ pSMPRequestBody->SMPCompletionFunc( agRoot, agIORequest, agIOStatus, agIOInfoLen, agFrameHandle ); return; } osGLOBAL bit32 dmPhyControlSend( dmRoot_t *dmRoot, // dmDeviceData_t *oneDeviceData, /* taget disk */ dmDeviceData_t *oneExpDeviceData, /* taget disk */ bit8 phyOp, bit8 phyID // added ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; agsaRoot_t *agRoot = dmAllShared->agRoot; // thenil // dmDeviceData_t *oneExpDeviceData; smpReqPhyControl_t smpPhyControlReq; // bit8 phyID; bit32 status; DM_DBG3(("dmPhyControlSend: start\n")); osti_memset(&smpPhyControlReq, 0, sizeof(smpReqPhyControl_t)); /* fill in SMP payload */ smpPhyControlReq.phyIdentifier = phyID; smpPhyControlReq.phyOperation = phyOp; status = dmSMPStart( dmRoot, agRoot, oneExpDeviceData, SMP_PHY_CONTROL, (bit8 *)&smpPhyControlReq, sizeof(smpReqPhyControl_t), AGSA_SMP_INIT_REQ ); return status; } osGLOBAL void dmReportGeneralSend( dmRoot_t *dmRoot, dmDeviceData_t *oneDeviceData ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; agsaRoot_t *agRoot = dmAllShared->agRoot; DM_DBG3(("dmReportGeneralSend: start\n")); DM_DBG3(("dmReportGeneralSend: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmReportGeneralSend: oneExpander %p did %d\n", oneDeviceData->dmExpander, oneDeviceData->dmExpander->id)); if (agRoot == agNULL) { DM_DBG1(("dmReportGeneralSend: agRoot is NULL!!!\n")); return; } dmSMPStart( dmRoot, agRoot, oneDeviceData, SMP_REPORT_GENERAL, agNULL, 0, AGSA_SMP_INIT_REQ ); return; } osGLOBAL void dmReportGeneralRespRcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { smpRespReportGeneral_t dmSMPReportGeneralResp; smpRespReportGeneral_t *pdmSMPReportGeneralResp; dmIntPortContext_t *onePortContext = agNULL; dmDiscovery_t *discovery; dmExpander_t *oneExpander = agNULL; #ifndef DIRECT_SMP dmSMPRequestBody_t *dmSMPRequestBody; dmSMPRequestBody_t *dmSMPResponseBody = agNULL; #endif dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; DM_DBG3(("dmReportGeneralRespRcvd: start\n")); DM_DBG3(("dmReportGeneralRespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmReportGeneralRespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); #ifndef DIRECT_SMP dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData; #endif pdmSMPReportGeneralResp = &dmSMPReportGeneralResp; dm_memset(&dmSMPReportGeneralResp, 0, sizeof(smpRespReportGeneral_t)); #ifdef DIRECT_SMP saFrameReadBlock(agRoot, frameHandle, 4, pdmSMPReportGeneralResp, sizeof(smpRespReportGeneral_t)); #else dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 4, pdmSMPReportGeneralResp, sizeof(smpRespReportGeneral_t)); #endif onePortContext = oneDeviceData->dmPortContext; discovery = &(onePortContext->discovery); if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmReportGeneralRespRcvd: invalid port or aborted discovery!!!\n")); return; } if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) { oneDeviceData->numOfPhys = (bit8) pdmSMPReportGeneralResp->numOfPhys; oneExpander = oneDeviceData->dmExpander; oneExpander->routingIndex = (bit16) REPORT_GENERAL_GET_ROUTEINDEXES(pdmSMPReportGeneralResp); oneExpander->configReserved = 0; oneExpander->configRouteTable = REPORT_GENERAL_IS_CONFIGURABLE(pdmSMPReportGeneralResp) ? 1 : 0; oneExpander->configuring = REPORT_GENERAL_IS_CONFIGURING(pdmSMPReportGeneralResp) ? 1 : 0; DM_DBG2(("dmReportGeneralRespRcvd: SAS 2 is %d\n", oneExpander->SAS2)); DM_DBG3(("dmReportGeneralRespRcvd: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmReportGeneralRespRcvd: oneExpander %p did %d\n", oneExpander, oneExpander->id)); if ( oneExpander->SAS2 == 0 && REPORT_GENERAL_IS_LONG_RESPONSE(pdmSMPReportGeneralResp) == 1) { oneExpander->SAS2 = REPORT_GENERAL_IS_LONG_RESPONSE(pdmSMPReportGeneralResp); DM_DBG2(("dmReportGeneralRespRcvd: SAS 2 Long Response=%d\n", REPORT_GENERAL_IS_LONG_RESPONSE(pdmSMPReportGeneralResp))); dmReportGeneralSend(dmRoot, oneDeviceData); return; } DM_DBG3(("dmReportGeneralRespRcvd: oneExpander=%p numberofPhys=0x%x RoutingIndex=0x%x\n", oneExpander, oneDeviceData->numOfPhys, oneExpander->routingIndex)); DM_DBG3(("dmReportGeneralRespRcvd: configRouteTable=%d configuring=%d\n", oneExpander->configRouteTable, oneExpander->configuring)); if (oneExpander->configuring == 1) { discovery->retries++; if (discovery->retries >= dmAllShared->MaxRetryDiscovery) { DM_DBG1(("dmReportGeneralRespRcvd: retries are over!!!\n")); DM_DBG1(("dmReportGeneralRespRcvd: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); discovery->retries = 0; /* failed the discovery */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else { DM_DBG3(("dmReportGeneralRespRcvd: keep retrying\n")); DM_DBG1(("dmReportGeneralRespRcvd: Prep222389 RETRY at %d Maximum Retry is %d\n", discovery->retries, dmAllShared->MaxRetryDiscovery)); DM_DBG1(("dmReportGeneralRespRcvd: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); // start timer for sending ReportGeneral dmDiscoveryConfiguringTimer(dmRoot, onePortContext, oneDeviceData); } } else { discovery->retries = 0; dmDiscoverSend(dmRoot, oneDeviceData); } } else { DM_DBG1(("dmReportGeneralRespRcvd: SMP failed; fn result 0x%x; stopping discovery !!!\n", frameHeader->smpFunctionResult)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } return; } osGLOBAL void dmReportGeneral2RespRcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { smpRespReportGeneral2_t dmSMPReportGeneral2Resp; smpRespReportGeneral2_t *pdmSMPReportGeneral2Resp; dmExpander_t *oneExpander = agNULL; dmIntPortContext_t *onePortContext = agNULL; dmDiscovery_t *discovery; #ifndef DIRECT_SMP dmSMPRequestBody_t *dmSMPRequestBody; dmSMPRequestBody_t *dmSMPResponseBody = agNULL; #endif bit32 ConfiguresOthers = agFALSE; dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; DM_DBG2(("dmReportGeneral2RespRcvd: start\n")); DM_DBG2(("dmReportGeneral2RespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG2(("dmReportGeneral2RespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); #ifndef DIRECT_SMP dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData; #endif pdmSMPReportGeneral2Resp = &dmSMPReportGeneral2Resp; dm_memset(&dmSMPReportGeneral2Resp, 0, sizeof(smpRespReportGeneral2_t)); #ifdef DIRECT_SMP saFrameReadBlock(agRoot, frameHandle, 4, pdmSMPReportGeneral2Resp, sizeof(smpRespReportGeneral2_t)); #else dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 4, pdmSMPReportGeneral2Resp, sizeof(smpRespReportGeneral2_t)); #endif onePortContext = oneDeviceData->dmPortContext; discovery = &(onePortContext->discovery); if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmReportGeneral2RespRcvd: invalid port or aborted discovery!!!\n")); return; } /* ??? start here */ if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) { oneDeviceData->numOfPhys = (bit8) pdmSMPReportGeneral2Resp->numOfPhys; oneExpander = oneDeviceData->dmExpander; oneExpander->routingIndex = (bit16) SAS2_REPORT_GENERAL_GET_ROUTEINDEXES(pdmSMPReportGeneral2Resp); oneExpander->configReserved = 0; oneExpander->configRouteTable = SAS2_REPORT_GENERAL_IS_CONFIGURABLE(pdmSMPReportGeneral2Resp) ? 1 : 0; oneExpander->configuring = SAS2_REPORT_GENERAL_IS_CONFIGURING(pdmSMPReportGeneral2Resp) ? 1 : 0; oneExpander->TTTSupported = SAS2_REPORT_GENERAL_IS_TABLE_TO_TABLE_SUPPORTED(pdmSMPReportGeneral2Resp) ? 1 : 0; ConfiguresOthers = SAS2_REPORT_GENERAL_IS_CONFIGURES_OTHERS(pdmSMPReportGeneral2Resp) ? 1 : 0; DM_DBG2(("dmReportGeneral2RespRcvd: SAS 2 is %d\n", oneExpander->SAS2)); DM_DBG3(("dmReportGeneral2RespRcvd: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmReportGeneral2RespRcvd: oneExpander %p did %d\n", oneExpander, oneExpander->id)); DM_DBG2(("dmReportGeneral2RespRcvd: oneExpander=%p numberofPhys=0x%x RoutingIndex=0x%x\n", oneExpander, oneDeviceData->numOfPhys, oneExpander->routingIndex)); DM_DBG2(("dmReportGeneral2RespRcvd: configRouteTable=%d configuring=%d\n", oneExpander->configRouteTable, oneExpander->configuring)); if (ConfiguresOthers) { DM_DBG2(("dmReportGeneral2RespRcvd: ConfiguresOthers is true\n")); discovery->ConfiguresOthers = agTRUE; } if (oneExpander->configuring == 1) { discovery->retries++; if (discovery->retries >= dmAllShared->MaxRetryDiscovery) { DM_DBG1(("dmReportGeneral2RespRcvd: retries are over!!!\n")); DM_DBG1(("dmReportGeneral2RespRcvd: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); discovery->retries = 0; /* failed the discovery */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else { DM_DBG2(("dmReportGeneral2RespRcvd: keep retrying\n")); DM_DBG1(("dmReportGeneral2RespRcvd: Prep222389 RETRY at %d Maximum Retry is %d\n", discovery->retries, dmAllShared->MaxRetryDiscovery)); DM_DBG1(("dmReportGeneral2RespRcvd: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); // start timer for sending ReportGeneral dmDiscoveryConfiguringTimer(dmRoot, onePortContext, oneDeviceData); } } else { discovery->retries = 0; dmDiscoverSend(dmRoot, oneDeviceData); } } else { DM_DBG2(("dmReportGeneral2RespRcvd: SMP failed, stopping discovery\n")); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } return; } osGLOBAL void dmDiscoverSend( dmRoot_t *dmRoot, dmDeviceData_t *oneDeviceData ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; agsaRoot_t *agRoot = dmAllShared->agRoot; smpReqDiscover_t smpDiscoverReq; dmExpander_t *oneExpander; DM_DBG3(("dmDiscoverSend: start\n")); DM_DBG3(("dmDiscoverSend: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); oneExpander = oneDeviceData->dmExpander; DM_DBG3(("dmDiscoverSend: oneExpander %p did %d\n", oneExpander, oneExpander->id)); DM_DBG3(("dmDiscoverSend: phyID 0x%x\n", oneExpander->discoveringPhyId)); dm_memset(&smpDiscoverReq, 0, sizeof(smpReqDiscover_t)); smpDiscoverReq.reserved1 = 0; smpDiscoverReq.reserved2 = 0; smpDiscoverReq.phyIdentifier = oneExpander->discoveringPhyId; smpDiscoverReq.reserved3 = 0; dmSMPStart( dmRoot, agRoot, oneDeviceData, SMP_DISCOVER, (bit8 *)&smpDiscoverReq, sizeof(smpReqDiscover_t), AGSA_SMP_INIT_REQ ); return; } osGLOBAL void dmDiscoverRespRcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { dmIntPortContext_t *onePortContext = agNULL; dmDiscovery_t *discovery; smpRespDiscover_t *pdmSMPDiscoverResp; #ifndef DIRECT_SMP dmSMPRequestBody_t *dmSMPRequestBody; dmSMPRequestBody_t *dmSMPResponseBody = agNULL; #endif dmExpander_t *oneExpander = agNULL; DM_DBG3(("dmDiscoverRespRcvd: start\n")); DM_DBG3(("dmDiscoverRespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDiscoverRespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); onePortContext = oneDeviceData->dmPortContext; oneExpander = oneDeviceData->dmExpander; discovery = &(onePortContext->discovery); #ifndef DIRECT_SMP dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData; #endif DM_DBG3(("dmDiscoverRespRcvd: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmDiscoverRespRcvd: oneExpander %p did %d\n", oneExpander, oneExpander->id)); if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmDiscoverRespRcvd: invalid port or aborted discovery!!!\n")); return; } pdmSMPDiscoverResp = &(discovery->SMPDiscoverResp); #ifdef DIRECT_SMP saFrameReadBlock(agRoot, frameHandle, 4, pdmSMPDiscoverResp, sizeof(smpRespDiscover_t)); #else dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 4, pdmSMPDiscoverResp, sizeof(smpRespDiscover_t)); #endif if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) { if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM) { dmUpStreamDiscoverExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp); } else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { dmDownStreamDiscoverExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp); } else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING) { /* not done with configuring routing 1. set the timer 2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy() */ DM_DBG3(("dmDiscoverRespRcvd: still configuring routing; setting timer\n")); DM_DBG3(("dmDiscoverRespRcvd: onePortContext %p oneDeviceData %p pdmSMPDiscoverResp %p\n", onePortContext, oneDeviceData, pdmSMPDiscoverResp)); dmhexdump("dmDiscoverRespRcvd", (bit8*)pdmSMPDiscoverResp, sizeof(smpRespDiscover_t)); dmConfigureRouteTimer(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp, agNULL); } else { /* nothing */ } } else if (frameHeader->smpFunctionResult == PHY_VACANT) { DM_DBG3(("dmDiscoverRespRcvd: smpFunctionResult is PHY_VACANT, phyid %d\n", oneExpander->discoveringPhyId)); if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM) { dmUpStreamDiscoverExpanderPhySkip(dmRoot, onePortContext, oneExpander); } else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { dmDownStreamDiscoverExpanderPhySkip(dmRoot, onePortContext, oneExpander); } else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING) { /* not done with configuring routing 1. set the timer 2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy() */ DM_DBG3(("dmDiscoverRespRcvd: still configuring routing; setting timer\n")); DM_DBG3(("dmDiscoverRespRcvd: onePortContext %p oneDeviceData %p pdmSMPDiscoverResp %p\n", onePortContext, oneDeviceData, pdmSMPDiscoverResp)); dmhexdump("dmDiscoverRespRcvd", (bit8*)pdmSMPDiscoverResp, sizeof(smpRespDiscover_t)); dmConfigureRouteTimer(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp, agNULL); } } else { DM_DBG1(("dmDiscoverRespRcvd: Discovery Error SMP function return result error=0x%x !!!\n", frameHeader->smpFunctionResult)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } return; } osGLOBAL void dmDiscover2RespRcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { dmIntPortContext_t *onePortContext = agNULL; dmDiscovery_t *discovery; smpRespDiscover2_t *pdmSMPDiscover2Resp; #ifndef DIRECT_SMP dmSMPRequestBody_t *dmSMPRequestBody; dmSMPRequestBody_t *dmSMPResponseBody = agNULL; #endif dmExpander_t *oneExpander = agNULL; DM_DBG2(("dmDiscover2RespRcvd: start\n")); DM_DBG2(("dmDiscover2RespRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG2(("dmDiscover2RespRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); onePortContext = oneDeviceData->dmPortContext; oneExpander = oneDeviceData->dmExpander; discovery = &(onePortContext->discovery); #ifndef DIRECT_SMP dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData; #endif DM_DBG3(("dmDiscoverRespRcvd: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmDiscoverRespRcvd: oneExpander %p did %d\n", oneExpander, oneExpander->id)); if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmDiscover2RespRcvd: invalid port or aborted discovery!!!\n")); return; } pdmSMPDiscover2Resp = &(discovery->SMPDiscover2Resp); #ifdef DIRECT_SMP saFrameReadBlock(agRoot, frameHandle, 4, pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t)); #else dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 4, pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t)); #endif if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ) { DM_DBG2(("dmDiscover2RespRcvd: phyIdentifier %d\n", pdmSMPDiscover2Resp->phyIdentifier)); DM_DBG2(("dmDiscover2RespRcvd: NegotiatedSSCHWMuxingSupported %d\n", pdmSMPDiscover2Resp->NegotiatedSSCHWMuxingSupported)); DM_DBG2(("dmDiscover2RespRcvd: SAS2_MUXING_SUPPORTED %d\n", SAS2_DISCRSP_IS_MUXING_SUPPORTED(pdmSMPDiscover2Resp))); DM_DBG2(("dmDiscover2RespRcvd: NegotiatedLogicalLinkRate %d\n", pdmSMPDiscover2Resp->NegotiatedLogicalLinkRate)); DM_DBG2(("dmDiscover2RespRcvd: ReasonNegotiatedPhysicalLinkRate %d\n", pdmSMPDiscover2Resp->ReasonNegotiatedPhysicalLinkRate)); DM_DBG2(("dmDiscover2RespRcvd: SAS2_DISCRSP_GET_LOGICAL_LINKRATE %d\n", SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pdmSMPDiscover2Resp))); DM_DBG2(("dmDiscover2RespRcvd: SAS2_DISCRSP_GET_LINKRATE %d\n", SAS2_DISCRSP_GET_LINKRATE(pdmSMPDiscover2Resp))); //NegotiatedLogicalLinkRate 13 //ReasonNegotiatedPhysicalLinkRate 94 if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM) { dmUpStreamDiscover2ExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscover2Resp); } else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { dmDownStreamDiscover2ExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscover2Resp); } else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING) { /* not done with configuring routing 1. set the timer 2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy() */ DM_DBG2(("dmDiscover2RespRcvd: still configuring routing; setting timer\n")); DM_DBG2(("dmDiscover2RespRcvd: onePortContext %p oneDeviceData %p pdmSMPDiscover2Resp %p\n", onePortContext, oneDeviceData, pdmSMPDiscover2Resp)); dmhexdump("dmDiscover2RespRcvd", (bit8*)pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t)); dmConfigureRouteTimer(dmRoot, onePortContext, oneExpander, agNULL, pdmSMPDiscover2Resp); } else { /* nothing */ } } else if (frameHeader->smpFunctionResult == PHY_VACANT) { DM_DBG2(("dmDiscover2RespRcvd: smpFunctionResult is PHY_VACANT, phyid %d\n", oneExpander->discoveringPhyId)); if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM) { dmUpStreamDiscover2ExpanderPhySkip(dmRoot, onePortContext, oneExpander); } else if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { dmDownStreamDiscover2ExpanderPhySkip(dmRoot, onePortContext, oneExpander); } else if (onePortContext->discovery.status == DISCOVERY_CONFIG_ROUTING) { /* not done with configuring routing 1. set the timer 2. on timer expiration, call tdsaSASDownStreamDiscoverExpanderPhy() */ DM_DBG2(("dmDiscover2RespRcvd: still configuring routing; setting timer\n")); DM_DBG2(("dmDiscover2RespRcvd: onePortContext %p oneDeviceData %p pdmSMPDiscover2Resp %p\n", onePortContext, oneDeviceData, pdmSMPDiscover2Resp)); dmhexdump("dmDiscover2RespRcvd", (bit8*)pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t)); dmConfigureRouteTimer(dmRoot, onePortContext, oneExpander, agNULL, pdmSMPDiscover2Resp); } else { /* nothing */ } } else { DM_DBG1(("dmDiscover2RespRcvd: Discovery Error SMP function return result error=0x%x\n", frameHeader->smpFunctionResult)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } return; } #ifdef NOT_YET osGLOBAL void tdsaDiscoverList2Send( tiRoot_t *tiRoot, tdsaDeviceData_t *oneDeviceData ) { agsaRoot_t *agRoot; tdsaExpander_t *oneExpander; smpReqDiscoverList2_t smpDiscoverListReq; DM_DBG1(("tdsaDiscoverList2Send: start\n")); DM_DBG1(("tdsaDiscoverList2Send: device %p did %d\n", oneDeviceData, oneDeviceData->id)); agRoot = oneDeviceData->agRoot; oneExpander = oneDeviceData->dmExpander; DM_DBG1(("tdsaDiscoverList2Send: phyID 0x%x\n", oneExpander->discoveringPhyId)); osti_memset(&smpDiscoverListReq, 0, sizeof(smpReqDiscoverList2_t)); smpDiscoverListReq.reserved1 = 0; smpDiscoverListReq.StartingPhyID = 0; smpDiscoverListReq.MaxNumDiscoverDesc = 40; /* 40 for SHORT FORMAT; 8 for Long Format; SAS2 p630 */ smpDiscoverListReq.byte10 = 0x2; /* phy filter; all but "no device attached" */ smpDiscoverListReq.byte11 = 0x1; /* descriptor type; SHORT FORMAT */ dmSMPStart( dmRoot, agRoot, oneDeviceData, SMP_DISCOVER_LIST, (bit8 *)&smpDiscoverListReq, sizeof(smpReqDiscoverList2_t), AGSA_SMP_INIT_REQ, agNULL ); return; } osGLOBAL void tdsaDiscoverList2RespRcvd( tiRoot_t *tiRoot, agsaRoot_t *agRoot, tdsaDeviceData_t *oneDeviceData, tdssSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { return; } #endif /* not yet */ /***************************************************************************** *! \brief dmReportPhySataSend * * Purpose: This function sends Report Phy SATA to a device. * * \param dmRoot: Pointer to the OS Specific module allocated dmRoot_t * instance. * \param oneDeviceData: Pointer to the device data. * \param phyId: Phy Identifier. * * \return: * None * * \note: * *****************************************************************************/ osGLOBAL void dmReportPhySataSend( dmRoot_t *dmRoot, dmDeviceData_t *oneDeviceData, bit8 phyId ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; agsaRoot_t *agRoot = dmAllShared->agRoot; dmExpander_t *oneExpander; smpReqReportPhySata_t smpReportPhySataReq; DM_DBG3(("dmReportPhySataSend: start\n")); DM_DBG3(("dmReportPhySataSend: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmReportPhySataSend: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmReportPhySataSend: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); oneExpander = oneDeviceData->dmExpander; if (oneExpander == agNULL) { DM_DBG1(("dmReportPhySataSend: Error!!! expander is NULL\n")); return; } DM_DBG3(("dmReportPhySataSend: device %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmReportPhySataSend: phyid %d\n", phyId)); dm_memset(&smpReportPhySataReq, 0, sizeof(smpReqReportPhySata_t)); smpReportPhySataReq.phyIdentifier = phyId; dmSMPStart( dmRoot, agRoot, oneExpander->dmDevice, SMP_REPORT_PHY_SATA, (bit8 *)&smpReportPhySataReq, sizeof(smpReqReportPhySata_t), AGSA_SMP_INIT_REQ ); return; } /***************************************************************************** *! \brief dmReportPhySataRcvd * * Purpose: This function processes Report Phy SATA response. * * \param dmRoot_t: Pointer to the OS Specific module allocated dmRoot_t * instance. * \param agRoot: Pointer to chip/driver Instance. * \param oneDeviceData: Pointer to the device data. * \param frameHeader: Pointer to SMP frame header. * \param frameHandle: A Handle used to refer to the response frame * * \return: * None * * \note: * *****************************************************************************/ osGLOBAL void dmReportPhySataRcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { smpRespReportPhySata_t SMPreportPhySataResp; smpRespReportPhySata_t *pSMPReportPhySataResp; dmExpander_t *oneExpander = oneDeviceData->dmExpander; dmIntPortContext_t *onePortContext = agNULL; agsaFisRegDeviceToHost_t *fis; dmDeviceData_t *SataDevice = agNULL; #ifndef DIRECT_SMP dmSMPRequestBody_t *tdSMPRequestBody; #endif bit8 sataDeviceType; bit8 *bit8fis; bit8 i = 0; bit32 a = 0; bit8 bit8fisarray[20]; DM_DBG3(("dmReportPhySataRcvd: start\n")); DM_DBG3(("dmReportPhySataRcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmReportPhySataRcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); #ifndef DIRECT_SMP tdSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData; #endif /* get the current sata device hanlde stored in the expander structure */ if (oneExpander != agNULL) { SataDevice = oneExpander->dmDeviceToProcess; } if (SataDevice != agNULL) { DM_DBG3(("dmReportPhySataRcvd: sasAddressHi 0x%08x\n", SataDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmReportPhySataRcvd: sasAddressLo 0x%08x\n", SataDevice->SASAddressID.sasAddressLo)); } else { DM_DBG3(("dmReportPhySataRcvd: SataDevice is NULL\n")); } pSMPReportPhySataResp = &SMPreportPhySataResp; #ifdef DIRECT_SMP saFrameReadBlock(agRoot, frameHandle, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t)); #else saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t)); #endif /* tdhexdump("dmReportPhySataRcvd", (bit8 *)pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));*/ #ifndef DIRECT_SMP ostiFreeMemory( dmRoot, tdSMPRequestBody->IndirectSMPReqosMemHandle, tdSMPRequestBody->IndirectSMPReqLen ); ostiFreeMemory( dmRoot, tdSMPRequestBody->IndirectSMPResposMemHandle, tdSMPRequestBody->IndirectSMPRespLen ); #endif onePortContext = oneDeviceData->dmPortContext; if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmReportPhySataRcvd: invalid port or aborted discovery!!!\n")); return; } if (SataDevice == agNULL) { DM_DBG1(("dmReportPhySataRcvd: SataDevice is NULL, wrong\n")); dmDiscoverAbort(dmRoot, onePortContext); return; } if (frameHeader->smpFunctionResult == PHY_VACANT ) { DM_DBG1(("dmReportPhySataRcvd: smpFunctionResult == PHY_VACANT, wrong\n")); return; } if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ) { fis = (agsaFisRegDeviceToHost_t*) &SMPreportPhySataResp.regDevToHostFis; if (fis->h.fisType == REG_DEV_TO_HOST_FIS) { /* save signature */ DM_DBG3(("dmReportPhySataRcvd: saves the signature\n")); /* saves signature */ SataDevice->satSignature[0] = fis->d.sectorCount; SataDevice->satSignature[1] = fis->d.lbaLow; SataDevice->satSignature[2] = fis->d.lbaMid; SataDevice->satSignature[3] = fis->d.lbaHigh; SataDevice->satSignature[4] = fis->d.device; SataDevice->satSignature[5] = 0; SataDevice->satSignature[6] = 0; SataDevice->satSignature[7] = 0; DM_DBG3(("dmReportPhySataRcvd: SATA Signature = %02x %02x %02x %02x %02x\n", SataDevice->satSignature[0], SataDevice->satSignature[1], SataDevice->satSignature[2], SataDevice->satSignature[3], SataDevice->satSignature[4])); sataDeviceType = tddmSATADeviceTypeDecode(SataDevice->satSignature); if( sataDeviceType == SATA_ATAPI_DEVICE) { SataDevice->agDeviceInfo.flag |= ATAPI_DEVICE_FLAG; } SataDevice->dmDeviceInfo.sataDeviceType = sataDeviceType; } /* Handling DataDomain buggy FIS */ else if (fis->h.error == REG_DEV_TO_HOST_FIS) { /* needs to flip fis to host order */ bit8fis = (bit8*)fis; for (i=0;i<5;i++) { a = DMA_LEBIT32_TO_BIT32(*(bit32*)bit8fis); DM_DBG3(("dmReportPhySataRcvd: a 0x%8x\n", a)); bit8fisarray[4*i] = (a & 0xFF000000) >> 24; bit8fisarray[4*i+1] = (a & 0x00FF0000) >> 16; bit8fisarray[4*i+2] = (a & 0x0000FF00) >> 8; bit8fisarray[4*i+3] = (a & 0x000000FF); bit8fis = bit8fis + 4; } fis = (agsaFisRegDeviceToHost_t*) bit8fisarray; /* save signature */ DM_DBG3(("dmReportPhySataRcvd: DataDomain ATAPI saves the signature\n")); /* saves signature */ SataDevice->satSignature[0] = fis->d.sectorCount; SataDevice->satSignature[1] = fis->d.lbaLow; SataDevice->satSignature[2] = fis->d.lbaMid; SataDevice->satSignature[3] = fis->d.lbaHigh; SataDevice->satSignature[4] = fis->d.device; SataDevice->satSignature[5] = 0; SataDevice->satSignature[6] = 0; SataDevice->satSignature[7] = 0; DM_DBG3(("dmReportPhySataRcvd: SATA Signature = %02x %02x %02x %02x %02x\n", SataDevice->satSignature[0], SataDevice->satSignature[1], SataDevice->satSignature[2], SataDevice->satSignature[3], SataDevice->satSignature[4])); sataDeviceType = tddmSATADeviceTypeDecode(SataDevice->satSignature); if( sataDeviceType == SATA_ATAPI_DEVICE) { SataDevice->agDeviceInfo.flag |= ATAPI_DEVICE_FLAG; } SataDevice->dmDeviceInfo.sataDeviceType = sataDeviceType; } else { DM_DBG3(("dmReportPhySataRcvd: getting next stp bride\n")); } /* Continure to report this STP device to TD*/ if (SataDevice->ExpDevice != agNULL) { tddmReportDevice(dmRoot, onePortContext->dmPortContext, &SataDevice->dmDeviceInfo, &SataDevice->ExpDevice->dmDeviceInfo, dmDeviceArrival); } else { tddmReportDevice(dmRoot, onePortContext->dmPortContext, &SataDevice->dmDeviceInfo, agNULL, dmDeviceArrival); } } else { DM_DBG3(("dmReportPhySataRcvd: siReportPhySataRcvd SMP function return result %x\n", frameHeader->smpFunctionResult)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } return; } /***************************************************************************** *! \brief dmReportPhySata2Rcvd * * Purpose: This function processes SAS2.0 Report Phy SATA response. * * \param dmRoot_t: Pointer to the OS Specific module allocated dmRoot_t * instance. * \param agRoot: Pointer to chip/driver Instance. * \param oneDeviceData: Pointer to the device data. * \param frameHeader: Pointer to SMP frame header. * \param frameHandle: A Handle used to refer to the response frame * * \return: * None * * \note: * *****************************************************************************/ osGLOBAL void dmReportPhySata2Rcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { smpRespReportPhySata2_t SMPreportPhySataResp; smpRespReportPhySata2_t *pSMPReportPhySataResp; dmExpander_t *oneExpander = oneDeviceData->dmExpander; dmIntPortContext_t *onePortContext = agNULL; agsaFisRegDeviceToHost_t *fis; dmDeviceData_t *SataDevice = agNULL; #ifndef DIRECT_SMP dmSMPRequestBody_t *tdSMPRequestBody; #endif bit8 sataDeviceType = 0; bit8 *bit8fis; bit8 i = 0; bit32 a = 0; bit8 bit8fisarray[20]; DM_DBG3(("dmReportPhySata2Rcvd: start\n")); DM_DBG3(("dmReportPhySata2Rcvd: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmReportPhySata2Rcvd: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); #ifndef DIRECT_SMP tdSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData; #endif /* get the current sata device hanlde stored in the expander structure */ if (oneExpander != agNULL) { SataDevice = oneExpander->dmDeviceToProcess; } if (SataDevice != agNULL) { DM_DBG3(("dmReportPhySata2Rcvd: sasAddressHi 0x%08x\n", SataDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmReportPhySata2Rcvd: sasAddressLo 0x%08x\n", SataDevice->SASAddressID.sasAddressLo)); } else { DM_DBG3(("dmReportPhySataRcvd: SataDevice is NULL\n")); } pSMPReportPhySataResp = &SMPreportPhySataResp; #ifdef DIRECT_SMP saFrameReadBlock(agRoot, frameHandle, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t)); #else saFrameReadBlock(agRoot, tdSMPRequestBody->IndirectSMPResp, 4, pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t)); #endif /* tdhexdump("dmReportPhySataRcvd", (bit8 *)pSMPReportPhySataResp, sizeof(smpRespReportPhySata_t));*/ #ifndef DIRECT_SMP ostiFreeMemory( dmRoot, tdSMPRequestBody->IndirectSMPReqosMemHandle, tdSMPRequestBody->IndirectSMPReqLen ); ostiFreeMemory( dmRoot, tdSMPRequestBody->IndirectSMPResposMemHandle, tdSMPRequestBody->IndirectSMPRespLen ); #endif onePortContext = oneDeviceData->dmPortContext; if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmReportPhySata2Rcvd: invalid port or aborted discovery!!!\n")); return; } if (SataDevice == agNULL) { DM_DBG1(("dmReportPhySata2Rcvd: SataDevice is NULL, wrong\n")); dmDiscoverAbort(dmRoot, onePortContext); return; } if ( frameHeader->smpFunctionResult == PHY_VACANT ) { DM_DBG1(("dmReportPhySata2Rcvd: smpFunctionResult == PHY_VACANT, wrong\n")); return; } if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ) { fis = (agsaFisRegDeviceToHost_t*) &SMPreportPhySataResp.regDevToHostFis; if (fis->h.fisType == REG_DEV_TO_HOST_FIS) { /* save signature */ DM_DBG3(("dmReportPhySata2Rcvd: saves the signature\n")); /* saves signature */ SataDevice->satSignature[0] = fis->d.sectorCount; SataDevice->satSignature[1] = fis->d.lbaLow; SataDevice->satSignature[2] = fis->d.lbaMid; SataDevice->satSignature[3] = fis->d.lbaHigh; SataDevice->satSignature[4] = fis->d.device; SataDevice->satSignature[5] = 0; SataDevice->satSignature[6] = 0; SataDevice->satSignature[7] = 0; DM_DBG3(("dmReportPhySata2Rcvd: SATA Signature = %02x %02x %02x %02x %02x\n", SataDevice->satSignature[0], SataDevice->satSignature[1], SataDevice->satSignature[2], SataDevice->satSignature[3], SataDevice->satSignature[4])); sataDeviceType = tddmSATADeviceTypeDecode(SataDevice->satSignature); if( sataDeviceType == SATA_ATAPI_DEVICE) { SataDevice->agDeviceInfo.flag |= ATAPI_DEVICE_FLAG; } SataDevice->dmDeviceInfo.sataDeviceType = sataDeviceType; } /* Handling DataDomain buggy FIS */ else if (fis->h.error == REG_DEV_TO_HOST_FIS) { /* needs to flip fis to host order */ bit8fis = (bit8*)fis; for (i=0;i<5;i++) { a = DMA_LEBIT32_TO_BIT32(*(bit32*)bit8fis); DM_DBG3(("dmReportPhySata2Rcvd: a 0x%8x\n", a)); bit8fisarray[4*i] = (a & 0xFF000000) >> 24; bit8fisarray[4*i+1] = (a & 0x00FF0000) >> 16; bit8fisarray[4*i+2] = (a & 0x0000FF00) >> 8; bit8fisarray[4*i+3] = (a & 0x000000FF); bit8fis = bit8fis + 4; } fis = (agsaFisRegDeviceToHost_t*) bit8fisarray; /* save signature */ DM_DBG3(("dmReportPhySata2Rcvd: DataDomain ATAPI saves the signature\n")); /* saves signature */ SataDevice->satSignature[0] = fis->d.sectorCount; SataDevice->satSignature[1] = fis->d.lbaLow; SataDevice->satSignature[2] = fis->d.lbaMid; SataDevice->satSignature[3] = fis->d.lbaHigh; SataDevice->satSignature[4] = fis->d.device; SataDevice->satSignature[5] = 0; SataDevice->satSignature[6] = 0; SataDevice->satSignature[7] = 0; DM_DBG3(("dmReportPhySata2Rcvd: SATA Signature = %02x %02x %02x %02x %02x\n", SataDevice->satSignature[0], SataDevice->satSignature[1], SataDevice->satSignature[2], SataDevice->satSignature[3], SataDevice->satSignature[4])); sataDeviceType = tddmSATADeviceTypeDecode(SataDevice->satSignature); if( sataDeviceType == SATA_ATAPI_DEVICE) { SataDevice->agDeviceInfo.flag |= ATAPI_DEVICE_FLAG; } SataDevice->dmDeviceInfo.sataDeviceType = sataDeviceType; } else { DM_DBG3(("dmReportPhySata2Rcvd: getting next stp bride\n")); } /* Continue to report this STP device to TD*/ if (SataDevice->ExpDevice != agNULL) { tddmReportDevice(dmRoot, onePortContext->dmPortContext, &SataDevice->dmDeviceInfo, &SataDevice->ExpDevice->dmDeviceInfo, dmDeviceArrival); } else { tddmReportDevice(dmRoot, onePortContext->dmPortContext, &SataDevice->dmDeviceInfo, agNULL, dmDeviceArrival); } } else { DM_DBG3(("dmReportPhySata2Rcvd: siReportPhySataRcvd SMP function return result %x\n", frameHeader->smpFunctionResult)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } return; } osGLOBAL bit32 dmRoutingEntryAdd( dmRoot_t *dmRoot, dmExpander_t *oneExpander, bit32 phyId, bit32 configSASAddressHi, bit32 configSASAddressLo ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; agsaRoot_t *agRoot = dmAllShared->agRoot; bit32 ret = agTRUE; dmIntPortContext_t *onePortContext; smpReqConfigureRouteInformation_t confRoutingInfo; bit32 i; DM_DBG3(("dmRoutingEntryAdd: start\n")); DM_DBG3(("dmRoutingEntryAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmRoutingEntryAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG3(("dmRoutingEntryAdd: phyid %d\n", phyId)); if (oneExpander->dmDevice->SASAddressID.sasAddressHi == configSASAddressHi && oneExpander->dmDevice->SASAddressID.sasAddressLo == configSASAddressLo ) { DM_DBG3(("dmRoutingEntryAdd: unnecessary\n")); return ret; } if (oneExpander->routingAttribute[phyId] != SAS_ROUTING_TABLE) { DM_DBG3(("dmRoutingEntryAdd: not table routing, routing is %d\n", oneExpander->routingAttribute[phyId])); return ret; } onePortContext = oneExpander->dmDevice->dmPortContext; onePortContext->discovery.status = DISCOVERY_CONFIG_ROUTING; /* reset smpReqConfigureRouteInformation_t */ dm_memset(&confRoutingInfo, 0, sizeof(smpReqConfigureRouteInformation_t)); if ( oneExpander->currentIndex[phyId] < oneExpander->routingIndex ) { DM_DBG3(("dmRoutingEntryAdd: adding sasAddressHi 0x%08x\n", configSASAddressHi)); DM_DBG3(("dmRoutingEntryAdd: adding sasAddressLo 0x%08x\n", configSASAddressLo)); DM_DBG3(("dmRoutingEntryAdd: phyid %d currentIndex[phyid] %d\n", phyId, oneExpander->currentIndex[phyId])); oneExpander->configSASAddressHi = configSASAddressHi; oneExpander->configSASAddressLo = configSASAddressLo; confRoutingInfo.reserved1[0] = 0; confRoutingInfo.reserved1[1] = 0; OSSA_WRITE_BE_16(agRoot, confRoutingInfo.expanderRouteIndex, 0, (oneExpander->currentIndex[phyId])); confRoutingInfo.reserved2 = 0; confRoutingInfo.phyIdentifier = (bit8)phyId; confRoutingInfo.reserved3[0] = 0; confRoutingInfo.reserved3[1] = 0; confRoutingInfo.disabledBit_reserved4 = 0; confRoutingInfo.reserved5[0] = 0; confRoutingInfo.reserved5[1] = 0; confRoutingInfo.reserved5[2] = 0; OSSA_WRITE_BE_32(agRoot, confRoutingInfo.routedSasAddressHi, 0, configSASAddressHi); OSSA_WRITE_BE_32(agRoot, confRoutingInfo.routedSasAddressLo, 0, configSASAddressLo); for ( i = 0; i < 16; i ++ ) { confRoutingInfo.reserved6[i] = 0; } dmSMPStart(dmRoot, agRoot, oneExpander->dmDevice, SMP_CONFIGURE_ROUTING_INFORMATION, (bit8 *)&confRoutingInfo, sizeof(smpReqConfigureRouteInformation_t), AGSA_SMP_INIT_REQ); oneExpander->currentIndex[phyId] ++; } else { DM_DBG3(("dmRoutingEntryAdd: Discovery Error routing index overflow for currentIndex=%d, routingIndex=%d\n", oneExpander->currentIndex[phyId], oneExpander->routingIndex)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); ret = agFALSE; } return ret; } osGLOBAL void dmConfigRoutingInfoRespRcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { dmIntPortContext_t *onePortContext; dmExpander_t *oneExpander = oneDeviceData->dmExpander; dmExpander_t *UpStreamExpander; dmExpander_t *DownStreamExpander; dmExpander_t *ReturningExpander; dmExpander_t *ConfigurableExpander; dmDeviceData_t *ReturningExpanderDeviceData = agNULL; bit32 dupConfigSASAddr = agFALSE; DM_DBG3(("dmConfigRoutingInfoRespRcvd: start\n")); DM_DBG3(("dmConfigRoutingInfoRespRcvd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmConfigRoutingInfoRespRcvd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); onePortContext = oneDeviceData->dmPortContext; if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmConfigRoutingInfoRespRcvd: invalid port or aborted discovery!!!\n")); return; } if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED || frameHeader->smpFunctionResult == PHY_VACANT ) { DownStreamExpander = oneExpander->dmCurrentDownStreamExpander; if (DownStreamExpander != agNULL) { DownStreamExpander->currentUpStreamPhyIndex ++; DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex)); DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander->numOfUpStreamPhys %d\n", DownStreamExpander->numOfUpStreamPhys)); DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander addrHi 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander addrLo 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressLo)); } oneExpander->currentDownStreamPhyIndex++; DM_DBG3(("dmConfigRoutingInfoRespRcvd: oneExpander->currentDownStreamPhyIndex %d oneExpander->numOfDownStreamPhys %d\n", oneExpander->currentDownStreamPhyIndex, oneExpander->numOfDownStreamPhys)); if ( (DownStreamExpander != agNULL) && (DownStreamExpander->currentUpStreamPhyIndex < DownStreamExpander->numOfUpStreamPhys) ) { DM_DBG3(("dmConfigRoutingInfoRespRcvd: first if\n")); DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex)); DM_DBG3(("dmConfigRoutingInfoRespRcvd: DownStreamExpander->upStreamPhys[] %d\n", DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex])); dmRoutingEntryAdd(dmRoot, oneExpander, DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex], oneExpander->configSASAddressHi, oneExpander->configSASAddressLo ); } else { /* traversing up till discovery Root onePortContext->discovery.RootExp */ DM_DBG3(("dmConfigRoutingInfoRespRcvd: else\n")); UpStreamExpander = oneExpander->dmUpStreamExpander; ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander); if (UpStreamExpander != agNULL) { DM_DBG3(("dmConfigRoutingInfoRespRcvd: UpStreamExpander addrHi 0x%08x\n", UpStreamExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmConfigRoutingInfoRespRcvd: UpStreamExpander addrLo 0x%08x\n", UpStreamExpander->dmDevice->SASAddressID.sasAddressLo)); } else { DM_DBG3(("dmConfigRoutingInfoRespRcvd: UpStreamExpander is NULL\n")); } dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, ConfigurableExpander, oneExpander->configSASAddressHi, oneExpander->configSASAddressLo ); if ( ConfigurableExpander != agNULL && dupConfigSASAddr == agFALSE) { DM_DBG3(("dmConfigRoutingInfoRespRcvd: else if\n")); DM_DBG3(("dmConfigRoutingInfoRespRcvd: ConfigurableExpander addrHi 0x%08x\n", ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmConfigRoutingInfoRespRcvd: ConfigurableExpander addrLo 0x%08x\n", ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo)); if ( UpStreamExpander != agNULL) { UpStreamExpander->dmCurrentDownStreamExpander = oneExpander; } ConfigurableExpander->currentDownStreamPhyIndex = dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander); ConfigurableExpander->dmReturnginExpander = oneExpander->dmReturnginExpander; if ( DownStreamExpander != agNULL) { DownStreamExpander->currentUpStreamPhyIndex = 0; } DM_DBG3(("dmConfigRoutingInfoRespRcvd: ConfigurableExpander->currentDownStreamPhyIndex %d\n", ConfigurableExpander->currentDownStreamPhyIndex)); DM_DBG3(("dmConfigRoutingInfoRespRcvd: ConfigurableExpander->downStreamPhys[] %d\n", ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex])); dmRoutingEntryAdd(dmRoot, ConfigurableExpander, ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex], oneExpander->configSASAddressHi, oneExpander->configSASAddressLo ); } else { /* going back to where it was */ /* ConfigRoutingInfo is done for a target */ DM_DBG3(("dmConfigRoutingInfoRespRcvd: $$$$$$ my change $$$$$ \n")); ReturningExpander = oneExpander->dmReturnginExpander; if ( DownStreamExpander != agNULL) { DownStreamExpander->currentUpStreamPhyIndex = 0; } /* debugging */ if (ReturningExpander != agNULL) { DM_DBG3(("dmConfigRoutingInfoRespRcvd: ReturningExpander addrHi 0x%08x\n", ReturningExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmConfigRoutingInfoRespRcvd: ReturningExpander addrLo 0x%08x\n", ReturningExpander->dmDevice->SASAddressID.sasAddressLo)); ReturningExpanderDeviceData = ReturningExpander->dmDevice; } /* No longer in DISCOVERY_CONFIG_ROUTING */ onePortContext->discovery.status = DISCOVERY_DOWN_STREAM; if (ReturningExpander != agNULL && ReturningExpanderDeviceData != agNULL) { /* If not the last phy */ if ( ReturningExpander->discoveringPhyId < ReturningExpanderDeviceData->numOfPhys ) { DM_DBG3(("dmConfigRoutingInfoRespRcvd: More Phys to discover\n")); /* continue discovery for the next phy */ /* needs to send only one Discovery not multiple times */ if (ReturningExpander->discoverSMPAllowed == agTRUE) { dmDiscoverSend(dmRoot, ReturningExpanderDeviceData); } if (ReturningExpander != agNULL) { ReturningExpander->discoverSMPAllowed = agFALSE; } } /* If the last phy */ else { DM_DBG3(("dmConfigRoutingInfoRespRcvd: No More Phys\n")); ReturningExpander->discoverSMPAllowed = agTRUE; /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, ReturningExpander); /* continue downstream discovering */ dmDownStreamDiscovering(dmRoot, onePortContext, ReturningExpanderDeviceData); //DownStreamExpander } } } } } else { DM_DBG1(("dmConfigRoutingInfoRespRcvd: Discovery Error SMP function return result error=0x%x !!!\n", frameHeader->smpFunctionResult)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } return; } osGLOBAL void dmConfigRoutingInfo2RespRcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { dmExpander_t *oneExpander = oneDeviceData->dmExpander; dmExpander_t *UpStreamExpander; dmExpander_t *DownStreamExpander; dmExpander_t *ReturningExpander; dmExpander_t *ConfigurableExpander; dmIntPortContext_t *onePortContext; dmDeviceData_t *ReturningExpanderDeviceData = agNULL; bit32 dupConfigSASAddr = agFALSE; DM_DBG2(("dmConfigRoutingInfo2RespRcvd: start\n")); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); onePortContext = oneDeviceData->dmPortContext; if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmConfigRoutingInfo2RespRcvd: invalid port or aborted discovery!!!\n")); return; } if (frameHeader->smpFunctionResult == PHY_VACANT) { DM_DBG1(("dmConfigRoutingInfo2RespRcvd: smpFunctionResult is PHY_VACANT\n")); } if ( frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED || frameHeader->smpFunctionResult == PHY_VACANT ) { DownStreamExpander = oneExpander->dmCurrentDownStreamExpander; if (DownStreamExpander != agNULL) { DownStreamExpander->currentUpStreamPhyIndex ++; DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex)); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander->numOfUpStreamPhys %d\n", DownStreamExpander->numOfUpStreamPhys)); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander addrHi 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander addrLo 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressLo)); } oneExpander->currentDownStreamPhyIndex++; DM_DBG2(("dmConfigRoutingInfo2RespRcvd: oneExpander->currentDownStreamPhyIndex %d oneExpander->numOfDownStreamPhys %d\n", oneExpander->currentDownStreamPhyIndex, oneExpander->numOfDownStreamPhys)); if ( (DownStreamExpander != agNULL) && (DownStreamExpander->currentUpStreamPhyIndex < DownStreamExpander->numOfUpStreamPhys) ) { DM_DBG2(("dmConfigRoutingInfo2RespRcvd: first if\n")); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander->currentUpStreamPhyIndex %d\n", DownStreamExpander->currentUpStreamPhyIndex)); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: DownStreamExpander->upStreamPhys[] %d\n", DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex])); dmRoutingEntryAdd(dmRoot, oneExpander, DownStreamExpander->upStreamPhys[DownStreamExpander->currentUpStreamPhyIndex], oneExpander->configSASAddressHi, oneExpander->configSASAddressLo ); } else { /* traversing up till discovery Root onePortContext->discovery.RootExp */ DM_DBG2(("dmConfigRoutingInfo2RespRcvd: else\n")); UpStreamExpander = oneExpander->dmUpStreamExpander; ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander); if (UpStreamExpander != agNULL) { DM_DBG2(("dmConfigRoutingInfo2RespRcvd: UpStreamExpander addrHi 0x%08x\n", UpStreamExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: UpStreamExpander addrLo 0x%08x\n", UpStreamExpander->dmDevice->SASAddressID.sasAddressLo)); } else { DM_DBG2(("dmConfigRoutingInfo2RespRcvd: UpStreamExpander is NULL\n")); } dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, ConfigurableExpander, oneExpander->configSASAddressHi, oneExpander->configSASAddressLo ); if ( ConfigurableExpander != agNULL && dupConfigSASAddr == agFALSE) { DM_DBG2(("dmConfigRoutingInfo2RespRcvd: else if\n")); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ConfigurableExpander addrHi 0x%08x\n", ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ConfigurableExpander addrLo 0x%08x\n", ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo)); if ( UpStreamExpander != agNULL) { UpStreamExpander->dmCurrentDownStreamExpander = oneExpander; } ConfigurableExpander->currentDownStreamPhyIndex = dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander); ConfigurableExpander->dmReturnginExpander = oneExpander->dmReturnginExpander; if ( DownStreamExpander != agNULL) { DownStreamExpander->currentUpStreamPhyIndex = 0; } DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ConfigurableExpander->currentDownStreamPhyIndex %d\n", ConfigurableExpander->currentDownStreamPhyIndex)); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ConfigurableExpander->downStreamPhys[] %d\n", ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex])); dmRoutingEntryAdd(dmRoot, ConfigurableExpander, ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex], oneExpander->configSASAddressHi, oneExpander->configSASAddressLo ); } else { /* going back to where it was */ /* ConfigRoutingInfo is done for a target */ DM_DBG2(("dmConfigRoutingInfo2RespRcvd: $$$$$$ my change $$$$$ \n")); ReturningExpander = oneExpander->dmReturnginExpander; if ( DownStreamExpander != agNULL) { DownStreamExpander->currentUpStreamPhyIndex = 0; } /* debugging */ if (ReturningExpander != agNULL) { DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ReturningExpander addrHi 0x%08x\n", ReturningExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG2(("dmConfigRoutingInfo2RespRcvd: ReturningExpander addrLo 0x%08x\n", ReturningExpander->dmDevice->SASAddressID.sasAddressLo)); ReturningExpanderDeviceData = ReturningExpander->dmDevice; } /* No longer in DISCOVERY_CONFIG_ROUTING */ onePortContext->discovery.status = DISCOVERY_DOWN_STREAM; if (ReturningExpander != agNULL && ReturningExpanderDeviceData != agNULL) { /* If not the last phy */ if ( ReturningExpander->discoveringPhyId < ReturningExpanderDeviceData->numOfPhys ) { DM_DBG2(("dmConfigRoutingInfo2RespRcvd: More Phys to discover\n")); /* continue discovery for the next phy */ /* needs to send only one Discovery not multiple times */ if (ReturningExpander->discoverSMPAllowed == agTRUE) { dmDiscoverSend(dmRoot, ReturningExpanderDeviceData); } if (ReturningExpander != agNULL) { ReturningExpander->discoverSMPAllowed = agFALSE; } } /* If the last phy */ else { DM_DBG2(("dmConfigRoutingInfo2RespRcvd: No More Phys\n")); ReturningExpander->discoverSMPAllowed = agTRUE; /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, ReturningExpander); /* continue downstream discovering */ dmDownStreamDiscovering(dmRoot, onePortContext, ReturningExpanderDeviceData); //DownStreamExpander } } } } } else { DM_DBG1(("dmConfigRoutingInfo2RespRcvd: Discovery Error SMP function return result error=0x%x!!!\n", frameHeader->smpFunctionResult)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } return; } /* no task management case here for phyControl*/ /* no task management case here for phyControl*/ osGLOBAL void dmPhyControlRespRcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { DM_DBG3(("dmPhyControlRespRcvd: start\n")); DM_DBG3(("dmPhyControlRespRcvd: expander device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmPhyControlRespRcvd: expander device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) { DM_DBG3(("dmPhyControlRespRcvd: SMP success\n")); } else { DM_DBG1(("dmPhyControlRespRcvd: SMP failure; result 0x%x !!!\n", frameHeader->smpFunctionResult)); } return; } /* no task management case here for phyControl*/ osGLOBAL void dmPhyControl2RespRcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { DM_DBG2(("dmPhyControl2RespRcvd: start\n")); DM_DBG2(("dmPhyControl2RespRcvd: expander device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG2(("dmPhyControl2RespRcvd: expander device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); if (frameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) { DM_DBG2(("dmPhyControl2RespRcvd: SMP success\n")); } else { DM_DBG1(("dmPhyControl2RespRcvd: SMP failure; result 0x%x !!!\n", frameHeader->smpFunctionResult)); } return; } osGLOBAL void dmPhyControlFailureRespRcvd( dmRoot_t *dmRoot, agsaRoot_t *agRoot, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { DM_DBG1(("dmPhyControlFailureRespRcvd: start\n")); return; } GLOBAL void dmSetDeviceInfoCB( agsaRoot_t *agRoot, agsaContext_t *agContext, agsaDevHandle_t *agDevHandle, bit32 status, bit32 option, bit32 param ) { dmRoot_t *dmRoot = agNULL; agsaIORequest_t *agIORequest; bit32 smstatus; agsaSASRequestBody_t *agSASRequestBody; dmSMPRequestBody_t *dmSMPRequestBody = agNULL; dmIntPortContext_t *onePortContext = agNULL; dmDeviceData_t *oneDeviceData; bit8 SMPRequestFunction; bit8 devType_S_Rate; DM_DBG1(("dmSetDeviceInfoCB: start\n")); DM_DBG4(("dmSetDeviceInfoCB: status 0x%x\n", status)); DM_DBG4(("dmSetDeviceInfoCB: option 0x%x\n", option)); DM_DBG4(("dmSetDeviceInfoCB: param 0x%x\n", param)); if (status != OSSA_SUCCESS) { DM_DBG1(("dmSetDeviceInfoCB: status %d\n", status)); DM_DBG1(("dmSetDeviceInfoCB: option 0x%x\n", option)); DM_DBG1(("dmSetDeviceInfoCB: param 0x%x\n", param)); if (option == 32) /* set connection rate */ { DM_DBG1(("dmSetDeviceInfoCB: IO failure\n")); agIORequest = (agsaIORequest_t *)agContext->osData; dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData; dmRoot = dmSMPRequestBody->dmRoot; oneDeviceData = dmSMPRequestBody->dmDevice; onePortContext = oneDeviceData->dmPortContext; SMPRequestFunction = dmSMPRequestBody->smpPayload[1]; if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if (SMPRequestFunction == SMP_PHY_CONTROL) { /* task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, agNULL, agNULL ); } } } if (agDevHandle == agNULL) { DM_DBG1(("dmSetDeviceInfoCB: agDevHandle is NULL\n")); return; } /* retry SMP */ if (option == 32) /* set connection rate */ { DM_DBG1(("dmSetDeviceInfoCB: set connection rate option\n")); agIORequest = (agsaIORequest_t *)agContext->osData; dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData; dmRoot = dmSMPRequestBody->dmRoot; agSASRequestBody = &(dmSMPRequestBody->agSASRequestBody); oneDeviceData = dmSMPRequestBody->dmDevice; onePortContext = oneDeviceData->dmPortContext; devType_S_Rate = oneDeviceData->agDeviceInfo.devType_S_Rate; devType_S_Rate = (devType_S_Rate & 0xF0) | (param >> 28); oneDeviceData->agDeviceInfo.devType_S_Rate = devType_S_Rate; SMPRequestFunction = dmSMPRequestBody->smpPayload[1]; DM_DBG1(("dmSetDeviceInfoCB: SMPRequestFunction 0x%x\n", SMPRequestFunction)); DM_DBG1(("dmSetDeviceInfoCB: new rate is 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo))); smstatus = saSMPStart( agRoot, agIORequest, 0, agDevHandle, AGSA_SMP_INIT_REQ, agSASRequestBody, &dmsaSMPCompleted ); if (status == AGSA_RC_SUCCESS) { /* increment the number of pending SMP */ onePortContext->discovery.pendingSMP++; // dmSMPRequestBody->retries++; if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { /* start discovery-related SMP timer */ dmDiscoverySMPTimer(dmRoot, onePortContext, (bit32)SMPRequestFunction, dmSMPRequestBody); } return; } else if (status == AGSA_RC_BUSY) { onePortContext->discovery.pendingSMP++; // dmSMPRequestBody->retries++; if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody); } else if (SMPRequestFunction == SMP_PHY_CONTROL) { /* For taskmanagement SMP, let's fail task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, agNULL, agNULL ); } else { } } else /* AGSA_RC_FAILURE */ { if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if (SMPRequestFunction == SMP_PHY_CONTROL) { /* task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, agNULL, agNULL ); } else { } } } return; } /* smp completion */ osGLOBAL void dmSMPCompleted( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle ) { dmIntRoot_t *dmIntRoot = agNULL; dmIntContext_t *dmAllShared = agNULL; dmSMPRequestBody_t *dmSMPRequestBody = agNULL; agsaSMPFrame_t *agSMPFrame; dmRoot_t *dmRoot = agNULL; dmIntPortContext_t *onePortContext = agNULL; dmIntPortContext_t *oldonePortContext; dmExpander_t *oneExpander = agNULL; dmDeviceData_t *oneDeviceData; agsaDevHandle_t *agDevHandle = agNULL; agsaSASRequestBody_t *agSASRequestBody; bit8 smpHeader[4]; bit8 SMPRequestFunction; dmSMPFrameHeader_t *dmResponseSMPFrameHeader; dmSMPFrameHeader_t *dmSMPFrameHeader; bit8 *dmSMPPayload; smpReqPhyControl_t *smpPhyControlReq; smpReqPhyControl2_t *smpPhyControl2Req; #ifndef DIRECT_SMP dmSMPRequestBody_t *dmSMPResponseBody = agNULL; dmSMPFrameHeader_t *dmRequestSMPFrameHeader; bit8 smpRequestHeader[4]; #endif bit32 status; bit32 ConnRate = SAS_CONNECTION_RATE_12_0G; agsaContext_t *agContext = agNULL; DM_DBG3(("dmSMPCompleted: start\n")); dmSMPRequestBody = (dmSMPRequestBody_t *)agIORequest->osData; dmRoot = dmSMPRequestBody->dmRoot; dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; oneDeviceData = dmSMPRequestBody->dmDevice; agSASRequestBody = &(dmSMPRequestBody->agSASRequestBody); agSMPFrame = &(agSASRequestBody->smpFrame); if (oneDeviceData->valid == agFALSE && oneDeviceData->valid2 == agFALSE && oneDeviceData->dmPortContext == agNULL && dmSMPRequestBody->dmPortContext->valid == agFALSE ) { DM_DBG3(("dmSMPCompleted: port has been destroyed\n")); /* all device, port information have been reset just put smp to freeList */ /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } onePortContext = oneDeviceData->dmPortContext; oneExpander = oneDeviceData->dmExpander; agDevHandle = oneExpander->agDevHandle; #ifdef DIRECT_SMP SMPRequestFunction = dmSMPRequestBody->smpPayload[1]; #else saFrameReadBlock(agRoot, dmSMPRequestBody->IndirectSMP, 0, smpRequestHeader, 4); dmRequestSMPFrameHeader = (dmSMPFrameHeader_t *)smpRequestHeader; SMPRequestFunction = dmRequestSMPFrameHeader->smpFunction; #endif #ifdef NOT_IN_USE /* for debugging; dump SMP request payload */ dmhexdump("smp payload", (bit8 *)agSASRequestBody->smpFrame.outFrameBuf, agSASRequestBody->smpFrame.outFrameLen ); dmhexdump("smp payload new", (bit8 *)dmSMPRequestBody->smpPayload, agSASRequestBody->smpFrame.outFrameLen ); #endif /* sanity check */ if (onePortContext != agNULL) { DM_DBG5(("dmSMPCompleted: pid %d\n", onePortContext->id)); } else { DM_DBG1(("dmSMPCompleted: Wrong, onePortContext is NULL!!!\n")); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } oldonePortContext = dmSMPRequestBody->dmPortContext; if (oldonePortContext != agNULL) { DM_DBG5(("dmSMPCompleted: old pid %d\n", oldonePortContext->id)); } else { DM_DBG1(("dmSMPCompleted: Wrong, oldonePortContext is NULL!!!\n")); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } /* decrement the number of pending SMP */ onePortContext->discovery.pendingSMP--; /* for port invalid case; full discovery -> full discovery; incremental discovery -> full discovery */ if (onePortContext != oldonePortContext) { DM_DBG1(("dmSMPCompleted: portcontext has changed!!!\n")); if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { /* stop SMP timer */ tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (onePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &(onePortContext->discovery.DiscoverySMPTimer) ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (oldonePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &(oldonePortContext->discovery.DiscoverySMPTimer) ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } } /* clean up expanders data strucures; move to free exp when device is cleaned */ dmCleanAllExp(dmRoot, oldonePortContext); /* remove devices */ dmInternalRemovals(dmRoot, oldonePortContext); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } if (onePortContext->valid == agFALSE || onePortContext->DiscoveryState == DM_DSTATE_COMPLETED || onePortContext->discovery.status == DISCOVERY_SAS_DONE || onePortContext->DiscoveryAbortInProgress == agTRUE ) { if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { /* stop SMP timer */ tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (onePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &(onePortContext->discovery.DiscoverySMPTimer) ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (oldonePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &(oldonePortContext->discovery.DiscoverySMPTimer) ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } } /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif if (onePortContext->discovery.pendingSMP == 0) { DM_DBG1(("dmSMPCompleted: aborting discovery\n")); if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED || onePortContext->discovery.status == DISCOVERY_SAS_DONE || onePortContext->DiscoveryAbortInProgress == agTRUE ) { onePortContext->DiscoveryAbortInProgress = agFALSE; onePortContext->DiscoveryState = DM_DSTATE_COMPLETED; onePortContext->discovery.status = DISCOVERY_SAS_DONE; dmCleanAllExp(dmRoot, onePortContext); if ( onePortContext->DiscoveryAbortInProgress == agTRUE) { tddmDiscoverCB( dmRoot, onePortContext->dmPortContext, dmDiscAborted ); } } } else { DM_DBG3(("dmSMPCompleted: not yet abort; non zero pendingSMP %d\n", onePortContext->discovery.pendingSMP)); } return; } if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { /* stop SMP timer */ tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (onePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &(onePortContext->discovery.DiscoverySMPTimer) ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (oldonePortContext->discovery.DiscoverySMPTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &(oldonePortContext->discovery.DiscoverySMPTimer) ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } } if (oneExpander->SAS2 == 0) { DM_DBG3(("dmSMPCompleted: SAS 1.1\n")); if (agIOStatus == OSSA_IO_SUCCESS) { //tdhexdump("dmSMPCompleted", (bit8*)agFrameHandle, agIOInfoLen); /* parsing SMP payload */ #ifdef DIRECT_SMP saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4); #else dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 0, smpHeader, 4); #endif dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader; /* SMP function dependent payload */ switch (dmResponseSMPFrameHeader->smpFunction) { case SMP_REPORT_GENERAL: DM_DBG3(("dmSMPCompleted: report general\n")); if (agIOInfoLen != sizeof(smpRespReportGeneral_t) + 4 && dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) { DM_DBG3(("dmSMPCompleted: mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (unsigned int)sizeof(smpRespReportGeneral_t) + 4)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } /* start here */ dmReportGeneralRespRcvd( dmRoot, agRoot, agIORequest, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); break; case SMP_DISCOVER: DM_DBG3(("dmSMPCompleted: discover\n")); if (agIOInfoLen != sizeof(smpRespDiscover_t) + 4 && dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) { DM_DBG3(("dmSMPCompleted: mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (unsigned int)sizeof(smpRespDiscover_t) + 4)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } dmDiscoverRespRcvd( dmRoot, agRoot, agIORequest, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); break; case SMP_REPORT_PHY_SATA: DM_DBG3(("dmSMPCompleted: report phy sata\n")); if (agIOInfoLen != sizeof(smpRespReportPhySata_t) + 4 && dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) { DM_DBG3(("dmSMPCompleted: mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (unsigned int)sizeof(smpRespReportPhySata_t) + 4)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } dmReportPhySataRcvd( dmRoot, agRoot, agIORequest, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); break; case SMP_CONFIGURE_ROUTING_INFORMATION: DM_DBG3(("dmSMPCompleted: configure routing information\n")); if (agIOInfoLen != 4 && dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) { DM_DBG3(("dmSMPCompleted: mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, 4)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } dmConfigRoutingInfoRespRcvd( dmRoot, agRoot, agIORequest, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); break; case SMP_PHY_CONTROL: DM_DBG3(("dmSMPCompleted: phy control\n")); if (agIOInfoLen != 4 && dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED) /*zero length is expected */ { DM_DBG3(("dmSMPCompleted: mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, 4)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } dmPhyControlRespRcvd( dmRoot, agRoot, agIORequest, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); break; case SMP_REPORT_ROUTING_INFORMATION: /* fall through */ case SMP_REPORT_PHY_ERROR_LOG: /* fall through */ case SMP_PHY_TEST_FUNCTION: /* fall through */ case SMP_REPORT_MANUFACTURE_INFORMATION: /* fall through */ case SMP_READ_GPIO_REGISTER: /* fall through */ case SMP_WRITE_GPIO_REGISTER: /* fall through */ default: DM_DBG1(("dmSMPCompleted: wrong SMP function 0x%x !!!\n", dmResponseSMPFrameHeader->smpFunction)); DM_DBG1(("dmSMPCompleted: smpFrameType 0x%x !!!\n", dmResponseSMPFrameHeader->smpFrameType)); DM_DBG1(("dmSMPCompleted: smpFunctionResult 0x%x !!!\n", dmResponseSMPFrameHeader->smpFunctionResult)); DM_DBG1(("dmSMPCompleted: smpReserved 0x%x !!!\n", dmResponseSMPFrameHeader->smpReserved)); dmhexdump("dmSMPCompleted: SMP payload !!!", (bit8 *)agFrameHandle, agIOInfoLen); break; } /* switch */ } /* OSSA_IO_SUCCESS */ else if (agIOStatus == OSSA_IO_ABORTED || agIOStatus == OSSA_IO_INVALID_LENGTH) { /* no retry this case */ DM_DBG1(("dmSMPCompleted: OSSA_IO_ABORTED or OSSA_IO_INVALID_LENGTH, status 0x%x\n", agIOStatus)); } else if (agIOStatus == OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE) { DM_DBG3(("dmSMPCompleted: OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE\n")); saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4); dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader; status = saSMPStart( agRoot, agIORequest, 0, agDevHandle, AGSA_SMP_INIT_REQ, agSASRequestBody, &dmsaSMPCompleted ); if (status == AGSA_RC_SUCCESS) { /* increment the number of pending SMP */ onePortContext->discovery.pendingSMP++; if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { /* start discovery-related SMP timer */ dmDiscoverySMPTimer(dmRoot, onePortContext, (bit32)(dmResponseSMPFrameHeader->smpFunction), dmSMPRequestBody); } return; } else if (status == AGSA_RC_BUSY) { if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL || dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER || dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA || dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody); } else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL) { /* For taskmanagement SMP, let's fail task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); } else { } } else /* AGSA_RC_FAILURE */ { if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL || dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER || dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA || dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL) { /* task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); } else { } } } /* OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE*/ else { if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED || agIOStatus == OSSA_IO_DS_NON_OPERATIONAL ) { DM_DBG1(("dmSMPCompleted: setting back to operational\n")); saSetDeviceState(agRoot, agNULL, 0, agDevHandle, SA_DS_OPERATIONAL); } if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED && dmAllShared->RateAdjust) { DM_DBG1(("dmSMPCompleted: OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); DM_DBG1(("dmSMPCompleted: SMPRequestFunction 0x%x\n", SMPRequestFunction)); ConnRate = DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo); if (ConnRate == SAS_CONNECTION_RATE_1_5G) { /* no retry; failure ??? */ if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if (SMPRequestFunction == SMP_PHY_CONTROL) { /* task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, agNULL, agNULL ); } else { } } else { ConnRate = ConnRate - 1; } agContext = &(dmSMPRequestBody->agContext); agContext->osData = agIORequest; saSetDeviceInfo(agRoot, agContext, 0, agDevHandle, 32, ConnRate << 28, dmSetDeviceInfoCB); } else { if (dmSMPRequestBody->retries < SMP_RETRIES) /* 5 */ { /* retry the SMP again */ DM_DBG1(("dmSMPCompleted: failed, but retries %d agIOStatus 0x%x %d agIOInfoLen %d !!!\n", dmSMPRequestBody->retries, agIOStatus, agIOStatus, agIOInfoLen)); saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4); dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader; status = saSMPStart( agRoot, agIORequest, 0, agDevHandle, AGSA_SMP_INIT_REQ, agSASRequestBody, &dmsaSMPCompleted ); if (status == AGSA_RC_SUCCESS) { /* increment the number of pending SMP */ onePortContext->discovery.pendingSMP++; dmSMPRequestBody->retries++; if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { /* start discovery-related SMP timer */ dmDiscoverySMPTimer(dmRoot, onePortContext, (bit32)(dmResponseSMPFrameHeader->smpFunction), dmSMPRequestBody); } return; } else if (status == AGSA_RC_BUSY) { onePortContext->discovery.pendingSMP++; dmSMPRequestBody->retries++; if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL || dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER || dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA || dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody); return; } else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL) { /* For taskmanagement SMP, let's fail task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); } else { } } else /* AGSA_RC_FAILURE */ { if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL || dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER || dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA || dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL) { /* task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); } else { } } } else { dmSMPFrameHeader = (dmSMPFrameHeader_t *)agSMPFrame->outFrameBuf; dmSMPPayload = (bit8 *)agSMPFrame->outFrameBuf + 4; DM_DBG1(("dmSMPCompleted: failed. no more retry. agIOStatus 0x%x %d !!!\n", agIOStatus, agIOStatus)); if (agIOStatus == OSSA_IO_DS_NON_OPERATIONAL) { DM_DBG1(("dmSMPCompleted: failed, agIOStatus is OSSA_IO_DS_NON_OPERATIONAL!!!\n")); } if (agIOStatus == OSSA_IO_DS_IN_RECOVERY) { DM_DBG1(("dmSMPCompleted: failed, agIOStatus is OSSA_IO_DS_IN_RECOVERY!!!\n")); } if (dmSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL || dmSMPFrameHeader->smpFunction == SMP_DISCOVER || dmSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA || dmSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { /* discovery failure */ DM_DBG1(("dmSMPCompleted: SMP function 0x%x\n", dmSMPFrameHeader->smpFunction)); DM_DBG1(("dmSMPCompleted: discover done with error\n")); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if (dmSMPFrameHeader->smpFunction == SMP_PHY_CONTROL) { DM_DBG3(("dmSMPCompleted: SMP_PHY_CONTROL\n")); smpPhyControlReq = (smpReqPhyControl_t *)dmSMPPayload; if (smpPhyControlReq->phyOperation == SMP_PHY_CONTROL_CLEAR_AFFILIATION) { DM_DBG3(("dmSMPCompleted: discover done with error\n")); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else { DM_DBG3(("dmSMPCompleted: unknown phy operation 0x%x\n", smpPhyControlReq->phyOperation)); } } /* SMP_PHY_CONTROL */ else { DM_DBG3(("dmSMPCompleted: SMP function 0x%x\n", dmSMPFrameHeader->smpFunction)); } } /* else */ } /* for RateAdjust */ } /* outer else */ } /* SAS 1.1 */ /************************************ SAS 2 ***********************************************/ else { DM_DBG2(("dmSMPCompleted: SAS 2\n")); if (agIOStatus == OSSA_IO_SUCCESS) { //tdhexdump("dmSMPCompleted", (bit8*)agFrameHandle, agIOInfoLen); /* parsing SMP payload */ #ifdef DIRECT_SMP saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4); #else dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; saFrameReadBlock(agRoot, dmSMPResponseBody->IndirectSMP, 0, smpHeader, 4); #endif dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader; /* SMP function dependent payload */ switch (dmResponseSMPFrameHeader->smpFunction) { case SMP_REPORT_GENERAL: DM_DBG2(("dmSMPCompleted: report general\n")); if ((agIOInfoLen != sizeof(smpRespReportGeneral2_t) + 4) && dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ) { DM_DBG1(("dmSMPCompleted: report general mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (int)sizeof(smpRespReportGeneral2_t) + 4)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } dmReportGeneral2RespRcvd( dmRoot, agRoot, agIORequest, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); break; case SMP_DISCOVER: DM_DBG2(("dmSMPCompleted: discover\n")); if ((agIOInfoLen != sizeof(smpRespDiscover2_t) + 4) && dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ) { DM_DBG1(("dmSMPCompleted: discover mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (int)sizeof(smpRespDiscover2_t) + 4)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } dmDiscover2RespRcvd( dmRoot, agRoot, agIORequest, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); break; case SMP_REPORT_PHY_SATA: DM_DBG2(("dmSMPCompleted: report phy sata\n")); if ((agIOInfoLen != sizeof(smpRespReportPhySata2_t) + 4) && dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ) { DM_DBG1(("dmSMPCompleted: report phy sata mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, (int)sizeof(smpRespReportPhySata2_t) + 4)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } dmReportPhySata2Rcvd( dmRoot, agRoot, agIORequest, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); break; case SMP_CONFIGURE_ROUTING_INFORMATION: DM_DBG2(("dmSMPCompleted: configure routing information\n")); if (agIOInfoLen != 4 && dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ) { DM_DBG1(("dmSMPCompleted: configure routing information mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, 4)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } dmConfigRoutingInfo2RespRcvd( dmRoot, agRoot, agIORequest, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); break; case SMP_PHY_CONTROL: DM_DBG2(("dmSMPCompleted: phy control\n")); if (agIOInfoLen != 4 && dmResponseSMPFrameHeader->smpFunctionResult == SMP_FUNCTION_ACCEPTED ) /*zero length is expected */ { DM_DBG1(("dmSMPCompleted: phy control mismatch len agIOInfoLen 0x%x 0x%x\n", agIOInfoLen, 4)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } dmPhyControl2RespRcvd( dmRoot, agRoot, agIORequest, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); break; #ifdef NOT_YET case SMP_DISCOVER_LIST: DM_DBG1(("dmSMPCompleted: SMP_DISCOVER_LIST\n")); DM_DBG1(("dmSMPCompleted: agIOInfoLen 0x%x \n", agIOInfoLen)); tdhexdump("dmSMPCompleted", (bit8*)agFrameHandle, agIOInfoLen); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; break; #endif case SMP_REPORT_ROUTING_INFORMATION: /* fall through */ case SMP_REPORT_PHY_ERROR_LOG: /* fall through */ case SMP_PHY_TEST_FUNCTION: /* fall through */ case SMP_REPORT_MANUFACTURE_INFORMATION: /* fall through */ case SMP_READ_GPIO_REGISTER: /* fall through */ case SMP_WRITE_GPIO_REGISTER: /* fall through */ default: DM_DBG1(("dmSMPCompleted: wrong SMP function 0x%x\n", dmResponseSMPFrameHeader->smpFunction)); DM_DBG1(("dmSMPCompleted: smpFrameType 0x%x\n", dmResponseSMPFrameHeader->smpFrameType)); DM_DBG1(("dmSMPCompleted: smpFunctionResult 0x%x\n", dmResponseSMPFrameHeader->smpFunctionResult)); DM_DBG1(("dmSMPCompleted: smpReserved 0x%x\n", dmResponseSMPFrameHeader->smpReserved)); dmhexdump("dmSMPCompleted: SMP payload", (bit8 *)agFrameHandle, agIOInfoLen); break; } } /* agIOStatus == OSSA_IO_SUCCESS */ else if (agIOStatus == OSSA_IO_ABORTED || agIOStatus == OSSA_IO_INVALID_LENGTH) { /* no retry this case */ DM_DBG1(("dmSMPCompleted: OSSA_IO_ABORTED or OSSA_IO_INVALID_LENGTH, status 0x%x\n", agIOStatus)); } else if (agIOStatus == OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE) { DM_DBG1(("dmSMPCompleted: OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE\n")); saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4); dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader; status = saSMPStart( agRoot, agIORequest, 0, agDevHandle, AGSA_SMP_INIT_REQ, agSASRequestBody, &dmsaSMPCompleted ); if (status == AGSA_RC_SUCCESS) { /* increment the number of pending SMP */ onePortContext->discovery.pendingSMP++; if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { /* start discovery-related SMP timer */ dmDiscoverySMPTimer(dmRoot, onePortContext, (bit32)(dmResponseSMPFrameHeader->smpFunction), dmSMPRequestBody); } return; } else if (status == AGSA_RC_BUSY) { if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL || dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER || dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA || dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody); } else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL) { /* For taskmanagement SMP, let's fail task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); } else { } } else /* AGSA_RC_FAILURE */ { if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL || dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER || dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA || dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL) { /* task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); } else { } } } else if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION) { DM_DBG1(("dmSMPCompleted: OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); /* skip to the next expander */ dmHandleZoneViolation( dmRoot, agRoot, agIORequest, oneDeviceData, agNULL, agFrameHandle ); } else { if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED || agIOStatus == OSSA_IO_DS_NON_OPERATIONAL ) { DM_DBG1(("dmSMPCompleted: setting back to operational\n")); saSetDeviceState(agRoot, agNULL, 0, agDevHandle, SA_DS_OPERATIONAL); } if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED && dmAllShared->RateAdjust) { DM_DBG1(("dmSMPCompleted: OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); DM_DBG1(("dmSMPCompleted: SMPRequestFunction 0x%x\n", SMPRequestFunction)); ConnRate = DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo); if (ConnRate == SAS_CONNECTION_RATE_1_5G) { /* no retry; failure ??? */ if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if (SMPRequestFunction == SMP_PHY_CONTROL) { /* task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, agNULL, agNULL ); } else { } } else { ConnRate = ConnRate - 1; } agContext = &(dmSMPRequestBody->agContext); agContext->osData = agIORequest; saSetDeviceInfo(agRoot, agContext, 0, agDevHandle, 32, ConnRate << 28, dmSetDeviceInfoCB); } else { if (dmSMPRequestBody->retries < SMP_RETRIES) /* 5 */ { /* retry the SMP again */ DM_DBG1(("dmSMPCompleted: failed! but retries %d agIOStatus 0x%x %d agIOInfoLen %d\n", dmSMPRequestBody->retries, agIOStatus, agIOStatus, agIOInfoLen)); saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4); dmResponseSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader; status = saSMPStart( agRoot, agIORequest, 0, agDevHandle, AGSA_SMP_INIT_REQ, agSASRequestBody, &dmsaSMPCompleted ); if (status == AGSA_RC_SUCCESS) { /* increment the number of pending SMP */ onePortContext->discovery.pendingSMP++; dmSMPRequestBody->retries++; if (SMPRequestFunction == SMP_REPORT_GENERAL || SMPRequestFunction == SMP_DISCOVER || SMPRequestFunction == SMP_REPORT_PHY_SATA || SMPRequestFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { /* start discovery-related SMP timer */ dmDiscoverySMPTimer(dmRoot, onePortContext, (bit32)(dmResponseSMPFrameHeader->smpFunction), dmSMPRequestBody); } return; } else if (status == AGSA_RC_BUSY) { onePortContext->discovery.pendingSMP++; dmSMPRequestBody->retries++; if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL || dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER || dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA || dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody); return; } else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL) { /* For taskmanagement SMP, let's fail task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); } else { } } else /* AGSA_RC_FAILURE */ { if (dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL || dmResponseSMPFrameHeader->smpFunction == SMP_DISCOVER || dmResponseSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA || dmResponseSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if (dmResponseSMPFrameHeader->smpFunction == SMP_PHY_CONTROL) { /* task management failure */ dmPhyControlFailureRespRcvd( dmRoot, agRoot, oneDeviceData, dmResponseSMPFrameHeader, agFrameHandle ); } else { } } } else { dmSMPFrameHeader = (dmSMPFrameHeader_t *)agSMPFrame->outFrameBuf; dmSMPPayload = (bit8 *)agSMPFrame->outFrameBuf + 4; DM_DBG1(("dmSMPCompleted: failed! no more retry! agIOStatus 0x%x %d\n", agIOStatus, agIOStatus)); if (agIOStatus == OSSA_IO_DS_NON_OPERATIONAL) { DM_DBG1(("dmSMPCompleted: failed! agIOStatus is OSSA_IO_DS_NON_OPERATIONAL\n")); } if (agIOStatus == OSSA_IO_DS_IN_RECOVERY) { DM_DBG1(("dmSMPCompleted: failed! agIOStatus is OSSA_IO_DS_IN_RECOVERY\n")); } if (dmSMPFrameHeader->smpFunction == SMP_REPORT_GENERAL || dmSMPFrameHeader->smpFunction == SMP_DISCOVER || dmSMPFrameHeader->smpFunction == SMP_REPORT_PHY_SATA || dmSMPFrameHeader->smpFunction == SMP_CONFIGURE_ROUTING_INFORMATION ) { /* discovery failure */ DM_DBG1(("dmSMPCompleted: SMP function 0x%x\n", dmSMPFrameHeader->smpFunction)); DM_DBG1(("dmSMPCompleted: discover done with error\n")); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if (dmSMPFrameHeader->smpFunction == SMP_PHY_CONTROL) { DM_DBG1(("dmSMPCompleted: SMP_PHY_CONTROL\n")); smpPhyControl2Req = (smpReqPhyControl2_t *)dmSMPPayload; if (smpPhyControl2Req->phyOperation == SMP_PHY_CONTROL_CLEAR_AFFILIATION) { DM_DBG1(("dmSMPCompleted: discover done with error\n")); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else { DM_DBG1(("dmSMPCompleted: unknown phy operation 0x%x\n", smpPhyControl2Req->phyOperation)); } } /* SMP_PHY_CONTROL */ else { DM_DBG1(("dmSMPCompleted: SMP function 0x%x\n", dmSMPFrameHeader->smpFunction)); } } /* else */ } /* for RateAdjust */ } /* outer else */ } /* SAS 2 else */ /* SMP request */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #ifndef DIRECT_SMP /* SMP response */ dmSMPResponseBody = (dmSMPRequestBody_t *)dmSMPRequestBody->IndirectSMPResponse; if (dmSMPResponseBody == agNULL) { DM_DBG1(("dmSMPCompleted: Wrong, dmSMPResponseBody is NULL!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPResponseBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); #endif return; } osGLOBAL void dmSMPAbortCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 flag, bit32 status) { dmRoot_t *dmRoot = agNULL; dmIntRoot_t *dmIntRoot = agNULL; dmIntContext_t *dmAllShared = agNULL; dmSMPRequestBody_t *dmSMPRequestBody = (dmSMPRequestBody_t *) agIORequest->osData; DM_DBG5(("dmSMPAbortCB: start\n")); if (dmSMPRequestBody == agNULL) { DM_DBG1(("dmSMPAbortCB: pSMPRequestBody is NULL!!! \n")); return; } dmRoot = dmSMPRequestBody->dmRoot; dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; /* put back into free smplist */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(dmSMPRequestBody->Link), &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); /* start here */ if (flag == 2) { /* abort all per port */ DM_DBG1(("dmSMPAbortCB: abort per port; not used!!!\n")); } else if (flag == 1) { /* abort all */ DM_DBG1(("dmSMPAbortCB: abort all; not used!!!\n")); } else if (flag == 0) { /* abort one */ DM_DBG1(("ossaSMPAbortCB: abort one\n")); if (status != OSSA_IO_SUCCESS) { DM_DBG1(("dmSMPAbortCB: abort one, status 0x%x\n", status)); } } else { DM_DBG1(("dmSMPAbortCB: not allowed case, flag 0x%x!!!\n", flag)); } return; } #endif /* FDS_DM */