core_xor.c
来自「6440linuxDriver的源代码」· C语言 代码 · 共 1,454 行 · 第 1/4 页
C
1,454 行
MV_PHYSICAL_ADDR tmpPhyAddress; PMV_XOR_Command_Header pCmdHeader; PMV_XOR_Command_Table pCmdTbl= (PMV_XOR_Command_Table)pCore->XOR_Cmd_Table; XOR_DELIVERY_QUEUE_ENTRY DELV_Q_Entry; MV_U8 sId; int availSg = SG_BUFFER_SINGLE_COUNT; //--- int consumed; //--- PMV_SG_Entry sg; //--- PSG_Buffer pSGBuf, pNextSGBuf, pTempBuf; pSGBuf = GetSGBufferFromPool(pCore); if (pSGBuf == NULL) { MV_DPRINT(("Ran out of SG Buffers!\n")); List_Add(&pReq->Queue_Pointer, &pCore->XOR_Waiting_List); return; } else { pReq->SG_Buffer = pSGBuf; } pReq->SlotNo=0xfff; SlotNo=XORGetOneCommandSlot(pCore, &pCmdHeader); pReq->SlotNo=SlotNo; sg = pSGBuf->Buffer_Vir; //--- tmpPhyAddress.value = pCore->Cmd_Table_DMA.value + ((MV_PU8)&pCmdTbl[SlotNo].NextTableAddressLo - (MV_PU8)pCore->Cmd_Table); pCmdHeader->Table_Address= tmpPhyAddress.parts.low; pCmdHeader->Table_Address_High= tmpPhyAddress.parts.high; pCmdHeader->XORTblLen=((sizeof(XOR_CMD_ENTRY)*MAX_XOR_CMD_ENTRY)/sizeof(MV_U32))+4; MV_ZeroMemory(&pCmdTbl[SlotNo], sizeof(MV_XOR_Command_Table));/*XOR_PRD 0: 1. Fill Buffer0 from Src[0] 2. if RAID6, Fill Buffer1 from Src[0]XOR_PRD 1..n: 3. XOR to Buffer0 from Src[1..n] 4. if RAID6, GF_Multiply and XOR to Buffer1 from Src[1..n]XOR_PRD n+1: 5. XOR to Buffer0 from Tgt0XOR_PRD n+2: 6. if RAID6, XOR to Buffer1 from Tgt1XOR_PRD ..+1: 3. Zero check on Buffer0 4. if RAID6, Zero check on Buffer1*/#ifdef USE_NEW_SGTABLE consumed = sgdt_prepare_hwprd( pCore, &pReq->Source_SG_Table_List[0], sg, availSg );#else consumed = pReq->Source_SG_Table_List[0].Valid_Entry_Count; for(i=0;i<pReq->Source_SG_Table_List[0].Valid_Entry_Count;i++) { MV_CopyMemory(&sg[i], &pReq->Source_SG_Table_List[0].Entry_Ptr[i], sizeof(MV_SG_Entry)); }#endif MV_ASSERT( consumed ); MV_ASSERT( availSg >= consumed ); pCmdTbl[SlotNo].XOR_PRD[0].PRDEntryCount = (MV_U8) consumed; U64_ASSIGN_U64(tmpPhyAddress, pSGBuf->Buffer_DMA); sg += consumed; availSg -= consumed; pCmdTbl[SlotNo].XOR_PRD[0].PRDTableAddress=tmpPhyAddress.parts.low; pCmdTbl[SlotNo].XOR_PRD[0].PRDTableAddressHigh=tmpPhyAddress.parts.high; pCmdTbl[SlotNo].XOR_PRD[0].Buffer0OpCode=OP_DIRECT_FILL; //direct fill if(pReq->Target_SG_Table_Count>1) pCmdTbl[SlotNo].XOR_PRD[0].Buffer1OpCode=OP_DIRECT_FILL; //direct fill pCmdTbl[SlotNo].TotalByteCount=pReq->Source_SG_Table_List[0].Byte_Count; for(sId=1;sId<pReq->Source_SG_Table_Count;sId++) { //if (availSg < pReq->Source_SG_Table_List[sId].Valid_Entry_Count) // Need a better solution. We don't know how many entries will be used in sgdt_prepare_hwprd. if (availSg < SG_BUFFER_SINGLE_COUNT) { pNextSGBuf = GetSGBufferFromPool(pCore); if (pNextSGBuf == NULL) { MV_DPRINT(("Ran out of SG Buffers!\n")); Tag_ReleaseOne(&pCore->XOR_Tag_Pool, SlotNo); while (pReq->SG_Buffer) { pTempBuf = ((PSG_Buffer)pReq->SG_Buffer)->NextBuffer; FreeSGBufferToPool(pCore, (PSG_Buffer *) &pReq->SG_Buffer); pReq->SG_Buffer = pTempBuf; } List_Add(&pReq->Queue_Pointer, &pCore->XOR_Waiting_List); return; } pSGBuf->NextBuffer = pNextSGBuf; sg = pNextSGBuf->Buffer_Vir; availSg = SG_BUFFER_SINGLE_COUNT; pSGBuf = pNextSGBuf; }#ifdef USE_NEW_SGTABLE consumed = sgdt_prepare_hwprd( pCore, &pReq->Source_SG_Table_List[sId], sg, availSg );#else consumed = pReq->Source_SG_Table_List[sId].Valid_Entry_Count; for(i=0;i<pReq->Source_SG_Table_List[sId].Valid_Entry_Count;i++) { MV_CopyMemory(&sg[i], &pReq->Source_SG_Table_List[sId].Entry_Ptr[i], sizeof(MV_SG_Entry)); }#endif MV_ASSERT( consumed ); MV_ASSERT( availSg >= consumed ); pCmdTbl[SlotNo].XOR_PRD[sId].PRDEntryCount = (MV_U8) consumed; tmpPhyAddress.value = pSGBuf->Buffer_DMA.value + ((MV_PU8)sg - (MV_PU8)pSGBuf->Buffer_Vir); sg += consumed; availSg -= consumed; pCmdTbl[SlotNo].XOR_PRD[sId].PRDTableAddress=tmpPhyAddress.parts.low; pCmdTbl[SlotNo].XOR_PRD[sId].PRDTableAddressHigh=tmpPhyAddress.parts.high; pCmdTbl[SlotNo].XOR_PRD[sId].Buffer0OpCode=OP_XOR_ENABLE; //XOR/* or we can do pCmdTbl[SlotNo].XOR_PRD[sId].DataByte0=pReq->Coef[0][sId]; pCmdTbl[SlotNo].XOR_PRD[sId].Buffer0OpCode=OP_GF_XOR_ENABLE; //1st GF+XOR*/ if(pReq->Target_SG_Table_Count>1) { pCmdTbl[SlotNo].XOR_PRD[sId].DataByte1=pReq->Coef[1][sId]; pCmdTbl[SlotNo].XOR_PRD[sId].Buffer1OpCode=OP_GF_XOR_ENABLE; //GF+XOR } } pCmdTbl[SlotNo].XOR_PRD[pReq->Source_SG_Table_Count].PRDEntryCount=1; //to workaround hardware no-action check pCmdTbl[SlotNo].XOR_PRD[pReq->Source_SG_Table_Count].Buffer0OpCode=OP_ZERO_CHECK_ENABLE; //Zero Check pCmdTbl[SlotNo].ValidEntry=pReq->Source_SG_Table_Count+1; // add 1 for the zero check entry pCmdTbl[SlotNo].InterruptEnable=1; pCore->XOR_Running_Req[SlotNo]=pReq; pCore->XOR_Req_Count++; XORPrepareDeliveryQueueEntry(pCore, SlotNo, &DELV_Q_Entry); XORWriteDELV_Q_Entry(pCore, &DELV_Q_Entry);// MV_DumpXORRegister(pCore); /* Request is sent to the hardware and not finished yet. */ pReq->Request_Status = XOR_STATUS_SUCCESS;}#endifvoid Core_HandleXORWaitingList(PCore_Driver_Extension pCore){ PMV_XOR_Request pXORReq = NULL; if( List_Empty(&pCore->XOR_Waiting_List) ) return; if(pCore->XOR_Req_Count>=pCore->Slot_Count_Supported) return; pXORReq = (PMV_XOR_Request)List_GetFirstEntry(&pCore->XOR_Waiting_List, MV_XOR_Request, Queue_Pointer);#ifdef RAID6_HARDWARE_XOR /* Allocate Core Driver Context to the XOR request. */ if ( pXORReq->Context[MODULE_CORE]==NULL ) { pXORReq->Context[MODULE_CORE] = GetCoreXORContextFromPool(pCore); if ( pXORReq->Context[MODULE_CORE]==NULL ) { MV_DASSERT(MV_FALSE); /* Shouldn't happen. Each XOR has a context. */ List_Add(&pXORReq->Queue_Pointer, &pCore->XOR_Waiting_List); return; } } else { MV_DASSERT(MV_FALSE); }#endif switch (pXORReq->Request_Type) { case XOR_REQUEST_WRITE: if( (pCore->Device_Id==DEVICE_ID_6440)&&(pCore->Revision_Id==0x0) ) XORWriteCommand_A1(pCore, pXORReq); else XORWriteCommand(pCore, pXORReq); break; case XOR_REQUEST_COMPARE: if( (pCore->Device_Id==DEVICE_ID_6440)&&(pCore->Revision_Id==0x0) ) XORCompareCommand_A1(pCore, pXORReq); else XORCompareCommand(pCore, pXORReq); break; case XOR_REQUEST_DMA: default: pXORReq->Request_Status = XOR_STATUS_INVALID_REQUEST; Core_CompleteXORReq(pCore, pXORReq); break; }}void Core_ModuleSendXORRequest(MV_PVOID This, PMV_XOR_Request pXORReq){ PCore_Driver_Extension pCore = (PCore_Driver_Extension)This; List_AddTail(&pXORReq->Queue_Pointer, &pCore->XOR_Waiting_List); if( !Tag_IsEmpty(&pCore->XOR_Tag_Pool) ) Core_HandleXORWaitingList(pCore);}MV_BOOLEAN HandleXORQueue_A1(MV_PVOID This){ PCore_Driver_Extension pCore = (PCore_Driver_Extension)This; PMV_XOR_Request pReq; MV_U32 reg; MV_U16 j; PXOR_COMPLETION_QUEUE_ENTRY pCMPL_Q; pCMPL_Q=(PXOR_COMPLETION_QUEUE_ENTRY)pCore->XOR_CMPL_Q; j=pCore->XOR_LastCMPL_Q; pCore->XOR_LastCMPL_Q=(MV_U16)(*(MV_U32 *)&pCMPL_Q[0])&0xfff; if(j==pCore->XOR_LastCMPL_Q) return MV_FALSE; if(pCore->XOR_LastCMPL_Q!=0xfff) { MV_U16 SlotNo; while(j!=pCore->XOR_LastCMPL_Q) { j++; if(j>=pCore->Slot_Count_Supported) j=0; SlotNo = (MV_U16)pCMPL_Q[j+1].SLOT_NM; if(pCore->XOR_Running_Req[SlotNo] == NULL) continue; pReq=pCore->XOR_Running_Req[SlotNo]; pReq->Request_Status = XOR_STATUS_SUCCESS; if(pCMPL_Q[j+1].CMD_ERR) { //MV_DumpXORRegister(This); reg = MV_REG_READ_DWORD(pCore->Mmio_Base, XOR_ERR_CODE); if(((PREG_XOR_ERR_CODE)®)->B0_ZR0_RSLT_CHK_ERR) pReq->Error_Offset = MV_REG_READ_DWORD(pCore->Mmio_Base, XOR_ERR_OFFSET0); else if(((PREG_XOR_ERR_CODE)®)->B1_ZR0_RSLT_CHK_ERR) pReq->Error_Offset = MV_REG_READ_DWORD(pCore->Mmio_Base, XOR_ERR_OFFSET1); MV_REG_WRITE_DWORD(pCore->Mmio_Base, XOR_ERR_CODE, 0); MV_REG_WRITE_DWORD(pCore->Mmio_Base, XOR_ERR_OFFSET0, 0); MV_REG_WRITE_DWORD(pCore->Mmio_Base, XOR_ERR_OFFSET1, 0); reg = MV_REG_READ_DWORD(pCore->Mmio_Base, XOR_IRQ_STAT); //Do we need to clear it again? MV_REG_WRITE_DWORD(pCore->Mmio_Base, XOR_IRQ_STAT, reg); pReq->Request_Status = XOR_STATUS_ERROR; } if(pCMPL_Q[j+1].CMD_CMPL) { pCore->XOR_Req_Count--; pCore->XOR_Running_Req[SlotNo]=NULL; Tag_ReleaseOne(&pCore->XOR_Tag_Pool, SlotNo); Core_CompleteXORReq(pCore, pReq); } } } Core_HandleXORWaitingList( pCore ); return MV_TRUE;}MV_BOOLEAN HandleXORQueue(MV_PVOID This){ PCore_Driver_Extension pCore = (PCore_Driver_Extension)This; PMV_XOR_Request pReq; MV_U32 reg; MV_U16 j; PXOR_COMPLETION_QUEUE_ENTRY pCMPL_Q; if( (pCore->Device_Id==DEVICE_ID_6440)&&(pCore->Revision_Id==0x0) ) return(HandleXORQueue_A1(This)); pCMPL_Q=(PXOR_COMPLETION_QUEUE_ENTRY)pCore->XOR_CMPL_Q; j=pCore->XOR_LastCMPL_Q; pCore->XOR_LastCMPL_Q=(MV_U16)(*(MV_U32 *)&pCMPL_Q[0])&0xfff; if(j==pCore->XOR_LastCMPL_Q) return MV_FALSE; if(pCore->XOR_LastCMPL_Q!=0xfff) { MV_U16 SlotNo; while(j!=pCore->XOR_LastCMPL_Q) { j++; if(j>=pCore->Slot_Count_Supported) j=0; SlotNo = (MV_U16)pCMPL_Q[j+1].SLOT_NM; if(pCore->XOR_Running_Req[SlotNo] == NULL) continue; pReq=pCore->XOR_Running_Req[SlotNo]; pReq->Request_Status = XOR_STATUS_SUCCESS; if(pCMPL_Q[j+1].CMD_ERR) { //MV_DumpXORRegister(This); reg = MV_REG_READ_DWORD(pCore->Mmio_Base, XOR_ERR_CODE); if(((PREG_XOR_ERR_CODE)®)->B0_ZR0_RSLT_CHK_ERR) pReq->Error_Offset = MV_REG_READ_DWORD(pCore->Mmio_Base, XOR_ERR_OFFSET0); else if(((PREG_XOR_ERR_CODE)®)->B1_ZR0_RSLT_CHK_ERR) pReq->Error_Offset = MV_REG_READ_DWORD(pCore->Mmio_Base, XOR_ERR_OFFSET1); MV_REG_WRITE_DWORD(pCore->Mmio_Base, XOR_ERR_CODE, 0); MV_REG_WRITE_DWORD(pCore->Mmio_Base, XOR_ERR_OFFSET0, 0); MV_REG_WRITE_DWORD(pCore->Mmio_Base, XOR_ERR_OFFSET1, 0); reg = MV_REG_READ_DWORD(pCore->Mmio_Base, XOR_IRQ_STAT); //Do we need to clear it again? MV_REG_WRITE_DWORD(pCore->Mmio_Base, XOR_IRQ_STAT, reg); pReq->Request_Status = XOR_STATUS_ERROR; } if(pCMPL_Q[j+1].CMD_CMPL) { pCore->XOR_Req_Count--; pCore->XOR_Running_Req[SlotNo]=NULL; Tag_ReleaseOne(&pCore->XOR_Tag_Pool, SlotNo); Core_CompleteXORReq(pCore, pReq); } } } Core_HandleXORWaitingList( pCore ); return MV_TRUE;}#ifdef RAID6_HARDWARE_XORBOOLEANXORWriteCommand_OneTable( IN PCore_Driver_Extension pCore, IN MV_U8 Source_SG_Table_Count, IN MV_U8 Target_SG_Table_Count, IN PMV_SG_Table Source_SG_Table_List, IN PMV_SG_Table Target_SG_Table_List, IN PXOR_COEF Coef, IN MV_U8 Max_Source_SG_Count, OUT PMV_XOR_Command_Table pCmdTbl, OUT PSG_Buffer * SG_Buffer ){ MV_U8 sId,tId; /* source index and target index. */ PMV_SG_Entry sg;#ifndef USE_NEW_SGTABLE MV_U32 i;#endif int consumed; PSG_Buffer pSGBuf, pNextSGBuf;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?