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

📄 ibmasmfs.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * IBM ASM Service Processor Device Driver * * 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.  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Copyright (C) IBM Corporation, 2004 * * Author: Max Asb鯿k <amax@us.ibm.com>  * *//* * Parts of this code are based on an article by Jonathan Corbet  * that appeared in Linux Weekly News. *//* * The IBMASM file virtual filesystem. It creates the following hierarchy * dymamically when mounted from user space: * *    /ibmasm *    |-- 0 *    |   |-- command *    |   |-- event *    |   |-- reverse_heartbeat *    |   `-- remote_video *    |       |-- depth *    |       |-- height *    |       `-- width *    . *    . *    . *    `-- n *        |-- command *        |-- event *        |-- reverse_heartbeat *        `-- remote_video *            |-- depth *            |-- height *            `-- width * * For each service processor the following files are created: * * command: execute dot commands * 	write: execute a dot command on the service processor * 	read: return the result of a previously executed dot command * * events: listen for service processor events * 	read: sleep (interruptible) until an event occurs *      write: wakeup sleeping event listener * * reverse_heartbeat: send a heartbeat to the service processor * 	read: sleep (interruptible) until the reverse heartbeat fails *      write: wakeup sleeping heartbeat listener * * remote_video/width * remote_video/height * remote_video/width: control remote display settings * 	write: set value * 	read: read value */#include <linux/fs.h>#include <linux/pagemap.h>#include <asm/uaccess.h>#include <asm/io.h>#include "ibmasm.h"#include "remote.h"#include "dot_command.h"#define IBMASMFS_MAGIC 0x66726f67static LIST_HEAD(service_processors);static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode);static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root);static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent);static struct super_block *ibmasmfs_get_super(struct file_system_type *fst,			int flags, const char *name, void *data){	return get_sb_single(fst, flags, data, ibmasmfs_fill_super);}static struct super_operations ibmasmfs_s_ops = {	.statfs		= simple_statfs,	.drop_inode	= generic_delete_inode,};static struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations;static struct file_system_type ibmasmfs_type = {	.owner          = THIS_MODULE,	.name           = "ibmasmfs",	.get_sb         = ibmasmfs_get_super,	.kill_sb        = kill_litter_super,};static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent){	struct inode *root;	struct dentry *root_dentry;	sb->s_blocksize = PAGE_CACHE_SIZE;	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;	sb->s_magic = IBMASMFS_MAGIC;	sb->s_op = &ibmasmfs_s_ops;	sb->s_time_gran = 1;	root = ibmasmfs_make_inode (sb, S_IFDIR | 0500);	if (!root)		return -ENOMEM;	root->i_op = &simple_dir_inode_operations;	root->i_fop = ibmasmfs_dir_ops;	root_dentry = d_alloc_root(root);	if (!root_dentry) {		iput(root);		return -ENOMEM;	}	sb->s_root = root_dentry;	ibmasmfs_create_files(sb, root_dentry);	return 0;}static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode){	struct inode *ret = new_inode(sb);	if (ret) {		ret->i_mode = mode;		ret->i_uid = ret->i_gid = 0;		ret->i_blksize = PAGE_CACHE_SIZE;		ret->i_blocks = 0;		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;	}	return ret;}static struct dentry *ibmasmfs_create_file (struct super_block *sb,			struct dentry *parent,		       	const char *name,			struct file_operations *fops,			void *data,			int mode){	struct dentry *dentry;	struct inode *inode;	dentry = d_alloc_name(parent, name);	if (!dentry)		return NULL;	inode = ibmasmfs_make_inode(sb, S_IFREG | mode);	if (!inode) {		dput(dentry);		return NULL;	}	inode->i_fop = fops;	inode->u.generic_ip = data;	d_add(dentry, inode);	return dentry;}static struct dentry *ibmasmfs_create_dir (struct super_block *sb,				struct dentry *parent,				const char *name){	struct dentry *dentry;	struct inode *inode;	dentry = d_alloc_name(parent, name);	if (!dentry)		return NULL;	inode = ibmasmfs_make_inode(sb, S_IFDIR | 0500);	if (!inode) {		dput(dentry);		return NULL;	}	inode->i_op = &simple_dir_inode_operations;	inode->i_fop = ibmasmfs_dir_ops;	d_add(dentry, inode);	return dentry;}int ibmasmfs_register(void){	return register_filesystem(&ibmasmfs_type);}void ibmasmfs_unregister(void){	unregister_filesystem(&ibmasmfs_type);}void ibmasmfs_add_sp(struct service_processor *sp){	list_add(&sp->node, &service_processors);}/* struct to save state between command file operations */struct ibmasmfs_command_data {	struct service_processor	*sp;	struct command			*command;};/* struct to save state between event file operations */struct ibmasmfs_event_data {	struct service_processor	*sp;	struct event_reader		reader;	int				active;};/* struct to save state between reverse heartbeat file operations */struct ibmasmfs_heartbeat_data {	struct service_processor	*sp;	struct reverse_heartbeat	heartbeat;	int				active;};static int command_file_open(struct inode *inode, struct file *file){	struct ibmasmfs_command_data *command_data;	if (!inode->u.generic_ip)		return -ENODEV;	command_data = kmalloc(sizeof(struct ibmasmfs_command_data), GFP_KERNEL);	if (!command_data)		return -ENOMEM;	command_data->command = NULL;	command_data->sp = inode->u.generic_ip;	file->private_data = command_data;	return 0;}static int command_file_close(struct inode *inode, struct file *file){	struct ibmasmfs_command_data *command_data = file->private_data;	if (command_data->command)		command_put(command_data->command);		kfree(command_data);	return 0;}static ssize_t command_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset){	struct ibmasmfs_command_data *command_data = file->private_data;	struct command *cmd;	int len;	unsigned long flags;	if (*offset < 0)		return -EINVAL;	if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE)		return 0;	if (*offset != 0)		return 0;	spin_lock_irqsave(&command_data->sp->lock, flags);	cmd = command_data->command;	if (cmd == NULL) {		spin_unlock_irqrestore(&command_data->sp->lock, flags);		return 0;	}	command_data->command = NULL;	spin_unlock_irqrestore(&command_data->sp->lock, flags);	if (cmd->status != IBMASM_CMD_COMPLETE) {		command_put(cmd);		return -EIO;	}	len = min(count, cmd->buffer_size);	if (copy_to_user(buf, cmd->buffer, len)) {		command_put(cmd);		return -EFAULT;	}	command_put(cmd);	return len;}static ssize_t command_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset){	struct ibmasmfs_command_data *command_data = file->private_data;	struct command *cmd;	unsigned long flags;	if (*offset < 0)		return -EINVAL;	if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE)		return 0;	if (*offset != 0)		return 0;	/* commands are executed sequentially, only one command at a time */

⌨️ 快捷键说明

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