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

📄 pci_hotplug_core.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * PCI HotPlug Controller Core * * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (c) 2001 IBM Corp. * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Send feedback to <greg@kroah.com> * */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/list.h>#include <linux/pagemap.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/init.h>#include <linux/pci.h>#include <asm/uaccess.h>#include "pci_hotplug.h"#if !defined(CONFIG_HOTPLUG_PCI_MODULE)	#define MY_NAME	"pci_hotplug"#else	#define MY_NAME	THIS_MODULE->name#endif#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: "__FUNCTION__": " fmt , MY_NAME , ## arg); } while (0)#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)/* local variables */static int debug;#define DRIVER_VERSION	"0.3"#define DRIVER_AUTHOR	"Greg Kroah-Hartman <greg@kroah.com>"#define DRIVER_DESC	"PCI Hot Plug PCI Core"///////////////////////////////////////////////////////////////////* Random magic number */#define PCIHPFS_MAGIC 0x52454541struct hotplug_slot_core {	struct dentry	*dir_dentry;	struct dentry	*power_dentry;	struct dentry	*attention_dentry;	struct dentry	*latch_dentry;	struct dentry	*adapter_dentry;	struct dentry	*test_dentry;};static struct super_operations pcihpfs_ops;static struct address_space_operations pcihpfs_aops;static struct file_operations pcihpfs_dir_operations;static struct file_operations default_file_operations;static struct inode_operations pcihpfs_dir_inode_operations;static struct vfsmount *pcihpfs_mount;	/* one of the mounts of our fs for reference counting */static int pcihpfs_mount_count;		/* times we have mounted our fs */static spinlock_t mount_lock;		/* protects our mount_count */static spinlock_t list_lock;LIST_HEAD(pci_hotplug_slot_list);static int pcihpfs_statfs (struct super_block *sb, struct statfs *buf){	buf->f_type = PCIHPFS_MAGIC;	buf->f_bsize = PAGE_CACHE_SIZE;	buf->f_namelen = 255;	return 0;}static struct dentry *pcihpfs_lookup (struct inode *dir, struct dentry *dentry){	d_add(dentry, NULL);	return NULL;}static struct inode *pcihpfs_get_inode (struct super_block *sb, int mode, int dev){	struct inode *inode = new_inode(sb);	if (inode) {		inode->i_mode = mode;		inode->i_uid = current->fsuid;		inode->i_gid = current->fsgid;		inode->i_blksize = PAGE_CACHE_SIZE;		inode->i_blocks = 0;		inode->i_rdev = NODEV;		inode->i_mapping->a_ops = &pcihpfs_aops;		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;		switch (mode & S_IFMT) {		default:			init_special_inode(inode, mode, dev);			break;		case S_IFREG:			inode->i_fop = &default_file_operations;			break;		case S_IFDIR:			inode->i_op = &pcihpfs_dir_inode_operations;			inode->i_fop = &pcihpfs_dir_operations;			break;		}	}	return inode; }static int pcihpfs_mknod (struct inode *dir, struct dentry *dentry, int mode, int dev){	struct inode *inode = pcihpfs_get_inode(dir->i_sb, mode, dev);	int error = -ENOSPC;	if (inode) {		d_instantiate(dentry, inode);		dget(dentry);		error = 0;	}	return error;}static int pcihpfs_mkdir (struct inode *dir, struct dentry *dentry, int mode){	return pcihpfs_mknod (dir, dentry, mode | S_IFDIR, 0);}static int pcihpfs_create (struct inode *dir, struct dentry *dentry, int mode){ 	return pcihpfs_mknod (dir, dentry, mode | S_IFREG, 0);}static int pcihpfs_link (struct dentry *old_dentry, struct inode *dir,			 struct dentry *dentry){	struct inode *inode = old_dentry->d_inode;	if(S_ISDIR(inode->i_mode))		return -EPERM;	inode->i_nlink++;	atomic_inc(&inode->i_count); 	dget(dentry);	d_instantiate(dentry, inode);	return 0;}static inline int pcihpfs_positive (struct dentry *dentry){	return dentry->d_inode && !d_unhashed(dentry);}static int pcihpfs_empty (struct dentry *dentry){	struct list_head *list;	spin_lock(&dcache_lock);	list_for_each(list, &dentry->d_subdirs) {		struct dentry *de = list_entry(list, struct dentry, d_child);		if (pcihpfs_positive(de)) {			spin_unlock(&dcache_lock);			return 0;		}	}	spin_unlock(&dcache_lock);	return 1;}static int pcihpfs_unlink (struct inode *dir, struct dentry *dentry){	int error = -ENOTEMPTY;	if (pcihpfs_empty(dentry)) {		struct inode *inode = dentry->d_inode;		inode->i_nlink--;		dput(dentry);		error = 0;	}	return error;}static int pcihpfs_rename (struct inode *old_dir, struct dentry *old_dentry,			   struct inode *new_dir, struct dentry *new_dentry){	int error = -ENOTEMPTY;	if (pcihpfs_empty(new_dentry)) {		struct inode *inode = new_dentry->d_inode;		if (inode) {			inode->i_nlink--;			dput(new_dentry);		}		error = 0;	}	return error;}#define pcihpfs_rmdir pcihpfs_unlink/* default file operations */static ssize_t default_read_file (struct file *file, char *buf, size_t count, loff_t *ppos){	dbg ("\n");	return 0;}static ssize_t default_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos){	dbg ("\n");	return count;}static loff_t default_file_lseek (struct file *file, loff_t offset, int orig){	loff_t retval = -EINVAL;	switch(orig) {	case 0:		if (offset > 0) {			file->f_pos = offset;			retval = file->f_pos;		} 		break;	case 1:		if ((offset + file->f_pos) > 0) {			file->f_pos += offset;			retval = file->f_pos;		} 		break;	default:		break;	}	return retval;}static int default_open (struct inode *inode, struct file *filp){	if (inode->u.generic_ip)		filp->private_data = inode->u.generic_ip;	return 0;}static int default_sync_file (struct file *file, struct dentry *dentry, int datasync){	return 0;}static struct address_space_operations pcihpfs_aops = {};static struct file_operations pcihpfs_dir_operations = {	read:		generic_read_dir,	readdir:	dcache_readdir,	fsync:		default_sync_file,};static struct file_operations default_file_operations = {	read:		default_read_file,	write:		default_write_file,	open:		default_open,	llseek:		default_file_lseek,	fsync:		default_sync_file,	mmap:		generic_file_mmap,};/* file ops for the "power" files */static ssize_t power_read_file (struct file *file, char *buf, size_t count, loff_t *offset);static ssize_t power_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);static struct file_operations power_file_operations = {	read:		power_read_file,	write:		power_write_file,	open:		default_open,	llseek:		default_file_lseek,	fsync:		default_sync_file,	mmap:		generic_file_mmap,};/* file ops for the "attention" files */static ssize_t attention_read_file (struct file *file, char *buf, size_t count, loff_t *offset);static ssize_t attention_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);static struct file_operations attention_file_operations = {	read:		attention_read_file,	write:		attention_write_file,	open:		default_open,	llseek:		default_file_lseek,	fsync:		default_sync_file,	mmap:		generic_file_mmap,};/* file ops for the "latch" files */static ssize_t latch_read_file (struct file *file, char *buf, size_t count, loff_t *offset);static struct file_operations latch_file_operations = {	read:		latch_read_file,	write:		default_write_file,	open:		default_open,	llseek:		default_file_lseek,	fsync:		default_sync_file,	mmap:		generic_file_mmap,};/* file ops for the "presence" files */static ssize_t presence_read_file (struct file *file, char *buf, size_t count, loff_t *offset);static struct file_operations presence_file_operations = {	read:		presence_read_file,	write:		default_write_file,	open:		default_open,	llseek:		default_file_lseek,	fsync:		default_sync_file,	mmap:		generic_file_mmap,};/* file ops for the "test" files */static ssize_t test_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);static struct file_operations test_file_operations = {	read:		default_read_file,	write:		test_write_file,	open:		default_open,	llseek:		default_file_lseek,	fsync:		default_sync_file,	mmap:		generic_file_mmap,};static struct inode_operations pcihpfs_dir_inode_operations = {	create:		pcihpfs_create,	lookup:		pcihpfs_lookup,	link:		pcihpfs_link,	unlink:		pcihpfs_unlink,	mkdir:		pcihpfs_mkdir,	rmdir:		pcihpfs_rmdir,	mknod:		pcihpfs_mknod,	rename:		pcihpfs_rename,};static struct super_operations pcihpfs_ops = {	statfs:		pcihpfs_statfs,	put_inode:	force_delete,};static struct super_block *pcihpfs_read_super (struct super_block *sb, void *data, int silent){	struct inode *inode;	struct dentry *root;	sb->s_blocksize = PAGE_CACHE_SIZE;	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;	sb->s_magic = PCIHPFS_MAGIC;	sb->s_op = &pcihpfs_ops;	inode = pcihpfs_get_inode(sb, S_IFDIR | 0755, 0);	if (!inode) {		dbg("%s: could not get inode!\n",__FUNCTION__);		return NULL;	}	root = d_alloc_root(inode);	if (!root) {		dbg("%s: could not get root dentry!\n",__FUNCTION__);		iput(inode);		return NULL;	}	sb->s_root = root;	return sb;}static DECLARE_FSTYPE(pcihpfs_fs_type, "pcihpfs", pcihpfs_read_super, FS_SINGLE | FS_LITTER);static int get_mount (void){	struct vfsmount *mnt;	spin_lock (&mount_lock);	if (pcihpfs_mount) {		mntget(pcihpfs_mount);		++pcihpfs_mount_count;		spin_unlock (&mount_lock);		goto go_ahead;	}	spin_unlock (&mount_lock);	mnt = kern_mount (&pcihpfs_fs_type);	if (IS_ERR(mnt)) {		err ("could not mount the fs...erroring out!\n");		return -ENODEV;	}	spin_lock (&mount_lock);	if (!pcihpfs_mount) {		pcihpfs_mount = mnt;		++pcihpfs_mount_count;		spin_unlock (&mount_lock);		goto go_ahead;	}	mntget(pcihpfs_mount);	++pcihpfs_mount_count;	spin_unlock (&mount_lock);	mntput(mnt);go_ahead:	dbg("pcihpfs_mount_count = %d\n", pcihpfs_mount_count);	return 0;}static void remove_mount (void){	struct vfsmount *mnt;	spin_lock (&mount_lock);	mnt = pcihpfs_mount;	--pcihpfs_mount_count;	if (!pcihpfs_mount_count)		pcihpfs_mount = NULL;	spin_unlock (&mount_lock);	mntput(mnt);	dbg("pcihpfs_mount_count = %d\n", pcihpfs_mount_count);}/** * pcihpfs_create_by_name - create a file, given a name * @name:	name of file * @mode:	type of file * @parent:	dentry of directory to create it in * @dentry:	resulting dentry of file * * There is a bit of overhead in creating a file - basically, we  * have to hash the name of the file, then look it up. This will * prevent files of the same name.  * We then call the proper vfs_ function to take care of all the  * file creation details.  * This function handles both regular files and directories. */static int pcihpfs_create_by_name (const char *name, mode_t mode,				   struct dentry *parent, struct dentry **dentry){	struct dentry *d = NULL;	struct qstr qstr;	int error;	/* If the parent is not specified, we create it in the root.	 * We need the root dentry to do this, which is in the super 	 * block. A pointer to that is in the struct vfsmount that we	 * have around.	 */	if (!parent ) {		if (pcihpfs_mount && pcihpfs_mount->mnt_sb) {			parent = pcihpfs_mount->mnt_sb->s_root;		}	}	if (!parent) {		dbg("Ah! can not find a parent!\n");		return -EFAULT;	}	*dentry = NULL;	qstr.name = name;	qstr.len = strlen(name); 	qstr.hash = full_name_hash(name,qstr.len);	parent = dget(parent);	down(&parent->d_inode->i_sem);	d = lookup_hash(&qstr,parent);	error = PTR_ERR(d);	if (!IS_ERR(d)) {		switch(mode & S_IFMT) {		case 0: 		case S_IFREG:			error = vfs_create(parent->d_inode,d,mode);			break;		case S_IFDIR:			error = vfs_mkdir(parent->d_inode,d,mode);			break;		default:			err("cannot create special files\n");		}		*dentry = d;	}	up(&parent->d_inode->i_sem);	dput(parent);	return error;}static struct dentry *fs_create_file (const char *name, mode_t mode,				      struct dentry *parent, void *data,				      struct file_operations *fops){	struct dentry *dentry;	int error;	dbg("creating file '%s'\n",name);	error = pcihpfs_create_by_name(name,mode,parent,&dentry);	if (error) {		dentry = NULL;	} else {		if (dentry->d_inode) {			if (data)				dentry->d_inode->u.generic_ip = data;			if (fops)			dentry->d_inode->i_fop = fops;		}	}	return dentry;}static void fs_remove_file (struct dentry *dentry){	struct dentry *parent = dentry->d_parent;		if (!parent || !parent->d_inode)		return;	down(&parent->d_inode->i_sem);	if (pcihpfs_positive(dentry)) {		if (dentry->d_inode) {			if (S_ISDIR(dentry->d_inode->i_mode))				vfs_rmdir(parent->d_inode,dentry);			else				vfs_unlink(parent->d_inode,dentry);		}		dput(dentry);	}	up(&parent->d_inode->i_sem);}#define GET_STATUS(name)	\static int get_##name##_status (struct hotplug_slot *slot, u8 *value)	\{									\	struct hotplug_slot_ops *ops = slot->ops;			\	int retval = 0;							\	if (ops->owner)							\		__MOD_INC_USE_COUNT(ops->owner);			\	if (ops->get_##name##_status)					\		retval = ops->get_##name##_status (slot, value);	\	else								\		*value = slot->info->name##_status;			\

⌨️ 快捷键说明

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