PATCH: Reserving memory and /proc/memzones

Donnie Roberts (droberts@nutnet.com)
Sun, 25 May 1997 08:43:24 -0400


This is a multi-part message in MIME format.

--------------313463C401BBAE716D1A80
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

This kernel patch is a modified version of Michel Lespinasse's
(walken@via.ecp.fr) /proc/memzones patch. It includes the ability to
exclude
memory addresses from use by marking the memory as reserved. This is
useful
if you have a slightly defective SIMM, which I happen to have. Since I
had
the kernel mark the bad memory as reserved, I have had no sig 11 errors
while compiling the kernel or anything else. The new kernel command-line
option is:

reservemem=<start addr>,<size>,...

Up to five blocks of memory can be reserved. I changed the end of low
memory to 0xa0000 instead of 0x9f000. If this causes a problem, (I
believe
this was a workaround for IBM's ThinkPad) just add:
reservemem=0x9f000,0x1000
I changed the kernel option reserve to reserveio to prevent confusion
between
the two. Here is what /proc/memzones looks like on my system:

Kernel 2.0.30:
00000000-00000fff : reserved
00001000-0009ffff : free
000c0000-000c7fff : rom
000ed000-000edfff : rom
00100000-00182fff : kernel code
00183000-00248fff : kernel data
00249000-00a6ffff : free
00a70000-00a71fff : reserved <-- This is the location of my bad ram
00a72000-027fffff : free

Kernel 2.1.38:
00000000-00002fff : reserved
00003000-0009ffff : free
000c0000-000c7fff : rom
000ed000-000edfff : rom
00100000-001a6fff : kernel code
001a7000-001b6fff : kernel data
001b7000-001bcfff : free <-- This gap is caused by freeing the
init code
001bd000-00280fff : kernel data
00281000-00a6ffff : free
00a70000-00a71fff : reserved
00a72000-027fffff : free

--------------313463C401BBAE716D1A80
Content-Type: text/plain; charset=us-ascii; name="reserve-mem-2.0.30.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="reserve-mem-2.0.30.patch"

diff -ru linux-old/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- linux-old/arch/i386/mm/init.c Thu Nov 14 08:20:09 1996
+++ linux/arch/i386/mm/init.c Sun May 25 05:25:25 1997
@@ -20,6 +20,7 @@
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
+#include <linux/ioport.h>

#include <asm/system.h>
#include <asm/segment.h>
@@ -204,6 +205,28 @@
return free_area_init(start_mem, end_mem);
}

+void scan_rom(void)
+{
+ int i, j, size;
+ unsigned char sum;
+
+ for (i= 0xa0000 ; i < 0x100000 ; ) {
+ if (readw(i) == 0xaa55) {
+ size = readb(i+2) << 9;
+ sum = 0;
+ for (j = i ; size-- > 0 ; j++) {
+ sum += readb(i);
+ }
+ if (!sum) {
+ request_memzone(i, j-i, "rom");
+ i = j;
+ continue;
+ }
+ }
+ i += 0x1000;
+ }
+}
+
void mem_init(unsigned long start_mem, unsigned long end_mem)
{
unsigned long start_low_mem = PAGE_SIZE;
@@ -235,26 +258,46 @@
* IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
* They seem to have done something stupid with the floppy
* controller as well..
+ *
+ * If you have the need to exclude 0x9F000, use the kernel option:
+ * reservemem=0x9f000,0x1000
+ *
+ * Likewise, if you have any area of ram to reserve, use:
+ * reservemem=<start addr>,<length>,...
+ *
+ * Up to 5 regions can be specified. This can be useful for excluding
+ * bad areas of ram without the need to replace the defective SIMM.
*/
- while (start_low_mem < 0x9f000) {
- clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
- start_low_mem += PAGE_SIZE;
+ request_memzone(0, start_low_mem, "reserved");
+ tmp = start_low_mem;
+ while (tmp < 0xa0000) {
+ if (!check_memzone(tmp, PAGE_SIZE)) {
+ clear_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
+ request_memzone(tmp, PAGE_SIZE, "free");
+ }
+ tmp += PAGE_SIZE;
}
-
- while (start_mem < high_memory) {
- clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
- start_mem += PAGE_SIZE;
+ tmp = start_mem;
+ while (tmp < high_memory) {
+ if (!check_memzone(tmp, PAGE_SIZE)) {
+ clear_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
+ request_memzone(tmp, PAGE_SIZE, "free");
+ }
+ tmp += PAGE_SIZE;
}
for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) {
if (tmp >= MAX_DMA_ADDRESS)
clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
if (PageReserved(mem_map+MAP_NR(tmp))) {
- if (tmp >= 0xA0000 && tmp < 0x100000)
+ if (check_memzone(tmp, PAGE_SIZE) || (tmp >= 0xA0000 && tmp < 0x100000))
reservedpages++;
- else if (tmp < (unsigned long) &_etext)
+ else if (tmp < (unsigned long) &_etext) {
+ request_memzone(tmp, PAGE_SIZE, "kernel code");
codepages++;
- else
+ } else {
+ request_memzone(tmp, PAGE_SIZE, "kernel data");
datapages++;
+ }
continue;
}
mem_map[MAP_NR(tmp)].count = 1;
@@ -265,12 +308,12 @@
free_page(tmp);
}
tmp = nr_free_pages << PAGE_SHIFT;
- printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
+ printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk reserved)\n",
tmp >> 10,
high_memory >> 10,
codepages << (PAGE_SHIFT-10),
- reservedpages << (PAGE_SHIFT-10),
- datapages << (PAGE_SHIFT-10));
+ datapages << (PAGE_SHIFT-10),
+ reservedpages << (PAGE_SHIFT-10));
/* test if the WP bit is honoured in supervisor mode */
if (wp_works_ok < 0) {
pg0[0] = pte_val(mk_pte(0, PAGE_READONLY));
@@ -281,6 +324,9 @@
if (wp_works_ok < 0)
wp_works_ok = 0;
}
+
+ scan_rom();
+
return;
}

diff -ru linux-old/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
--- linux-old/drivers/net/ibmtr.c Sun Apr 27 19:21:08 1997
+++ linux/drivers/net/ibmtr.c Sun May 25 05:25:25 1997
@@ -221,8 +221,6 @@
struct tok_info *ti=0;
static struct tok_info *badti=0; /* if fail after kmalloc, reuse */

- static unsigned char Shared_Ram_Base = IBMTR_SHARED_RAM_BASE;
-
/* this is the major adapter probe loop. For each call to tok_probe,
we try each remaining entry in TokBaseAddrs[] as a possible
adapter. Once an entry is rejected or assigned, we zero it to
@@ -499,21 +497,34 @@
/* finish figuring the shared RAM address */
if (cardpresent==TR_ISA) {
static unsigned char ram_bndry_mask[]={0xfe, 0xfc, 0xf8, 0xf0};
- unsigned char new_base, rrr_32, chk_base, rbm;
+ static unsigned char ram_pos[47]=
+ {0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+ 0xc8, 0xca, 0xce, 0xcc, 0xc0, 0xc2, 0xc4, 0xc6,
+ 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
+ 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
+ 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
+ 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc};
+ unsigned char new_base, rrr_32, rbm;
+ unsigned int i;
+
rrr_32 = (readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD))>>2;
- rbm = ram_bndry_mask[rrr_32];
- new_base = (Shared_Ram_Base + (~rbm)) & rbm; /* up to boundary */
- chk_base = new_base + (ti->mapped_ram_size>>3);
- if (chk_base > (IBMTR_SHARED_RAM_BASE+IBMTR_SHARED_RAM_SIZE)) {
- DPRINTK("Shared RAM for this adapter (%05x) exceeds driver"
- " limit (%05x), adapter not started.\n",
- chk_base<<12, (IBMTR_SHARED_RAM_BASE+
- IBMTR_SHARED_RAM_SIZE)<<12);
- badti=ti;
- } else { /* seems cool, record what we have figured out */
- ti->sram_base = new_base;
- Shared_Ram_Base = new_base;
+ rbm = ram_bndry_mask[rrr_32 & 3];
+
+ for (i = 0 ; i < 47 ; i++) {
+ if ((new_base = ram_pos[i]) & ~rbm)
+ continue;
+ if ((ti->mmio + ACA_OFFSET <
+ new_base << 12 + ti->mapped_ram_size << 9) &&
+ (ti->mmio + ACA_OFFSET + 0x200 > new_base << 12))
+ /* mmio zone overlaps the proposed sram zone */
+ continue;
+ if (check_memzone(new_base<<12, ti->mapped_ram_size<<9))
+ continue;
+ ti->sram_base = new_base;
+ break;
}
+ if (i == 47)
+ badti=ti;
}

