--- ipmitool-1.8.11/lib/ipmi_delloem.c.orig 2011-06-17 16:37:58.000000000 +0200 +++ ipmitool-1.8.11/lib/ipmi_delloem.c 2011-06-17 16:46:57.000000000 +0200 @@ -80,7 +80,7 @@ static int current_arg =0; uint8_t iDRAC_FLAG=0; LCD_MODE lcd_mode; static uint8_t LcdSupported=0; - +static uint8_t SetLEDSupported=0; volatile uint8_t IMC_Type = IMC_IDRAC_10G; @@ -166,6 +166,13 @@ static int getpowersupplyfruinfo(struct struct fru_header header, struct fru_info fru); static void ipmi_powermonitor_usage(void); +static int ipmi_getsesmask(int, char **); +static int CheckSetLEDSupport(struct ipmi_intf * intf); +static int IsSetLEDSupported(void); +static void ipmi_setled_usage(void); +static int ipmi_delloem_setled_main(struct ipmi_intf *intf, int argc, char ** argv); +static int ipmi_setled_state (struct ipmi_intf * intf, int bayId, int slotId, int state); +static int ipmi_getdrivemap (struct ipmi_intf * intf, int b, int d, int f, int *bayId, int *slotId); /***************************************************************** * Function Name: ipmi_delloem_main @@ -188,6 +195,7 @@ ipmi_delloem_main(struct ipmi_intf * int ipmi_idracvalidator_command(intf); CheckLCDSupport (intf); + CheckSetLEDSupport (intf); if (argc == 0 || strncmp(argv[0], "help\0", 5) == 0) { @@ -209,6 +217,11 @@ ipmi_delloem_main(struct ipmi_intf * int { rc = ipmi_delloem_lan_main (intf,argc,argv); } + /* SetLED support */ + else if (IsSetLEDSupported() && strncmp(argv[current_arg], "setled\0", 7) == 0) + { + rc = ipmi_delloem_setled_main (intf,argc,argv); + } /*Powermanagement report processing*/ else if (strncmp(argv[current_arg], "powermonitor\0", 13) == 0) { @@ -244,6 +257,8 @@ static void usage(void) lprintf(LOG_NOTICE, " mac"); if (IsLANSupported()) lprintf(LOG_NOTICE, " lan"); + if (IsSetLEDSupported()) + lprintf(LOG_NOTICE, " setled"); lprintf(LOG_NOTICE, " powermonitor"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, "For help on individual commands type:"); @@ -4218,3 +4233,277 @@ ipmi_powermonitor_usage(void) lprintf(LOG_NOTICE, " To disable set power cap"); lprintf(LOG_NOTICE, ""); } +/********************************************************************** +* Function Name: ipmi_setled_usage +* +* Description: This function prints help message for setled command +* Input: +* Output: +* +* Return: +* +***********************************************************************/ +static void +ipmi_setled_usage(void) +{ + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, " setled "); + lprintf(LOG_NOTICE, " Set backplane LED state"); + lprintf(LOG_NOTICE, " b:d.f = PCI Bus:Device.Function of drive (lspci format)"); + lprintf(LOG_NOTICE, " state = present|online|hotspare|identify|rebuilding|"); + lprintf(LOG_NOTICE, " fault|predict|critical|failed"); + lprintf(LOG_NOTICE, ""); +} + +static int +IsSetLEDSupported(void) +{ + return SetLEDSupported; +} + +static int +CheckSetLEDSupport(struct ipmi_intf * intf) +{ + struct ipmi_rs * rsp = NULL; + struct ipmi_rq req = {0}; + uint8_t data[4]; + + SetLEDSupported = 0; + req.msg.netfn = DELL_OEM_NETFN; + req.msg.lun = 0; + req.msg.cmd = 0xD5; /* Storage */ + req.msg.data_len = 10; + req.msg.data = data; + + memset(data, 0, sizeof(data)); + data[0] = 0x01; // get + data[1] = 0x00; // subcmd:get firmware version + data[2] = 0x08; // length lsb + data[3] = 0x00; // length msb + data[4] = 0x00; // offset lsb + data[5] = 0x00; // offset msb + data[6] = 0x00; // bay id + data[7] = 0x00; + data[8] = 0x00; + data[9] = 0x00; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL || rsp->ccode != 0) + { + return; + } + SetLEDSupported = 1; +} + +/***************************************************************** +* Function Name: ipmi_getdrivemap +* +* Description: This function returns mapping of BDF to Bay:Slot +* Input: intf - ipmi interface +* bdf - PCI Address of drive +* *bay - Returns bay ID + *slot - Returns slot ID +* Output: +* +* Return: +* +******************************************************************/ +static int +ipmi_getdrivemap(struct ipmi_intf * intf, int b, int d, int f, int *bay, int *slot) +{ + struct ipmi_rs * rsp = NULL; + struct ipmi_rq req = {0}; + uint8_t data[8]; + + /* Get mapping of BDF to bay:slot */ + req.msg.netfn = DELL_OEM_NETFN; + req.msg.lun = 0; + req.msg.cmd = 0xD5; + req.msg.data_len = 8; + req.msg.data = data; + + memset(data, 0, sizeof(data)); + data[0] = 0x01; // get + data[1] = 0x07; // storage map + data[2] = 0x06; // length lsb + data[3] = 0x00; // length msb + data[4] = 0x00; // offset lsb + data[5] = 0x00; // offset msb + data[6] = b; // bus + data[7] = (d << 3) + f; // devfn + + rsp = intf->sendrecv(intf, &req); + + if (rsp == NULL) + { + lprintf(LOG_ERR, " Error issuing getdrivemap command.\n"); + return -1; + } + else if (rsp->ccode != 0) + { + lprintf(LOG_ERR, " Error issuing getdrivemap command: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + *bay = rsp->data[7]; + *slot = rsp->data[8]; + if (*bay == 0xFF || *slot == 0xFF) + { + lprintf(LOG_ERR, "Error could not get drive bay:slot mapping"); + return -1; + } + return 0; +} + +/***************************************************************** +* Function Name: ipmi_setled_state +* +* Description: This function updates the LED on the backplane +* Input: intf - ipmi interface +* bdf - PCI Address of drive +* state - SES Flags state of drive +* Output: +* +* Return: +* +******************************************************************/ +static int +ipmi_setled_state (struct ipmi_intf * intf, int bayId, int slotId, int state) +{ + struct ipmi_rs * rsp = NULL; + struct ipmi_rq req = {0}; + uint8_t data[20]; + + /* Issue Drive Status Update to bay:slot */ + req.msg.netfn = DELL_OEM_NETFN; + req.msg.lun = 0; + req.msg.cmd = 0xD5; + req.msg.data_len = 20; + req.msg.data = data; + + memset(data, 0, sizeof(data)); + data[0] = 0x00; // set + data[1] = 0x04; // set drive status + data[2] = 0x0e; // length lsb + data[3] = 0x00; // length msb + data[4] = 0x00; // offset lsb + data[5] = 0x00; // offset msb + data[6] = 0x0e; // length lsb + data[7] = 0x00; // length msb + data[8] = bayId; // bayid + data[9] = slotId; // slotid + data[10] = state & 0xff; // state LSB + data[11] = state >> 8; // state MSB; + + rsp = intf->sendrecv(intf, &req); + + if (rsp == NULL) + { + lprintf(LOG_ERR, " Error issuing setled command.\n"); + return -1; + } + else if (rsp->ccode != 0) + { + lprintf(LOG_ERR, " Error issuing setled command: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + return 0; +} + +/***************************************************************** +* Function Name: ipmi_getsesmask +* +* Description: This function calculates bits in SES drive update +* Return: Mask set with bits for SES backplane update +* +******************************************************************/ +static int ipmi_getsesmask(int argc, char **argv) +{ + int mask = 0; + int idx; + + while (current_arg < argc) { + if (!strcmp(argv[current_arg], "present")) + mask |= (1L << 0); + if (!strcmp(argv[current_arg], "online")) + mask |= (1L << 1); + if (!strcmp(argv[current_arg], "hotspare")) + mask |= (1L << 2); + if (!strcmp(argv[current_arg], "identify")) + mask |= (1L << 3); + if (!strcmp(argv[current_arg], "rebuilding")) + mask |= (1L << 4); + if (!strcmp(argv[current_arg], "fault")) + mask |= (1L << 5); + if (!strcmp(argv[current_arg], "predict")) + mask |= (1L << 6); + if (!strcmp(argv[current_arg], "critical")) + mask |= (1L << 9); + if (!strcmp(argv[current_arg], "failed")) + mask |= (1L << 10); + current_arg++; + } + return mask; +} + +/***************************************************************** +* Function Name: ipmi_delloem_setled_main +* +* Description: This function processes the delloem setled command +* Input: intf - ipmi interface + argc - no of arguments + argv - argument string array +* Output: +* +* Return: return code 0 - success +* -1 - failure +* +******************************************************************/ +static int +ipmi_delloem_setled_main(struct ipmi_intf * intf, int argc, char ** argv) +{ + int rc = 0; + int n, b,d,f, mask; + int bayId, slotId; + + bayId = 0xFF; + slotId = 0xFF; + + current_arg++; + if (argc < current_arg) + { + usage(); + return -1; + } + + /* ipmitool delloem setled info*/ + if (argc == 1) + { + ipmi_setled_usage(); + return 0; + } + else if (sscanf(argv[current_arg], "%*x:%x:%x.%x", &b,&d,&f) == 3) { + /* We have bus/dev/function of drive */ + current_arg++; + ipmi_getdrivemap (intf, b, d, f, &bayId, &slotId); + } + else if (sscanf(argv[current_arg], "%x:%x.%x", &b,&d,&f) == 3) { + /* We have bus/dev/function of drive */ + current_arg++; + } + else { + ipmi_setled_usage(); + return -1; + } + /* Get mask of SES flags */ + mask = ipmi_getsesmask(argc, argv); + + /* Get drive mapping */ + if (ipmi_getdrivemap (intf, b, d, f, &bayId, &slotId)) + return -1; + + /* Set drive LEDs */ + return ipmi_setled_state (intf, bayId, slotId, mask); +}