📄 core_init.c
字号:
case PM_STATE_DEVICE_PLUG_OUT: SATA_PM_HandleDeviceUnplug(pCore, pPM); break; default: break; } return MV_TRUE;}#endif/* please move this to windows driver directory */#ifdef _OS_WINDOWS#define MV_PCI_READ_CONFIG_DWORD(x, y, z) *z = MV_PCI_READ_DWORD(x, y)/* pay attention to the seq. of the arguments */#define MV_PCI_WRITE_CONFIG_DWORD(x, y, z) MV_PCI_WRITE_DWORD(x, z, y)#endif /* _OS_WINDOWS *//* * Global controller reset */static MV_BOOLEANResetController(PCore_Driver_Extension pCore){ MV_LPVOID mmio = pCore->Mmio_Base; MV_U32 tmp; MV_BOOLEAN ret = MV_TRUE; MV_U32 reg; /* Reset controller */ tmp = MV_REG_READ_DWORD(mmio, HBA_CONTROL); if ((tmp & HOST_RESET) == 0) {#ifdef _OS_BIOS pCore->host_reseting = 1;#endif//WORKAROUND for WD1500 issue. if( (pCore->Device_Id==DEVICE_ID_6440)&&(pCore->Revision_Id==0x0) ) { MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL, ®); reg &=~MV_PCI_PHY_PWR_ON; reg |= MV_PCI_PHY_OFF; MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL, reg); MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL2, ®); reg &=~MV_PCI_PHY_PWR_ON; reg |= MV_PCI_PHY_OFF; MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL2, reg); } MV_REG_WRITE_DWORD(mmio, HBA_CONTROL, tmp | HOST_RESET); MV_REG_READ_DWORD(mmio, HBA_CONTROL); /* flush */ } /* Reset must complete within 1 second, or the hardware should be considered fried. */ HBA_SleepMillisecond(pCore, 1000); tmp = MV_REG_READ_DWORD(mmio, HBA_CONTROL); if (tmp & HOST_RESET) { MV_ASSERT(MV_FALSE); //TBD; ret = MV_FALSE; }#ifdef _OS_BIOS pCore->host_reseting = 0;#endif return ret;}void UpdateWidePortPhyMap(PCore_Driver_Extension pCore){ MV_LPVOID mmio = pCore->Mmio_Base; PDomain_Port pPort; MV_U8 i,j; MV_U32 reg; for ( i = 0; i<pCore->Phy_Num; i++) { if ( 0 == (pCore->Phy[i].PhyStatus & MV_PHY_READY_MASK)) continue; pCore->Phy[i].WidePortPhyMap |= MV_BIT(i); pPort = pCore->Phy[i].pDomainPort; if (pCore->Phy[i].Type&PORT_TYPE_SAS) { /* update WidePortPhyMap */ for (j=i+1; j<pCore->Phy_Num; j++) { if (!(pCore->Phy[j].PhyStatus & MV_PHY_READY_MASK)) continue; if ((pCore->Phy[i].AttDevInfo & (PORT_DEV_SMP_TRGT | PORT_DEV_SSP_TRGT | PORT_DEV_STP_TRGT)) && (U64_COMP_U64_VALUE(pCore->Phy[i].AttDevSASAddr, pCore->Phy[j].AttDevSASAddr)) && (U64_COMP_U64_VALUE(pCore->Phy[i].DevSASAddr, pCore->Phy[j].DevSASAddr))) { pCore->Phy[i].WidePortPhyMap |= MV_BIT(j); pCore->Phy[j].WidePortPhyMap = pCore->Phy[i].WidePortPhyMap; if (pPort == NULL) pPort=pCore->Phy[j].pDomainPort; else pCore->Phy[j].pDomainPort = pPort; } } } /* if it is a new port */ if(pPort==NULL) { pPort = GetPortFromPool(pCore); if (pPort==NULL) return; MV_PRINT("phy %d on port %p.\n", i, pPort); pCore->Phy[i].pDomainPort=pPort; pPort->pPhy = &pCore->Phy[i]; pPort->Type = pCore->Phy[i].Type; pPort->Port_State = PORT_STATE_IDLE; pPort->DiscoveryInstance = 0; pPort->Core_Extension = pCore; pPort->Device_Number = 0; pPort->Expander_Number=0;/* update all wide port group */ for( j=i+1; j<pCore->Phy_Num; j++) { if(pCore->Phy[i].WidePortPhyMap&MV_BIT(j)) pCore->Phy[j].pDomainPort=pPort; } } else pCore->Phy[i].pDomainPort = pPort; WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_WIDE_PORT); reg=pCore->Phy[i].WidePortPhyMap; pPort->MemberPhyMap = pCore->Phy[i].WidePortPhyMap; WRITE_PORT_CONFIG_DATA(mmio,i,reg); }}void DetectPortType(PCore_Driver_Extension pCore, MV_U8 i){ MV_LPVOID mmio = pCore->Mmio_Base; MV_U32 reg; /* enable auto port detection */ MV_REG_WRITE_DWORD(mmio, VSR_PORT_TYPE_REG, MODE_AUTO_DET_EN); HBA_SleepMillisecond(pCore, 100); /* TODO check & save device type*/ reg = MV_REG_READ_DWORD(mmio, VSR_PORT_TYPE_REG); if (reg & MODE_SAS_SATA & (1 << i)) { pCore->Phy[i].Type = PORT_TYPE_SAS; } else { pCore->Phy[i].Type = PORT_TYPE_SATA; }}void SetPhyTuning( PCore_Driver_Extension pCore, MV_U8 i, PHY_TUNING phy_tuning){ MV_U32 tmp; MV_LPVOID mmio = pCore->Mmio_Base; // Amp (amplitude) and Pre-emphasis tuning WRITE_PORT_VSR_ADDR(mmio,i,1); tmp=READ_PORT_VSR_DATA(mmio,i); // Set 0 from bit 14 till bit 8 tmp&=~(0x7F00); // Set the bits tmp|= (phy_tuning.AMP << 11)|(phy_tuning.Pre_Emphasis << 8); WRITE_PORT_VSR_DATA(mmio,i,tmp); // Drive EN and Half Pre-emphasis enable WRITE_PORT_VSR_ADDR(mmio,i,11); tmp=READ_PORT_VSR_DATA(mmio,i); // Set 0 from bit 14 till bit 8 tmp&=~(0x23F); // Set the bits tmp|= (phy_tuning.Pre_Half_En << 9)|(phy_tuning.Drive_En); WRITE_PORT_VSR_DATA(mmio,i,tmp);}void UpdatePhyInfo(PCore_Driver_Extension pCore, MV_U8 i){ MV_LPVOID mmio = pCore->Mmio_Base; MV_U32 tmp; MV_ZeroMemory(&pCore->Phy[i], sizeof(Domain_Phy)); DetectPortType(pCore,i); WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_DEV_INFO); pCore->Phy[i].DevInfo = READ_PORT_CONFIG_DATA(mmio,i); WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_DEV_ADDR_LO); pCore->Phy[i].DevSASAddr.parts.low = READ_PORT_CONFIG_DATA(mmio,i); WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_DEV_ADDR_HI); pCore->Phy[i].DevSASAddr.parts.high = READ_PORT_CONFIG_DATA(mmio,i); pCore->Phy[i].PhyStatus = READ_PORT_PHY_CONTROL(mmio,i); if (pCore->Phy[i].PhyStatus & MV_PHY_READY_MASK) { if (pCore->Phy[i].Type&PORT_TYPE_SAS) { WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_ATT_DEV_INFO); pCore->Phy[i].AttDevInfo = READ_PORT_CONFIG_DATA(mmio,i); WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_ATT_DEV_ADDR_LO); pCore->Phy[i].AttDevSASAddr.parts.low = READ_PORT_CONFIG_DATA(mmio,i); WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_ATT_DEV_ADDR_HI); pCore->Phy[i].AttDevSASAddr.parts.high = READ_PORT_CONFIG_DATA(mmio,i);; }/* workaround for HW phy decoding error on 1.5g disk drive */ WRITE_PORT_VSR_ADDR(mmio,i,0x06); tmp=READ_PORT_VSR_DATA(mmio,i); if( ((pCore->Phy[i].PhyStatus&MV_NEG_SPP_PHYS_LINK_RATE_MASK)>>MV_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET) == PHY_LINKRATE_1_5) tmp&=~0x20000000; else tmp|=0x20000000; WRITE_PORT_VSR_DATA(mmio,i,tmp); } pCore->Phy[i].IRQStatus = READ_PORT_IRQ_STAT(mmio,i);}/* * It's equivalent to ahci_host_init and ahci_port_start */static MV_VOID InitChip(PCore_Driver_Extension pCore){ MV_LPVOID mmio = pCore->Mmio_Base; MV_U8 i; MV_U32 tmp; AdapterInfo AI;/* HBA_Info_Page HBA_Info_Param; */ MV_U8 SasAddr[8]={0x50,0x05,0x04,0x30,0x11,0xab,0x00,0x00}; tmp = MV_REG_READ_DWORD(mmio, COMMON_CONFIG); tmp |= MV_SAS_SATA_RST; MV_REG_WRITE_DWORD(mmio, COMMON_CONFIG, tmp); MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_CMD, &tmp); tmp |= MV_PCI_DEV_EN; MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_CMD, tmp);#if USE_MSI mv_enable_msi(pCore);#endif /* USE_MSI *//* commented out for 25 MHz */#if 0 tmp = 0x100f3631; /* PLL for performance */ MV_PCI_WRITE_CONFIG_DWORD(pCore, 0x8c, tmp);#endif /* 0 */ /* write to device control _AND_ device status register? - A.C. */ MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_DEV_CTRL, &tmp); tmp &= ~MV_PCI_RD_REQ_MASK; tmp |= MV_PCI_RD_REQ_SIZE; MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_DEV_CTRL, tmp); MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL, &tmp); tmp &= ~MV_PCI_PHY_OFF; tmp |= MV_PCI_PHY_PWR_ON; MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL, tmp); MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL2, &tmp); tmp &= ~MV_PCI_PHY_OFF; tmp |= MV_PCI_PHY_PWR_ON; MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL2, tmp); /* reset control */ MV_REG_WRITE_DWORD(pCore->Mmio_Base, COMMON_CONTROL, 0); /* workaround for SATA R-ERR, to ignore phy glitch */ MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x118); tmp = MV_REG_READ_DWORD(mmio, COMMON_CMD_DATA); tmp &=~0x200; tmp |= 0x400; MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, tmp); /* enable retry 127 times */ MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x128); MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, 0x7f7f); /* extend open frame timeout to max */ MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x124); tmp = MV_REG_READ_DWORD(mmio, COMMON_CMD_DATA); tmp &=~0xffff; tmp |=0x3fff; MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, tmp); /* workaround for WDTIMEOUT , set to 550 ms */ MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x13c);// MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, 0x7ffff); MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, 0xffffff); /* up with PLL */ /* not to halt for different port op during wideport link change */ MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x1a4); MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, 0xffefbf7d); /* workaround for Seagate disk not-found OOB sequence, recv COMINIT before sending out COMWAKE */ MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x1b8); tmp = MV_REG_READ_DWORD(mmio, COMMON_CMD_DATA); tmp &=0x0000ffff; tmp |=0x00fa0000; MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, tmp); MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, CMD_PHY_TIMER); tmp = MV_REG_READ_DWORD(mmio, COMMON_CMD_DATA); tmp &=0x1fffffff; tmp |=(MV_U32)2L<<29; /* 8ms retry */ MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, tmp); AI.bar[2] = pCore->Base_Address[2];#ifdef DBG_PROGRAM_SAS_ADDRESS Odin_NVRamWrite( &AI, NVRAM_OFF( SasAddr ), SasAddr, NVRAM_SIZE( SasAddr ) ); #endif /* DBG_PROGRAM_SAS_ADDRESS */#if defined( SAS_ADDR_IN_NVRAM ) if (Odin_NVRamRead(&AI, NVRAM_OFF(SasAddr), SasAddr, NVRAM_SIZE(SasAddr)) || (U64_COMPARE_U32((*(MV_U64 *) SasAddr), 0) == 0)) { U64_ASSIGN((*(MV_U64 *) SasAddr), 0x0000ab1130040550ULL); }#elif defined(SUPPORT_CSMI) do { HBA_Info_Page HBA_Info_Param; int i; if( -1 == OdinSPI_Init(&AI)) break; if (!mvui_init_param(pCore, &HBA_Info_Param)) break; for (i = 0; i < 8; i++) { SasAddr[i] = HBA_Info_Param.SAS_Address[0].b[i]; } /* Set phy tuning registers if HBA_Info_Param is valid */ for (i = 0; i < pCore->Phy_Num; i++) { if ((HBA_Info_Param.PHY_Tuning[i].Reserved[0] == 0) & (HBA_Info_Param.PHY_Tuning[i].Reserved[1] == 0)) { SetPhyTuning(pCore, (MV_U8)i, HBA_Info_Param.PHY_Tuning[i]); } } } while (0);#endif if( (U64_COMPARE_U32((*(MV_U64 *) SasAddr), 0) == 0) || (U64_COMP_U64(0xffffffffffffffffULL, (*(MV_U64 *) SasAddr))) ) { U64_ASSIGN((*(MV_U64 *) SasAddr), 0x0000ab1130040550ULL); } for ( i = 0; i<pCore->Phy_Num; i++) { DetectPortType(pCore,i);/* Set SAS Addr */ mv_set_SASAddr(pCore, i, SasAddr);/*enable Phy Port XMT*/ tmp = READ_PORT_PHY_CONTROL(mmio, i); tmp |= MV_PHY_RESET; WRITE_PORT_PHY_CONTROL(mmio, i, tmp); HBA_SleepMillisecond(pCore, 100);/*reset irq */ tmp=READ_PORT_IRQ_STAT(mmio,i); tmp&=~SIG_FIS_RCVD_MASK; WRITE_PORT_IRQ_STAT(mmio,i,tmp);/*enable phy change interrupt and broadcast change*/ #ifdef SUPPORT_PM tmp = PHY_RDY_CHNG_MASK | BRDCST_CHNG_RCVD_MASK | UNASSOC_FIS_RCVD_MASK;#else tmp = PHY_RDY_CHNG_MASK | BRDCST_CHNG_RCVD_MASK;#endif WRITE_PORT_IRQ_MASK(mmio,i,tmp); UpdatePhyInfo(pCore, i); } /* this function needs a complete rewrite for God's sake - A.C. */ UpdateWidePortPhyMap(pCore); /* reset CMD queue */ tmp = MV_REG_READ_DWORD(mmio, COMMON_CONTROL); tmp |= RESET_CMD_ISSUE; MV_REG_WRITE_DWORD(mmio, COMMON_CONTROL, tmp);#ifndef SOFTWARE_XOR /* reset XOR CMD queue */ tmp = XOR_RESET; MV_REG_WRITE_DWORD(mmio, XOR_CONTROL, tmp);#endif /* little endian for open address and command table, etc. */ /* A.C. * it seems that ( from the spec ) turning on big-endian won't * do us any good on big-endian machines, need further confirmation */ tmp = MV_REG_READ_DWORD(mmio, COMMON_CONFIG); MV_DPRINT(("COMMON_CONFIG (default) = 0x%x\n", tmp)); tmp |= MV_CMD_TBL_BE; tmp |= MV_DATA_BE; tmp &= ~MV_OPEN_ADDR_BE; tmp |= MV_RSPNS_FRAME_BE; MV_REG_WRITE_DWORD(mmio, COMMON_CONFIG, tmp); tmp = MV_REG_READ_DWORD(mmio, COMMON_CONFIG); MV_DPRINT(("COMMON_CONFIG (written) = 0x%x\n", tmp));/* assign command list address */ MV_REG_WRITE_DWORD(mmio, COMMON_LST_ADDR, pCore->Cmd_List_DMA.parts.low); MV_REG_WRITE_DWORD(mmio, COMMON_LST_ADDR_HI, pCore->Cmd_List_DMA.parts.high);/* assign FIS address */ MV_REG_WRITE_DWORD(mmio, COMMON_FIS_ADDR, pCore->RX_FIS_DMA.parts.low); MV_REG_WRITE_DWORD(mmio, COMMON_FIS_ADDR_HI, pCore->RX_FIS_DMA.parts.high);/* assign delivery queue address */ tmp = 0; MV_REG_WRITE_DWORD(mmio, COMMON_DELV_Q_CONFIG, tmp); tmp = DELV_QUEUE_SIZE_MASK & pCore->Slot_Count_Supported; tmp |= DELV_QUEUE_ENABLE; MV_REG_WRITE_DWORD(mmio, COMMON_DELV_Q_CONFIG, tmp); MV_REG_WRITE_DWORD(mmio, COMMON_DELV_Q_ADDR, pCore->DELV_Q_DMA.parts.low); MV_REG_WRITE_DWORD(mmio, COMMON_DELV_Q_ADDR_HI, pCore->DELV_Q_DMA.parts.high); // write in a default value for completion queue pointer in memory tmp = 0xFFF; MV_CopyMemory( pCore->CMPL_Q, &tmp, 4 ); /* assign completion queue address */ tmp = 0; MV_REG_WRITE_DWORD(mmio, COMMON_CMPL_Q_CONFIG, tmp); tmp = CMPL_QUEUE_SIZ
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -