25-akpm/drivers/pcmcia/Makefile      |    2 
 25-akpm/drivers/pcmcia/cistpl.c      |   45 ++------
 25-akpm/drivers/pcmcia/cs.c          |  101 ++++++++----------
 25-akpm/drivers/pcmcia/cs_internal.h |   10 -
 25-akpm/drivers/pcmcia/map.h         |   20 +++
 25-akpm/drivers/pcmcia/mapstatic.c   |  144 ++++++++++++++++++++++++++
 25-akpm/drivers/pcmcia/mapwindow.c   |  181 +++++++++++++++++++++++++++++++++
 25-akpm/drivers/pcmcia/rsrc_mgr.c    |  187 +++++++++++++++++++++--------------
 25-akpm/include/pcmcia/ss.h          |    1 
 9 files changed, 525 insertions(+), 166 deletions(-)

diff -puN drivers/pcmcia/cistpl.c~pcmcia-10 drivers/pcmcia/cistpl.c
--- 25/drivers/pcmcia/cistpl.c~pcmcia-10	Tue Mar 18 15:12:29 2003
+++ 25-akpm/drivers/pcmcia/cistpl.c	Tue Mar 18 15:12:29 2003
@@ -55,6 +55,7 @@
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
+#include "map.h"
 
 static const u_char mantissa[] = {
     10, 12, 13, 15, 20, 25, 30, 35,
@@ -84,17 +85,9 @@ static const u_int exponent[] = {
 
 INT_MODULE_PARM(cis_width,	0);		/* 16-bit CIS? */
 
-void release_cis_mem(socket_info_t *s)
+static void release_cis_mem(socket_info_t *s)
 {
-    if (s->cis_mem.sys_start != 0) {
-	s->cis_mem.flags &= ~MAP_ACTIVE;
-	s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
-	if (!(s->cap.features & SS_CAP_STATIC_MAP))
-	    release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
-	iounmap(s->cis_virt);
-	s->cis_mem.sys_start = 0;
-	s->cis_virt = NULL;
-    }
+	s->map_ops->cis_unmap(s);
 }
 
 /*
@@ -105,29 +98,13 @@ void release_cis_mem(socket_info_t *s)
 static unsigned char *
 set_cis_map(socket_info_t *s, unsigned int card_offset, unsigned int flags)
 {
-    pccard_mem_map *mem = &s->cis_mem;
-    if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
-	mem->sys_start == 0) {
-	int low = !(s->cap.features & SS_CAP_PAGE_REGS);
-	validate_mem(s);
-	mem->sys_start = 0;
-	if (find_mem_region(&mem->sys_start, s->cap.map_size,
-			    s->cap.map_size, low, "card services", s)) {
-	    printk(KERN_NOTICE "cs: unable to map card memory!\n");
-	    return NULL;
-	}
-	mem->sys_stop = mem->sys_start+s->cap.map_size-1;
-	s->cis_virt = ioremap(mem->sys_start, s->cap.map_size);
-    }
-    mem->card_start = card_offset;
-    mem->flags = flags;
-    s->ss_entry->set_mem_map(s->sock, mem);
-    if (s->cap.features & SS_CAP_STATIC_MAP) {
-	if (s->cis_virt)
-	    iounmap(s->cis_virt);
-	s->cis_virt = ioremap(mem->sys_start, s->cap.map_size);
-    }
-    return s->cis_virt;
+	void *ret;
+
+	ret = s->map_ops->cis_map(s, card_offset, flags);
+	if (!ret)
+		printk(KERN_ERR "cs: unable to map card memory!\n");
+
+	return s->cis_virt;
 }
 
 /*======================================================================
@@ -198,6 +175,7 @@ int read_cis_mem(socket_info_t *s, int a
 	    addr = 0;
 	}
     }
+    release_cis_mem(s);
     DEBUG(3, "cs:  %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
 	  *(u_char *)(ptr+0), *(u_char *)(ptr+1),
 	  *(u_char *)(ptr+2), *(u_char *)(ptr+3));
@@ -258,6 +236,7 @@ void write_cis_mem(socket_info_t *s, int
 	    addr = 0;
 	}
     }
+    release_cis_mem(s);
 }
 
 /*======================================================================
diff -puN drivers/pcmcia/cs.c~pcmcia-10 drivers/pcmcia/cs.c
--- 25/drivers/pcmcia/cs.c~pcmcia-10	Tue Mar 18 15:12:29 2003
+++ 25-akpm/drivers/pcmcia/cs.c	Tue Mar 18 15:12:29 2003
@@ -60,6 +60,7 @@
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include "cs_internal.h"
+#include "map.h"
 
 #ifdef CONFIG_PCI
 #define PCI_OPT " [pci]"
@@ -268,11 +269,6 @@ static int set_io_map(socket_info_t *s, 
 	return s->ss_entry->set_io_map(s->sock, io);
 }
 
-static int set_mem_map(socket_info_t *s, struct pccard_mem_map *mem)
-{
-	return s->ss_entry->set_mem_map(s->sock, mem);
-}
-
 static int suspend_socket(socket_info_t *s)
 {
 	s->socket = dead_socket;
@@ -360,6 +356,12 @@ int pcmcia_register_socket(struct device
 
 		init_socket(s);
 		s->ss_entry->inquire_socket(s->sock, &s->cap);
+
+		if (s->cap.features & SS_CAP_STATIC_MAP)
+			s->map_ops = &smap_ops;
+		else
+			s->map_ops = &winmap_ops;
+
 #ifdef CONFIG_PROC_FS
 		if (proc_pccard) {
 			char name[3];
@@ -416,7 +418,6 @@ void pcmcia_unregister_socket(struct dev
 #endif
 		
 		shutdown_socket(s);
-		release_cis_mem(s);
 		while (s->clients) {
 			client = s->clients;
 			s->clients = s->clients->next;
@@ -511,6 +512,8 @@ static void shutdown_socket(socket_info_
     }
     free_regions(&s->a_region);
     free_regions(&s->c_region);
+
+    s->map_ops->remove(s);
 } /* shutdown_socket */
 
 /*
@@ -620,6 +623,9 @@ static void unreset_socket(socket_info_t
 	    else
 		send_event(s, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
 	} else if (s->state & SOCKET_SETUP_PENDING) {
+	    int ret = s->map_ops->insert(s);
+	    if (ret)
+		printk(KERN_ERR "PCMCIA: insert failed: %d\n", ret);
 #ifdef CONFIG_CARDBUS
 	    if (s->state & SOCKET_CARDBUS) {
 		cb_alloc(s);
@@ -1190,8 +1196,8 @@ int pcmcia_get_window(window_handle_t *h
     if (w == MAX_WIN)
 	return CS_NO_MORE_ITEMS;
     win = &s->win[w];
-    req->Base = win->ctl.sys_start;
-    req->Size = win->ctl.sys_stop - win->ctl.sys_start + 1;
+    req->Base = win->ctl.res->start;
+    req->Size = win->ctl.res->end - win->ctl.res->start + 1;
     req->AccessSpeed = win->ctl.speed;
     req->Attributes = 0;
     if (win->ctl.flags & MAP_ATTRIB)
@@ -1338,10 +1344,13 @@ int pcmcia_map_mem_page(window_handle_t 
 	return CS_BAD_HANDLE;
     if (req->Page != 0)
 	return CS_BAD_PAGE;
+
     s = win->sock;
-    win->ctl.card_start = req->CardOffset;
-    if (set_mem_map(s, &win->ctl) != 0)
+
+    if (s->map_ops->mem_modify(s, &win->ctl, req->CardOffset,
+			       win->ctl.speed, win->ctl.flags))
 	return CS_BAD_OFFSET;
+
     return CS_SUCCESS;
 } /* map_mem_page */
 
@@ -1402,22 +1411,26 @@ int pcmcia_modify_configuration(client_h
 
 int pcmcia_modify_window(window_handle_t win, modwin_t *req)
 {
+    socket_info_t *s;
+    unsigned int flags;
+
     if ((win == NULL) || (win->magic != WINDOW_MAGIC))
 	return CS_BAD_HANDLE;
 
-    win->ctl.flags &= ~(MAP_ATTRIB|MAP_ACTIVE);
+    flags = win->ctl.flags & ~(MAP_ATTRIB|MAP_ACTIVE);
     if (req->Attributes & WIN_MEMORY_TYPE)
-	win->ctl.flags |= MAP_ATTRIB;
+	flags |= MAP_ATTRIB;
     if (req->Attributes & WIN_ENABLE)
-	win->ctl.flags |= MAP_ACTIVE;
+	flags |= MAP_ACTIVE;
     if (req->Attributes & WIN_DATA_WIDTH_16)
-	win->ctl.flags |= MAP_16BIT;
+	flags |= MAP_16BIT;
     if (req->Attributes & WIN_USE_WAIT)
-	win->ctl.flags |= MAP_USE_WAIT;
-    win->ctl.speed = req->AccessSpeed;
-    set_mem_map(win->sock, &win->ctl);
-    
-    return CS_SUCCESS;
+	flags |= MAP_USE_WAIT;
+
+    s = win->sock;
+
+    return s->map_ops->mem_modify(s, &win->ctl, win->ctl.card_start,
+				  req->AccessSpeed, flags);
 } /* modify_window */
 
 /*======================================================================
@@ -1639,12 +1652,10 @@ int pcmcia_release_window(window_handle_
 
     /* Shut down memory window */
     win->ctl.flags &= ~MAP_ACTIVE;
-    set_mem_map(s, &win->ctl);
-    s->state &= ~SOCKET_WIN_REQ(win->index);
 
-    /* Release system memory */
-    if(!(s->cap.features & SS_CAP_STATIC_MAP))
-	release_mem_region(win->base, win->size);
+    s->map_ops->mem_unmap(s, &win->ctl);
+
+    s->state &= ~SOCKET_WIN_REQ(win->index);
     win->handle->state &= ~CLIENT_WIN_REQ(win->index);
 
     win->magic = 0;
@@ -1929,8 +1940,7 @@ int pcmcia_request_window(client_handle_
 {
     socket_info_t *s;
     window_t *win;
-    u_long align;
-    int w;
+    int w, ret;
     
     if (CHECK_HANDLE(*handle))
 	return CS_BAD_HANDLE;
@@ -1943,16 +1953,8 @@ int pcmcia_request_window(client_handle_
     /* Window size defaults to smallest available */
     if (req->Size == 0)
 	req->Size = s->cap.map_size;
-    align = (((s->cap.features & SS_CAP_MEM_ALIGN) ||
-	      (req->Attributes & WIN_STRICT_ALIGN)) ?
-	     req->Size : s->cap.map_size);
     if (req->Size & (s->cap.map_size-1))
 	return CS_BAD_SIZE;
-    if ((req->Base && (s->cap.features & SS_CAP_STATIC_MAP)) ||
-	(req->Base & (align-1)))
-	return CS_BAD_BASE;
-    if (req->Base)
-	align = 0;
 
     /* Allocate system memory window */
     for (w = 0; w < MAX_WIN; w++)
@@ -1965,18 +1967,6 @@ int pcmcia_request_window(client_handle_
     win->index = w;
     win->handle = *handle;
     win->sock = s;
-    win->base = req->Base;
-    win->size = req->Size;
-
-    if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
-	find_mem_region(&win->base, win->size, align,
-			(req->Attributes & WIN_MAP_BELOW_1MB) ||
-			!(s->cap.features & SS_CAP_PAGE_REGS),
-			(*handle)->dev_info, s))
-	return CS_IN_USE;
-    (*handle)->state |= CLIENT_WIN_REQ(w);
-
-    /* Configure the socket controller */
     win->ctl.map = w+1;
     win->ctl.flags = 0;
     win->ctl.speed = req->AccessSpeed;
@@ -1988,18 +1978,19 @@ int pcmcia_request_window(client_handle_
 	win->ctl.flags |= MAP_16BIT;
     if (req->Attributes & WIN_USE_WAIT)
 	win->ctl.flags |= MAP_USE_WAIT;
-    win->ctl.sys_start = win->base;
-    win->ctl.sys_stop = win->base + win->size-1;
     win->ctl.card_start = 0;
-    if (set_mem_map(s, &win->ctl) != 0)
-	return CS_BAD_ARGS;
-    s->state |= SOCKET_WIN_REQ(w);
 
-    /* Return window handle */
-    req->Base = win->ctl.sys_start;
-    *wh = win;
+    ret = s->map_ops->mem_map(s, &win->ctl, req, (*handle)->dev_info);
+    if (ret == CS_SUCCESS) {
+	(*handle)->state |= CLIENT_WIN_REQ(w);
+	s->state |= SOCKET_WIN_REQ(w);
+
+	/* Return window handle */
+	req->Base = win->ctl.res->start;
+	*wh = win;
+    }
     
-    return CS_SUCCESS;
+    return ret;
 } /* request_window */
 
 /*======================================================================
diff -puN drivers/pcmcia/cs_internal.h~pcmcia-10 drivers/pcmcia/cs_internal.h
--- 25/drivers/pcmcia/cs_internal.h~pcmcia-10	Tue Mar 18 15:12:29 2003
+++ 25-akpm/drivers/pcmcia/cs_internal.h	Tue Mar 18 15:12:29 2003
@@ -75,8 +75,6 @@ typedef struct window_t {
     u_short		index;
     client_handle_t	handle;
     struct socket_info_t *sock;
-    u_long		base;
-    u_long		size;
     pccard_mem_map	ctl;
 } window_t;
 
@@ -118,9 +116,12 @@ typedef struct config_t {
 #define MAX_CIS_TABLE	64
 #define MAX_CIS_DATA	512
 
+struct map_operations;
+
 typedef struct socket_info_t {
     spinlock_t			lock;
     struct pccard_operations *	ss_entry;
+    struct map_operations	*map_ops;
     u_int			sock;
     socket_state_t		socket;
     socket_cap_t		cap;
@@ -207,7 +208,6 @@ int read_cis_mem(socket_info_t *s, int a
 		 u_int addr, u_int len, void *ptr);
 void write_cis_mem(socket_info_t *s, int attr,
 		   u_int addr, u_int len, void *ptr);
-void release_cis_mem(socket_info_t *s);
 int verify_cis_cache(socket_info_t *s);
 void preload_cis_cache(socket_info_t *s);
 int get_first_tuple(client_handle_t handle, tuple_t *tuple);
@@ -236,8 +236,8 @@ int copy_memory(memory_handle_t handle, 
 void validate_mem(socket_info_t *s);
 int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
 		   char *name, socket_info_t *s);
-int find_mem_region(u_long *base, u_long num, u_long align,
-		    int force_low, char *name, socket_info_t *s);
+struct resource *find_mem_region(u_long base, u_long num, u_long align,
+				 int low, char *name, socket_info_t *s);
 int try_irq(u_int Attributes, int irq, int specific);
 void undo_irq(u_int Attributes, int irq);
 int adjust_resource_info(client_handle_t handle, adjust_t *adj);
diff -puN drivers/pcmcia/Makefile~pcmcia-10 drivers/pcmcia/Makefile
--- 25/drivers/pcmcia/Makefile~pcmcia-10	Tue Mar 18 15:12:29 2003
+++ 25-akpm/drivers/pcmcia/Makefile	Tue Mar 18 15:12:29 2003
@@ -16,7 +16,7 @@ obj-$(CONFIG_PCMCIA_SA1111)		+= sa1111_c
 
 yenta_socket-objs				:= pci_socket.o yenta.o
 
-pcmcia_core-objs-y				:= cistpl.o rsrc_mgr.o bulkmem.o cs.o
+pcmcia_core-objs-y				:= cistpl.o rsrc_mgr.o bulkmem.o cs.o mapstatic.o mapwindow.o
 pcmcia_core-objs-$(CONFIG_CARDBUS)		+= cardbus.o
 pcmcia_core-objs				:= $(pcmcia_core-objs-y)
 
diff -puN /dev/null drivers/pcmcia/map.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/drivers/pcmcia/map.h	Tue Mar 18 15:12:29 2003
@@ -0,0 +1,20 @@
+
+struct socket_info_t;
+
+struct map_operations {
+	int	(*insert)(struct socket_info_t *);
+	void	(*remove)(struct socket_info_t *);
+
+	void	(*cis_unmap)(struct socket_info_t *);
+	void	*(*cis_map)(struct socket_info_t *, unsigned int, unsigned int);
+
+	void	(*mem_unmap)(struct socket_info_t *, pccard_mem_map *);
+	int	(*mem_map)(struct socket_info_t *, pccard_mem_map *,
+			   struct win_req_t *, char *);
+	int	(*mem_modify)(struct socket_info_t *, pccard_mem_map *,
+			      unsigned int, unsigned int, unsigned int);
+};
+
+extern struct map_operations smap_ops;
+extern struct map_operations winmap_ops;
+
diff -puN /dev/null drivers/pcmcia/mapstatic.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/drivers/pcmcia/mapstatic.c	Tue Mar 18 15:12:29 2003
@@ -0,0 +1,144 @@
+/*
+ * linux/drivers/pcmcia/mapstatic.c
+ *
+ * Handle static mapped sockets.  Things to note:
+ *
+ *  - the virtual address of a mapping can change when the card memory
+ *    offset / type changes.  Clients must not assume this is constant.
+ *    (normal usage seems to indicate a call to RequestWindow, followed
+ *    by a call to MapMemPage.  This can not work for static mapped
+ *    sockets, and requires all card drivers and cs.c to be fixed.)
+ *
+ *  - the current way we obtain the base address of a mapping is bogus
+ *    and needs to die - set_mem_map() offers a different interface
+ *    for statically mapped sockets to that for windowed sockets.
+ */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+
+#include <linux/timer.h>
+struct proc_dir_entry;
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+#include "map.h"
+
+static int smap_insert(struct socket_info_t *s)
+{
+	return 0;
+}
+
+static void smap_remove(struct socket_info_t *s)
+{
+}
+
+static void smap_cis_unmap(struct socket_info_t *s)
+{
+	pccard_mem_map *mem = &s->cis_mem;
+
+	mem->flags = 0;
+	mem->card_start = 0;
+
+	if (s->cis_virt)
+		iounmap(s->cis_virt);
+	if (s->cis_mem.res)
+		release_resource(s->cis_mem.res);
+
+	s->cis_virt = NULL;
+	s->cis_mem.res = NULL;
+}
+
+static void *
+smap_cis_map(struct socket_info_t *s, unsigned int card_offset, unsigned int flags)
+{
+	pccard_mem_map *mem = &s->cis_mem;
+
+	if (mem->card_start != card_offset || mem->flags != flags) {
+		smap_cis_unmap(s);
+
+		mem->flags = flags;
+		mem->sys_start = 0;
+		mem->sys_stop = s->cap.map_size - 1;
+		mem->card_start = card_offset;
+
+		s->ss_entry->set_mem_map(s->sock, mem);
+
+		mem->res = request_mem_region(mem->sys_start, s->cap.map_size,
+					      "card services");
+		if (mem->res)
+			s->cis_virt = ioremap(mem->res->start, s->cap.map_size);
+
+		if (!s->cis_virt)
+			smap_cis_unmap(s);
+	}
+
+	return s->cis_virt;
+}
+
+
+
+
+static void smap_mem_unmap(struct socket_info_t *s, pccard_mem_map *map)
+{
+	BUG_ON(!map->res);
+
+	release_resource(map->res);
+	map->res = NULL;
+}
+
+static int
+smap_mem_map(struct socket_info_t *s, pccard_mem_map *map, struct win_req_t *req, char *dev_info)
+{
+	BUG_ON(map->res);
+
+	if (req->Base != 0)
+		return CS_BAD_BASE;
+
+	map->sys_start = 0;
+	map->sys_stop = req->Size - 1;
+
+	if (s->ss_entry->set_mem_map(s->sock, map) != 0)
+		return CS_BAD_ARGS;
+
+	map->res = request_mem_region(map->sys_start, req->Size, dev_info);
+
+	return map->res ? CS_SUCCESS : CS_IN_USE;
+}
+
+static int
+smap_mem_modify(struct socket_info_t *s, pccard_mem_map *map,
+		unsigned int card_offset, unsigned int speed,
+		unsigned int flags)
+{
+	BUG_ON(!map->res);
+
+	if (map->card_start != card_offset)
+		return CS_BAD_OFFSET;
+
+	map->speed = speed;
+	map->flags = flags;
+
+	return s->ss_entry->set_mem_map(s->sock, map) ? CS_BAD_ARGS : 0;
+}
+
+
+
+struct map_operations smap_ops = {
+	.insert		= smap_insert,
+	.remove		= smap_remove,
+
+	.cis_unmap	= smap_cis_unmap,
+	.cis_map	= smap_cis_map,
+
+	.mem_unmap	= smap_mem_unmap,
+	.mem_map	= smap_mem_map,
+	.mem_modify	= smap_mem_modify,
+};
diff -puN /dev/null drivers/pcmcia/mapwindow.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/drivers/pcmcia/mapwindow.c	Tue Mar 18 15:12:29 2003
@@ -0,0 +1,181 @@
+/*
+ * linux/drivers/pcmcia/mapwindow.c
+ *
+ * Handle window mapped sockets.  Things to note:
+ *
+ *  - validate_mem() will call winmap_cis_map and winmap_cis_unmap
+ *    during it's probe for usable memory.
+ */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+
+#include <asm/io.h>
+
+#include <linux/timer.h>
+struct proc_dir_entry;
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+#include "map.h"
+
+/*
+ * A card was inserted.  Find a memory resource for the CIS, claim it,
+ * and setup a mapping.
+ */
+static int winmap_insert(struct socket_info_t *s)
+{
+	BUG_ON(s->cis_mem.res);
+	BUG_ON(s->cis_virt);
+
+	if (!(s->cap.features & SS_CAP_CARDBUS))
+		validate_mem(s);
+
+	s->cis_mem.res = find_mem_region(0, s->cap.map_size, s->cap.map_size,
+					 0, "card services", s);
+
+	if (!s->cis_mem.res)
+		return -EBUSY;
+
+	s->cis_virt = ioremap(s->cis_mem.res->start, s->cap.map_size);
+	if (!s->cis_virt) {
+		release_resource(s->cis_mem.res);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*
+ * The card was removed.  Release resources claimed by winmap_insert().
+ */
+static void winmap_remove(struct socket_info_t *s)
+{
+	if (s->cis_virt)
+		iounmap(s->cis_virt);
+	if (s->cis_mem.res)
+		release_resource(s->cis_mem.res);
+
+	s->cis_virt = NULL;
+	s->cis_mem.res = NULL;
+}
+
+/*
+ * Unmap a CIS mapping.  Note that the resource and ioremap of
+ * the region remains in place since winmap_cis_map() did not
+ * setup this mapping.
+ */
+static void winmap_cis_unmap(struct socket_info_t *s)
+{
+	pccard_mem_map *mem = &s->cis_mem;
+
+	if (mem->flags & MAP_ACTIVE) {
+		mem->flags &= ~MAP_ACTIVE;
+		s->ss_entry->set_mem_map(s->sock, mem);
+	}
+}
+
+/*
+ * Map card memory at card_offset in the memory region defined
+ * by "flags" into memory, returning the virtual address of this
+ * mapping.  We may be altering a pre-existing mapping.
+ */
+static void *
+winmap_cis_map(struct socket_info_t *s, unsigned int card_offset, unsigned int flags)
+{
+	pccard_mem_map *mem = &s->cis_mem;
+
+	if (s->cis_virt &&
+	    (mem->card_start != card_offset || mem->flags != flags)) {
+		mem->flags = flags;
+		mem->sys_start = mem->res->start;
+		mem->sys_stop = mem->res->start + s->cap.map_size - 1;
+		mem->card_start = card_offset;
+
+		s->ss_entry->set_mem_map(s->sock, mem);
+	}
+
+	return s->cis_virt;
+}
+
+
+
+
+static void winmap_mem_unmap(struct socket_info_t *s, pccard_mem_map *map)
+{
+	BUG_ON(!map->res);
+
+	s->ss_entry->set_mem_map(s->sock, map);
+
+	release_resource(map->res);
+	map->res = NULL;
+}
+
+static int
+winmap_mem_map(struct socket_info_t *s, pccard_mem_map *map, struct win_req_t *req, char *dev_info)
+{
+	unsigned long align;
+
+	BUG_ON(map->res);
+
+	align = s->cap.map_size;
+	if ((s->cap.features & SS_CAP_MEM_ALIGN) ||
+	    (req->Attributes & WIN_STRICT_ALIGN))
+		align = req->Size;
+
+	if (req->Base & (align-1))
+		return CS_BAD_BASE;
+	if (req->Base)
+		align = 0;
+
+	map->res = find_mem_region(req->Base, req->Size, align,
+				   req->Attributes & WIN_MAP_BELOW_1MB,
+				   dev_info, s);
+	if (!map->res)
+		return CS_IN_USE;
+
+	map->sys_start = map->res->start;
+	map->sys_stop = map->res->end;
+
+	if (s->ss_entry->set_mem_map(s->sock, map) != 0) {
+		release_resource(map->res);
+		map->res = NULL;
+		return CS_BAD_ARGS;
+	}
+
+	return CS_SUCCESS;
+}
+
+static int
+winmap_mem_modify(struct socket_info_t *s, pccard_mem_map *map,
+		  unsigned int card_offset, unsigned int speed,
+		  unsigned int flags)
+{
+	BUG_ON(!map->res);
+
+	map->card_start = card_offset;
+	map->speed = speed;
+	map->flags = flags;
+
+	return s->ss_entry->set_mem_map(s->sock, map) ? CS_BAD_ARGS : 0;
+}
+
+
+
+struct map_operations winmap_ops = {
+	.insert		= winmap_insert,
+	.remove		= winmap_remove,
+
+	.cis_unmap	= winmap_cis_unmap,
+	.cis_map	= winmap_cis_map,
+
+	.mem_unmap	= winmap_mem_unmap,
+	.mem_map	= winmap_mem_map,
+	.mem_modify	= winmap_mem_modify,
+};
diff -puN drivers/pcmcia/rsrc_mgr.c~pcmcia-10 drivers/pcmcia/rsrc_mgr.c
--- 25/drivers/pcmcia/rsrc_mgr.c~pcmcia-10	Tue Mar 18 15:12:29 2003
+++ 25-akpm/drivers/pcmcia/rsrc_mgr.c	Tue Mar 18 15:12:29 2003
@@ -54,6 +54,7 @@
 #include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
+#include "map.h"
 
 /*====================================================================*/
 
@@ -142,22 +143,6 @@ static inline int check_io_resource(unsi
 	return 0;
 }
 
-/* FIXME: Fundamentally racy. */
-static inline int check_mem_resource(unsigned long b, unsigned long n,
-				     struct pci_dev *dev)
-{
-	struct resource *region;
-
-	region = __request_region(resource_parent(b, n, IORESOURCE_MEM, dev),
-				  b, n, "check_mem_resource");
-	if (!region)
-		return -EBUSY;
-
-	release_resource(region);
-	kfree(region);
-	return 0;
-}
-
 static struct resource *make_resource(unsigned long b, unsigned long n,
 				      int flags, char *name)
 {
@@ -188,7 +173,7 @@ static int request_io_resource(unsigned 
 	return err;
 }
 
-static int request_mem_resource(unsigned long b, unsigned long n,
+static struct resource *request_mem_resource(unsigned long b, unsigned long n,
 				char *name, struct pci_dev *dev)
 {
 	struct resource *res = make_resource(b, n, IORESOURCE_MEM, name);
@@ -197,10 +182,12 @@ static int request_mem_resource(unsigned
 
 	if (res) {
 		err = request_resource(pr, res);
-		if (err)
+		if (err) {
 			kfree(res);
+			res = NULL;
+		}
 	}
-	return err;
+	return res;
 }
 
 /*======================================================================
@@ -343,52 +330,103 @@ static void do_io_probe(ioaddr_t base, i
 ======================================================================*/
 
 /* Validation function for cards with a valid CIS */
-static int cis_readable(socket_info_t *s, u_long base)
+static int readable(socket_info_t *s, struct resource *res, cisinfo_t *info)
 {
-    cisinfo_t info1, info2;
-    int ret;
-    s->cis_mem.sys_start = base;
-    s->cis_mem.sys_stop = base+s->cap.map_size-1;
-    s->cis_virt = ioremap(base, s->cap.map_size);
-    ret = pcmcia_validate_cis(s->clients, &info1);
-    /* invalidate mapping and CIS cache */
-    iounmap(s->cis_virt);
-    s->cis_used = 0;
-    if ((ret != 0) || (info1.Chains == 0))
-	return 0;
-    s->cis_mem.sys_start = base+s->cap.map_size;
-    s->cis_mem.sys_stop = base+2*s->cap.map_size-1;
-    s->cis_virt = ioremap(base+s->cap.map_size, s->cap.map_size);
-    ret = pcmcia_validate_cis(s->clients, &info2);
-    iounmap(s->cis_virt);
-    s->cis_used = 0;
-    return ((ret == 0) && (info1.Chains == info2.Chains));
+	/* this can not work for now. */
+	int ret = -1;
+
+	s->cis_mem.res = res;
+	s->cis_virt = ioremap(res->start, s->cap.map_size);
+	if (s->cis_virt) {
+		ret = pcmcia_validate_cis(s->clients, info);
+		/* invalidate mapping and CIS cache */
+		iounmap(s->cis_virt);
+		s->cis_virt = NULL;
+		s->cis_mem.res = NULL;
+		s->cis_used = 0;
+	}
+	if ((ret != 0) || (info->Chains == 0))
+		return 0;
+	return 1;
 }
 
 /* Validation function for simple memory cards */
-static int checksum(socket_info_t *s, u_long base)
+static int checksum(socket_info_t *s, struct resource *res)
 {
-    int i, a, b, d;
-    s->cis_mem.sys_start = base;
-    s->cis_mem.sys_stop = base+s->cap.map_size-1;
-    s->cis_virt = ioremap(base, s->cap.map_size);
-    s->cis_mem.card_start = 0;
-    s->cis_mem.flags = MAP_ACTIVE;
-    s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
-    /* Don't bother checking every word... */
-    a = 0; b = -1;
-    for (i = 0; i < s->cap.map_size; i += 44) {
-	d = readl(s->cis_virt+i);
-	a += d; b &= d;
-    }
-    iounmap(s->cis_virt);
-    return (b == -1) ? -1 : (a>>1);
+	pccard_mem_map map;
+	int i, a = 0, b = -1, d;
+	void *virt;
+
+	virt = ioremap(res->start, s->cap.map_size);
+	if (virt) {
+		map.map = 0;
+		map.flags = MAP_ACTIVE;
+		map.speed = 0;
+		map.res = res;
+		map.sys_start = res->start;
+		map.sys_stop = res->end;
+		map.card_start = 0;
+		s->ss_entry->set_mem_map(s->sock, &map);
+
+		/* Don't bother checking every word... */
+		for (i = 0; i < s->cap.map_size; i += 44) {
+			d = readl(virt+i);
+			a += d;
+			b &= d;
+		}
+
+		map.flags = 0;
+		s->ss_entry->set_mem_map(s->sock, &map);
+
+		iounmap(virt);
+	}
+
+	return (b == -1) ? -1 : (a>>1);
 }
 
-static int checksum_match(socket_info_t *s, u_long base)
+static int
+cis_readable(socket_info_t *s, unsigned long base, unsigned long size)
 {
-    int a = checksum(s, base), b = checksum(s, base+s->cap.map_size);
-    return ((a == b) && (a >= 0));
+	struct resource *res1, *res2;
+	cisinfo_t info1, info2;
+	int ret = 0;
+
+	res1 = request_mem_region(base, size/2, "cs memory probe");
+	res2 = request_mem_region(base + size/2, size/2, "cs memory probe");
+
+	if (res1 && res2) {
+		ret = readable(s, res1, &info1);
+		ret += readable(s, res2, &info2);
+	}
+
+	if (res2)
+		release_resource(res2);
+	if (res1)
+		release_resource(res1);
+
+	return ((ret == 2) && (info1.Chains == info2.Chains));
+}
+
+static int
+checksum_match(struct socket_info_t *s, unsigned long base, unsigned long size)
+{
+	struct resource *res1, *res2;
+	int a = -1, b = -1;
+
+	res1 = request_mem_region(base, size/2, "cs memory probe");
+	res2 = request_mem_region(base + size/2, size/2, "cs memory probe");
+
+	if (res1 && res2) {
+		a = checksum(s, res1);
+		b = checksum(s, res2);
+	}
+
+	if (res2)
+		release_resource(res2);
+	if (res1)
+		release_resource(res1);
+
+	return ((a == b) && (a >= 0));
 }
 
 /*======================================================================
@@ -412,16 +450,16 @@ static int do_mem_probe(u_long base, u_l
 	step = 2 * s->cap.map_size;
     for (i = j = base; i < base+num; i = j + step) {
 	if (!fail) {	
-	    for (j = i; j < base+num; j += step)
-		if ((check_mem_resource(j, step, s->cap.cb_dev) == 0) &&
-		    cis_readable(s, j))
+	    for (j = i; j < base+num; j += step) {
+		if (cis_readable(s, j, step))
 		    break;
+	    }
 	    fail = ((i == base) && (j == base+num));
 	}
 	if (fail) {
 	    for (j = i; j < base+num; j += 2*step)
-		if ((check_mem_resource(j, 2*step, s->cap.cb_dev) == 0) &&
-		    checksum_match(s, j) && checksum_match(s, j + step))
+		if (checksum_match(s, j, step) &&
+		    checksum_match(s, j + step, step))
 		    break;
 	}
 	if (i != j) {
@@ -555,12 +593,16 @@ int find_io_region(ioaddr_t *base, ioadd
     return ret;
 }
 
-int find_mem_region(u_long *base, u_long num, u_long align,
-		    int force_low, char *name, socket_info_t *s)
+struct resource *
+find_mem_region(u_long base, u_long num, u_long align, int low, char *name,
+		socket_info_t *s)
 {
+    struct resource *res = NULL;
     u_long try;
     resource_map_t *m;
-    int ret = -1;
+    int force_low;
+
+    force_low = low || !(s->cap.features & SS_CAP_PAGE_REGS);
 
     down(&rsrc_sem);
     while (1) {
@@ -569,15 +611,13 @@ int find_mem_region(u_long *base, u_long
 	    if ((force_low != 0) ^ (m->base < 0x100000))
 		continue;
 
-	    try = (m->base & ~(align-1)) + *base;
+	    try = (m->base & ~(align-1)) + base;
 	    for (try = (try >= m->base) ? try : try+align;
 		 (try >= m->base) && (try+num <= m->base+m->num);
 		 try += align) {
-		if (request_mem_resource(try, num, name, s->cap.cb_dev) == 0) {
-		    *base = try;
-		    ret = 0;
+		res = request_mem_resource(try, num, name, s->cap.cb_dev);
+		if (res)
 		    goto out;
-		}
 		if (!align)
 		    break;
 	    }
@@ -588,7 +628,7 @@ int find_mem_region(u_long *base, u_long
     }
  out:
     up(&rsrc_sem);
-    return ret;
+    return res;
 }
 
 /*======================================================================
@@ -744,7 +784,10 @@ static int adjust_memory(adjust_t *adj)
 	ret = sub_interval(&mem_db, base, num);
 	if (ret == CS_SUCCESS) {
 	    for (i = 0; i < sockets; i++) {
-		release_cis_mem(socket_table[i]);
+		if (socket_table[i]->cis_virt) {
+		    socket_table[i]->map_ops->remove(socket_table[i]);
+		    socket_table[i]->map_ops->insert(socket_table[i]);
+		}
 #ifdef CONFIG_CARDBUS
 		cb_release_cis_mem(socket_table[i]);
 #endif
diff -puN include/pcmcia/ss.h~pcmcia-10 include/pcmcia/ss.h
--- 25/include/pcmcia/ss.h~pcmcia-10	Tue Mar 18 15:12:29 2003
+++ 25-akpm/include/pcmcia/ss.h	Tue Mar 18 15:12:29 2003
@@ -111,6 +111,7 @@ typedef struct pccard_mem_map {
     u_char	map;
     u_char	flags;
     u_short	speed;
+    struct resource *res;
     u_long	sys_start, sys_stop;
     u_int	card_start;
 } pccard_mem_map;

_