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

📄 e100_proc.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 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*******************************************************************************//***********************************************************************                                                                       ** INTEL CORPORATION                                                     **                                                                       ** This software is supplied under the terms of the license included     ** above.  All use of this driver must be in accordance with the terms   ** of that license.                                                      **                                                                       ** Module Name:  e100_proc.c                                             **                                                                       ** Abstract:     Functions to handle the proc file system.               **               Create the proc directories and files and run read and  **               write requests from the user                            **                                                                       ** Environment:  This file is intended to be specific to the Linux       **               operating system.                                       **                                                                       ***********************************************************************/#include <linux/config.h>#if 0#include "e100.h"/* MDI sleep time is at least 50 ms, in jiffies */#define MDI_SLEEP_TIME ((HZ / 20) + 1)/***************************************************************************//*       /proc File System Interaface Support Functions                    *//***************************************************************************/static struct proc_dir_entry *adapters_proc_dir = 0;/* externs from e100_main.c */extern char e100_short_driver_name[];extern char e100_driver_version[];extern struct net_device_stats *e100_get_stats(struct net_device *dev);extern char *e100_get_brand_msg(struct e100_private *bdp);extern int e100_mdi_write(struct e100_private *, u32, u32, u16);static void e100_proc_cleanup(void);static unsigned char e100_init_proc_dir(void);#define ADAPTERS_PROC_DIR "PRO_LAN_Adapters"#define WRITE_BUF_MAX_LEN 20	#define READ_BUF_MAX_LEN  256#define E100_PE_LEN       25#define bdp_drv_off(off) (unsigned long)(offsetof(struct e100_private, drv_stats.off))#define bdp_prm_off(off) (unsigned long)(offsetof(struct e100_private, params.off))typedef struct _e100_proc_entry {	char *name;	read_proc_t *read_proc;	write_proc_t *write_proc;	unsigned long offset;	/* offset into bdp. ~0 means no value, pass NULL. */} e100_proc_entry;static intgeneric_read(char *page, char **start, off_t off, int count, int *eof, int len){	if (len <= off + count)		*eof = 1;	*start = page + off;	len -= off;	if (len > count)		len = count;	if (len < 0)		len = 0;	return len;}static intread_ulong(char *page, char **start, off_t off,	   int count, int *eof, unsigned long l){	int len;	len = sprintf(page, "%lu\n", l);	return generic_read(page, start, off, count, eof, len);}static intread_gen_ulong(char *page, char **start, off_t off,	       int count, int *eof, void *data){	unsigned long val = 0;	if (data)		val = *((unsigned long *) data);	return read_ulong(page, start, off, count, eof, val);}static intread_hwaddr(char *page, char **start, off_t off,	    int count, int *eof, unsigned char *hwaddr){	int len;	len = sprintf(page, "%02X:%02X:%02X:%02X:%02X:%02X\n",		      hwaddr[0], hwaddr[1], hwaddr[2],		      hwaddr[3], hwaddr[4], hwaddr[5]);	return generic_read(page, start, off, count, eof, len);}static intread_descr(char *page, char **start, off_t off, int count, int *eof, void *data){	struct e100_private *bdp = data;	int len;	len = sprintf(page, "%s\n", bdp->id_string);	return generic_read(page, start, off, count, eof, len);}static intread_permanent_hwaddr(char *page, char **start, off_t off,		      int count, int *eof, void *data){	struct e100_private *bdp = data;	unsigned char *hwaddr = bdp->perm_node_address;	return read_hwaddr(page, start, off, count, eof, hwaddr);}static intread_part_number(char *page, char **start, off_t off,		 int count, int *eof, void *data){	struct e100_private *bdp = data;	int len;	len = sprintf(page, "%06lx-%03x\n",		      (unsigned long) (bdp->pwa_no >> 8),		      (unsigned int) (bdp->pwa_no & 0xFF));	return generic_read(page, start, off, count, eof, len);}static voidset_led(struct e100_private *bdp, u16 led_mdi_op){	e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL,		       bdp->phy_addr, led_mdi_op);	set_current_state(TASK_UNINTERRUPTIBLE);	schedule_timeout(MDI_SLEEP_TIME);	/* turn led ownership to the chip */	e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL,		       bdp->phy_addr, PHY_82555_LED_NORMAL_CONTROL);}static intwrite_blink_led_timer(struct file *file, const char *buffer,		      unsigned long count, void *data){	struct e100_private *bdp = data;	char s_blink_op[WRITE_BUF_MAX_LEN + 1];	char *res;	unsigned long i_blink_op;	if (!buffer)		return -EINVAL;	if (count > WRITE_BUF_MAX_LEN) {		count = WRITE_BUF_MAX_LEN;	}	if (copy_from_user(s_blink_op, buffer, count))		return -EFAULT;	s_blink_op[count] = '\0';	i_blink_op = simple_strtoul(s_blink_op, &res, 0);	if (res == s_blink_op) {		return -EINVAL;	}	switch (i_blink_op) {	case LED_OFF:		set_led(bdp, PHY_82555_LED_OFF);		break;	case LED_ON:		if (bdp->rev_id >= D101MA_REV_ID)			set_led(bdp, PHY_82555_LED_ON_559);		else			set_led(bdp, PHY_82555_LED_ON_PRE_559);		break;	default:		return -EINVAL;	}	return count;}static e100_proc_entry e100_proc_list[] = {	{"Description",           read_descr,            0, 0},	{"Permanent_HWaddr",      read_permanent_hwaddr, 0, 0},	{"Part_Number",           read_part_number,      0, 0},	{"\n",},	{"Rx_TCP_Checksum_Good",  read_gen_ulong, 0, ~0},	{"Rx_TCP_Checksum_Bad",   read_gen_ulong, 0, ~0},	{"Tx_TCP_Checksum_Good",  read_gen_ulong, 0, ~0},	{"Tx_TCP_Checksum_Bad",   read_gen_ulong, 0, ~0},	{"\n",},	{"Tx_Abort_Late_Coll",    read_gen_ulong, 0, bdp_drv_off(tx_late_col)},	{"Tx_Deferred_Ok",        read_gen_ulong, 0, bdp_drv_off(tx_ok_defrd)},	{"Tx_Single_Coll_Ok",     read_gen_ulong, 0, bdp_drv_off(tx_one_retry)},	{"Tx_Multi_Coll_Ok",      read_gen_ulong, 0, bdp_drv_off(tx_mt_one_retry)},	{"Rx_Long_Length_Errors", read_gen_ulong, 0, ~0},	{"\n",},	{"Tx_Flow_Control_Pause", read_gen_ulong, 0, bdp_drv_off(xmt_fc_pkts)},	{"Rx_Flow_Control_Pause", read_gen_ulong, 0, bdp_drv_off(rcv_fc_pkts)},	{"Rx_Flow_Control_Unsup", read_gen_ulong, 0, bdp_drv_off(rcv_fc_unsupported)},	{"\n",},	{"Tx_TCO_Packets",        read_gen_ulong, 0, bdp_drv_off(xmt_tco_pkts)},	{"Rx_TCO_Packets",        read_gen_ulong, 0, bdp_drv_off(rcv_tco_pkts)},	{"\n",},	{"Rx_Interrupt_Packets",  read_gen_ulong, 0, bdp_drv_off(rx_intr_pkts)},	{"Identify_Adapter", 0, write_blink_led_timer, 0},	{"", 0, 0, 0}};static intread_info(char *page, char **start, off_t off, int count, int *eof, void *data){	struct e100_private *bdp = data;	e100_proc_entry *pe;	int tmp;	void *val;	int len = 0;	for (pe = e100_proc_list; pe->name[0]; pe++) {		if (pe->name[0] == '\n') {			len += sprintf(page + len, "\n");			continue;		}		if (pe->read_proc) {			if ((len + READ_BUF_MAX_LEN + E100_PE_LEN + 1) >=			    PAGE_SIZE)				break;			if (pe->offset != ~0)				val = ((char *) bdp) + pe->offset;			else				val = NULL;			len += sprintf(page + len, "%-"				       __MODULE_STRING(E100_PE_LEN)				       "s ", pe->name);			len += pe->read_proc(page + len, start, 0,					     READ_BUF_MAX_LEN + 1, &tmp, val);		}	}	return generic_read(page, start, off, count, eof, len);}static struct proc_dir_entry *create_proc_rw(char *name, void *data, struct proc_dir_entry *parent,	       read_proc_t * read_proc, write_proc_t * write_proc){	struct proc_dir_entry *pdep;	mode_t mode = S_IFREG;	if (write_proc) {		mode |= S_IWUSR;		if (read_proc) {			mode |= S_IRUSR;		}	} else if (read_proc) {		mode |= S_IRUGO;	}	if (!(pdep = create_proc_entry(name, mode, parent)))		return NULL;	pdep->read_proc = read_proc;	pdep->write_proc = write_proc;	pdep->data = data;	return pdep;}voide100_remove_proc_subdir(struct e100_private *bdp, char *name){	e100_proc_entry *pe;	char info[256];	int len;	/* If our root /proc dir was not created, there is nothing to remove */	if (adapters_proc_dir == NULL) {		return;	}	len = strlen(bdp->ifname);	strncpy(info, bdp->ifname, sizeof (info));	strncat(info + len, ".info", sizeof (info) - len);	if (bdp->proc_parent) {		for (pe = e100_proc_list; pe->name[0]; pe++) {			if (pe->name[0] == '\n')				continue;			remove_proc_entry(pe->name, bdp->proc_parent);		}		remove_proc_entry(bdp->ifname, adapters_proc_dir);		bdp->proc_parent = NULL;	}	remove_proc_entry(info, adapters_proc_dir);	/* try to remove the main /proc dir, if it's empty */	e100_proc_cleanup();}inte100_create_proc_subdir(struct e100_private *bdp){	struct proc_dir_entry *dev_dir;	e100_proc_entry *pe;	char info[256];	int len;	void *data;	/* create the main /proc dir if needed */	if (!adapters_proc_dir) {		if (!e100_init_proc_dir())			return -ENOMEM;	}	strncpy(info, bdp->ifname, sizeof (info));	len = strlen(info);	strncat(info + len, ".info", sizeof (info) - len);	/* info */	if (!(create_proc_rw(info, bdp, adapters_proc_dir, read_info, 0))) {		e100_proc_cleanup();		return -ENOMEM;	}	dev_dir = create_proc_entry(bdp->ifname, S_IFDIR,				    adapters_proc_dir);	bdp->proc_parent = dev_dir;	if (!dev_dir) {		e100_remove_proc_subdir(bdp, bdp->ifname);		return -ENOMEM;	}	for (pe = e100_proc_list; pe->name[0]; pe++) {		if (pe->name[0] == '\n')			continue;		if (pe->offset != ~0)			data = ((char *) bdp) + pe->offset;		else			data = NULL;		if (!(create_proc_rw(pe->name, data, dev_dir,				     pe->read_proc, pe->write_proc))) {			e100_remove_proc_subdir(bdp, bdp->ifname);			return -ENOMEM;		}	}	return 0;}/**************************************************************************** * Name:          e100_init_proc_dir * * Description:   This routine creates the top-level /proc directory for the *                driver in /proc/net * * Arguments:     none * * Returns:       true on success, false on fail * ***************************************************************************/static unsigned chare100_init_proc_dir(void){	int len;	/* first check if adapters_proc_dir already exists */	len = strlen(ADAPTERS_PROC_DIR);	for (adapters_proc_dir = proc_net->subdir;	     adapters_proc_dir; adapters_proc_dir = adapters_proc_dir->next) {		if ((adapters_proc_dir->namelen == len) &&		    (!memcmp(adapters_proc_dir->name, ADAPTERS_PROC_DIR, len)))			break;	}	if (!adapters_proc_dir)		adapters_proc_dir =			create_proc_entry(ADAPTERS_PROC_DIR, S_IFDIR, proc_net);	if (!adapters_proc_dir)		return false;	return true;}/**************************************************************************** * Name:          e100_proc_cleanup * * Description:   This routine clears the top-level /proc directory, if empty. * * Arguments:     none * * Returns:       none * ***************************************************************************/static voide100_proc_cleanup(void){	struct proc_dir_entry *de;	if (adapters_proc_dir == NULL) {		return;	}	/* check if subdir list is empty before removing adapters_proc_dir */	for (de = adapters_proc_dir->subdir; de; de = de->next) {		/* ignore . and .. */		if (*(de->name) != '.')			break;	}	if (de)		return;	remove_proc_entry(ADAPTERS_PROC_DIR, proc_net);	adapters_proc_dir = NULL;}#endif /* CONFIG_PROC_FS */

⌨️ 快捷键说明

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