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)&reg)->B0_ZR0_RSLT_CHK_ERR)					pReq->Error_Offset = MV_REG_READ_DWORD(pCore->Mmio_Base, XOR_ERR_OFFSET0);				else if(((PREG_XOR_ERR_CODE)&reg)->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)&reg)->B0_ZR0_RSLT_CHK_ERR)					pReq->Error_Offset = MV_REG_READ_DWORD(pCore->Mmio_Base, XOR_ERR_OFFSET0);				else if(((PREG_XOR_ERR_CODE)&reg)->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 + -
显示快捷键?