/* * Brief: Implement IPMB send and receive function in this file, include primary IPMB and secondary IPMB. * Author: Jimbo_Zhang@outlook.com * Date: 2019-9-9 */ /* Standard includes. */ #include #include #include #include #include #include #include #include "com_IPMI_LANIfc.h" #include "com_IPMI_RMCP.h" #include "RMCP.h" #include "LANIfc.h" #include "com_IPMIDefs.h" #include "RMCP.h" #include "MD.h" #include /* getaddrinfo(3) et al. */ #include /* sockaddr_in & sockaddr_in6 definition. */ #include #include #include "main.h" #include "Session.h" #include "com_IPMI_SDR.h" #include "com_IPMI_Storage.h" #include "SDR.h" #include /*此头必须带上*/ pid_t gettid() { return syscall(SYS_gettid); /*这才是内涵*/ } //static int sendIPMBPkt(uint32_t ipmb_bus, uint8_t* i2c_send_buf, uint8_t size); static uint8_t ValidateIPMBChkSums ( uint8_t* Data, uint8_t Size); static void ProcessIPMBReq ( MsgPkt_T* pReq); uint8_t IsResponseMatch (MsgPkt_T* pReq, MsgPkt_T* pRes); static void* RecvIPMBPkt (void *pArg); int gFd_PrimaryIpmbIfcQ, gFd_PrimaryIpmbResQ; int gFd_SecondaryIpmbIfcQ, gFd_SecondaryIpmbResQ; int gFd_Primary, gFd_Secondary; pthread_mutex_t primary_mutex, secondary_mutex; /*! \brief IPMB Task. Generating primary_IPMB task and secondary_IPMB task in this task. \param: 0: primary ipmb, 1: secondary ipmb \retval none */ void *IPMBIfcTask(void *Param) { // int i; MsgPkt_T RcvMsgPkt; uint8_t dev_name[10] = {0}; uint8_t IPMB_IFC_Q[32] = {0}; uint8_t IPMB_RES_Q[32] = {0}; uint8_t OwnerAddr; int fd_IpmbDev; int fd_IpmbIfcQ, fd_IpmbResQ; uint8_t ipmbSelect = *(uint8_t*)Param; int RetVal; pthread_mutex_t *pMutex; //printf("ipmbSelect: %d\n", ipmbSelect); //Primary IPMB if((ipmbSelect == 0) && g_BMCInfo.IpmiConfig.PrimaryIPMBSupport) { printf("Primary IPMBIfcTask start...\n"); strcpy(IPMB_IFC_Q, PRIMARY_IPMB_IFC_Q); strcpy(IPMB_RES_Q, PRIMARY_IPMB_RES_Q); sprintf(dev_name, "/dev/i2c%d", g_BMCInfo.IpmiConfig.PrimaryIPMBBus); OwnerAddr = g_BMCInfo.PrimaryIPMBAddr; pMutex = &primary_mutex; } //Secondary IPMB else if((ipmbSelect == 1) && g_BMCInfo.IpmiConfig.SecondaryIPMBSupport) { printf("Secondary IPMBIfcTask start...\n"); strcpy(IPMB_IFC_Q, SECONDARY_IPMB_IFC_Q); strcpy(IPMB_RES_Q, SECONDARY_IPMB_RES_Q); sprintf(dev_name, "/dev/i2c%d", g_BMCInfo.IpmiConfig.SecondaryIPMBBus); OwnerAddr = g_BMCInfo.SecondaryIPMBAddr; pMutex = &secondary_mutex; } else { printf("Invalid param! %d\n", ipmbSelect); return (void *)-1; } //create IPMB_IFC_Q if(-1 != access(IPMB_IFC_Q, F_OK)) { remove(IPMB_IFC_Q); } if(0 != mkfifo (IPMB_IFC_Q, 0777)) { printf("%s: Create %s fifo failed! %s\n", __FUNCTION__, IPMB_IFC_Q, strerror(errno)); return (void*)-1; } fd_IpmbIfcQ = open (IPMB_IFC_Q, O_RDWR); if(-1 == fd_IpmbIfcQ) { printf("%s: Open %s fifo failed! %s\n", __FUNCTION__, IPMB_IFC_Q, strerror(errno)); return (void*)-1; } //create IPMB_RES_Q if(-1 != access(IPMB_RES_Q, F_OK)) { remove(IPMB_RES_Q); } if(0 != mkfifo (IPMB_RES_Q, 0777)) { printf("%s: Create %s fifo failed! %s\n", __FUNCTION__, IPMB_RES_Q, strerror(errno)); return (void*)-1; } fd_IpmbResQ = open (IPMB_RES_Q, O_RDWR); if(-1 == fd_IpmbResQ) { printf("%s: Open %s fifo failed! %s\n", __FUNCTION__, IPMB_RES_Q, strerror(errno)); return (void*)-1; } fd_IpmbDev = open (dev_name, O_RDWR); if(-1 == fd_IpmbDev) { printf("%s: Open IPMB failed! %s\n", __FUNCTION__, strerror(errno)); return (void*)-1; } //set IPMB address if(0 != stm32_i2c_set_addr(fd_IpmbDev, OwnerAddr)) printf("Set ipmb address fail.\n"); if(ipmbSelect == 0) { gFd_PrimaryIpmbIfcQ = fd_IpmbIfcQ; gFd_PrimaryIpmbResQ = fd_IpmbResQ; gFd_Primary = fd_IpmbDev; } else if(ipmbSelect == 1) { gFd_SecondaryIpmbIfcQ = fd_IpmbIfcQ; gFd_SecondaryIpmbResQ = fd_IpmbResQ; gFd_Secondary = fd_IpmbDev; } pthread_mutex_init(pMutex, NULL); /*Create a thread to recv IPMB Pkt */ gThreadIndex++; if(0 != pthread_create(&gThreadIDs[gThreadIndex],NULL,RecvIPMBPkt,Param)) { printf("%s: Create RecvIPMBPkt thread failed! %s\n", __FUNCTION__, strerror(errno)); return (void *)-1; } while(1) { while(GetMsg(fd_IpmbIfcQ, &RcvMsgPkt, WAIT_INFINITE) != 0); switch(RcvMsgPkt.Param) { case PARAM_REQUEST: //printf("---> IPMBIfcTask/PARAM_REQUEST\n"); ProcessIPMBReq (&RcvMsgPkt); break; case PARAM_BRIDGE: //printf("---> IPMBIfcTask/PARAM_BRIDGE, channel: %d\n", RcvMsgPkt.Channel); /* Send the response */ if(RcvMsgPkt.Channel == PRIMARY_IPMB_CHANNEL) { RetVal = stm32_i2c_master_write(gFd_Primary, RcvMsgPkt.Data[0], &RcvMsgPkt.Data[1], RcvMsgPkt.Size-1); printf("PriTx: "); } else if(RcvMsgPkt.Channel == SECONDARY_IPMB_CHANNEL) { RetVal = stm32_i2c_master_write(gFd_Secondary, RcvMsgPkt.Data[0], &RcvMsgPkt.Data[1], RcvMsgPkt.Size-1); printf("SecTx: "); } else { printf("IPMBIfc.c: IPMB channel error. %#x\r\n", RcvMsgPkt.Channel); } int i; for(i=0;iData; int RetVal = 0; ReqLen = pReq->Size; /* Validate Checksums */ if (TRUE != ValidateIPMBChkSums ((uint8_t*)pIPMIMsgReq, ReqLen)) { printf ("IPMBIfc.c : IPMB Checksum validation failed\r\n"); return; } pReq->Param = PARAM_IFC; pReq->Cmd = pIPMIMsgReq->Cmd; pReq->NetFnLUN = pIPMIMsgReq->NetFnLUN; if(pReq->Channel == PRIMARY_IPMB_CHANNEL) pReq->SrcQ = gFd_PrimaryIpmbResQ; else pReq->SrcQ = gFd_SecondaryIpmbResQ; if(0 == ValidateMsgHdr(pReq)) { /* Post the message to message handler Task */ if (0 != PostMsg (gFd_MsgHndlrIfc, pReq)) { printf("IPMB post message to MsgHndlrTask fail!\n");; } } else { //printf("Bridge response to Originator\n"); return; } /* Post the message to message handler Task */ //PostMsg (gFd_MsgHndlrIfc, pReq); if(pReq->ResTimeOut < 1) pReq->ResTimeOut = 10; do { if(pReq->Channel == PRIMARY_IPMB_CHANNEL) { RetVal = GetMsg (gFd_PrimaryIpmbResQ, &ResPkt, pReq->ResTimeOut); if((pReq->Cmd == CMD_GET_SDR) && (pReq->NetFnLUN == (NETFN_STORAGE<<2)) && (pReq->Data[4+6] == 5)) { ResPkt.Data[3+6] = g_BMCInfo.PrimaryIPMBAddr; ResPkt.Data[ResPkt.Size-1] = CalculateCheckSum (ResPkt.Data, ResPkt.Size-1); } } else { RetVal = GetMsg (gFd_SecondaryIpmbResQ, &ResPkt, pReq->ResTimeOut); //为传感器的owner ID打的补丁 if((pReq->Cmd == CMD_GET_SDR) && (pReq->NetFnLUN == (NETFN_STORAGE<<2)) && (pReq->Data[4+6] == 5)) { ResPkt.Data[3+6] = g_BMCInfo.SecondaryIPMBAddr; ResPkt.Data[ResPkt.Size-1] = CalculateCheckSum (ResPkt.Data, ResPkt.Size-1); } } }while(!RetVal && !IsResponseMatch(pReq, &ResPkt) ); if (0 != RetVal) { printf("Warning: Process IPMB request fail, return timeout.\r\n"); ResPkt.Param = PARAM_NORMAL_RESPONSE; ResPkt.Size = sizeof(IPMIMsgHdr_T)+2; SwapIPMIMsgHdr(((IPMIMsgHdr_T*)pReq->Data), ((IPMIMsgHdr_T*)ResPkt.Data)); ResPkt.Data[sizeof(IPMIMsgHdr_T)] = CC_TIMEOUT; ResPkt.Data[sizeof(IPMIMsgHdr_T)+1] = CalculateCheckSum2(ResPkt.Data, sizeof(IPMIMsgHdr_T)+1); } /* If its not normal IPMI Response just return */ if (PARAM_NO_RESPONSE == ResPkt.Param) { printf ("IPMBIfc.c : IPMB request packet dropped, not processed\n"); return; } /* Send the response */ if(pReq->Channel == PRIMARY_IPMB_CHANNEL) { pthread_mutex_lock(&primary_mutex); RetVal = stm32_i2c_master_write(gFd_Primary, ResPkt.Data[0], &ResPkt.Data[1], ResPkt.Size-1); pthread_mutex_unlock(&primary_mutex); printf("PriTx: "); } else if(pReq->Channel == SECONDARY_IPMB_CHANNEL) { pthread_mutex_lock(&secondary_mutex); RetVal = stm32_i2c_master_write(gFd_Secondary, ResPkt.Data[0], &ResPkt.Data[1], ResPkt.Size-1); pthread_mutex_unlock(&secondary_mutex); printf("SecTx: "); } else { printf("IPMBIfc.c: IPMB channel error. %#x\r\n", pReq->Channel); } int i; for(i=0;iData)->RqSeqLUN) >> 2) != ((((IPMIMsgHdr_T*)pReq->Data)->RqSeqLUN) >> 2) ) && ( (pReq->NetFnLUN & 0x4) && (PARAM_NO_RESPONSE != pRes->Param) ) ) { return FALSE; } return TRUE; } /** * @fn RecvIPMBPkt * @brief This function receives IPMB request packet and post the message to * IPMB interface queue **/ static void* RecvIPMBPkt (void *Param) { MsgPkt_T IPMBReqPkt; int IPMBSlaveFd; int retval; uint8_t ipmbSelect = *(uint8_t*)Param; int i; prctl(PR_SET_NAME, __FUNCTION__, 0, 0, 0); int curThreadIndex = 0; pthread_mutex_t *pMutex; memset(&IPMBReqPkt,0,sizeof(MsgPkt_T)); if(0 == ipmbSelect) { printf ("Primary IPMB Receiver Started...\n"); IPMBReqPkt.Data [0] = g_BMCInfo.PrimaryIPMBAddr; IPMBReqPkt.Channel = PRIMARY_IPMB_CHANNEL; IPMBSlaveFd = gFd_Primary; pMutex = &primary_mutex; //printf("Primary: %p\n", RecvIPMBPkt); } else if(1 == ipmbSelect) { printf ("Secondary IPMB Receiver Started...\n"); IPMBReqPkt.Data [0] = g_BMCInfo.SecondaryIPMBAddr; IPMBReqPkt.Channel = SECONDARY_IPMB_CHANNEL; IPMBSlaveFd = gFd_Secondary; pMutex = &secondary_mutex; //printf("Secondary: %p\n", RecvIPMBPkt); } /* Loop forever */ while (1) { //printf("ppid: %d, pid: %d, tid: %d, i: %d, ipmbSelect: %d\n", getppid(), getpid(), gettid(), i++, ipmbSelect); pthread_mutex_lock(pMutex); pthread_mutex_unlock(pMutex); retval = stm32_i2c_slave_recv(IPMBSlaveFd, &IPMBReqPkt.Data[1]); if( retval > 5) { IPMBReqPkt.Param = PARAM_REQUEST; IPMBReqPkt.Size = retval + 1; /* +1 to include BMC Slave address */ int cnt; if(0 == ipmbSelect) printf("\nPriRx: "); else printf("\nSecRx: "); for(cnt=0;cnt < IPMBReqPkt.Size; cnt++) printf("%02x ", IPMBReqPkt.Data[cnt]); printf("\n"); /* Post the IPMB Request message to IPMBIfc Queue */ if(ipmbSelect == 0) { if (0 != PostMsg (gFd_PrimaryIpmbIfcQ, &IPMBReqPkt)) { printf ("IPMBIfc.c : Error posting message to IPMBIfc_Q\n"); } } else { if (0 != PostMsg (gFd_SecondaryIpmbIfcQ, &IPMBReqPkt)) { printf ("IPMBIfc.c : Error posting message to IPMBIfc_Q\n"); } } } } return (void*)-1; }