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

📄 e1000_proc.c

📁 COPE the first practical network coding scheme which is developped on click
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************    Copyright(c) 1999 - 2002 Intel Corporation. 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.  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.    The full GNU General Public License is included in this distribution in the  file called LICENSE.    Contact Information:  Linux NICS <linux.nics@intel.com>  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************//* * Proc fs support. * * Read-only files created by driver (if CONFIG_PROC_FS): * * /proc/net/PRO_LAN_Adapters/<ethx>.info * /proc/net/PRO_LAN_Adapters/<ethx>/<attribute> * * where <ethx>      is the system device name, i.e eth0. *       <attribute> is the driver attribute name. * * There is one file for each driver attribute, where the contents * of the file is the attribute value.  The ethx.info file contains * a list of all driver attributes in one file. * */#include "e1000.h"#ifdef CONFIG_PROC_FS#include <linux/proc_fs.h>#define ADAPTERS_PROC_DIR           "PRO_LAN_Adapters"#define TAG_MAX_LENGTH              32#define LINE_MAX_LENGTH             80#define FIELD_MAX_LENGTH            LINE_MAX_LENGTH - TAG_MAX_LENGTH - 3extern char e1000_driver_name[];extern char e1000_driver_version[];/* * The list of driver proc attributes is stored in a proc_list link * list.  The list is build with proc_list_setup and is used to * build the proc fs nodes.  The private data for each node is the * corresponding link in the link list. */struct proc_list {	struct list_head list;                  /* link list */	char tag[TAG_MAX_LENGTH + 1];           /* attribute name */	void *data;                             /* attribute data */	size_t len;				/* sizeof data */	char *(*func)(void *, size_t, char *);  /* format data func */};static inte1000_proc_read(char *page, char **start, off_t off, int count, int *eof){	int len = strlen(page);	page[len++] = '\n';	if(len <= off + count)		*eof = 1;	*start = page + off;	len -= off;	if(len > count)		len = count;	if(len < 0)		len = 0;	return len;}static inte1000_proc_info_read(char *page, char **start, off_t off,                     int count, int *eof, void *data){	struct list_head *proc_list_head = data, *curr;	struct proc_list *elem;	char *p = page;	char buf[FIELD_MAX_LENGTH + 1];	list_for_each(curr, proc_list_head) {		elem = list_entry(curr, struct proc_list, list);		if (p - page + LINE_MAX_LENGTH >= PAGE_SIZE)			break;		if(!strlen(elem->tag))			p += sprintf(p, "\n");		else			p += sprintf(p, "%-*.*s %.*s\n", 				TAG_MAX_LENGTH, TAG_MAX_LENGTH,				elem->tag, FIELD_MAX_LENGTH,				elem->func(elem->data, elem->len, buf));	}	*p = '\0';	return e1000_proc_read(page, start, off, count, eof);}static inte1000_proc_single_read(char *page, char **start, off_t off,                       int count, int *eof, void *data){	struct proc_list *elem = data;	sprintf(page, "%.*s", FIELD_MAX_LENGTH, elem->func(elem->data, 	        elem->len, page));	return e1000_proc_read(page, start, off, count, eof);}static void __devexite1000_proc_dirs_free(char *name, struct list_head *proc_list_head){	struct proc_dir_entry *intel_proc_dir, *proc_dir;	char info_name[strlen(name) + strlen(".info")];	for(intel_proc_dir = proc_net->subdir; intel_proc_dir;		intel_proc_dir = intel_proc_dir->next) {		if((intel_proc_dir->namelen == strlen(ADAPTERS_PROC_DIR)) &&		   !memcmp(intel_proc_dir->name, ADAPTERS_PROC_DIR, strlen(ADAPTERS_PROC_DIR)))			break;	}	if(!intel_proc_dir)		return;	for(proc_dir = intel_proc_dir->subdir; proc_dir;		proc_dir = proc_dir->next) {		if ((proc_dir->namelen == strlen(name)) &&		    !memcmp(proc_dir->name, name, strlen(name)))			break;	}	if(proc_dir) {		struct list_head *curr;		struct proc_list *elem;		list_for_each(curr, proc_list_head) {			elem = list_entry(curr, struct proc_list, list);			remove_proc_entry(elem->tag, proc_dir);		}		strcpy(info_name, name);		strcat(info_name, ".info");		remove_proc_entry(info_name, intel_proc_dir);		remove_proc_entry(name, intel_proc_dir);	}	/* If the intel dir is empty, remove it */	for(proc_dir = intel_proc_dir->subdir; proc_dir;		proc_dir = proc_dir->next) {		/* ignore . and .. */		if(*(proc_dir->name) == '.')			continue;		break;	}	if(!proc_dir)		remove_proc_entry(ADAPTERS_PROC_DIR, proc_net);}static int __devinite1000_proc_singles_create(struct proc_dir_entry *parent,                          struct list_head *proc_list_head){	struct list_head *curr;	struct proc_list *elem;	list_for_each(curr, proc_list_head) {		struct proc_dir_entry *proc_entry;		elem = list_entry(curr, struct proc_list, list);		if(!strlen(elem->tag))			continue;		if(!(proc_entry =			create_proc_entry(elem->tag, S_IFREG, parent)))			return 0;		proc_entry->read_proc = e1000_proc_single_read;		proc_entry->data = elem;		SET_MODULE_OWNER(proc_entry);	}	return 1;}static void __devinite1000_proc_dirs_create(void *data, char *name,                        struct list_head *proc_list_head){	struct proc_dir_entry *intel_proc_dir, *proc_dir, *info_entry;	char info_name[strlen(name) + strlen(".info")];	for(intel_proc_dir = proc_net->subdir; intel_proc_dir;		intel_proc_dir = intel_proc_dir->next) {		if((intel_proc_dir->namelen == strlen(ADAPTERS_PROC_DIR)) &&		   !memcmp(intel_proc_dir->name, ADAPTERS_PROC_DIR, strlen(ADAPTERS_PROC_DIR)))			break;	}	if(!intel_proc_dir)		if(!(intel_proc_dir =			create_proc_entry(ADAPTERS_PROC_DIR,				S_IFDIR, proc_net)))			return;	if(!(proc_dir =		create_proc_entry(name, S_IFDIR, intel_proc_dir)))		return;	SET_MODULE_OWNER(proc_dir);	if(!e1000_proc_singles_create(proc_dir, proc_list_head))		return;	strcpy(info_name, name);	strcat(info_name, ".info");	if(!(info_entry =		create_proc_entry(info_name, S_IFREG, intel_proc_dir)))		return;	SET_MODULE_OWNER(info_entry);	info_entry->read_proc = e1000_proc_info_read;	info_entry->data = proc_list_head;}static void __devinite1000_proc_list_add(struct list_head *proc_list_head, char *tag,                    void *data, size_t len, 		    char *(*func)(void *, size_t, char *)){	struct proc_list *new = (struct proc_list *)		kmalloc(sizeof(struct proc_list), GFP_KERNEL);	if(!new)		return;	strncpy(new->tag, tag, TAG_MAX_LENGTH);	new->data = data;	new->len  = len;	new->func = func;	list_add_tail(&new->list, proc_list_head);}static void __devexite1000_proc_list_free(struct list_head *proc_list_head){	struct proc_list *elem;	while(!list_empty(proc_list_head)) {		elem = list_entry(proc_list_head->next, struct proc_list, list);		list_del(&elem->list);		kfree(elem);	}}/* * General purpose formating functions */static char *e1000_proc_str(void *data, size_t len, char *buf){	sprintf(buf, "%s", (char *)data);	return buf;}static char *e1000_proc_hex(void *data, size_t len, char *buf){	switch(len) {	case sizeof(uint8_t):		sprintf(buf, "0x%02x", *(uint8_t *)data);		break;	case sizeof(uint16_t):		sprintf(buf, "0x%04x", *(uint16_t *)data);		break;	case sizeof(uint32_t):		sprintf(buf, "0x%08x", *(uint32_t *)data);		break;	case sizeof(uint64_t):		sprintf(buf, "0x%08Lx", (unsigned long long)*(uint64_t *)data);		break;	}	return buf;}static char *e1000_proc_unsigned(void *data, size_t len, char *buf){	switch(len) {	case sizeof(uint8_t):		sprintf(buf, "%u", *(uint8_t *)data);		break;	case sizeof(uint16_t):		sprintf(buf, "%u", *(uint16_t *)data);		break;	case sizeof(uint32_t):		sprintf(buf, "%u", *(uint32_t *)data);		break;	case sizeof(uint64_t):		sprintf(buf, "%Lu", (unsigned long long)*(uint64_t *)data);		break;	}	return buf;}/* * Specific formating functions */static char *e1000_proc_part_number(void *data, size_t len, char *buf){	sprintf(buf, "%06x-%03x", *(uint32_t *)data >> 8,	        *(uint32_t *)data & 0x000000FF);	return buf;}static char *e1000_proc_slot(void *data, size_t len, char *buf){	struct e1000_adapter *adapter = data;	sprintf(buf, "%u", PCI_SLOT(adapter->pdev->devfn));

⌨️ 快捷键说明

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