diff options
author | Andrew Wilcox <andy@protium.com> | 2006-12-07 19:22:25 +0000 |
---|---|---|
committer | Andrew Wilcox <andy@protium.com> | 2006-12-07 19:22:25 +0000 |
commit | 21f0d4357067e495f29a752e529ee6f55a14f3d2 (patch) | |
tree | b7f5c8b5c04ca88183af568e9fd8b4adafe50410 /packages/sccd/files/scc-utils.c | |
parent | b76d8f80b7cb99176838281a15c4b8f8f60ae18d (diff) |
sccd: StorCenter Control Daemon: leds and fan control server/client
Diffstat (limited to 'packages/sccd/files/scc-utils.c')
-rw-r--r-- | packages/sccd/files/scc-utils.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/packages/sccd/files/scc-utils.c b/packages/sccd/files/scc-utils.c new file mode 100644 index 0000000000..ab48ecb677 --- /dev/null +++ b/packages/sccd/files/scc-utils.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2006 + * Protium Computing, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Protium Computing, Inc. + * 4. The name of Protium Computing, Inc. may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY PROTIUM COMPUTING ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PROTIUM COMPUTING BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <stdio.h> +#include <fcntl.h> +#include <time.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/select.h> +#include <sys/syslog.h> +#include <sys/resource.h> +#include <termios.h> + +#include "scc.h" + +int scc_die = 0; + +char +scc_cksum(int *i, int *j) +{ + unsigned char s; + unsigned char *b; + + b = (unsigned char *)i; + s = b[0] + b[1] + b[2] + b[3]; + b = (unsigned char *)j; + s = s + b[0] + b[1] + b[2]; + s = (s & 0x7f); + + return((char)s); +} + +int +scc_validate(int *i, int *j, int verbose) +{ + int r, s; + + /* if (verbose) printf("Packet: [0x%08x 0x%08x]\n", *i, *j); */ + + switch (*i & SCC_POWERMASK) { + case SCC_RUN: + if (verbose) printf("\tPower: run\n"); + break; + case SCC_STOP: + if (verbose) printf("\tPower: stop\n"); + break; + case SCC_ADVISESTOP: + if (verbose) printf("\tPower: advise stop\n"); + break; + case SCC_RESTART: + if (verbose) printf("\tPower: restart\n"); + break; + case SCC_ADVISERESTART: + if (verbose) printf("\tPower: advise restart\n"); + break; + case SCC_RESET: + if (verbose) printf("\tPower: reset\n"); + break; + case SCC_ADVISERESET: + if (verbose) printf("\tPower: advise reset\n"); + break; + default: + if (verbose) printf("validate: bad power 0x%08x\n", *i); + return(-1); + } + + switch (*i & SCC_LEDMASK) { + case SCC_LEDOFF: + if (verbose) printf("\tLed: off\n"); + break; + case SCC_LEDBLUE: + if (verbose) printf("\tLed: blue\n"); + break; + case SCC_LEDRED: + if (verbose) printf("\tLed: red\n"); + break; + case SCC_LEDBLUEFLASH: + if (verbose) printf("\tLed: blue flash\n"); + break; + case SCC_LEDREDFLASH: + if (verbose) printf("\tLed: red flash\n"); + break; + case SCC_LEDALTERNATE1: + if (verbose) printf("\tLed: alternate1\n"); + break; + case SCC_LEDALTERNATE3: + if (verbose) printf("\tLed: alternate3\n"); + break; + default: + if (verbose) printf("validate: bad led value 0x%08x\n", *i); + return(-1); + } + + r = ((*i & SCC_LEDRATEMASK) >> SCC_LEDRATESHIFT); + + if (verbose) { + printf("\tLed Flash Rate: %d\n", r); + } + + if (r >= SCC_LEDRATEHI) + printf("warning: led rate too high - led on (%d)\n", r); + if (r <= SCC_LEDRATELO) + printf("warning: led rate too low - led off (%d)\n", r); + + + switch (*i & SCC_FANMASK) { + case SCC_FANAUTO: + if (verbose) printf("\tFan: auto\n"); + break; + case SCC_FANON: + if (verbose) printf("\tFan: on\n"); + break; + default: + if (verbose) printf("validate: bad fan value 0x%08x\n", *i); + return(-1); + } + + r = ((*j & SCC_FANTEMPONMASK) >> SCC_FANTEMPONSHIFT); + s = ((*j & SCC_FANTEMPOFFMASK) >> SCC_FANTEMPOFFSHIFT); + + if (verbose) { + printf("\tFan On Temprature: %dC\n", r); + printf("\tFan Off Temprature: %dC\n", s); + } + + if (r >= SCC_FANTEMPONHI) + printf("warning: fan on temp too high - fan off (%dC)\n", r); + if (s <= SCC_FANTEMPONLO) + printf("warning: fan on temp too low - fan on (%dC)\n", s); + if ((r - s) < SCC_FANTEMPDIFF) { + printf("warning: fan on/off temp too close or on < off \n"); + printf("warning:\tfan on (%dC) fan off (%dC) \n", r, s); + } + + r = *j & SCC_IDMASK; + if ((r != SCC_HOST) && + (r != SCC_CTLR00) && + (r != SCC_CTLR12)) { + printf("warning: bad id %08x\n", r); + } + + r = *j & SCC_CKSUMMASK; + if (r != scc_cksum(i, j)) { + printf("warning: checksum incorrect (%02x != %02x)\n", + r, scc_cksum(i, j)); + } + return(0); +} + +int +scc_setval(int *i, int mask, int val) +{ + /* clear the field */ + *i = (*i & (mask ^ 0xffffffff)); + + /* insert the field */ + *i = (*i ^ val); + return(0); +} + +int +scc_setrate(int *i, int mask, int shift, int val) +{ + /* Assumption: val is < field width */ + + /* clear the field */ + *i = (*i & (mask ^ 0xffffffff)); + + /* insert the field */ + *i = (*i ^ (val << shift)); + return(0); +} + +int +scc_defaults(int *i, int *j) +{ + scc_setval(i, SCC_POWERMASK, SCC_POWERDEFAULT); + scc_setval(i, SCC_LEDMASK, SCC_LEDDEFAULT); + scc_setrate(i, SCC_LEDRATEMASK, SCC_LEDRATESHIFT, SCC_LEDRATEDEFAULT); + scc_setval(i, SCC_FANMASK, SCC_FANDEFAULT); + + scc_setrate(j, SCC_FANTEMPONMASK, + SCC_FANTEMPONSHIFT, SCC_FANTEMPONDEFAULT); + scc_setrate(j, SCC_FANTEMPOFFMASK, + SCC_FANTEMPOFFSHIFT, SCC_FANTEMPOFFDEFAULT); + return(0); +} + +void +scc_sighandler(int sig) +{ + /* + * Just catch quit and term and set die + */ + switch(sig) { + case SIGQUIT: + case SIGTERM: + syslog(LOG_INFO, "Terminating"); + scc_die=1; + break; + } +} + +int +scc_daemonize(int cores) +{ + int fd, i; + char pidstr[20]; + pid_t pid; + + struct rlimit limit[1] = {{ 0, 0 }}; + + + if (!cores) { + /* + * No corefiles please + */ + if (getrlimit(RLIMIT_CORE, limit) == -1) { + perror("getrlimit"); + return -1; + } + + limit->rlim_cur = 0; + + if (setrlimit(RLIMIT_CORE, limit) != 0) { + perror("setrlimit"); + return -1; + } + } + + /* + * Must be root + */ + if (getuid() != 0) { + fprintf(stderr, "Must be root\n"); + return -1; + } + + /* + * If parent isn't init, make it init. + */ + if (getppid() != 1) { + + pid = fork(); + if (pid == -1) { + return -1; + } + if (pid != 0) { + exit(EXIT_SUCCESS); + } + + setsid(); + + /* + * ignore sig hup so that when our new padre exits + * the kinder won't exit + */ + signal(SIGHUP, SIG_IGN); + + pid = fork(); + if (pid == -1) { + return -1; + } + if (pid != 0) { + exit(EXIT_SUCCESS); + } + } + + /* + * Set working dir to root + */ + chdir("/"); + + /* + * Make sure file creations are created with explicit perms + */ + umask(0); + + /* + * Close all FDs + */ + for (i = 0; i < sysconf(_SC_OPEN_MAX); i++) { + close(i); + } + + /* + * set std in, out, err to /dev/null + */ + for (i = 0; i < 3; i++) { + + if ((fd = open("/dev/null", (i==0?O_RDONLY:O_WRONLY))) == -1) { + perror("setting up stdin, stdout, stderr"); + return -1; + } + + if (i != fd) { + if (dup2(fd, i) == -1) { + perror("setting up stdin, stdout, stderr"); + return -1; + } + close(fd); + } + } + + /* + * Open and lock the pid file. Ensures only one daemon + * Write our pid into the file + */ + fd = open(SCC_PIDFILE, O_RDWR|O_CREAT, 0640); + if (fd < 0) { + return(-1); + + } + + if (lockf(fd, F_TLOCK, 0) < 0) { + /* we are not alone */ + close(fd); + return(-1); + } + + sprintf(pidstr,"%-6d\n", getpid()); + write(fd, pidstr, strlen(pidstr)); + + /* + * Open syslog + */ + openlog("sccd", LOG_PID, LOG_DAEMON); + syslog(LOG_INFO, "Starting"); + + /* + * Ignore some signals and handle others + */ + signal(SIGCHLD, SIG_IGN); + signal(SIGTSTP, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + signal(SIGQUIT, scc_sighandler); + signal(SIGTERM, scc_sighandler); + + return(0); +} + + |