summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2005-12-06 20:55:39 +0100
committerDominik Brodowski <brodo@isilmar.linta.de>2005-12-06 20:58:39 +0100
commita60643f3c2a2df8645965b085ba8325901f31b09 (patch)
treeb14fcead171d3c041356b98f28c0a743ff6ca0df
parent8afe48747b193e039bdc698406adbbadabf21aa4 (diff)
downloadpcmciautils-a60643f3c2a2df8645965b085ba8325901f31b09.tar.gz
Release of pcmciautils-009 (2005-09-13)
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r--Makefile6
-rw-r--r--src/lex_config.l1
-rw-r--r--src/pccardctl.c77
-rw-r--r--src/pcmcia-check-broken-cis.c155
-rw-r--r--src/startup.c14
-rw-r--r--src/yacc_config.y1
6 files changed, 224 insertions, 30 deletions
diff --git a/Makefile b/Makefile
index 30ef605..ea93a75 100644
--- a/Makefile
+++ b/Makefile
@@ -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