proposed /proc/memzones addition

Michel LESPINASSE (walken@via.ecp.fr)
Sat, 8 Feb 1997 11:12:08 +0100 (MET)


Hi,

The /proc/interrupts, ioports, dma, pci entryes are VERY useful for me
when I'm hacking my hardware, but monday I felt that /proc/memzones was
lacking. This entry should report the RAM used by the kernel, for general
storage as well as for memory mapped hardware. This would also avoid
conflicts between hardware that can choose their memory mapping address.

Well, here is my proposed patch. It is against kernel 2.0.29, but I
think this should be very easy to adapt to any newer version.
As an example of the modifications this involves on memory-mappign device
drivers, I've done the ibm token ring driver patch too.

The result looks like this :
0000-9ffff : ram
c0000-c7fff : rom
c8000-c87ff : rom
d1e00-d1fff : ibmtr mmio
d4000-d7fff : ibmtr shared RAM
266000-1ffffff : ram

It would be most useful if more drivers used this....

Comments, flames, remarks welcome....

--------------------------------------------------------------------------

diff -ru linux/arch/i386/mm/init.c linux-2.0.29/arch/i386/mm/init.c
--- linux/arch/i386/mm/init.c Thu Nov 14 14:20:09 1996
+++ linux-2.0.29/arch/i386/mm/init.c Sat Feb 8 10:06:22 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;
@@ -236,11 +259,13 @@
* They seem to have done something stupid with the floppy
* controller as well..
*/
+ request_memzone (0, 0xa0000, "ram");
while (start_low_mem < 0x9f000) {
clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
start_low_mem += PAGE_SIZE;
}

+ request_memzone (start_mem, high_memory-start_mem, "ram");
while (start_mem < high_memory) {
clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
start_mem += PAGE_SIZE;
@@ -281,6 +306,9 @@
if (wp_works_ok < 0)
wp_works_ok = 0;
}
+
+ scan_rom();
+
return;
}

diff -ru linux/drivers/net/ibmtr.c linux-2.0.29/drivers/net/ibmtr.c
--- linux/drivers/net/ibmtr.c Thu Aug 29 18:15:14 1996
+++ linux-2.0.29/drivers/net/ibmtr.c Sat Feb 8 09:08:29 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/drivers/net/ibmtr.h linux-2.0.29/drivers/net/ibmtr.h
--- linux/drivers/net/ibmtr.h Fri Feb 7 23:25:56 1997
+++ linux-2.0.29/drivers/net/ibmtr.h Sat Feb 8 08:52:56 1997
@@ -13,11 +13,6 @@
#define NOTOK 0
#define TOKDEBUG 1

-#ifndef IBMTR_SHARED_RAM_BASE
-#define IBMTR_SHARED_RAM_BASE 0xD4
-#define IBMTR_SHARED_RAM_SIZE 0x10
-#endif
-
#define CHANNEL_ID 0X1F30
#define AIP 0X1F00
#define AIPCHKSUM1 0X1F60
diff -ru linux/fs/proc/array.c linux-2.0.29/fs/proc/array.c
--- linux/fs/proc/array.c Wed Oct 30 02:42:41 1996
+++ linux-2.0.29/fs/proc/array.c Sat Feb 8 07:04:45 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/fs/proc/root.c linux-2.0.29/fs/proc/root.c
--- linux/fs/proc/root.c Tue Apr 30 12:09:45 1996
+++ linux-2.0.29/fs/proc/root.c Sat Feb 8 07:29:22 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/include/linux/ioport.h linux-2.0.29/include/linux/ioport.h
--- linux/include/linux/ioport.h Sat Dec 30 20:00:41 1995
+++ linux-2.0.29/include/linux/ioport.h Sat Feb 8 06:59:19 1997
@@ -22,6 +22,12 @@
extern void release_region(unsigned int from, unsigned int extent);
extern int get_ioport_list(char *);

+#define HAVE_MEMRESERVE
+extern void memreserve_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/include/linux/proc_fs.h linux-2.0.29/include/linux/proc_fs.h
--- linux/include/linux/proc_fs.h Sat Feb 8 04:40:16 1997
+++ linux-2.0.29/include/linux/proc_fs.h Sat Feb 8 07:07:40 1997
@@ -34,6 +34,7 @@
PROC_KSYMS,
PROC_DMA,
PROC_IOPORTS,
+ PROC_MEMZONES,
#ifdef __SMP_PROF__
PROC_SMP_PROF,
#endif
diff -ru linux/init/main.c linux-2.0.29/init/main.c
--- linux/init/main.c Sat Nov 23 14:28:23 1996
+++ linux-2.0.29/init/main.c Sat Feb 8 07:01:58 1997
@@ -253,6 +253,7 @@
void (*setup_func)(char *, int *);
} bootsetups[] = {
{ "reserve=", reserve_setup },
+ { "memreserve=", memreserve_setup },
{ "profile=", profile_setup },
#ifdef CONFIG_BLK_DEV_RAM
{ "ramdisk_start=", ramdisk_start_setup },
diff -ru linux/kernel/resource.c linux-2.0.29/kernel/resource.c
--- linux/kernel/resource.c Sat Dec 30 20:00:41 1995
+++ linux-2.0.29/kernel/resource.c Sat Feb 8 06:56:18 1997
@@ -14,6 +14,7 @@
#include <linux/ioport.h>

#define IOTABLE_SIZE 64
+#define MEMTABLE_SIZE 64

typedef struct resource_entry_t {
u_long from, num;
@@ -22,18 +23,19 @@
} 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)
+int get_resource_list(resource_entry_t *p, char *buf)
{
- resource_entry_t *p;
int len = 0;

- for (p = iolist.next; (p) && (len < 4000); p = p->next)
+ for (; (p) && (len < 4000); p = p->next)
len += sprintf(buf+len, "%04lx-%04lx : %s\n",
p->from, p->from+p->num-1, p->name);
if (p)
@@ -41,6 +43,17 @@
return len;
}

+int get_ioport_list(char *buf)
+{
+ return get_resource_list(iolist.next, buf);
+}
+
+int get_memzone_list(char *buf)
+{
+ return get_resource_list(memlist.next, buf);
+}
+
+
/*
* The workhorse function: find where to put a new entry
*/
@@ -67,39 +80,50 @@
}

/*
- * Call this from the device driver to register the ioport region.
+ * Call this from the device driver to register the ioport region or memzone.
*/
-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];
+ 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, IOTABLE_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 +135,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,6 +154,11 @@
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)
{
@@ -126,4 +166,12 @@

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

--------------------------------------------------------------------------

Michel "Walken" LESPINASSE - Student at Ecole Centrale Paris (France)
www Email : walken@via.ecp.fr
(o o) VideoLan project : http://videolan.via.ecp.fr/
------oOO--(_)--OOo-------------------------------------------------------
Yow ! 1135 KB/s remote host TCP bandwidth over 10Mb/s ethernet. Beat that!