/* dwm: irq and other final setup moved here so if we find other
@@ -535,6 +546,10 @@
/*?? Now, allocate some of the PIO PORTs for this driver.. */
request_region(PIOaddr,TR_IO_EXTENT,"ibmtr"); /* record PIOaddr range
as busy */
+ request_memzone(ti->mmio + ACA_OFFSET, 0x200, "ibmtr mmio");
+ request_memzone(ti->sram ? ti->sram : (ti->sram_base << 12),
+ ti->mapped_ram_size << 9, "ibmtr shared RAM");
+
#if !TR_NEWFORMAT
DPRINTK("%s",version); /* As we have passed card identification,
let the world know we're here! */
diff -ru linux-old/drivers/net/ibmtr.h linux/drivers/net/ibmtr.h
--- linux-old/drivers/net/ibmtr.h Sun May 25 06:04:46 1997
+++ linux/drivers/net/ibmtr.h Sun May 25 05:25:25 1997
@@ -13,11 +13,6 @@
#define NOTOK 0
#define TOKDEBUG 1

-#ifndef IBMTR_SHARED_RAM_BASE
-#define IBMTR_SHARED_RAM_BASE 0xD0
-#define IBMTR_SHARED_RAM_SIZE 0x10
-#endif
-
#define CHANNEL_ID 0X1F30
#define AIP 0X1F00
#define AIPCHKSUM1 0X1F60
diff -ru linux-old/fs/proc/array.c linux/fs/proc/array.c
--- linux-old/fs/proc/array.c Tue Oct 29 20:42:41 1996
+++ linux/fs/proc/array.c Sun May 25 05:25:25 1997
@@ -1033,6 +1033,10 @@

case PROC_IOPORTS:
return get_ioport_list(page);
+
+ case PROC_MEMZONES:
+ return get_memzone_list(page);
+
#ifdef CONFIG_BLK_DEV_MD
case PROC_MD:
return get_md_status(page);
diff -ru linux-old/fs/proc/root.c linux/fs/proc/root.c
--- linux-old/fs/proc/root.c Tue Apr 30 06:09:45 1996
+++ linux/fs/proc/root.c Sun May 25 05:25:25 1997
@@ -349,6 +349,10 @@
S_IFREG | S_IRUGO, 1, 0, 0,
});
proc_register(&proc_root, &(struct proc_dir_entry) {
+ PROC_MEMZONES, 8, "memzones",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ });
+ proc_register(&proc_root, &(struct proc_dir_entry) {
PROC_CMDLINE, 7, "cmdline",
S_IFREG | S_IRUGO, 1, 0, 0,
});
diff -ru linux-old/include/linux/ioport.h linux/include/linux/ioport.h
--- linux-old/include/linux/ioport.h Sat Dec 30 14:00:41 1995
+++ linux/include/linux/ioport.h Sun May 25 05:25:25 1997
@@ -16,12 +16,18 @@
* 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 void reserveio_setup(char *str, int *ints);
extern int check_region(unsigned int from, unsigned int extent);
extern void request_region(unsigned int from, unsigned int extent,const char *name);
extern void release_region(unsigned int from, unsigned int extent);
extern int get_ioport_list(char *);

