⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipmi_con_smi.cpp

📁 HIP 硬件设备管理标准接口
💻 CPP
字号:
/* * * Copyright (c) 2004 by FORCE Computers * * Note that this file is based on parts of OpenIPMI * written by Corey Minyard <minyard@mvista.com> * of MontaVista Software. Corey's code was helpful * and many thanks go to him. He gave the permission * to use this code in OpenHPI under BSD license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  This * file and program are licensed under a BSD style license.  See * the Copying file included with the OpenHPI distribution for * full licensing terms. * * Authors: *     Thomas Kanngieser <thomas.kanngieser@fci.com> */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include "ipmi_con_smi.h"// This is an overlay for all the address types, so it's easy to// determine the actual address type.  This is kind of like addresses// work for sockets.#define IPMI_MAX_ADDR_SIZE 32struct ipmi_addr{  // Try to take these from the "Channel Medium Type" table  // in section 6.5 of the IPMI 1.5 manual.  int   addr_type;  short channel;  char  data[IPMI_MAX_ADDR_SIZE];};// When the address is not used, the type will be set to this value.// The channel is the BMC's channel number for the channel (usually// 0), or IPMC_BMC_CHANNEL if communicating directly with the BMC.#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE	0x0cstruct ipmi_system_interface_addr{  int           addr_type;  short         channel;  unsigned char lun;};// An IPMB Address.#define IPMI_IPMB_ADDR_TYPE		0x01// Used for broadcast get device id as described in section 17.9 of the// IPMI 1.5 manual.#define IPMI_IPMB_BROADCAST_ADDR_TYPE	0x41struct ipmi_ipmb_addr{  int           addr_type;  short         channel;  unsigned char slave_addr;  unsigned char lun;};// Channel for talking directly with the BMC.  When using this// channel, This is for the system interface address type only.  FIXME// - is this right, or should we use -1?#define IPMI_BMC_CHANNEL  0xf#define IPMI_NUM_CHANNELS 0x10// A raw IPMI message without any addressing.  This covers both// commands and responses.  The completion code is always the first// byte of data in the response (as the spec shows the messages laid// out).struct ipmi_msg{  unsigned char  netfn;  unsigned char  cmd;  unsigned short data_len;  unsigned char  *data;};// Messages sent to the interface are this format.struct ipmi_req{  unsigned char *addr; // Address to send the message to.  unsigned int  addr_len;  long    msgid; // The sequence number for the message.  This                 // exact value will be reported back in the                 // response to this request if it is a command.                 // If it is a response, this will be used as                 // the sequence value for the response.  struct ipmi_msg msg;};// Receive types for messages coming from the receive interface.  This// is used for the receive in-kernel interface and in the receive// IOCTL.#define IPMI_RESPONSE_RECV_TYPE		1 // A response to a command#define IPMI_ASYNC_EVENT_RECV_TYPE	2 // Something from the event queue#define IPMI_CMD_RECV_TYPE		3 // A command from somewhere else// Note that async events and received commands do not have a completion// code as the first byte of the incoming data, unlike a response.// Messages received from the interface are this format.struct ipmi_recv{  int     recv_type; // Is this a command, response or an                     // asyncronous event.  unsigned char *addr;    // Address the message was from is put                          // here.  The caller must supply the                          // memory.  unsigned int  addr_len; // The size of the address buffer.                          // The caller supplies the full buffer                          // length, this value is updated to                          // the actual message length when the                          // message is received.  long    msgid; // The sequence number specified in the request                 // if this is a response.  If this is a command,                 // this will be the sequence number from the                 // command.  struct ipmi_msg msg; // The data field must point to a buffer.                       // The data_size field must be set to the                       // size of the message buffer.  The                       // caller supplies the full buffer                       // length, this value is updated to the                       // actual message length when the message                       // is received.};// Get/set the default timing values for an interface.  You shouldn't// generally mess with these.struct ipmi_timing_parms{	int          retries;	unsigned int retry_time_ms;};// The magic IOCTL value for this interface.#define IPMI_IOC_MAGIC 'i'// Send a message to the interfaces.  error values are://   - EFAULT - an address supplied was invalid.//   - EINVAL - The address supplied was not valid, or the command//              was not allowed.//   - EMSGSIZE - The message to was too large.//   - ENOMEM - Buffers could not be allocated for the command.#define IPMICTL_SEND_COMMAND		_IOR(IPMI_IOC_MAGIC, 13,	\					     struct ipmi_req)// Like RECEIVE_MSG, but if the message won't fit in the buffer, it// will truncate the contents instead of leaving the data in the// buffer.#define IPMICTL_RECEIVE_MSG_TRUNC	_IOWR(IPMI_IOC_MAGIC, 11,	\					      struct ipmi_recv)// Set whether this interface receives events.  Note that the first// user registered for events will get all pending events for the// interface.  error values://  - EFAULT - an address supplied was invalid.#define IPMICTL_SET_GETS_EVENTS_CMD	_IOR(IPMI_IOC_MAGIC, 16, int)#define IPMICTL_SET_TIMING_PARMS_CMD	_IOR(IPMI_IOC_MAGIC, 22, \					     struct ipmi_timing_parms)cIpmiConSmi::cIpmiConSmi( unsigned int timeout, int log_level, int if_num )  : cIpmiCon( timeout, log_level ),     m_if_num( if_num ){}cIpmiConSmi::~cIpmiConSmi(){  if ( IsOpen() )       Close();}intcIpmiConSmi::OpenSmiFd( int if_num ){  int fd;  char devname[30];  sprintf( devname, "/dev/ipmidev/%d", if_num );  fd = open( devname, O_RDWR );  if ( fd >= 0 )       return fd;  sprintf( devname, "/dev/ipmi/%d", if_num );  fd = open( devname, O_RDWR );  if ( fd >= 0 )       return fd;  sprintf( devname, "/dev/ipmi%d", if_num );  fd = open( devname, O_RDWR );  return fd;}intcIpmiConSmi::IfGetMaxSeq(){  return dMaxSeq;}intcIpmiConSmi::IfOpen(){  int fd = OpenSmiFd( m_if_num );  if ( fd < 0 )       return fd;  struct ipmi_timing_parms parms;  int                      rv;  parms.retries       = 0;  parms.retry_time_ms = 1000;  rv = ioctl( fd, IPMICTL_SET_TIMING_PARMS_CMD, &parms );  if ( rv == -1 )       stdlog << "Warning: Could not set timing parms !\n";  // we want async events  int val = 1;  rv = ioctl( fd, IPMICTL_SET_GETS_EVENTS_CMD, &val );  if ( rv == -1 )       stdlog << "Warning: Could not set gets events !\n";  return fd;}voidcIpmiConSmi::IfClose(){}SaErrorTcIpmiConSmi::IfSendCmd( cIpmiRequest *r ){  cIpmiAddr send_addr = r->m_send_addr;  ipmi_addr addr;  unsigned int addr_len = 0;  addr.addr_type = (int)send_addr.m_type;  // convert addr  switch( send_addr.m_type )     {       case eIpmiAddrTypeSystemInterface:            {              ipmi_system_interface_addr *si = (ipmi_system_interface_addr *)&addr;              si->channel = send_addr.m_channel;              si->lun     = send_addr.m_lun;              addr_len = sizeof( ipmi_system_interface_addr );            }            break;       case eIpmiAddrTypeIpmb:       case eIpmiAddrTypeIpmbBroadcast:            {              ipmi_ipmb_addr *ipmb = (ipmi_ipmb_addr *)&addr;              ipmb->channel    = send_addr.m_channel;              ipmb->slave_addr = send_addr.m_slave_addr;              ipmb->lun        = send_addr.m_lun;              addr_len = sizeof( ipmi_ipmb_addr );            }            break;       default:            assert( 0 );            return SA_ERR_HPI_INVALID_PARAMS;     }  struct ipmi_req req;  req.addr = (unsigned char *)&addr;  req.addr_len = addr_len;  req.msg.netfn    = r->m_msg.m_netfn;  req.msg.cmd      = r->m_msg.m_cmd;    req.msg.data_len = r->m_msg.m_data_len;  req.msg.data     = r->m_msg.m_data;  req.msgid = r->m_seq;  int rv = ioctl( m_fd, IPMICTL_SEND_COMMAND, &req );  if ( rv )       return SA_ERR_HPI_INVALID_REQUEST;  return SA_OK;}voidcIpmiConSmi::IfReadResponse(){  unsigned char data[dIpmiMaxMsgLength];  ipmi_addr     addr;  ipmi_recv     recv;  recv.msg.data     = data;  recv.msg.data_len = dIpmiMaxMsgLength;  recv.addr         = (unsigned char *)&addr;  recv.addr_len     = sizeof( ipmi_addr );  int rv = ioctl( m_fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv );  if ( rv == -1 )     {       if ( errno == EMSGSIZE )            // The message was truncated, handle it as such.            data[0] = eIpmiCcRequestedDataLengthExceeded;       else            return;     }  // convert addr  cIpmiAddr rsp_addr;  rsp_addr.m_type = (tIpmiAddrType)addr.addr_type;  switch( rsp_addr.m_type )     {       case eIpmiAddrTypeSystemInterface:            {              ipmi_system_interface_addr *si = (ipmi_system_interface_addr *)&addr;              rsp_addr.m_channel = si->channel;              rsp_addr.m_lun     = si->lun;            }            break;       case eIpmiAddrTypeIpmb:       case eIpmiAddrTypeIpmbBroadcast:            {              ipmi_ipmb_addr *ipmb = (ipmi_ipmb_addr *)&addr;              rsp_addr.m_channel    = ipmb->channel;              rsp_addr.m_slave_addr = ipmb->slave_addr;              rsp_addr.m_lun        = ipmb->lun;            }            break;       default:            assert( 0 );            return;     }  // convert msg  cIpmiMsg rsp;  rsp.m_netfn    = (tIpmiNetfn)recv.msg.netfn;  rsp.m_cmd      = (tIpmiCmd)recv.msg.cmd;  rsp.m_data_len = recv.msg.data_len;  if ( rsp.m_data_len )       memcpy( rsp.m_data, recv.msg.data, rsp.m_data_len );  int seq = (int)recv.msgid;  switch( recv.recv_type )     {       case IPMI_RESPONSE_RECV_TYPE:	    HandleResponse( seq, rsp_addr, rsp );	    break;       case IPMI_ASYNC_EVENT_RECV_TYPE:	    HandleEvent( rsp_addr, rsp );	    break;       case IPMI_CMD_RECV_TYPE:            // incomming command            stdlog << "SMI: incomming ipmi command "                    << IpmiCmdToString( rsp.m_netfn, rsp.m_cmd ) << ".\n";	    break;       default:	    break;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -