core_i2c.c
来自「6440linuxDriver的源代码」· C语言 代码 · 共 723 行 · 第 1/2 页
C
723 行
#include "core_header.h"#ifdef SUPPORT_I2C#include "core_exp.h"#include "core_i2c.h"#ifdef SUPPORT_ERROR_HANDLINGextern void Core_ReqTimeout (MV_PVOID This, MV_PVOID temp);#endifMV_U8 Read_I2C_Register(PCore_Driver_Extension pCore, MV_U8 regIndex){ MV_U32 reg; reg=0; ((PREG_I2C_SOFTWARE_CONTROL)®)->ADRS_PORT = regIndex; ((PREG_I2C_SOFTWARE_CONTROL)®)->READ_EN = 1; MV_IO_WRITE_DWORD(pCore->Base_Address[MV_PCI_BAR2],I2C_SOFTWARE_CONTROL,reg); reg=MV_IO_READ_DWORD(pCore->Base_Address[MV_PCI_BAR2],I2C_SOFTWARE_CONTROL); return((MV_U8)((PREG_I2C_SOFTWARE_CONTROL)®)->DATA_PORT);}voidWrite_I2C_Register(PCore_Driver_Extension pCore, MV_U8 regIndex, MV_U8 regVal){ MV_U32 reg; reg=0; ((PREG_I2C_SOFTWARE_CONTROL)®)->ADRS_PORT = regIndex; ((PREG_I2C_SOFTWARE_CONTROL)®)->DATA_PORT = regVal; ((PREG_I2C_SOFTWARE_CONTROL)®)->WRITE_EN = 1; MV_IO_WRITE_DWORD(pCore->Base_Address[MV_PCI_BAR2],I2C_SOFTWARE_CONTROL,reg); ((PREG_I2C_SOFTWARE_CONTROL)®)->WRITE_EN = 0; MV_IO_WRITE_DWORD(pCore->Base_Address[MV_PCI_BAR2],I2C_SOFTWARE_CONTROL,reg); return;}MV_U8 I2C_FindCCR(MV_U32 LinkRate){ MV_U8 n, m, bestN = 0, bestM = 0; MV_U32 expPortion, currentFreq, minDiff, currentDiff; minDiff = 0xFFFFFFFF;/* f=sys_clock/((M+1)*2^(N+1)), sys_clock=OscFreq/10 */ for(n=0; n<8; n++) { expPortion = 1<<(n+1); /*2^(N+1)*/ for(m=0; m<16; m++) { currentFreq=I2C_SYS_CLOCK/((m+1)*expPortion); currentDiff=(currentFreq<=LinkRate)?(LinkRate-currentFreq):0xFFFFFFFF; if(currentDiff<minDiff) { minDiff = currentDiff; bestN=n; bestM=m; } } } return((bestM<<3) | bestN );}MV_BOOLEAN I2C_InterruptServiceRoutine(MV_PVOID This){ PCore_Driver_Extension pCore=(PCore_Driver_Extension)This; void (*pCallBack)(MV_PVOID pExtension,MV_PVOID pContext); MV_U8 I2cCtlReg,I2cStatusReg; PDomain_I2cLink pI2cLink=&pCore->I2cLink; MV_U8 *pBuffer; MV_BOOLEAN bDoReset=MV_FALSE, bCompleted=MV_FALSE; PMV_Request pReq; MV_U32 reg; if( pI2cLink->pI2cRequest==NULL ){ return MV_FALSE; } pReq=(PMV_Request)pI2cLink->pI2cRequest; pBuffer=pReq->Data_Buffer; pCallBack=(void (*)(MV_PVOID pExtension,MV_PVOID pContext))pReq->Completion; if(pCallBack==NULL) return MV_FALSE; I2cCtlReg = Read_I2C_Register(pCore, MI2C_CONTROL); if( (!((PREG_MI2C_CONTROL)&I2cCtlReg)->IEN) || (!((PREG_MI2C_CONTROL)&I2cCtlReg)->IFLG) ) return MV_FALSE; I2cStatusReg = Read_I2C_Register(pCore, MI2C_STATUS); //MV_PRINT("* \n" ); //MV_PRINT("* I2C I2cCtlReg = 0x%x \n", I2cCtlReg); //MV_PRINT("* I2C pI2cLink->I2C_State = 0x%x \n", pI2cLink->I2C_State ); //MV_PRINT("* I2C I2cStatusReg = 0x%x \n", I2cStatusReg); switch(pI2cLink->I2C_State) { case I2C_STATE_CMD: switch(I2cStatusReg) { case MI2C_STATUS_START_TX: case MI2C_STATUS_ADDR_W_TX_ACK: case MI2C_STATUS_MDATA_TX_ACK: if(pI2cLink->I2cXferCount < pI2cLink->I2cCmdFrameLen) { if(pI2cLink->I2cCmdHeader[1]==I2C_CT_H2D_SES) {/* I2cCmdHeader = [6 bytes of cmd header]+[checksum] I2cCmdFrameLen = length of SES request page + 7*//*I2C_CT_H2D_SES: [6 bytes of cmd header]+[SES request page]+[checksum] */ if(pI2cLink->I2cXferCount<6) Write_I2C_Register(pCore,MI2C_DATA,pI2cLink->I2cCmdHeader[pI2cLink->I2cXferCount]); else if(pI2cLink->I2cXferCount==(pI2cLink->I2cCmdFrameLen-1)) Write_I2C_Register(pCore,MI2C_DATA,pI2cLink->I2cCmdHeader[6]); else Write_I2C_Register(pCore,MI2C_DATA,pBuffer[pI2cLink->I2cXferCount-6]); } else Write_I2C_Register(pCore,MI2C_DATA,pI2cLink->I2cCmdHeader[pI2cLink->I2cXferCount]);/*I2C_CT_D2H_SES: [6 bytes of cmd header]+[checksum] */ pI2cLink->I2cXferCount++; } else {/* last byte transfered, generate a STOP signal */ ((PREG_MI2C_CONTROL)&I2cCtlReg)->STP=1;/* move to next command phase, and reset the count for receiving */ pI2cLink->I2C_State=I2C_STATE_RESPONSE; pI2cLink->I2cXferCount=0; } break; default:/* error occurred */ if(pI2cLink->I2cXferCount) ((PREG_MI2C_CONTROL)&I2cCtlReg)->STP=1; else bDoReset=MV_TRUE; /* done, post command */ //MV_PRINT("Command terminated.\n"); pI2cLink->I2C_State=I2C_STATE_ERROR; pReq->Scsi_Status=REQ_STATUS_ERROR; bCompleted=MV_TRUE; break; } break; case I2C_STATE_RESPONSE: switch(I2cStatusReg) { case MI2C_STATUS_ADDR_W_TX_ACK: case MI2C_STATUS_MDATA_TX_ACK:/* STOP sent */ break; case MI2C_STATUS_SADDR_W_RX_ACK: case MI2C_STATUS_SADDR_DATA_RX_ACK: if(pI2cLink->I2cXferCount < pI2cLink->I2cRspFrameLen) {/* for response, I2cCmdHeader = [6 bytes of cmd header]+[status]+[checksum] I2cRspFrameLen = length of SES request page + 8*//*I2C_CT_H2D_SES: [6 bytes of cmd header]+[status]+[checksum]*/ if(pI2cLink->I2cCmdHeader[1]==I2C_CT_H2D_SES) pI2cLink->I2cCmdHeader[pI2cLink->I2cXferCount]=Read_I2C_Register(pCore, MI2C_DATA); else {/*I2C_CT_D2H_SES: [6 bytes of cmd header]+[status]+[SES response page]+[checksum] */ if(pI2cLink->I2cXferCount<7) pI2cLink->I2cCmdHeader[pI2cLink->I2cXferCount]=Read_I2C_Register(pCore, MI2C_DATA); else if(pI2cLink->I2cXferCount==(pI2cLink->I2cCmdFrameLen-1)) pI2cLink->I2cCmdHeader[7]=Read_I2C_Register(pCore, MI2C_DATA); else pBuffer[pI2cLink->I2cXferCount-7]=Read_I2C_Register(pCore, MI2C_DATA); } pI2cLink->I2cXferCount++; } else{ MV_PRINT("I2c Receiver buffer overflow, 0x%x\n",pI2cLink->I2cXferCount++); } break; case MI2C_STATUS_STOP_RX: /* done, post command */ //MV_PRINT("Command completed (MI2C_STATUS_STOP_RX).\n"); ((PREG_MI2C_CONTROL)&I2cCtlReg)->STP=1; pI2cLink->I2C_State=I2C_STATE_IDLE; pReq->Scsi_Status=REQ_STATUS_SUCCESS; bCompleted=MV_TRUE; break; default:/* error occurred */ bDoReset=MV_TRUE; /* done, post command */ //MV_PRINT("Command terminated.\n"); pReq->Scsi_Status=REQ_STATUS_ERROR; pI2cLink->I2C_State=I2C_STATE_ERROR; bCompleted=MV_TRUE; break; } break; case I2C_STATE_IDLE: case I2C_STATE_ERROR: default: bDoReset=MV_TRUE; break; }/* re-enable I2C : Write to MI2C_CONTROL Register */ ((PREG_MI2C_CONTROL)&I2cCtlReg)->IFLG=0; //MV_PRINT("* I2cCtlReg Int serivce 0x%x\n", I2cCtlReg); Write_I2C_Register(pCore, MI2C_CONTROL, I2cCtlReg); if(bDoReset) { Write_I2C_Register(pCore,MI2C_SOFT_RESET,0); Write_I2C_Register(pCore,MI2C_CLOCK_CONTROL,pI2cLink->I2C_Clock); } if(bCompleted) { //MV_PRINT("* I2C interrupt completed\n" ); reg = MV_REG_READ_DWORD(pCore->Mmio_Base, COMMON_IRQ_MASK); //MV_PRINT("* IRQ status = 0x%x\n", reg ); reg &= ~INT_SLAVE_I2C; //MV_PRINT("* IRQ status (after) = 0x%x\n", reg ); MV_REG_WRITE_DWORD(pCore->Mmio_Base, COMMON_IRQ_MASK, reg); pI2cLink->pI2cRequest=NULL;#if defined(SUPPORT_ERROR_HANDLING) && defined(_OS_WINDOWS) if ( pI2cLink->pI2cDevice->Outstanding_Req > 0 ) { pI2cLink->pI2cDevice->Outstanding_Req--; } /* request for this device came back, so we cancel the timer */ if( pI2cLink->pI2cDevice->Timer_ID != NO_CURRENT_TIMER ) { Timer_CancelRequest( pCore, pI2cLink->pI2cDevice->Timer_ID ); pI2cLink->pI2cDevice->Timer_ID = NO_CURRENT_TIMER; } /* if there are more outstanding requests, we send a new timer */ if ( pI2cLink->pI2cDevice->Outstanding_Req > 0 ) { pI2cLink->pI2cDevice->Timer_ID = Timer_AddRequest( pCore, REQUEST_TIME_OUT, Core_ReqTimeout, pI2cLink->pI2cDevice, NULL ); }#endif /* defined(SUPPORT_ERROR_HANDLING) && defined(_OS_WINDOWS) */ pCallBack(pCore, pReq); } return MV_TRUE;}voidI2C_SendI2cFrame(MV_PVOID This, PMV_Request pReq){ PCore_Driver_Extension pCore=(PCore_Driver_Extension)This; PDomain_I2cLink pI2cLink=&pCore->I2cLink; MV_U8 I2cCtlReg; Write_I2C_Register(pCore,MI2C_DATA,pI2cLink->I2cCmdHeader[0]); pI2cLink->I2cXferCount=0; pI2cLink->I2C_State=I2C_STATE_CMD; pI2cLink->pI2cRequest=pReq; I2cCtlReg = Read_I2C_Register(pCore, MI2C_CONTROL); ((PREG_MI2C_CONTROL)&I2cCtlReg)->STA=1; Write_I2C_Register(pCore, MI2C_CONTROL, I2cCtlReg);}MV_U8 I2C_SataChecksum(MV_U8* buffer, MV_U32 length, MV_U8 sumseed){ MV_U8 checksum; MV_U32 index; checksum=-sumseed; /* Calculate the IPMB based checksum and return */ for(index = 0; index < length; index ++) { checksum += buffer[index]; } /* Return type is a byte, a negative value is automatically adjusted */ return -checksum;}#define I2C_STD_INQUIRY_SIZE 36#ifndef _OS_BIOS MV_U8 BASEATTR I2C_INQUIRY_DEVICE_DATA[I2C_STD_INQUIRY_SIZE] = { 0x0D, 0x00, 0x05, 0x02, I2C_STD_INQUIRY_SIZE-5, 0x00, 0x40, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };#define I2C_VPD_PAGE0_SIZE 7MV_U8 BASEATTR I2C_INQUIRY_VPD_PAGE0_DATA[I2C_VPD_PAGE0_SIZE] = { 0x0D, 0x00, 0x00, 0x03, 0x00, 0x80, 0x83};/* VP PG80 Unit Serial Number, Header only */#define I2C_VPD_PAGE80_SIZE 4MV_U8 BASEATTR I2C_INQUIRY_VPD_PAGE80_DATA[I2C_VPD_PAGE80_SIZE] = { 0x0D, 0x80, 0x00, 0x00};/* VP PG83 Device Identification, Emulated whole page */#define I2C_VPD_PAGE83_SIZE 0x18MV_U8 BASEATTR I2C_INQUIRY_VPD_PAGE83_DATA[I2C_VPD_PAGE83_SIZE] = { 0x0D, 0x83, 0x00, 0x14, 0x61, 0x93, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x94, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00};#endif /* #ifndef _OS_BIOS */MV_U32I2C_MakeSerialNumber( MV_PU8 pString, PIDENTIFY_SEP_DATA pSepIdentify, MV_U32 BufferLen ){ MV_U32 i; MV_CopyMemory(pString, pSepIdentify->vendorID, MV_MIN(BufferLen, 8)); for(i=0;(((i*2)+8)<BufferLen)&&(i<8);i++) sprintf((pString+8+(i*2)),"%02x",pSepIdentify->logicalID[7-i]); return MV_MIN(BufferLen, (i*2)+8);}MV_QUEUE_COMMAND_RESULTI2C_InquiryCmd( PDomain_I2cLink pI2cLink, PMV_Request pMvReq ){ PIDENTIFY_SEP_DATA pSepIdentify=(PIDENTIFY_SEP_DATA)(pI2cLink->I2cIdentify); MV_U8 statusCode = REQ_STATUS_SUCCESS; MV_U8 senseKey = 0, adSenseCode = 0; MV_U32 tmpLen = 0; if ( (pMvReq->Cdb[1] & CDB_INQUIRY_EVPD)==0) { /* Shall return standard INQUIRY data */ if (pMvReq->Cdb[2]!=0) { /* PAGE CODE field must be zero when EVPD is zero for a valid request */ /* sense key as ILLEGAL REQUEST and additional sense code as INVALID FIELD IN CDB */ statusCode = REQ_STATUS_HAS_SENSE; senseKey = SCSI_SK_ILLEGAL_REQUEST; adSenseCode = SCSI_ASC_INVALID_FEILD_IN_CDB; } else { tmpLen = MV_MIN(pMvReq->Data_Transfer_Length, I2C_STD_INQUIRY_SIZE); MV_CopyMemory(pMvReq->Data_Buffer, I2C_INQUIRY_DEVICE_DATA, tmpLen); if (pMvReq->Data_Transfer_Length > 8) { MV_CopyMemory((MV_PU8)(pMvReq->Data_Buffer)+8, pSepIdentify->vendorID, MV_MIN((pMvReq->Data_Transfer_Length - 8), 8)); if(pMvReq->Data_Transfer_Length > 16) { MV_CopyMemory((MV_PU8)(pMvReq->Data_Buffer)+16, pSepIdentify->productID, MV_MIN((pMvReq->Data_Transfer_Length - 16), 16)); if(pMvReq->Data_Transfer_Length > 32) MV_CopyMemory((MV_PU8)(pMvReq->Data_Buffer)+32, pSepIdentify->revisionLevel, MV_MIN((pMvReq->Data_Transfer_Length - 32), 4)); } } } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?