+#define HAVE_MEMRESERVE
+extern void reservemem_setup(char *str, int *ints);
+extern int check_memzone(unsigned int from, unsigned int extent);
+extern void request_memzone(unsigned int from, unsigned int extent,const char *name);
+extern void release_memzone(unsigned int from, unsigned int extent);
+extern int get_memzone_list(char *);

#define HAVE_AUTOIRQ
extern void *irq2dev_map[16]; /* Use only if you own the IRQ. */
diff -ru linux-old/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- linux-old/include/linux/proc_fs.h Sun Apr 27 19:21:12 1997
+++ linux/include/linux/proc_fs.h Sun May 25 05:25:25 1997
@@ -34,6 +34,7 @@
PROC_KSYMS,
PROC_DMA,
PROC_IOPORTS,
+ PROC_MEMZONES,
#ifdef __SMP_PROF__
PROC_SMP_PROF,
#endif
diff -ru linux-old/init/main.c linux/init/main.c
--- linux-old/init/main.c Sat Nov 23 08:28:23 1996
+++ linux/init/main.c Sun May 25 05:25:25 1997
@@ -252,7 +252,8 @@
const char *str;
void (*setup_func)(char *, int *);
} bootsetups[] = {
- { "reserve=", reserve_setup },
+ { "reserveio=", reserveio_setup },
+ { "reservemem=", reservemem_setup },
{ "profile=", profile_setup },
#ifdef CONFIG_BLK_DEV_RAM
{ "ramdisk_start=", ramdisk_start_setup },
diff -ru linux-old/kernel/resource.c linux/kernel/resource.c
--- linux-old/kernel/resource.c Sun Apr 27 19:21:12 1997
+++ linux/kernel/resource.c Sat May 25 05:25:25 1997
@@ -4,7 +4,7 @@
* Copyright (C) 1995 Linus Torvalds
* David Hinds
*
- * Kernel io-region resource management
+ * Kernel io and memory region resource management
*/

#include <linux/sched.h>
@@ -14,6 +14,7 @@
#include <linux/ioport.h>

#define IOTABLE_SIZE 128
+#define MEMTABLE_SIZE 64

typedef struct resource_entry_t {
u_long from, num;
@@ -22,11 +23,13 @@
} resource_entry_t;

static resource_entry_t iolist = { 0, 0, "", NULL };
+static resource_entry_t memlist = { 0, 0, "", NULL };

static resource_entry_t iotable[IOTABLE_SIZE];
+static resource_entry_t memtable[MEMTABLE_SIZE];

/*
- * This generates the report for /proc/ioports
+ * This generates the report for /proc/ioports or /proc/memzones
*/
int get_ioport_list(char *buf)
{
@@ -41,6 +44,20 @@
return len;
}

+int get_memzone_list(char *buf)
+{
+ resource_entry_t *p;
+ int len = 0;
+
+ for (p = memlist.next; (p) && (len < 4000); p = p->next)
+ len += sprintf(buf+len, "%08lx-%08lx : %s\n",
+ p->from, p->from+p->num-1, p->name);
+ if (p)
+ len += sprintf(buf+len, "4K limit reached!\n");
+ return len;
+}
+
+
/*
* The workhorse function: find where to put a new entry
*/
@@ -67,39 +84,57 @@
}

/*
- * Call this from the device driver to register the ioport region.
+ * Call this from the device driver to register the ioport or memory region.
*/
-void request_region(unsigned int from, unsigned int num, const char *name)
+void request_resource(resource_entry_t *res, resource_entry_t *list, unsigned int size, unsigned int from, unsigned int num, const char *name)
{
resource_entry_t *p;
int i;

- for (i = 0; i < IOTABLE_SIZE; i++)
- if (iotable[i].num == 0)
+ for ( ; size > 0 ; res++, size--)
+ if (res->num == 0)
break;
- if (i == IOTABLE_SIZE)
- printk("warning: ioport table is full\n");
+ if ( !size )
+ printk("warning: resource table is full\n");
else {
- p = find_gap(&iolist, from, num);
+ p = find_gap(list, from, num);
if (p == NULL)
return;
- iotable[i].name = name;
- iotable[i].from = from;
- iotable[i].num = num;
- iotable[i].next = p->next;
- p->next = &iotable[i];
+
+/* If allocating an adjacent space, combine into one entry */
+
+ if (p->from+p->num == from && !strcmp(p->name, name)) {
+ p->num += num;
+ } else {
+ res->name = name;
+ res->from = from;
+ res->num = num;
+ res->next = p->next;
+ p->next = res;
+ }
return;
}
}

+void request_region(unsigned int from, unsigned int num, const char *name)
+{
+ request_resource(iotable, &iolist, IOTABLE_SIZE, from, num, name);
+}
+
+void request_memzone(unsigned int from, unsigned int num, const char *name)
+{
+ request_resource(memtable, &memlist, MEMTABLE_SIZE, from, num, name);
+}
+
+
/*
* Call this when the device driver is unloaded
*/
-void release_region(unsigned int from, unsigned int num)
+void release_resource(resource_entry_t *p, unsigned int from, unsigned int num)
{
- resource_entry_t *p, *q;
+ resource_entry_t *q;

- for (p = &iolist; ; p = q) {
+ for ( ; ; p = q) {
q = p->next;
if (q == NULL)
break;
@@ -111,6 +146,17 @@
}
}

+void release_region(unsigned int from, unsigned int num)
+{
+ release_resource(&iolist, from, num);
+}
+
+void release_memzone(unsigned int from, unsigned int num)
+{
+ release_resource(&memlist, from, num);
+}
+
+
/*
* Call this to check the ioport region before probing
*/
@@ -119,11 +165,24 @@
return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
}

+int check_memzone(unsigned int from, unsigned int num)
+{
+ return (find_gap(&memlist, from, num) == NULL) ? -EBUSY : 0;
+}
+
/* Called from init/main.c to reserve IO ports. */
-void reserve_setup(char *str, int *ints)
+void reserveio_setup(char *str, int *ints)
{
int i;

for (i = 1; i < ints[0]; i += 2)
request_region(ints[i], ints[i+1], "reserved");
}
+
+void reservemem_setup(char *str, int *ints)
+{
+ int i;
+
+ for (i = 1; i < ints[0]; i += 2)
+ request_memzone(ints[i], ints[i+1], "reserved");
+}

--------------313463C401BBAE716D1A80
Content-Type: text/plain; charset=us-ascii; name="reserve-mem-2.1.38.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="reserve-mem-2.1.38.patch"

diff -ru linux-old/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- linux-old/arch/i386/mm/init.c Fri May 16 15:27:42 1997
+++ linux/arch/i386/mm/init.c Sat May 24 21:59:50 1997
@@ -21,6 +21,7 @@
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
+#include <linux/ioport.h>

#include <asm/system.h>
#include <asm/uaccess.h>
@@ -261,6 +262,28 @@
return free_area_init(start_mem, end_mem);
}

