diff -Naur -X exclude-files ac_cur/arch/um/include/mem_user.h ac/arch/um/include/mem_user.h
--- ac_cur/arch/um/include/mem_user.h	Wed Dec 31 19:00:00 1969
+++ ac/arch/um/include/mem_user.h	Sun Jul 15 21:44:24 2001
@@ -0,0 +1,55 @@
+/*
+ * arch/um/include/mem_user.h
+ *
+ * BRIEF MODULE DESCRIPTION
+ * user side memory interface for support IO memory inside user mode linux
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ *         Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MEM_USER_H
+#define _MEM_USER_H
+
+extern int create_mem_file(unsigned long len);
+extern void setup_range(int fd, char *driver, unsigned long start,
+			unsigned long usable, unsigned long total);
+extern void map(unsigned long virt, void *p, unsigned long len, int r,
+		int w, int x);
+extern void parse_iomem(char *str);
+extern void setup_memory(void);
+extern unsigned long find_iomem(char *driver, unsigned long *len_out);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Naur -X exclude-files ac_cur/arch/um/include/user_util.h ac/arch/um/include/user_util.h
--- ac_cur/arch/um/include/user_util.h	Sun Jul 15 21:54:27 2001
+++ ac/arch/um/include/user_util.h	Sun Jul 15 21:44:24 2001
@@ -30,7 +30,6 @@
 
 extern struct cpu_task cpu_tasks[];
 
-extern int physmem_fd;
 extern int brk_fd;
 
 extern unsigned long low_physmem;
@@ -42,8 +41,6 @@
 extern void *last_brk;
 extern void *brk_start;
 
-extern int physmem_inode;
-
 extern int tracing_pid;
 
 extern char host_info[];
@@ -65,9 +62,6 @@
 extern void stack_protections(unsigned long address, int len);
 extern void abandon_proc_space(int (*proc)(void *), unsigned long sp);
 extern int signals(int (*init_proc)(void *), void *sp);
-extern unsigned long setup_memory(unsigned long total_size,
-				  unsigned long physmem_size, int *fd_out,
-				  int *inode_out);
 extern void map(unsigned long virt, void *p, unsigned long len, 
 		int r, int w, int x);
 extern int unmap(unsigned long address, unsigned long len);
@@ -122,7 +116,6 @@
 extern int raw(int fd, int complain);
 extern void cooked(int fd);
 extern int switcheroo(int fd, int prot, void *from, void *to, int size);
-extern int create_vm_file(unsigned long len);
 extern void *update_brk(void);
 extern void check_brk(void *process_brk);
 extern void idle_sleep(int secs);
diff -Naur -X exclude-files ac_cur/arch/um/kernel/Makefile ac/arch/um/kernel/Makefile
--- ac_cur/arch/um/kernel/Makefile	Sun Jul 15 21:54:27 2001
+++ ac/arch/um/kernel/Makefile	Sun Jul 15 21:44:24 2001
@@ -1,9 +1,9 @@
 OBJ = um.o
 
 OBJS = process.o current.o exec_kern.o exec_user.o init_task.o irq.o \
-	irq_user.o mem.o ptrace.o reboot.o resource.o \
-	setup.o signal_user.o smp.o syscall_kern.o \
-	syscall_user.o sys_call_table.o time.o time_kern.o tlb.o trap_kern.o \
+	irq_user.o mem.o mem_user.o ptrace.o reboot.o resource.o \
+	setup.o signal_user.o smp.o syscall_kern.o syscall_user.o \
+	sys_call_table.o time.o time_kern.o tlb.o trap_kern.o \
 	trap_user.o um_arch.o user_util.o uaccess_user.o
 
 OX_OBJS = ksyms.o process_kern.o signal_kern.o user_syms.o
@@ -32,25 +32,28 @@
 exec_user.o: exec_user.c
 	$(CC) $(USER_CFLAGS) -c -o $@ $<
 
-process.o: process.c
+irq_user.o: irq_user.c
 	$(CC) $(USER_CFLAGS) -c -o $@ $<
 
-syscall_user.o: syscall_user.c
+mem_user.o: mem_user.c
 	$(CC) $(USER_CFLAGS) -c -o $@ $<
 
-trap_user.o: trap_user.c
+process.o: process.c
 	$(CC) $(USER_CFLAGS) -c -o $@ $<
 
 signal_user.o: signal_user.c
 	$(CC) $(USER_CFLAGS) -c -o $@ $<
 
+syscall_user.o: syscall_user.c
+	$(CC) $(USER_CFLAGS) -c -o $@ $<
+
 time.o: time.c
 	$(CC) $(USER_CFLAGS) -c -o $@ $<
 
-user_util.o: user_util.c
+trap_user.o: trap_user.c
 	$(CC) $(USER_CFLAGS) -c -o $@ $<
 
-irq_user.o: irq_user.c
+user_util.o: user_util.c
 	$(CC) $(USER_CFLAGS) -c -o $@ $<
 
 uaccess.o: uaccess_user.c
diff -Naur -X exclude-files ac_cur/arch/um/kernel/mem_user.c ac/arch/um/kernel/mem_user.c
--- ac_cur/arch/um/kernel/mem_user.c	Wed Dec 31 19:00:00 1969
+++ ac/arch/um/kernel/mem_user.c	Sun Jul 15 21:44:24 2001
@@ -0,0 +1,212 @@
+/*
+ * arch/um/kernel/mem_user.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ * user side memory routines for supporting IO memory inside user mode linux
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ *         Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include "kern_util.h"
+#include "user.h"
+
+struct mem_region {
+	struct mem_region *next;
+	char *driver;
+	unsigned long start;
+	unsigned long usable;
+	unsigned long total;
+	int fd;
+};
+
+struct mem_region physmem_region;
+
+struct mem_region *mem_list = &physmem_region;
+
+int create_mem_file(unsigned long len)
+{
+	char tempname[sizeof("/tmp/vm_file-XXXXXX\0")];
+	int fd;
+	char zero;
+
+	strcpy(tempname, "/tmp/vm_file-XXXXXX");
+	if((fd = mkstemp(tempname)) < 0){
+		perror("open - cannot create /tmp/vm_file-XXXXXX");
+		exit(1);
+	}
+	if(unlink(tempname) < 0){
+		perror("unlink");
+		exit(1);
+	}
+	if (fchmod(fd, 0777) < 0){
+		perror("fchmod");
+		exit(1);
+	}
+	if(lseek(fd, len, SEEK_SET) < 0){
+		perror("lseek");
+		exit(1);
+	}
+	zero = 0;
+	if(write(fd, &zero, 1) != 1){
+		perror("write");
+		exit(1);
+	}
+	return(fd);
+}
+
+void setup_range(int fd, char *driver, unsigned long start, 
+		 unsigned long usable, unsigned long total)
+{
+	struct mem_region *region, *next;
+
+	if(fd == -1){
+		fd = create_mem_file(usable);
+		region = &physmem_region;
+		next = physmem_region.next;
+	}
+	else {
+		region = malloc(sizeof(*region));
+		if(region == NULL){
+			perror("Allocating iomem struct");
+			exit(1);
+		}
+		next = physmem_region.next;
+	}
+	*region = ((struct mem_region) { next, driver, start, usable, 
+					 total, fd } );
+	if(region != &physmem_region) physmem_region.next = region;
+}
+
+void setup_memory(void)
+{
+	struct mem_region *region;
+	void *loc;
+	unsigned long start;
+	int page;
+
+	start = -1;
+	region = mem_list;
+	page = page_size();
+	while(region){
+		if(region->start != -1) start = region->start;
+		else region->start = start;
+		loc = mmap((void *) region->start, region->usable,
+			   PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
+			   region->fd, 0);
+		if(loc != (void *) region->start){
+			perror("Mapping memory");
+			exit(1);
+		}
+		start += region->total;
+		start = (start + page - 1) & ~(page - 1);
+		region = region->next;
+	}
+}
+
+void parse_iomem(char *str)
+{
+	struct stat buf;
+	char *file, *driver;
+	int fd;
+
+	driver = str;
+	file = strchr(str,',');
+	if(file == NULL){
+		printk(__FUNCTION__ " failed to parse iomem\n");
+		return;
+	}
+	*file = '\0';
+	file++;
+	fd = open(file, O_RDWR);
+	if(fd < 0){
+		perror("Couldn't open io file");
+		return;
+	}
+	if(fstat(fd, &buf) < 0) {
+		perror(__FUNCTION__ "fstat - cannot fstat file");
+		exit(1);
+	}
+	setup_range(fd, driver, -1, buf.st_size, buf.st_size);
+}
+
+void map(unsigned long virt, void *p, unsigned long len, int r,
+	 int w, int x)
+{
+	struct mem_region *region;
+	unsigned long phys = (unsigned long) p;
+	void *loc;
+	int prot;
+
+	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
+		(x ? PROT_EXEC : 0);
+	for(region = mem_list; region ; region = region->next) {
+		if((phys < region->start) || 
+		   (phys >= region->start + region->usable))
+			continue;
+		phys -= region->start;
+		loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, 
+			   region->fd, phys);
+		if(loc != (void *) virt){
+			panic("Error mapping a page - errno = %d", errno);
+		}
+		return;
+	}
+	panic("No physical or IO memory region for address 0x%x\n", phys);
+}
+
+unsigned long find_iomem(char *driver, unsigned long *len_out)
+{
+	struct mem_region *region;
+
+	for(region = mem_list; region ; region = region->next) {
+		if(!strcmp(region->driver, driver)) {
+			*len_out = region->usable;
+			return(region->start);
+		}
+	}
+	*len_out = 0;
+	return 0;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Naur -X exclude-files ac_cur/arch/um/kernel/um_arch.c ac/arch/um/kernel/um_arch.c
--- ac_cur/arch/um/kernel/um_arch.c	Sun Jul 15 21:56:00 2001
+++ ac/arch/um/kernel/um_arch.c	Sun Jul 15 21:53:25 2001
@@ -27,6 +27,7 @@
 #include "kern_util.h"
 #include "kern.h"
 #include "mprot.h"
+#include "mem_user.h"
 
 unsigned long _stext;
 
@@ -81,14 +82,12 @@
 #define XSTRING(s) #s
 #define STRING(s) XSTRING(s)
 
-int physmem_fd = -1;
-
 extern unsigned long high_physmem;
 
-unsigned long physmem;
+unsigned long physmem = 0x50000000 + NESTING * 0x10000000;
+
 unsigned long start_vm;
 unsigned long end_vm;
-int physmem_inode;
 
 int ncpus = 1;
 
@@ -202,7 +201,7 @@
 	brk_start = sbrk(0);
 	remap_data(ROUND_DOWN(&__bss_start), ROUND_UP(brk_start));
 	last_brk = (void *) brk_start;
-	brk_fd = create_vm_file(0);
+	brk_fd = create_mem_file(0);
 #ifdef CONFIG_GPROF
 	remap_profiling_buffers();
 #endif
@@ -266,8 +265,9 @@
   
 	add_process_vmas();
 	unblock_shlib_mem();
-	physmem = setup_memory(physmem_size + VMALLOC_OFFSET + virtmem_size,
-			       physmem_size, &physmem_fd, &physmem_inode);
+	setup_range(-1, NULL, physmem, physmem_size, 
+		    physmem_size + VMALLOC_OFFSET + virtmem_size);
+	setup_memory();
 	high_physmem = physmem + physmem_size;
 	start_vm = physmem + physmem_size + VMALLOC_OFFSET;
 	end_vm = start_vm + virtmem_size;
diff -Naur -X exclude-files ac_cur/arch/um/kernel/user_syms.c ac/arch/um/kernel/user_syms.c
--- ac_cur/arch/um/kernel/user_syms.c	Sun Jul 15 21:56:00 2001
+++ ac/arch/um/kernel/user_syms.c	Sun Jul 15 21:44:24 2001
@@ -8,6 +8,7 @@
 #include <sys/stat.h>
 #include <sys/vfs.h>
 #include "user_util.h"
+#include "mem_user.h"
 
 /* XXX All the __CONFIG_* stuff is broken because this file can't include
  * config.h
@@ -97,3 +98,5 @@
 
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(getuid);
+
+EXPORT_SYMBOL(find_iomem);
diff -Naur -X exclude-files ac_cur/arch/um/kernel/user_util.c ac/arch/um/kernel/user_util.c
--- ac_cur/arch/um/kernel/user_util.c	Sun Jul 15 21:56:00 2001
+++ ac/arch/um/kernel/user_util.c	Sun Jul 15 21:44:24 2001
@@ -24,6 +24,7 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
+#include "mem_user.h"
 
 #define COMMAND_LINE_SIZE _POSIX_ARG_MAX
 
@@ -83,39 +84,6 @@
 	fclose(maps);
 }
 
-int create_vm_file(unsigned long len)
-{
-	char tempname[32];
-	int fd;
-	char zero;
-
-	strcpy(tempname, "/tmp/vm_file-XXXXXX");
-	if ((fd = mkstemp(tempname)) < 0) {
-		perror("open - cannot create /tmp/vm_file-XXXXXX");
-		exit(1);
-	}
-	if(unlink(tempname) < 0){
-		perror("unlink");
-		exit(1);
-	}
-	if (fchmod(fd, 0777) < 0){
-		perror("fchmod");
-		exit(1);
-	}
-	if(len > 0){
-		if(lseek(fd, len, SEEK_SET) < 0){
-			perror("lseek");
-			exit(1);
-		}
-		zero = 0;
-		if(write(fd, &zero, 1) != 1){
-			perror("write");
-			exit(1);
-		}
-	}
-	return(fd);
-}
-
 void remap_data(void *segment_start, void *segment_end)
 {
 	void *addr;
@@ -131,7 +99,7 @@
 			prot = PROT_READ | PROT_WRITE | PROT_EXEC;
 			size = (unsigned long) segment_end - 
 				(unsigned long) segment_start;
-			data = create_vm_file(size);
+			data = create_mem_file(size);
 			if((addr = mmap(NULL, size, PROT_WRITE | PROT_READ, 
 					MAP_SHARED, data, 0)) < 0){
 				perror("mapping new data segment");
@@ -207,53 +175,6 @@
 void stack_protections(unsigned long address, int len)
 {
 	mprotect((void *) address, len, PROT_READ | PROT_WRITE | PROT_EXEC);
-}
-
-static unsigned long physmem_start = 0x50000000 + NESTING * 0x10000000;
-
-unsigned long setup_memory(unsigned long total_size, 
-			   unsigned long physmem_size, int *fd_out,
-			   int *inode_out)
-{
-	void *mem;
-	struct stat buf;
-
-	mem = mmap((void *) physmem_start, total_size, PROT_NONE, 
-		   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-	if(mem < 0){
-		perror("Mapping all of memory");
-		exit(1);
-	}
-	munmap(mem, total_size);
-	*fd_out = create_vm_file(physmem_size);
-	if(mmap(mem, physmem_size, PROT_READ | PROT_WRITE, 
-		MAP_SHARED | MAP_FIXED, *fd_out, 0) != mem){
-		perror("Mapping physical memory");
-		exit(1);
-	}
-	if(fstat(*fd_out, &buf) < 0){
-		perror("Stat-ing phymem_fd");
-		exit(1);
-	}
-	*inode_out = buf.st_ino;
-	return((unsigned long) mem);
-}
-
-void map(unsigned long virt, void *p, unsigned long len, int r,
-	 int w, int x)
-{
-	unsigned long phys = (unsigned long) p;
-	int prot;
-
-	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
-		(x ? PROT_EXEC : 0);
-	if((phys < physmem) || (phys > high_physmem))
-		panic("map : physmem out of range");
-	phys -= physmem;
-	if(mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, physmem_fd,
-		phys) != (void *) virt){
-		panic("Error mapping a page - errno = %d", errno);
-	}
 }
 
 void protect(unsigned long addr, unsigned long len, int r, int w, int x)
diff -Naur -X exclude-files ac_cur/arch/um/kernel/um_arch.c ac/arch/um/kernel/um_arch.c
--- ac_cur/arch/um/kernel/um_arch.c	Sun Jul 15 21:53:25 2001
+++ ac/arch/um/kernel/um_arch.c	Sun Jul 15 22:03:32 2001
@@ -243,6 +243,9 @@
 		else if(!strncmp(argv[i], "umid=", strlen("umid="))){
 			create_pid_file(&argv[i][strlen("umid=")]);
 		}
+		else if(!strncmp(argv[i], "iomem=",strlen("iomem="))){
+			parse_iomem(&argv[i][strlen("iomem=")]);
+		} 
 		else if(!strcmp(argv[i], "--version")){
                         printf("%s\n", system_utsname.release);
 			exit(0);