From: Dominik Brodowski <linux@dominikbrodowski.net>

Here follow PCMCIA-related patches which allow for kernel-based matching
between 16-bit PCMCIA devices and their drivers.  If you're using this (and
using a special startup script or small tool), you don't need to run "cardmgr"
any longer.  cardmgr still works, though, allowing for a gradual transition.

These patches apply on top of what's in 2.6.11-rc4-mm1; for proper operation
pcmcia-bridge-resource-management-fix.patch should be removed first, though. 
Andrew, please apply them to your next -mm release.


1. Theory of operation I: setting up the sockets
------------------------------------------------
- the appropriate socket driver is initialized (modprobe or built-in)
- a hotplug event (CLASS=pcmcia_socket) is generated
- if it's a socket which doesn't map the resources statically, resources
  available for use by PCMCIA cards need to be marked as "allowed". This is
  done using either a small shell script[*] or pcmcia-socket-startup[**]. The
  latter parses /etc/pcmcia/config.opts -- the same file cardmgr currently
  uses for this purpose.

[*] e.g.
#!/bin/sh
echo -n "+ 0x00000100 - 0x000004cf" > /sys/class/pcmcia_socket/pcmcia_socket1/available_resources_io
echo -n "+ 0x60000000 - 0x60ffffff" > /sys/class/pcmcia_socket/pcmcia_socket1/available_resources_mem
echo -n "1" > /sys/class/pcmcia_socket/pcmcia_socket1/available_resources_setup_done

[**] note: for pcmcia-socket-startup to work properly you need a patch for 
     libsysfs (it is already accepted by the maintainer of the package). See 
     below for details.


2. Theory of operation II: setting up a device
----------------------------------------------
- a pcmcia device is discovered in the socket
- device information is determined and exported to sysfs 
- a hotplug event is created, passing -- among others -- a complete MODNAME 
  string to userspace. Available match flags are the product ID strings [in
  userspace, only the hashes are matched -- you can't use strings in 
  modules.alias], manufactor and card ID, the multifunction device number,
  the pseudo-multifunction device number [this is what e.g.
	bind "serial_cs", bind "serial_cs"
  was before], whether it needs a CIS override, and the function ID [this match
  is only used if it is allowed by userspace -- it should be avoided and will 
  be removed in future, after existing users have been converted to matches of 
  other types].
- modprobe $MODNAME [*]
- the device is matched against drivers. function ID matches are ignored at
  this stage. If the device needs a CIS override, it is requested from 
  userspace using the firmware helpers. It is recommended to have a symlink 
  either from  /lib/firmware/cis/ to /etc/pcmcia/cis/ or the other way to let 
  both (old) cardmgr and (new) firmware.agent access the override CIS data.
- if no driver was found, an userspace helper checks whether the card is one of
  two(!) which can only be detected using cardmgr's tuple directive. If this is
  the case, a CIS override is done using 
  /sys/class/pcmcia_socket/pcmcia_socket%n/cis , loading a CIS with proper
  identification values.
- if this doesn't lead to a driver being bound to the device, function ID-based
  matches are allowed.

[*] note: for this to work properly you need a patch to be written which loads
    _all_ matching modules, not just one]


3. patches
----------
I'll not send the patches which add the proper device identification tables to 
this list, but only (and a bit later) to Andrew and the appropriate 
maintainers. You can find them already at
http://www.kernel.org/pub/linux/kernel/people/brodo/patches/2.6.11-rc5/
-- they start with pcmcia-25-

I used all identification information I could find in pcmcia-cs, the kernel,
and some web resources and, but probably missed some. If I did, please send 
me either the appropriate device info from the cardmgr config file or the 
output of "pcmcia-modalias" (see below) -- or a PCMCIA_MATCH patch.


4. userspace tools
------------------
Several GPL[*] userspace tools are required or useful for this (new) method of 
operation. I'll send them to this list for review, and they're also available 
_temporarily_ at
http://www.kernel.org/pub/linux/kernel/people/brodo/temp-pcmcia-tools.tar.gz

I'm still undecided on what to do with these userspace tools. IMO they could 
either be merged into pcmcia-cs or distributed in addition to pcmcia-cs. Also, 
I'd be very glad if somebody else could maintain and improve these tools.

pcmcia-socket-startup
This tool is based on "cardmgr" by Dave Hinds, but most of it was removed. The 
remains parse the /etc/pcmcia/config file for allowed ioport and iomem ranges 
and for disallowed IRQs, and sets these using libsysfs. Due to a bug in 
libsysfs, a patch is needed for this to work properly. It takes one parameter, 
the socket number to be set up.