+__initfunc(void scan_rom(void))
+{
+ int i, j, size;
+ unsigned char sum;
+
+ for (i= 0xa0000 ; i < 0x100000 ; ) {
+ if (readw(i) == 0xaa55) {
+ size = readb(i+2) << 9;
+ sum = 0;
+ for (j = i ; size-- > 0 ; j++) {
+ sum += readb(i);
+ }
+ if (!sum) {
+ request_memzone(i, j-i, "rom");
+ i = j;
+ continue;
+ }
+ }
+ i += 0x1000;
+ }
+}
+
__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
{
unsigned long start_low_mem = PAGE_SIZE;
@@ -296,32 +319,54 @@
* IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
* They seem to have done something stupid with the floppy
* controller as well..
+ *
+ * If you have the need to exclude 0x9f000, use the kernel option:
+ * reservemem=0x9f000,0x1000
+ *
+ * Likewise, if you have any area of ram to reserve, use:
+ * reservemem=<start addr>,<length>,...
+ *
+ * Up to 5 regions can be specified. This can be useful for excluding
+ * bad areas of ram without the need to replace the defective SIMM.
*/
- while (start_low_mem < 0x9f000+PAGE_OFFSET) {
- clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
- start_low_mem += PAGE_SIZE;
+ request_memzone(0, start_low_mem-PAGE_OFFSET, "reserved");
+ tmp = start_low_mem;
+ while (tmp < 0xa0000+PAGE_OFFSET) {
+ if (!check_memzone(tmp-PAGE_OFFSET, PAGE_SIZE)) {
+ clear_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
+ request_memzone(tmp-PAGE_OFFSET, PAGE_SIZE, "free");
+ }
+ tmp += PAGE_SIZE;
}
-
- while (start_mem < end_mem) {
- clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
- start_mem += PAGE_SIZE;
+ tmp = start_mem;
+ while (tmp < end_mem) {
+ if (!check_memzone(tmp-PAGE_OFFSET, PAGE_SIZE)) {
+ clear_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
+ request_memzone(tmp-PAGE_OFFSET, PAGE_SIZE, "free");
+ }
+ tmp += PAGE_SIZE;
}
for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
if (tmp >= MAX_DMA_ADDRESS)
clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
if (PageReserved(mem_map+MAP_NR(tmp))) {
if (tmp >= (unsigned long) &_text && tmp < (unsigned long) &_edata) {
- if (tmp < (unsigned long) &_etext)
+ if (tmp < (unsigned long) &_etext) {
+ request_memzone(tmp-PAGE_OFFSET, PAGE_SIZE, "kernel code");
codepages++;
- else
+ } else {
+ request_memzone(tmp-PAGE_OFFSET, PAGE_SIZE, "kernel data");
datapages++;
+ }
} else if (tmp >= (unsigned long) &__init_begin
- && tmp < (unsigned long) &__init_end)
+ && tmp < (unsigned long) &__init_end) {
+ request_memzone(tmp-PAGE_OFFSET, PAGE_SIZE, "free");
initpages++;
- else if (tmp >= (unsigned long) &__bss_start
- && tmp < (unsigned long) start_mem)
+ } else if (tmp >= (unsigned long) &__bss_start
+ && tmp < (unsigned long) start_mem) {
+ request_memzone(tmp-PAGE_OFFSET, PAGE_SIZE, "kernel data");
datapages++;
- else
+ } else
reservedpages++;
continue;
}
@@ -332,13 +377,13 @@
#endif
free_page(tmp);
}
- printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+ printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init, %dk reserved)\n",
(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
max_mapnr << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10),
- reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
- initpages << (PAGE_SHIFT-10));
+ initpages << (PAGE_SHIFT-10),
+ reservedpages << (PAGE_SHIFT-10));
/* test if the WP bit is honoured in supervisor mode */
if (wp_works_ok < 0) {
unsigned char tmp_reg;
@@ -362,6 +407,9 @@
} else
printk("Ok.\n");
}
+
+ scan_rom();
+
return;
}

diff -ru linux-old/fs/proc/array.c linux/fs/proc/array.c
--- linux-old/fs/proc/array.c Fri May 16 15:28:04 1997
+++ linux/fs/proc/array.c Sat May 24 07:45:01 1997
@@ -1085,6 +1085,10 @@

case PROC_IOPORTS:
return get_ioport_list(page);
+
+ case PROC_MEMZONES:
+ return get_memzone_list(page);
+
#ifdef CONFIG_BLK_DEV_MD
case PROC_MD:
return get_md_status(page);
diff -ru linux-old/fs/proc/root.c linux/fs/proc/root.c
--- linux-old/fs/proc/root.c Fri May 16 15:28:04 1997
+++ linux/fs/proc/root.c Sat May 24 07:49:32 1997
@@ -502,6 +502,11 @@
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
+static struct proc_dir_entry proc_root_memzones = {
+ PROC_MEMZONES, 8, "memzones",
+ 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,
@@ -584,6 +589,7 @@
proc_register(&proc_root, &proc_root_filesystems);
proc_register(&proc_root, &proc_root_dma);
proc_register(&proc_root, &proc_root_ioports);
+ proc_register(&proc_root, &proc_root_memzones);
proc_register(&proc_root, &proc_root_cmdline);
#ifdef CONFIG_RTC
proc_register(&proc_root, &proc_root_rtc);
diff -ru linux-old/include/linux/ioport.h linux/include/linux/ioport.h
--- linux-old/include/linux/ioport.h Fri Apr 11 13:47:40 1997
+++ linux/include/linux/ioport.h Sat May 24 08:15:09 1997
@@ -16,11 +16,18 @@
* 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 void reserveio_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 *);
+
+#define HAVE_MEMRESERVE
+extern void reservemem_setup(char *str, int *ints);
+extern int check_memzone(unsigned long from, unsigned long extent);
+extern void request_memzone(unsigned long from, unsigned long extent,const char *name);
+extern void release_memzone(unsigned long from, unsigned long extent);
+extern int get_memzone_list(char *);

#ifdef __sparc__
extern unsigned long occupy_region(unsigned long base, unsigned long end,
diff -ru linux-old/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- linux-old/include/linux/proc_fs.h Fri May 16 15:28:09 1997
+++ linux/include/linux/proc_fs.h Sat May 24 08:52:08 1997
@@ -36,6 +36,7 @@
PROC_KSYMS,
PROC_DMA,
PROC_IOPORTS,
+ PROC_MEMZONES,
#ifdef __SMP_PROF__
PROC_SMP_PROF,
#endif
diff -ru linux-old/init/main.c linux/init/main.c
--- linux-old/init/main.c Fri May 16 15:28:37 1997
+++ linux/init/main.c Sat May 24 07:51:22 1997
@@ -293,7 +293,8 @@
const char *str;
void (*setup_func)(char *, int *);
} bootsetups[] __initdata = {
- { "reserve=", reserve_setup },
+ { "reserveio=", reserveio_setup },
+ { "reservemem=", reservemem_setup },
{ "profile=", profile_setup },
#ifdef __SMP__
{ "nosmp", smp_setup },
diff -ru linux-old/kernel/resource.c linux/kernel/resource.c
--- linux-old/kernel/resource.c Fri May 16 15:28:10 1997
+++ linux/kernel/resource.c Sat May 24 09:05:18 1997
@@ -4,17 +4,19 @@
* Copyright (C) 1995 Linus Torvalds
* David Hinds
*
- * Kernel io-region resource management
+ * Kernel io and memory region resource management
*/

#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/string.h>
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/init.h>

#define IOTABLE_SIZE 128
+#define MEMTABLE_SIZE 64

typedef struct resource_entry_t {
u_long from, num;
@@ -23,11 +25,13 @@
} resource_entry_t;

static resource_entry_t iolist = { 0, 0, "", NULL };
+static resource_entry_t memlist = { 0, 0, "", NULL };

static resource_entry_t iotable[IOTABLE_SIZE];
+static resource_entry_t memtable[MEMTABLE_SIZE];

/*
- * This generates the report for /proc/ioports
+ * This generates the report for /proc/ioports or /proc/memzones
*/
int get_ioport_list(char *buf)
{
@@ -42,6 +46,20 @@
return len;
}

+int get_memzone_list(char *buf)
+{
+ resource_entry_t *p;
+ int len = 0;
+
+ for (p = memlist.next; (p) && (len < 4000); p = p->next)
+ len += sprintf(buf+len, "%08lx-%08lx : %s\n",
+ p->from, p->from+p->num-1, p->name);
+ if (p)
+ len += sprintf(buf+len, "4K limit reached!\n");
+ return len;
+}
+
+
/*
* The workhorse function: find where to put a new entry
*/
@@ -68,39 +86,56 @@
}

