⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mem.c

📁 arm平台上的uclinux系统全部源代码
💻 C
字号:
/* *  linux/arch/arm/drivers/char/mem.c * *  Copyright (C) 1991, 1992  Linus Torvalds * *  Modifications for ARM Copyright (C) 1995, 1996 Russell King */#include <linux/config.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/tty.h>#include <linux/miscdevice.h>#include <linux/tpqic02.h>#include <linux/malloc.h>#include <linux/mman.h>#include <linux/mm.h>#include <linux/random.h>#include <asm/segment.h>#include <asm/io.h>#include <asm/pgtable.h>extern int con_fb_read(char *buf, unsigned long pos, int count);extern int con_fb_write(const char *buf, unsigned long pos, int count);extern int con_fb_mmap(unsigned long vma_start, unsigned long vma_offset,			unsigned long vma_end, pgprot_t prot);#ifdef CONFIG_SOUNDvoid soundcard_init(void);#endifstatic int read_ram(struct inode * inode, struct file * file, char * buf, int count){	return -EIO;}static int write_ram(struct inode * inode, struct file * file, const char * buf, int count){	return -EIO;}static int read_mem(struct inode * inode, struct file * file, char * buf, int count){	unsigned long p = file->f_pos;	p += PAGE_OFFSET;	if (count < 0)		return -EINVAL;	if (MAP_NR(p) >= max_mapnr)		return 0;	if (count > high_memory - p)		count = high_memory - p;	memcpy_tofs(buf,(void *) p,count);	file->f_pos += count;	return count;}static int write_mem(struct inode * inode, struct file * file, const char * buf, int count){	unsigned long p = file->f_pos;	p += PAGE_OFFSET;	if (count < 0)		return -EINVAL;	if (MAP_NR(p) >= max_mapnr)		return 0;	if (count > high_memory - p)		count = high_memory - p;	memcpy_fromfs((void *) p,buf,count);	file->f_pos += count;	return count;}static int mmap_mem(struct inode * inode, struct file * file, struct vm_area_struct * vma){#ifndef NO_MM	if (vma->vm_offset & ~PAGE_MASK)		return -ENXIO;	/*	 * This disables memory caching/buffering	 */#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110)	if (MAP_NR(vma->vm_offset) >= max_mapnr)		pgprot_val(vma->vm_page_prot) &= ~(PTE_CACHEABLE | PTE_BUFFERABLE);#endif	if (remap_page_range(vma->vm_start, vma->vm_offset, vma->vm_end - vma->vm_start, vma->vm_page_prot))		return -EAGAIN;	vma->vm_inode = inode;	inode->i_count++;#else	vma->vm_start = file->f_pos+PAGE_OFFSET+vma->vm_offset;#endif /* !NO_MM */		return 0;}static int read_fb(struct inode * inode, struct file *file, char *buf, int count){	if (count < 0)		return -EINVAL;	count = con_fb_read(buf, file->f_pos, count);	if (count > 0)		file->f_pos += count;	return count;}static int write_fb(struct inode * inode, struct file * file, const char * buf, int count){	if (count < 0)		return -EINVAL;	count = con_fb_write(buf, file->f_pos, count);	if (count > 0)		file->f_pos += count;	return count;}static int mmap_fb(struct inode * inode, struct file * file, struct vm_area_struct * vma){	int ret;	#ifndef NO_MM	if (vma->vm_offset & ~PAGE_MASK)		return -ENXIO;	ret = con_fb_mmap(vma->vm_start, vma->vm_offset, vma->vm_end, vma->vm_page_prot);	if (ret)		return ret;	vma->vm_inode = inode;	inode->i_count ++;#else	ret = con_fb_mmap(vma->vm_start, vma->vm_offset, vma->vm_end, __pgprot(0));	if (ret)		return ret;#endif		return 0;}static int read_kmem(struct inode *inode, struct file *file, char *buf, int count){	int read1, read2;	read1 = read_mem(inode, file, buf, count);	if (read1 < 0)		return read1;	read2 = vread(buf + read1, (char *) ((unsigned long) file->f_pos), count - read1);	if (read2 < 0)		return read2;	file->f_pos += read2;	return read1 + read2;}static int read_port(struct inode * inode, struct file * file,char * buf, int count){	unsigned int i = file->f_pos;	char * tmp = buf;	while (count-- > 0 && (i < 65536 || (i > 0x80000000 && i < 0x84000000))) {		put_user(inb(i),tmp);		i++;		tmp++;	}	file->f_pos = i;	return tmp-buf;}static int write_port(struct inode * inode, struct file * file, const char * buf, int count){	unsigned int i = file->f_pos;	const char * tmp = buf;	while (count-- > 0 && (i < 65536 || (i > 0x80000000 && i < 0x84000000))) {		outb(get_user(tmp),i);		i++;		tmp++;	}	file->f_pos = i;	return tmp-buf;}static int read_null(struct inode * node, struct file * file, char * buf, int count){	return 0;}static int write_null(struct inode * inode, struct file * file, const char * buf, int count){	return count;}static int read_zero(struct inode * node, struct file * file, char * buf, int count){	int left;	for (left = count; left > 0; left--) {		put_user(0,buf);		buf++;		if (need_resched)			schedule();	}	return count;}static int mmap_zero(struct inode * inode, struct file * file, struct vm_area_struct * vma){#ifndef NO_MM	if (vma->vm_flags & VM_SHARED)		return -EINVAL;	if (zeromap_page_range(vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot))		return -EAGAIN;	return 0;#else /* !NO_MM */	/* FIXME: trivial calloc() implementation is feasible */	return -ENOSYS;#endif /* !NO_MM */}static int read_full(struct inode * node, struct file * file, char * buf,int count){	file->f_pos += count;	return count;}static int write_full(struct inode * inode, struct file * file, const char * buf, int count){	return -ENOSPC;}/* * Special lseek() function for /dev/null and /dev/zero.  Most notably, you can fopen() * both devices with "a" now.  This was previously impossible.  SRB. */static int null_lseek(struct inode * inode, struct file * file, off_t offset, int orig){	return file->f_pos=0;}/* * The memory devices use the full 32/64 bits of the offset, and so we cannot * check against negative addresses: they are ok. The return value is weird, * though, in that case (0). * * also note that seeking relative to the "end of file" isn't supported: * it has no meaning, so it returns -EINVAL. */static int memory_lseek(struct inode * inode, struct file * file, off_t offset, int orig){	switch (orig) {		case 0:			file->f_pos = offset;			return file->f_pos;		case 1:			file->f_pos += offset;			return file->f_pos;		default:			return -EINVAL;	}	if (file->f_pos < 0)		return 0;	return file->f_pos;}#define write_kmem	write_mem#define mmap_kmem	mmap_mem#define zero_lseek	null_lseek#define write_zero	write_nullstatic struct file_operations ram_fops = {	memory_lseek,	read_ram,	write_ram,	NULL,		/* ram_readdir */	NULL,		/* ram_select */	NULL,		/* ram_ioctl */	NULL,		/* ram_mmap */	NULL,		/* no special open code */	NULL,		/* no special release code */	NULL		/* fsync */};static struct file_operations mem_fops = {	memory_lseek,	read_mem,	write_mem,	NULL,		/* mem_readdir */	NULL,		/* mem_select */	NULL,		/* mem_ioctl */	mmap_mem,	NULL,		/* no special open code */	NULL,		/* no special release code */	NULL		/* fsync */};static struct file_operations fb_fops = {	memory_lseek,	read_fb,	write_fb,	NULL,		/* mem_readdir */	NULL,		/* mem_select */	NULL,		/* mem_ioctl */	mmap_fb,	NULL,		/* no special open code */	NULL,		/* no special release code */	NULL		/* fsync */};static struct file_operations kmem_fops = {	memory_lseek,	read_kmem,	write_kmem,	NULL,		/* kmem_readdir */	NULL,		/* kmem_select */	NULL,		/* kmem_ioctl */	mmap_kmem,	NULL,		/* no special open code */	NULL,		/* no special release code */	NULL		/* fsync */};static struct file_operations null_fops = {	null_lseek,	read_null,	write_null,	NULL,		/* null_readdir */	NULL,		/* null_select */	NULL,		/* null_ioctl */	NULL,		/* null_mmap */	NULL,		/* no special open code */	NULL,		/* no special release code */	NULL		/* fsync */};static struct file_operations port_fops = {	memory_lseek,	read_port,	write_port,	NULL,		/* port_readdir */	NULL,		/* port_select */	NULL,		/* port_ioctl */	NULL,		/* port_mmap */	NULL,		/* no special open code */	NULL,		/* no special release code */	NULL		/* fsync */};static struct file_operations zero_fops = {	zero_lseek,	read_zero,	write_zero,	NULL,		/* zero_readdir */	NULL,		/* zero_select */	NULL,		/* zero_ioctl */	mmap_zero,	NULL,		/* no special open code */	NULL		/* no special release code */};static struct file_operations full_fops = {	memory_lseek,	read_full,	write_full,	NULL,		/* full_readdir */	NULL,		/* full_select */	NULL,		/* full_ioctl */	NULL,		/* full_mmap */	NULL,		/* no special open code */	NULL		/* no special release code */};static int memory_open(struct inode * inode, struct file * filp){	switch (MINOR(inode->i_rdev)) {		case 0:			filp->f_op = &ram_fops;			break;		case 1:			filp->f_op = &mem_fops;			break;		case 2:			filp->f_op = &kmem_fops;			break;		case 3:			filp->f_op = &null_fops;			break;		case 4:			filp->f_op = &port_fops;			break;		case 5:			filp->f_op = &zero_fops;			break;		case 7:			filp->f_op = &full_fops;			break;		case 8:			filp->f_op = &random_fops;			break;		case 9:			filp->f_op = &urandom_fops;			break;		case 128:			filp->f_op = &fb_fops;			break;		default:			return -ENXIO;	}	if (filp->f_op && filp->f_op->open)		return filp->f_op->open(inode,filp);	return 0;}static struct file_operations memory_fops = {	NULL,		/* lseek */	NULL,		/* read */	NULL,		/* write */	NULL,		/* readdir */	NULL,		/* select */	NULL,		/* ioctl */	NULL,		/* mmap */	memory_open,	/* just a selector for the real open */	NULL,		/* release */	NULL		/* fsync */};int chr_dev_init(void){	if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))		printk("unable to get major %d for memory devs\n", MEM_MAJOR);	rand_initialize();	tty_init();#ifdef CONFIG_PRINTER	lp_init();#endif#if defined(CONFIG_MOUSE) || defined(CONFIG_SOFT_WATCHDOG)	misc_init();#endif#ifdef CONFIG_SOUND	soundcard_init();#endif	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -