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

📄 io_mem.c

📁 2440linux下的iomem操作新方法
💻 C
字号:
/* * main.c -- the bare scull char module * * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet * Copyright (C) 2001 O'Reilly & Associates * * The source code in this file can be freely used, adapted, * and redistributed in source or binary form, so long as an * acknowledgment appears in derived source files.  The citation * should list that the code comes from the book "Linux Device * Drivers" by Alessandro Rubini and Jonathan Corbet, published * by O'Reilly & Associates.   No warranty is attached; * we cannot take responsibility for errors or fitness for use. * */#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/kernel.h>	/* printk() */#include <linux/slab.h>		/* kmalloc() */#include <linux/fs.h>		/* everything... */#include <linux/errno.h>	/* error codes */#include <linux/types.h>	/* size_t */#include <linux/proc_fs.h>#include <linux/fcntl.h>	/* O_ACCMODE */#include <linux/seq_file.h>#include <linux/cdev.h>#include <linux/sched.h>  /* current and everything */#include <asm/system.h>		/* cli(), *_flags */#include <asm/uaccess.h>	/* copy_*_user */#include <asm/atomic.h>#include "IO_mem.h"		/* local definitions *//* * Our parameters which can be set at load time. */int IO_mem_major =   0;int IO_mem_minor =   0;unsigned int gpjcon_old =0;unsigned int gpjdat_old =0;unsigned int gpjup_old  =0;unsigned long io_addr;module_param(IO_mem_major, int, S_IRUGO);module_param(IO_mem_minor, int, S_IRUGO);struct IO_mem_dev *IO_mem_devices;	/* allocated in scull_init_module */static atomic_t IO_mem_available = ATOMIC_INIT(1);static spinlock_t IO_mem_lock = SPIN_LOCK_UNLOCKED;static DECLARE_WAIT_QUEUE_HEAD(IO_mem_wait);struct resource *IO_mem_resource;/* * Open and close */int IO_mem_open(struct inode *inode, struct file *filp){	struct IO_mem_dev *dev; /* device information */	spin_lock(&IO_mem_lock);	while (! atomic_dec_and_test (&IO_mem_available)) {		atomic_inc(&IO_mem_available);		spin_unlock(&IO_mem_lock);		if (filp->f_flags & O_NONBLOCK) return -EAGAIN;		if (wait_event_interruptible (IO_mem_wait, atomic_read (&IO_mem_available)))			return -ERESTARTSYS; /* tell the fs layer to handle it */				spin_lock(&IO_mem_lock);	}	spin_unlock(&IO_mem_lock);	dev = container_of(inode->i_cdev, struct IO_mem_dev, cdev);	io_addr =(unsigned long) ioremap_nocache(0x560000d0 , 0x0c); //	io_addr =(unsigned long) ioport_map(0x560000d0 , 0x0c);  /*WARNING: "ioport_map"  undefined!  Don't use it*/	printk( "io_addr : %lx\n", io_addr);	/* now trim to 0 the length of the device if open was write-only */	gpjcon_old = ioread32 (io_addr);	gpjdat_old = ioread32 (io_addr+4);	gpjup_old = ioread32 (io_addr+8);		mb();	iowrite32(0x01555555,io_addr);	iowrite32(0x1fff,io_addr+8);		wmb();	iowrite32(0x0,io_addr+4);	filp->private_data = dev; /* for other methods */	return nonseekable_open(inode, filp);          /* success */}int IO_mem_release(struct inode *inode, struct file *filp){	iowrite32((u32) gpjcon_old ,io_addr);	iowrite32((u32) gpjdat_old ,io_addr+4);	iowrite32((u32) gpjup_old ,io_addr+8);	iounmap((void *)io_addr);//	ioport_unmap((void *)io_addr);   /*WARNING: "ioport_unmap"  undefined!  Don't use it*/	atomic_inc(&IO_mem_available); /* release the device */	wake_up_interruptible_sync(&IO_mem_wait); /* awake other uid's */	return 0;}/* * The ioctl() implementation */int IO_mem_ioctl(struct inode *inode, struct file *filp,                 unsigned int cmd, unsigned long arg){	int err = 0;	int retval = 0;	unsigned int current_status;  	/*	 * extract the type and number bitfields, and don't decode	 * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()	 */	if (_IOC_TYPE(cmd) != IO_MEM_MAGIC) return -ENOTTY;	if (_IOC_NR(cmd) > IO_MEM_MAXNR) return -ENOTTY;	/*	 * the direction is a bitmask, and VERIFY_WRITE catches R/W	 * transfers. `Type' is user-oriented, while	 * access_ok is kernel-oriented, so the concept of "read" and	 * "write" is reversed	 */	if (_IOC_DIR(cmd) & _IOC_READ)		err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));	if (err) return -EFAULT;	switch(cmd) {	  case IO_MEM_0:	iowrite32(0x0,io_addr+4);	break;        	  case IO_MEM_1: 	iowrite32(0x1,io_addr+4);	break;	  case IO_MEM_2: 	iowrite32(0x2,io_addr+4);	break;	  case IO_MEM_3: 	iowrite32(0x3,io_addr+4);	break;	case IO_MEM_STATUS:	current_status = ioread32 (io_addr+4);	retval = __put_user(current_status, (unsigned int __user *)arg);	break;	  default:  /* redundant, as cmd was checked against MAXNR */		return -ENOTTY;	}	return retval;}struct file_operations IO_mem_fops = {	.owner =    THIS_MODULE,	.ioctl =    IO_mem_ioctl,	.open =     IO_mem_open,	.release =  IO_mem_release,	.llseek =		no_llseek,};/* * Finally, the module stuff *//* * The cleanup function is used to handle initialization failures as well. * Thefore, it must be careful to work correctly even if some of the items * have not been initialized */void IO_mem_cleanup_module(void){	dev_t devno = MKDEV(IO_mem_major, IO_mem_minor);	if (IO_mem_resource!=NULL) release_mem_region(0x560000d0, 0x0c);	/* Get rid of our char dev entries */	if (IO_mem_devices) {		cdev_del(&IO_mem_devices->cdev);		kfree(IO_mem_devices);	}		/* cleanup_module is never called if registering failed */	unregister_chrdev_region(devno, 1);}/* * Set up the char_dev structure for this device. */static void IO_mem_setup_cdev(struct IO_mem_dev *dev){	int err, devno = MKDEV(IO_mem_major, IO_mem_minor);    	cdev_init(&dev->cdev, &IO_mem_fops);	dev->cdev.owner = THIS_MODULE;	err = cdev_add (&dev->cdev, devno, 1);	/* Fail gracefully if need be */	if (err)		printk(KERN_NOTICE "Error %d adding IO_mem", err);}int IO_mem_init_module(void){	int result;	dev_t dev = 0;/* * Get a range of minor numbers to work with, asking for a dynamic * major unless directed otherwise at load time. */	if (IO_mem_major) {		dev = MKDEV(IO_mem_major, IO_mem_minor);		result = register_chrdev_region(dev, 1, "IO_mem");	} else {		result = alloc_chrdev_region(&dev, IO_mem_minor, 1,				"IO_mem");		IO_mem_major = MAJOR(dev);	}	if (result < 0) {		printk(KERN_WARNING "IO_mem: can't get major %d\n", IO_mem_major);		return result;	}        /* 	 * allocate the devices -- we can't have them static, as the number	 * can be specified at load time	 */	IO_mem_devices = kmalloc(sizeof(struct IO_mem_dev), GFP_KERNEL);	if (!IO_mem_devices) {		result = -ENOMEM;		goto fail;  /* Make this more graceful */	}	memset(IO_mem_devices, 0, sizeof(struct IO_mem_dev));        /* Initialize each device. */		init_MUTEX(&IO_mem_devices->sem);		 IO_mem_setup_cdev(IO_mem_devices);	if ((IO_mem_resource=request_mem_region(0x560000d0, 0x0c,"IO_mem"))==NULL) 		goto fail;	return 0; /* succeed */  fail:	IO_mem_cleanup_module();	return result;}module_init(IO_mem_init_module);module_exit(IO_mem_cleanup_module);MODULE_AUTHOR("Tekkaman Ninja");MODULE_LICENSE("Dual BSD/GPL");

⌨️ 快捷键说明

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