File sgpio_0.10.patch of Package sgpio

diff -urN sgpio_rh_snap4/sgpio.c sgpio_new/sgpio.c
--- sgpio_rh_snap4/sgpio.c	2008-07-14 16:01:37.000000000 +0200
+++ sgpio_new/sgpio.c	2008-11-27 15:03:45.000000000 +0100
@@ -8,7 +8,7 @@
  *
  * 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. See the GNU General Public License 
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  * for more details.
  *
  * You should have received a copy of the GNU General Public License along
@@ -19,15 +19,16 @@
 
 /*
  * Intel SGPIO enclosure management utility
- * Author: Eric R Hall <Eric.R.Hall@intel.com> 
- * 
+ * Author: Eric R Hall <Eric.R.Hall@intel.com>
+ * Rework: Krzysztof Wojcik <krzysztof.wojcik@intel.com>
+ *
  */
 
 #include <stdio.h>     /* used by printf */
 #include <unistd.h>    /* used by chdir and write */
 #include <stdlib.h>    /* used by exit */
-#include <math.h>	   /* used by math functions */
-#include <getopt.h>    /* used by command.c to parse the command line */ 
+#include <math.h>      /* used by math functions */
+#include <getopt.h>    /* used by command.c to parse the command line */
 #include <string.h>    /* used to manipulate strings */
 #include <fcntl.h>     /* used for O_WRONLY definition in 'open()' */
 #include <time.h>      /* used by usleep because SGPIO driver is slow */
@@ -35,6 +36,7 @@
 #include <signal.h>    /* needed by signals */
 #include <syslog.h>    /* used for message log */
 #include <sys/types.h> /* used by read() */
+#include <dirent.h>
 
 /***************** 80 chars ***************************************************/
 
@@ -48,23 +50,23 @@
 #include "version.h"
 
 /* this programs available commands */
-#include "commands.h"  
+#include "commands.h"
 
 /* define the directory paths to the LED "files" */
-#define SUPPORTED_DISKS 5  // 0-5=6	
+#define MAX_DISK_IDX    5  
 #define SYSFS_BASE      "/sys/class"
-#define PORT_NAME		"/scsi_host/host" /* host0 = port0 ~ sda */
-#define SW_CONTROL		"/scsi_device"
-#define EM_MESSAGE		"/em_message"
+#define PORT_NAME	"/scsi_host/host" /* host0 = port0 ~ sda */
+#define SW_CONTROL	"/scsi_device"
+#define EM_MESSAGE	"/em_message"
 #define EM_MESSAGE_TYPE	"/em_message_type"
 #define EM_MESSAGE_DFLT	"0"
 
 /* per section 12.2.1 in the ACHI 1.2 spec */
-#define LOCATE_LED   524288  /* or bitmask 2^19 */
-#define FAULT_LED    4194304 /* or bitmask 2^22 */
-#define REBUILD_LED  4718592 /* 2^19 + 2^22 */
-#define ACTIV_LED	 65536	 /* 2^16 */
-#define OFF_LED      0       /* nothing! */
+#define LOCATE_LED      524288  /* or bitmask 2^19 */
+#define FAULT_LED    	4194304 /* or bitmask 2^22 */
+#define REBUILD_LED  	4718592 /* 2^19 + 2^22 */
+#define ACTIV_LED	65536	/* 2^16 */
+#define OFF_LED      	0       /* nothing! */
 
 /* LEDs in the backplane per disk and the order of the leds
  * Although there are only physically two LEDs on an Intel Intelliegent
@@ -73,62 +75,85 @@
  * and off. */
 #define LEDS_PER_DISK  5 /* locate, fault, rebuild, activity, and off */
 /* time to wait in uSec before sending next command to the SGPIO bus */
-#define SGPIO_wait      1000
+#define SGPIO_WAIT      1500
 
-/* set the buf size for led_write, which should also be
- * the return from the write() */
+/* set the buf size for led_write */
 #define WRITE_BUF 20
 
+/* some number that's unlikely to be random */
+#define INITIATED 1009
+
+/* /sys/class/scsi_device/0:0:0:0/device/block:sda
+* the path in the fs is 47 char */
+#define FS_PATH_LEN 47
+
+/* message lenth */
+#define MESSAGE_LEN 50
+
+/*index of port number in fs path*/
+#define PORT_NUM_LOC 21
+
+/*denotes free record in the disk structure*/
+#define PORT_FREE -1
+
+#define NONE -1
+
+static const char *sys_scsi_path = "/sys/class/scsi_disk/";
+static const char *sys_scsi_dev_blk_sles = "/device/block/";
+static const char *sys_scsi_dev_blk_rh = "/device/block:";
+
 /* define global variables */
 /* the led list is used to dynamically set the 'LEDs' for each disk */
-int _led_list[] = { LOCATE_LED, FAULT_LED, REBUILD_LED, ACTIV_LED, OFF_LED };
-/* blink rates in Hz for locate, fault, rebuild, activity */ 
+int _led_list[] = {LOCATE_LED, FAULT_LED, REBUILD_LED, ACTIV_LED, OFF_LED};
+/* blink rates in Hz for locate, fault, rebuild, activity */
 int _led_rate = 0;
+/* SIGALRM flag*/
+volatile sig_atomic_t sigal_flag = 0;
 /* done defining global variables */
 
 /* led structure; path to control, init'd status, states, and file handler */
