📄 core_init.c
字号:
#include "core_header.h"#include "core_exp.h"#include "core_helper.h"#include "core_init.h"#include "core_ibcd.h"#include "core_sata.h"#include "core_spi.h"#include "core_eeprom.h"#include "com_nvram.h"void Device_IssueSoftReset(PDomain_Port pPort, PDomain_Device pDevice, MV_BOOLEAN SRST, MV_BOOLEAN isPortReset);static void Device_IssueIdentify(PDomain_Port pPort, PDomain_Device pDevice);static void Device_IssueSetUDMAMode(PDomain_Port pPort, PDomain_Device pDevice);static void Device_IssueSetPIOMode(PDomain_Port pPort, PDomain_Device pDevice);static void Device_EnableWriteCache(PDomain_Port pPort, PDomain_Device pDevice);static void Device_EnableReadAhead(PDomain_Port pPort, PDomain_Device pDevice);void SATA_PMInitReqCallback(PCore_Driver_Extension pCore, PMV_Request pReq);void SATA_PMHotplugReqCallback(PCore_Driver_Extension pCore, PMV_Request pReq);MV_U8 GetMaxNegotiatedLinkRate(PDomain_Port pPort);MV_U8 GetMinNegotiatedLinkRate(PDomain_Port pPort);extern void Core_HandleWaitingList(PCore_Driver_Extension pCore);extern void Expander_SMPRequest_ReportGeneral(PDomain_Port pPort, PDomain_Expander pTgt);extern void Expander_SMPRequest_Discover(PDomain_Port pPort, PDomain_Expander pTgt, MV_U8 PhyId);extern void Device_MakeReadCapacity16TaskRequest(PDomain_Device pDevice);extern void Device_MakeReadCapacityTaskRequest(PDomain_Device pDevice);extern void Device_MakeInquiryTaskRequest(PDomain_Device pDevice);#ifdef CORE_SAS_SUPPORT_ATA_COMMANDextern void Device_MakeModeSenseRequest(PDomain_Device pDevice);extern void Device_MakeModeSelectRequest(PDomain_Device pDevice);#endifextern void Expander_SMPRequest_ReportPHYSATA(PDomain_Port pPort, PDomain_Expander pTgt, MV_U8 PhyId, PDomain_Device pDevice);#ifdef SUPPORT_SESextern void Device_MakeSesRcvDiagRequest(PDomain_Device pDevice, MV_U8 PageCode);#endif#ifdef SUPPORT_SGPIOvoid SGPIO_Initialize( MV_PVOID This );extern void SGPIOtest(MV_PVOID This);#endif#ifdef SUPPORT_I2Cextern void I2C_ModuleInitialize(MV_PVOID This);#endifextern void Device_MakeStartStopUnitRequest(PDomain_Device pDevice, MV_U8 Control);void SATA_PortDetect( PDomain_Port pPort, PDomain_Device pDevice );MV_BOOLEAN mvChannelStateMachine( PCore_Driver_Extension pCore, PDomain_Port pPort );static MV_BOOLEAN SAS_DeviceStateMachine( PCore_Driver_Extension pCore, PDomain_Device pDevice );#ifdef SUPPORT_HOT_PLUGvoid Device_SoftReset(PDomain_Port pPort, PDomain_Device pDevice){ PCore_Driver_Extension pCore = pPort->Core_Extension; pDevice->State = DEVICE_STATE_RESET_DONE;#ifndef _OS_BIOS SATA_DeviceStateMachine (pCore, pDevice);#endif}#endif /* #ifdef SUPPORT_HOT_PLUG */ //TBD: Refer to CamAtaDevResetStart/* * Initialize this port including possible device hard or soft reset. */ //Lily test#define mvDisableIntr(portMmio, old_stat) do{ \ old_stat = MV_REG_READ_DWORD(portMmio, PORT_IRQ_MASK); \ MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_MASK, 0);\ }while(0)#define mvEnableIntr(portMmio, old_stat) MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_MASK, old_stat)MV_BOOLEAN SATA_PortDeviceDetected( PDomain_Port pPort ){ PCore_Driver_Extension pCore = pPort->Core_Extension; MV_LPVOID mmio = pCore->Mmio_Base; MV_U32 temp; MV_U8 i; for (i=0; i<pCore->Phy_Num; i++) { if (pPort->MemberPhyMap & MV_BIT(i)) break; } WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_PHY_STATUS); temp = READ_PORT_CONFIG_DATA(mmio,i); return ( ((PREG_CONFIG_PHY_STATUS)&temp)->PHY_RDY == 1 );}MV_BOOLEAN SATA_PortDeviceReady(PDomain_Port pPort, PDomain_Device pDevice){ PCore_Driver_Extension pCore = pPort->Core_Extension; MV_LPVOID mmio = pCore->Mmio_Base; MV_U32 temp, signature=0; MV_U8 i, retry; pDevice->Dev_Type = DT_DIRECT_ACCESS_BLOCK; pDevice->Connection = DC_SERIAL | DC_ATA; pDevice->Status = DEVICE_STATUS_EXISTING|DEVICE_STATUS_FUNCTIONAL; pDevice->pPort = pPort; for (retry = 0; retry < 5; retry++) { signature = 0; for (i = 0; i < pCore->Phy_Num; i++) { if (pPort->MemberPhyMap & MV_BIT(i)) break; } /* check signature */ WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_SATA_SIG3); temp = READ_PORT_CONFIG_DATA(mmio,i) & 0xFF; signature |= temp; WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_SATA_SIG1); temp = READ_PORT_CONFIG_DATA(mmio,i) & 0xFFFFFF; signature |= (temp<<8); WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_SATA_SIG0); temp = READ_PORT_CONFIG_DATA(mmio,i); if ( signature==0xEB140101 ) /* ATAPI signature */ { pDevice->Connection |= DC_ATAPI; return ((MV_U8)(temp >> 24) == 0x01); } else if( signature == 0x96690101 ) /* PM signature */ { pPort->Setting |= PORT_SETTING_PM_EXISTING; pPort->Setting |= PORT_SETTING_PM_FUNCTIONAL; return ((MV_U8)(temp >> 16) == 0x50 ); } else if ( signature==0x00000101 ) /* ATA signature */ { return ((MV_U8)(temp >> 16) == 0x50 ); } HBA_SleepMillisecond( pCore, 5 ); } MV_PRINT("Invalid signature, treat as ATA\n"); return ((MV_U8)(temp >> 16) == 0x50 );}MV_U8 SATA_GetRegisterSet( PCore_Driver_Extension pCore ){ MV_LPVOID mmio = pCore->Mmio_Base; MV_U32 temp; MV_U8 i; /** * choose a register set to be associated with this device * we always grab the first available one */ temp = MV_REG_READ_DWORD( mmio, COMMON_CONTROL ); for( i=0; i<16; i++ ) { if( !(temp & MV_BIT((i+16))) ) { MV_REG_WRITE_DWORD( mmio, COMMON_CONTROL, temp | MV_BIT((i+16)) ); return i; } } MV_DPRINT(("ERROR: ran out of register sets\n")); return 0;}void SATA_PortReset( PDomain_Port pPort, MV_BOOLEAN hardReset ){ PCore_Driver_Extension pCore = pPort->Core_Extension; PDomain_Device pDevice = NULL; MV_U8 i = 0;#ifndef SUPPORT_PM MV_U32 loop = 10000; MV_LPVOID mmio = pCore->Mmio_Base;#endif /* SUPPORT_PM */ MV_ASSERT( pPort->Port_State==PORT_STATE_IDLE ); pPort->Device_Number = 0; if( hardReset ) { //TBD: MV_DASSERT(MV_FALSE); } if( !SATA_PortDeviceDetected( pPort ) ) { pPort->Port_State = PORT_STATE_INIT_DONE; mvChannelStateMachine( pCore, pPort ); return; } for(i=0;i<pCore->Phy_Num;i++) { if(pPort->MemberPhyMap&MV_BIT(i)) break; }#ifndef SUPPORT_PM /* Enable SUPPORT_PM will Enable Sinature Received Interrupt This loop will waste time */ /* wait until signature FIS comes in to send soft reset */ while( loop > 0 ) { if (mv_is_sig_fis_received(mmio, i)) { MV_DPRINT(("power on: got signature FIS\n")); break; } HBA_SleepMillisecond( pCore, 1 ); loop--; } MV_DPRINT(("Port %d waited %d millisecond for the signature FIS.\n", pPort->Id, 10000-loop));#endif /* Device is ready */ pDevice = GetDeviceFromPool( pCore ); if( pDevice == NULL ) return;#ifndef USE_DYN_REGISTER_SET pDevice->Register_Set = SATA_GetRegisterSet(pCore);#endif /* This is for Hibernation. In Hibernation, driver can execute 1 request at one time But mvChannelStateMachine is for loop detection If there're multiple devices in different channel, some devices can not detect correctly These code will add them to waiting list */ List_AddTail(&pDevice->Queue_Pointer, &pPort->Device_List); pPort->Device_Number++; pDevice->pPort = pPort; pDevice->Connection = DC_SERIAL | DC_ATA; pDevice->Dev_Type = DT_DIRECT_ACCESS_BLOCK;#ifdef SUPPORT_PM Device_IssueSoftReset( pPort, pDevice, MV_TRUE, MV_TRUE );#else SATA_PortDetect(pPort, pDevice);#endif /* SUPPORT_PM */}void SATA_PortDetect( PDomain_Port pPort, PDomain_Device pDevice ){ PCore_Driver_Extension pCore = pPort->Core_Extension; MV_U8 i; MV_U32 loop;#ifdef SUPPORT_PM PDomain_PM pPM = NULL;#endif MV_DPRINT(("SATA_PortDetect\n")); loop = 5000; while ( loop>0 ) { if (SATA_PortDeviceReady(pPort, pDevice)) { MV_DPRINT(("Device %d is ready after %d millisecond.\n", pDevice->Id, 5000-loop)); break; } HBA_SleepMillisecond(pCore, 1); loop--; if ( loop==0 ) MV_DPRINT(("Device %d not ready\n", pDevice->Id)); } /* if (!SATA_PortDeviceReady(pPort, pDevice)) { HBA_SleepMillisecond( pCore, 10 ); // device not ready - for now we'll try sending commands anyway } */ for (i = 0; i < pCore->Phy_Num; i++) { if (pPort->MemberPhyMap & MV_BIT(i)) break; } if( pPort->Setting & PORT_SETTING_PM_EXISTING ) // found PM { List_Del(&pDevice->Queue_Pointer); pPort->Device_Number--; FreeDeviceToPool(pCore, pDevice);#ifdef SUPPORT_PM if (pPort->pPM == NULL) { pPM = GetPMFromPool(pCore); if( pPM == NULL ) return; pPort->pPM = pPM; } else pPM = pPort->pPM; pPM->pPort = pPort; pPM->CheckedPort = 0; pPM->ActPortNumber = 0;#ifndef USE_DYN_REGISTER_SET pPM->Register_Set = SATA_GetRegisterSet(pCore); pPM->Last_Register_Set = pPM->Register_Set;#endif pPM->State = PM_STATE_IDLE; pPM->Status |= PM_STATUS_RESET; SATA_PMStateMachine(pCore, pPM);#endif } else {#ifdef SUPPORT_PM if (pPort->pPM) { FreePMToPool(pCore, pPort->pPM); pPort->pPM = NULL; }#endif /* SUPPORT_PM */ pDevice->pPort = pPort; pDevice->Connection = DC_SERIAL | DC_ATA; pDevice->Dev_Type = DT_DIRECT_ACCESS_BLOCK; pDevice->Status = DEVICE_STATUS_EXISTING | DEVICE_STATUS_FUNCTIONAL; pDevice->State = DEVICE_STATE_SRST_1; SATA_DeviceStateMachine(pCore, pDevice); }}void STP_DeviceReset( PDomain_Port pPort, PDomain_Expander pExpander, struct SMPResponse *pSMPResp ){ PCore_Driver_Extension pCore = pPort->Core_Extension; PDomain_Device pDevice = NULL; MV_U8 i; for( i=0; i<pPort->Device_Number; i++ ) { pDevice = (PDomain_Device)List_GetFirstEntry(&pPort->Device_List, Domain_Device, Queue_Pointer); List_AddTail( &pDevice->Queue_Pointer, &pPort->Device_List ); if ( pDevice->pExpander == pExpander ) { if( pDevice->Phy_Id == pSMPResp->Response.ReportPhySATA.PhyIdentifier ) break; } } if( i == pPort->Device_Number ) { MV_DPRINT(("error: report PHY SATA finished but can't find device\n")); return; } if( pSMPResp->Response.ReportPhySATA.FIS.Status == 0x50 ) {#ifndef USE_DYN_REGISTER_SET /** * choose a register set to be associated with this device * we always grab the first available one */ pDevice->Register_Set = SATA_GetRegisterSet(pCore);#endif pDevice->Status = DEVICE_STATUS_EXISTING|DEVICE_STATUS_FUNCTIONAL; pDevice->State = DEVICE_STATE_RESET_DONE; pDevice->pPort = pPort; pDevice->Connection = DC_SCSI | DC_SERIAL | DC_ATA; pDevice->Dev_Type = DT_DIRECT_ACCESS_BLOCK; pDevice->pExpander = pExpander; pDevice->pPort = pPort; SATA_DeviceStateMachine(pCore, pDevice); }}MV_U8 Port_FindTgtNo( IN MV_PVOID This, IN MV_U8 *SasAddr){ PDomain_Port pPort=(PDomain_Port)This; PCore_Driver_Extension pCore = pPort->Core_Extension; MV_U8 i; for(i=MIN_EXPANDER_ID; i<MAX_EXPANDER_ID; i++) { MV_U8 index=MapDeviceId(pCore,i); if(index!=ID_NOT_MAPPED) { if((pCore->Expanders[index].pPort==pPort)&& MV_Equals((MV_U8 *)&pCore->Expanders[index].SASAddr, SasAddr, 8)) return index; } } return ID_NOT_MAPPED;}void CheckDeviceChange(PDomain_Expander pExpander, MV_PVOID pDiscoveryExtension, MV_U8 i){ PDomain_Port pPort=pExpander->pPort; PCore_Driver_Extension pCore = pPort->Core_Extension; PDomain_Device pDevice = NULL; MV_U8 Remained; Remained = pExpander->Device_Number; while( (!List_Empty(&pExpander->Device_List))&& (Remained>0) ) { MV_U8 j; MV_U8 data[512]; pTarget_Dev_Map pTgtMap; pDevice = List_GetFirstEntry(&pExpander->Device_List, Domain_Device, Exp_Queue_Pointer); DISC_GetTgtDevMap(pDiscoveryExtension, pPort, MAP_TGT_INFO, i, data); pTgtMap=(pTarget_Dev_Map)data; for(j=0;j<pTgtMap->Info.TotalDevCounts;j++) { if (MV_Equals(pTgtMap->TgtDev[j].DevSASAddr, (MV_U8 *)&pDevice->SASAddr, 8)) {/* update the linkrate info in case it is changed */ pDevice->NegotiatedLinkRate=pTgtMap->TgtDev[j].NegotiatedLinkRate&0x0f; pDevice->Capacity&=~DEVICE_CAPACITY_RATE_3G; pDevice->Capacity|=DEVICE_CAPACITY_RATE_1_5G; if(pTgtMap->TgtDev[j].MaxLinkRateCapability==PHY_LINKRATE_3) pDevice->Capacity|=DEVICE_CAPACITY_RATE_3G; List_AddTail( &pDevice->Exp_Queue_Pointer, &pExpander->Device_List ); break; } } if(j>=pTgtMap->Info.TotalDevCounts) { /* Not found, device is removed */ core_notify_device_hotplug(pCore, EVENT_DEVICE_REMOVAL, pDevice->Id); Port_AbortRequests(pPort,REQ_STATUS_NO_DEVICE,pDevice); List_Del( &pDevice->Queue_Pointer ); pPort->Device_Number--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -