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

📄 i810_rng.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
字号:
/*	Hardware driver for Intel i810 Random Number Generator (RNG)	Copyright 2000,2001 Jeff Garzik <jgarzik@mandrakesoft.com>	Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>	Driver Web site:  http://sourceforge.net/projects/gkernel/	Please read Documentation/i810_rng.txt for details on use.	----------------------------------------------------------	This software may be used and distributed according to the terms        of the GNU General Public License, incorporated herein by reference. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/interrupt.h>#include <linux/spinlock.h>#include <linux/random.h>#include <linux/miscdevice.h>#include <linux/smp_lock.h>#include <linux/mm.h>#include <asm/io.h>#include <asm/uaccess.h>/* * core module and version information */#define RNG_VERSION "0.9.6"#define RNG_MODULE_NAME "i810_rng"#define RNG_DRIVER_NAME   RNG_MODULE_NAME " hardware driver " RNG_VERSION#define PFX RNG_MODULE_NAME ": "/* * debugging macros */#undef RNG_DEBUG /* define to enable copious debugging info */#ifdef RNG_DEBUG/* note: prints function name for you */#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)#else#define DPRINTK(fmt, args...)#endif#undef RNG_NDEBUG        /* define to disable lightweight runtime checks */#ifdef RNG_NDEBUG#define assert(expr)#else#define assert(expr) \        if(!(expr)) {                                   \        printk( "Assertion failed! %s,%s,%s,line=%d\n", \        #expr,__FILE__,__FUNCTION__,__LINE__);          \        }#endif/* * RNG registers (offsets from rng_mem) */#define RNG_HW_STATUS			0#define		RNG_PRESENT		0x40#define		RNG_ENABLED		0x01#define RNG_STATUS			1#define		RNG_DATA_PRESENT	0x01#define RNG_DATA			2/* * Magic address at which Intel PCI bridges locate the RNG */#define RNG_ADDR			0xFFBC015F#define RNG_ADDR_LEN			3#define RNG_MISCDEV_MINOR		183 /* official *//* * various RNG status variables.  they are globals * as we only support a single RNG device */static void *rng_mem;			/* token to our ioremap'd RNG register area */static struct semaphore rng_open_sem;	/* Semaphore for serializing rng_open/release *//* * inlined helper functions for accessing RNG registers */static inline u8 rng_hwstatus (void){	assert (rng_mem != NULL);	return readb (rng_mem + RNG_HW_STATUS);}static inline u8 rng_hwstatus_set (u8 hw_status){	assert (rng_mem != NULL);	writeb (hw_status, rng_mem + RNG_HW_STATUS);	return rng_hwstatus ();}static inline int rng_data_present (void){	assert (rng_mem != NULL);	return (readb (rng_mem + RNG_STATUS) & RNG_DATA_PRESENT) ? 1 : 0;}static inline int rng_data_read (void){	assert (rng_mem != NULL);	return readb (rng_mem + RNG_DATA);}/* * rng_enable - enable the RNG hardware */static int rng_enable (void){	int rc = 0;	u8 hw_status, new_status;	DPRINTK ("ENTER\n");	hw_status = rng_hwstatus ();	if ((hw_status & RNG_ENABLED) == 0) {		new_status = rng_hwstatus_set (hw_status | RNG_ENABLED);		if (new_status & RNG_ENABLED)			printk (KERN_INFO PFX "RNG h/w enabled\n");		else {			printk (KERN_ERR PFX "Unable to enable the RNG\n");			rc = -EIO;		}	}	DPRINTK ("EXIT, returning %d\n", rc);	return rc;}/* * rng_disable - disable the RNG hardware */static void rng_disable(void){	u8 hw_status, new_status;	DPRINTK ("ENTER\n");	hw_status = rng_hwstatus ();	if (hw_status & RNG_ENABLED) {		new_status = rng_hwstatus_set (hw_status & ~RNG_ENABLED);			if ((new_status & RNG_ENABLED) == 0)			printk (KERN_INFO PFX "RNG h/w disabled\n");		else {			printk (KERN_ERR PFX "Unable to disable the RNG\n");		}	}	DPRINTK ("EXIT\n");}static int rng_dev_open (struct inode *inode, struct file *filp){	int rc;	if ((filp->f_mode & FMODE_READ) == 0)		return -EINVAL;	if (filp->f_mode & FMODE_WRITE)		return -EINVAL;	/* wait for device to become free */	if (filp->f_flags & O_NONBLOCK) {		if (down_trylock (&rng_open_sem))			return -EAGAIN;	} else {		if (down_interruptible (&rng_open_sem))			return -ERESTARTSYS;	}	rc = rng_enable ();	if (rc) {		up (&rng_open_sem);		return rc;	}	return 0;}static int rng_dev_release (struct inode *inode, struct file *filp){	rng_disable ();	up (&rng_open_sem);	return 0;}static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size,			     loff_t * offp){	static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED;	int have_data;	u8 data = 0;	ssize_t ret = 0;	while (size) {		spin_lock (&rng_lock);		have_data = 0;		if (rng_data_present ()) {			data = rng_data_read ();			have_data = 1;		}		spin_unlock (&rng_lock);		if (have_data) {			if (put_user (data, buf++)) {				ret = ret ? : -EFAULT;				break;			}			size--;			ret++;		}		if (filp->f_flags & O_NONBLOCK)			return ret ? : -EAGAIN;		current->state = TASK_INTERRUPTIBLE;		schedule_timeout(1);		if (signal_pending (current))			return ret ? : -ERESTARTSYS;	}	return ret;}static struct file_operations rng_chrdev_ops = {	owner:		THIS_MODULE,	open:		rng_dev_open,	release:	rng_dev_release,	read:		rng_dev_read,};static struct miscdevice rng_miscdev = {	RNG_MISCDEV_MINOR,	RNG_MODULE_NAME,	&rng_chrdev_ops,};/* * rng_init_one - look for and attempt to init a single RNG */static int __init rng_init_one (struct pci_dev *dev){	int rc;	u8 hw_status;	DPRINTK ("ENTER\n");	rc = misc_register (&rng_miscdev);	if (rc) {		printk (KERN_ERR PFX "cannot register misc device\n");		DPRINTK ("EXIT, returning %d\n", rc);		goto err_out;	}	rng_mem = ioremap (RNG_ADDR, RNG_ADDR_LEN);	if (rng_mem == NULL) {		printk (KERN_ERR PFX "cannot ioremap RNG Memory\n");		DPRINTK ("EXIT, returning -EBUSY\n");		rc = -EBUSY;		goto err_out_free_miscdev;	}	/* Check for Intel 82802 */	hw_status = rng_hwstatus ();	if ((hw_status & RNG_PRESENT) == 0) {		printk (KERN_ERR PFX "RNG not detected\n");		DPRINTK ("EXIT, returning -ENODEV\n");		rc = -ENODEV;		goto err_out_free_map;	}	/* turn RNG h/w off, if it's on */	if (hw_status & RNG_ENABLED)		hw_status = rng_hwstatus_set (hw_status & ~RNG_ENABLED);	if (hw_status & RNG_ENABLED) {		printk (KERN_ERR PFX "cannot disable RNG, aborting\n");		goto err_out_free_map;	}	DPRINTK ("EXIT, returning 0\n");	return 0;err_out_free_map:	iounmap (rng_mem);err_out_free_miscdev:	misc_deregister (&rng_miscdev);err_out:	return rc;}/* * Data for PCI driver interface * * This data only exists for exporting the supported * PCI ids via MODULE_DEVICE_TABLE.  We do not actually * register a pci_driver, because someone else might one day * want to register another driver on the same PCI id. */static struct pci_device_id rng_pci_tbl[] __initdata = {	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, },	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, },	{ 0x8086, 0x1130, PCI_ANY_ID, PCI_ANY_ID, },	{ 0, },};MODULE_DEVICE_TABLE (pci, rng_pci_tbl);MODULE_AUTHOR("Jeff Garzik, Philipp Rumpf, Matt Sottek");MODULE_DESCRIPTION("Intel i8xx chipset Random Number Generator (RNG) driver");MODULE_LICENSE("GPL");/* * rng_init - initialize RNG module */static int __init rng_init (void){	int rc;	struct pci_dev *pdev;	DPRINTK ("ENTER\n");	init_MUTEX (&rng_open_sem);	pci_for_each_dev(pdev) {		if (pci_match_device (rng_pci_tbl, pdev) != NULL)			goto match;	}	DPRINTK ("EXIT, returning -ENODEV\n");	return -ENODEV;match:	rc = rng_init_one (pdev);	if (rc)		return rc;	printk (KERN_INFO RNG_DRIVER_NAME " loaded\n");	DPRINTK ("EXIT, returning 0\n");	return 0;}/* * rng_init - shutdown RNG module */static void __exit rng_cleanup (void){	DPRINTK ("ENTER\n");	misc_deregister (&rng_miscdev);	iounmap (rng_mem);	DPRINTK ("EXIT\n");}module_init (rng_init);module_exit (rng_cleanup);

⌨️ 快捷键说明

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