IPMI driver
ipmi_msghandler: IPMI的核心,負責處理所有的message,IPMI user及IPMI的physical interface (SMI, System Management Interface)都綁在msghandler上。但只提供kernelland的interface,userland則需另一個下一個driver (devintf)。
ipmi_devintf: userland的 IOCTL。
ipmi_si: 不同system interface (如SMIC, BT, SSIF和KCS)的driver。下面的範例即需要這個。
ipmi_watchdog: 一個watchdog timer來監控系統
ipmi_poweroff: 藉由IPMI關機
IPMI addressing
目前有兩種address type:
system interface (範例中使用):
struct ipmi_system_interface_addr
{
int addr_type;
short channel;
};
這裡 addr_type設為IPMI_SYSTEM_INTERFACE_ADDR_TYPE,channel則是IPMI_BMC_CHANNEL。
另一個IPMB沒用過:
struct ipmi_ipmb_addr
{
int addr_type;};
short channel;
unsigned char slave_addr;
unsigned char lun;
這裡channel通常填0。
IPMI message
struct ipmi_msg
{
unsigned char netfn;};
unsigned char lun;
unsigned char cmd;
unsigned char *data;
int data_len;
Front Panel 有四顆telco alarm LED: PWR/CRI/MJR/MNR,以下為透過IPMI kernel driver傳送IPMI message給BMC來控制LED。
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
#define IPMI_MAX_INTF (4)
static ipmi_user_t ipmi_mh_user = NULL;
static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data)
{
ipmi_free_recv_msg(msg);
return;
}
static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,};
static int Led_ctrl_entry_point()
{
int rv;
struct ipmi_system_interface_addr addr;
uint8_t data[4] = {0};
struct kernel_ipmi_msg msg;
for (i=0; i<IPMI_MAX_INTF && rv; i++) {
rv = ipmi_create_user(i, &ipmi_hndlrs, NULL, &ipmi_mh_user);
}
if (rv < 0) {
V54_PRINTF("warning: create user fail, watchdog broken\n");
}
addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; //0x0c
addr.channel = IPMI_BMC_CHANNEL; //0xf
addr.lun = 0;
msg.netfn = IPMI_NETFUNC_APP; //0x06
msg.cmd = IPMI_ALARMS_CMD; //0x52
data[0] = 0x03;
data[1] = 0x40;
data[2] = 0x1;
data[3] = 0xf7; //Turn on PWR
msg.data_len = sizeof(data);
msg.data = data;
rv = ipmi_request_settime(t5520ur_led_user, (struct ipmi_addr*)&addr, 0, &msg,NULL, 1, -1, 0);
if (rv) {
printk("warning: send request fail, led broken\n");
}
ipmi_destroy_user(ipmi_mh_user);
return 0;
}
留言列表