update the OpenIPMI interface,

support sending and receiving from IPMB addresses
This commit is contained in:
Duncan Laurie 2004-08-27 16:30:07 +00:00
parent d5b598c93d
commit c52b6e80ba
2 changed files with 161 additions and 70 deletions

View File

@ -45,101 +45,128 @@
#include <sys/stat.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <linux/ipmi.h>
#include <config.h>
#include "open.h"
#ifdef HAVE_OPENIPMI_H
# include <linux/ipmi.h>
#else
# include "open.h"
#endif
extern int verbose;
struct ipmi_intf ipmi_openipmi_intf = {
.open = ipmi_openipmi_open,
.close = ipmi_openipmi_close,
.sendrecv = ipmi_openipmi_send_cmd,
};
#define IPMI_OPENIPMI_DEV "/dev/ipmi0"
void ipmi_openipmi_close(struct ipmi_intf * intf)
{
if (intf && intf->fd >= 0)
close(intf->fd);
}
int ipmi_openipmi_open(struct ipmi_intf * intf)
static int ipmi_openipmi_open(struct ipmi_intf * intf)
{
int i = 0;
intf->fd = open(OPENIPMI_DEV, O_RDWR);
intf->fd = open(IPMI_OPENIPMI_DEV, O_RDWR);
if (intf->fd < 0) {
perror("Could not open ipmi device");
lperror(LOG_ERR, "Could not open ipmi device");
return -1;
}
if (ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i)) {
perror("Could not set to get events");
lperror(LOG_ERR, "Could not set to get events");
return -1;
}
if (intf->my_addr) {
unsigned int a = intf->my_addr;
if (ioctl(intf->fd, IPMICTL_SET_MY_ADDRESS_CMD, &a)) {
lperror(LOG_ERR, "Could not set IPMB address");
return -1;
}
lprintf(LOG_DEBUG, "Set my IPMB address to 0x%x", intf->my_addr);
}
intf->opened = 1;
return intf->fd;
}
struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
static void ipmi_openipmi_close(struct ipmi_intf * intf)
{
if (intf && intf->fd >= 0)
close(intf->fd);
intf->opened = 0;
}
static struct ipmi_rs *ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
{
struct ipmi_recv recv;
struct ipmi_addr addr;
struct ipmi_system_interface_addr bmc_addr;
struct ipmi_system_interface_addr bmc_addr = {
addr_type: IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
channel: IPMI_BMC_CHANNEL,
};
struct ipmi_ipmb_addr ipmb_addr = {
addr_type: IPMI_IPMB_ADDR_TYPE,
};
struct ipmi_req _req;
static struct ipmi_rs rsp;
static int curr_seq = 0;
fd_set rset;
if (!intf)
if (!intf || !req)
return NULL;
if (!intf->opened && intf->open && intf->open(intf) < 0)
return NULL;
if (!intf->opened) {
intf->opened = 1;
if (intf->open(intf) < 0) {
printf("Unable to open OpenIPMI interface!\n");
intf->opened = 0;
return NULL;
}
}
if (verbose > 2)
printbuf(req->msg.data, req->msg.data_len, "send_cmd");
if (!req)
return NULL;
/*
* setup and send message
*/
memset(&_req, 0, sizeof(struct ipmi_req));
if (verbose > 2)
printbuf(req->msg.data, req->msg.data_len, "send_ipmi_cmd_dev");
if (intf->target_addr &&
intf->target_addr != intf->my_addr) {
/* use IPMB address if needed */
ipmb_addr.slave_addr = intf->target_addr;
_req.addr = (char *) &ipmb_addr;
_req.addr_len = sizeof(ipmb_addr);
lprintf(LOG_DEBUG, "Sending request to IPMB target @ 0x%x",
intf->target_addr);
} else {
/* otherwise use system interface */
lprintf(LOG_DEBUG, "Sending request to System Interface");
_req.addr = (char *) &bmc_addr;
_req.addr_len = sizeof(bmc_addr);
}
FD_ZERO(&rset);
FD_SET(intf->fd, &rset);
bmc_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
bmc_addr.channel = IPMI_BMC_CHANNEL;
bmc_addr.lun = 0;
_req.addr = (char *) &bmc_addr;
_req.addr_len = sizeof(bmc_addr);
_req.msgid = curr_seq++;
_req.msg.netfn = req->msg.netfn;
_req.msg.cmd = req->msg.cmd;
_req.msg.data = req->msg.data;
_req.msg.data_len = req->msg.data_len;
if (ioctl(intf->fd, IPMICTL_SEND_COMMAND, &_req) < 0) {
printf("Error sending command: %s\n", strerror(errno));
lperror(LOG_ERR, "Error sending command");
return NULL;
}
/*
* wait for and retrieve response
*/
FD_ZERO(&rset);
FD_SET(intf->fd, &rset);
if (select(intf->fd+1, &rset, NULL, NULL, NULL) < 0) {
perror("select");
lperror(LOG_ERR, "Error doing select");
return NULL;
}
if (!FD_ISSET(intf->fd, &rset)) {
printf("Error no data available\n");
lprintf(LOG_ERR, "Error no data available");
return NULL;
}
@ -150,28 +177,30 @@ struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq
/* get data */
if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
printf("Error receiving message: %s\n", strerror(errno));
lperror(LOG_ERR, "Error receiving message");
if (errno != EMSGSIZE)
return NULL;
}
if (verbose > 1) {
printf("Got message:\n");
printf(" type = %d\n", recv.recv_type);
printf(" channel = 0x%x\n", addr.channel);
printf(" msgid = %ld\n", recv.msgid);
printf(" netfn = 0x%x\n", recv.msg.netfn);
printf(" cmd = 0x%x\n", recv.msg.cmd);
if (verbose > 4) {
fprintf(stderr, "Got message:");
fprintf(stderr, " type = %d\n", recv.recv_type);
fprintf(stderr, " channel = 0x%x\n", addr.channel);
fprintf(stderr, " msgid = %ld\n", recv.msgid);
fprintf(stderr, " netfn = 0x%x\n", recv.msg.netfn);
fprintf(stderr, " cmd = 0x%x\n", recv.msg.cmd);
if (recv.msg.data && recv.msg.data_len) {
printf(" data_len = %d\n", recv.msg.data_len);
printf(" data =");
printbuf(recv.msg.data, recv.msg.data_len, "data");
fprintf(stderr, " data_len = %d\n", recv.msg.data_len);
fprintf(stderr, " data = %s\n",
buf2str(recv.msg.data, recv.msg.data_len));
}
}
/* save completion code */
rsp.ccode = recv.msg.data[0];
rsp.data_len = recv.msg.data_len - 1;
/* save response data for caller */
if (!rsp.ccode && rsp.data_len) {
memmove(rsp.data, rsp.data + 1, rsp.data_len);
rsp.data[recv.msg.data_len] = 0;
@ -180,10 +209,12 @@ struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq
return &rsp;
}
int open_intf_setup(struct ipmi_intf ** intf)
{
*intf = &ipmi_openipmi_intf;
return 0;
}
struct ipmi_intf ipmi_open_intf = {
name: "open",
desc: "Linux OpenIPMI Interface",
open: ipmi_openipmi_open,
close: ipmi_openipmi_close,
sendrecv: ipmi_openipmi_send_cmd,
target_addr: IPMI_BMC_SLAVE_ADDR,
};
int intf_setup(struct ipmi_intf ** intf) __attribute__ ((weak, alias("open_intf_setup")));

View File

@ -37,14 +37,74 @@
#ifndef IPMI_OPENIPMI_H
#define IPMI_OPENIPMI_H
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#define IPMI_MAX_ADDR_SIZE 0x20
#define IPMI_BMC_CHANNEL 0xf
#define IPMI_NUM_CHANNELS 0x10
#define OPENIPMI_DEV "/dev/ipmi0"
#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c
#define IPMI_IPMB_ADDR_TYPE 0x01
#define IPMI_IPMB_BROADCAST_ADDR_TYPE 0x41
struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
int ipmi_openipmi_open(struct ipmi_intf * intf);
void ipmi_openipmi_close(struct ipmi_intf * intf);
int open_intf_setup(struct ipmi_intf ** intf);
#define IPMI_RESPONSE_RECV_TYPE 1
#define IPMI_ASYNC_EVENT_RECV_TYPE 2
#define IPMI_CMD_RECV_TYPE 3
#endif
struct ipmi_addr {
int addr_type;
short channel;
char data[IPMI_MAX_ADDR_SIZE];
};
struct ipmi_msg {
unsigned char netfn;
unsigned char cmd;
unsigned short data_len;
unsigned char *data;
};
struct ipmi_req {
unsigned char *addr;
unsigned int addr_len;
long msgid;
struct ipmi_msg msg;
};
struct ipmi_recv {
int recv_type;
unsigned char *addr;
unsigned int addr_len;
long msgid;
struct ipmi_msg msg;
};
struct ipmi_cmdspec {
unsigned char netfn;
unsigned char cmd;
};
struct ipmi_system_interface_addr {
int addr_type;
short channel;
unsigned char lun;
};
struct ipmi_ipmb_addr {
int addr_type;
short channel;
unsigned char slave_addr;
unsigned char lun;
};
#define IPMI_IOC_MAGIC 'i'
#define IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv)
#define IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv)
#define IPMICTL_SEND_COMMAND _IOR(IPMI_IOC_MAGIC, 13, struct ipmi_req)
#define IPMICTL_REGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 14, struct ipmi_cmdspec)
#define IPMICTL_UNREGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 15, struct ipmi_cmdspec)
#define IPMICTL_SET_GETS_EVENTS_CMD _IOR(IPMI_IOC_MAGIC, 16, int)
#define IPMICTL_SET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 17, unsigned int)
#define IPMICTL_GET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 18, unsigned int)
#define IPMICTL_SET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 19, unsigned int)
#define IPMICTL_GET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 20, unsigned int)
#endif /*IPMI_OPENIPMI_H*/