pcmcia-modalias
This tool reads device information and generates a MODALIAS string just like 
the kernel exports using hotplug for this device. It takes one paramter, the 
device's bus_id string (e.g. "pcmcia-modalias 1.0" for the first device on the 
second PCMCIA socket)


pcmcia-check-broken-cis
This checks whether the CIS is so broken that only the "tuple"-based match is
possible. It takes one parameter, the socket the PCMCIA card to be tested is
inserted to, and returns nothing (if no CIS override is needed), or the CIS
file name. The CIS parsing is done using a much simplified version of what
is to be found in drivers/pcmcia/cistpl.c, so this is based on Dave Hinds
work as well.


hotplug/pcmcia*
The hotplug scripts are quite self-explanatory and also allow for "coldplug" 
(i.e. they work around "missed" events during boot).


pccardctl
This previously announced tool uses sysfs instead of an ioctl for commands 
like "eject", "insert", "info" and "ident".


[*] reason: they're partly based on other GPL-licensed tools.


This patch:


Don't inform cardmgr of ejection requests so that "cardctl eject" behaves
_exactly_ the same as a physical ejection from an userspace point of view.

Removing this allows us to clean up some other code which is otherwise unused.

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/pcmcia/ds.c |   45 ++------------------------------------------
 1 files changed, 3 insertions(+), 42 deletions(-)

diff -puN drivers/pcmcia/ds.c~pcmcia-dont-send-eject-request-events-to-userspace drivers/pcmcia/ds.c
--- 25/drivers/pcmcia/ds.c~pcmcia-dont-send-eject-request-events-to-userspace	Sun Mar  6 17:28:05 2005
+++ 25-akpm/drivers/pcmcia/ds.c	Sun Mar  6 17:28:05 2005
@@ -91,8 +91,7 @@ struct pcmcia_bus_socket {
 	struct pcmcia_callback	callback;
 	int			state;
 	user_info_t		*user;
-	int			req_pending, req_result;
-	wait_queue_head_t	queue, request;
+	wait_queue_head_t	queue;
 	struct pcmcia_socket	*parent;
 
 	/* the PCMCIA devices connected to this socket (normally one, more
@@ -673,19 +672,6 @@ static void handle_event(struct pcmcia_b
     wake_up_interruptible(&s->queue);
 }
 
-static int handle_request(struct pcmcia_bus_socket *s, event_t event)
-{
-    if (s->req_pending != 0)
-	return CS_IN_USE;
-    if (s->state & DS_SOCKET_BUSY)
-	s->req_pending = 1;
-    handle_event(s, event);
-    if (wait_event_interruptible(s->request, s->req_pending <= 0))
-        return CS_IN_USE;
-    if (s->state & DS_SOCKET_BUSY)
-        return s->req_result;
-    return CS_SUCCESS;
-}
 
 /*======================================================================
 
@@ -767,9 +753,6 @@ static int ds_event(struct pcmcia_socket
 		break;
 
 	case CS_EVENT_EJECTION_REQUEST:
-		ret = handle_request(s, event);
-		if (ret)
-			break;
 		ret = send_event(skt, event, priority);
 		break;
 
@@ -1216,8 +1199,6 @@ static int ds_release(struct inode *inod
     /* Unlink user data structure */
     if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
 	s->state &= ~DS_SOCKET_BUSY;
-	s->req_pending = 0;
-	wake_up_interruptible(&s->request);
     }
     file->private_data = NULL;
     for (link = &s->user; *link; link = &(*link)->next)
@@ -1266,33 +1247,14 @@ static ssize_t ds_read(struct file *file
 static ssize_t ds_write(struct file *file, const char __user *buf,
 			size_t count, loff_t *ppos)
 {
-    struct pcmcia_bus_socket *s;
-    user_info_t *user;
-
     ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode));
-    
+
     if (count != 4)
 	return -EINVAL;
     if ((file->f_flags & O_ACCMODE) == O_RDONLY)
 	return -EBADF;
 
-    user = file->private_data;
-    if (CHECK_USER(user))
-	return -EIO;
-
-    s = user->socket;
-    if (s->state & DS_SOCKET_DEAD)
-        return -EIO;
-
-    if (s->req_pending) {
-	s->req_pending--;
-	get_user(s->req_result, (int __user *)buf);
-	if ((s->req_result != 0) || (s->req_pending == 0))
-	    wake_up_interruptible(&s->request);
-    } else
-	return -EIO;
-
-    return 4;
+    return -EIO;
 } /* ds_write */
 
 /*====================================================================*/
@@ -1564,7 +1526,6 @@ static int __devinit pcmcia_bus_add_sock
 	msleep(250);
 
 	init_waitqueue_head(&s->queue);
-	init_waitqueue_head(&s->request);
 	INIT_LIST_HEAD(&s->devices_list);
 
 	/* Set up hotline to Card Services */
_