/******************************************************************************* ** *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 #include #include #include #include #include #include #include #ifdef FDS_DM #include #include #include #include #include #include /*****************************************************************************/ /*! \brief dmDiscover * * * Purpose: A discovery is started by this function * * \param dmRoot: DM context handle. * \param dmPortContext: Pointer to this instance of port context * \param option: Discovery option * * \return: * DM_RC_SUCCESS * DM_RC_FAILURE * */ /*****************************************************************************/ osGLOBAL bit32 dmDiscover( dmRoot_t *dmRoot, dmPortContext_t *dmPortContext, bit32 option) { dmIntPortContext_t *onePortContext = agNULL; bit32 ret = DM_RC_FAILURE; DM_DBG3(("dmDiscover: start\n")); onePortContext = (dmIntPortContext_t *)dmPortContext->dmData; if (onePortContext == agNULL) { DM_DBG1(("dmDiscover: onePortContext is NULL!!!\n")); return DM_RC_FAILURE; } if (onePortContext->valid == agFALSE) { DM_DBG1(("dmDiscover: invalid port!!!\n")); return DM_RC_FAILURE; } if (onePortContext->RegFailed == agTRUE) { DM_DBG1(("dmDiscover: Registration failed!!!\n")); return DM_RC_FAILURE; } switch ( option ) { case DM_DISCOVERY_OPTION_FULL_START: DM_DBG3(("dmDiscover: full, pid %d\n", onePortContext->id)); onePortContext->discovery.type = DM_DISCOVERY_OPTION_FULL_START; dmDiscoveryResetMCN(dmRoot, onePortContext); ret = dmFullDiscover(dmRoot, onePortContext); break; case DM_DISCOVERY_OPTION_INCREMENTAL_START: DM_DBG3(("dmDiscover: incremental, pid %d\n", onePortContext->id)); onePortContext->discovery.type = DM_DISCOVERY_OPTION_INCREMENTAL_START; dmDiscoveryResetMCN(dmRoot, onePortContext); ret = dmIncrementalDiscover(dmRoot, onePortContext, agFALSE); break; case DM_DISCOVERY_OPTION_ABORT: DM_DBG3(("dmDiscover: abort\n")); if (onePortContext->DiscoveryState != DM_DSTATE_COMPLETED) { if (onePortContext->discovery.pendingSMP == 0) { dmDiscoverAbort(dmRoot, onePortContext); tddmDiscoverCB( dmRoot, onePortContext->dmPortContext, dmDiscAborted ); } else { DM_DBG3(("dmDiscover: abortInProgress\n")); onePortContext->DiscoveryAbortInProgress = agTRUE; tddmDiscoverCB( dmRoot, dmPortContext, dmDiscAbortInProgress ); } } else { DM_DBG3(("dmDiscover: no discovery to abort\n")); tddmDiscoverCB( dmRoot, dmPortContext, dmDiscAbortInvalid ); } ret = DM_RC_SUCCESS; break; default: break; } return ret; } osGLOBAL bit32 dmFullDiscover( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmExpander_t *oneExpander = agNULL; dmSASSubID_t dmSASSubID; dmDeviceData_t *oneExpDeviceData = agNULL; DM_DBG1(("dmFullDiscover: start\n")); if (onePortContext->valid == agFALSE) { DM_DBG1(("dmFullDiscover: invalid port!!!\n")); return DM_RC_FAILURE; } if (onePortContext->DiscoveryState == DM_DSTATE_STARTED) { DM_DBG1(("dmFullDiscover: no two instances of discovery allowed!!!\n")); return DM_RC_FAILURE; } onePortContext->DiscoveryState = DM_DSTATE_STARTED; dmSASSubID.sasAddressHi = onePortContext->sasRemoteAddressHi; dmSASSubID.sasAddressLo = onePortContext->sasRemoteAddressLo; /* check OnePortContext->discovery.discoveringExpanderList */ oneExpander = dmExpFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo); if (oneExpander != agNULL) { oneExpDeviceData = oneExpander->dmDevice; } else { /* check dmAllShared->mainExpanderList */ oneExpander = dmExpMainListFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo); if (oneExpander != agNULL) { oneExpDeviceData = oneExpander->dmDevice; } } if (oneExpDeviceData != agNULL) { dmSASSubID.initiator_ssp_stp_smp = oneExpDeviceData->initiator_ssp_stp_smp; dmSASSubID.target_ssp_stp_smp = oneExpDeviceData->target_ssp_stp_smp; oneExpDeviceData->registered = agTRUE; dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, oneExpDeviceData, 0xFF); } else { DM_DBG1(("dmFullDiscover:oneExpDeviceData is NULL!!!\n")); return DM_RC_FAILURE; } dmUpStreamDiscoverStart(dmRoot, onePortContext); return DM_RC_SUCCESS; } osGLOBAL bit32 dmIncrementalDiscover( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, bit32 flag ) { dmExpander_t *oneExpander = agNULL; dmSASSubID_t dmSASSubID; dmDeviceData_t *oneExpDeviceData = agNULL; DM_DBG1(("dmIncrementalDiscover: start\n")); if (onePortContext->valid == agFALSE) { DM_DBG1(("dmIncrementalDiscover: invalid port!!!\n")); return DM_RC_FAILURE; } /* TDM triggerred; let go DM triggerred */ if (flag == agFALSE) { if (onePortContext->DiscoveryState == DM_DSTATE_STARTED) { DM_DBG1(("dmIncrementalDiscover: no two instances of discovery allowed!!!\n")); return DM_RC_FAILURE; } } onePortContext->DiscoveryState = DM_DSTATE_STARTED; onePortContext->discovery.type = DM_DISCOVERY_OPTION_INCREMENTAL_START; dmSASSubID.sasAddressHi = onePortContext->sasRemoteAddressHi; dmSASSubID.sasAddressLo = onePortContext->sasRemoteAddressLo; /* check OnePortContext->discovery.discoveringExpanderList */ oneExpander = dmExpFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo); if (oneExpander != agNULL) { oneExpDeviceData = oneExpander->dmDevice; } else { /* check dmAllShared->mainExpanderList */ oneExpander = dmExpMainListFind(dmRoot, onePortContext, dmSASSubID.sasAddressHi, dmSASSubID.sasAddressLo); if (oneExpander != agNULL) { oneExpDeviceData = oneExpander->dmDevice; } } if (oneExpDeviceData != agNULL) { dmSASSubID.initiator_ssp_stp_smp = oneExpDeviceData->initiator_ssp_stp_smp; dmSASSubID.target_ssp_stp_smp = oneExpDeviceData->target_ssp_stp_smp; oneExpDeviceData->registered = agTRUE; dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, oneExpDeviceData, 0xFF); } else { DM_DBG1(("dmIncrementalDiscover:oneExpDeviceData is NULL!!!\n")); return DM_RC_FAILURE; } dmUpStreamDiscoverStart(dmRoot, onePortContext); return DM_RC_SUCCESS; } osGLOBAL void dmUpStreamDiscoverStart( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { // dmExpander_t *oneExpander = agNULL; bit32 sasAddressHi, sasAddressLo; dmDeviceData_t *oneDeviceData; dmExpander_t *oneExpander = agNULL; DM_DBG3(("dmUpStreamDiscoverStart: start\n")); if (onePortContext->valid == agFALSE) { DM_DBG1(("dmUpStreamDiscoverStart: invalid port!!!\n")); return; } /* at this point, the 1st expander should have been registered. find an expander from onePortContext */ sasAddressHi = onePortContext->sasRemoteAddressHi; sasAddressLo = onePortContext->sasRemoteAddressLo; DM_DBG3(("dmUpStreamDiscoverStart: Port Remote AddrHi 0x%08x Remote AddrLo 0x%08x\n", sasAddressHi, sasAddressLo)); oneDeviceData = dmDeviceFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo); // oneDeviceData = oneExpander->dmDevice; // start here onePortContext->discovery.status = DISCOVERY_UP_STREAM; if (oneDeviceData == agNULL) { DM_DBG1(("dmUpStreamDiscoverStart: oneExpander is NULL, wrong!!!\n")); return; } else { if ( (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE) || (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE) || DEVICE_IS_SMP_TARGET(oneDeviceData) ) { #if 1 /* for incremental discovery */ /* start here: if not on discoveringExpanderList, alloc and add dmNewEXPorNot() */ oneExpander = dmExpFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo); if ( oneExpander == agNULL) { /* alloc and add */ oneExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, oneDeviceData); if ( oneExpander != agNULL) { dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander); } else { DM_DBG1(("dmUpStreamDiscoverStart: failed to allocate expander or discovey aborted!!!\n")); return; } } #endif dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } else { DM_DBG1(("dmUpStreamDiscoverStart: oneDeviceData is not an Expander did %d, wrong!!!\n", oneDeviceData->id)); return; } } return; } /* sends report general */ osGLOBAL void dmUpStreamDiscovering( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmDeviceData_t *oneDeviceData ) { dmList_t *ExpanderList; dmExpander_t *oneNextExpander = agNULL; DM_DBG3(("dmUpStreamDiscovering: start\n")); if (onePortContext->valid == agFALSE) { DM_DBG1(("dmUpStreamDiscovering: invalid port!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); if (DMLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList))) { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); DM_DBG3(("dmUpStreamDiscovering: should be the end\n")); oneNextExpander = agNULL; } else { DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList)); oneNextExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); if ( oneNextExpander != agNULL) { DMLIST_ENQUEUE_AT_HEAD(&(oneNextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList)); DM_DBG3(("dmUpStreamDiscovering tdsaSASUpStreamDiscovering: dequeue head\n")); DM_DBG3(("dmUpStreamDiscovering: expander id %d\n", oneNextExpander->id)); } else { DM_DBG1(("dmUpStreamDiscovering: oneNextExpander is NULL!!!\n")); } tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } if (oneNextExpander != agNULL) { dmReportGeneralSend(dmRoot, oneNextExpander->dmDevice); } else { DM_DBG3(("dmUpStreamDiscovering: No more expander list\n")); dmDownStreamDiscoverStart(dmRoot, onePortContext, oneDeviceData); } return; } osGLOBAL void dmDownStreamDiscoverStart( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmDeviceData_t *oneDeviceData ) { dmExpander_t *UpStreamExpander; dmExpander_t *oneExpander; DM_DBG3(("dmDownStreamDiscoverStart: start\n")); if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmDownStreamDiscoverStart: invalid port or aborted discovery!!!\n")); return; } /* set discovery status */ onePortContext->discovery.status = DISCOVERY_DOWN_STREAM; /* If it's an expander */ if ( (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE) || (oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE) || DEVICE_IS_SMP_TARGET(oneDeviceData) ) { oneExpander = oneDeviceData->dmExpander; UpStreamExpander = oneExpander->dmUpStreamExpander; /* If the two expanders are the root of two edge sets; sub-to-sub */ if ( (UpStreamExpander != agNULL) && ( UpStreamExpander->dmUpStreamExpander == oneExpander ) ) { DM_DBG3(("dmDownStreamDiscoverStart: Root found pExpander=%p pUpStreamExpander=%p\n", oneExpander, UpStreamExpander)); //Saves the root expander onePortContext->discovery.RootExp = oneExpander; DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); /* reset up stream inform for pExpander */ oneExpander->dmUpStreamExpander = agNULL; /* Add the pExpander to discovering list */ dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander); /* reset up stream inform for oneExpander */ UpStreamExpander->dmUpStreamExpander = agNULL; /* Add the UpStreamExpander to discovering list */ dmDiscoveringExpanderAdd(dmRoot, onePortContext, UpStreamExpander); } /* If the two expanders are not the root of two edge sets. eg) one root */ else { //Saves the root expander onePortContext->discovery.RootExp = oneExpander; DM_DBG3(("dmDownStreamDiscoverStart: NO Root pExpander=%p\n", oneExpander)); DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmDownStreamDiscoverStart: Root exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); /* (2.2.2.1) Add the pExpander to discovering list */ dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander); } } /* Continue down stream discovering */ dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData); return; } osGLOBAL void dmDownStreamDiscovering( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmDeviceData_t *oneDeviceData ) { dmExpander_t *NextExpander = agNULL; dmList_t *ExpanderList; DM_DBG3(("dmDownStreamDiscovering: start\n")); if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmDownStreamDiscovering: invalid port or aborted discovery!!!\n")); return; } tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); if (DMLIST_EMPTY(&(onePortContext->discovery.discoveringExpanderList))) { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); DM_DBG3(("dmDownStreamDiscovering: should be the end\n")); NextExpander = agNULL; } else { DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(onePortContext->discovery.discoveringExpanderList)); NextExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); if ( NextExpander != agNULL) { DMLIST_ENQUEUE_AT_HEAD(&(NextExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList)); DM_DBG3(("dmDownStreamDiscovering tdsaSASDownStreamDiscovering: dequeue head\n")); DM_DBG3(("dmDownStreamDiscovering: expander id %d\n", NextExpander->id)); } else { DM_DBG1(("dmDownStreamDiscovering: NextExpander is NULL!!!\n")); } tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } /* If there is an expander for continue discoving */ if ( NextExpander != agNULL) { DM_DBG3(("dmDownStreamDiscovering: Found pNextExpander=%p discoveryStatus=0x%x\n", NextExpander, onePortContext->discovery.status)); switch (onePortContext->discovery.status) { /* If the discovery status is DISCOVERY_DOWN_STREAM */ case DISCOVERY_DOWN_STREAM: /* Send report general for the next expander */ DM_DBG3(("dmDownStreamDiscovering: DownStream pNextExpander=%p\n", NextExpander)); DM_DBG3(("dmDownStreamDiscovering: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmDownStreamDiscovering: oneExpander %p did %d\n", oneDeviceData->dmExpander, oneDeviceData->dmExpander->id)); DM_DBG3(("dmDownStreamDiscovering: 2nd oneDeviceData %p did %d\n", NextExpander->dmDevice, NextExpander->dmDevice->id)); DM_DBG3(("dmDownStreamDiscovering: 2nd oneExpander %p did %d\n", NextExpander, NextExpander->id)); DM_DBG3(("dmDownStreamDiscovering: 2nd used oneExpander %p did %d\n", NextExpander->dmDevice->dmExpander, NextExpander->dmDevice->dmExpander->id)); if (NextExpander != NextExpander->dmDevice->dmExpander) { DM_DBG3(("dmDownStreamDiscovering: wrong!!!\n")); } dmReportGeneralSend(dmRoot, NextExpander->dmDevice); break; /* If the discovery status is DISCOVERY_CONFIG_ROUTING */ case DISCOVERY_CONFIG_ROUTING: case DISCOVERY_REPORT_PHY_SATA: /* set discovery status */ onePortContext->discovery.status = DISCOVERY_DOWN_STREAM; DM_DBG3(("dmDownStreamDiscovering: pPort->discovery.status=DISCOVERY_CONFIG_ROUTING, make it DOWN_STREAM\n")); /* If not the last phy */ if ( NextExpander->discoveringPhyId < NextExpander->dmDevice->numOfPhys ) { DM_DBG3(("dmDownStreamDiscovering: pNextExpander->discoveringPhyId=0x%x pNextExpander->numOfPhys=0x%x. Send More Discover\n", NextExpander->discoveringPhyId, NextExpander->dmDevice->numOfPhys)); /* Send discover for the next expander */ dmDiscoverSend(dmRoot, NextExpander->dmDevice); } /* If it's the last phy */ else { DM_DBG3(("dmDownStreamDiscovering: Last Phy, remove expander%p start DownStream=%p\n", NextExpander, NextExpander->dmDevice)); dmDiscoveringExpanderRemove(dmRoot, onePortContext, NextExpander); dmDownStreamDiscovering(dmRoot, onePortContext, NextExpander->dmDevice); } break; default: DM_DBG3(("dmDownStreamDiscovering: *** Unknown pPort->discovery.status=0x%x\n", onePortContext->discovery.status)); } } /* If no expander for continue discoving */ else { DM_DBG3(("dmDownStreamDiscovering: No more expander DONE\n")); /* discover done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_SUCCESS); } return; } osGLOBAL void dmUpStreamDiscoverExpanderPhy( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander, smpRespDiscover_t *pDiscoverResp ) { agsaSASIdentify_t sasIdentify; dmSASSubID_t dmSASSubID; bit32 attachedSasHi, attachedSasLo; dmExpander_t *AttachedExpander = agNULL; bit8 connectionRate; dmDeviceData_t *oneDeviceData = agNULL; dmDeviceData_t *AttachedDevice = agNULL; dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; DM_DBG3(("dmUpStreamDiscoverExpanderPhy: start\n")); if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmUpStreamDiscoverExpanderPhy: invalid port or aborted discovery!!!\n")); return; } if (oneExpander != oneExpander->dmDevice->dmExpander) { DM_DBG1(("dmUpStreamDiscoverExpanderPhy: wrong!!!\n")); } dm_memset(&sasIdentify, 0, sizeof(agsaSASIdentify_t)); oneDeviceData = oneExpander->dmDevice; DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n", oneExpander->discoveringPhyId, oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG3((" Attached device: %s\n", ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" : (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" : (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander"))))); if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE) { DM_DBG3((" SAS address : %08x-%08x\n", DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp), DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp))); DM_DBG3((" SSP Target : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0)); DM_DBG3((" STP Target : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0)); DM_DBG3((" SMP Target : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0)); DM_DBG3((" SATA DEVICE : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0)); DM_DBG3((" SSP Initiator : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG3((" STP Initiator : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG3((" SMP Initiator : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG3((" Phy ID : %d\n", pDiscoverResp->phyIdentifier)); DM_DBG3((" Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier)); } /* for debugging */ if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier) { DM_DBG1(("dmUpStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n")); DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d !!!\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier)); dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); return; } /* saving routing attribute for non self-configuring expanders */ oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = (bit8)DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp); if ( oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE ) { DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_FANOUT_EXPANDER\n")); if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE) { DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing on fanout expander device!!!\n")); /* discovery error */ onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* (2.1.3) discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); return; } } else { DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_DEV_TYPE_EDGE_EXPANDER\n")); if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE) { /* Setup sasIdentify for the attached device */ sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier; sasIdentify.deviceType_addressFrameType = (bit8)(pDiscoverResp->attachedDeviceType & 0x70); sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator; sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target; *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi; *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo; /* incremental discovery */ dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify); dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify); dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp; dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp; attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp); attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp); /* If the phy has subtractive routing attribute */ if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE) { DM_DBG3(("dmUpStreamDiscoverExpanderPhy: SA_SAS_ROUTING_SUBTRACTIVE\n")); /* Setup upstream phys */ dmExpanderUpStreamPhyAdd(dmRoot, oneExpander, (bit8) pDiscoverResp->attachedPhyIdentifier); /* If the expander already has an upsteam device set up */ if (oneExpander->hasUpStreamDevice == agTRUE) { /* just to update MCN */ dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData); /* If the sas address doesn't match */ if ( ((oneExpander->upStreamSASAddressHi != attachedSasHi) || (oneExpander->upStreamSASAddressLo != attachedSasLo)) && (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE || DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) ) { /* TODO: discovery error, callback */ DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n")); /* call back to notify discovery error */ onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } else { /* Setup SAS address for up stream device */ oneExpander->hasUpStreamDevice = agTRUE; oneExpander->upStreamSASAddressHi = attachedSasHi; oneExpander->upStreamSASAddressLo = attachedSasLo; if ( (onePortContext->sasLocalAddressHi != attachedSasHi) || (onePortContext->sasLocalAddressLo != attachedSasLo) ) { /* Find the device from the discovered list */ AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData); /* New device, If the device has been discovered before */ if ( AttachedDevice != agNULL) /* old device */ { DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Seen This Device Before\n")); /* If attached device is an edge expander */ if ( AttachedDevice->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE) { /* The attached device is an expander */ AttachedExpander = AttachedDevice->dmExpander; /* If the two expanders are the root of the two edge expander sets */ if ( (AttachedExpander->upStreamSASAddressHi == DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo)) && (AttachedExpander->upStreamSASAddressLo == DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)) ) { /* Setup upstream expander for the pExpander */ oneExpander->dmUpStreamExpander = AttachedExpander; } /* If the two expanders are not the root of the two edge expander sets */ else { /* TODO: loop found, discovery error, callback */ DM_DBG1(("dmUpStreamDiscoverExpanderPhy: **** Topology Error loop detection!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmUpStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } /* If attached device is not an edge expander */ else { /*TODO: should not happen, ASSERT */ DM_DBG3(("dmUpStreamDiscoverExpanderPhy, *** Attached Device is not Edge. Confused!!!\n")); } } /* AttachedExpander != agNULL */ /* New device, If the device has not been discovered before */ else /* new device */ { /* Add the device */ DM_DBG3(("dmUpStreamDiscoverExpanderPhy: New device\n")); /* read minimum rate from the configuration onePortContext->LinkRate is SPC's local link rate */ connectionRate = (bit8)MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)); DM_DBG3(("dmUpStreamDiscoverExpanderPhy: link rate 0x%x\n", onePortContext->LinkRate)); DM_DBG3(("dmUpStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp))); DM_DBG3(("dmUpStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate)); if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp)) { /* incremental discovery */ if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, STP_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } else { /* incremental discovery */ AttachedDevice = dmFindRegNValid( dmRoot, onePortContext, &dmSASSubID ); /* not registered and not valid; add this*/ if (AttachedDevice == agNULL) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, STP_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } } } /* DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp) */ else { /* incremental discovery */ if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, SAS_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } else { /* incremental discovery */ AttachedDevice = dmFindRegNValid( dmRoot, onePortContext, &dmSASSubID ); /* not registered and not valid; add this*/ if (AttachedDevice == agNULL) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, SAS_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } } } /* If the device is added successfully */ if ( AttachedDevice != agNULL) { /* (3.1.2.3.2.3.2.1) callback about new device */ if ( DISCRSP_IS_SSP_TARGET(pDiscoverResp) || DISCRSP_IS_SSP_INITIATOR(pDiscoverResp) || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) || DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) ) { DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found SSP/SMP SAS %08x-%08x\n", attachedSasHi, attachedSasLo)); } else { DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found a SAS STP device.\n")); } /* If the attached device is an expander */ if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) ) { /* Allocate an expander data structure */ AttachedExpander = dmDiscoveringExpanderAlloc( dmRoot, onePortContext, AttachedDevice ); DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found expander=%p\n", AttachedExpander)); /* If allocate successfully */ if ( AttachedExpander != agNULL) { /* Add the pAttachedExpander to discovering list */ dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander); /* Setup upstream expander for the pExpander */ oneExpander->dmUpStreamExpander = AttachedExpander; } /* If failed to allocate */ else { DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Failed to allocate expander data structure!!!\n")); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } /* If the attached device is an end device */ else { DM_DBG3(("dmUpStreamDiscoverExpanderPhy: Found end device\n")); /* LP2006-05-26 added upstream device to the newly found device */ AttachedDevice->dmExpander = oneExpander; oneExpander->dmUpStreamExpander = agNULL; } } else { DM_DBG1(("dmUpStreamDiscoverExpanderPhy: Failed to add a device!!!\n")); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } /* else, new device */ } /* onePortContext->sasLocalAddressLo != attachedSasLo */ } /* else */ } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE */ } /* DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE */ } /* big else */ oneExpander->discoveringPhyId ++; if (onePortContext->discovery.status == DISCOVERY_UP_STREAM) { if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys ) { DM_DBG3(("dmUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM find more ...\n")); /* continue discovery for the next phy */ dmDiscoverSend(dmRoot, oneDeviceData); } else { DM_DBG3(("dmUpStreamDiscoverExpanderPhy: DISCOVERY_UP_STREAM last phy continue upstream..\n")); /* for MCN */ dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData); /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander); /* continue upstream discovering */ dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } } else { DM_DBG3(("dmUpStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status)); } DM_DBG3(("dmUpStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1)); return; } osGLOBAL void dmUpStreamDiscover2ExpanderPhy( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander, smpRespDiscover2_t *pDiscoverResp ) { dmDeviceData_t *oneDeviceData; dmDeviceData_t *AttachedDevice = agNULL; dmExpander_t *AttachedExpander; agsaSASIdentify_t sasIdentify; bit8 connectionRate; bit32 attachedSasHi, attachedSasLo; dmSASSubID_t dmSASSubID; dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: start\n")); if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: invalid port or aborted discovery!!!\n")); return; } if (oneExpander != oneExpander->dmDevice->dmExpander) { DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: wrong!!!\n")); } dm_memset(&sasIdentify, 0, sizeof(agsaSASIdentify_t)); oneDeviceData = oneExpander->dmDevice; DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Phy #%d of SAS %08x-%08x\n", oneExpander->discoveringPhyId, oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG2((" Attached device: %s\n", ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" : (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" : (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander"))))); if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE) { DM_DBG2((" SAS address : %08x-%08x\n", SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp), SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp))); DM_DBG2((" SSP Target : %d\n", SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0)); DM_DBG2((" STP Target : %d\n", SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0)); DM_DBG2((" SMP Target : %d\n", SAS2_DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0)); DM_DBG2((" SATA DEVICE : %d\n", SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0)); DM_DBG2((" SSP Initiator : %d\n", SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG2((" STP Initiator : %d\n", SAS2_DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG2((" SMP Initiator : %d\n", SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG2((" Phy ID : %d\n", pDiscoverResp->phyIdentifier)); DM_DBG2((" Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier)); } if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier) { DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: !!! Incorrect SMP response !!!\n")); DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier)); dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover2_t)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); return; } /* saving routing attribute for non self-configuring expanders */ oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp); if ( oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE ) { DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_DEV_TYPE_FANOUT_EXPANDER\n")); if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE) { DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing on fanout expander device!!!\n")); /* discovery error */ onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* (2.1.3) discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); return; } } else { DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_DEV_TYPE_EDGE_EXPANDER\n")); if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE) { /* Setup sasIdentify for the attached device */ sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier; sasIdentify.deviceType_addressFrameType = pDiscoverResp->attachedDeviceTypeReason & 0x70; sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator; sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target; *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi; *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo; /* incremental discovery */ dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify); dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify); dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp; dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp; attachedSasHi = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp); attachedSasLo = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp); /* If the phy has subtractive routing attribute */ if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE) { DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: SA_SAS_ROUTING_SUBTRACTIVE\n")); /* Setup upstream phys */ dmExpanderUpStreamPhyAdd(dmRoot, oneExpander, (bit8) pDiscoverResp->attachedPhyIdentifier); /* If the expander already has an upsteam device set up */ if (oneExpander->hasUpStreamDevice == agTRUE) { /* just to update MCN */ dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData); /* If the sas address doesn't match */ if ( ((oneExpander->upStreamSASAddressHi != attachedSasHi) || (oneExpander->upStreamSASAddressLo != attachedSasLo)) && (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE || SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) ) { /* TODO: discovery error, callback */ DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n")); /* call back to notify discovery error */ onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } else { /* Setup SAS address for up stream device */ oneExpander->hasUpStreamDevice = agTRUE; oneExpander->upStreamSASAddressHi = attachedSasHi; oneExpander->upStreamSASAddressLo = attachedSasLo; if ( (onePortContext->sasLocalAddressHi != attachedSasHi) || (onePortContext->sasLocalAddressLo != attachedSasLo) ) { /* Find the device from the discovered list */ AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData); /* If the device has been discovered before */ if ( AttachedDevice != agNULL) { DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Seen This Device Before\n")); /* If attached device is an edge expander */ if ( AttachedDevice->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE) { /* The attached device is an expander */ AttachedExpander = AttachedDevice->dmExpander; /* If the two expanders are the root of the two edge expander sets */ if ( (AttachedExpander->upStreamSASAddressHi == DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo)) && (AttachedExpander->upStreamSASAddressLo == DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo)) ) { /* Setup upstream expander for the pExpander */ oneExpander->dmUpStreamExpander = AttachedExpander; } /* If the two expanders are not the root of the two edge expander sets */ else { /* TODO: loop found, discovery error, callback */ DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: **** Topology Error loop detection!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmUpStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } /* If attached device is not an edge expander */ else { /*TODO: should not happen, ASSERT */ DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, *** Attached Device is not Edge. Confused!!!\n")); } } /* If the device has not been discovered before */ else { /* Add the device */ DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: New device\n")); /* read minimum rate from the configuration onePortContext->LinkRate is SPC's local link rate */ connectionRate = MIN(onePortContext->LinkRate, SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pDiscoverResp)); DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: link rate 0x%x\n", onePortContext->LinkRate)); DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: negotiatedPhyLinkRate 0x%x\n", SAS2_DISCRSP_GET_LINKRATE(pDiscoverResp))); DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: connectionRate 0x%x\n", connectionRate)); //hhhhhhhh if (SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp)) { /* incremental discovery */ if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, STP_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } else { /* incremental discovery */ AttachedDevice = dmFindRegNValid( dmRoot, onePortContext, &dmSASSubID ); /* not registered and not valid; add this*/ if (AttachedDevice == agNULL) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, STP_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } } } else { /* incremental discovery */ if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, SAS_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } else { /* incremental discovery */ AttachedDevice = dmFindRegNValid( dmRoot, onePortContext, &dmSASSubID ); /* not registered and not valid; add this*/ if (AttachedDevice == agNULL) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, SAS_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } } } /* If the device is added successfully */ if ( AttachedDevice != agNULL) { /* (3.1.2.3.2.3.2.1) callback about new device */ if ( SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp) || SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) || SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp) ) { DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found SSP/SMP SAS %08x-%08x\n", attachedSasHi, attachedSasLo)); } else { DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found a SAS STP device.\n")); } /* If the attached device is an expander */ if ( (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) || (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) ) { /* Allocate an expander data structure */ AttachedExpander = dmDiscoveringExpanderAlloc( dmRoot, onePortContext, AttachedDevice ); DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found expander=%p\n", AttachedExpander)); /* If allocate successfully */ if ( AttachedExpander != agNULL) { /* Add the pAttachedExpander to discovering list */ dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander); /* Setup upstream expander for the pExpander */ oneExpander->dmUpStreamExpander = AttachedExpander; } /* If failed to allocate */ else { DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, Failed to allocate expander data structure!!!\n")); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } /* If the attached device is an end device */ else { DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: Found end device\n")); /* LP2006-05-26 added upstream device to the newly found device */ AttachedDevice->dmExpander = oneExpander; oneExpander->dmUpStreamExpander = agNULL; } } else { DM_DBG1(("dmUpStreamDiscover2ExpanderPhy, Failed to add a device!!!\n")); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } } } } /* substractive routing */ } } oneExpander->discoveringPhyId ++; if (onePortContext->discovery.status == DISCOVERY_UP_STREAM) { if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys ) { DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: DISCOVERY_UP_STREAM find more ...\n")); /* continue discovery for the next phy */ dmDiscoverSend(dmRoot, oneDeviceData); } else { DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: DISCOVERY_UP_STREAM last phy continue upstream..\n")); /* for MCN */ dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData); /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander); /* continue upstream discovering */ dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } } else { DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status)); } DM_DBG2(("dmUpStreamDiscover2ExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1)); return; } osGLOBAL void dmDownStreamDiscoverExpanderPhy( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander, smpRespDiscover_t *pDiscoverResp ) { agsaSASIdentify_t sasIdentify; dmSASSubID_t dmSASSubID; bit32 attachedSasHi, attachedSasLo; dmExpander_t *AttachedExpander; dmExpander_t *UpStreamExpander; dmExpander_t *ConfigurableExpander = agNULL; bit8 connectionRate, negotiatedPhyLinkRate; bit32 configSASAddressHi; bit32 configSASAddressLo; bit32 dupConfigSASAddr = agFALSE; dmDeviceData_t *oneDeviceData; dmDeviceData_t *AttachedDevice = agNULL; bit32 SAS2SAS11Check = agFALSE; dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; DM_DBG3(("dmDownStreamDiscoverExpanderPhy: start\n")); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); DM_ASSERT(dmRoot, "(dmDownStreamDiscoverExpanderPhy) dmRoot NULL"); DM_ASSERT(onePortContext, "(dmDownStreamDiscoverExpanderPhy) pPort NULL"); DM_ASSERT(oneExpander, "(dmDownStreamDiscoverExpanderPhy) pExpander NULL"); DM_ASSERT(pDiscoverResp, "(dmDownStreamDiscoverExpanderPhy) pDiscoverResp NULL"); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: onePortContxt=%p oneExpander=%p\n", onePortContext, oneExpander)); if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmDownStreamDiscoverExpanderPhy: invalid port or aborted discovery!!!\n")); return; } if (oneExpander != oneExpander->dmDevice->dmExpander) { DM_DBG1(("dmDownStreamDiscoverExpanderPhy: wrong!!!\n")); } /* (1) Find the device structure of the expander */ oneDeviceData = oneExpander->dmDevice; DM_ASSERT(oneDeviceData, "(dmDownStreamDiscoverExpanderPhy) pDevice NULL"); /* for debugging */ DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Phy #%d of SAS %08x-%08x\n", oneExpander->discoveringPhyId, oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG3((" Attached device: %s\n", ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" : (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" : (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander"))))); /* for debugging */ if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier) { DM_DBG1(("dmDownStreamDiscoverExpanderPhy: !!! Incorrect SMP response !!!\n")); DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Request PhyID #%d Response PhyID #%d !!!\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier)); dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover_t)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); return; } if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE) { DM_DBG3((" SAS address : %08x-%08x\n", DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp), DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp))); DM_DBG3((" SSP Target : %d\n", DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0)); DM_DBG3((" STP Target : %d\n", DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0)); DM_DBG3((" SMP Target : %d\n", DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0)); DM_DBG3((" SATA DEVICE : %d\n", DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0)); DM_DBG3((" SSP Initiator : %d\n", DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG3((" STP Initiator : %d\n", DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG3((" SMP Initiator : %d\n", DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG3((" Phy ID : %d\n", pDiscoverResp->phyIdentifier)); DM_DBG3((" Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier)); } /* end for debugging */ /* saving routing attribute for non self-configuring expanders */ oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp); oneExpander->discoverSMPAllowed = agTRUE; /* If a device is attached */ if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE) { /* Setup sasIdentify for the attached device */ sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier; sasIdentify.deviceType_addressFrameType = pDiscoverResp->attachedDeviceType & 0x70; sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator; sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target; *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi; *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo; /* incremental discovery */ dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify); dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify); dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp; dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp; attachedSasHi = DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp); attachedSasLo = DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp); /* If it's a direct routing */ if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_DIRECT) { /* If the attached device is an expander */ if ( (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) || (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) ) { DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error direct routing can't connect to expander!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); return; } } /* If the expander's attached device is not myself */ if ( (attachedSasHi != onePortContext->sasLocalAddressHi) || (attachedSasLo != onePortContext->sasLocalAddressLo) ) { /* Find the attached device from discovered list */ AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData); /* If the device has not been discovered before */ if ( AttachedDevice == agNULL) //11 { /* If the phy has subtractive routing attribute */ if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE && (DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE || DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) ) { /* TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Deferred!!! **** Topology Error subtractive routing error - inconsistent SAS address!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); onePortContext->discovery.DeferredError = agTRUE; } else /* 11 */ { /* Add the device */ /* read minimum rate from the configuration onePortContext->LinkRate is SPC's local link rate */ connectionRate = MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: link rate 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo))); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: negotiatedPhyLinkRate 0x%x\n", DISCRSP_GET_LINKRATE(pDiscoverResp))); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: connectionRate 0x%x\n", connectionRate)); if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp)) { if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, STP_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } else { /* incremental discovery */ AttachedDevice = dmFindRegNValid( dmRoot, onePortContext, &dmSASSubID ); /* not registered and not valid; add this*/ if (AttachedDevice == agNULL) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, STP_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } } } /* DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp) */ else /* 22 */ { if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, SAS_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } else { /* incremental discovery */ AttachedDevice = dmFindRegNValid( dmRoot, onePortContext, &dmSASSubID ); /* not registered and not valid; add this*/ if (AttachedDevice == agNULL) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, SAS_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } } } /* else 22 */ DM_DBG3(("dmDownStreamDiscoverExpanderPhy: newDevice pDevice=%p\n", AttachedDevice)); /* If the device is added successfully */ if ( AttachedDevice != agNULL) { if ( SA_IDFRM_IS_SSP_TARGET(&sasIdentify) || SA_IDFRM_IS_SMP_TARGET(&sasIdentify) || SA_IDFRM_IS_SSP_INITIATOR(&sasIdentify) || SA_IDFRM_IS_SMP_INITIATOR(&sasIdentify) ) { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Report a new SAS device !!\n")); } else { if ( SA_IDFRM_IS_STP_TARGET(&sasIdentify) || SA_IDFRM_IS_SATA_DEVICE(&sasIdentify) ) { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found an STP or SATA device.\n")); } else { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found Other type of device.\n")); } } /* LP2006-05-26 added upstream device to the newly found device */ AttachedDevice->dmExpander = oneExpander; DM_DBG3(("dmDownStreamDiscoverExpanderPhy: AttachedDevice %p did %d\n", AttachedDevice, AttachedDevice->id)); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Attached oneExpander %p did %d\n", AttachedDevice->dmExpander, AttachedDevice->dmExpander->id)); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: oneExpander %p did %d\n", oneDeviceData->dmExpander, oneDeviceData->dmExpander->id)); /* If the phy has table routing attribute */ if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE) { /* If the attached device is a fan out expander */ if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) { /* TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys are connected!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) { /* Allocate an expander data structure */ AttachedExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, AttachedDevice); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found a EDGE exp device.%p\n", AttachedExpander)); /* If allocate successfully */ if ( AttachedExpander != agNULL) { /* set up downstream information on configurable expander */ dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId); /* Setup upstream information */ dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId); AttachedExpander->hasUpStreamDevice = agTRUE; AttachedExpander->upStreamSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); AttachedExpander->upStreamSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); AttachedExpander->dmUpStreamExpander = oneExpander; /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */ dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander); } /* If failed to allocate */ else { DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Failed to allocate expander data structure!!!\n")); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE */ /* If status is still DISCOVERY_DOWN_STREAM */ if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st before\n")); dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); UpStreamExpander = oneExpander->dmUpStreamExpander; ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander); configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo); configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); if (ConfigurableExpander) { if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) && (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo)) ) { /* directly attached between oneExpander and ConfigurableExpander */ DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st before loc 1\n")); configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi; configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo; } else { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st before loc 2\n")); configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo); configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); } } /* if !ConfigurableExpander */ dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, ConfigurableExpander, configSASAddressHi, configSASAddressLo ); if ( ConfigurableExpander && dupConfigSASAddr == agFALSE) { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 1st q123\n")); UpStreamExpander->dmCurrentDownStreamExpander = oneExpander; ConfigurableExpander->currentDownStreamPhyIndex = dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander); ConfigurableExpander->dmReturnginExpander = oneExpander; dmRoutingEntryAdd(dmRoot, ConfigurableExpander, ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex], configSASAddressHi, configSASAddressLo ); } } /* onePortContext->discovery.status == DISCOVERY_DOWN_STREAM */ } /* AttachedDevice != agNULL */ /* If fail to add the device */ else { DM_DBG1(("dmDownStreamDiscoverExpanderPhy: Failed to add a device!!!\n")); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } /* else 11 */ } /* AttachedDevice == agNULL */ /* If the device has been discovered before */ else /* haha discovered before 33 */ { /* If the phy has subtractive routing attribute */ if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE) { /* If the expander doesn't have up stream device */ if ( oneExpander->hasUpStreamDevice == agFALSE) { /* TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error loop, or end device connects to two expanders!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } /* If the expander has up stream device */ else /* 44 */ { /* If sas address doesn't match */ if ( (oneExpander->upStreamSASAddressHi != attachedSasHi) || (oneExpander->upStreamSASAddressLo != attachedSasLo) ) { /* TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two subtractive phys!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } /* else 44 */ } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE */ /* If the phy has table routing attribute */ else if ( DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE) { /* If the attached device is a fan out expander */ if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) { /* (2.3.3.2.1.1) TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error fan out expander to routing table phy!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } /* If the attached device is an edge expander */ else if ( DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) { /* Setup up stream inform */ AttachedExpander = AttachedDevice->dmExpander; DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found edge expander=%p\n", AttachedExpander)); /* If the attached expander has up stream device */ if ( AttachedExpander->hasUpStreamDevice == agTRUE) { /* compare the sas address */ if ( (AttachedExpander->upStreamSASAddressHi != DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo)) || (AttachedExpander->upStreamSASAddressLo != DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo))) { /* TODO: discovery error, callback */ SAS2SAS11Check = dmSAS2SAS11ErrorCheck(dmRoot, onePortContext, AttachedExpander, oneExpander, oneExpander); if (SAS2SAS11Check == agTRUE) { DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error SAS2 and SAS1.1!!!\n")); } else { DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys connected (1)!!!\n")); } onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Add edge expander=%p\n", AttachedExpander)); /* set up downstream information on configurable expander */ dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId); /* haha */ dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId); /* Add the pAttachedExpander to discovering list */ dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander); } } /* AttachedExpander->hasUpStreamDevice == agTRUE */ /* If the attached expander doesn't have up stream device */ else { /* TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscoverExpanderPhy: **** Topology Error two table routing phys connected (2)!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscoverExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } /* DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE */ } /* DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE */ /* do this regradless of sub or table */ /* If status is still DISCOVERY_DOWN_STREAM */ if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd before\n")); dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); UpStreamExpander = oneExpander->dmUpStreamExpander; ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander); configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo); configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); if (ConfigurableExpander) { if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) && (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo)) ) { /* directly attached between oneExpander and ConfigurableExpander */ DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd before loc 1\n")); configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi; configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo; } else { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd before loc 2\n")); configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo); configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); } } /* if !ConfigurableExpander */ dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, ConfigurableExpander, configSASAddressHi, configSASAddressLo ); if ( ConfigurableExpander && dupConfigSASAddr == agFALSE) { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 2nd q123 \n")); UpStreamExpander->dmCurrentDownStreamExpander = oneExpander; ConfigurableExpander->currentDownStreamPhyIndex = dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander); ConfigurableExpander->dmReturnginExpander = oneExpander; dmRoutingEntryAdd(dmRoot, ConfigurableExpander, ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex], configSASAddressHi, configSASAddressLo ); } } /* onePortContext->discovery.status == DISCOVERY_DOWN_STREAM */ /* incremental discovery */ if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START) { connectionRate = MIN(onePortContext->LinkRate, DISCRSP_GET_LINKRATE(pDiscoverResp)); if (DISCRSP_IS_STP_TARGET(pDiscoverResp) || DISCRSP_IS_SATA_DEVICE(pDiscoverResp)) { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: incremental SATA_STP\n")); dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, STP_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } else { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: incremental SAS\n")); dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, SAS_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } } /* onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START */ } /* else 33 */ } /* (attachedSasLo != onePortContext->sasLocalAddressLo) */ else /* else 44 */ { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: Found Self\n")); DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 3rd before\n")); dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); UpStreamExpander = oneExpander->dmUpStreamExpander; ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander); dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, ConfigurableExpander, onePortContext->sasLocalAddressHi, onePortContext->sasLocalAddressLo ); if ( ConfigurableExpander && dupConfigSASAddr == agFALSE) { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: 3rd q123 Setup routing table\n")); UpStreamExpander->dmCurrentDownStreamExpander = oneExpander; ConfigurableExpander->currentDownStreamPhyIndex = dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander); ConfigurableExpander->dmReturnginExpander = oneExpander; dmRoutingEntryAdd(dmRoot, ConfigurableExpander, ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex], onePortContext->sasLocalAddressHi, onePortContext->sasLocalAddressLo ); } } /* else 44 */ } /* DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE */ /* If no device is attached */ else { DM_DBG2(("!!!!!!!!!!!!!!!!!!!!! SPIN SATA !!!!!!!!!!!!!!!!!!!!!!!!!!!\n")); negotiatedPhyLinkRate = DISCRSP_GET_LINKRATE(pDiscoverResp); // added by thenil if (negotiatedPhyLinkRate == 0x03) { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: SPIN SATA sent reset\n")); dmPhyControlSend(dmRoot, oneDeviceData, SMP_PHY_CONTROL_HARD_RESET, pDiscoverResp->phyIdentifier ); } /* do nothing */ } /* Increment the discovering phy id */ oneExpander->discoveringPhyId ++; /* If the discovery status is DISCOVERY_DOWN_STREAM */ if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM ) { /* If not the last phy */ if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys ) { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: More Phys to discover\n")); /* continue discovery for the next phy */ dmDiscoverSend(dmRoot, oneDeviceData); } /* If the last phy */ else { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: No More Phys\n")); /* for MCN */ dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData); /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander); /* continue downstream discovering */ dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } } else { DM_DBG3(("dmDownStreamDiscoverExpanderPhy: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status)); } DM_DBG3(("dmDownStreamDiscoverExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1)); return; } /* works at SAS2 expander (called in dmDownStreamDiscover2ExpanderPhy()) if currentExpander is SAS2, called in dmDownStreamDiscover2ExpanderPhy() if currentExpander is SAS1.1, called in dmDownStreamDiscoverExpanderPhy() */ osGLOBAL bit32 dmSAS2SAS11ErrorCheck( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *topExpander, dmExpander_t *bottomExpander, dmExpander_t *currentExpander ) { bit32 result = agFALSE, i = 0; bit8 downStreamPhyID, upStreamPhyID; DM_DBG2(("dmSAS2SAS11ErrorCheck: start\n")); if (topExpander == agNULL) { DM_DBG2(("dmSAS2SAS11ErrorCheck: topExpander is NULL\n")); return result; } if (bottomExpander == agNULL) { DM_DBG2(("dmSAS2SAS11ErrorCheck: bottomExpander is NULL\n")); return result; } if (currentExpander == agNULL) { DM_DBG2(("dmSAS2SAS11ErrorCheck: currentExpander is NULL\n")); return result; } DM_DBG2(("dmSAS2SAS11ErrorCheck: topExpander addrHi 0x%08x addrLo 0x%08x\n", topExpander->dmDevice->SASAddressID.sasAddressHi, topExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG2(("dmSAS2SAS11ErrorCheck: bottomExpander addrHi 0x%08x addrLo 0x%08x\n", bottomExpander->dmDevice->SASAddressID.sasAddressHi, bottomExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG2(("dmSAS2SAS11ErrorCheck: currentExpander addrHi 0x%08x addrLo 0x%08x\n", currentExpander->dmDevice->SASAddressID.sasAddressHi, currentExpander->dmDevice->SASAddressID.sasAddressLo)); for (i=0;idownStreamPhys[i]; upStreamPhyID = bottomExpander->upStreamPhys[i]; if (currentExpander->SAS2 == 1) { if ( downStreamPhyID == upStreamPhyID && topExpander->routingAttribute[downStreamPhyID] == SAS_ROUTING_TABLE && bottomExpander->routingAttribute[i] == SAS_ROUTING_SUBTRACTIVE && topExpander->SAS2 == 0 && bottomExpander->SAS2 == 1 ) { result = agTRUE; break; } } else if (currentExpander->SAS2 == 0) { if ( downStreamPhyID == upStreamPhyID && topExpander->routingAttribute[downStreamPhyID] == SAS_ROUTING_SUBTRACTIVE && bottomExpander->routingAttribute[i] == SAS_ROUTING_TABLE && topExpander->SAS2 == 1 && bottomExpander->SAS2 == 0 ) { result = agTRUE; break; } } } return result; } osGLOBAL void dmDownStreamDiscover2ExpanderPhy( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander, smpRespDiscover2_t *pDiscoverResp ) { dmDeviceData_t *oneDeviceData; dmExpander_t *UpStreamExpander; dmDeviceData_t *AttachedDevice = agNULL; dmExpander_t *AttachedExpander; agsaSASIdentify_t sasIdentify; bit8 connectionRate; bit32 attachedSasHi, attachedSasLo; dmSASSubID_t dmSASSubID; dmExpander_t *ConfigurableExpander = agNULL; bit32 dupConfigSASAddr = agFALSE; bit32 configSASAddressHi; bit32 configSASAddressLo; bit32 SAS2SAS11Check = agFALSE; dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: start\n")); DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); DM_ASSERT(dmRoot, "(dmDownStreamDiscover2ExpanderPhy) dmRoot NULL"); DM_ASSERT(onePortContext, "(dmDownStreamDiscover2ExpanderPhy) pPort NULL"); DM_ASSERT(oneExpander, "(dmDownStreamDiscover2ExpanderPhy) pExpander NULL"); DM_ASSERT(pDiscoverResp, "(dmDownStreamDiscover2ExpanderPhy) pDiscoverResp NULL"); DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: onePortContxt=%p oneExpander=%p oneDeviceData=%p\n", onePortContext, oneExpander, oneExpander->dmDevice)); if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: invalid port or aborted discovery!!!\n")); return; } if (oneExpander != oneExpander->dmDevice->dmExpander) { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: wrong!!!\n")); } /* (1) Find the device structure of the expander */ oneDeviceData = oneExpander->dmDevice; DM_ASSERT(oneDeviceData, "(dmDownStreamDiscover2ExpanderPhy) pDevice NULL"); /* for debugging */ DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Phy #%d of SAS %08x-%08x\n", oneExpander->discoveringPhyId, oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG2((" Attached device: %s\n", ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 0 ? "No Device" : (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 1 ? "End Device" : (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == 2 ? "Edge Expander" : "Fanout Expander"))))); /* for debugging */ if (oneExpander->discoveringPhyId != pDiscoverResp->phyIdentifier) { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: !!! Incorrect SMP response !!!\n")); DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: Request PhyID #%d Response PhyID #%d\n", oneExpander->discoveringPhyId, pDiscoverResp->phyIdentifier)); dmhexdump("NO_DEVICE", (bit8*)pDiscoverResp, sizeof(smpRespDiscover2_t)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); return; } if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE) { DM_DBG2((" SAS address : %08x-%08x\n", SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp), SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp))); DM_DBG2((" SSP Target : %d\n", SAS2_DISCRSP_IS_SSP_TARGET(pDiscoverResp)?1:0)); DM_DBG2((" STP Target : %d\n", SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp)?1:0)); DM_DBG2((" SMP Target : %d\n", SAS2_DISCRSP_IS_SMP_TARGET(pDiscoverResp)?1:0)); DM_DBG2((" SATA DEVICE : %d\n", SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp)?1:0)); DM_DBG2((" SSP Initiator : %d\n", SAS2_DISCRSP_IS_SSP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG2((" STP Initiator : %d\n", SAS2_DISCRSP_IS_STP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG2((" SMP Initiator : %d\n", SAS2_DISCRSP_IS_SMP_INITIATOR(pDiscoverResp)?1:0)); DM_DBG2((" Phy ID : %d\n", pDiscoverResp->phyIdentifier)); DM_DBG2((" Attached Phy ID: %d\n", pDiscoverResp->attachedPhyIdentifier)); } /* saving routing attribute for non self-configuring expanders */ oneExpander->routingAttribute[pDiscoverResp->phyIdentifier] = SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp); oneExpander->discoverSMPAllowed = agTRUE; /* If a device is attached */ if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) != SAS_NO_DEVICE) { /* Setup sasIdentify for the attached device */ sasIdentify.phyIdentifier = pDiscoverResp->phyIdentifier; sasIdentify.deviceType_addressFrameType = pDiscoverResp->attachedDeviceTypeReason & 0x70; sasIdentify.initiator_ssp_stp_smp = pDiscoverResp->attached_Ssp_Stp_Smp_Sata_Initiator; sasIdentify.target_ssp_stp_smp = pDiscoverResp->attached_SataPS_Ssp_Stp_Smp_Sata_Target; *(bit32*)sasIdentify.sasAddressHi = *(bit32*)pDiscoverResp->attachedSasAddressHi; *(bit32*)sasIdentify.sasAddressLo = *(bit32*)pDiscoverResp->attachedSasAddressLo; /* incremental discovery */ dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify); dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify); dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp; dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp; attachedSasHi = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSHI(pDiscoverResp); attachedSasLo = SAS2_DISCRSP_GET_ATTACHED_SAS_ADDRESSLO(pDiscoverResp); /* If it's a direct routing */ if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_DIRECT) { /* If the attached device is an expander */ if ( (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) || (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) ) { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error direct routing can't connect to expander!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); return; } } /* If the expander's attached device is not myself */ if ( (attachedSasHi != onePortContext->sasLocalAddressHi) || (attachedSasLo != onePortContext->sasLocalAddressLo) ) { /* Find the attached device from discovered list */ AttachedDevice = dmPortSASDeviceFind(dmRoot, onePortContext, attachedSasLo, attachedSasHi, oneDeviceData); /* If the device has not been discovered before */ if ( AttachedDevice == agNULL) //11 { //qqqqqq if (0) { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error subtractive routing error - inconsistent SAS address!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else { /* Add the device */ /* read minimum rate from the configuration onePortContext->LinkRate is SPC's local link rate */ connectionRate = MIN(onePortContext->LinkRate, SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pDiscoverResp)); DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: link rate 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo))); DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: negotiatedPhyLinkRate 0x%x\n", SAS2_DISCRSP_GET_LINKRATE(pDiscoverResp))); DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: connectionRate 0x%x\n", connectionRate)); if (SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp)) { if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, STP_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } else { /* incremental discovery */ AttachedDevice = dmFindRegNValid( dmRoot, onePortContext, &dmSASSubID ); /* not registered and not valid; add this*/ if (AttachedDevice == agNULL) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, STP_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } } } else { if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, SAS_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } else { /* incremental discovery */ AttachedDevice = dmFindRegNValid( dmRoot, onePortContext, &dmSASSubID ); /* not registered and not valid; add this*/ if (AttachedDevice == agNULL) { AttachedDevice = dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, SAS_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } } } DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: newDevice pDevice=%p\n", AttachedDevice)); /* If the device is added successfully */ if ( AttachedDevice != agNULL) { if ( SA_IDFRM_IS_SSP_TARGET(&sasIdentify) || SA_IDFRM_IS_SMP_TARGET(&sasIdentify) || SA_IDFRM_IS_SSP_INITIATOR(&sasIdentify) || SA_IDFRM_IS_SMP_INITIATOR(&sasIdentify) ) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Report a new SAS device !!\n")); } else { if ( SA_IDFRM_IS_STP_TARGET(&sasIdentify) || SA_IDFRM_IS_SATA_DEVICE(&sasIdentify) ) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found an STP or SATA device.\n")); } else { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found Other type of device.\n")); } } /* LP2006-05-26 added upstream device to the newly found device */ AttachedDevice->dmExpander = oneExpander; DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: AttachedDevice %p did %d\n", AttachedDevice, AttachedDevice->id)); DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: Attached oneExpander %p did %d\n", AttachedDevice->dmExpander, AttachedDevice->dmExpander->id)); DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmDownStreamDiscover2ExpanderPhy: oneExpander %p did %d\n", oneDeviceData->dmExpander, oneDeviceData->dmExpander->id)); /* If the phy has table routing attribute */ if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE) { /* If the attached device is a fan out expander */ if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) { /* TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error two table routing phys are connected!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) { /* Allocate an expander data structure */ AttachedExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, AttachedDevice); DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found a EDGE exp device.%p\n", AttachedExpander)); /* If allocate successfully */ if ( AttachedExpander != agNULL) { /* set up downstream information on configurable expander */ dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId); /* Setup upstream information */ dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId); //qqqqq AttachedExpander->hasUpStreamDevice = agTRUE; AttachedExpander->upStreamSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); AttachedExpander->upStreamSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); AttachedExpander->dmUpStreamExpander = oneExpander; /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */ dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander); } /* If failed to allocate */ else { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy, Failed to allocate expander data structure!!!\n")); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } } //qqqqq else if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE && (SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE || SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) ) { /* Allocate an expander data structure */ AttachedExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, AttachedDevice); DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found a EDGE/FANOUT exp device.%p\n", AttachedExpander)); /* If allocate successfully */ if ( AttachedExpander != agNULL) { /* set up downstream information on configurable expander */ dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId); /* Setup upstream information */ dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId); AttachedExpander->hasUpStreamDevice = agTRUE; AttachedExpander->upStreamSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); AttachedExpander->upStreamSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); AttachedExpander->dmUpStreamExpander = oneExpander; /* (2.3.2.2.2.2.2.2.2) Add the pAttachedExpander to discovering list */ dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander); } /* If failed to allocate */ else { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy, Failed to allocate expander data structure (2)!!!\n")); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } /* If status is still DISCOVERY_DOWN_STREAM */ if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM && onePortContext->discovery.ConfiguresOthers == agFALSE) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st before\n")); dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); UpStreamExpander = oneExpander->dmUpStreamExpander; ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander); configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo); configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); if (ConfigurableExpander) { if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) && (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo)) ) { /* directly attached between oneExpander and ConfigurableExpander */ DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st before loc 1\n")); configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi; configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo; } else { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st before loc 2\n")); configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo); configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); } } /* if !ConfigurableExpander */ dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, ConfigurableExpander, configSASAddressHi, configSASAddressLo ); if ( ConfigurableExpander && dupConfigSASAddr == agFALSE) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 1st q123\n")); UpStreamExpander->dmCurrentDownStreamExpander = oneExpander; ConfigurableExpander->currentDownStreamPhyIndex = dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander); ConfigurableExpander->dmReturnginExpander = oneExpander; dmRoutingEntryAdd(dmRoot, ConfigurableExpander, ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex], configSASAddressHi, configSASAddressLo ); } } } /* If fail to add the device */ else { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy, Failed to add a device!!!\n")); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } } /* If the device has been discovered before */ else /* discovered before */ { /* If the phy has subtractive routing attribute */ if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_SUBTRACTIVE) { /* If the expander doesn't have up stream device */ if ( oneExpander->hasUpStreamDevice == agFALSE) { /* TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error loop, or end device connects to two expanders!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } /* If the expander has up stream device */ else { //qqqqq /* If sas address doesn't match */ if ( (oneExpander->upStreamSASAddressHi != attachedSasHi) || (oneExpander->upStreamSASAddressLo != attachedSasLo) ) { /* TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** two subtractive phys!!! Allowed in SAS2!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; onePortContext->discovery.DeferredError = agTRUE; } } } /* If the phy has table routing attribute */ else if ( SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE) { /* If the attached device is a fan out expander */ if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_FANOUT_EXPANDER_DEVICE) { /* (2.3.3.2.1.1) TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error fan out expander to routing table phy!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } /* If the attached device is an edge expander */ else if ( SAS2_DISCRSP_GET_ATTACHED_DEVTYPE(pDiscoverResp) == SAS_EDGE_EXPANDER_DEVICE) { /* Setup up stream inform */ AttachedExpander = AttachedDevice->dmExpander; DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found edge expander=%p\n", AttachedExpander)); //hhhhhh /* If the attached expander has up stream device */ if ( AttachedExpander->hasUpStreamDevice == agTRUE) { /* compare the sas address */ if ( (AttachedExpander->upStreamSASAddressHi != DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo)) || (AttachedExpander->upStreamSASAddressLo != DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo))) { if (AttachedExpander->TTTSupported && oneExpander->TTTSupported) { /* needs further error checking UpstreamExpanderOfAttachedExpander = AttachedExpander->UpStreamExpander for (i=0;idownStreamPhys[i] != 0 && } */ SAS2SAS11Check = dmSAS2SAS11ErrorCheck(dmRoot, onePortContext, AttachedExpander->dmUpStreamExpander, AttachedExpander, oneExpander); if (SAS2SAS11Check == agTRUE) { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error SAS2 and SAS1.1!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: Allowed Table to Table (1)\n")); /* move on to the next phys but should be not proceed after oneExpander */ oneExpander->UndoDueToTTTSupported = agTRUE; onePortContext->discovery.DeferredError = agFALSE; } } else { /* TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error two table routing phys connected (1)!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } else { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Add edge expander=%p\n", AttachedExpander)); /* set up downstream information on configurable expander */ dmExpanderDownStreamPhyAdd(dmRoot, oneExpander, (bit8) oneExpander->discoveringPhyId); /* haha */ dmExpanderUpStreamPhyAdd(dmRoot, AttachedExpander, (bit8) oneExpander->discoveringPhyId); /* Add the pAttachedExpander to discovering list */ dmDiscoveringExpanderAdd(dmRoot, onePortContext, AttachedExpander); } } /* If the attached expander doesn't have up stream device */ else { if (AttachedExpander->TTTSupported && oneExpander->TTTSupported) { DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: Allowed Table to Table (2)\n")); /* move on to the next phys but should be not proceed after oneExpander */ oneExpander->UndoDueToTTTSupported = agTRUE; onePortContext->discovery.DeferredError = agFALSE; } else { /* TODO: discovery error, callback */ DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: **** Topology Error two table routing phys connected (2)!!!\n")); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&oneDeviceData->agDeviceInfo); onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier = oneExpander->discoveringPhyId; DM_DBG1(("dmDownStreamDiscover2ExpanderPhy: sasAddressHi 0x%08x sasAddressLo 0x%08x phyid 0x%x\n", onePortContext->discovery.sasAddressIDDiscoverError.sasAddressHi, onePortContext->discovery.sasAddressIDDiscoverError.sasAddressLo, onePortContext->discovery.sasAddressIDDiscoverError.phyIdentifier)); /* discovery done */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } } } } /* for else if (SAS2_DISCRSP_GET_ROUTINGATTRIB(pDiscoverResp) == SAS_ROUTING_TABLE) */ /* do this regradless of sub or table */ /* If status is still DISCOVERY_DOWN_STREAM */ if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM && onePortContext->discovery.ConfiguresOthers == agFALSE) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd before\n")); dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); UpStreamExpander = oneExpander->dmUpStreamExpander; ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander); configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo); configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); if (ConfigurableExpander) { if ( (ConfigurableExpander->dmDevice->SASAddressID.sasAddressHi == DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo)) && (ConfigurableExpander->dmDevice->SASAddressID.sasAddressLo == DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo)) ) { /* directly attached between oneExpander and ConfigurableExpander */ DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd before loc 1\n")); configSASAddressHi = oneExpander->dmDevice->SASAddressID.sasAddressHi; configSASAddressLo = oneExpander->dmDevice->SASAddressID.sasAddressLo; } else { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd before loc 2\n")); configSASAddressHi = DEVINFO_GET_SAS_ADDRESSHI(&AttachedDevice->agDeviceInfo); configSASAddressLo = DEVINFO_GET_SAS_ADDRESSLO(&AttachedDevice->agDeviceInfo); } } /* if !ConfigurableExpander */ dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, ConfigurableExpander, configSASAddressHi, configSASAddressLo ); if ( ConfigurableExpander && dupConfigSASAddr == agFALSE) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 2nd q123 \n")); UpStreamExpander->dmCurrentDownStreamExpander = oneExpander; ConfigurableExpander->currentDownStreamPhyIndex = dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander); ConfigurableExpander->dmReturnginExpander = oneExpander; dmRoutingEntryAdd(dmRoot, ConfigurableExpander, ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex], configSASAddressHi, configSASAddressLo ); } } /* if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) */ /* incremental discovery */ if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START) { connectionRate = MIN(onePortContext->LinkRate, SAS2_DISCRSP_GET_LOGICAL_LINKRATE(pDiscoverResp)); if (SAS2_DISCRSP_IS_STP_TARGET(pDiscoverResp) || SAS2_DISCRSP_IS_SATA_DEVICE(pDiscoverResp)) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: incremental SATA_STP\n")); dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, STP_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } else { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: incremental SAS\n")); dmPortSASDeviceAdd( dmRoot, onePortContext, sasIdentify, agFALSE, connectionRate, dmAllShared->itNexusTimeout, 0, SAS_DEVICE_TYPE, oneDeviceData, oneExpander, pDiscoverResp->phyIdentifier ); } } }/* else; existing devce */ } /* not attached to myself */ /* If the attached device is myself */ else { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Found Self\n")); DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 3rd before\n")); dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); if (onePortContext->discovery.ConfiguresOthers == agFALSE) { UpStreamExpander = oneExpander->dmUpStreamExpander; ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander); dupConfigSASAddr = dmDuplicateConfigSASAddr(dmRoot, ConfigurableExpander, onePortContext->sasLocalAddressHi, onePortContext->sasLocalAddressLo ); if ( ConfigurableExpander && dupConfigSASAddr == agFALSE) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: 3rd q123 Setup routing table\n")); UpStreamExpander->dmCurrentDownStreamExpander = oneExpander; ConfigurableExpander->currentDownStreamPhyIndex = dmFindCurrentDownStreamPhyIndex(dmRoot, ConfigurableExpander); ConfigurableExpander->dmReturnginExpander = oneExpander; dmRoutingEntryAdd(dmRoot, ConfigurableExpander, ConfigurableExpander->downStreamPhys[ConfigurableExpander->currentDownStreamPhyIndex], onePortContext->sasLocalAddressHi, onePortContext->sasLocalAddressLo ); } } } } /* If no device is attached */ else { } /* Increment the discovering phy id */ oneExpander->discoveringPhyId ++; /* If the discovery status is DISCOVERY_DOWN_STREAM */ if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM ) { /* If not the last phy */ if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys ) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: More Phys to discover\n")); /* continue discovery for the next phy */ dmDiscoverSend(dmRoot, oneDeviceData); } /* If the last phy */ else { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: No More Phys\n")); /* for MCN */ dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData); ConfigurableExpander = dmFindConfigurableExp(dmRoot, onePortContext, oneExpander); if (oneExpander->UndoDueToTTTSupported == agTRUE && ConfigurableExpander != agNULL) // if (oneExpander->UndoDueToTTTSupported == agTRUE) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: Not sure!!!\n")); dmDiscoveringUndoAdd(dmRoot, onePortContext, oneExpander); oneExpander->UndoDueToTTTSupported = agFALSE; } /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander); /* continue downstream discovering */ dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } } else { DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status)); } DM_DBG2(("dmDownStreamDiscover2ExpanderPhy: end return phyID#%d\n", oneExpander->discoveringPhyId - 1)); return; } osGLOBAL void dmDiscoveringUndoAdd( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmList_t *ExpanderList; dmExpander_t *tempExpander; dmIntPortContext_t *tmpOnePortContext = onePortContext; DM_DBG2(("dmDiscoveringUndoAdd: start\n")); if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList))) { DM_DBG2(("dmDiscoveringUndoAdd: empty discoveringExpanderList\n")); return; } // DM_DBG2(("dmDiscoveringUndoAdd: before\n")); // dmDumpAllExp(dmRoot, onePortContext, oneExpander); ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink; while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList)) { tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); if ( tempExpander == agNULL) { DM_DBG1(("dmDiscoveringUndoAdd: tempExpander is NULL!!!\n")); return; } if (tempExpander->dmUpStreamExpander == oneExpander) { DM_DBG2(("dmDiscoveringUndoAdd: match!!! expander id %d\n", tempExpander->id)); DM_DBG2(("dmDiscoveringUndoAdd: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG2(("dmDiscoveringUndoAdd: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo)); tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); DMLIST_DEQUEUE_THIS(&(tempExpander->linkNode)); // DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->freeExpanderList)); DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->mainExpanderList)); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink; } if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList))) { DM_DBG2(("dmDiscoveringUndoAdd: hitting break\n")); break; } ExpanderList = ExpanderList->flink; } // DM_DBG2(("dmDiscoveringUndoAdd: after\n")); // dmDumpAllExp(dmRoot, onePortContext, oneExpander); return; } osGLOBAL void dmHandleZoneViolation( dmRoot_t *dmRoot, agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, dmDeviceData_t *oneDeviceData, dmSMPFrameHeader_t *frameHeader, agsaFrameHandle_t frameHandle ) { dmIntPortContext_t *onePortContext = agNULL; dmExpander_t *oneExpander = agNULL; DM_DBG1(("dmHandleZoneViolation: start\n")); DM_DBG1(("dmHandleZoneViolation: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG1(("dmHandleZoneViolation: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); onePortContext = oneDeviceData->dmPortContext; oneExpander = oneDeviceData->dmExpander; if (dmDiscoverCheck(dmRoot, onePortContext) == agTRUE) { DM_DBG1(("dmHandleZoneViolation: invalid port or aborted discovery!!!\n")); return; } /* for MCN */ dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData); /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander); if ( onePortContext->discovery.status == DISCOVERY_UP_STREAM) { /* continue upstream discovering */ dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } else /* DISCOVERY_DOWN_STREAM or DISCOVERY_CONFIG_ROUTING */ { /* continue downstream discovering */ dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } return; } osGLOBAL void dmUpStreamDiscoverExpanderPhySkip( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { dmDeviceData_t *oneDeviceData; DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: start\n")); oneDeviceData = oneExpander->dmDevice; DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); oneExpander->discoveringPhyId++; if (onePortContext->discovery.status == DISCOVERY_UP_STREAM) { if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys ) { DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: More Phys to discover\n")); /* continue discovery for the next phy */ dmDiscoverSend(dmRoot, oneDeviceData); } else { DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: No More Phys\n")); /* for MCN */ dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData); /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander); /* continue upstream discovering */ dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } } else { DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status)); } DM_DBG3(("dmUpStreamDiscoverExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1)); return; } osGLOBAL void dmUpStreamDiscover2ExpanderPhySkip( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { dmDeviceData_t *oneDeviceData; DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: start\n")); oneDeviceData = oneExpander->dmDevice; oneExpander->discoveringPhyId++; if (onePortContext->discovery.status == DISCOVERY_UP_STREAM) { if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys ) { DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: DISCOVERY_UP_STREAM find more ...\n")); /* continue discovery for the next phy */ dmDiscoverSend(dmRoot, oneDeviceData); } else { DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: DISCOVERY_UP_STREAM last phy continue upstream..\n")); /* for MCN */ dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData); /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander); /* continue upstream discovering */ dmUpStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } } else { DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_UP_STREAM; status %d\n", onePortContext->discovery.status)); } DM_DBG2(("dmUpStreamDiscover2ExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1)); return; } osGLOBAL void dmDownStreamDiscoverExpanderPhySkip( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { dmDeviceData_t *oneDeviceData; DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: start\n")); oneDeviceData = oneExpander->dmDevice; DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); /* Increment the discovering phy id */ oneExpander->discoveringPhyId ++; /* If the discovery status is DISCOVERY_DOWN_STREAM */ if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM ) { /* If not the last phy */ if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys ) { DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: More Phys to discover\n")); /* continue discovery for the next phy */ dmDiscoverSend(dmRoot, oneDeviceData); } /* If the last phy */ else { DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: No More Phys\n")); /* for MCN */ dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData); /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander); /* continue downstream discovering */ dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } } else { DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status)); } DM_DBG3(("dmDownStreamDiscoverExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1)); return; } osGLOBAL void dmDownStreamDiscover2ExpanderPhySkip( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { dmDeviceData_t *oneDeviceData; DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: start\n")); oneDeviceData = oneExpander->dmDevice; /* Increment the discovering phy id */ oneExpander->discoveringPhyId ++; /* If the discovery status is DISCOVERY_DOWN_STREAM */ if ( onePortContext->discovery.status == DISCOVERY_DOWN_STREAM ) { /* If not the last phy */ if ( oneExpander->discoveringPhyId < oneDeviceData->numOfPhys ) { DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: More Phys to discover\n")); /* continue discovery for the next phy */ dmDiscoverSend(dmRoot, oneDeviceData); } /* If the last phy */ else { DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: No More Phys\n")); /* for MCN */ dmUpdateAllAdjacent(dmRoot, onePortContext, oneDeviceData); /* remove the expander from the discovering list */ dmDiscoveringExpanderRemove(dmRoot, onePortContext, oneExpander); /* continue downstream discovering */ dmDownStreamDiscovering(dmRoot, onePortContext, oneDeviceData); } } else { DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: onePortContext->discovery.status not in DISCOVERY_DOWN_STREAM; status %d\n", onePortContext->discovery.status)); } DM_DBG2(("dmDownStreamDiscover2ExpanderPhySkip: end return phyID#%d\n", oneExpander->discoveringPhyId - 1)); return; } osGLOBAL void dmExpanderUpStreamPhyAdd( dmRoot_t *dmRoot, dmExpander_t *oneExpander, bit8 phyId ) { bit32 i; bit32 hasSet = agFALSE; DM_DBG3(("dmExpanderUpStreamPhyAdd: start, phyid %d\n", phyId)); DM_DBG3(("dmExpanderUpStreamPhyAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmExpanderUpStreamPhyAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG3(("dmExpanderUpStreamPhyAdd: phyid %d numOfUpStreamPhys %d\n", phyId, oneExpander->numOfUpStreamPhys)); for ( i = 0; i < oneExpander->numOfUpStreamPhys; i ++ ) { if ( oneExpander->upStreamPhys[i] == phyId ) { hasSet = agTRUE; break; } } if ( hasSet == agFALSE ) { oneExpander->upStreamPhys[oneExpander->numOfUpStreamPhys ++] = phyId; } DM_DBG3(("dmExpanderUpStreamPhyAdd: AFTER phyid %d numOfUpStreamPhys %d\n", phyId, oneExpander->numOfUpStreamPhys)); /* for debugging */ for ( i = 0; i < oneExpander->numOfUpStreamPhys; i ++ ) { DM_DBG3(("dmExpanderUpStreamPhyAdd: index %d upstream[index] %d\n", i, oneExpander->upStreamPhys[i])); } return; } osGLOBAL void dmExpanderDownStreamPhyAdd( dmRoot_t *dmRoot, dmExpander_t *oneExpander, bit8 phyId ) { bit32 i; bit32 hasSet = agFALSE; DM_DBG3(("dmExpanderDownStreamPhyAdd: start, phyid %d\n", phyId)); DM_DBG3(("dmExpanderDownStreamPhyAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmExpanderDownStreamPhyAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG3(("dmExpanderDownStreamPhyAdd: phyid %d numOfDownStreamPhys %d\n", phyId, oneExpander->numOfDownStreamPhys)); for ( i = 0; i < oneExpander->numOfDownStreamPhys; i ++ ) { if ( oneExpander->downStreamPhys[i] == phyId ) { hasSet = agTRUE; break; } } if ( hasSet == agFALSE ) { oneExpander->downStreamPhys[oneExpander->numOfDownStreamPhys ++] = phyId; } DM_DBG3(("dmExpanderDownStreamPhyAdd: AFTER phyid %d numOfDownStreamPhys %d\n", phyId, oneExpander->numOfDownStreamPhys)); /* for debugging */ for ( i = 0; i < oneExpander->numOfDownStreamPhys; i ++ ) { DM_DBG3(("dmExpanderDownStreamPhyAdd: index %d downstream[index] %d\n", i, oneExpander->downStreamPhys[i])); } return; } osGLOBAL void dmDiscoveryReportMCN( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; bit16 extension = 0; dmDeviceData_t *oneAttachedExpDeviceData = agNULL; DM_DBG2(("dmDiscoveryReportMCN: start\n")); /* if full disocvery, report all devices using MCN if incremental discovery, 1. compare MCN and PrevMCN 2. report the changed ones; report MCN 3. set PrevMCN to MCN PrevMCN = MCN */ DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if ( oneDeviceData == agNULL) { DM_DBG1(("dmDiscoveryReportMCN: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmDiscoveryReportMCN: loop did %d\n", oneDeviceData->id)); if (oneDeviceData->dmPortContext == onePortContext) { DM_DBG2(("dmDiscoveryReportMCN: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG2(("dmDiscoveryReportMCN: MCN 0x%08x PrevMCN 0x%08x\n", oneDeviceData->MCN, oneDeviceData->PrevMCN)); if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { DM_DBG2(("dmDiscoveryReportMCN: FULL_START\n")); } else { DM_DBG2(("dmDiscoveryReportMCN: INCREMENTAL_START\n")); } /* if MCN is 0, the device is removed */ if (oneDeviceData->MCN != oneDeviceData->PrevMCN && oneDeviceData->MCN != 0) { DM_DBG2(("dmDiscoveryReportMCN: reporting \n")); extension = oneDeviceData->dmDeviceInfo.ext; /* zero out MCN in extension */ extension = extension & 0x7FF; /* sets MCN in extension */ extension = extension | (oneDeviceData->MCN << 11); DEVINFO_PUT_EXT(&(oneDeviceData->dmDeviceInfo), extension); DM_DBG5(("dmDiscoveryReportMCN: MCN 0x%08x PrevMCN 0x%08x\n", DEVINFO_GET_EXT_MCN(&(oneDeviceData->dmDeviceInfo)), oneDeviceData->PrevMCN)); if (oneDeviceData->ExpDevice != agNULL) { DM_DBG2(("dmDiscoveryReportMCN: attached expander case\n")); oneAttachedExpDeviceData = oneDeviceData->ExpDevice; tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, dmDeviceMCNChange); } else { DM_DBG2(("dmDiscoveryReportMCN: No attached expander case\n")); tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, dmDeviceMCNChange); } oneDeviceData->PrevMCN = oneDeviceData->MCN; } else { DM_DBG2(("dmDiscoveryReportMCN: No change; no reporting \n")); if (oneDeviceData->MCN == 0) { oneDeviceData->PrevMCN = oneDeviceData->MCN; } } } DeviceListList = DeviceListList->flink; } return; } osGLOBAL void dmDiscoveryDumpMCN( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; DM_DBG3(("dmDiscoveryDumpMCN: start\n")); DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmDiscoveryDumpMCN: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmDiscoveryDumpMCN: loop did %d\n", oneDeviceData->id)); if (oneDeviceData->dmPortContext == onePortContext) { DM_DBG3(("dmDiscoveryDumpMCN: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG3(("dmDiscoveryDumpMCN: MCN 0x%08x PrevMCN 0x%08x\n", oneDeviceData->MCN, oneDeviceData->PrevMCN)); } DeviceListList = DeviceListList->flink; } return; } osGLOBAL void dmDiscoveryResetMCN( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; DM_DBG2(("dmDiscoveryResetMCN: start\n")); /* reinitialize the device data belonging to this portcontext */ DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmDiscoveryResetMCN: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmDiscoveryResetMCN: loop did %d\n", oneDeviceData->id)); if (oneDeviceData->dmPortContext == onePortContext) { if (oneDeviceData->ExpDevice != agNULL) { DM_DBG2(("dmDiscoveryResetMCN: resetting oneDeviceData->ExpDevice\n")); oneDeviceData->ExpDevice = agNULL; } DM_DBG3(("dmDiscoveryResetMCN: resetting MCN and MCNdone\n")); oneDeviceData->MCN = 0; oneDeviceData->MCNDone = agFALSE; DM_DBG2(("dmDiscoveryResetMCN: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); } DeviceListList = DeviceListList->flink; } return; } /* do min(oneDeviceData, found-one) in all upstream and downstream find ajcanent expanders and mark it done; sees only ajcacent targets */ osGLOBAL void dmUpdateAllAdjacent( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmDeviceData_t *oneDeviceData /* current one */ ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *tmponeDeviceData = agNULL; dmList_t *DeviceListList; DM_DBG2(("dmUpdateAllAdjacent: start\n")); if (oneDeviceData == agNULL) { DM_DBG1(("dmUpdateAllAdjacent: oneDeviceData is NULL!!!\n")); return; } oneDeviceData->MCNDone = agTRUE; DM_DBG2(("dmUpdateAllAdjacent: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { tmponeDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if ( tmponeDeviceData == agNULL) { DM_DBG1(("dmUpdateAllAdjacent: tmponeDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmUpdateAllAdjacent: loop did %d\n", tmponeDeviceData->id)); if (tmponeDeviceData->dmPortContext == onePortContext && tmponeDeviceData->ExpDevice == oneDeviceData) { DM_DBG2(("dmUpdateAllAdjacent: setting MCN DONE\n")); DM_DBG2(("dmUpdateAllAdjacent: tmponeDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", tmponeDeviceData->SASAddressID.sasAddressHi, tmponeDeviceData->SASAddressID.sasAddressLo)); tmponeDeviceData->MCNDone = agTRUE; if (oneDeviceData->directlyAttached == agFALSE) { DM_DBG2(("dmUpdateAllAdjacent: tmponeDeviceData MCN 0x%x\n", tmponeDeviceData->MCN)); DM_DBG2(("dmUpdateAllAdjacent: oneDeviceData MCN 0x%x\n", oneDeviceData->MCN)); tmponeDeviceData->MCN = MIN(oneDeviceData->MCN, tmponeDeviceData->MCN); } } DeviceListList = DeviceListList->flink; } return; } osGLOBAL void dmUpdateMCN( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmDeviceData_t *AdjacentDeviceData, /* adjacent expander */ dmDeviceData_t *oneDeviceData /* current one */ ) { DM_DBG2(("dmUpdateMCN: start\n")); if (AdjacentDeviceData == agNULL) { DM_DBG1(("dmUpdateMCN: AdjacentDeviceData is NULL!!!\n")); return; } if (oneDeviceData == agNULL) { DM_DBG1(("dmUpdateMCN: oneDeviceData is NULL!!!\n")); return; } DM_DBG2(("dmUpdateMCN: Current sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG2(("dmUpdateMCN: AdjacentDeviceData one sasAddressHi 0x%08x sasAddressLo 0x%08x\n", AdjacentDeviceData->SASAddressID.sasAddressHi, AdjacentDeviceData->SASAddressID.sasAddressLo)); if (onePortContext->discovery.status == DISCOVERY_UP_STREAM) { DM_DBG2(("dmUpdateMCN: DISCOVERY_UP_STREAM\n")); } if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { DM_DBG2(("dmUpdateMCN: DISCOVERY_DOWN_STREAM\n")); } /* MCN */ /* directly attached one does not have MCN update only adjacent device data */ if (oneDeviceData->directlyAttached == agTRUE && AdjacentDeviceData->MCNDone == agFALSE) { AdjacentDeviceData->MCN++; DM_DBG2(("dmUpdateMCN: case 1 oneDeviceData MCN 0x%x\n", oneDeviceData->MCN)); DM_DBG2(("dmUpdateMCN: case 1 AdjacentDeviceData MCN 0x%x\n", AdjacentDeviceData->MCN)); } else if (AdjacentDeviceData->MCNDone == agFALSE) { AdjacentDeviceData->MCN++; AdjacentDeviceData->MCN = MIN(oneDeviceData->MCN, AdjacentDeviceData->MCN); DM_DBG2(("dmUpdateMCN: case 2 oneDeviceData MCN 0x%x\n", oneDeviceData->MCN)); DM_DBG2(("dmUpdateMCN: case 2 AdjacentDeviceData MCN 0x%x\n", AdjacentDeviceData->MCN)); } return; } /* go through expander list and device list array ??? */ osGLOBAL dmDeviceData_t * dmPortSASDeviceFind( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, bit32 sasAddrLo, bit32 sasAddrHi, dmDeviceData_t *CurrentDeviceData /* current expander */ ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData, *RetDeviceData=agNULL; dmList_t *DeviceListList; DM_DBG3(("dmPortSASDeviceFind: start\n")); DM_DBG3(("dmPortSASDeviceFind: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", sasAddrHi, sasAddrLo)); DM_ASSERT((agNULL != dmRoot), ""); DM_ASSERT((agNULL != onePortContext), ""); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); /* find a device's existence */ DeviceListList = dmAllShared->MainDeviceList.flink; if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { DM_DBG3(("dmPortSASDeviceFind: Full discovery\n")); while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmPortSASDeviceFind: oneDeviceData is NULL!!!\n")); return agNULL; } if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) && (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) && (oneDeviceData->valid == agTRUE) && (oneDeviceData->dmPortContext == onePortContext) ) { DM_DBG3(("dmPortSASDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id)); DM_DBG3(("dmPortSASDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmPortSASDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); RetDeviceData = oneDeviceData; dmUpdateMCN(dmRoot, onePortContext, RetDeviceData, CurrentDeviceData); break; } DeviceListList = DeviceListList->flink; } } else { /* incremental discovery */ DM_DBG3(("dmPortSASDeviceFind: Incremental discovery\n")); while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmPortSASDeviceFind: oneDeviceData is NULL!!!\n")); return agNULL; } if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) && (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) && (oneDeviceData->valid2 == agTRUE) && (oneDeviceData->dmPortContext == onePortContext) ) { DM_DBG3(("dmPortSASDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id)); DM_DBG3(("dmPortSASDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmPortSASDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); RetDeviceData = oneDeviceData; dmUpdateMCN(dmRoot, onePortContext, RetDeviceData, CurrentDeviceData); break; } DeviceListList = DeviceListList->flink; } } tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); return RetDeviceData; } bit32 dmNewEXPorNot( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmSASSubID_t *dmSASSubID ) { // dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; // dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmExpander_t *oneExpander = agNULL; dmList_t *ExpanderList; bit32 ret = agTRUE; dmDeviceData_t *oneDeviceData = agNULL; DM_DBG3(("dmNewEXPorNot: start\n")); /* find a device's existence */ ExpanderList = onePortContext->discovery.discoveringExpanderList.flink; while (ExpanderList != &(onePortContext->discovery.discoveringExpanderList)) { oneExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); if ( oneExpander == agNULL) { DM_DBG1(("dmNewEXPorNot: oneExpander is NULL!!!\n")); return agFALSE; } oneDeviceData = oneExpander->dmDevice; if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) && (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) && (oneDeviceData->dmPortContext == onePortContext) ) { DM_DBG3(("dmNewEXPorNot: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id)); ret = agFALSE; break; } ExpanderList = ExpanderList->flink; } return ret; } bit32 dmNewSASorNot( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmSASSubID_t *dmSASSubID ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; bit32 ret = agTRUE; DM_DBG3(("dmNewSASorNot: start\n")); /* find a device's existence */ DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmNewSASorNot: oneDeviceData is NULL!!!\n")); return agFALSE; } if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) && (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) && (oneDeviceData->dmPortContext == onePortContext) && (oneDeviceData->registered == agTRUE) ) { DM_DBG3(("dmNewSASorNot: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id)); ret = agFALSE; break; } DeviceListList = DeviceListList->flink; } return ret; } /* call osGLOBAL bit32 tddmReportDevice( dmRoot_t *dmRoot, dmPortContext_t *dmPortContext, dmDeviceInfo_t *dmDeviceInfo ) if not reported, report Device to TDM */ osGLOBAL dmDeviceData_t * dmPortSASDeviceAdd( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, agsaSASIdentify_t sasIdentify, bit32 sasInitiator, bit8 connectionRate, bit32 itNexusTimeout, bit32 firstBurstSize, bit32 deviceType, dmDeviceData_t *oneExpDeviceData, dmExpander_t *dmExpander, bit8 phyID ) { dmDeviceData_t *oneDeviceData = agNULL; bit8 dev_s_rate = 0; bit8 sasorsata = 1; dmSASSubID_t dmSASSubID; bit8 ExpanderConnectionRate = connectionRate; dmDeviceData_t *oneAttachedExpDeviceData = agNULL; bit16 extension = 0; bit32 current_link_rate = 0; DM_DBG3(("dmPortSASDeviceAdd: start\n")); DM_DBG3(("dmPortSASDeviceAdd: connectionRate %d\n", connectionRate)); dmSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify); dmSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify); dmSASSubID.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp; dmSASSubID.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp; if (oneExpDeviceData != agNULL) { ExpanderConnectionRate = DEVINFO_GET_LINKRATE(&oneExpDeviceData->agDeviceInfo); DM_DBG3(("dmPortSASDeviceAdd: ExpanderConnectionRate 0x%x\n", ExpanderConnectionRate)); } if (oneExpDeviceData != agNULL) { if (oneExpDeviceData->SASAddressID.sasAddressHi == 0x0 && oneExpDeviceData->SASAddressID.sasAddressLo == 0x0) { DM_DBG1(("dmPortSASDeviceAdd: 1st Wrong expander!!!\n")); } } /* old device and already reported to TDM */ if ( agFALSE == dmNewSASorNot( dmRoot, onePortContext, &dmSASSubID ) ) /* old device */ { DM_DBG3(("dmPortSASDeviceAdd: OLD qqqq initiator_ssp_stp_smp %d target_ssp_stp_smp %d\n", dmSASSubID.initiator_ssp_stp_smp, dmSASSubID.target_ssp_stp_smp)); /* allocate a new device and set the valid bit */ oneDeviceData = dmAddSASToSharedcontext( dmRoot, onePortContext, &dmSASSubID, oneExpDeviceData, phyID ); if (oneDeviceData == agNULL) { DM_DBG1(("dmPortSASDeviceAdd: no more device, oneDeviceData is null!!!\n")); } /* If a device is allocated */ if ( oneDeviceData != agNULL ) { if (onePortContext->discovery.status == DISCOVERY_UP_STREAM) { DM_DBG3(("dmPortSASDeviceAdd: OLD, UP_STREAM\n")); } if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { DM_DBG3(("dmPortSASDeviceAdd: OLD, DOWN_STREAM\n")); } if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { DM_DBG3(("dmPortSASDeviceAdd: FULL_START\n")); oneDeviceData->MCN++; } else { /* incremental */ DM_DBG3(("dmPortSASDeviceAdd: INCREMENTAL_START\n")); if (oneDeviceData->MCN == 0 && oneDeviceData->directlyAttached == agFALSE) { oneDeviceData->MCN++; } } DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData MCN 0x%08x\n", oneDeviceData->MCN)); DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify))); DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify))); // oneDeviceData->sasIdentify = sasIdentify; dm_memcpy(&(oneDeviceData->sasIdentify), &sasIdentify, sizeof(agsaSASIdentify_t)); DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify))); DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify))); /* parse sasIDframe to fill in agDeviceInfo */ DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT); DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)itNexusTimeout); DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, (bit16)firstBurstSize); DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 1); oneDeviceData->SASSpecDeviceType = SA_IDFRM_GET_DEVICETTYPE(&sasIdentify); /* adjusting connectionRate */ oneAttachedExpDeviceData = oneDeviceData->ExpDevice; if (oneAttachedExpDeviceData != agNULL) { connectionRate = MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)); DM_DBG3(("dmPortSASDeviceAdd: 1st connectionRate 0x%x DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n", connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo))); } else { DM_DBG3(("dmPortSASDeviceAdd: 1st oneAttachedExpDeviceData is NULL\n")); } /* Device Type, SAS or SATA, connection rate; bit7 --- bit0 */ sasorsata = (bit8)deviceType; /* sTSDK spec device typ */ dev_s_rate = dev_s_rate | (sasorsata << 4); dev_s_rate = dev_s_rate | MIN(connectionRate, ExpanderConnectionRate); /* detect link rate change */ current_link_rate = DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo); if (current_link_rate != (bit32)MIN(connectionRate, ExpanderConnectionRate)) { DM_DBG1(("dmPortSASDeviceAdd: link rate changed current 0x%x new 0x%x\n", current_link_rate, MIN(connectionRate, ExpanderConnectionRate))); DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->dmDeviceInfo, dev_s_rate); if (oneDeviceData->ExpDevice != agNULL) { oneAttachedExpDeviceData = oneDeviceData->ExpDevice; tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, dmDeviceRateChange); } else { tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, dmDeviceArrival); } } DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate); DEVINFO_PUT_SAS_ADDRESSLO( &oneDeviceData->agDeviceInfo, SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify) ); DEVINFO_PUT_SAS_ADDRESSHI( &oneDeviceData->agDeviceInfo, SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify) ); oneDeviceData->agContext.osData = oneDeviceData; oneDeviceData->agContext.sdkData = agNULL; } return oneDeviceData; } /* old device */ /* new device */ DM_DBG3(("dmPortSASDeviceAdd: NEW qqqq initiator_ssp_stp_smp %d target_ssp_stp_smp %d\n", dmSASSubID.initiator_ssp_stp_smp, dmSASSubID.target_ssp_stp_smp)); /* allocate a new device and set the valid bit */ oneDeviceData = dmAddSASToSharedcontext( dmRoot, onePortContext, &dmSASSubID, oneExpDeviceData, phyID ); if (oneDeviceData == agNULL) { DM_DBG1(("dmPortSASDeviceAdd: no more device, oneDeviceData is null !!!\n")); } /* If a device is allocated */ if ( oneDeviceData != agNULL ) { // DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify))); // DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify))); // oneDeviceData->sasIdentify = sasIdentify; dm_memcpy(&(oneDeviceData->sasIdentify), &sasIdentify, sizeof(agsaSASIdentify_t)); if (onePortContext->discovery.status == DISCOVERY_UP_STREAM) { DM_DBG3(("dmPortSASDeviceAdd: NEW, UP_STREAM\n")); } if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { DM_DBG3(("dmPortSASDeviceAdd: NEW, DOWN_STREAM\n")); } if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { DM_DBG3(("dmPortSASDeviceAdd: FULL_START\n")); oneDeviceData->MCN++; } else { /* incremental */ DM_DBG3(("dmPortSASDeviceAdd: INCREMENTAL_START\n")); if (oneDeviceData->MCN == 0 && oneDeviceData->directlyAttached == agFALSE) { oneDeviceData->MCN++; } } DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData MCN 0x%08x\n", oneDeviceData->MCN)); DM_DBG3(("dmPortSASDeviceAdd: oneDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG3(("dmPortSASDeviceAdd: sasAddressHi 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify))); DM_DBG3(("dmPortSASDeviceAdd: sasAddressLo 0x%08x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify))); /* parse sasIDframe to fill in agDeviceInfo */ DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT); DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)itNexusTimeout); DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, (bit16)firstBurstSize); DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 1); oneDeviceData->SASSpecDeviceType = SA_IDFRM_GET_DEVICETTYPE(&sasIdentify); /* adjusting connectionRate */ oneAttachedExpDeviceData = oneDeviceData->ExpDevice; if (oneAttachedExpDeviceData != agNULL) { connectionRate = MIN(connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo)); DM_DBG3(("dmPortSASDeviceAdd: 2nd connectionRate 0x%x DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo) 0x%x\n", connectionRate, DEVINFO_GET_LINKRATE(&oneAttachedExpDeviceData->agDeviceInfo))); } else { DM_DBG3(("dmPortSASDeviceAdd: 2nd oneAttachedExpDeviceData is NULL\n")); } /* Device Type, SAS or SATA, connection rate; bit7 --- bit0 */ sasorsata = (bit8)deviceType; dev_s_rate = dev_s_rate | (sasorsata << 4); dev_s_rate = dev_s_rate | MIN(connectionRate, ExpanderConnectionRate); DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate); DEVINFO_PUT_SAS_ADDRESSLO( &oneDeviceData->agDeviceInfo, SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify) ); DEVINFO_PUT_SAS_ADDRESSHI( &oneDeviceData->agDeviceInfo, SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify) ); oneDeviceData->agContext.osData = oneDeviceData; oneDeviceData->agContext.sdkData = agNULL; DM_DBG3(("dmPortSASDeviceAdd: did %d\n", oneDeviceData->id)); /* reporting to TDM; setting dmDeviceInfo */ DEVINFO_PUT_SMPTO(&oneDeviceData->dmDeviceInfo, DEFAULT_SMP_TIMEOUT); DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->dmDeviceInfo, (bit16)itNexusTimeout); DEVINFO_PUT_FBS(&oneDeviceData->dmDeviceInfo, (bit16)firstBurstSize); DEVINFO_PUT_FLAG(&oneDeviceData->dmDeviceInfo, 1); DEVINFO_PUT_INITIATOR_SSP_STP_SMP(&oneDeviceData->dmDeviceInfo, dmSASSubID.initiator_ssp_stp_smp); DEVINFO_PUT_TARGET_SSP_STP_SMP(&oneDeviceData->dmDeviceInfo, dmSASSubID.target_ssp_stp_smp); extension = phyID; /* setting 6th bit of dev_s_rate */ if (oneDeviceData->SASSpecDeviceType == SAS_EDGE_EXPANDER_DEVICE || oneDeviceData->SASSpecDeviceType == SAS_FANOUT_EXPANDER_DEVICE ) { extension = (bit16)(extension | (1 << 8)); } DEVINFO_PUT_EXT(&oneDeviceData->dmDeviceInfo, extension); DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->dmDeviceInfo, dev_s_rate); DEVINFO_PUT_SAS_ADDRESSLO( &oneDeviceData->dmDeviceInfo, SA_IDFRM_GET_SAS_ADDRESSLO(&oneDeviceData->sasIdentify) ); DEVINFO_PUT_SAS_ADDRESSHI( &oneDeviceData->dmDeviceInfo, SA_IDFRM_GET_SAS_ADDRESSHI(&oneDeviceData->sasIdentify) ); if (oneDeviceData->ExpDevice != agNULL) { DM_DBG3(("dmPortSASDeviceAdd: attached expander case\n")); oneAttachedExpDeviceData = oneDeviceData->ExpDevice; /* Puts attached expander's SAS address into dmDeviceInfo */ DEVINFO_PUT_SAS_ADDRESSLO( &oneAttachedExpDeviceData->dmDeviceInfo, oneAttachedExpDeviceData->SASAddressID.sasAddressLo ); DEVINFO_PUT_SAS_ADDRESSHI( &oneAttachedExpDeviceData->dmDeviceInfo, oneAttachedExpDeviceData->SASAddressID.sasAddressHi ); DM_DBG3(("dmPortSASDeviceAdd: oneAttachedExpDeviceData addrHi 0x%08x addrLo 0x%08x PhyID 0x%x ext 0x%x\n", DM_GET_SAS_ADDRESSHI(oneAttachedExpDeviceData->dmDeviceInfo.sasAddressHi), DM_GET_SAS_ADDRESSLO(oneAttachedExpDeviceData->dmDeviceInfo.sasAddressLo), phyID, extension)); if (oneAttachedExpDeviceData->SASAddressID.sasAddressHi == 0x0 && oneAttachedExpDeviceData->SASAddressID.sasAddressLo == 0x0) { DM_DBG1(("dmPortSASDeviceAdd: 2nd Wrong expander!!!\n")); } if (oneDeviceData->reported == agFALSE) { oneDeviceData->registered = agTRUE; oneDeviceData->reported = agTRUE; if (deviceType == STP_DEVICE_TYPE) { /*STP device, DM need send SMP Report Phy SATA to get the SATA device type */ oneAttachedExpDeviceData->dmExpander->dmDeviceToProcess = oneDeviceData; dmReportPhySataSend(dmRoot, oneAttachedExpDeviceData, phyID); } else { /* SAS or SMP device */ tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, dmDeviceArrival); } } } else { DM_DBG3(("dmPortSASDeviceAdd: NO attached expander case\n")); if (oneDeviceData->reported == agFALSE) { oneDeviceData->registered = agTRUE; oneDeviceData->reported = agTRUE; tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, dmDeviceArrival); } } } return oneDeviceData; } osGLOBAL dmDeviceData_t * dmFindRegNValid( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmSASSubID_t *dmSASSubID ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; bit32 found = agFALSE; DM_DBG3(("dmFindRegNValid: start\n")); /* find a device's existence */ DeviceListList = dmAllShared->MainDeviceList.flink; if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { DM_DBG3(("dmFindRegNValid: Full discovery\n")); while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmFindRegNValid: oneDeviceData is NULL!!!\n")); return agFALSE; } if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) && (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) && (oneDeviceData->valid == agTRUE) && (oneDeviceData->dmPortContext == onePortContext) ) { DM_DBG3(("dmFindRegNValid: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id)); DM_DBG3(("dmFindRegNValid: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmFindRegNValid: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); found = agTRUE; break; } DeviceListList = DeviceListList->flink; } } else { /* incremental discovery */ DM_DBG3(("dmFindRegNValid: Incremental discovery\n")); while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmFindRegNValid: oneDeviceData is NULL!!!\n")); return agFALSE; } if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) && (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) && (oneDeviceData->valid2 == agTRUE) && (oneDeviceData->dmPortContext == onePortContext) ) { DM_DBG3(("dmFindRegNValid: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id)); DM_DBG3(("dmFindRegNValid: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmFindRegNValid: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); found = agTRUE; break; } DeviceListList = DeviceListList->flink; } } if (found == agFALSE) { DM_DBG3(("dmFindRegNValid: end returning NULL\n")); return agNULL; } else { DM_DBG3(("dmFindRegNValid: end returning NOT NULL\n")); return oneDeviceData; } } osGLOBAL void dmNotifyBC( dmRoot_t *dmRoot, dmPortContext_t *dmPortContext, bit32 type) { dmIntPortContext_t *onePortContext = agNULL; onePortContext = (dmIntPortContext_t *)dmPortContext->dmData; DM_DBG3(("dmNotifyBC: start\n")); if (onePortContext == agNULL) { DM_DBG1(("dmNotifyBC: onePortContext is NULL, wrong!!!\n")); return; } if (type == OSSA_HW_EVENT_BROADCAST_CHANGE) { if (onePortContext->DiscoveryAbortInProgress == agFALSE) { if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED) { DM_DBG3(("dmNotifyBC: BROADCAST_CHANGE\n")); onePortContext->DiscoveryState = DM_DSTATE_NOT_STARTED; onePortContext->discoveryOptions = DM_DISCOVERY_OPTION_INCREMENTAL_START; /* processed broadcast change */ onePortContext->discovery.SeenBC = agFALSE; } else { DM_DBG3(("dmNotifyBC: pid %d BROADCAST_CHANGE; updating SeenBC. Do nothing.\n", onePortContext->id)); onePortContext->discovery.SeenBC = agTRUE; } } } else if (type == OSSA_HW_EVENT_BROADCAST_SES) { DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_SES\n")); } else if (type == OSSA_HW_EVENT_BROADCAST_EXP) { DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_EXP\n")); } else { DM_DBG3(("dmNotifyBC: unspecified broadcast type 0x%x\n", type)); } return; } #ifdef WORKED /* triggers incremental discovery */ osGLOBAL void dmNotifyBC( dmRoot_t *dmRoot, dmPortContext_t *dmPortContext, bit32 type) { dmIntPortContext_t *onePortContext = agNULL; onePortContext = (dmIntPortContext_t *)dmPortContext->dmData; DM_DBG3(("dmNotifyBC: start\n")); if (type == OSSA_HW_EVENT_BROADCAST_CHANGE) { if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED) { DM_DBG3(("dmNotifyBC: BROADCAST_CHANGE; does incremental discovery\n")); onePortContext->DiscoveryState = DM_DSTATE_NOT_STARTED; onePortContext->discoveryOptions = DM_DISCOVERY_OPTION_INCREMENTAL_START; /* processed broadcast change */ onePortContext->discovery.SeenBC = agFALSE; if (onePortContext->discovery.ResetTriggerred == agTRUE) { DM_DBG3(("dmNotifyBC: tdsaBCTimer\n")); dmBCTimer(dmRoot, onePortContext); } else { dmDiscover( dmRoot, dmPortContext, DM_DISCOVERY_OPTION_INCREMENTAL_START ); } } else { DM_DBG3(("dmNotifyBC: pid %d BROADCAST_CHANGE; updating SeenBC. Do nothing.\n", onePortContext->id)); onePortContext->discovery.SeenBC = agTRUE; } } else if (type == OSSA_HW_EVENT_BROADCAST_SES) { DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_SES\n")); } else if (type == OSSA_HW_EVENT_BROADCAST_EXP) { DM_DBG3(("dmNotifyBC: OSSA_HW_EVENT_BROADCAST_EXP\n")); } else { DM_DBG3(("dmNotifyBC: unspecified broadcast type 0x%x\n", type)); } return; } #endif osGLOBAL bit32 dmResetFailedDiscovery( dmRoot_t *dmRoot, dmPortContext_t *dmPortContext) { dmIntPortContext_t *onePortContext = agNULL; DM_DBG1(("dmResetFailedDiscovery: start\n")); onePortContext = (dmIntPortContext_t *)dmPortContext->dmData; if (onePortContext == agNULL) { DM_DBG1(("dmResetFailedDiscovery: onePortContext is NULL, wrong!!!\n")); return DM_RC_FAILURE; } if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED_WITH_FAILURE) { onePortContext->DiscoveryState = DM_DSTATE_COMPLETED; } else { DM_DBG1(("dmResetFailedDiscovery: discovery is NOT DM_DSTATE_COMPLETED_WITH_FAILURE. It is 0x%x\n", onePortContext->DiscoveryState)); return DM_RC_FAILURE; } return DM_RC_SUCCESS; } osGLOBAL bit32 dmQueryDiscovery( dmRoot_t *dmRoot, dmPortContext_t *dmPortContext) { dmIntPortContext_t *onePortContext = agNULL; DM_DBG3(("dmQueryDiscovery: start\n")); onePortContext = (dmIntPortContext_t *)dmPortContext->dmData; if (onePortContext == agNULL) { DM_DBG1(("dmQueryDiscovery: onePortContext is NULL, wrong!!!\n")); return DM_RC_FAILURE; } /* call tddmQueryDiscoveryCB() */ if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED) { tddmQueryDiscoveryCB(dmRoot, dmPortContext, onePortContext->discoveryOptions, dmDiscCompleted); } else if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED_WITH_FAILURE) { tddmQueryDiscoveryCB(dmRoot, dmPortContext, onePortContext->discoveryOptions, dmDiscFailed); } else { tddmQueryDiscoveryCB(dmRoot, dmPortContext, onePortContext->discoveryOptions, dmDiscInProgress); } return DM_RC_SUCCESS; } /* should only for an expander */ osGLOBAL bit32 dmRegisterDevice( dmRoot_t *dmRoot, dmPortContext_t *dmPortContext, dmDeviceInfo_t *dmDeviceInfo, agsaDevHandle_t *agDevHandle ) { dmIntPortContext_t *onePortContext = agNULL; dmExpander_t *oneExpander = agNULL; bit32 sasAddressHi, sasAddressLo; dmDeviceData_t *oneDeviceData = agNULL; dmSASSubID_t dmSASSubID; DM_DBG3(("dmRegisterDevice: start\n")); onePortContext = (dmIntPortContext_t *)dmPortContext->dmData; if (onePortContext == agNULL) { DM_DBG1(("dmRegisterDevice: onePortContext is NULL!!!\n")); return DM_RC_FAILURE; } if (onePortContext->valid == agFALSE) { DM_DBG1(("dmRegisterDevice: invalid port!!!\n")); return DM_RC_FAILURE; } onePortContext->RegFailed = agFALSE; /* tdssAddSASToSharedcontext() from ossaHwCB() osGLOBAL void tdssAddSASToSharedcontext( tdsaPortContext_t *tdsaPortContext_Instance, agsaRoot_t *agRoot, agsaDevHandle_t *agDevHandle, tdsaSASSubID_t *agSASSubID, bit32 registered, bit8 phyID, bit32 flag ); from discovery osGLOBAL tdsaDeviceData_t * tdssNewAddSASToSharedcontext( agsaRoot_t *agRoot, tdsaPortContext_t *onePortContext, tdsaSASSubID_t *agSASSubID, tdsaDeviceData_t *oneExpDeviceData, bit8 phyID ); */ /* start here */ dmSASSubID.sasAddressHi = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressHi); dmSASSubID.sasAddressLo = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressLo); dmSASSubID.initiator_ssp_stp_smp = dmDeviceInfo->initiator_ssp_stp_smp; dmSASSubID.target_ssp_stp_smp = dmDeviceInfo->target_ssp_stp_smp; oneDeviceData = dmAddSASToSharedcontext(dmRoot, onePortContext, &dmSASSubID, agNULL, 0xFF); if (oneDeviceData == agNULL) { DM_DBG1(("dmRegisterDevice: oneDeviceData is NULL!!!\n")); return DM_RC_FAILURE; } oneDeviceData->agDeviceInfo.devType_S_Rate = dmDeviceInfo->devType_S_Rate; dm_memcpy(oneDeviceData->agDeviceInfo.sasAddressHi, dmDeviceInfo->sasAddressHi, 4); dm_memcpy(oneDeviceData->agDeviceInfo.sasAddressLo, dmDeviceInfo->sasAddressLo, 4); /* finds the type of expanders */ if (DEVINFO_GET_EXT_SMP(dmDeviceInfo)) { if (DEVINFO_GET_EXT_EXPANDER_TYPE(dmDeviceInfo) == SAS_EDGE_EXPANDER_DEVICE) { oneDeviceData->SASSpecDeviceType = SAS_EDGE_EXPANDER_DEVICE; } else if (DEVINFO_GET_EXT_EXPANDER_TYPE(dmDeviceInfo) == SAS_FANOUT_EXPANDER_DEVICE) { oneDeviceData->SASSpecDeviceType = SAS_FANOUT_EXPANDER_DEVICE; } else { /* default */ DM_DBG4(("dmRegisterDevice: no expander type. default to edge expander\n")); oneDeviceData->SASSpecDeviceType = SAS_EDGE_EXPANDER_DEVICE; } } if (DEVINFO_GET_EXT_MCN(dmDeviceInfo) == 0xF) { DM_DBG1(("dmRegisterDevice: directly attached expander\n")); oneDeviceData->directlyAttached = agTRUE; oneDeviceData->dmDeviceInfo.ext = (bit16)(oneDeviceData->dmDeviceInfo.ext | (0xF << 11)); } else { DM_DBG1(("dmRegisterDevice: NOT directly attached expander\n")); oneDeviceData->directlyAttached = agFALSE; } if (onePortContext->DiscoveryState == DM_DSTATE_NOT_STARTED) { DM_DBG3(("dmRegisterDevice: DM_DSTATE_NOT_STARTED\n")); /* before the discovery is started */ oneExpander = dmDiscoveringExpanderAlloc(dmRoot, onePortContext, oneDeviceData); if ( oneExpander != agNULL) { oneExpander->agDevHandle = agDevHandle; /* update SAS address field */ oneExpander->dmDevice->SASAddressID.sasAddressHi = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressHi); oneExpander->dmDevice->SASAddressID.sasAddressLo = DM_GET_SAS_ADDRESSLO(dmDeviceInfo->sasAddressLo); DM_DBG3(("dmRegisterDevice: AddrHi 0x%08x AddrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi, oneExpander->dmDevice->SASAddressID.sasAddressLo)); dmDiscoveringExpanderAdd(dmRoot, onePortContext, oneExpander); } else { DM_DBG1(("dmRegisterDevice: failed to allocate expander !!!\n")); /* remember that the registration failed so that a discovery can't be started */ onePortContext->RegFailed = agTRUE; return DM_RC_FAILURE; } } else { /* the discovery has started. Alloc and add have been done. find an expander using dmDeviceInfo, and update the expander's agDevHandle call dmExpFind() */ DM_DBG3(("dmRegisterDevice: NOT DM_DSTATE_NOT_STARTED\n")); sasAddressHi = DM_GET_SAS_ADDRESSHI(dmDeviceInfo->sasAddressHi); sasAddressLo = DM_GET_SAS_ADDRESSLO(dmDeviceInfo->sasAddressLo); DM_DBG3(("dmRegisterDevice: AddrHi 0x%08x AddrLo 0x%08x\n", sasAddressHi, sasAddressLo)); oneExpander = dmExpFind(dmRoot, onePortContext, sasAddressHi, sasAddressLo); if ( oneExpander != agNULL) { oneExpander->agDevHandle = agDevHandle; } else { DM_DBG1(("dmRegisterDevice: not allowed case, wrong !!!\n")); return DM_RC_FAILURE; } } return DM_RC_SUCCESS; } osGLOBAL dmExpander_t * dmDiscoveringExpanderAlloc( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmDeviceData_t *oneDeviceData ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmExpander_t *oneExpander = agNULL; dmList_t *ExpanderList; DM_DBG3(("dmDiscoveringExpanderAlloc: start\n")); DM_DBG3(("dmDiscoveringExpanderAlloc: did %d\n", oneDeviceData->id)); DM_DBG3(("dmDiscoveringExpanderAlloc: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDiscoveringExpanderAlloc: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); if (onePortContext->valid == agFALSE) { DM_DBG1(("dmDiscoveringExpanderAlloc: invalid port!!!\n")); return agNULL; } /* check exitence in dmAllShared->mainExpanderList */ oneExpander = dmExpMainListFind(dmRoot, onePortContext, oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo); if (oneExpander == agNULL) { tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); if (DMLIST_EMPTY(&(dmAllShared->freeExpanderList))) { DM_DBG1(("dmDiscoveringExpanderAlloc: no free expanders pid %d!!!\n", onePortContext->id)); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); return agNULL; } else { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); DMLIST_DEQUEUE_FROM_HEAD(&ExpanderList, &(dmAllShared->freeExpanderList)); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); oneExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); } if (oneExpander != agNULL) { DM_DBG1(("dmDiscoveringExpanderAlloc: pid %d exp id %d \n", onePortContext->id, oneExpander->id)); tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); DMLIST_DEQUEUE_THIS(&(oneExpander->linkNode)); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); oneExpander->dmDevice = oneDeviceData; oneExpander->dmUpStreamExpander = agNULL; oneExpander->dmCurrentDownStreamExpander = agNULL; oneExpander->dmReturnginExpander = agNULL; oneExpander->hasUpStreamDevice = agFALSE; oneExpander->numOfUpStreamPhys = 0; oneExpander->currentUpStreamPhyIndex = 0; oneExpander->discoveringPhyId = 0; oneExpander->underDiscovering = agFALSE; dm_memset( &(oneExpander->currentIndex), 0, sizeof(oneExpander->currentIndex)); oneDeviceData->dmExpander = oneExpander; DM_DBG3(("dmDiscoveringExpanderAlloc: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmDiscoveringExpanderAlloc: oneExpander %p did %d\n", oneDeviceData->dmExpander, oneDeviceData->dmExpander->id)); } return oneExpander; } osGLOBAL void dmDiscoveringExpanderAdd( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { DM_DBG3(("dmDiscoveringExpanderAdd: start\n")); DM_DBG3(("dmDiscoveringExpanderAdd: expander id %d\n", oneExpander->id)); DM_DBG3(("dmDiscoveringExpanderAdd: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmDiscoveringExpanderAdd: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); if (onePortContext->valid == agFALSE) { DM_DBG1(("dmDiscoveringExpanderAdd: invalid port!!!\n")); return; } if (onePortContext->discovery.status == DISCOVERY_UP_STREAM) { DM_DBG3(("dmDiscoveringExpanderAdd: UPSTREAM\n")); } else if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { DM_DBG3(("dmDiscoveringExpanderAdd: DOWNSTREAM\n")); } else { DM_DBG3(("dmDiscoveringExpanderAdd: status %d\n", onePortContext->discovery.status)); } if ( oneExpander->underDiscovering == agFALSE) { DM_DBG3(("dmDiscoveringExpanderAdd: ADDED \n")); oneExpander->underDiscovering = agTRUE; tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(onePortContext->discovery.discoveringExpanderList)); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } return; } osGLOBAL dmExpander_t * dmFindConfigurableExp( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { dmExpander_t *tempExpander; dmIntPortContext_t *tmpOnePortContext = onePortContext; dmExpander_t *ret = agNULL; DM_DBG3(("dmFindConfigurableExp: start\n")); if (oneExpander == agNULL) { DM_DBG3(("dmFindConfigurableExp: NULL expander\n")); return agNULL; } DM_DBG3(("dmFindConfigurableExp: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmFindConfigurableExp: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList))) { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); DM_DBG3(("dmFindConfigurableExp: empty UpdiscoveringExpanderList\n")); return agNULL; } else { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } tempExpander = oneExpander->dmUpStreamExpander; while (tempExpander) { DM_DBG3(("dmFindConfigurableExp: loop exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmFindConfigurableExp: loop exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo)); if (tempExpander->configRouteTable) { DM_DBG3(("dmFindConfigurableExp: found configurable expander\n")); ret = tempExpander; break; } tempExpander = tempExpander->dmUpStreamExpander; } return ret; } osGLOBAL bit32 dmDuplicateConfigSASAddr( dmRoot_t *dmRoot, dmExpander_t *oneExpander, bit32 configSASAddressHi, bit32 configSASAddressLo ) { bit32 i; bit32 ret = agFALSE; DM_DBG3(("dmDuplicateConfigSASAddr: start\n")); if (oneExpander == agNULL) { DM_DBG3(("dmDuplicateConfigSASAddr: NULL expander\n")); return agTRUE; } if (oneExpander->dmDevice->SASAddressID.sasAddressHi == configSASAddressHi && oneExpander->dmDevice->SASAddressID.sasAddressLo == configSASAddressLo ) { DM_DBG3(("dmDuplicateConfigSASAddr: unnecessary\n")); return agTRUE; } DM_DBG3(("dmDuplicateConfigSASAddr: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmDuplicateConfigSASAddr: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG3(("dmDuplicateConfigSASAddr: configsasAddressHi 0x%08x\n", configSASAddressHi)); DM_DBG3(("dmDuplicateConfigSASAddr: configsasAddressLo 0x%08x\n", configSASAddressLo)); DM_DBG3(("dmDuplicateConfigSASAddr: configSASAddrTableIndex %d\n", oneExpander->configSASAddrTableIndex)); for(i=0;iconfigSASAddrTableIndex;i++) { if (oneExpander->configSASAddressHiTable[i] == configSASAddressHi && oneExpander->configSASAddressLoTable[i] == configSASAddressLo ) { DM_DBG3(("dmDuplicateConfigSASAddr: FOUND\n")); ret = agTRUE; break; } } /* new one; let's add it */ if (ret == agFALSE) { DM_DBG3(("dmDuplicateConfigSASAddr: adding configSAS Addr\n")); DM_DBG3(("dmDuplicateConfigSASAddr: configSASAddrTableIndex %d\n", oneExpander->configSASAddrTableIndex)); oneExpander->configSASAddressHiTable[oneExpander->configSASAddrTableIndex] = configSASAddressHi; oneExpander->configSASAddressLoTable[oneExpander->configSASAddrTableIndex] = configSASAddressLo; oneExpander->configSASAddrTableIndex++; } return ret; } osGLOBAL bit16 dmFindCurrentDownStreamPhyIndex( dmRoot_t *dmRoot, dmExpander_t *oneExpander ) { dmExpander_t *DownStreamExpander; bit16 index = 0; bit16 i; bit8 phyId = 0; DM_DBG3(("dmFindCurrentDownStreamPhyIndex: start\n")); if (oneExpander == agNULL) { DM_DBG1(("dmFindCurrentDownStreamPhyIndex: wrong, oneExpander is NULL!!!\n")); return 0; } DownStreamExpander = oneExpander->dmCurrentDownStreamExpander; if (DownStreamExpander == agNULL) { DM_DBG1(("dmFindCurrentDownStreamPhyIndex: wrong, DownStreamExpander is NULL!!!\n")); return 0; } DM_DBG3(("dmFindCurrentDownStreamPhyIndex: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmFindCurrentDownStreamPhyIndex: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG3(("dmFindCurrentDownStreamPhyIndex: downstream exp addrHi 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmFindCurrentDownStreamPhyIndex: downstream exp addrLo 0x%08x\n", DownStreamExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG3(("dmFindCurrentDownStreamPhyIndex: numOfDownStreamPhys %d\n", oneExpander->numOfDownStreamPhys)); phyId = DownStreamExpander->upStreamPhys[0]; DM_DBG3(("dmFindCurrentDownStreamPhyIndex: phyId %d\n", phyId)); for (i=0; inumOfDownStreamPhys;i++) { if (oneExpander->downStreamPhys[i] == phyId) { index = i; break; } } DM_DBG3(("dmFindCurrentDownStreamPhyIndex: index %d\n", index)); return index; } osGLOBAL bit32 dmFindDiscoveringExpander( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { dmList_t *ExpanderList; dmExpander_t *tempExpander; dmIntPortContext_t *tmpOnePortContext = onePortContext; bit32 ret = agFALSE; DM_DBG3(("dmFindDiscoveringExpander: start\n")); DM_DBG3(("dmFindDiscoveringExpander: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmFindDiscoveringExpander: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList))) { DM_DBG3(("dmFindDiscoveringExpander: empty discoveringExpanderList\n")); return ret; } ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink; while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList)) { tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); if (tempExpander == oneExpander) { if (tempExpander != agNULL) { DM_DBG3(("dmFindDiscoveringExpander: match, expander id %d\n", tempExpander->id)); DM_DBG3(("dmFindDiscoveringExpander: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmFindDiscoveringExpander: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo)); } ret = agTRUE; break; } ExpanderList = ExpanderList->flink; } return ret; } osGLOBAL void dmDiscoveringExpanderRemove( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; DM_DBG3(("dmDiscoveringExpanderRemove: start\n")); DM_DBG3(("dmDiscoveringExpanderRemove: expander id %d\n", oneExpander->id)); DM_DBG3(("dmDiscoveringExpanderRemove: exp addrHi 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmDiscoveringExpanderRemove: exp addrLo 0x%08x\n", oneExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG3(("dmDiscoveringExpanderRemove: BEFORE\n")); dmDumpAllExp(dmRoot, onePortContext, oneExpander); dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); dmDumpAllFreeExp(dmRoot); // if is temporary till smp problem is fixed if (dmFindDiscoveringExpander(dmRoot, onePortContext, oneExpander) == agTRUE) { DM_DBG3(("dmDiscoveringExpanderRemove: oneDeviceData %p did %d\n", oneExpander->dmDevice, oneExpander->dmDevice->id)); DM_DBG3(("dmDiscoveringExpanderRemove: oneExpander %p did %d\n", oneExpander, oneExpander->id)); if (oneExpander != oneExpander->dmDevice->dmExpander) { DM_DBG3(("dmDiscoveringExpanderRemove: before !!! wrong !!!\n")); } oneExpander->underDiscovering = agFALSE; oneExpander->discoveringPhyId = 0; tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); DMLIST_DEQUEUE_THIS(&(oneExpander->linkNode)); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); if (onePortContext->discovery.status == DISCOVERY_UP_STREAM) { DM_DBG3(("dmDiscoveringExpanderRemove: DISCOVERY_UP_STREAM\n")); tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->upNode), &(onePortContext->discovery.UpdiscoveringExpanderList)); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); onePortContext->discovery.NumOfUpExp++; } else { DM_DBG3(("dmDiscoveringExpanderRemove: Status %d\n", onePortContext->discovery.status)); tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(dmAllShared->mainExpanderList)); // DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(dmAllShared->freeExpanderList)); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } // error checking if (oneExpander != oneExpander->dmDevice->dmExpander) { DM_DBG3(("dmDiscoveringExpanderRemove: after !!! wrong !!!\n")); } } //end temp if else { DM_DBG1(("dmDiscoveringExpanderRemove: !!! problem !!!\n")); } DM_DBG3(("dmDiscoveringExpanderRemove: AFTER\n")); dmDumpAllExp(dmRoot, onePortContext, oneExpander); dmDumpAllUpExp(dmRoot, onePortContext, oneExpander); dmDumpAllFreeExp(dmRoot); return; } /* returns an expander with sasAddrLo, sasAddrHi from dmAllShared->mainExpanderList */ osGLOBAL dmExpander_t * dmExpMainListFind( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, bit32 sasAddrHi, bit32 sasAddrLo ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmList_t *ExpanderList; dmExpander_t *tempExpander; DM_DBG3(("dmExpMainListFind: start\n")); tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); if (DMLIST_EMPTY(&(dmAllShared->mainExpanderList))) { DM_DBG1(("dmExpMainListFind: empty mainExpanderList\n")); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); return agNULL; } else { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } ExpanderList = dmAllShared->mainExpanderList.flink; while (ExpanderList != &(dmAllShared->mainExpanderList)) { tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); if (tempExpander == agNULL) { DM_DBG1(("dmExpMainListFind: tempExpander is NULL!!!\n")); return agNULL; } DM_DBG3(("dmExpMainListFind: expander id %d\n", tempExpander->id)); DM_DBG3(("dmExpMainListFind: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmExpMainListFind: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo)); if ((tempExpander->dmDevice->SASAddressID.sasAddressHi == sasAddrHi) && (tempExpander->dmDevice->SASAddressID.sasAddressLo == sasAddrLo) && (tempExpander->dmDevice->dmPortContext == onePortContext) ) { DM_DBG3(("dmExpMainListFind: found expander id %d\n", tempExpander->id)); DM_DBG3(("dmExpMainListFind: found exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmExpMainListFind: found exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo)); return tempExpander; } ExpanderList = ExpanderList->flink; } return agNULL; } /* returns an expander with sasAddrLo, sasAddrHi from discoveringExpanderList */ osGLOBAL dmExpander_t * dmExpFind( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, bit32 sasAddrHi, bit32 sasAddrLo ) { dmList_t *ExpanderList; dmExpander_t *tempExpander; dmIntPortContext_t *tmpOnePortContext = onePortContext; DM_DBG3(("dmExpFind: start\n")); tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList))) { DM_DBG3(("dmExpFind tdsaDumpAllExp: empty discoveringExpanderList\n")); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); return agNULL; } else { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink; while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList)) { tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); if (tempExpander == agNULL) { DM_DBG1(("dmExpFind: tempExpander is NULL!!!\n")); return agNULL; } DM_DBG3(("dmExpFind: expander id %d\n", tempExpander->id)); DM_DBG3(("dmExpFind: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmExpFind: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo)); if ((tempExpander->dmDevice->SASAddressID.sasAddressHi == sasAddrHi) && (tempExpander->dmDevice->SASAddressID.sasAddressLo == sasAddrLo) && (tempExpander->dmDevice->dmPortContext == onePortContext) ) { DM_DBG3(("dmExpFind: found\n")); return tempExpander; } ExpanderList = ExpanderList->flink; } return agNULL; } osGLOBAL bit32 dmDiscoverCheck( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { DM_DBG3(("dmDiscoverCheck: start\n")); if (onePortContext == agNULL) { DM_DBG1(("dmDiscoverCheck: onePortContext is NULL!!!\n")); return agTRUE; } if (onePortContext->valid == agFALSE) { DM_DBG1(("dmDiscoverCheck: invalid port!!!\n")); return agTRUE; } if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED || onePortContext->discovery.status == DISCOVERY_SAS_DONE ) { DM_DBG1(("dmDiscoverCheck: aborted discovery!!!\n")); tddmDiscoverCB( dmRoot, onePortContext->dmPortContext, dmDiscAborted ); return agTRUE; } return agFALSE; } /* ??? needs to handle pending SMPs move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList */ osGLOBAL void dmDiscoverAbort( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { DM_DBG1(("dmDiscoverAbort: start\n")); if (onePortContext->DiscoveryState == DM_DSTATE_COMPLETED || onePortContext->discovery.status == DISCOVERY_SAS_DONE) { DM_DBG1(("dmDiscoverAbort: not allowed case!!! onePortContext->DiscoveryState 0x%x onePortContext->discovery.status 0x%x\n", onePortContext->DiscoveryState, onePortContext->discovery.status)); return; } onePortContext->DiscoveryState = DM_DSTATE_COMPLETED; onePortContext->discovery.status = DISCOVERY_SAS_DONE; /* move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList */ dmCleanAllExp(dmRoot, onePortContext); return; } /* move from dmAllShared->discoveringExpanderList to dmAllShared->mainExpanderList */ osGLOBAL void dmCleanAllExp( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmList_t *ExpanderList; dmExpander_t *tempExpander; dmExpander_t *oneExpander = agNULL; dmIntPortContext_t *tmpOnePortContext = onePortContext; DM_DBG3(("dmCleanAllExp: start\n")); DM_DBG3(("dmCleanAllExp: pid %d\n", onePortContext->id)); DM_DBG3(("dmCleanAllExp: before all clean up\n")); dmDumpAllFreeExp(dmRoot); /* clean up UpdiscoveringExpanderList*/ DM_DBG3(("dmCleanAllExp: clean discoveringExpanderList\n")); if (!DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList))) { ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink; while (ExpanderList != &(tmpOnePortContext->discovery.discoveringExpanderList)) { tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); if (tempExpander == agNULL) { DM_DBG1(("dmCleanAllExp: tempExpander is NULL!!!\n")); return; } DM_DBG3(("dmCleanAllExp: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmCleanAllExp: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG3(("dmCleanAllExp: exp id %d\n", tempExpander->id)); oneExpander = dmExpMainListFind(dmRoot, tmpOnePortContext, tempExpander->dmDevice->SASAddressID.sasAddressHi, tempExpander->dmDevice->SASAddressID.sasAddressLo); if (oneExpander == agNULL) { DM_DBG3(("dmCleanAllExp: moving\n")); DM_DBG3(("dmCleanAllExp: moving, exp id %d\n", tempExpander->id)); /* putting back to the free pool */ tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); DMLIST_DEQUEUE_THIS(&(tempExpander->linkNode)); // DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->freeExpanderList)); DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->mainExpanderList)); if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.discoveringExpanderList))) { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); break; } else { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } ExpanderList = tmpOnePortContext->discovery.discoveringExpanderList.flink; } else { DM_DBG3(("dmCleanAllExp: in mainExpanderList; skippig\n")); ExpanderList = ExpanderList->flink; } } } else { DM_DBG3(("dmCleanAllExp: empty discoveringExpanderList\n")); } /* reset discoveringExpanderList */ DMLIST_INIT_HDR(&(tmpOnePortContext->discovery.discoveringExpanderList)); /* clean up UpdiscoveringExpanderList*/ DM_DBG3(("dmCleanAllExp: clean UpdiscoveringExpanderList\n")); if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList))) { DM_DBG3(("dmCleanAllExp: empty UpdiscoveringExpanderList\n")); return; } ExpanderList = tmpOnePortContext->discovery.UpdiscoveringExpanderList.flink; while (ExpanderList != &(tmpOnePortContext->discovery.UpdiscoveringExpanderList)) { tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, upNode, ExpanderList); if (tempExpander == agNULL) { DM_DBG1(("dmCleanAllExp: tempExpander is NULL!!!\n")); return; } DM_DBG3(("dmCleanAllExp: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmCleanAllExp: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo)); DM_DBG3(("dmCleanAllExp: exp id %d\n", tempExpander->id)); oneExpander = dmExpMainListFind(dmRoot, tmpOnePortContext, tempExpander->dmDevice->SASAddressID.sasAddressHi, tempExpander->dmDevice->SASAddressID.sasAddressLo); if (oneExpander == agNULL) { DM_DBG3(("dmCleanAllExp: moving\n")); DM_DBG3(("dmCleanAllExp: moving exp id %d\n", tempExpander->id)); tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); DMLIST_DEQUEUE_THIS(&(tempExpander->upNode)); DMLIST_ENQUEUE_AT_TAIL(&(tempExpander->linkNode), &(dmAllShared->mainExpanderList)); if (DMLIST_EMPTY(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList))) { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); break; } else { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } ExpanderList = tmpOnePortContext->discovery.UpdiscoveringExpanderList.flink; } else { DM_DBG3(("dmCleanAllExp: in mainExpanderList; skippig\n")); ExpanderList = ExpanderList->flink; } } /* reset UpdiscoveringExpanderList */ DMLIST_INIT_HDR(&(tmpOnePortContext->discovery.UpdiscoveringExpanderList)); DM_DBG3(("dmCleanAllExp: after all clean up\n")); dmDumpAllFreeExp(dmRoot); return; } osGLOBAL void dmInternalRemovals( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; DM_DBG3(("dmInternalRemovals: start\n")); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList))) { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); DM_DBG3(("dmInternalRemovals: empty device list\n")); return; } else { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); } DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmInternalRemovals: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmInternalRemovals: loop did %d\n", oneDeviceData->id)); DM_DBG3(("dmInternalRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmInternalRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG3(("dmInternalRemovals: valid %d\n", oneDeviceData->valid)); DM_DBG3(("dmInternalRemovals: valid2 %d\n", oneDeviceData->valid2)); DM_DBG3(("dmInternalRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached)); if ( oneDeviceData->dmPortContext == onePortContext) { DM_DBG3(("dmInternalRemovals: right portcontext pid %d\n", onePortContext->id)); if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START) { DM_DBG3(("dmInternalRemovals: incremental discovery\n")); oneDeviceData->valid2 = agFALSE; } else { DM_DBG3(("dmInternalRemovals: full discovery\n")); oneDeviceData->valid = agFALSE; } DeviceListList = DeviceListList->flink; } else { if (oneDeviceData->dmPortContext != agNULL) { DM_DBG3(("dmInternalRemovals: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id)); } else { DM_DBG3(("dmInternalRemovals: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id)); } DeviceListList = DeviceListList->flink; } } return; } osGLOBAL void dmDiscoveryResetProcessed( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; DM_DBG3(("dmDiscoveryResetProcessed: start\n")); /* reinitialize the device data belonging to this portcontext */ DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmDiscoveryResetProcessed: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmDiscoveryResetProcessed: loop did %d\n", oneDeviceData->id)); if (oneDeviceData->dmPortContext == onePortContext) { DM_DBG3(("dmDiscoveryResetProcessed: resetting procssed flag\n")); oneDeviceData->processed = agFALSE; } DeviceListList = DeviceListList->flink; } return; } /* calls osGLOBAL void tddmDiscoverCB( dmRoot_t *dmRoot, dmPortContext_t *dmPortContext, bit32 eventStatus ) */ osGLOBAL void dmDiscoverDone( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, bit32 flag ) { DM_DBG3(("dmDiscoverDone: start\n")); DM_DBG3(("dmDiscoverDone: pid %d\n", onePortContext->id)); /* Set discovery status */ onePortContext->discovery.status = DISCOVERY_SAS_DONE; /* clean up expanders data strucures; move to free exp when device is cleaned */ dmCleanAllExp(dmRoot, onePortContext); dmDumpAllMainExp(dmRoot, onePortContext); dmDiscoveryResetProcessed(dmRoot, onePortContext); dmDiscoveryDumpMCN(dmRoot, onePortContext); if (onePortContext->discovery.SeenBC == agTRUE) { DM_DBG3(("dmDiscoverDone: broadcast change; discover again\n")); dmDiscoveryResetMCN(dmRoot, onePortContext); dmInternalRemovals(dmRoot, onePortContext); /* processed broadcast change */ onePortContext->discovery.SeenBC = agFALSE; if (onePortContext->discovery.ResetTriggerred == agTRUE) { DM_DBG3(("dmDiscoverDone: dmBCTimer\n")); dmBCTimer(dmRoot, onePortContext); } else { dmIncrementalDiscover(dmRoot, onePortContext, agTRUE); } } else { onePortContext->DiscoveryState = DM_DSTATE_COMPLETED; if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_FULL_START) { if (flag == DM_RC_SUCCESS) { dmResetReported(dmRoot, onePortContext ); dmDiscoveryReportMCN(dmRoot, onePortContext ); /* call tddmDiscoverCB() */ tddmDiscoverCB( dmRoot, onePortContext->dmPortContext, dmDiscCompleted ); } else if (flag != DM_RC_SUCCESS || onePortContext->discovery.DeferredError == agTRUE) { onePortContext->DiscoveryState = DM_DSTATE_COMPLETED_WITH_FAILURE; DM_DBG1(("dmDiscoverDone: Error; clean up!!!\n")); dmDiscoveryInvalidateDevices(dmRoot, onePortContext ); tddmDiscoverCB( dmRoot, onePortContext->dmPortContext, dmDiscFailed ); } } else { if (flag == DM_RC_SUCCESS) { dmReportChanges(dmRoot, onePortContext ); dmDiscoveryReportMCN(dmRoot, onePortContext ); tddmDiscoverCB( dmRoot, onePortContext->dmPortContext, dmDiscCompleted ); } else if (flag != DM_RC_SUCCESS || onePortContext->discovery.DeferredError == agTRUE) { onePortContext->DiscoveryState = DM_DSTATE_COMPLETED_WITH_FAILURE; dmDiscoveryInvalidateDevices(dmRoot, onePortContext ); tddmDiscoverCB( dmRoot, onePortContext->dmPortContext, dmDiscFailed ); } } } return; } /* called by dmDiscoveryErrorRemovals() or dmReportRemovals() on discovery failure */ osGLOBAL void dmSubReportRemovals( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmDeviceData_t *oneDeviceData, bit32 flag ) { dmDeviceData_t *oneAttachedExpDeviceData = agNULL; DM_DBG3(("dmSubReportRemovals: start\n")); DM_DBG3(("dmSubReportRemovals: flag 0x%x\n", flag)); if (flag == dmDeviceRemoval) { oneDeviceData->registered = agFALSE; } if (oneDeviceData->ExpDevice != agNULL) { DM_DBG3(("dmSubReportRemovals: attached expander case\n")); oneAttachedExpDeviceData = oneDeviceData->ExpDevice; tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, flag); } else { DM_DBG3(("dmSubReportRemovals: NO attached expander case\n")); tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, flag); } /* this function is called at the end of discovery; reinitializes oneDeviceData->reported */ oneDeviceData->reported = agFALSE; return; } /* called by dmReportChanges() on discovery success */ osGLOBAL void dmSubReportChanges( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmDeviceData_t *oneDeviceData, bit32 flag ) { dmDeviceData_t *oneAttachedExpDeviceData = agNULL; DM_DBG3(("dmSubReportChanges: start\n")); DM_DBG3(("dmSubReportChanges: flag 0x%x\n", flag)); if (flag == dmDeviceRemoval) { oneDeviceData->registered = agFALSE; } if (oneDeviceData->reported == agFALSE) { if (oneDeviceData->ExpDevice != agNULL) { DM_DBG3(("dmSubReportChanges: attached expander case\n")); oneAttachedExpDeviceData = oneDeviceData->ExpDevice; tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, &oneAttachedExpDeviceData->dmDeviceInfo, flag); } else { DM_DBG3(("dmSubReportChanges: NO attached expander case\n")); tddmReportDevice(dmRoot, onePortContext->dmPortContext, &oneDeviceData->dmDeviceInfo, agNULL, flag); } } else { DM_DBG3(("dmSubReportChanges: skip; been reported\n")); } /* this function is called at the end of discovery; reinitializes oneDeviceData->reported */ oneDeviceData->reported = agFALSE; return; } /* should add or remove be reported per device??? */ osGLOBAL void dmReportChanges( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; bit32 added = agFALSE, removed = agFALSE; // dmDeviceData_t *oneAttachedExpDeviceData = agNULL; DM_DBG3(("dmReportChanges: start\n")); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList))) { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); DM_DBG3(("dmReportChanges: empty device list\n")); return; } else { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); } DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmReportChanges: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmReportChanges: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmReportChanges: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); if ( oneDeviceData->dmPortContext == onePortContext) { DM_DBG3(("dmReportChanges: right portcontext\n")); if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi && oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo ) { DM_DBG1(("dmReportChanges: keep, not reporting did 0x%x\n", oneDeviceData->id)); oneDeviceData->valid = agTRUE; oneDeviceData->valid2 = agFALSE; } else if ( (oneDeviceData->valid == agTRUE) && (oneDeviceData->valid2 == agTRUE) ) { DM_DBG3(("dmReportChanges: same\n")); /* reset valid bit */ oneDeviceData->valid = oneDeviceData->valid2; oneDeviceData->valid2 = agFALSE; dmSubReportChanges(dmRoot, onePortContext, oneDeviceData, dmDeviceNoChange); } else if ( (oneDeviceData->valid == agTRUE) && (oneDeviceData->valid2 == agFALSE) ) { DM_DBG3(("dmReportChanges: removed\n")); removed = agTRUE; /* reset valid bit */ oneDeviceData->valid = oneDeviceData->valid2; oneDeviceData->valid2 = agFALSE; onePortContext->RegisteredDevNums--; dmSubReportChanges(dmRoot, onePortContext, oneDeviceData, dmDeviceRemoval); } else if ( (oneDeviceData->valid == agFALSE) && (oneDeviceData->valid2 == agTRUE) ) { DM_DBG3(("dmReportChanges: added\n")); added = agTRUE; /* reset valid bit */ oneDeviceData->valid = oneDeviceData->valid2; oneDeviceData->valid2 = agFALSE; dmSubReportChanges(dmRoot, onePortContext, oneDeviceData, dmDeviceArrival); } else { DM_DBG3(("dmReportChanges: else\n")); } } else { DM_DBG3(("dmReportChanges: different portcontext\n")); } DeviceListList = DeviceListList->flink; } /* osGLOBAL void tddmReportDevice( dmRoot_t *dmRoot, dmPortContext_t *dmPortContext, dmDeviceInfo_t *dmDeviceInfo, dmDeviceInfo_t *dmExpDeviceInfo, bit32 flag ) */ /* arrival or removal at once */ if (added == agTRUE) { DM_DBG3(("dmReportChanges: added at the end\n")); #if 0 /* TBD */ ostiInitiatorEvent( tiRoot, onePortContext->tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceArrival, agNULL ); #endif } if (removed == agTRUE) { DM_DBG3(("dmReportChanges: removed at the end\n")); #if 0 /* TBD */ ostiInitiatorEvent( tiRoot, onePortContext->tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceRemoval, agNULL ); #endif } if (onePortContext->discovery.forcedOK == agTRUE && added == agFALSE && removed == agFALSE) { DM_DBG3(("dmReportChanges: missed chance to report. forced to report OK\n")); onePortContext->discovery.forcedOK = agFALSE; #if 0 /* TBD */ ostiInitiatorEvent( tiRoot, onePortContext->tiPortalContext, agNULL, tiIntrEventTypeDiscovery, tiDiscOK, agNULL ); #endif } if (added == agFALSE && removed == agFALSE) { DM_DBG3(("dmReportChanges: the same\n")); } return; } osGLOBAL void dmReportRemovals( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, bit32 flag ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; bit32 removed = agFALSE; DM_DBG1(("dmReportRemovals: start\n")); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList))) { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); DM_DBG3(("dmReportRemovals: empty device list\n")); return; } else { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); } DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmReportRemovals: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmReportRemovals: loop did %d\n", oneDeviceData->id)); DM_DBG3(("dmReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG3(("dmReportRemovals: valid %d\n", oneDeviceData->valid)); DM_DBG3(("dmReportRemovals: valid2 %d\n", oneDeviceData->valid2)); DM_DBG3(("dmReportRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached)); if ( oneDeviceData->dmPortContext == onePortContext) { DM_DBG3(("dmReportRemovals: right portcontext pid %d\n", onePortContext->id)); if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi && oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo ) { DM_DBG1(("dmReportRemovals: keeping\n")); oneDeviceData->valid = agTRUE; oneDeviceData->valid2 = agFALSE; } else if (oneDeviceData->valid == agTRUE) { DM_DBG3(("dmReportRemovals: removing\n")); /* notify only reported devices to OS layer*/ if ( DEVICE_IS_SSP_TARGET(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData) || DEVICE_IS_SATA_DEVICE(oneDeviceData) ) { removed = agTRUE; } /* all targets except expanders */ DM_DBG3(("dmReportRemovals: did %d\n", oneDeviceData->id)); DM_DBG3(("dmReportRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmReportRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); onePortContext->RegisteredDevNums--; dmSubReportRemovals(dmRoot, onePortContext, oneDeviceData, dmDeviceRemoval); /* reset valid bit */ oneDeviceData->valid = agFALSE; oneDeviceData->valid2 = agFALSE; } /* called by port invalid case */ if (flag == agTRUE) { oneDeviceData->dmPortContext = agNULL; } DeviceListList = DeviceListList->flink; } else { if (oneDeviceData->dmPortContext != agNULL) { DM_DBG3(("dmReportRemovals: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id)); } else { DM_DBG3(("dmReportRemovals: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id)); } DeviceListList = DeviceListList->flink; } } if (removed == agTRUE) { DM_DBG3(("dmReportRemovals: removed at the end\n")); #if 0 /* TBD */ ostiInitiatorEvent( tiRoot, onePortContext->tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceRemoval, agNULL ); #endif } return; } osGLOBAL void dmResetReported( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; DM_DBG3(("dmResetReported: start\n")); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList))) { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); DM_DBG3(("dmResetReported: empty device list\n")); return; } else { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); } DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmResetReported: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmResetReported: loop did %d\n", oneDeviceData->id)); DM_DBG3(("dmResetReported: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmResetReported: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG3(("dmResetReported: valid %d\n", oneDeviceData->valid)); DM_DBG3(("dmResetReported: valid2 %d\n", oneDeviceData->valid2)); DM_DBG3(("dmResetReported: directlyAttached %d\n", oneDeviceData->directlyAttached)); if ( oneDeviceData->dmPortContext == onePortContext) { DM_DBG3(("dmResetReported: right portcontext pid %d\n", onePortContext->id)); oneDeviceData->reported = agFALSE; DeviceListList = DeviceListList->flink; } else { if (oneDeviceData->dmPortContext != agNULL) { DM_DBG3(("dmResetReported: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id)); } else { DM_DBG3(("dmResetReported: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id)); } DeviceListList = DeviceListList->flink; } } return; } /* called on discover failure */ osGLOBAL void dmDiscoveryInvalidateDevices( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; DM_DBG1(("dmDiscoveryInvalidateDevices: start\n")); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList))) { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); DM_DBG3(("dmDiscoveryInvalidateDevices: empty device list\n")); return; } else { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); } DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmDiscoveryInvalidateDevices: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmDiscoveryInvalidateDevices: loop did %d\n", oneDeviceData->id)); DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG3(("dmDiscoveryInvalidateDevices: valid %d\n", oneDeviceData->valid)); DM_DBG3(("dmDiscoveryInvalidateDevices: valid2 %d\n", oneDeviceData->valid2)); DM_DBG3(("dmDiscoveryInvalidateDevices: directlyAttached %d\n", oneDeviceData->directlyAttached)); if ( oneDeviceData->dmPortContext == onePortContext) { DM_DBG3(("dmDiscoveryInvalidateDevices: right portcontext pid %d\n", onePortContext->id)); if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi && oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo ) { DM_DBG1(("dmDiscoveryInvalidateDevices: keeping\n")); oneDeviceData->valid = agTRUE; oneDeviceData->valid2 = agFALSE; } else { oneDeviceData->valid = agFALSE; oneDeviceData->valid2 = agFALSE; oneDeviceData->registered = agFALSE; oneDeviceData->reported = agFALSE; /* all targets other than expanders */ DM_DBG3(("dmDiscoveryInvalidateDevices: did %d\n", oneDeviceData->id)); DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDiscoveryInvalidateDevices: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); onePortContext->RegisteredDevNums--; } DeviceListList = DeviceListList->flink; } else { if (oneDeviceData->dmPortContext != agNULL) { DM_DBG3(("dmDiscoveryInvalidateDevices: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id)); } else { DM_DBG3(("dmDiscoveryInvalidateDevices: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id)); } DeviceListList = DeviceListList->flink; } } return; } /* should DM report the device removal to TDM on an error case? or DM simply removes the devices For now, the second option. */ osGLOBAL void dmDiscoveryErrorRemovals( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; DM_DBG1(("dmDiscoveryErrorRemovals: start\n")); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList))) { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); DM_DBG3(("dmDiscoveryErrorRemovals: empty device list\n")); return; } else { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); } DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmDiscoveryErrorRemovals: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmDiscoveryErrorRemovals: loop did %d\n", oneDeviceData->id)); DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); DM_DBG3(("dmDiscoveryErrorRemovals: valid %d\n", oneDeviceData->valid)); DM_DBG3(("dmDiscoveryErrorRemovals: valid2 %d\n", oneDeviceData->valid2)); DM_DBG3(("dmDiscoveryErrorRemovals: directlyAttached %d\n", oneDeviceData->directlyAttached)); if ( oneDeviceData->dmPortContext == onePortContext) { DM_DBG3(("dmDiscoveryErrorRemovals: right portcontext pid %d\n", onePortContext->id)); if (oneDeviceData->SASAddressID.sasAddressHi == onePortContext->sasRemoteAddressHi && oneDeviceData->SASAddressID.sasAddressLo == onePortContext->sasRemoteAddressLo ) { DM_DBG1(("dmDiscoveryErrorRemovals: keeping\n")); oneDeviceData->valid = agTRUE; oneDeviceData->valid2 = agFALSE; } else { oneDeviceData->valid = agFALSE; oneDeviceData->valid2 = agFALSE; /* all targets other than expanders */ DM_DBG3(("dmDiscoveryErrorRemovals: did %d\n", oneDeviceData->id)); DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDiscoveryErrorRemovals: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); onePortContext->RegisteredDevNums--; dmSubReportRemovals(dmRoot, onePortContext, oneDeviceData, dmDeviceRemoval); } DeviceListList = DeviceListList->flink; } else { if (oneDeviceData->dmPortContext != agNULL) { DM_DBG3(("dmDiscoveryErrorRemovals: different portcontext; oneDeviceData->dmPortContext pid %d oneportcontext pid %d\n", oneDeviceData->dmPortContext->id, onePortContext->id)); } else { DM_DBG3(("dmDiscoveryErrorRemovals: different portcontext; oneDeviceData->dmPortContext pid NULL oneportcontext pid %d\n", onePortContext->id)); } DeviceListList = DeviceListList->flink; } } return; } /* move from dmAllShared->mainExpanderList to dmAllShared->freeExpanderList */ osGLOBAL void dmDiscoveryExpanderCleanUp( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmExpander_t *oneExpander = agNULL; dmList_t *ExpanderList = agNULL; dmDeviceData_t *oneDeviceData = agNULL; DM_DBG3(("dmDiscoveryExpanderCleanUp: start\n")); /* be sure to call osGLOBAL void dmExpanderDeviceDataReInit( dmRoot_t *dmRoot, dmExpander_t *oneExpander ); */ tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); if (!DMLIST_EMPTY(&(dmAllShared->mainExpanderList))) { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); ExpanderList = dmAllShared->mainExpanderList.flink; while (ExpanderList != &(dmAllShared->mainExpanderList)) { oneExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); if (oneExpander == agNULL) { DM_DBG1(("dmDiscoveryExpanderCleanUp: oneExpander is NULL!!!\n")); return; } oneDeviceData = oneExpander->dmDevice; DM_DBG3(("dmDiscoveryExpanderCleanUp: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDiscoveryExpanderCleanUp: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); if ( oneDeviceData->dmPortContext == onePortContext) { dmExpanderDeviceDataReInit(dmRoot, oneExpander); tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); DMLIST_DEQUEUE_THIS(&(oneExpander->linkNode)); DMLIST_ENQUEUE_AT_TAIL(&(oneExpander->linkNode), &(dmAllShared->freeExpanderList)); if (DMLIST_EMPTY(&(dmAllShared->mainExpanderList))) { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); break; } else { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } ExpanderList = dmAllShared->mainExpanderList.flink; } else { ExpanderList = ExpanderList->flink; } } } else { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); DM_DBG3(("dmDiscoveryExpanderCleanUp: empty mainExpanderList\n")); } return; } /* moves all devices from dmAllShared->MainDeviceList to dmAllShared->FreeDeviceList */ osGLOBAL void dmDiscoveryDeviceCleanUp( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; DM_DBG3(("dmDiscoveryDeviceCleanUp: start\n")); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); if (!DMLIST_EMPTY(&(dmAllShared->MainDeviceList))) { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmDiscoveryDeviceCleanUp: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmDiscoveryDeviceCleanUp: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDiscoveryDeviceCleanUp: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); if ( oneDeviceData->dmPortContext == onePortContext) { dmDeviceDataReInit(dmRoot, oneDeviceData); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); DMLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink)); DMLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(dmAllShared->FreeDeviceList)); if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList))) { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); break; } else { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); } onePortContext->RegisteredDevNums--; DeviceListList = dmAllShared->MainDeviceList.flink; } else { DeviceListList = DeviceListList->flink; } } } else { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); DM_DBG3(("dmDiscoveryDeviceCleanUp: empty MainDeviceList\n")); } return; } osGLOBAL void dmDumpAllExp( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { DM_DBG3(("dmDumpAllExp: start\n")); return; } osGLOBAL void dmDumpAllUpExp( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander ) { DM_DBG3(("dmDumpAllUpExp: start\n")); return; } osGLOBAL void dmDumpAllFreeExp( dmRoot_t *dmRoot ) { DM_DBG3(("dmDumpAllFreeExp: start\n")); return; } osGLOBAL void dmDumpAllMainExp( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmList_t *ExpanderList; dmExpander_t *tempExpander; DM_DBG3(("dmDumpAllMainExp: start\n")); tddmSingleThreadedEnter(dmRoot, DM_EXPANDER_LOCK); if (DMLIST_EMPTY(&(dmAllShared->mainExpanderList))) { DM_DBG3(("dmDumpAllMainExp: empty discoveringExpanderList\n")); tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); return; } else { tddmSingleThreadedLeave(dmRoot, DM_EXPANDER_LOCK); } ExpanderList = dmAllShared->mainExpanderList.flink; while (ExpanderList != &(dmAllShared->mainExpanderList)) { tempExpander = DMLIST_OBJECT_BASE(dmExpander_t, linkNode, ExpanderList); if (tempExpander == agNULL) { DM_DBG1(("dmDumpAllMainExp: tempExpander is NULL!!!\n")); return; } DM_DBG3(("dmDumpAllMainExp: expander id %d\n", tempExpander->id)); DM_DBG3(("dmDumpAllMainExp: exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmDumpAllMainExp: exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo)); if ((tempExpander->dmDevice->dmPortContext == onePortContext) ) { DM_DBG3(("dmDumpAllMainExp: found expander id %d\n", tempExpander->id)); DM_DBG3(("dmDumpAllMainExp: found exp addrHi 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressHi)); DM_DBG3(("dmDumpAllMainExp: found exp addrLo 0x%08x\n", tempExpander->dmDevice->SASAddressID.sasAddressLo)); } ExpanderList = ExpanderList->flink; } return; } osGLOBAL void dmDumpAllMainDevice( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; bit32 total = 0, port_total = 0; DM_DBG3(("dmDumpAllMainDevice: start\n")); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); if (DMLIST_EMPTY(&(dmAllShared->MainDeviceList))) { DM_DBG3(("dmDumpAllMainDevice: empty discoveringExpanderList\n")); tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); return; } else { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); } DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG3(("dmDumpAllMainDevice: oneDeviceData is NULL!!!\n")); return; } DM_DBG3(("dmDumpAllMainDevice: oneDeviceData id %d\n", oneDeviceData->id)); DM_DBG3(("dmDumpAllMainDevice: addrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDumpAllMainDevice: addrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); total++; if ((oneDeviceData->dmPortContext == onePortContext) ) { DM_DBG3(("dmDumpAllMainDevice: found oneDeviceData id %d\n", oneDeviceData->id)); DM_DBG3(("dmDumpAllMainDevice: found addrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDumpAllMainDevice: found addrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); port_total++; } DeviceListList = DeviceListList->flink; } DM_DBG3(("dmDumpAllMainDevice: total %d port_totaol %d\n", total, port_total)); return; } osGLOBAL dmDeviceData_t * dmAddSASToSharedcontext( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmSASSubID_t *dmSASSubID, dmDeviceData_t *oneExpDeviceData, bit8 phyID ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; bit32 new_device = agTRUE; DM_DBG3(("dmAddSASToSharedcontext: start\n")); DM_DBG3(("dmAddSASToSharedcontext: oneportContext ID %d\n", onePortContext->id)); if (oneExpDeviceData != agNULL) { DM_DBG3(("dmAddSASToSharedcontext: oneExpDeviceData sasAddressHi 0x%08x sasAddressLo 0x%08x\n", oneExpDeviceData->SASAddressID.sasAddressHi, oneExpDeviceData->SASAddressID.sasAddressLo)); } else { DM_DBG3(("dmAddSASToSharedcontext: oneExpDeviceData is NULL\n")); } /* find a device's existence */ DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmAddSASToSharedcontext: oneDeviceData is NULL!!!\n")); return agNULL; } if ((oneDeviceData->SASAddressID.sasAddressHi == dmSASSubID->sasAddressHi) && (oneDeviceData->SASAddressID.sasAddressLo == dmSASSubID->sasAddressLo) && (oneDeviceData->dmPortContext == onePortContext) ) { DM_DBG3(("dmAddSASToSharedcontext: pid %d did %d\n", onePortContext->id, oneDeviceData->id)); new_device = agFALSE; break; } DeviceListList = DeviceListList->flink; } /* new device */ if (new_device == agTRUE) { DM_DBG3(("dmAddSASToSharedcontext: new device\n")); DM_DBG3(("dmAddSASToSharedcontext: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", dmSASSubID->sasAddressHi, dmSASSubID->sasAddressLo)); tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); if (!DMLIST_NOT_EMPTY(&(dmAllShared->FreeDeviceList))) { tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); DM_DBG1(("dmAddSASToSharedcontext: empty DeviceData FreeLink\n")); dmDumpAllMainDevice(dmRoot, onePortContext); return agNULL; } DMLIST_DEQUEUE_FROM_HEAD(&DeviceListList, &(dmAllShared->FreeDeviceList)); tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, FreeLink, DeviceListList); if (oneDeviceData != agNULL) { DM_DBG3(("dmAddSASToSharedcontext: oneDeviceData %p pid %d did %d\n", oneDeviceData, onePortContext->id, oneDeviceData->id)); onePortContext->Count++; oneDeviceData->dmRoot = dmRoot; /* saving sas address */ oneDeviceData->SASAddressID.sasAddressLo = dmSASSubID->sasAddressLo; oneDeviceData->SASAddressID.sasAddressHi = dmSASSubID->sasAddressHi; oneDeviceData->initiator_ssp_stp_smp = dmSASSubID->initiator_ssp_stp_smp; oneDeviceData->target_ssp_stp_smp = dmSASSubID->target_ssp_stp_smp; oneDeviceData->dmPortContext = onePortContext; /* handles both SAS target and STP-target, SATA-device */ if (!DEVICE_IS_SATA_DEVICE(oneDeviceData) && !DEVICE_IS_STP_TARGET(oneDeviceData)) { oneDeviceData->DeviceType = DM_SAS_DEVICE; } else { oneDeviceData->DeviceType = DM_SATA_DEVICE; } if (oneExpDeviceData != agNULL) { oneDeviceData->ExpDevice = oneExpDeviceData; } /* set phyID only when it has initial value of 0xFF */ if (oneDeviceData->phyID == 0xFF) { oneDeviceData->phyID = phyID; } /* incremental discovery */ /* add device to incremental-related link. Report using this link when incremental discovery is done */ if (onePortContext->DiscoveryState == DM_DSTATE_NOT_STARTED) { DM_DBG3(("dmAddSASToSharedcontext: DM_DSTATE_NOT_STARTED\n")); DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); oneDeviceData->valid = agTRUE; } else { if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START) { DM_DBG3(("dmAddSASToSharedcontext: incremental discovery\n")); DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); oneDeviceData->valid2 = agTRUE; } else { DM_DBG3(("dmAddSASToSharedcontext: full discovery\n")); DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); oneDeviceData->valid = agTRUE; } } /* add the devicedata to the portcontext */ tddmSingleThreadedEnter(dmRoot, DM_DEVICE_LOCK); DMLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->MainLink), &(dmAllShared->MainDeviceList)); tddmSingleThreadedLeave(dmRoot, DM_DEVICE_LOCK); DM_DBG3(("dmAddSASToSharedcontext: one case pid %d did %d \n", onePortContext->id, oneDeviceData->id)); DM_DBG3(("dmAddSASToSharedcontext: new case pid %d did %d phyID %d\n", onePortContext->id, oneDeviceData->id, oneDeviceData->phyID)); } } else /* old device */ { DM_DBG3(("dmAddSASToSharedcontext: old device\n")); DM_DBG3(("dmAddSASToSharedcontext: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); DM_DBG3(("dmAddSASToSharedcontext: sasAddressHi 0x%08x sasAddressLo 0x%08x\n", dmSASSubID->sasAddressHi, dmSASSubID->sasAddressLo)); oneDeviceData->dmRoot = dmRoot; /* saving sas address */ oneDeviceData->SASAddressID.sasAddressLo = dmSASSubID->sasAddressLo; oneDeviceData->SASAddressID.sasAddressHi = dmSASSubID->sasAddressHi; oneDeviceData->initiator_ssp_stp_smp = dmSASSubID->initiator_ssp_stp_smp; oneDeviceData->target_ssp_stp_smp = dmSASSubID->target_ssp_stp_smp; oneDeviceData->dmPortContext = onePortContext; /* handles both SAS target and STP-target, SATA-device */ if (!DEVICE_IS_SATA_DEVICE(oneDeviceData) && !DEVICE_IS_STP_TARGET(oneDeviceData)) { oneDeviceData->DeviceType = DM_SAS_DEVICE; } else { oneDeviceData->DeviceType = DM_SATA_DEVICE; } if (oneExpDeviceData != agNULL) { oneDeviceData->ExpDevice = oneExpDeviceData; } /* set phyID only when it has initial value of 0xFF */ if (oneDeviceData->phyID == 0xFF) { oneDeviceData->phyID = phyID; } if (onePortContext->DiscoveryState == DM_DSTATE_NOT_STARTED) { DM_DBG3(("dmAddSASToSharedcontext: DM_DSTATE_NOT_STARTED\n")); DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); oneDeviceData->valid = agTRUE; } else { if (onePortContext->discovery.type == DM_DISCOVERY_OPTION_INCREMENTAL_START) { DM_DBG3(("dmAddSASToSharedcontext: incremental discovery\n")); DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); oneDeviceData->valid2 = agTRUE; } else { DM_DBG3(("dmAddSASToSharedcontext: full discovery\n")); DM_DBG3(("dmAddSASToSharedcontext: sasAddrHi 0x%08x \n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmAddSASToSharedcontext: sasAddrLo 0x%08x \n", oneDeviceData->SASAddressID.sasAddressLo)); oneDeviceData->valid = agTRUE; } } DM_DBG3(("dmAddSASToSharedcontext: old case pid %d did %d phyID %d\n", onePortContext->id, oneDeviceData->id, oneDeviceData->phyID)); } return oneDeviceData; } /* no checking of valid and valid2 */ osGLOBAL dmDeviceData_t * dmDeviceFind( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, bit32 sasAddrHi, bit32 sasAddrLo ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDeviceData_t *oneDeviceData = agNULL; dmList_t *DeviceListList; bit32 found = agFALSE; DM_DBG3(("dmDeviceFind: start\n")); /* find a device's existence */ DeviceListList = dmAllShared->MainDeviceList.flink; while (DeviceListList != &(dmAllShared->MainDeviceList)) { oneDeviceData = DMLIST_OBJECT_BASE(dmDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { DM_DBG1(("dmDeviceFind: oneDeviceData is NULL!!!\n")); return agNULL; } if ((oneDeviceData->SASAddressID.sasAddressHi == sasAddrHi) && (oneDeviceData->SASAddressID.sasAddressLo == sasAddrLo) && // (oneDeviceData->valid == agTRUE) && (oneDeviceData->dmPortContext == onePortContext) ) { DM_DBG3(("dmDeviceFind: Found pid %d did %d\n", onePortContext->id, oneDeviceData->id)); DM_DBG3(("dmDeviceFind: sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); DM_DBG3(("dmDeviceFind: sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); found = agTRUE; break; } DeviceListList = DeviceListList->flink; } if (found == agFALSE) { DM_DBG3(("dmDeviceFind: end returning NULL\n")); return agNULL; } else { DM_DBG3(("dmDeviceFind: end returning NOT NULL\n")); return oneDeviceData; } } osGLOBAL void dmBCTimer( dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDiscovery_t *discovery; DM_DBG3(("dmBCTimer: start\n")); discovery = &(onePortContext->discovery); tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->BCTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->BCTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } if (onePortContext->valid == agTRUE) { dmSetTimerRequest( dmRoot, &discovery->BCTimer, BC_TIMER_VALUE/dmAllShared->usecsPerTick, dmBCTimerCB, onePortContext, agNULL, agNULL ); dmAddTimer( dmRoot, &dmAllShared->timerlist, &discovery->BCTimer ); } return; } osGLOBAL void dmBCTimerCB( dmRoot_t * dmRoot, void * timerData1, void * timerData2, void * timerData3 ) { dmIntPortContext_t *onePortContext; dmDiscovery_t *discovery; DM_DBG3(("dmBCTimerCB: start\n")); onePortContext = (dmIntPortContext_t *)timerData1; discovery = &(onePortContext->discovery); tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->BCTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->BCTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } discovery->ResetTriggerred = agFALSE; if (onePortContext->valid == agTRUE) { dmDiscover(dmRoot, onePortContext->dmPortContext, DM_DISCOVERY_OPTION_INCREMENTAL_START ); } return; } /* discovery related SMP timers */ osGLOBAL void dmDiscoverySMPTimer(dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, bit32 functionCode, dmSMPRequestBody_t *dmSMPRequestBody ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDiscovery_t *discovery; DM_DBG3(("dmDiscoverySMPTimer: start\n")); DM_DBG3(("dmDiscoverySMPTimer: pid %d SMPFn 0x%x\n", onePortContext->id, functionCode)); /* start the SMP timer which works as SMP application timer */ discovery = &(onePortContext->discovery); tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->DiscoverySMPTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->DiscoverySMPTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } dmSetTimerRequest( dmRoot, &discovery->DiscoverySMPTimer, SMP_TIMER_VALUE/dmAllShared->usecsPerTick, dmDiscoverySMPTimerCB, onePortContext, dmSMPRequestBody, agNULL ); dmAddTimer ( dmRoot, &dmAllShared->timerlist, &discovery->DiscoverySMPTimer ); return; } osGLOBAL void dmDiscoverySMPTimerCB( dmRoot_t * dmRoot, void * timerData1, void * timerData2, void * timerData3 ) { agsaRoot_t *agRoot; dmIntPortContext_t *onePortContext; bit8 SMPFunction; #ifndef DIRECT_SMP dmSMPFrameHeader_t *dmSMPFrameHeader; bit8 smpHeader[4]; #endif dmSMPRequestBody_t *dmSMPRequestBody; dmDiscovery_t *discovery; dmDeviceData_t *oneDeviceData; agsaIORequest_t *agAbortIORequest = agNULL; agsaIORequest_t *agToBeAbortIORequest = agNULL; dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmExpander_t *oneExpander = agNULL; dmSMPRequestBody_t *dmAbortSMPRequestBody = agNULL; dmList_t *SMPList; DM_DBG1(("dmDiscoverySMPTimerCB: start!!!\n")); onePortContext = (dmIntPortContext_t *)timerData1; dmSMPRequestBody = (dmSMPRequestBody_t *)timerData2; discovery = &(onePortContext->discovery); oneDeviceData = dmSMPRequestBody->dmDevice; agToBeAbortIORequest = &(dmSMPRequestBody->agIORequest); agRoot = dmAllShared->agRoot; #ifdef DIRECT_SMP SMPFunction = dmSMPRequestBody->smpPayload[1]; #else saFrameReadBlock(agRoot, dmSMPRequestBody->IndirectSMP, 0, smpHeader, 4); dmSMPFrameHeader = (dmSMPFrameHeader_t *)smpHeader; SMPFunction = dmSMPFrameHeader->smpFunction; #endif DM_DBG3(("dmDiscoverySMPTimerCB: SMP function 0x%x\n", SMPFunction)); tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->DiscoverySMPTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->DiscoverySMPTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } //for debugging // saGetPendingPICI(agRoot); switch (SMPFunction) { case SMP_REPORT_GENERAL: /* fall through */ case SMP_DISCOVER: /* fall through */ case SMP_CONFIGURE_ROUTING_INFORMATION: /* fall through */ DM_DBG1(("dmDiscoverySMPTimerCB: failing discovery, SMP function 0x%x !!!\n", SMPFunction)); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); return; /* no more things to do */ case SMP_REPORT_PHY_SATA: DM_DBG1(("dmDiscoverySMPTimerCB: failing discovery, SMP function SMP_REPORT_PHY_SATA !!!\n")); dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); break; default: /* do nothing */ DM_DBG1(("dmDiscoverySMPTimerCB: Error, not allowed case!!!\n")); break; } if (oneDeviceData->registered == agTRUE && (oneDeviceData->valid == agTRUE || oneDeviceData->valid2 == agTRUE) ) { /* call to saSMPAbort(one) */ /* get an smp REQUEST from the free list */ tddmSingleThreadedEnter(dmRoot, DM_SMP_LOCK); if (DMLIST_EMPTY(&(dmAllShared->freeSMPList))) { DM_DBG1(("dmDiscoverySMPTimerCB: no free SMP, can't abort SMP!!!\n")); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); return; } else { DMLIST_DEQUEUE_FROM_HEAD(&SMPList, &(dmAllShared->freeSMPList)); tddmSingleThreadedLeave(dmRoot, DM_SMP_LOCK); dmAbortSMPRequestBody = DMLIST_OBJECT_BASE(dmSMPRequestBody_t, Link, SMPList); if (dmAbortSMPRequestBody == agNULL) { DM_DBG1(("dmDiscoverySMPTimerCB: dmAbortSMPRequestBody is NULL!!!\n")); return; } DM_DBG5(("dmDiscoverySMPTimerCB: SMP id %d\n", dmAbortSMPRequestBody->id)); } dmAbortSMPRequestBody->dmRoot = dmRoot; agAbortIORequest = &(dmAbortSMPRequestBody->agIORequest); agAbortIORequest->osData = (void *) dmAbortSMPRequestBody; agAbortIORequest->sdkData = agNULL; /* SALL takes care of this */ oneExpander = oneDeviceData->dmExpander; DM_DBG1(("dmDiscoverySMPTimerCB: calling saSMPAbort!!!\n")); saSMPAbort(agRoot, agAbortIORequest, 0, oneExpander->agDevHandle, 0, /* abort one */ agToBeAbortIORequest, dmSMPAbortCB ); } return; } osGLOBAL void dmSMPBusyTimer(dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmDeviceData_t *oneDeviceData, dmSMPRequestBody_t *dmSMPRequestBody ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDiscovery_t *discovery; DM_DBG3(("dmSMPBusyTimer: start\n")); DM_DBG3(("dmSMPBusyTimer: pid %d\n", onePortContext->id)); discovery = &(onePortContext->discovery); tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->SMPBusyTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->SMPBusyTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } dmSetTimerRequest( dmRoot, &discovery->SMPBusyTimer, SMP_BUSY_TIMER_VALUE/dmAllShared->usecsPerTick, dmSMPBusyTimerCB, onePortContext, oneDeviceData, dmSMPRequestBody ); dmAddTimer ( dmRoot, &dmAllShared->timerlist, &discovery->SMPBusyTimer ); return; } osGLOBAL void dmSMPBusyTimerCB( dmRoot_t * dmRoot, void * timerData1, void * timerData2, void * timerData3 ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; agsaRoot_t *agRoot; dmIntPortContext_t *onePortContext; dmDeviceData_t *oneDeviceData; dmSMPRequestBody_t *dmSMPRequestBody; agsaSASRequestBody_t *agSASRequestBody; agsaIORequest_t *agIORequest; agsaDevHandle_t *agDevHandle; dmDiscovery_t *discovery; bit32 status = AGSA_RC_FAILURE; dmExpander_t *oneExpander = agNULL; DM_DBG3(("dmSMPBusyTimerCB: start\n")); onePortContext = (dmIntPortContext_t *)timerData1; oneDeviceData = (dmDeviceData_t *)timerData2; dmSMPRequestBody = (dmSMPRequestBody_t *)timerData3; agRoot = dmAllShared->agRoot; agIORequest = &(dmSMPRequestBody->agIORequest); oneExpander = oneDeviceData->dmExpander; agDevHandle = oneExpander->agDevHandle; agSASRequestBody = &(dmSMPRequestBody->agSASRequestBody); discovery = &(onePortContext->discovery); discovery->SMPRetries++; if (discovery->SMPRetries < SMP_BUSY_RETRIES) { status = saSMPStart( agRoot, agIORequest, 0, agDevHandle, AGSA_SMP_INIT_REQ, agSASRequestBody, &dmsaSMPCompleted ); } if (status == AGSA_RC_SUCCESS) { discovery->SMPRetries = 0; tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->SMPBusyTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->SMPBusyTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } } else if (status == AGSA_RC_FAILURE) { tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->SMPBusyTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->SMPBusyTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } discovery->SMPRetries = 0; dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else /* AGSA_RC_BUSY */ { if (discovery->SMPRetries >= SMP_BUSY_RETRIES) { /* done with retris; give up */ DM_DBG3(("dmSMPBusyTimerCB: retries are over\n")); tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->SMPBusyTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->SMPBusyTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } discovery->SMPRetries = 0; dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); } else { /* keep retrying */ dmSMPBusyTimer(dmRoot, onePortContext, oneDeviceData, dmSMPRequestBody); } } return; } /* expander configuring timer */ osGLOBAL void dmDiscoveryConfiguringTimer(dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmDeviceData_t *oneDeviceData ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDiscovery_t *discovery; DM_DBG3(("dmDiscoveryConfiguringTimer: start\n")); DM_DBG3(("dmDiscoveryConfiguringTimer: pid %d\n", onePortContext->id)); discovery = &(onePortContext->discovery); tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->discoveryTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->discoveryTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } DM_DBG3(("dmDiscoveryConfiguringTimer: UsecsPerTick %d\n", dmAllShared->usecsPerTick)); DM_DBG3(("dmDiscoveryConfiguringTimer: Timervalue %d\n", DISCOVERY_CONFIGURING_TIMER_VALUE/dmAllShared->usecsPerTick)); dmSetTimerRequest( dmRoot, &discovery->discoveryTimer, DISCOVERY_CONFIGURING_TIMER_VALUE/dmAllShared->usecsPerTick, dmDiscoveryConfiguringTimerCB, onePortContext, oneDeviceData, agNULL ); dmAddTimer ( dmRoot, &dmAllShared->timerlist, &discovery->discoveryTimer ); return; } osGLOBAL void dmDiscoveryConfiguringTimerCB( dmRoot_t * dmRoot, void * timerData1, void * timerData2, void * timerData3 ) { dmIntPortContext_t *onePortContext = agNULL; dmDiscovery_t *discovery = agNULL; dmDeviceData_t *oneDeviceData = agNULL; onePortContext = (dmIntPortContext_t *)timerData1; oneDeviceData = (dmDeviceData_t *)timerData2; discovery = &(onePortContext->discovery); DM_DBG3(("dmDiscoveryConfiguringTimerCB: start\n")); tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->discoveryTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->discoveryTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } if (oneDeviceData->valid == agTRUE || oneDeviceData->valid2 == agTRUE) { dmReportGeneralSend(dmRoot, oneDeviceData); } return; } osGLOBAL void dmConfigureRouteTimer(dmRoot_t *dmRoot, dmIntPortContext_t *onePortContext, dmExpander_t *oneExpander, smpRespDiscover_t *pdmSMPDiscoverResp, smpRespDiscover2_t *pdmSMPDiscover2Resp ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmDiscovery_t *discovery; DM_DBG3(("dmConfigureRouteTimer: start\n")); DM_DBG3(("dmConfigureRouteTimer: pid %d\n", onePortContext->id)); discovery = &(onePortContext->discovery); DM_DBG3(("dmConfigureRouteTimer: onePortContext %p oneExpander %p pdmSMPDiscoverResp %p\n", onePortContext, oneExpander, pdmSMPDiscoverResp)); DM_DBG3(("dmConfigureRouteTimer: discovery %p \n", discovery)); DM_DBG3(("dmConfigureRouteTimer: pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries)); DM_DBG3(("dmConfigureRouteTimer: discovery->status %d\n", discovery->status)); tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->configureRouteTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->configureRouteTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } DM_DBG3(("dmConfigureRouteTimer: UsecsPerTick %d\n", dmAllShared->usecsPerTick)); DM_DBG3(("dmConfigureRouteTimer: Timervalue %d\n", CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick)); if (oneExpander->SAS2 == 0) { /* SAS 1.1 */ dmSetTimerRequest( dmRoot, &discovery->configureRouteTimer, CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick, dmConfigureRouteTimerCB, (void *)onePortContext, (void *)oneExpander, (void *)pdmSMPDiscoverResp ); } else { /* SAS 2 */ dmSetTimerRequest( dmRoot, &discovery->configureRouteTimer, CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick, dmConfigureRouteTimerCB, (void *)onePortContext, (void *)oneExpander, (void *)pdmSMPDiscover2Resp ); } dmAddTimer ( dmRoot, &dmAllShared->timerlist, &discovery->configureRouteTimer ); return; } osGLOBAL void dmConfigureRouteTimerCB( dmRoot_t * dmRoot, void * timerData1, void * timerData2, void * timerData3 ) { dmIntRoot_t *dmIntRoot = (dmIntRoot_t *)dmRoot->dmData; dmIntContext_t *dmAllShared = (dmIntContext_t *)&dmIntRoot->dmAllShared; dmIntPortContext_t *onePortContext; dmExpander_t *oneExpander; smpRespDiscover_t *pdmSMPDiscoverResp = agNULL; smpRespDiscover2_t *pdmSMPDiscover2Resp = agNULL; dmDiscovery_t *discovery; DM_DBG3(("dmConfigureRouteTimerCB: start\n")); onePortContext = (dmIntPortContext_t *)timerData1; oneExpander = (dmExpander_t *)timerData2; if (oneExpander->SAS2 == 0) { pdmSMPDiscoverResp = (smpRespDiscover_t *)timerData3; } else { pdmSMPDiscover2Resp = (smpRespDiscover2_t *)timerData3; } discovery = &(onePortContext->discovery); DM_DBG3(("dmConfigureRouteTimerCB: onePortContext %p oneExpander %p pdmSMPDiscoverResp %p\n", onePortContext, oneExpander, pdmSMPDiscoverResp)); DM_DBG3(("dmConfigureRouteTimerCB: discovery %p\n", discovery)); DM_DBG3(("dmConfigureRouteTimerCB: pid %d configureRouteRetries %d\n", onePortContext->id, discovery->configureRouteRetries)); DM_DBG3(("dmConfigureRouteTimerCB: discovery.status %d\n", discovery->status)); discovery->configureRouteRetries++; if (discovery->configureRouteRetries >= dmAllShared->MaxRetryDiscovery) { DM_DBG3(("dmConfigureRouteTimerCB: retries are over\n")); tddmSingleThreadedEnter(dmRoot, DM_TIMER_LOCK); if (discovery->configureRouteTimer.timerRunning == agTRUE) { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); dmKillTimer( dmRoot, &discovery->configureRouteTimer ); } else { tddmSingleThreadedLeave(dmRoot, DM_TIMER_LOCK); } discovery->configureRouteRetries = 0; /* failed the discovery */ dmDiscoverDone(dmRoot, onePortContext, DM_RC_FAILURE); return; } if (oneExpander->SAS2 == 0) { if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { DM_DBG3(("dmConfigureRouteTimerCB: proceed by calling dmDownStreamDiscoverExpanderPhy\n")); dmhexdump("dmConfigureRouteTimerCB", (bit8*)pdmSMPDiscoverResp, sizeof(smpRespDiscover_t)); discovery->configureRouteRetries = 0; dmDownStreamDiscoverExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscoverResp); } else { DM_DBG3(("dmConfigureRouteTimerCB: setting timer again\n")); /* set the timer again */ dmSetTimerRequest( dmRoot, &discovery->configureRouteTimer, CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick, dmConfigureRouteTimerCB, (void *)onePortContext, (void *)oneExpander, (void *)pdmSMPDiscoverResp ); dmAddTimer ( dmRoot, &dmAllShared->timerlist, &discovery->configureRouteTimer ); } } /* SAS 1.1 */ else { /* SAS 2 */ if (onePortContext->discovery.status == DISCOVERY_DOWN_STREAM) { DM_DBG2(("dmConfigureRouteTimerCB: proceed by calling dmDownStreamDiscover2ExpanderPhy\n")); dmhexdump("dmConfigureRouteTimerCB", (bit8*)pdmSMPDiscover2Resp, sizeof(smpRespDiscover2_t)); dmDownStreamDiscover2ExpanderPhy(dmRoot, onePortContext, oneExpander, pdmSMPDiscover2Resp); } else { DM_DBG2(("dmConfigureRouteTimerCB: setting timer again\n")); /* set the timer again */ dmSetTimerRequest( dmRoot, &discovery->configureRouteTimer, CONFIGURE_ROUTE_TIMER_VALUE/dmAllShared->usecsPerTick, dmConfigureRouteTimerCB, (void *)onePortContext, (void *)oneExpander, (void *)pdmSMPDiscover2Resp ); dmAddTimer ( dmRoot, &dmAllShared->timerlist, &discovery->configureRouteTimer ); } } return; } #endif /* FDS_ DM */