/*
- * Call this from the device driver to register the ioport region.
+ * Call this from the device driver to register the ioport or memory region.
*/
-void request_region(unsigned long from, unsigned long num, const char *name)
+void request_resource(resource_entry_t *res, resource_entry_t *list, unsigned int size, unsigned long from, unsigned long num, const char *name)
{
resource_entry_t *p;
- int i;

- for (i = 0; i < IOTABLE_SIZE; i++)
- if (iotable[i].num == 0)
+ for ( ; size > 0 ; res++, size--)
+ if (res->num == 0)
break;
- if (i == IOTABLE_SIZE)
- printk("warning: ioport table is full\n");
+ if ( !size )
+ printk("warning: resource table is full\n");
else {
- p = find_gap(&iolist, from, num);
+ p = find_gap(list, from, num);
if (p == NULL)
return;
- iotable[i].name = name;
- iotable[i].from = from;
- iotable[i].num = num;
- iotable[i].next = p->next;
- p->next = &iotable[i];
+
+ /* If allocating an adjacent space, combine into one entry */
+
+ if (p->from+p->num == from && !strcmp(p->name, name)) {
+ p->num += num;
+ } else {
+ res->name = name;
+ res->from = from;
+ res->num = num;
+ res->next = p->next;
+ p->next = res;
+ }
return;
}
}

+void request_region(unsigned long from, unsigned long num, const char *name)
+{
+ request_resource(iotable, &iolist, IOTABLE_SIZE, from, num, name);
+}
+
+void request_memzone(unsigned long from, unsigned long num, const char *name)
+{
+ request_resource(memtable, &memlist, MEMTABLE_SIZE, from, num, name);
+}
+
+
/*
* Call this when the device driver is unloaded
*/
-void release_region(unsigned long from, unsigned long num)
+void release_resource(resource_entry_t *p, unsigned long from, unsigned long num)
{
- resource_entry_t *p, *q;
+ resource_entry_t *q;

- for (p = &iolist; ; p = q) {
+ for ( ; ; p = q) {
q = p->next;
if (q == NULL)
break;
@@ -112,6 +147,17 @@
}
}

+void release_region(unsigned long from, unsigned long num)
+{
+ release_resource(&iolist, from, num);
+}
+
+void release_memzone(unsigned long from, unsigned long num)
+{
+ release_resource(&memlist, from, num);
+}
+
+
/*
* Call this to check the ioport region before probing
*/
@@ -120,6 +166,11 @@
return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
}

+int check_memzone(unsigned long from, unsigned long num)
+{
+ return (find_gap(&memlist, from, num) == NULL) ? -EBUSY : 0;
+}
+
#ifdef __sparc__ /* Why to carry unused code on other architectures? */
/*
* This is for architectures with MMU-managed ports (sparc).
@@ -182,10 +233,20 @@
#endif

/* Called from init/main.c to reserve IO ports. */
-__initfunc(void reserve_setup(char *str, int *ints))
+__initfunc(void reserveio_setup(char *str, int *ints))
{
int i;

for (i = 1; i < ints[0]; i += 2)
request_region(ints[i], ints[i+1], "reserved");
}
+
+/* Called from init/main.c to reserve memory. */
+__initfunc(void reservemem_setup(char *str, int *ints))
+{
+ int i;
+
+ for (i = 1; i < ints[0]; i += 2)
+ request_memzone(ints[i], ints[i+1], "reserved");
+}
+

--------------313463C401BBAE716D1A80--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu