bk://bk.arm.linux.org.uk/linux-2.6-pcmcia
linux@de.rmk.(none)|ChangeSet|20040706202122|02650 linux

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/07/06 21:21:22+01:00 linux@de.rmk.(none) 
#   [PCMCIA] card insert / eject
#   
#   Patch from Dominik Brodowski
#   
#   Add two further attributes, "card_insert" and "card_eject". Reading
#   these files will fail; but writing _anything_ non-empty to these
#   files will execute an user insert/ejection request -- equivalent
#   to "cardctl insert", "cardctl eject".
#   
#   To ensure proper error values to userspace, transform the return
#   values from CS_ error codes to -E error codes.
# 
# drivers/pcmcia/socket_sysfs.c
#   2004/07/06 21:17:48+01:00 linux@de.rmk.(none) +32 -0
#   [PATCH] card insert / eject
# 
# drivers/pcmcia/ds.c
#   2004/07/06 21:17:48+01:00 linux@de.rmk.(none) +2 -2
#   [PATCH] card insert / eject
# 
# drivers/pcmcia/cs.c
#   2004/07/06 21:17:47+01:00 linux@de.rmk.(none) +8 -6
#   [PATCH] card insert / eject
# 
# ChangeSet
#   2004/07/06 21:12:33+01:00 linux@de.rmk.(none) 
#   [PCMCIA] card vpp / vcc
#   
#   Patch from Dominik Brodowski
#   
#   Add attributes "card_vpp" and "card_vcc" which return these voltages,
#   like "3.3V"
# 
# drivers/pcmcia/socket_sysfs.c
#   2004/07/06 21:04:53+01:00 linux@de.rmk.(none) +20 -0
#   [PATCH] card vpp / vcc
# 
# ChangeSet
#   2004/07/06 20:57:25+01:00 linux@de.rmk.(none) 
#   [PCMCIA] card voltage
#   
#   Patch from Dominik Brodowski
#   
#   Add an attribute "card_voltage" which returns the card's voltage
#   requirements:
#   
#   "5.0V", "3.3V" or "X.XV".
# 
# drivers/pcmcia/socket_sysfs.c
#   2004/07/06 20:53:45+01:00 linux@de.rmk.(none) +17 -0
#   [PATCH] card voltage
# 
# ChangeSet
#   2004/07/06 20:45:17+01:00 linux@de.rmk.(none) 
#   [PCMCIA] core socket sysfs support, export card type
#   
#   Patch from Dominik Brodowski
#   
#   Add a first socket-related sysfs entry; and to keep things ordered,
#   do so in a new file drivers/pcmcia/socket_sysfs.c. To keep things
#   easy, all files will be present all the time, even if no card is in
#   the socket at a specific moment -- however, accessing the file will
#   result in -ENODEV then, so that
#   
#   # cat /sys/class/pcmcia_socket/pcmcia_socket1/card_type
#   
#   will cause an error message like
#   
#   "cat: card_type: No such device"
#   
#   which is quite self-explanatory.
#   
#   
#   The attribute "card_type" will return either "16-bit" or "32-bit",
#   depending on whether the PCCard is a 16-bit PCMCIA card or a 32-bit
#   CardBus card. The result "invalid" should not happen, and if it
#   happens, something strange is going on.
# 
# drivers/pcmcia/socket_sysfs.c
#   2004/07/06 20:41:25+01:00 linux@de.rmk.(none) +76 -0
# 
# drivers/pcmcia/socket_sysfs.c
#   2004/07/06 20:41:25+01:00 linux@de.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-pcmcia/drivers/pcmcia/socket_sysfs.c
# 
# drivers/pcmcia/cs_internal.h
#   2004/07/06 20:41:25+01:00 linux@de.rmk.(none) +3 -0
#   [PATCH] core socket sysfs support, export card type
# 
# drivers/pcmcia/cs.c
#   2004/07/06 20:41:25+01:00 linux@de.rmk.(none) +7 -0
#   [PATCH] core socket sysfs support, export card type
# 
# drivers/pcmcia/Makefile
#   2004/07/06 20:41:24+01:00 linux@de.rmk.(none) +1 -1
#   [PATCH] core socket sysfs support, export card type
# 
# ChangeSet
#   2004/07/05 21:33:44+01:00 linux@de.rmk.(none) 
#   [PCMCIA] check for proper registration with device core
#   
#   Patch from Dominik Brodowski
#   
#   Fail if registration of socket with driver core failed. This is
#   necessary so that socket-related sysfs entries will appear always
#   if a socket thread is up and running.
# 
# drivers/pcmcia/cs.c
#   2004/07/05 21:30:45+01:00 linux@de.rmk.(none) +8 -3
#   [PATCH] check for proper registration with device core
# 
# ChangeSet
#   2004/06/26 18:49:10-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-pcmcia
# 
# drivers/pcmcia/yenta_socket.c
#   2004/06/26 18:49:07-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/pcmcia/i82365.c
#   2004/06/26 18:49:07-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/ide/legacy/ide-cs.c
#   2004/06/26 18:49:07-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/24 12:55:15-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-pcmcia
# 
# drivers/ide/legacy/ide-cs.c
#   2004/06/24 12:55:11-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/20 23:57:00-07:00 akpm@bix.(none) 
#   Merge bk://bk.arm.linux.org.uk/linux-2.6-pcmcia
#   into bix.(none):/usr/src/bk-pcmcia
# 
# drivers/pcmcia/yenta_socket.c
#   2004/06/20 23:56:57-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/pcmcia/i82365.c
#   2004/06/20 23:56:57-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
diff -Nru a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
--- a/drivers/pcmcia/Makefile	2004-07-08 18:18:20 -07:00
+++ b/drivers/pcmcia/Makefile	2004-07-08 18:18:20 -07:00
@@ -18,7 +18,7 @@
 obj-$(CONFIG_PCMCIA_SA1111)			+= sa11xx_core.o sa1111_cs.o
 obj-$(CONFIG_PCMCIA_PXA2XX)                     += pxa2xx_core.o pxa2xx_cs.o
 