-struct led_context {
-    char path[256];
-    int init;
-    int current_state;
-    int next_state;
-    int fd;
+struct led_context{
+	char path[256];
+	int init;
+	int current_state;
+	int next_state;
+	int fd;
 };
 
 /* uses the led_context to associate disks to leds */
-struct disk {
-    struct led_context data[LEDS_PER_DISK];
-    int id;
-    int port;
-    int init;
-    char name[7];
+struct disk{
+	struct led_context data[LEDS_PER_DISK];
+	int id;
+	int host_port;
+	int init;
+	char name[7];
 };
 
 /* structure for the disks associated with the led structure */
-struct disk disks[(SUPPORTED_DISKS+1)];
+struct disk disks[(MAX_DISK_IDX+1)];
 
 /* define the version to return.  Uses version.h */
-static int version() {
-    printf("Utility Version %i.%i\n", UTIL_VERSION_MAJOR, \
-     UTIL_VERSION_MINOR);
-    printf("SGPIO Specification Version %i.%i\n", SGPIO_VERSION_MAJOR, \
-     SGPIO_VERSION_MINOR);
-    return 0;
+static int version(){
+	printf("Utility Version %i.%i\n", UTIL_VERSION_MAJOR, \
+	UTIL_VERSION_MINOR);
+	printf("SGPIO Specification Version %i.%i\n", SGPIO_VERSION_MAJOR, \
+	SGPIO_VERSION_MINOR);
+	return 0;
 }
 
 /* display help information */
-static int help(char *argv) {
-    printf("SGPIO tool for intelligent hard disk drive backplanes\nUsage:\n" \
-     "%s [[-d|--disk] <sda,sdb,sdc,etc...> | [-p|--port] <0,1,2,etc...>]\n" \
-     "[-s|--status] <fault|locate|rebuild|off> [-f|--freq] <1,2,3,etc...>\n",
-     argv);
-    return 0;
+static int help(char *argv){
+	printf("SGPIO tool for intelligent hard disk drive backplanes\nUsage:\n" \
+	"%s [[-d|--disk] <sda,sdb,sdc,etc...> | [-p|--port] <0,1,2,etc...>]\n" \
+	"[-s|--status] <fault|locate|rebuild|off> [-f|--freq] <1,2,3,etc...>\n",
+	argv);
+	return 0;
 }
 
 /* define the led states */
-static void init_led(struct led_context *led) {
-    led->current_state = 0;
-    led->next_state = 0;
+static void init_led(struct led_context *led){
+	led->current_state = 0;
+	led->next_state = 0;
 }
 
 /* declare the whatportis [sdX] prototype */
@@ -142,6 +167,12 @@
 
 int led_set(int port_num);
 
+/* declare the led_change_state function prototype */
+int led_change_state(void);
+
+void led_init(void);
+
+int led_execute(int next_state, char *message);
 
 /* declare the timer event function prototype */
 void alarm_handler(int signo);
@@ -149,505 +180,504 @@
 /* declare the timer function that runs every x sec or usec prototype */
 int led_timer();
 
+int find_port_number(char *location);
+
 /* the main */
-int main (int argc, char **argv) {
-    char delims[] = ","; /* used to split --disk argument sda,sdb,sdc */
-    char* result;  /* the result of the 'split' disks used in the -d argument */
-    int c;  /* used as the command argument case selector */
-    int ii = 0; /* used in the jj for loop */
-    int leds = 0; /* used in the jj loop for number of supported LEDs */
-    int port_num = -1; /* 'case: p' port number */
-    int freq = 0;
-    
-    /* Let's dynamically figure out what this program was called as
-     * in case someone renames the utility. */
-    char *progname = argv[0];
-    /* if there is a '/' before the program name, then truncate the data
-     * before it.  In case there is no '/' before the filename, the
-     * if statement resets progname to argv[0].
-     * This program will segFault without the test. */
-    if((progname = strrchr (progname, '/')) != 0) {
-    	/* remove the first char, '/', from the beginning of the
-    	 * string by incrementing the pointer location. */
-    	progname++;
-    } else {
-    	/* This will seem cheap, but if we get here then progname
-    	 * is a null pointer and we need to fill it with something.
-    	 * In this case, we'll fill it with the called program name. */
-    	progname = argv[0];
-    }
-    /* done figuring out the program name. */
-
-    if (argc < 2) {
-       	help(progname);
-        exit(1);
-    }
-    
-
-    while (1) {
-        /* getopt_long uses this option index */
-        int option_index = 0;
-     
-        c = getopt_long(argc, argv, short_options, long_options,
-          &option_index);
-             
-        /* Detect the end of the options. */
-        if (c == -1) {
-        	break;
-        }
-
-        switch (c) {
-            case 0:
-                if (long_options[option_index].flag != 0)
-                    break;
-                printf ("option %s", long_options[option_index].name);
-                if (optarg)
-                    printf (" with arg %s", optarg);
-                printf ("\n");
-                break;
-            
-            case 'h':
-            	/* print help to the screen with the parsed program name */
-                help(progname);
-                break;
-            	
-            case 'p':
-            	      	                	
-                /* split the string at the 'delims' and then loop */
-                result = strtok( optarg, delims );
-                while( result != NULL ) {
-                	port_num = abs(atoi(result));
-                	if(port_num > SUPPORTED_DISKS) {
-                		printf("Error: not a valid port number!\n");
-                		return -1;
-                	}	                    
-                	
-                	/* call the led_set function that initalized and sets the 
-	            	 * paths and data for the disks LED */
-	            	led_set(port_num);
-	            	
-                	/* move to the next entry after the current deliminator,
-                	 *  this should be the next port number */
-                	result = strtok( NULL, delims );
-                }
-            	break;
-                
-            case 'd':
-        	       	                	
-            /* split the string at the 'delims' and then loop */
-            result = strtok( optarg, delims );
-                        	
-            while( result != NULL ) {
-            	           	
-            	port_num = whatportis(result);
-            	
-            	/* bounds checking, if anything is out of bounds here
-            	 * the tool will segfault - we must quit! */
-            	if(strlen(result) != 3 || port_num > SUPPORTED_DISKS
-            			|| port_num < 0) {
-            		printf("Error: not a valid device: %s\n", result);
-            		return -1;
-                    
-            	}	                    
-            	
-            	/* call the led_set function that initalized and sets the 
-            	 * paths and data for the disks LED */
-            	led_set(port_num);
-            	
-            	/* move to the next entry after the current deliminator,
-            	 *  this should be the next port number */
-            	result = strtok( NULL, delims );
-            }
-        	break;          
-
-            case 's':
-                /* strcmp exits 0 for true, it needs to be 1 for locate */
-                if (!(strcmp(optarg, "locate"))) {
-	                /* since we don't know which disk LEDs have been
-	            	 * init'd we'll just cycle through all of them.
-	            	 */
-                	for(ii=0;ii<=SUPPORTED_DISKS; ii++) {
-                		                	
-                		/* the problem with cycling through all of the disks
-	            		 * is that the un-init'd ones have junk data that we
-	            		 * don't want to write to the fs; a simple check is 
-	            		 * made to make sure that the disk was init'd. */
-	            		for (leds=0;leds<LEDS_PER_DISK;leds++) {
-	            			if((disks[ii].data[leds].next_state == LOCATE_LED)
-	            				&& (disks[ii].init == 1009)){
-	            				printf("Locate LED was ");
-	            				/* some number that's unlikely to be random */
-	            				disks[ii].data[leds].init = 1009;
-	            				                		
-	            				if(led_write(&disks[ii].data[leds], 1) \
-	            						!= WRITE_BUF)
-	            					printf("not set");
-	            				else
-	            					printf("set");
-	            				
-	            				printf(" for %s\n",disks[ii].name);
-	            			}
-	            		}
-	           		}
-                }
-                
-                if (!(strcmp(optarg, "fault"))) {
-	            	/* since we don't know which disk LEDs have been
-	            	 * init'd we'll just cycle through all of them.
-	            	 */
-                	for(ii=0;ii<=SUPPORTED_DISKS; ii++) {
-                		/* the problem with cycling through all of the disks
-	            		 * is that the un-init'd ones have junk data that we
-	            		 * don't want to write to the fs; a simple check is 
-	            		 * made to make sure that the disk was init'd. */
-	            		for (leds=0;leds<LEDS_PER_DISK;leds++) {
-	            			if((disks[ii].data[leds].next_state == FAULT_LED) &&
-	            				(disks[ii].init == 1009)) {
-	            				/* some number that's unlikely to be random */
-	            				disks[ii].data[leds].init = 1009;
-	            				                		
-	            				printf("Fault LED was ");
-	            				if(led_write(&disks[ii].data[leds], 1) \
-	            						!= WRITE_BUF)
-	            					printf("not set");
-	            				else
-	            					printf("set");
-	            				
-	            				printf(" for %s\n",disks[ii].name);
-	            			}
-	            		}
-	           		}
-                }
-
-                if (!(strcmp(optarg, "rebuild"))) {
-                	/* since we don't know which disk LEDs have been
-	            	 * init'd we'll just cycle through all of them.
-	            	 */
-                	for(ii=0;ii<=SUPPORTED_DISKS; ii++) {
-                		/* the problem with cycling through all of the disks
-	            		 * is that the un-init'd ones have junk data that we
-	            		 * don't want to write to the fs; a simple check is 
-	            		 * made to make sure that the disk was init'd. */
-	            		for (leds=0;leds<LEDS_PER_DISK;leds++) {
-	            			if((disks[ii].data[leds].next_state == REBUILD_LED)
-	            				&& (disks[ii].init == 1009)) {
-	            				/* some number that's unlikely to be random */
-	            				disks[ii].data[leds].init = 1009;
-	            				                		
-	            				printf("Rebuild LED was ");
-	            				if(led_write(&disks[ii].data[leds], 1) \
-	            						!= WRITE_BUF)
-	            					printf("not set");
-	            				else
-	            					printf("set");
-	            				
-	            				printf(" for %s\n",disks[ii].name);
-	            			}
-	            		}
-	           		}
-                }
-
-                if (!(strcmp(optarg, "off"))) {
-	            	/* since we don't know which disk LEDs have been
-	            	 * init'd we'll just cycle through all of them.
-	            	 */
-	            	for(ii=0;ii<=SUPPORTED_DISKS; ii++) {
-	            		/* the problem with cycling through all of the disks
-	            		 * is that the un-init'd ones have junk data that we
-	            		 * don't want to write to the fs; a simple check is 
-	            		 * made to make sure that the disk was init'd. */
-	            		for (leds=0;leds<LEDS_PER_DISK;leds++) {
-	            			if((disks[ii].data[leds].next_state == OFF_LED) &&
-	            					(disks[ii].init == 1009)) {
-	            				/* some number that's unlikely to be random */
-	            				disks[ii].data[leds].init = 1009;
-	            				                		
-	            				printf("LED was ");
-	            				if(led_write(&disks[ii].data[leds], 1) \
-	            						!= WRITE_BUF)
-	            					printf("not set");
-	            				else
-	            					printf("set");
-	            				
-	            				printf(" to off for %s\n",disks[ii].name);
-	            			}
-	            		}
-	           		}
-                }
-                if (!(strcmp(optarg, "activity"))) {
-	            	/* since we don't know which disk LEDs have been
-	            	 * init'd we'll just cycle through all of them.
-	            	 */
-	            	for(ii=0;ii<=SUPPORTED_DISKS; ii++) {
-	            		/* the problem with cycling through all of the disks
-	            		 * is that the un-init'd ones have junk data that we
-	            		 * don't want to write to the fs; a simple check is 
-	            		 * made to make sure that the disk was init'd. */
-	            		for (leds=0;leds<LEDS_PER_DISK;leds++) {
-	            			if((disks[ii].data[leds].next_state == ACTIV_LED) &&
-	            				(disks[ii].init == 1009)) {
-	            				/* some number that's unlikely to be random */
-	            				disks[ii].data[leds].init = 1009;
-	            				                		
-	            				printf("Activity LED was ");
-	            				if(led_write(&disks[ii].data[leds], 1) \
-	            						!= WRITE_BUF)
-	            					printf("not set");
-	            				else
-	            					printf("set");
-	            				
-	            				printf(" for %s\n",disks[ii].name);
-	            			}
-	            		}
-	           		}
-                }
-                
-                break;
-                
-            case 'f':
-            	freq = abs(atoi(optarg));
-            	if(freq < 1 || freq > 10)
-            		printf("Invalid frequency, please use between 1 and 10\n");
-            	else
-            		_led_rate = freq;
-            	break;
-            	
-            case 'V':
-                version();
-                break;
-
-            default:
-            	//printf("Unknown command\n");
-            	help(progname);
-                exit(1);
-            }
-    }
-    
-    /* Print any remaining command line arguments that were not parsed */
-    if (optind < argc) {
-        printf ("Error!  Unknown arguments: ");
-        while (optind < argc)
-            printf ("%s ", argv[optind++]);
-        printf("\nPlease use -h for more information.\n");    
-    }
-   
-   /* not sure if we need to close the file
-    *close(disks[jj].data[0].path); */
-    
-    /* start the timer.  It loops continuously because the timer needs
-     * to be reset.  This might not be the best idea since we've basically
-     * locked the tool down until the timer fails. */
-    if(_led_rate != 0)
-    	for(;;)
-    		led_timer();
-    
-    exit (0);
-}
-
-/* used for debugging.  Could be removed */
-int port_status(struct led_context *data, int port) {
-	char Buff[8];
-    read(data->fd, Buff, sizeof(Buff));
-    printf("Port: %d buff: %d\n", port, abs( atoi( Buff ) ));
-    return 0;
+int main(int argc, char **argv){
+	char delims[] = ","; /* used to split --disk argument sda,sdb,sdc */
+	char* result;  /* the result of the 'split' disks used in the -d argument */
+	int c;  /* used as the command argument case selector */
+	int port_num = -1; /* 'case: p' port number */
+	int freq = 0;     /* blink rates reset to zero- disable blinking*/
+	int next_state = NONE; /* store next sate of LEDs*/
+	char message[MESSAGE_LEN]; /* store messages */
+	int i = 0;
+		
+	/* Let's dynamically figure out what this program was called as
+	 * in case someone renames the utility. */
+	char *progname = argv[0];
+	/* if there is a '/' before the program name, then truncate the data
+	* before it.  In case there is no '/' before the filename, the
+	* if statement resets progname to argv[0].
+	* This program will segFault without the test. */
+	if((progname = strrchr (progname, '/')) != 0){
+	/* remove the first char, '/', from the beginning of the
+	 * string by incrementing the pointer location. */
+		progname++;
+	}
+	else{
+	/* This will seem cheap, but if we get here then progname
+	 * is a null pointer and we need to fill it with something.
+	 * In this case, we'll fill it with the called program name. */
+		progname = argv[0];
+	}
+	/* done figuring out the program name. */
+
+	if(argc < 2){
+		help(progname);
+		exit(1);
+	}
+
+	led_init();
+
+	while(1){
+		/* getopt_long uses this option index */
+		int option_index = 0;
+		char *end_str = 0;
+
+		c = getopt_long(argc, argv, short_options, long_options,
+		  &option_index);
+
+		/* Detect the end of the options. */
+		if(c == -1){
+			break;
+		}
+
+		switch(c){
+			case 0:
+				if(long_options[option_index].flag != 0)
+					break;
+				printf ("option %s",
+				        long_options[option_index].name);
+				if(optarg)
+					printf (" with arg %s", optarg);
+				printf ("\n");
+				break;
+			case 'h':
+				/* print help to the screen with the
+				 * parsed program name */
+				help(progname);
+				break;
+			case 'p':
+				/* split the string at the 'delims' and then loop */
+				result = strtok(optarg, delims);
+				while(result != NULL){
+					port_num = strtol(result, &end_str, 10);
+					if(port_num < 0 || *end_str != '\0'){
+						printf("Error: %s is not a "
+							"valid port number!\n",
+							result);
+						return -1;
+					}
+					/* call the led_set function that
+					 * initalized and sets the
+					 * paths and data for the disks LED */
+					if(led_set(port_num) != 0){
+						printf("Error: can not initialize "
+							"data for disks LED!\n");
+						return -1;
+					}
+					/* move to the next entry after the
+					 * current deliminator,
+					 * this should be the next port number */
+					result = strtok(NULL, delims);
+				}
+				break;
+			case 'd':
+				/* split the string at the 'delims' and then loop */
+				result = strtok(optarg, delims);
+				while(result != NULL){
+					if((port_num = whatportis(result)) == -1){
+						printf("Error: can not extract "
+							"port number!\n");
+						return -1;
+					}
+					/* bounds checking, if anything is
+					 * out of bounds here
+					 * the tool will segfault - we must quit! */
+					if(strlen(result) != 3 || port_num < 0){
+						printf("Error: not a valid "
+							"device: %s\n", result);
+						return -1;
+
+					}
+					/* call the led_set function that
+					 * initalized and sets the
+					 * paths and data for the disks LED */
+					if(led_set(port_num) != 0){
+						printf("Error: can not initialize "
+							"data for disks LED!\n");
+						return -1;
+					}
+					/* move to the next entry after the
+					 * current deliminator,
+					 *  this should be the next port number */
+					result = strtok(NULL, delims);
+				}
+				break;
+			case 's':
+				if(!(strcmp(optarg, "locate"))){
+					next_state = LOCATE_LED;
+					sprintf(message,"Locate LED was ");
+				}
+				else if(!(strcmp(optarg, "fault"))){
+					next_state = FAULT_LED;
+					sprintf(message,"Fault LED was ");
+				}
+				else if(!(strcmp(optarg, "rebuild"))){
+					next_state = REBUILD_LED;
+					sprintf(message, "Rebuild LED was ");
+				}
+				else if(!(strcmp(optarg, "off"))){
+					next_state = OFF_LED;
+					sprintf(message, "Off LED was ");
+				}
+				else if(!(strcmp(optarg, "activity"))){
+					next_state = ACTIV_LED;
+					sprintf(message, "Activate LED was ");
+				}
+				else{
+					printf("Error: Unknown option: %s!\n",
+					       optarg);
+					return -1;
+				}
+				break;
+			case 'f':
+				freq = strtol(optarg, &end_str, 10);
+				if(freq < 1 || freq > 10 || *end_str != '\0'){
+					printf("Error: Invalid frequency, "
+						"please use number between 1 and 10!\n");
+					return -1;
+				}
+				else
+					_led_rate = freq;
+				break;
+			case 'V':
+				version();
+				break;
+			default:
+				printf("Unknown command\n");
+				help(progname);
+				exit(1);
+			}
+		}
+
+	/* Print any remaining command line arguments that were not parsed */
+	if(optind < argc){
+		printf ("Error!  Unknown arguments: ");
+		while (optind < argc)
+		printf ("%s ", argv[optind++]);
+		printf("\nPlease use -h for more information.\n");
+	}
+
+	/* not sure if we need to close the file
+	*close(disks[jj].data[0].path); */
+
+	/* start the timer for non inteligent backplanes.
+	* It loops continuously because the timer needs
+	* to be reset.  */
+	if(_led_rate != 0){
+		sigal_flag = 1;
+		while(1){
+		/* use signals to alert the user if the alarm failed */
+			if (signal(SIGALRM, alarm_handler) == SIG_ERR) {
+				printf("Error: Unable to catch SIGALRM\n!");
+			}
+			if(sigal_flag){
+				if(led_timer() != 0){
+					printf("Error: Unable to set "
+						"LEDs timer!\n");
+					exit(0);
+				}
+				if(led_change_state() != 0){
+					printf("Error: Unable to change "
+						"state of LEDs\n");
+					exit(0);
+				}
+				sigal_flag = 0;
+			}
+		}
+	}
+	if(next_state == NONE){
+		printf("Error: State of LED must be specified!\n");
+		exit(0);
+	}
+	while(disks[i++].host_port == PORT_FREE){
+		if(i > MAX_DISK_IDX){
+			printf("Error: Port number or disk name must be specified!\n");
+			exit(0);
+		}
+	}
+	if(led_execute(next_state, message) != 0){
+		printf("Error: Unable to execute set command!\n");
+	}
+	exit(0);
 }
 
-int led_write(struct led_context *data, int chg_state) {
-	
-	/* set the return state in case write fails to */
-	int return_state = -1;
-    
-	/* this timeout is needed because the utility
-	 * will write to the sgpio bus too fast and
-	 * the Intel backplane will miss the data */
-	usleep(SGPIO_wait);
-	
-    /* get the net state of the led from the data structure */
-    int state = data->next_state;
-    
-    /* if the change state is set to 0, then the LED should be turned off 
-     * and the state from the data structure should be ignored */
-    if(chg_state == 0)
-    	state = 0;
-    
-    /* create a char buffer to store the led state since
-     * we will be printing it as a char/string to the fs */
-    char buf[WRITE_BUF];
-    
-    /* cast buf with a string of the decimal value of the led state */
-    sprintf(buf, "%d", state);
-    
-    /* This is just debug to make sure the 'data' is correct */
-     if (verbose_flag) {
-        printf("led_write: led state: %d led next state: %d path: %s\n",\
-            data->current_state, state, data->path);
-     } 
-    
-    /* use the file handler in the data struct to print the buffer 
-     * and only print x bytes of the size of the buffer.
-     * The number returned from write is the number of bytes written.
-     * Write should only ever write two bytes, else it's a failure
-     */
-    return_state = write(data->fd,buf,sizeof(buf));
-    //printf("ledwrite return: %d\n\n", return_state);
-    /* time to swap the LED states.  This may not be needed if
-       flashing the LEDs is not required */
-    data->next_state = data->current_state;
-    data->current_state = state;
-    
-    /* should return the buf size */
-    return return_state;
-}
-
-int isSWControl(int port) {
-	char location[49];
-	int loc;
-	int buffer;
-	
-	sprintf(location,"%s%s/%d:0:0:0/device/sw_control",
-		SYSFS_BASE, SW_CONTROL, port);
-	loc = open("test", O_RDWR, 0);
-	char Buff[2];
-	read(loc, Buff, sizeof(Buff));
-	buffer = abs( atoi( Buff ) );
-	printf("isSWControl: %d buff: %d\n", port, buffer);
-	return buffer;
-}
-
-int whatportis(const char *disk) {
-    int port;
-    /* /sys/class/scsi_device/0:0:0:0/device/block:sda
-     * the path in the fs is 47 char */
-    char location[48];  
-    
-    /* quit if disk is not 3 chars */ 
-    if (strlen(disk) != 3)
-        return -1;
-
-    for(port = 0; port <= SUPPORTED_DISKS; port++ ) {
-    	/* fill 'location' with a string of SYSFS_BASE, port number, port name
-    	 * and disk name */
-    	sprintf(location,"%s%s/%d:0:0:0/device/block:%s",
-    			SYSFS_BASE, SW_CONTROL, port, disk);
-	
-    	if (verbose_flag)
-    		printf("whatportis: disk: %s location: %s\n", disk, location);
-	
-    	/* chdir returns 0 for completion and -1 for incomplete */
-    	if (chdir(location) == 0)
-    		return port;
-    }
-    return -1;
+void led_init(void){
+	int i;
+	for(i=0;i<=MAX_DISK_IDX;i++){
+		disks[i].host_port = PORT_FREE;
+	}
 }
 
-void alarm_handler(int signo) {
+/* since we don't know which disk LEDs have been
+ * init'd we'll just cycle through all of them.
+ */
+int led_execute(int next_state, char *message){
+	int leds = 0;
+	int ii = 0;
+	for(ii=0;ii<=MAX_DISK_IDX; ii++){
+		/* the problem with cycling through all of the disks
+		 * is that the un-init'd ones have junk data that we
+		 * don't want to write to the fs; a simple check is
+		 * made to make sure that the disk was init'd. */
+		for(leds=0;leds<LEDS_PER_DISK;leds++){
+			if((disks[ii].data[leds].next_state == next_state)
+					&& (disks[ii].init == INITIATED)){
+				disks[ii].data[leds].init = INITIATED;
+				if(led_write(&disks[ii].data[leds], 1) == -1){
+					syslog(LOG_INFO, "%snot set for %s\n",
+					       message, disks[ii].name);
+					if(verbose_flag)
+						printf("%snot set for %s\n",
+						       message, disks[ii].name);
+					return -1;
+				}
+				else{
+					syslog(LOG_INFO, "%sset for %s\n",
+					       message, disks[ii].name);
+					if(verbose_flag)
+						printf("%sset for %s\n",
+						       message, disks[ii].name);
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+int led_change_state(void){
 	int myleds = 0;
 	int mydisks = 0;
-	if (verbose_flag)
-		printf("Timer hit! %d\n", abs(time(NULL)));
-	
-	for (mydisks=0;mydisks<=SUPPORTED_DISKS;mydisks++) {
-		for(myleds=0;myleds<LEDS_PER_DISK;myleds++) {
-			if (disks[mydisks].data[myleds].init == 1009) {
-				if (verbose_flag) {
-					printf("Timer:\n\tname: %s\n", disks[mydisks].name);
-					printf("\tdisk: %d led: %d\n", mydisks, myleds);
+
+	for(mydisks=0;mydisks<=MAX_DISK_IDX;mydisks++){
+		for(myleds=0;myleds<LEDS_PER_DISK;myleds++){
+			if(disks[mydisks].data[myleds].init == INITIATED){
+				if(verbose_flag){
+					printf("Timer:\n\tname: %s\n",
+					       disks[mydisks].name);
+					printf("\tdisk: %d led: %d\n",
+					       mydisks, myleds);
 					printf("\tcurrent_state: %d\n",
-						disks[mydisks].data[myleds].current_state);
+					       disks[mydisks].data[myleds].current_state);
 					printf("\tnext_state: %d\n",
-						disks[mydisks].data[myleds].next_state);
-					printf("\tinit: %d\n\n", disks[mydisks].data[myleds].init);	
+					       disks[mydisks].data[myleds].next_state);
+					printf("\tinit: %d\n\n",
+					       disks[mydisks].data[myleds].init);
+				}
+				if(led_write(&disks[mydisks].data[myleds], 1) == -1){
+					printf("Error: Failed to set led %d for "
+					       "port %d!\n", myleds, disks[mydisks].host_port);//fix!!!!
+					return -1;
 				}
-				if(led_write(&disks[mydisks].data[myleds], 1) != WRITE_BUF)
-					printf("Failed to set led %d for port %d\n", myleds,
-							mydisks);
 			}
 		}
 	}
+	return 0;
 }
 
-/* set up the timer function that runs every x sec or usec */
-int led_timer() {
-	/* create the delay structure */
-	struct itimerval delay;
-	int ret;
-	
-	/* use signals to alert the user if the alarm failed */
-	if (signal(SIGALRM, alarm_handler) == SIG_ERR) {
-		perror("Unable to catch SIGALRM");
+int led_write(struct led_context *data, int chg_state){
+
+	/* set the return state in case write fails to */
+	int return_state = -1;
+
+	/* this timeout is needed because the utility
+	 * will write to the sgpio bus too fast and
+	 * the Intel backplane will miss the data */
+	usleep(SGPIO_WAIT);
+
+	/* get the next state of the led from the data structure */
+	int state = data->next_state;
+
+	/* if the change state is set to 0, then the LED should be turned off
+	* and the state from the data structure should be ignored */
+	if(chg_state == 0)
+		state = 0;
+
+	/* create a char buffer to store the led state since
+	* we will be printing it as a char/string to the fs */
+	char buf[WRITE_BUF];
+
+	/* cast buf with a string of the decimal value of the led state */
+ 	if(sprintf(buf, "%d", state) < 1){
+		printf("Error: Unable to write LED state to buffor!\n");
 		return -1;
 	}
-	
-	float temp_rate = 1.0/_led_rate/2;
-	int rate = temp_rate*1000000;
-	//printf("%d", test);
-	        
-	    
-	
-	/* the time values for the alarm.  It has uS granularity */
-	delay.it_value.tv_sec = 0;
-	delay.it_value.tv_usec = rate;
-	delay.it_interval.tv_sec = 0;
-	delay.it_interval.tv_usec = rate;
-	
-	/* reset the timer with the above time values */
-	ret = setitimer(ITIMER_REAL, &delay, NULL);
-	
-	/* if the timer failed to reset, error out */
-	if (ret) {
-		perror("setitimer\n");
-		return -1;
+
+ 	/* This is just debug to make sure the 'data' is correct */
+ 	if(verbose_flag){
+ 	printf("led_write: led state: %d led next state: %d path: %s\n",
+ 	       data->current_state, state, data->path);
+ 	}
+
+ 	/* use the file handler in the data struct to print the buffer
+ 	 * and only print x bytes of the size of the buffer.
+ 	 * The number returned from write is the number of bytes written.
+ 	 * Write should only ever write two bytes, else it's a failure
+ 	 */
+ 	return_state = write(data->fd,buf,strlen(buf));
+	if(return_state == -1){
+		printf("Error: Unable to write to descriptor!\n");
+		return return_state;
 	}
-	pause();
-	return 0;
+	data->next_state = data->current_state;
+	data->current_state = state;
+
+	/* should return the buf len */
+	return return_state;
 }
 
-int led_set(int port_num) {
+int led_set(int port_num){
 	int leds = 0;
+	int index = 0;
+
+	while(disks[index].host_port != PORT_FREE){
+		if(++index > MAX_DISK_IDX){
+			printf("Error: Too many disks!\n");
+			return -1;
+		} 
+	}
+
 	/* Give the port a name */
-	sprintf(disks[port_num].name,"Port %d", port_num);
-	disks[port_num].init = 1009;
+	if(sprintf(disks[index].name,"Port %d", port_num) < 0){
+		printf("Error: Unable to write port number to buffor!\n");
+		return -1;
+	}
+	disks[index].init = INITIATED;
 	/* set up the LEDs for each port */
-	for(leds=0;leds<LEDS_PER_DISK;leds++) {
+	for(leds=0;leds<LEDS_PER_DISK;leds++){
 		/* creates the inital LED struct with
 		 * current_state and next_state */
-		init_led(&disks[port_num].data[leds]);
-		
-		
+		init_led(&disks[index].data[leds]);
+
 		/* if the disk has already been init'd then skip it.
-		 * This would only occur if the user specified the 
-		 * same port/disk twice 
-		if (disks[port_num].data[leds].init == 1009)
+		 * This would only occur if the user specified the
+		 * same port/disk twice
+		if (disks[port_num].data[leds].init == INITIATED)
 		    break;
 		*/
-		
+
 		/* populate the port path */
-		sprintf(disks[port_num].data[leds].path,"%s%s%d%s",\
-				SYSFS_BASE, PORT_NAME, port_num, EM_MESSAGE);
-		
-		
-		disks[port_num].data[leds].next_state = _led_list[leds];
-		
-		
-		if (verbose_flag) {
+		if(sprintf(disks[index].data[leds].path,"%s%s%d%s",\
+				SYSFS_BASE, PORT_NAME, port_num, EM_MESSAGE) < 0){
+			printf("Error: Unable to write port path to buffor!\n");
+			return -1;
+		}
+
+		disks[index].data[leds].next_state = _led_list[leds];
+
+
+		if(verbose_flag){
 			printf("port %d leds %d\n" \
-		   "next_state %d init %d\n", port_num, leds,
-		   disks[port_num].data[leds].next_state,
-		   disks[port_num].data[leds].init);
+			       "next_state %d init %d\n", port_num, leds,
+			       disks[index].data[leds].next_state,
+			       disks[index].data[leds].init);
 		}
-		        				
+
 		/* create the file handler and set it as read/write
 		 * to allow port_status to read em_message */
-		disks[port_num].data[leds].fd = 
-			open(disks[port_num].data[leds].path, O_RDWR,0);
-		
+		disks[index].data[leds].fd =
+			open(disks[index].data[leds].path, O_RDWR,0);
+
 		/* if the file handler failed, the path to the
 		 * requested disk was not found, we'll need to quit */
-		if (disks[port_num].data[leds].fd < 0) {
-			printf("Unable to find port: %d\n", port_num);
-				return -1;
-		}	
-	}           
+		if(disks[index].data[leds].fd < 0){
+			printf("Error: Unable to find path to requested disk: port %d!\n", 
+				port_num);
+			return -1;
+		}
+	}
 	/* done setting up the LEDs */
+	disks[index].host_port = port_num;
 	return 0;
 }
+
+int find_port_number(char *location){
+	DIR *dir;
+	char *ptr = NULL;
+	int port = -1;
+	if((dir = opendir(location))){
+		closedir(dir);
+		ptr = strchr((const char *)&location[PORT_NUM_LOC], ':');
+		if(ptr){
+			*ptr = 0;
+			port = atoi((char *) &location[PORT_NUM_LOC]);
+		}
+	}
+	return port;
+}
+	
+
+int whatportis(const char *disk){
+	int port = -1;
+	/* /sys/class/scsi_device/0:0:0:0/device/block:sda
+	 * the path in the fs is 47 char */
+	char location[FS_PATH_LEN+1];
+
+	char dir_qan, len;
+	int i;
+	struct dirent **dir_ent;
+
+	/* quit if disk is not 3 chars */
+	if(strlen(disk) != 3)
+		return -1;
+
+	dir_qan = scandir(sys_scsi_path, &dir_ent, 0, alphasort);
+	if(dir_qan < 0){
+		printf("Error: /sys/class/scsi_disk not contain any directory\n");
+		return -1;
+	}
+
+	strcpy(location, sys_scsi_path);
+	len = strlen(location);
+
+	for(i=0;i<dir_qan;i++){
+		const char *dir_name = dir_ent[i]->d_name;
+		if(port == -1){
+			sprintf(location + len, "%s%s%s", 
+				dir_name, sys_scsi_dev_blk_sles, disk);
+			port = find_port_number(location);
+			if(port == -1){
+				sprintf(location + len, "%s%s%s", 
+					dir_name, sys_scsi_dev_blk_rh, disk);
+				port = find_port_number(location);
+			}
+		}
+		free(dir_ent[i]);
+	}
+	free(dir_ent);
+	return port;
+}
+
+void alarm_handler(int signo){
+	sigal_flag = 1;
+}
+
+/* set up the timer function that runs every x sec or usec */
+int led_timer(){
+	/* create the delay structure */
+	struct itimerval delay;
+	int ret;
+
+	float temp_rate = 1.0/_led_rate/2;
+	int rate = temp_rate*1000000;
+
+	/* the time values for the alarm.  It has uS granularity */
+	delay.it_value.tv_sec = 0;
+	delay.it_value.tv_usec = rate;
+	delay.it_interval.tv_sec = 0;
+	delay.it_interval.tv_usec = rate;
+
+	/* reset the timer with the above time values */
+	ret = setitimer(ITIMER_REAL, &delay, NULL);
+
+	/* if the timer failed to reset, error out */
+	if(ret){
+		perror("setitimer\n");
+		return -1;
+	}
+	return 0;
+}
+
+
diff -urN sgpio_rh_snap4/version.h sgpio_new/version.h
--- sgpio_rh_snap4/version.h	2008-07-14 16:01:37.000000000 +0200
+++ sgpio_new/version.h	2008-11-25 09:05:24.000000000 +0100
@@ -8,7 +8,7 @@
  *
  * 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. See the GNU General Public License 
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  * for more details.
  *
  * You should have received a copy of the GNU General Public License along
@@ -18,11 +18,11 @@
 
 /*
  * Intel SGPIO enclosure management utility
- * Author: Eric R Hall <Eric.R.Hall@intel.com> 
- * 
+ * Author: Eric R Hall <Eric.R.Hall@intel.com>
+ *
  */
 
 #define UTIL_VERSION_MAJOR 0
-#define UTIL_VERSION_MINOR 9
+#define UTIL_VERSION_MINOR 10
 #define SGPIO_VERSION_MAJOR 1
 #define SGPIO_VERSION_MINOR 2
openSUSE Build Service is sponsored by