📄 core_api.c
字号:
PDomain_Expander pExp; PMV_Request pOrgReq = (PMV_Request)pReq->Org_Req; struct SMPResponse *pSMPResp = (struct SMPResponse *)pReq->Data_Buffer; MV_U8 phyIndex = (MV_U8)pReq->Req_Flag; pExp = &pCore->Expanders[MapDeviceId(pCore, pExpInfo->Link.Self.DevID)]; if( pSMPResp->Function == DISCOVER ) { pExpInfo->Link.Self.PhyID[phyIndex] = pSMPResp->Response.Discover.AttachedPhyIdentifier; if( phyIndex == 0 ) { // only need to store the SAS address once, should be the same for all parent phys MV_CopyMemory( pExpInfo->Link.Parent.SAS_Address, pSMPResp->Response.Discover.SASAddress, 8 ); } FreeSMPScratchToPool( pCore, (PSMP_Scratch_Buffer)pReq->Scratch_Buffer ); FreeInternalReqToPool( pCore, pReq ); if( phyIndex == pExpInfo->Link.Self.PhyCnt-1 ) Core_GetExpInformationHardware( pCore, pExp, pExpInfo, pOrgReq, REPORT_GENERAL, 0 ); else Core_GetExpInformationHardware( pCore, pExp, pExpInfo, pOrgReq, DISCOVER, phyIndex+1 ); return; } else if( pSMPResp->Function == REPORT_GENERAL ) { pExpInfo->Configuring = pSMPResp->Response.ReportGeneral.Configuring; MV_CopyMemory( &pExpInfo->ExpChangeCount, pSMPResp->Response.ReportGeneral.ExpanderChangeCount, 2 ); FreeSMPScratchToPool( pCore, (PSMP_Scratch_Buffer)pReq->Scratch_Buffer ); FreeInternalReqToPool( pCore, pReq ); pCore->Scratch_Count2++; /* convert SAS addr to little-endian */ if (pExpInfo->Link.Parent.SAS_Address[0] != 0x50) mv_swap_bytes(pExpInfo->Link.Parent.SAS_Address, 8); if (pExpInfo->Link.Self.SAS_Address[0] != 0x50) mv_swap_bytes(pExpInfo->Link.Self.SAS_Address, 8); if (pCore->Scratch_Count2 == pCore->Scratch_Count1) CompleteRequest(pCore, pOrgReq, 0); }}void Core_GetExpInformationHardware( PCore_Driver_Extension pCore, PDomain_Expander pExp, PExp_Info pExpInfo, PMV_Request pReq, MV_U8 requestType, MV_U8 phyIndex ){ PMV_Request pNewReq = GetInternalReqFromPool(pCore); PSMP_Scratch_Buffer pSMPSB; struct SMPRequest *pSMPReq; PMV_SG_Table pSGTable; if( pNewReq == NULL ) { MV_DPRINT(("ERROR: No more free internal requests. Request aborted.\n")); return; } pSMPSB = GetSMPScratchFromPool(pCore); if( pSMPSB == NULL ) { FreeInternalReqToPool(pCore, pReq); MV_DPRINT(("ERROR: No more free SMP scratch buffer. Request aborted.\n")); return; } pSGTable = &pReq->SG_Table; /* Prepare identify ATA task */ pNewReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC; pNewReq->Cdb[1] = CDB_CORE_MODULE; pNewReq->Cdb[2] = CDB_CORE_SMP; pNewReq->Tag = 0xbb; pNewReq->Device_Id = (requestType == DISCOVER) ? pExp->pParent->ExpId : pExp->ExpId; pNewReq->Cmd_Initiator = pCore; pNewReq->Data_Transfer_Length = sizeof(struct SMPRequest); pNewReq->Data_Buffer = &pSMPSB->SMP_Req; pNewReq->Org_Req = pReq;#ifndef CORE_SAS_SUPPORT_ATA_COMMAND pNewReq->Context[MODULE_CORE] = pExpInfo;#else ((PCORE_CONTEXT)(pNewReq->Context[MODULE_CORE]))->u.cdb.Data_Buffer = pExpInfo;#endif /* CORE_SAS_SUPPORT_ATA_COMMAND */ pNewReq->Scratch_Buffer = pSMPSB; pSMPReq = (struct SMPRequest *)pNewReq->Data_Buffer; pSMPReq->Function = requestType; if( requestType == DISCOVER ) { // send discover on every phy; use Req_Flag to keep track of what phy we're on pSMPReq->Request.Discover.PhyIdentifier = pExp->ParentPhyId[phyIndex]; pNewReq->Req_Flag = phyIndex; } pSMPReq->SMPFrameType = SMP_REQUEST_FRAME; pNewReq->Completion = (void(*)(MV_PVOID,PMV_Request))Core_GetExpInformationCallback; /* Make SG table */ SGTable_Init(pSGTable, 0); /* Send this internal request */ Core_ModuleSendRequest(pCore, pNewReq);}MV_VOIDCore_GetExpInformation( PCore_Driver_Extension pCore, IN PDomain_Expander pExp, OUT PExp_Info pExpInfo, IN PMV_Request pReq ){ MV_U8 i, phyId=0; pExpInfo->Link.Self.DevType = DEVICE_TYPE_EXPANDER; pExpInfo->Link.Self.DevID = pExp->ExpId; pExpInfo->Link.Self.PhyCnt = pExp->ParentPhyCount; MV_CopyMemory( pExpInfo->Link.Self.SAS_Address, &pExp->SASAddr.value, 8 ); if( pExp->pParent != NULL ) { pExpInfo->Link.Parent.DevType = DEVICE_TYPE_EXPANDER; pExpInfo->Link.Parent.DevID = pExp->pParent->ExpId; } else if( pExp->pPort != NULL ) { for( i=0; i<pCore->Phy_Num; i++ ) { if( pExp->pPort->MemberPhyMap & MV_BIT(i) ) { pExpInfo->Link.Self.PhyID[phyId] = (MV_U8)(pCore->Phy[i].AttDevInfo >> 24); phyId++; } } pExpInfo->Link.Parent.DevType = DEVICE_TYPE_PORT; pExpInfo->Link.Parent.DevID = pExp->pPort->Id; MV_CopyMemory( pExpInfo->Link.Parent.SAS_Address, &pExp->SASAddr, 8 ); } pExpInfo->Link.Parent.PhyCnt = pExp->ParentPhyCount; MV_CopyMemory( pExpInfo->Link.Parent.PhyID, pExp->ParentPhyId, 8 ); pExpInfo->RouteTableConfigurable = pExp->configurable_route_table; pExpInfo->PhyCount = pExp->Phy_Count; pExpInfo->MaxRouteIndexes = (MV_U16)pExp->Route_Index_Count; /* the following is dummy code for now - later will merge with official discovery engine and it will provide the needed info */ pExpInfo->ComponentID = pExp->ComponentID; pExpInfo->ComponentRevisionID = pExp->ComponentRevisionID; MV_CopyMemory( pExpInfo->ComponentVendorID, pExp->ComponentVendorID, 8 ); MV_CopyMemory( pExpInfo->VendorID, pExp->VendorID, 8 ); MV_CopyMemory( pExpInfo->ProductID, pExp->ProductID, 16 ); MV_CopyMemory( pExpInfo->ProductRev, pExp->ProductRev, 4 ); /* Following info needs hardware access, will obtain through REPORT_GENERAL MV_BOOLEAN Configuring; MV_U16 ExpChangeCount; */ /* if parent is an expander, we first issue DISCOVER, then REPORT_GENERAL otherwise, skip DISCOVER */ if( pExp->pParent != NULL ) Core_GetExpInformationHardware( pCore, pExp, pExpInfo, pReq, DISCOVER, 0 ); else Core_GetExpInformationHardware( pCore, pExp, pExpInfo, pReq, REPORT_GENERAL, 0 );} #ifdef SUPPORT_PMMV_VOIDCore_GetPMInformation( PCore_Driver_Extension pCore, IN PDomain_Port pPort, OUT PPM_Info pPM ){ PDomain_PM pPortMultiplier; pPM->Link.Self.DevType = DEVICE_TYPE_PM; pPM->Link.Self.DevID = pPort->Id; pPM->Link.Self.PhyCnt = 1; pPM->Link.Self.PhyID[0] = pPort->Id; pPM->Link.Parent.DevType = DEVICE_TYPE_PORT; pPM->Link.Parent.DevID = 0; pPM->Link.Parent.PhyCnt = 1; pPM->Link.Parent.PhyID[0] = pPort->Id; pPortMultiplier = pPort->pPM; pPM->VendorId = pPortMultiplier->VendorId; pPM->DeviceId = pPortMultiplier->DeviceId; pPM->ProductRevision = pPortMultiplier->ProductRevision; pPM->PMSpecRevision = pPortMultiplier->SpecRevision; pPM->NumberOfPorts = pPortMultiplier->NumberOfPorts;}#endif /* SUPPORT_PM */#ifndef BIOS_NOT_SUPPORTMV_VOIDCore_GetHDConfiguration( PCore_Driver_Extension pCore, IN PDomain_Port pPort, IN PDomain_Device pDevice, OUT PHD_Config pHD ){ if ( !(pDevice->Status & DEVICE_STATUS_FUNCTIONAL) ) { pHD->HDID = 0xFF; return; } pHD->HDID = pDevice->Id ; if (pDevice->Setting & DEVICE_SETTING_WRITECACHE_ENABLED) pHD->WriteCacheOn = MV_TRUE; else pHD->WriteCacheOn = MV_FALSE; if ( pDevice->Setting & DEVICE_SETTING_SMART_ENABLED ) pHD->SMARTOn = MV_TRUE; else pHD->SMARTOn = MV_FALSE; if ( pDevice->NegotiatedLinkRate == PHY_LINKRATE_3 ) pHD->DriveSpeed = HD_SPEED_3G; else pHD->DriveSpeed = HD_SPEED_1_5G;}#endif /* #ifndef BIOS_NOT_SUPPORT */MV_BOOLEAN core_pd_request_get_HD_info(PCore_Driver_Extension pCore, PMV_Request pMvReq){ PHD_Info pHDInfo = (PHD_Info)pMvReq->Data_Buffer; MV_U16 HDID; #ifdef DEBUG_BIOS //MV_DUMP32(0xCCCCEEE1);#endif MV_CopyMemory(&HDID, &pMvReq->Cdb[2], 2); Core_GetHDInfo( pCore, HDID, pHDInfo ); if (HDID != 0xFF && pHDInfo->Link.Self.DevType == DEVICE_TYPE_NONE) { if (pMvReq->Sense_Info_Buffer != NULL) ((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = ERR_INVALID_HD_ID; pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE; } else pMvReq->Scsi_Status = REQ_STATUS_SUCCESS; return MV_TRUE;}MV_BOOLEAN core_pd_request_get_HD_info_ext(PCore_Driver_Extension pCore, PMV_Request pMvReq){ PHD_Info pHDInfo = (PHD_Info)pMvReq->Data_Buffer; MV_U16 HDID; #ifdef DEBUG_BIOS //MV_DUMP32(0xCCCCEEE1);#endif MV_CopyMemory(&HDID, &pMvReq->Cdb[2], 2); Core_GetHDInfo_Ext( pCore, HDID, pHDInfo ); if (HDID != 0xFF && pHDInfo->Link.Self.DevType == DEVICE_TYPE_NONE) { if (pMvReq->Sense_Info_Buffer != NULL) ((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = ERR_INVALID_HD_ID; pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE; } else pMvReq->Scsi_Status = REQ_STATUS_SUCCESS; return MV_TRUE;}MV_BOOLEAN core_pd_request_get_expander_info( PCore_Driver_Extension pCore, PMV_Request pMvReq ){ PExp_Info pExpInfo = (PExp_Info)pMvReq->Data_Buffer; MV_U16 ExpID; MV_U8 status = REQ_STATUS_SUCCESS; MV_CopyMemory(&ExpID, &pMvReq->Cdb[2], 2); if (ExpID != 0xFF && ExpID > pCore->Expander_Count_Supported+MIN_EXPANDER_ID) { status = ERR_INVALID_EXP_ID; } else { Core_GetExpInfo( pCore, ExpID, pExpInfo, pMvReq ); if (ExpID != 0xFF && pExpInfo->Link.Self.DevType == DEVICE_TYPE_NONE) { status = ERR_INVALID_EXP_ID; } } if (status != REQ_STATUS_SUCCESS) { if (pMvReq->Sense_Info_Buffer != NULL) ((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = status; pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE; } else pMvReq->Scsi_Status = REQ_STATUS_SUCCESS; // done getting info for all the expanders, finish here; // if not done, the request will be completed later after requests // returned from hardware if( pCore->Scratch_Count2 == pCore->Scratch_Count1 ) CompleteRequest( pCore, pMvReq, 0 ); return MV_TRUE;}#ifdef SUPPORT_PMMV_BOOLEAN core_pd_request_get_PM_info( PCore_Driver_Extension pCore, PMV_Request pMvReq ){ PPM_Info pPMInfo = (PPM_Info)pMvReq->Data_Buffer; MV_U16 PMID; MV_CopyMemory(&PMID, &pMvReq->Cdb[2], 2); if (PMID != 0xFF && PMID > MAX_PM_SUPPORTED) { if (pMvReq->Sense_Info_Buffer != NULL) ((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = ERR_INVALID_PM_ID; pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE; return MV_TRUE; } Core_GetPMInfo( pCore, PMID, pPMInfo ); pMvReq->Scsi_Status = REQ_STATUS_SUCCESS; return MV_TRUE;}#endif /* SUPPORT_PM */#ifndef BIOS_NOT_SUPPORTMV_BOOLEAN core_pd_request_get_HD_config( PCore_Driver_Extension pCore, PMV_Request pMvReq ){ PHD_Config pHDConfig = (PHD_Config)pMvReq->Data_Buffer; MV_U16 ConfigID; MV_CopyMemory(&ConfigID, &pMvReq->Cdb[2], 2); Core_GetHDConfig( pCore, ConfigID, pHDConfig ); if (ConfigID != 0xFF && pHDConfig->HDID == 0xFF) { if (pMvReq->Sense_Info_Buffer != NULL) ((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = ERR_INVALID_HD_ID; pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE; } else pMvReq->Scsi_Status = REQ_STATUS_SUCCESS; return MV_TRUE;}MV_BOOLEAN core_pd_request_get_HD_status( PCore_Driver_Extension pCore, PMV_Request pMvReq ){ PHD_Status pHDStatus = (PHD_Status)pMvReq->Data_Buffer; PDomain_Port pPort = NULL; PDomain_Device pDevice = NULL; MV_U8 portId, deviceId; MV_U16 HDId; MV_U8 cacheMode = 0; MV_U8 status = REQ_STATUS_SUCCESS; MV_CopyMemory(&HDId, &pMvReq->Cdb[2], 2); if ( Core_MapHDId(pCore, HDId, &portId, &deviceId) ) { pPort = &pCore->Ports[MapPortEntry(pCore,portId)]; pDevice = &pCore->Devices[deviceId]; if ( !(pDevice->Status & DEVICE_STATUS_FUNCTIONAL) ) { status = ERR_INVALID_HD_ID; }#ifndef CORE_SAS_SUPPORT_ATA_COMMAND else if (IS_SSP(pDevice)) { // if SAS drive we bypass for now pMvReq->Scsi_Status = REQ_STATUS_SUCCESS; return MV_TRUE; }#endif else { if (pMvReq->Cdb[4] == APICDB4_PD_SMART_RETURN_STATUS) { cacheMode = CDB_CORE_SMART_RETURN_STATUS; } else status = ERR_INVALID_REQUEST; } if (status == REQ_STATUS_SUCCESS) { // Convert it into SCSI_CMD_MARVELL_SPECIFIC request. pMvReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC; pMvReq->Cdb[1] = CDB_CORE_MODULE; pMvReq->Cdb[2] = cacheMode; pMvReq->Device_Id = pDevice->Id; if (pHDStatus) pHDStatus->HDID = pDevice->Id; } } else { status = ERR_INVALID_HD_ID; } if (status != REQ_STATUS_SUCCESS) { if (pMvReq->Sense_Info_Buffer != NULL) ((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = status; pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE; return MV_TRUE; } else { pMvReq->Scsi_Status = REQ_STATUS_SUCCESS; return MV_FALSE; // Need to access hardware. }}MV_BOOLEAN core_pd_request_set_HD_config( PCore_Driver_Extension pCore, PMV_Request pMvReq ){ PDomain_Port pPort = NULL; PDomain_Device pDevice = NULL; MV_U8 portId, deviceId, i; MV_U16 HDId; MV_U8 cacheMode = 0; MV_U8 status = REQ_STATUS_SUCCESS; MV_U32 phy_status; MV_CopyMemory(&HDId, &pMvReq->Cdb[2], 2); if ( Core_MapHDId(pCore, HDId, &portId, &deviceId) ) { pPort = &pCore->Ports[MapPortEntry(pCore,portId)]; pDevice = &pCore->Devices[deviceId]; if ( !(pDevice->Status & DEVICE_STATUS_FUNCTIONAL) ) { status = ERR_INVALID_HD_ID; }#ifndef CORE_SAS_SUPPORT_ATA_COMMAND else if (IS_SSP(pDevice)) { if ( !((pMvReq->Cdb[4] == APICDB4_PD_SET_SPEED_3G) || (pMvReq->Cdb[4] == APICDB4_PD_SET_SPEED_1_5G)) ) { // if SAS drive we bypass for now pMvReq->Scsi_Status = REQ_STATUS_SUCCESS; return MV_TRUE; } }#endif else { if (pMvReq->Cdb[4] == APICDB4_PD_SET_WRITE_CACHE_OFF) { cacheMode = CDB_CORE_DISABLE_WRITE_CACHE; } else if (pMvReq->Cdb[4] == APICDB4_PD_SET_WRITE_CACHE_ON) { cacheMode = CDB_CORE_ENABLE_WRITE_CACHE; } else if (pMvReq->Cdb[4] == APICDB4_PD_SET_SMART_OFF) { cacheMode = CDB_CORE_DISABLE_SMART; } else if (pMvReq->Cdb[4] == APICDB4_PD_SET_SMART_ON) { cacheMode = CDB_CORE_ENABLE_SMART; } else if (pMvReq->Cdb[4] == APICDB4_PD_SET_SPEED_3G) { if (!(pDevice->Capacity & DEVICE_CAPACITY_RATE_3G)) { status = ERR_INVALID_PARAMETER; } else {/* allow speed setting only when idle */ if(pDevice->Outstanding_Req>0) status = ERR_NO_RESOURCE; else { if(pDevice->pExpander==NULL) { if (pDevice->NegotiatedLinkRate != PHY_LINKRATE_3) { for(i=0;i<pCore->Phy_Num;i++) { if(pPort->MemberPhyMap&MV_BIT(i)) { phy_status = READ_PORT_PHY_CONTROL(pCore->Mmio_Base, i); phy_status &= ~MV_MAX_SPP_PHYS_LINK_RATE_MASK; phy_status |= PHY_LINKRATE_3 << 12;/* this will only set the max linkrate */ WRITE_PORT_PHY_CONTROL(pCore->Mmio_Base, i, phy_status); } } pDevice->NegotiatedLinkRate = PHY_LINKRATE_3;/* the actual negotiated linkrate will be set after reset */ } mv_reset_phy(pCore, pPort->MemberPhyMap, MV_FALSE); } else {/* for devices behind expander: *//* Issuing a SMP phy_control to the expander to set max and min programmed linkrate and reset *//* this will only set the max linkrate *//* the actual negotiated linkrate will be set after reset, the result depends on its connection path */ Expander_SMPRequest_PhyControl(pPort,pDevice->pExpander,pDevice->Phy_Id,LINK_RESET,(PHY_LINKRATE_3<<4)+PHY_LINKRATE_1_5); } } pMvReq->Scsi_Status = REQ_STATUS_SUCCESS; return MV_TRUE; // Do not need to access hardware. } } else if (pMvReq->Cdb[4] == APICDB4_PD_SET_SPEED_1_5G) { if (!(pDevice->Capacity & DEVICE_CAPACITY_RATE_1_5G)) { status = ERR_INVALID_PARAMETER; } else { if(pDevice->Outstanding_Req>0) status = ERR_NO_RESOURCE; else { if(pDevice->pExpander==NULL) { if (pDevice->NegotiatedLinkRate != PHY_LINKRATE_1_5) { for(i=0;i<pCore->Phy_Num;i++) { if(pPort->MemberPhyMap&MV_BIT(i)) { phy_status = READ_PORT_PHY_CONTROL(pCore->Mmio_Base, i); phy_status &= ~MV_MAX_SPP_PHYS_LINK_RATE_MASK; phy_status |= PHY_LINKRATE_1_5 << 12; WRITE_PORT_PHY_CONTROL(pCore->Mmio_Base, i, phy_status); } } pDevice->NegotiatedLinkRate = PHY_LINKRATE_1_5;/* the actual negotiated linkrate will be set after reset */ } mv_reset_phy(pCore, pPort->MemberPhyMap, MV_FALSE); } else {/* for devices behind expander: *//* Issuing a SMP phy_control to the expander to set max and min programmed linkrate and reset *//* this will only set the max linkrate *//* the actual negotiated linkrate will be set after reset, the result depends on its connection path */ Expander_SMPRequest_PhyControl(pPort,pDevice->pExpander,pDevice->Phy_Id,LINK_RESET,(PHY_LINKRATE_1_5<<4)+PHY_LINKRATE_1_5); } } pMvReq->Scsi_Status = REQ_STATUS_SUCCESS; return MV_TRUE; // Do not need to access hardware.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -