📄 e1000_proc.c
字号:
/******************************************************************************* 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 + -