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

📄 rt2x00debug.c

📁 r73模块的无线网卡在Linux下的驱动程序
💻 C
字号:
/*	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project	<http://rt2x00.serialmonkey.com>	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. *//*	Module: rt2x00lib	Abstract: rt2x00 debugfs specific routines. */#ifdef RT2X00DEBUGFS#include <linux/debugfs.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/uaccess.h>#include "rt_config.h"#define PRINT_LINE_LEN_MAX 32struct rt2x00debug_intf {	/*	 * Pointer to driver structure where	 * this debugfs entry belongs to.	 */	struct rt2x00_dev *rt2x00dev;	/*	 * Reference to the rt2x00debug structure	 * which can be used to communicate with	 * the registers.	 */	const struct rt2x00debug *debug;	/*	 * Debugfs entries for:	 * - driver folder	 * - driver file	 * - chipset file	 * - register offset/value files	 * - eeprom offset/value files	 * - bbp offset/value files	 * - rf offset/value files	 */	struct dentry *driver_folder;	struct dentry *driver_entry;	struct dentry *chipset_entry;	struct dentry *csr_off_entry;	struct dentry *csr_val_entry;	struct dentry *eeprom_off_entry;	struct dentry *eeprom_val_entry;	struct dentry *bbp_off_entry;	struct dentry *bbp_val_entry;	struct dentry *rf_off_entry;	struct dentry *rf_val_entry;	/*	 * Driver and chipset files will use a data buffer	 * that has been created in advance. This will simplify	 * the code since we can use the debugfs functions.	 */	struct debugfs_blob_wrapper driver_blob;	struct debugfs_blob_wrapper chipset_blob;	/*	 * Requested offset for each register type.	 */	unsigned int offset_csr;	unsigned int offset_eeprom;	unsigned int offset_bbp;	unsigned int offset_rf;};static int rt2x00debug_file_open(struct inode *inode, struct file *file){	struct rt2x00debug_intf *intf = inode->i_private;	file->private_data = inode->i_private;	if (!try_module_get(intf->debug->owner))		return -EBUSY;	return 0;}static int rt2x00debug_file_release(struct inode *inode, struct file *file){	struct rt2x00debug_intf *intf = file->private_data;	module_put(intf->debug->owner);	return 0;}#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)	\static ssize_t rt2x00debug_read_##__name(struct file *file,	\					 char __user *buf,	\					 size_t length,		\					 loff_t *offset)	\{								\	struct rt2x00debug_intf *intf =	file->private_data;	\	const struct rt2x00debug *debug = intf->debug;		\	char line[16];						\	size_t size;						\	__type value;						\								\	if (*offset)						\		return 0;					\								\	if (intf->offset_##__name >= debug->__name.word_count)	\		return -EINVAL;					\								\	debug->__name.read(intf->rt2x00dev,			\			   intf->offset_##__name, &value);	\								\	size = sprintf(line, __format, value);			\								\	if (copy_to_user(buf, line, size))			\		return -EFAULT;					\								\	*offset += size;					\	return size;						\}#define RT2X00DEBUGFS_OPS_WRITE(__name, __type)			\static ssize_t rt2x00debug_write_##__name(struct file *file,	\					  const char __user *buf,\					  size_t length,	\					  loff_t *offset)	\{								\	struct rt2x00debug_intf *intf =	file->private_data;	\	const struct rt2x00debug *debug = intf->debug;		\	char line[16];						\	size_t size;						\	__type value;						\								\	if (*offset)						\		return 0;					\								\	if (!capable(CAP_NET_ADMIN))				\		return -EPERM;					\								\	if (intf->offset_##__name >= debug->__name.word_count)	\		return -EINVAL;					\								\	if (copy_from_user(line, buf, length))			\		return -EFAULT;					\								\	size = strlen(line);					\	value = simple_strtoul(line, NULL, 0);			\								\	debug->__name.write(intf->rt2x00dev,			\			    intf->offset_##__name, value);	\								\	*offset += size;					\	return size;						\}#define RT2X00DEBUGFS_OPS(__name, __format, __type)		\RT2X00DEBUGFS_OPS_READ(__name, __format, __type);		\RT2X00DEBUGFS_OPS_WRITE(__name, __type);			\								\static const struct file_operations rt2x00debug_fop_##__name = {\	.owner		= THIS_MODULE,				\	.read		= rt2x00debug_read_##__name,		\	.write		= rt2x00debug_write_##__name,		\	.open		= rt2x00debug_file_open,		\	.release	= rt2x00debug_file_release,		\};RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);static struct dentry *rt2x00debug_create_file_driver(const char *name,						     struct rt2x00debug_intf						     *intf,						     struct debugfs_blob_wrapper						     *blob){	char *data;	data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL);	if (!data)		return NULL;	blob->data = data;	data += sprintf(data, "driver: %s\n", DRIVER_NAME);	data += sprintf(data, "version: %s\n", DRIVER_VERSION);	data += sprintf(data, "compiled: %s %s\n", __DATE__, __TIME__);	blob->size = strlen(blob->data);	return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);}static struct dentry *rt2x00debug_create_file_chipset(const char *name,						      struct rt2x00debug_intf						      *intf,						      struct						      debugfs_blob_wrapper						      *blob){	const struct rt2x00debug *debug = intf->debug;	char *data;	data = kzalloc(4 * PRINT_LINE_LEN_MAX, GFP_KERNEL);	if (!data)		return NULL;	blob->data = data;	data += sprintf(data, "csr length: %d\n", debug->csr.word_count);	data += sprintf(data, "eeprom length: %d\n", debug->eeprom.word_count);	data += sprintf(data, "bbp length: %d\n", debug->bbp.word_count);	data += sprintf(data, "rf length: %d\n", debug->rf.word_count);	blob->size = strlen(blob->data);	return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);}void rt2x00debug_register(struct rt2x00_dev *rt2x00dev){	const struct rt2x00debug *debug = rt2x00dev->ops->debugfs;	struct rt2x00debug_intf *intf;	intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);	if (!intf)		return;	intf->debug = debug;	intf->rt2x00dev = rt2x00dev;	rt2x00dev->debugfs_intf = intf;	intf->driver_folder =	    debugfs_create_dir(DRIVER_NAME, NULL);	if (IS_ERR(intf->driver_folder))		goto exit;	intf->driver_entry =	    rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);	if (IS_ERR(intf->driver_entry))		goto exit;	intf->chipset_entry =	    rt2x00debug_create_file_chipset("chipset",					    intf, &intf->chipset_blob);	if (IS_ERR(intf->chipset_entry))		goto exit;#define RT2X00DEBUGFS_CREATE_ENTRY(__intf, __name)		\({								\	(__intf)->__name##_off_entry =				\	    debugfs_create_u32(__stringify(__name) "_offset",	\			       S_IRUGO | S_IWUSR,		\			       (__intf)->driver_folder,		\			       &(__intf)->offset_##__name);	\	if (IS_ERR((__intf)->__name##_off_entry))		\		goto exit;					\								\	(__intf)->__name##_val_entry =				\	    debugfs_create_file(__stringify(__name) "_value",	\				S_IRUGO | S_IWUSR,		\				(__intf)->driver_folder,	\				(__intf), &rt2x00debug_fop_##__name);\	if (IS_ERR((__intf)->__name##_val_entry))		\		goto exit;					\})	RT2X00DEBUGFS_CREATE_ENTRY(intf, csr);	RT2X00DEBUGFS_CREATE_ENTRY(intf, eeprom);	RT2X00DEBUGFS_CREATE_ENTRY(intf, bbp);	RT2X00DEBUGFS_CREATE_ENTRY(intf, rf);#undef RT2X00DEBUGFS_CREATE_ENTRY	return;exit:	rt2x00debug_deregister(rt2x00dev);	return;}void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev){	const struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;	if (unlikely(!intf))		return;	debugfs_remove(intf->rf_val_entry);	debugfs_remove(intf->rf_off_entry);	debugfs_remove(intf->bbp_val_entry);	debugfs_remove(intf->bbp_off_entry);	debugfs_remove(intf->eeprom_val_entry);	debugfs_remove(intf->eeprom_off_entry);	debugfs_remove(intf->csr_val_entry);	debugfs_remove(intf->csr_off_entry);	debugfs_remove(intf->chipset_entry);	debugfs_remove(intf->driver_entry);	debugfs_remove(intf->driver_folder);	kfree(intf->chipset_blob.data);	kfree(intf->driver_blob.data);	kfree(intf);	rt2x00dev->debugfs_intf = NULL;}#endif /* RT2X00DEBUGFS */

⌨️ 快捷键说明

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