The patch should apply against either 2.2.* or 2.3.*.
-- Dave
--- linux/kernel/resource.c.O Thu Nov 12 09:58:32 1998
+++ linux/kernel/resource.c Fri Jun 18 09:12:50 1999
@@ -1,10 +1,17 @@
/*
* linux/kernel/resource.c
*
- * Copyright (C) 1995 Linus Torvalds
- * David Hinds
+ * Copyright (C) 1995, 1999 Linus Torvalds
+ * David Hinds
*
- * Kernel io-region resource management
+ * Kernel resource management
+ *
+ * We now distinguish between claiming space for devices (using the
+ * 'occupy' and 'vacate' calls), and associating a resource with a
+ * device driver (with the 'request', 'release', and 'check' calls).
+ * A resource can be claimed even if there is no associated driver
+ * (by occupying with name=NULL). Vacating a resource makes it
+ * available for other dynamically configured devices.
*/
#include <linux/sched.h>
@@ -12,47 +19,59 @@
#include <linux/ioport.h>
#include <linux/init.h>
-#define IOTABLE_SIZE 128
+#define RSRC_TABLE_SIZE 128
-typedef struct resource_entry_t {
+struct resource_entry {
u_long from, num;
const char *name;
- struct resource_entry_t *next;
-} resource_entry_t;
+ struct resource_entry *next;
+};
-static resource_entry_t iolist = { 0, 0, "", NULL };
+struct resource_entry res_list[] = {
+ { 0, 0, NULL, NULL }, /* IO */
+ { 0, 0, NULL, NULL } /* mem */
+};
-static resource_entry_t iotable[IOTABLE_SIZE];
+static struct resource_entry rsrc_table[RSRC_TABLE_SIZE];
/*
- * This generates the report for /proc/ioports
+ * This generates reports for /proc/ioports and /proc/memory
*/
-int get_ioport_list(char *buf)
+int get_resource_list(int class, char *buf)
{
- resource_entry_t *p;
+ struct resource_entry *root = &res_list[class];
+ struct resource_entry *p;
int len = 0;
-
- for (p = iolist.next; (p) && (len < 4000); p = p->next)
- len += sprintf(buf+len, "%04lx-%04lx : %s\n",
- p->from, p->from+p->num-1, p->name);
+ char *fmt = (class == RES_IO) ?
+ "%04lx-%04lx : %s\n" : "%08lx-%08lx : %s\n";
+
+ for (p = root->next; (p) && (len < 4000); p = p->next)
+ len += sprintf(buf+len, fmt, p->from, p->from+p->num-1,
+ (p->name ? p->name : "occupied"));
if (p)
len += sprintf(buf+len, "4K limit reached!\n");
return len;
}
/*
- * The workhorse function: find where to put a new entry
+ * Basics: find a matching resource entry, or find an insertion point
*/
-static resource_entry_t *find_gap(resource_entry_t *root,
- u_long from, u_long num)
+static struct resource_entry *
+find_match(struct resource_entry *root, u_long from, u_long num)
{
- unsigned long flags;
- resource_entry_t *p;
-
+ struct resource_entry *p;
+ for (p = root; p; p = p->next)
+ if ((p->from == from) && (p->num == num))
+ return p;
+ return NULL;
+}
+
+static struct resource_entry *
+find_gap(struct resource_entry *root, u_long from, u_long num)
+{
+ struct resource_entry *p;
if (from > from+num-1)
return NULL;
- save_flags(flags);
- cli();
for (p = root; ; p = p->next) {
if ((p != root) && (p->from+p->num-1 >= from)) {
p = NULL;
@@ -61,123 +80,147 @@
if ((p->next == NULL) || (p->next->from > from+num-1))
break;
}
- restore_flags(flags);
return p;
}
/*
- * Call this from the device driver to register the ioport region.
+ * Call this from a driver to assert ownership of a resource
*/
-void request_region(unsigned long from, unsigned long num, const char *name)
+void request_resource(int class, unsigned long from,
+ unsigned long num, const char *name)
{
- resource_entry_t *p;
+ struct resource_entry *root = &res_list[class];
+ struct resource_entry *p;
+ long flags;
int i;
- for (i = 0; i < IOTABLE_SIZE; i++)
- if (iotable[i].num == 0)
+ p = find_match(root, from, num);
+ if (p) {
+ p->name = name;
+ return;
+ }
+
+ save_flags(flags);
+ cli();
+ for (i = 0; i < RSRC_TABLE_SIZE; i++)
+ if (rsrc_table[i].num == 0)
break;
- if (i == IOTABLE_SIZE)
- printk("warning: ioport table is full\n");
+ if (i == RSRC_TABLE_SIZE)
+ printk("warning: resource table is full\n");
else {
- p = find_gap(&iolist, from, num);
- if (p == NULL)
+ p = find_gap(root, from, num);
+ if (p == NULL) {
+ restore_flags(flags);
return;
- iotable[i].name = name;
- iotable[i].from = from;
- iotable[i].num = num;
- iotable[i].next = p->next;
- p->next = &iotable[i];
- return;
+ }
+ rsrc_table[i].name = name;
+ rsrc_table[i].from = from;
+ rsrc_table[i].num = num;
+ rsrc_table[i].next = p->next;
+ p->next = &rsrc_table[i];
}
+ restore_flags(flags);
}
/*
- * Call this when the device driver is unloaded
+ * Call these when a driver is unloaded but the device remains
*/
-void release_region(unsigned long from, unsigned long num)
+void release_resource(int class, unsigned long from, unsigned long num)
{
- resource_entry_t *p, *q;
-
- for (p = &iolist; ; p = q) {
- q = p->next;
- if (q == NULL)
- break;
- if ((q->from == from) && (q->num == num)) {
- q->num = 0;
- p->next = q->next;
- return;
- }
- }
+ struct resource_entry *root = &res_list[class];
+ struct resource_entry *p;
+ p = find_match(root, from, num);
+ if (p) p->name = NULL;
}
/*
- * Call this to check the ioport region before probing
+ * Call these to check a region for conflicts before probing
*/
-int check_region(unsigned long from, unsigned long num)
+int check_resource(int class, unsigned long from, unsigned long num)
{
- return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
+ struct resource_entry *root = &res_list[class];
+ struct resource_entry *p;
+ p = find_match(root, from, num);
+ if (p != NULL)
+ return (p->name != NULL) ? -EBUSY : 0;
+ return (find_gap(root, from, num) == NULL) ? -EBUSY : 0;
}
-#ifdef __sparc__ /* Why to carry unused code on other architectures? */
/*
- * This is for architectures with MMU-managed ports (sparc).
+ * Call this to claim a resource for a piece of hardware
*/
-unsigned long occupy_region(unsigned long base, unsigned long end,
- unsigned long num, unsigned int align, const char *name)
+unsigned long occupy_resource(int class, unsigned long base,
+ unsigned long end, unsigned long num,
+ unsigned long align, const char *name)
{
+ struct resource_entry *root = &res_list[class];
unsigned long from = 0, till;
unsigned long flags;
int i;
- resource_entry_t *p; /* Scanning ptr */
- resource_entry_t *p1; /* === p->next */
- resource_entry_t *s; /* Found slot */
+ struct resource_entry *p, *q;
- if (base > end-1)
- return 0;
- if (num > end - base)
+ if ((base > end-1) || (num > end - base))
return 0;
- for (i = 0; i < IOTABLE_SIZE; i++)
- if (iotable[i].num == 0)
+ for (i = 0; i < RSRC_TABLE_SIZE; i++)
+ if (rsrc_table[i].num == 0)
break;
- if (i == IOTABLE_SIZE) {
- /* Driver prints a warning typically. */
+ if (i == RSRC_TABLE_SIZE)
return 0;
- }
save_flags(flags);
cli();
/* printk("occupy: search in %08lx[%08lx] ", base, end - base); */
- s = NULL;
- for (p = &iolist; p != NULL; p = p1) {
- p1 = p->next;
+ for (p = root; p != NULL; p = q) {
+ q = p->next;
/* Find window in list */
- from = (p->from+p->num + align-1) & ~((unsigned long)align-1);
- till = (p1 == NULL)? (unsigned long) (0 - (unsigned long)align): p1->from;
+ from = (p->from+p->num + align-1) & ~(align-1);
+ till = (q == NULL) ? (0 - align) : q->from;
/* printk(" %08lx:%08lx", from, till); */
/* Clip window with base and end */
if (from < base) from = base;
if (till > end) till = end;
/* See if result is large enougth */
- if (from < till && from + num < till) {
- s = p;
+ if ((from < till) && (from + num < till))
break;
- }
}
/* printk("\r\n"); */
restore_flags(flags);
- if (s == NULL)
+ if (p == NULL)
return 0;
- iotable[i].name = name;
- iotable[i].from = from;
- iotable[i].num = num;
- iotable[i].next = s->next;
- s->next = &iotable[i];
+ rsrc_table[i].name = name;
+ rsrc_table[i].from = from;
+ rsrc_table[i].num = num;
+ rsrc_table[i].next = p->next;
+ p->next = &rsrc_table[i];
return from;
}
-#endif
+
+/*
+ * Call this when a resource becomes available for other hardware
+ */
+void vacate_resource(int class, unsigned long from, unsigned long num)
+{
+ struct resource_entry *root = &res_list[class];
+ struct resource_entry *p, *q;
+ long flags;
+
+ save_flags(flags);
+ cli();
+ for (p = root; ; p = q) {
+ q = p->next;
+ if (q == NULL)
+ break;
+ if ((q->from == from) && (q->num == num)) {
+ q->num = 0;
+ p->next = q->next;
+ break;
+ }
+ }
+ restore_flags(flags);
+}
/* Called from init/main.c to reserve IO ports. */
void __init reserve_setup(char *str, int *ints)
--- linux/kernel/ksyms.c.O Thu Jun 17 10:32:35 1999
+++ linux/kernel/ksyms.c Fri Jun 18 08:08:19 1999
@@ -302,10 +302,12 @@
EXPORT_SYMBOL(enable_hlt);
#endif
-/* IO port handling */
-EXPORT_SYMBOL(check_region);
-EXPORT_SYMBOL(request_region);
-EXPORT_SYMBOL(release_region);
+/* resource handling */
+EXPORT_SYMBOL(check_resource);
+EXPORT_SYMBOL(request_resource);
+EXPORT_SYMBOL(release_resource);
+EXPORT_SYMBOL(occupy_resource);
+EXPORT_SYMBOL(vacate_resource);
/* process management */
EXPORT_SYMBOL(__wake_up);
--- linux/include/linux/ioport.h.O Wed Oct 22 08:31:55 1997
+++ linux/include/linux/ioport.h Fri Jun 18 08:05:37 1999
@@ -1,14 +1,38 @@
/*
- * portio.h Definitions of routines for detecting, reserving and
+ * ioport.h Definitions of routines for detecting, reserving and
* allocating system resources.
*
- * Version: 0.01 8/30/93
- *
- * Author: Donald Becker (becker@super.org)
+ * Authors: Donald Becker (becker@cesdis.gsfc.nasa.gov)
+ * David Hinds (dhinds@zen.stanford.edu)
*/
-#ifndef _LINUX_PORTIO_H
-#define _LINUX_PORTIO_H
+#ifndef _LINUX_IOPORT_H
+#define _LINUX_IOPORT_H
+
+#define RES_IO 0
+#define RES_MEM 1
+
+extern void reserve_setup(char *str, int *ints);
+
+extern struct resource_entry *iolist, *memlist;
+
+extern int get_resource_list(int class, char *buf);
+extern int check_resource(int class,
+ unsigned long from, unsigned long extent);
+extern void request_resource(int class,
+ unsigned long from, unsigned long extent,
+ const char *name);
+extern void release_resource(int class,
+ unsigned long from, unsigned long extent);
+extern unsigned long occupy_resource(int class,
+ unsigned long base, unsigned long end,
+ unsigned long num, unsigned long align,
+ const char *name);
+extern void vacate_resource(int class,
+ unsigned long from, unsigned long extent);
+
+#define get_ioport_list(buf) get_resource_list(RES_IO, buf)
+#define get_mem_list(buf) get_resource_list(RES_MEM, buf)
#define HAVE_PORTRESERVE
/*
@@ -16,20 +40,21 @@
* Once you have found you hardware, register it with request_region().
* If you unload the driver, use release_region to free ports.
*/
-extern void reserve_setup(char *str, int *ints);
-extern int check_region(unsigned long from, unsigned long extent);
-extern void request_region(unsigned long from, unsigned long extent,const char *name);
-extern void release_region(unsigned long from, unsigned long extent);
-extern int get_ioport_list(char *);
-
-#ifdef __sparc__
-extern unsigned long occupy_region(unsigned long base, unsigned long end,
- unsigned long num, unsigned int align,
- const char *name);
-#endif
+#define check_region(f,e) check_resource(RES_IO,f,e)
+#define request_region(f,e,n) request_resource(RES_IO,f,e,n)
+#define release_region(f,e) release_resource(RES_IO,f,e)
+#define occupy_region(b,e,n,a,s) occupy_resource(RES_IO,b,e,n,a,s)
+#define vacate_region(f,e) vacate_resource(RES_IO,f,e)
+
+#define HAVE_MEMRESERVE
+#define check_mem_region(f,e) check_resource(RES_MEM,f,e)
+#define request_mem_region(f,e,n) request_resource(RES_MEM,f,e,n)
+#define release_mem_region(f,e) release_resource(RES_MEM,f,e)
+#define occupy_mem_region(b,e,n,a,s) occupy_resource(RES_MEM,b,e,n,a,s)
+#define vacate_mem_region(f,e) vacate_resource(RES_MEM,f,e)
#define HAVE_AUTOIRQ
extern void autoirq_setup(int waittime);
extern int autoirq_report(int waittime);
-#endif /* _LINUX_PORTIO_H */
+#endif /* _LINUX_IOPORT_H */
--- linux/fs/proc/root.c.O Thu Jun 17 10:32:34 1999
+++ linux/fs/proc/root.c Fri Jun 18 08:48:46 1999
@@ -621,6 +621,11 @@
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
+static struct proc_dir_entry proc_root_memory = {
+ PROC_MEMORY, 6, "memory",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations
+};
static struct proc_dir_entry proc_root_cmdline = {
PROC_CMDLINE, 7, "cmdline",
S_IFREG | S_IRUGO, 1, 0, 0,
@@ -709,6 +714,7 @@
proc_register(&proc_root, &proc_root_fs);
proc_register(&proc_root, &proc_root_dma);
proc_register(&proc_root, &proc_root_ioports);
+ proc_register(&proc_root, &proc_root_memory);
proc_register(&proc_root, &proc_root_cmdline);
#ifdef CONFIG_RTC
proc_register(&proc_root, &proc_root_rtc);
--- linux/fs/proc/array.c.O Thu Jun 17 10:30:53 1999
+++ linux/fs/proc/array.c Fri Jun 18 08:48:49 1999
@@ -1326,6 +1326,9 @@
case PROC_IOPORTS:
return get_ioport_list(page);
+
+ case PROC_MEMORY:
+ return get_mem_list(page);
#ifdef CONFIG_BLK_DEV_MD
case PROC_MD:
return get_md_status(page);
--- linux/include/linux/proc_fs.h.O Fri Jun 18 00:39:44 1999
+++ linux/include/linux/proc_fs.h Fri Jun 18 08:48:47 1999
@@ -37,6 +37,7 @@
PROC_KSYMS,
PROC_DMA,
PROC_IOPORTS,
+ PROC_MEMORY,
PROC_PROFILE, /* whether enabled or not */
PROC_CMDLINE,
PROC_SYS,
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/