-pcmcia_core-y					+= cistpl.o rsrc_mgr.o bulkmem.o cs.o
+pcmcia_core-y					+= cistpl.o rsrc_mgr.o bulkmem.o cs.o socket_sysfs.o
 pcmcia_core-$(CONFIG_CARDBUS)			+= cardbus.o
 
 sa11xx_core-y					+= soc_common.o sa11xx_base.o
diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c	2004-07-08 18:18:20 -07:00
+++ b/drivers/pcmcia/cs.c	2004-07-08 18:18:20 -07:00
@@ -264,7 +264,10 @@
 		goto err;
 
 	wait_for_completion(&socket->thread_done);
-	BUG_ON(!socket->thread);
+	if(!socket->thread) {
+		printk(KERN_WARNING "PCMCIA: warning: socket thread for socket %p did not start\n", socket);
+		return -EIO;
+	}
 	pcmcia_parse_events(socket, SS_DETECT);
 
 	return 0;
@@ -678,9 +681,8 @@
 	int ret;
 
 	daemonize("pccardd");
-	skt->thread = current;
-	complete(&skt->thread_done);
 
+	skt->thread = current;
 	skt->socket = dead_socket;
 	skt->ops->init(skt);
 	skt->ops->set_socket(skt, &skt->socket);
@@ -690,7 +692,17 @@
 	if (ret) {
 		printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n",
 			skt);
+		skt->thread = NULL;
+		complete_and_exit(&skt->thread_done, 0);
 	}
