diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2005-12-06 20:55:39 +0100 |
---|---|---|
committer | Dominik Brodowski <brodo@isilmar.linta.de> | 2005-12-06 20:58:39 +0100 |
commit | a60643f3c2a2df8645965b085ba8325901f31b09 (patch) | |
tree | b14fcead171d3c041356b98f28c0a743ff6ca0df | |
parent | 8afe48747b193e039bdc698406adbbadabf21aa4 (diff) | |
download | pcmciautils-a60643f3c2a2df8645965b085ba8325901f31b09.tar.gz |
Release of pcmciautils-009 (2005-09-13)
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | src/lex_config.l | 1 | ||||
-rw-r--r-- | src/pccardctl.c | 77 | ||||
-rw-r--r-- | src/pcmcia-check-broken-cis.c | 155 | ||||
-rw-r--r-- | src/startup.c | 14 | ||||
-rw-r--r-- | src/yacc_config.y | 1 |
6 files changed, 224 insertions, 30 deletions
@@ -40,7 +40,7 @@ PCMCIA_SOCKET_STARTUP = pcmcia-socket-startup CBDUMP = cbdump CISDUMP = dump_cis -VERSION = 008 +VERSION = 009 #INSTALL_DIR = /usr/local/sbin RELEASE_NAME = pcmciautils-$(VERSION) @@ -102,12 +102,12 @@ OPTIMIZATION := ${shell if $(CC) -Os -S -o /dev/null -xc /dev/null >/dev/null 2> # check if compiler option is supported cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} -WARNINGS := -Wall -fno-builtin -Wchar-subscripts -Wpointer-arith -Wsign-compare +WARNINGS := -Wall -Wchar-subscripts -Wpointer-arith -Wsign-compare WARNINGS += $(call cc-supports,-Wno-pointer-sign) WARNINGS += $(call cc-supports,-Wdeclaration-after-statement) WARNINGS += -Wshadow -CFLAGS := -pipe +CFLAGS := -pipe -DVERSION=\"$(VERSION)\" YFLAGS := -d HEADERS = \ diff --git a/src/lex_config.l b/src/lex_config.l index 746edc1..2d99966 100644 --- a/src/lex_config.l +++ b/src/lex_config.l @@ -15,6 +15,7 @@ */ #undef src +#undef VERSION #include <stdio.h> #include <stdlib.h> diff --git a/src/pccardctl.c b/src/pccardctl.c index a8ed681..02ad3ee 100644 --- a/src/pccardctl.c +++ b/src/pccardctl.c @@ -26,6 +26,37 @@ #define MAX_SOCKET 8 +static int pccardctl_power_one(unsigned long socket_no, unsigned int device, + unsigned int power) +{ + int ret; + char file[SYSFS_PATH_MAX]; + struct sysfs_attribute *attr; + + snprintf(file, SYSFS_PATH_MAX, + "/sys/bus/pcmcia/devices/%lu.%u/power/state", + socket_no, device); + + attr = sysfs_open_attribute(file); + if (!attr) + return -ENODEV; + + ret = sysfs_write_attribute(attr, power ? "3" : "0", 1); + + sysfs_close_attribute(attr); + + return (ret); +} + +static int pccardctl_power(unsigned long socket_no, unsigned int power) +{ + unsigned int i; + for (i=0; i<2; i++) /* max 2 devices per socket */ + pccardctl_power_one(socket_no, i, power); + + return 0; +} + static int pccardctl_echo_one(unsigned long socket_no, const char *in_file) { int ret; @@ -187,12 +218,31 @@ static int pccardctl_info(unsigned long socket_no) } static void print_header(void) { - printf("pccardctl (C) 2004 Dominik Brodowski, (C) 1999 David A. Hinds\n"); + printf("pcmciautils %s\n", VERSION); + printf("Copyright (C) 2004-2005 Dominik Brodowski, (C) 1999 David A. Hinds\n"); printf("Report errors and bugs to <linux-pcmcia@lists.infradead.org>, please.\n"); } +static char *cmdname[] = { + "insert", + "eject", + "suspend", + "resume", + "reset", + "info", + "status", + "config", + "ident", +}; + static void print_help(void) { - /* TBD */ + unsigned int i; + + printf("Usage: pccardctl COMMAND\n"); + printf("Supported commands are:\n"); + for (i = 0; i < sizeof(cmdname)/sizeof(cmdname[0]); i++) { + printf("\t%s\n", cmdname[i]); + } } static void print_unknown_arg(void) { @@ -221,18 +271,6 @@ enum { NCMD }; -static char *cmdname[] = { - "insert", - "eject", - "suspend", - "resume", - "reset", - "info", - "status", - "config", - "ident", -}; - int main(int argc, char **argv) { extern char *optarg; @@ -316,6 +354,17 @@ int main(int argc, char **argv) { case PCCARDCTL_IDENT: ret = pccardctl_ident(cont); break; + case PCCARDCTL_SUSPEND: + ret = pccardctl_power(cont, 3); + break; + case PCCARDCTL_RESET: + ret = pccardctl_power(cont, 3); + if (ret && socket_is_set) + return (ret); + /* fall through */ + case PCCARDCTL_RESUME: + ret = pccardctl_power(cont, 0); + break; default: fprintf(stderr, "command '%s' not yet handled by pccardctl\n", cmdname[cmd]); return -EAGAIN; diff --git a/src/pcmcia-check-broken-cis.c b/src/pcmcia-check-broken-cis.c index 82d8f14..d5597fa 100644 --- a/src/pcmcia-check-broken-cis.c +++ b/src/pcmcia-check-broken-cis.c @@ -13,14 +13,25 @@ * (C) 2005 Dominik Brodowski */ +#include <fcntl.h> +#include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include <errno.h> #include <syslog.h> +#include <sys/types.h> +#include <sys/stat.h> + #include "cistpl.h" + +#define FIRMWARE_PATH "/lib/firmware" +#define CIS_PATH "/etc/pcmcia/cis" +#define SOCKET_PATH "/sys/class/pcmcia_socket/pcmcia_socket%d/cis" + struct needs_cis { unsigned long code; unsigned long ofs; @@ -39,20 +50,140 @@ static struct needs_cis cis_table[] = { { }, }; +int device_has_driver() { + char *devpath, *path; + struct stat sbuf; + + devpath = getenv("DEVPATH"); + if (!devpath) + return ENODEV; + path = alloca(strlen(devpath)+15); + sprintf(path,"/sys/%s/driver", devpath); + if (!stat(path,&sbuf)) { + return 1; + } + return 0; +} + +char *read_cis(char *cis_file, int *size) { + char *cis_path; + char *ret; + int rc, cis_fd; + struct stat sbuf; + + cis_path = alloca(strlen(FIRMWARE_PATH) + strlen(cis_file) + 2); + sprintf(cis_path,"%s/%s", FIRMWARE_PATH, cis_file); + cis_fd = open(cis_path, O_RDONLY); + if (cis_fd == -1) { + cis_path = alloca(strlen(CIS_PATH) + strlen(cis_file) + 2); + sprintf(cis_path,"%s/%s", CIS_PATH, cis_file); + if (cis_fd == -1) { + rc = errno; + errno = rc; + return NULL; + } + } + fstat(cis_fd, &sbuf); + ret = malloc(sbuf.st_size); + if (!ret) { + rc = errno; + close(cis_fd); + errno = rc; + return NULL; + } + if (read(cis_fd, ret, sbuf.st_size) != sbuf.st_size) { + rc = errno; + free(ret); + close(cis_fd); + errno = rc; + return NULL; + } + close(cis_fd); + *size = sbuf.st_size; + return ret; +} + +int write_cis(char *cis, int socket_no, int size) { + char *cis_path; + int cis_fd, count, rc; + + cis_path = alloca(strlen(SOCKET_PATH) + 2); + sprintf(cis_path,SOCKET_PATH, socket_no); + + cis_fd = open(cis_path, O_RDWR); + if (cis_fd == -1) { + return errno; + } + + count = 0; + while (count < size) { + int c; + + c = write(cis_fd, cis+count, size-count); + if (c <= 0) { + rc = errno; + close(cis_fd); + return rc; + } + count += c; + } + close(cis_fd); + return 0; +} + +int repair_cis(char *cis_file, int socket_no) { + char *cis; + int rc, size; + + if (device_has_driver()) { + return 0; + } + + cis = read_cis(cis_file, &size); + if (!cis) + return errno; + + rc = write_cis(cis, socket_no, size); + free(cis); + return rc; +} + +static void usage(const char *progname) { + fprintf(stderr, + "Usage: %s [-r|--repair] <socketname>\n", progname); + exit(1); +} + +static struct option options[] = { { "repair", 0, NULL, 'r' }, + { NULL, 0, NULL, 0 } }; + int main(int argc, char **argv) { int ret; + char *socket; unsigned int socket_no; struct needs_cis * entry = NULL; tuple_t tuple; unsigned char buf[256]; - - if (argc != 2) - return -EINVAL; - - ret = sscanf(argv[1], "%u", &socket_no); - if (ret != 1) - return -ENODEV; - + int opt; + int repair = 0; + + while ((opt = getopt_long(argc, argv, "r", options, NULL)) != -1) { + switch (opt) { + case 'r': + repair = 1; + break; + default: + usage(argv[0]); + } + } + if ((socket = getenv("SOCKET_NO"))) { + socket_no = (unsigned int)strtoul(socket, NULL, 0); + } else { + if (argc < optind + 1) + usage(argv[0]); + socket_no = strtoul(argv[optind], NULL, 0); + } + ret = read_out_cis(socket_no, NULL); if (ret) return (ret); @@ -78,8 +209,12 @@ int main(int argc, char **argv) { entry++; continue; } - - printf("%s", entry->cisfile); + + if (repair) { + return repair_cis(entry->cisfile, socket_no); + } else { + printf("%s", entry->cisfile); + } }; return 0; diff --git a/src/startup.c b/src/startup.c index 0dd5f38..0197f4c 100644 --- a/src/startup.c +++ b/src/startup.c @@ -223,22 +223,30 @@ static void adjust_resources(unsigned int socket_no) int main(int argc, char *argv[]) { char *socket_no; - unsigned long socket; + unsigned long socket, i; + unsigned int all_sockets = 0; if ((socket_no = getenv("SOCKET_NO"))) { socket = strtoul(socket_no, NULL, 0); } else if (argc == 2) { socket = strtoul(argv[1], NULL, 0); + } else if (argc == 1) { + socket = 0; + all_sockets = 1; } else { return -EINVAL; } load_config(); - adjust_resources(socket); + for (i = 0; i < MAX_SOCKS; i++) { + if ((socket != i) && (!all_sockets)) + continue; - setup_done(socket); + adjust_resources(i); + setup_done(i); + } return 0; } diff --git a/src/yacc_config.y b/src/yacc_config.y index f6df721..23fc054 100644 --- a/src/yacc_config.y +++ b/src/yacc_config.y @@ -19,6 +19,7 @@ #include <sys/types.h> #include "startup.h" +#undef VERSION /* If bison: generate nicer error messages */ #define YYERROR_VERBOSE 1 |