core_i2c.c
来自「6440linuxDriver的源代码」· C语言 代码 · 共 723 行 · 第 1/2 页
C
723 行
else { /* Shall return the specific page of Vital Production Data */ switch (pMvReq->Cdb[2]) { case 0x00: /* Supported VPD pages */ tmpLen = MV_MIN(pMvReq->Data_Transfer_Length, I2C_VPD_PAGE0_SIZE);/* supported VPD page */ MV_CopyMemory(pMvReq->Data_Buffer, I2C_INQUIRY_VPD_PAGE0_DATA, tmpLen); break; case 0x80: /* Unit Serial Number VPD Page */ tmpLen = MV_MIN(pMvReq->Data_Transfer_Length, I2C_VPD_PAGE80_SIZE); MV_CopyMemory(pMvReq->Data_Buffer, I2C_INQUIRY_VPD_PAGE80_DATA, tmpLen); if (pMvReq->Data_Transfer_Length > I2C_VPD_PAGE80_SIZE) { tmpLen = I2C_MakeSerialNumber( (MV_PU8)(pMvReq->Data_Buffer)+I2C_VPD_PAGE80_SIZE, pSepIdentify, pMvReq->Data_Transfer_Length - I2C_VPD_PAGE80_SIZE); *(((MV_PU8)(pMvReq->Data_Buffer)) + 3) = I2C_VPD_PAGE80_SIZE + 24;/* serial number= 8 charactors of Vendor String + 16 charactors of 8 bytes-naa id */ tmpLen += I2C_VPD_PAGE80_SIZE; } break; case 0x83: /* Device Identification VPD Page */ tmpLen = MV_MIN(pMvReq->Data_Transfer_Length, I2C_VPD_PAGE83_SIZE); MV_CopyMemory(pMvReq->Data_Buffer, I2C_INQUIRY_VPD_PAGE83_DATA, tmpLen); if (pMvReq->Data_Transfer_Length > 8) { MV_CopyMemory((MV_PU8)(pMvReq->Data_Buffer)+8, pSepIdentify->logicalID, MV_MIN((pMvReq->Data_Transfer_Length - 8), 8)); if(pMvReq->Data_Transfer_Length > 23) *((MV_PU8)(pMvReq->Data_Buffer)+ 23)=pSepIdentify->channelID; } break; default: statusCode = REQ_STATUS_HAS_SENSE; senseKey = SCSI_SK_ILLEGAL_REQUEST; adSenseCode = SCSI_ASC_INVALID_FEILD_IN_CDB; break; } } if (statusCode==REQ_STATUS_HAS_SENSE) { if (pMvReq->Sense_Info_Buffer != NULL) { ((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = 0x70; /* Current */ ((MV_PU8)pMvReq->Sense_Info_Buffer)[2] = senseKey; ((MV_PU8)pMvReq->Sense_Info_Buffer)[7] = 0; /* additional sense length */ ((MV_PU8)pMvReq->Sense_Info_Buffer)[12] = adSenseCode; /* additional sense code */ } } pMvReq->Data_Transfer_Length = tmpLen; pMvReq->Scsi_Status=statusCode; return MV_QUEUE_COMMAND_RESULT_FINISHED;}MV_QUEUE_COMMAND_RESULTI2C_PrepareAndSendCommand( IN PCore_Driver_Extension pCore, IN PMV_Request pReq ){ MV_U32 reg; int i = 0; PDomain_I2cLink pI2cLink=&pCore->I2cLink; if( (pI2cLink->I2C_State==I2C_STATE_CMD)|| (pI2cLink->I2C_State==I2C_STATE_RESPONSE) ) return MV_QUEUE_COMMAND_RESULT_FULL; switch(pReq->Cdb[0]) { case SCSI_CMD_INQUIRY: return I2C_InquiryCmd(pI2cLink,pReq); case I2C_CMD_IDENTIFY_SEP: case SCSI_CMD_RCV_DIAG_RSLT:/* build the I2C SEP command frame */ pI2cLink->I2cCmdHeader[0] = (pReq->Req_Flag & REQ_FLAG_EXTERNAL) ? pReq->Cdb[1] : pI2cLink->I2cSEP_Address; pI2cLink->I2cCmdHeader[1] = I2C_CT_D2H_SES; pI2cLink->I2cCmdHeader[2] = I2C_SataChecksum(pI2cLink->I2cCmdHeader, 2, 0); pI2cLink->I2cCmdHeader[3] = (pReq->Req_Flag & REQ_FLAG_EXTERNAL) ? pReq->Cdb[3] : I2C_SEMB_ADDR; pI2cLink->I2cCmdHeader[4] = 0; /*pI2cLink->I2cCmdHeader[4] = i2cCmdSeq++;*/ pI2cLink->I2cCmdHeader[5] = pReq->Cdb[0]; pI2cLink->I2cCmdHeader[6] = I2C_SataChecksum(&pI2cLink->I2cCmdHeader[3], 3, 0); pI2cLink->I2cCmdFrameLen = 7; pI2cLink->I2cRspFrameLen= 8 + (MV_U16)pReq->Data_Transfer_Length; break; case SCSI_CMD_SND_DIAG:/* build the I2C SEP command frame */ pI2cLink->I2cCmdHeader[0] = (pReq->Req_Flag & REQ_FLAG_EXTERNAL) ? pReq->Cdb[1] : pI2cLink->I2cSEP_Address; pI2cLink->I2cCmdHeader[1] = I2C_CT_H2D_SES; pI2cLink->I2cCmdHeader[2] = I2C_SataChecksum(pI2cLink->I2cCmdHeader, 2, 0); pI2cLink->I2cCmdHeader[3] = (pReq->Req_Flag & REQ_FLAG_EXTERNAL) ? pReq->Cdb[3] : I2C_SEMB_ADDR; pI2cLink->I2cCmdHeader[4] = 0; /*pCore->I2cCmdHeader[4] = i2cCmdSeq++;*/ pI2cLink->I2cCmdHeader[5] = pReq->Cdb[0]; pI2cLink->I2cCmdHeader[6] = I2C_SataChecksum(pReq->Data_Buffer, pReq->Data_Transfer_Length, I2C_SataChecksum(&pI2cLink->I2cCmdHeader[3], 3, 0)); pI2cLink->I2cCmdFrameLen = 7 + (MV_U16)pReq->Data_Transfer_Length; pI2cLink->I2cRspFrameLen= 8 + (MV_U16)pReq->Data_Transfer_Length; break; default: pReq->Scsi_Status = REQ_STATUS_INVALID_REQUEST; return MV_QUEUE_COMMAND_RESULT_FINISHED; } reg = MV_REG_READ_DWORD(pCore->Mmio_Base, COMMON_IRQ_MASK); reg |= INT_SLAVE_I2C; MV_REG_WRITE_DWORD(pCore->Mmio_Base, COMMON_IRQ_MASK, reg); I2C_SendI2cFrame(pCore,pReq); return MV_QUEUE_COMMAND_RESULT_SENT;}static MV_BOOLEAN I2C_DeviceStateMachine( PCore_Driver_Extension pCore, PDomain_Device pDevice );void I2C_IdentifyCallback( IN MV_PVOID This, IN PMV_Request pReq){ PCore_Driver_Extension pCore = (PCore_Driver_Extension)This; PDomain_I2cLink pI2cLink=&pCore->I2cLink; PDomain_Port pPort; PDomain_Device pDevice = NULL; pPort = &pCore->Ports[MapPortEntry(pCore,MapPortId(pCore, pReq->Device_Id))]; pDevice = &pCore->Devices[MapDeviceId(pCore, pReq->Device_Id)]; if( pReq->Scsi_Status==REQ_STATUS_ERROR ) { MV_PRINT("I2C callback error\n"); pDevice->Status &=~DEVICE_STATUS_FUNCTIONAL; pDevice->State = DEVICE_STATE_RESET_DONE; } else { MV_PRINT("I2C Connected\n"); MV_CopyMemory(pI2cLink->I2cIdentify,pReq->Data_Buffer,64); pDevice->State = DEVICE_STATE_IDENTIFY_DONE; } if( pReq->Scratch_Buffer ) FreeSATAScratchToPool(pCore, (PSATA_Scratch_Buffer *) &pReq->Scratch_Buffer); FreeInternalReqToPool(pCore, pReq); I2C_DeviceStateMachine(pCore, pDevice);}voidI2C_MakeIdentifyRequest(PDomain_Device pDevice){ PCore_Driver_Extension pCore = pDevice->pPort->Core_Extension; PMV_Request pReq = GetInternalReqFromPool(pCore); PSATA_Scratch_Buffer pSATASB; PMV_SG_Table pSGTable; if( pReq == NULL ) { // no internal requests available - wait for now pDevice->Is_Waiting = MV_TRUE; return; } pSATASB = GetSATAScratchFromPool(pCore); if( pSATASB == NULL ) { FreeInternalReqToPool(pCore, pReq); MV_DPRINT(("ERROR: No more free SATA scratch buffer. Request aborted.\n")); return; } pSGTable = &pReq->SG_Table; /* Prepare identify */ pReq->Cdb[0] = I2C_CMD_IDENTIFY_SEP; pReq->Tag = 0xac; pReq->Device_Id = pDevice->Id; //pReq->Req_Flag; pReq->Cmd_Initiator = pDevice->pPort->Core_Extension; pReq->Data_Transfer_Length = 64; pReq->Data_Buffer = pSATASB->Scratch_Vir; pReq->Scratch_Buffer = pSATASB; pReq->Completion = (void(*)(MV_PVOID,PMV_Request))I2C_IdentifyCallback;/* current I2c doesn't need DMA, but kept for future HW change. Make SG table */ SGTable_Init(pSGTable, 0); SGTable_Append(pSGTable, pSATASB->Scratch_DMA.parts.low, pSATASB->Scratch_DMA.parts.high, pReq->Data_Transfer_Length ); /* Send this internal request */ I2C_PrepareAndSendCommand(pCore, pReq);}/* Search through possible address - Starting with the default addresses of C0 and c2. If the two fails then start trying from 00 till FF. Return: TRUE if there are valid addresses to try FALSE if there are no valid addresses to try */MV_BOOLEAN I2C_CycleAddress( PDomain_I2cLink pI2cLink ){ static MV_U16 numSearches = 0; if( numSearches == 0 ) { //MV_PRINT("* Try Address 0xC0 \n"); pI2cLink->I2cSEP_Address = I2C_SEP_ADDR0; numSearches++; return MV_TRUE; } else if( numSearches == 1 ) { //MV_PRINT("* Try Address 0xC2 \n"); pI2cLink->I2cSEP_Address = I2C_SEP_ADDR1; numSearches++; return MV_TRUE; // disable multi-I2C address search /*} else if( numSearches > 1 && numSearches < 0x10 ) { pI2cLink->I2cSEP_Address = I2C_SEP_ADDR0 + (numSearches*2); MV_PRINT("* Try Address 0x%x \n", pI2cLink->I2cSEP_Address ); numSearches++; return MV_TRUE;*/ } else { //MV_PRINT("* Tried all addresses \n" ); return MV_FALSE; }}static void I2C_StopModule(MV_PVOID This){ MV_U8 regI2c; PCore_Driver_Extension pCore=(PCore_Driver_Extension)This; Write_I2C_Register(pCore, MI2C_SOFT_RESET, 0); Write_I2C_Register(pCore,MI2C_CONTROL,0);}static MV_BOOLEAN I2C_DeviceStateMachine( PCore_Driver_Extension pCore, PDomain_Device pDevice ){ PDomain_Port pPort = pDevice->pPort; PDomain_I2cLink pI2cLink=&pCore->I2cLink; switch ( pDevice->State ) { case DEVICE_STATE_RESET_DONE: //MV_DPRINT(("I2C Device %d DEVICE_STATE_RESET_DONE.\n", pDevice->Id)); pI2cLink->pI2cDevice=pDevice; /* To do inquiry */ if( I2C_CycleAddress( pI2cLink ) ){ //MV_PRINT("pI2cLink->I2cSEP_Address = 0x%x \n", pI2cLink->I2cSEP_Address ); I2C_MakeIdentifyRequest( pDevice ); break; } pDevice->State = DEVICE_STATE_IDENTIFY_DONE; I2C_StopModule(pCore); case DEVICE_STATE_IDENTIFY_DONE: //MV_DPRINT(("I2C Device %d DEVICE_STATE_IDENTIFY_DONE.\n", pDevice->Id)); pDevice->State=DEVICE_STATE_INIT_DONE; if(!(pDevice->Status&DEVICE_STATUS_FUNCTIONAL)) { List_Del( &pDevice->Queue_Pointer ); FreeDeviceToPool(pCore, pDevice); pPort->Device_Number--; pI2cLink->pI2cDevice=NULL; FreePortToPool(pCore, pPort); } default: /* The first time initialization */ core_start_cmpl_notify(pCore->desc); break; } return MV_TRUE;}voidCheckI2CDevice(MV_PVOID This){ PCore_Driver_Extension pCore=(PCore_Driver_Extension)This; PDomain_Port pPort; PDomain_Device pDevice = NULL;/* first Create a virtual port and a virtual device. */ pPort = GetPortFromPool(pCore); if(pPort==NULL) return;/* a virtual port is a port with no phy in its MemberPhyMap. */ pPort->MemberPhyMap=0; pPort->Type = PORT_TYPE_SAS|PORT_TYPE_I2C; /* it is emulated as a SSP SES device */ pPort->Port_State = PORT_STATE_INIT_DONE; /* don't block the channel state machine */ pPort->DiscoveryInstance = 0; pPort->Core_Extension = pCore; pPort->Expander_Number=0; pDevice = GetDeviceFromPool( pCore ); if( pDevice == NULL ) { FreePortToPool(pCore, pPort); return; }/* create a virtual SES device. */ pDevice->Status = DEVICE_STATUS_EXISTING | DEVICE_STATUS_FUNCTIONAL; pDevice->State = DEVICE_STATE_RESET_DONE; pDevice->Connection = DC_SCSI | DC_SERIAL; pDevice->Dev_Type = DT_ENCLOSURE; U64_ZERO_VALUE(pDevice->Max_LBA); if (pCore->State == CORE_STATE_STARTED) pDevice->Need_Notify = MV_TRUE; U64_ZERO_VALUE(pDevice->SASAddr); pDevice->pPort = pPort; pPort->Device_Number=1; List_AddTail( &pDevice->Queue_Pointer, &pPort->Device_List ); I2C_DeviceStateMachine(pCore, pDevice );}void I2C_ModuleInitialize(MV_PVOID This){ PCore_Driver_Extension pCore=(PCore_Driver_Extension)This; PDomain_I2cLink pI2cLink=&pCore->I2cLink; MV_U32 reg; MV_U8 regI2c; Write_I2C_Register(pCore, MI2C_SOFT_RESET, 0); regI2c=0; ((PREG_MI2C_CONTROL)®I2c)->ENAB=1; ((PREG_MI2C_CONTROL)®I2c)->IEN=1; ((PREG_MI2C_CONTROL)®I2c)->AAK=1; Write_I2C_Register(pCore,MI2C_CONTROL,regI2c); Write_I2C_Register(pCore,MI2C_SLAVE_ADDRESS,I2C_SEMB_ADDR); Write_I2C_Register(pCore,MI2C_X_SLAVE_ADDRESS,0); /* set the baud rate register to */ regI2c=I2C_FindCCR(I2C_LINK_RATE); Write_I2C_Register(pCore,MI2C_CLOCK_CONTROL,regI2c); //MV_PRINT("Clk Frequency regI2c = 0x%x\n", regI2c ); pI2cLink->I2C_Clock=regI2c; CheckI2CDevice(This); return;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?