+	if (pccard_sysfs_init(skt)) {
+		printk(KERN_WARNING "PCMCIA: unable to register sysfs attributes for socket 0x%p\n",
+			skt);
+		skt->thread = NULL;
+		class_device_unregister(&skt->dev);
+		complete_and_exit(&skt->thread_done, 0);
+	}
+	complete(&skt->thread_done);
 
 	add_wait_queue(&skt->thread_wait, &wait);
 	for (;;) {
@@ -2031,16 +2043,18 @@
 	down(&skt->skt_sem);
 	do {
 		if (!(skt->state & SOCKET_PRESENT)) {
-			ret = CS_NO_CARD;
+			ret = -ENODEV;
 			break;
 		}
 
 		ret = send_event(skt, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW);
-		if (ret != 0)
+		if (ret != 0) {
+			ret = -EINVAL;
 			break;
+		}
 
 		socket_remove(skt);
-		ret = CS_SUCCESS;
+		ret = 0;
 	} while (0);
 	up(&skt->skt_sem);
 
@@ -2056,14 +2070,14 @@
 	down(&skt->skt_sem);
 	do {
 		if (skt->state & SOCKET_PRESENT) {
-			ret = CS_IN_USE;
+			ret = -EBUSY;
 			break;
 		}
 		if (socket_insert(skt) == CS_NO_CARD) {
-			ret = CS_NO_CARD;
+			ret = -ENODEV;
 			break;
 		}
-		ret = CS_SUCCESS;
+		ret = 0;
 	} while (0);
 	up(&skt->skt_sem);
 
diff -Nru a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
--- a/drivers/pcmcia/cs_internal.h	2004-07-08 18:18:20 -07:00
+++ b/drivers/pcmcia/cs_internal.h	2004-07-08 18:18:20 -07:00
@@ -192,6 +192,9 @@
 int adjust_resource_info(client_handle_t handle, adjust_t *adj);
 void release_resource_db(void);
 
+/* In socket_sysfs.c */
+int pccard_sysfs_init(struct pcmcia_socket *s);
+
 extern struct rw_semaphore pcmcia_socket_list_rwsem;
 extern struct list_head pcmcia_socket_list;
 
diff -Nru a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
--- a/drivers/pcmcia/ds.c	2004-07-08 18:18:20 -07:00
+++ b/drivers/pcmcia/ds.c	2004-07-08 18:18:20 -07:00
@@ -973,10 +973,10 @@
 	ret = pcmcia_resume_card(s->parent);
 	break;
     case DS_EJECT_CARD:
-	ret = pcmcia_eject_card(s->parent);
+	err = pcmcia_eject_card(s->parent);
 	break;
     case DS_INSERT_CARD:
-	ret = pcmcia_insert_card(s->parent);
+	err = pcmcia_insert_card(s->parent);
 	break;
     case DS_ACCESS_CONFIGURATION_REGISTER:
 	if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
diff -Nru a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/pcmcia/socket_sysfs.c	2004-07-08 18:18:20 -07:00
@@ -0,0 +1,145 @@
+/*
+ * socket_sysfs.c -- most of socket-related sysfs output
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * (C) 2003 - 2004		Dominik Brodowski
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+
+#define IN_CARD_SERVICES
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+#include "cs_internal.h"
+
+#define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev)
+
+static ssize_t pccard_show_type(struct class_device *dev, char *buf)
+{
+	int val;
+	struct pcmcia_socket *s = to_socket(dev);
+
+        if (!(s->state & SOCKET_PRESENT))
+                return -ENODEV;
+	s->ops->get_status(s, &val);
+	if (val & SS_CARDBUS)
+		return sprintf(buf, "32-bit\n");
+	if (val & SS_DETECT)
+		return sprintf(buf, "16-bit\n");
+	return sprintf(buf, "invalid\n");
+}
+static CLASS_DEVICE_ATTR(card_type, 0400, pccard_show_type, NULL);
+
+static ssize_t pccard_show_voltage(struct class_device *dev, char *buf)
+{
+	int val;
+	struct pcmcia_socket *s = to_socket(dev);
+
+        if (!(s->state & SOCKET_PRESENT))
+                return -ENODEV;
+	s->ops->get_status(s, &val);
+	if (val & SS_3VCARD)
+		return sprintf(buf, "3.3V\n");
+	if (val & SS_XVCARD)
+		return sprintf(buf, "X.XV\n");
+	return sprintf(buf, "5.0V\n");
+}
+static CLASS_DEVICE_ATTR(card_voltage, 0400, pccard_show_voltage, NULL);
+
+static ssize_t pccard_show_vpp(struct class_device *dev, char *buf)
+{
+	struct pcmcia_socket *s = to_socket(dev);
+	if (!(s->state & SOCKET_PRESENT))
+		return -ENODEV;
+	return sprintf(buf, "%d.%dV\n", s->socket.Vpp / 10, s->socket.Vpp % 10);
+}
+static CLASS_DEVICE_ATTR(card_vpp, 0400, pccard_show_vpp, NULL);
+
+static ssize_t pccard_show_vcc(struct class_device *dev, char *buf)
+{
+	struct pcmcia_socket *s = to_socket(dev);
+	if (!(s->state & SOCKET_PRESENT))
+		return -ENODEV;
+	return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10, s->socket.Vcc % 10);
+}
+static CLASS_DEVICE_ATTR(card_vcc, 0400, pccard_show_vcc, NULL);
+
+
+static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, size_t count)
+{
+	ssize_t ret;
+	struct pcmcia_socket *s = to_socket(dev);
+
+	if (!count)
+		return -EINVAL;
+
+	ret = pcmcia_insert_card(s);
+
+	return ret ? ret : count;
+}
+static CLASS_DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert);
+
+static ssize_t pccard_store_eject(struct class_device *dev, const char *buf, size_t count)
+{
+	ssize_t ret;
+	struct pcmcia_socket *s = to_socket(dev);
+
+	if (!count)
+		return -EINVAL;
+
+	ret = pcmcia_eject_card(s);
+
+	return ret ? ret : count;
+}
+static CLASS_DEVICE_ATTR(card_eject, 0200, NULL, pccard_store_eject);
+
+
+static struct class_device_attribute *pccard_socket_attributes[] = {
+	&class_device_attr_card_type,
+	&class_device_attr_card_voltage,
+	&class_device_attr_card_vpp,
+	&class_device_attr_card_vcc,
+	&class_device_attr_card_insert,
+	&class_device_attr_card_eject,
+	NULL,
+};
+
+int pccard_sysfs_init(struct pcmcia_socket *s)
+{
+	struct class_device_attribute *attr;
+	unsigned int i;
+	int ret = 0;
+        for (i = 0; (attr = pccard_socket_attributes[i]); i++) {
+                if ((ret = class_device_create_file(&s->dev, attr)))
+			return (ret);
+        }
+	return (ret);
+}
