#include <linux/config.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/proc_fs.h> #include <linux/mm.h> #include <linux/major.h> #include <asm/segment.h> #include <asm/uaccess.h> #include <asm/io.h> #include <linux/kernel.h> #include <linux/bigphysarea.h> #define lnxuio_major (42) /* uio dev major number */ #define lnxuio_allocpage _IOW('x',7,size_t) #define lnxuio_deallocpage _IOW('x',8,size_t) #define lnxuio_getptr _IOW('x',9,size_t) #define UIO_MAX_BUFFERS 100 #define lnxuio_fail 0 #define lnxuio_ok 1 /* * contiguous memory block descriptor */ typedef struct uio_mem_t { unsigned long kaddr; /* kernel virtual address */ unsigned long uaddr; /* user virtual address */ unsigned long paddr; /* physical address */ int size; /* size in bytes */ } uio_mem_t; #define COUNT 100 /* max number of memory areas */ static int current_count = 0; static int total_count = 0; /* * global bookkeeping arrays (common to all processes ..) */ static void *addr[COUNT]; static int size[COUNT]; static int upid[COUNT]; static int lnxuio_open( struct inode* ino, struct file* filep) { MOD_INC_USE_COUNT; return 0; } static int lnxuio_close( struct inode* ino, struct file* filep) { MOD_DEC_USE_COUNT; } static int lnxuio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { unsigned int cur_minor = MINOR(inode->i_rdev); int i; int found_flag; int pagecount; struct uio_mem_t l_uio; copy_from_user(&l_uio , (struct uio_mem_t *) arg, sizeof(struct uio_mem_t)); switch (cmd) { case lnxuio_allocpage : pagecount = (int)((l_uio.size -1)/4096 + 1); /* pages */ if (total_count >= COUNT) { return -ENFILE; } /* find a free slot */ for (i=0; i < COUNT; i++) if (size[i]==-1) break; current_count = i; addr[current_count] = bigphysarea_alloc_pages(pagecount, 0, GFP_KERNEL); if (addr[current_count] == 0) { return -ENOMEM; } l_uio.uaddr = (unsigned)virt_to_bus((unsigned*)addr[current_count]); l_uio.paddr = (unsigned)virt_to_phys((unsigned*)addr[current_count]); l_uio.kaddr = (unsigned)addr[current_count]; size[current_count] = pagecount; upid[current_count] = current->pid; total_count++; copy_to_user((struct uio_mem_t *) arg, &l_uio, sizeof(struct uio_mem_t)); return 0; break; case lnxuio_deallocpage : found_flag = 0; for (i = 0; i < COUNT; i++) { if ( (unsigned)addr[i] == l_uio.kaddr) { bigphysarea_free_pages(addr[i]); current_count = i; found_flag = 1; } } if (found_flag == 0) { return -ENXIO; } size[current_count] = -1; total_count--; return 0; break; default : return -EINVAL; } int uio_table_read (char *buf, char **start, off_t offset, int len, int unused) { int i; len=0; len+=sprintf(buf+len,"PhysAddr \t Size \t Pid \t lnxuio v1.2\n"); for (i = 0; i < COUNT; i++) if (size[i] != -1) { len+=sprintf(buf+len,"%x\t",(unsigned)addr[i]); len+=sprintf(buf+len,"%d \t",size[i]); len+=sprintf(buf+len,"%d \n",upid[i]); } return len; } static struct file_operations fops = { ioctl: lnxuio_ioctl, open: lnxuio_open, release: lnxuio_close, } static struct proc_dir_entry uio_proc_file = { 0,9 ,"uio_table", S_IFREG | S_IRUGO,1,0,0,0, NULL, &uio_table_read}; int init_module(void) { int i; if (register_chrdev(lnxuio_major, "physmem-manager", &fops)) { printk(" lnxuio: register physmem-manager failed. \n"); return -EIO; } proc_register(&proc_root, &uio_proc_file) ; for (i = 0; i < COUNT; i++) size[i] = -1; printk(" lnxuio: physmem-manager loaded; dev major %d\n",lnxuio_major); return 0; } void cleanup_module(void) { int i; if (unregister_chrdev(lnxuio_major, "physmem-manager") != 0) { printk(" lnxuio: cleanup_module failed\n"); } else { for (i=0; i < COUNT; i++) if (size[i] != -1) { bigphysarea_free_pages(addr[i]); } proc_unregister(&proc_root,uio_proc_file.low_ino); printk(" lnxuio: physmem-manager removed\n"); } }
Bigphysarea is a driver which allocates a big piece of memory during boottime and returns the entire piece or parts of it to a requesting driver. The driver is not created by Pauline, but is maintained by Pauline for the newer kernels.
Some hardware requires memory in physical continuous blocks. Howevery, the longer your Linux system is running, the more main memory is getting allocated and freed in different sizes. This leads to the fenomenen called 'memory fragmentation'. And the end result of this all is a machine which has enough memory left, but scattered all over the place, thereby failing our drivers with an 'out of memory'. Prime examples of these hardware are soundcards which need to be initialized and the above mentioned framegrabber.
Bytes Timestamp Filename ________ ____________________ ____________________________ 7136 Aug 21 14:06:29 1998 bigphysarea-2.1.116.tar.gz 7165 Feb 17 11:18:40 1999 bigphysarea-2.2.1.tar.gz 7198 May 20 22:56:11 1999 bigphysarea-2.2.9.tar.gz 7173 Oct 23 10:22:54 1999 bigphysarea-2.2.12.tar.gz 6676 Dec 28 11:29:02 1999 bigphysarea-2.3.34.tar.gz 6787 Jan 24 15:10:10 2000 bigphysarea-2.3.40.tar.gz 7158 Oct 20 09:11:15 2000 bigphysarea-2.2.13.tar.gz 7473 Oct 20 09:11:59 2000 bigphysarea-2.4.0.tar.gz [LATEST]When there is no patch for the exact kernel version you are running, try the patch with the lower number. Changes are it will work without problems.
cd DIS/src/kernel tar zxvof bigphysarea-2.x.x.tar.gz cp bigphysarea-2.x.x/bigphysarea-patch /usr/src/linux cd /usr/src/linux patch -p1 < bigphysarea-patch
Enables kernel support for reserving large areas of physical memory at boot-time for use by certain device drivers (such as video framegrabbers, etc.) which require it. To use this feature, boot the kernel with the boot-time option 'bigphysarea=nnn' where 'nnn' is the number of pages (a page is usually 4K) to reserve.
Update your /etc/lilo.conf (or other boot selection system you use) to include the following lines: image = /vmlinux label = Linux append = "bigphysarea=1024" (Other values for the size of the bigphys area can be chosen, as required - `1024' equals 4096K, or 4M. Run lilo to install the new loader and kernel and reboot. lilo reboot
cat /proc/bigphysarea This should return something like: Big physical area, size 4096 kB free list: used list: number of blocks: 1 0 size of largest block: 4096 kB 0 kB total: 4096 kB 0 kB