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

📄 netproto.c

📁 Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/drivers/usbd/net_fd/netproto.c - network prototype library * * Copyright (c) 2000, 2001, 2002 Lineo * Copyright (c) 2001 Hewlett Packard * * By:  *      Stuart Lynne <sl@lineo.com>,  *      Tom Rushworth <tbr@lineo.com>,  *      Bruce Balden <balden@lineo.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., 675 Mass Ave, Cambridge, MA 02139, USA. * *//* netproto * * This is a simple linux network driver library that is suitable for * implementing layered network drivers.  * * E.g. networking over adsl or usb. * */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/list.h>#include <asm/uaccess.h>#include <linux/netdevice.h>#include <linux/skbuff.h>#include <linux/etherdevice.h>#include <net/arp.h>#include <linux/rtnetlink.h>#include <linux/smp_lock.h>#include <linux/ctype.h>#include <linux/timer.h>#include <linux/string.h>#include <linux/atmdev.h>#include <linux/pkt_sched.h>#include "../usbd-debug.h"#ifndef MODULE#undef GET_USE_COUNT#undef THIS_MODULE#define GET_USE_COUNT(foo) 0#define THIS_MODULE 0#endif/* Debug switches ****************************************************************************** */int dbgflg_usbdfd_pinit = 0;int dbgflg_usbdfd_poc = 0;int dbgflg_usbdfd_prx = 0;int dbgflg_usbdfd_ptx = 0;int dbgflg_usbdfd_pmgmt = 0;static debug_option dbg_table[] = {	{&dbgflg_usbdfd_pinit, NULL, "init", "initialization/termination handling"},	{&dbgflg_usbdfd_poc, NULL, "oc", "open/close handling"},	{&dbgflg_usbdfd_prx, NULL, "rx", "receive (from host)"},	{&dbgflg_usbdfd_ptx, NULL, "tx", "transmit (to host)"},	{&dbgflg_usbdfd_pmgmt, NULL, "mgmt", "management (ioctl) handling"},	{NULL, NULL, NULL, NULL}};#define dbg_pinit(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_pinit,lvl,fmt,##args)#define dbg_poc(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_poc,lvl,fmt,##args)#define dbg_prx(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_prx,lvl,fmt,##args)#define dbg_ptx(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_ptx,lvl,fmt,##args)#define dbg_pmgmt(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_pmgmt,lvl,fmt,##args)debug_option *netproto_get_dbg_table (void){	return (dbg_table);}// This needs to be after the dbg_* macros because of inlines....#include "netproto.h"char *netproto_procname;	// name to use for proc filesystemint netproto_devices;		// maximum number of interfaces that can be createdstruct netproto_dev **netproto_device_array;	// pointer to array of pointers to netproto dev structuresrwlock_t netproto_rwlock = RW_LOCK_UNLOCKED;	// lock for netproto device array access/* Network Device support functions ***************************************************************  * * net_dev.get_stats = netproto_get_stats; * net_dev.set_mac_address = netproto_set_mac_addr  * net_dev.hard_start_xmit = netproto_start_xmit  * net_dev.do_ioctl = netproto_do_ioctl  * net_dev.set_multicast = netproto_set_multicast   //  * net_dev.open = netproto_open                     // tell management thread to start ATM connection  * net_dev.stop = netproto_stop                     // tell management thread to close ATM connection  * net_dev.tx_timeout = netproto_tx_timeout         // tell the driver that tx has timed out * net_dev.set_config = netproto_set_config         // set ATM configuration details *//* * * netproto_init - network device open function  * @net_dev: pointer to &struct net_device  * * Initialize the device.  */static int netproto_init (struct net_device *net_dev){	dbg_pinit (1, "%s", net_dev->name);	//if (netif_running(net_dev)) {	//    return -EBUSY;	//}	return 0;}/* * * netproto_uninit - network device uninit function  * @net_dev: pointer to &struct net_device  * * UnInitialize the device.  */static void netproto_uninit (struct net_device *net_dev){	dbg_pinit (1, "%s", net_dev->name);	return;}/* * * netproto_open - network device open function  * @net_dev: pointer to &struct net_device  * * Start the device.  */static int netproto_open (struct net_device *net_dev){	//struct netproto_dev *dev = net_dev->priv;	dbg_poc (1, "%s", net_dev->name);	netif_wake_queue (net_dev);	dbg_poc (2, "OK %s", net_dev->name);	return 0;}/* * * netproto_stop - network device stop function * @net_dev: pointer to &struct net_device  * * Stop the device.  */static int netproto_stop (struct net_device *net_dev){	//struct netproto_dev *device = net_dev->priv;	dbg_poc (1, "%s", net_dev->name);	netif_stop_queue (net_dev);	return 0;}/* * * netproto_get_stats - network device get stats function * @net_dev: pointer to &struct net_device  * * Retreive network device stats structure. */static struct net_device_stats *netproto_get_stats (struct net_device *net_dev){	struct netproto_dev *device = net_dev->priv;	return &device->stats;}#if 0/* * * netproto_set_multicast - * @net_dev: pointer to &struct net_device  * * Set device to match multicast status */static void netproto_set_multicast (struct net_device *net_dev){	//struct netproto_dev *device = net_dev->priv;	if (net_dev->flags & IFF_PROMISC) {		// enable promiscuous mode	}#if 0	else if ((net_dev->flags & IFF_ALLMULTI) || (net_dev->mc_count > HW_MAX_ADDRS)) {		// disable promiscous mode, set filter	} else if (net_dev->mc_count) {		// walk address list and load filters	}#endif	else {		// disable promiscuous mode	}	return;}#endif/* * * netproto_set_mac_addr - network device set mac address function * @net_dev: pointer to &struct net_device  * @p: pointer to sockaddr structure * * Set mac address. */static int netproto_set_mac_addr (struct net_device *net_dev, void *p){	struct netproto_dev *device = net_dev->priv;	struct sockaddr *addr = p;	if (netif_running (net_dev)) {		return -EBUSY;	}	{		unsigned long flags;		write_lock_irqsave (&device->rwlock, flags);		memcpy (net_dev->dev_addr, addr->sa_data, net_dev->addr_len);		device->addr_set = 1;		write_unlock_irqrestore (&device->rwlock, flags);	}	// push down	if (device->set_addr) {		device->set_addr (device->interface, p, ETH_ALEN);	}	return 0;}/* * * netproto_tx_timeout - network device transmit timeout function * @net_dev: pointer to &struct net_device  * * Called by network layer to tell the driver that transmit has timed out. */static void netproto_tx_timeout (struct net_device *net_dev){	struct netproto_dev *device = net_dev->priv;	dbg_ptx (7, "");	if (device->tx_timeout) {		device->tx_timeout (device->interface);	}}/* * * netproto_set_config - network device set config function * @net_dev: pointer to &struct net_device  * @map: pointer to &struct ifmap  * * Only allow things to be set if not running. */static int netproto_set_config (struct net_device *net_dev, struct ifmap *map){	if (netif_running (net_dev)) {		return -EBUSY;	}	if (map->mem_start) {		net_dev->mem_start = map->mem_start;	}	if (map->irq) {		net_dev->irq = map->irq;	}	if (map->base_addr) {		net_dev->base_addr = map->base_addr;	}	// XXX copy to device	return 0;}/* * * netproto_change_mtu - network device set config function * @net_dev: pointer to &struct net_device  * @mtu: max transmission unit * * Set MTU, if running we can only change it to something less * than or equal to MTU when PVC opened. */static int netproto_change_mtu (struct net_device *net_dev, int mtu){	struct netproto_dev *dev = net_dev->priv;	if (netif_running (net_dev)) {		if (mtu > dev->mtu) {			return -EBUSY;		}		net_dev->mtu = mtu;		return 0;	}	net_dev->mtu = mtu;	// XXX copy to device	return 0;}/* * * netproto_start_xmit - network device start xmit function * @skb: pointer to &struct sk_buff to send * @net_dev: pointer to &struct net_device  * * Called by kernel network layer to transmit a frame on this interface, * grab locks and pass to netproto_do_xmit(). * * The network layer flow control is managed to prevent more than  * device->max_queue_entries from being outstanding. See also  * netproto_done(). *  *  */static int netproto_start_xmit (struct sk_buff *skb, struct net_device *net_dev){	struct netproto_dev *device = net_dev->priv;	int len = skb->len;	int rc;	dbg_ptx (7, "");	dbg_ptx (7, "skb: %p", skb);	if (!netif_carrier_ok (net_dev)) {		dbg_ptx (0, "no carrier %p", skb);		dev_kfree_skb_any (skb);		//netif_stop_queue(net_dev);		return 0;	}	// stop queue, it will be restart only when we are ready for another skb	netif_stop_queue (net_dev);	// lock and update some stats	{		unsigned long flags;		write_lock_irqsave (&device->rwlock, flags);		device->stopped++;		device->queued_entries++;		device->queued_bytes += skb->len;		write_unlock_irqrestore (&device->rwlock, flags);	}	// Set the timestamp for tx timeout	net_dev->trans_start = jiffies;	// XXX should we use skb->stamp here	*(time_t *) (&skb->cb) = jiffies;#if 0	dbg_ptx (7, "skb: %p head: %p data: %p tail: %p len: %d",		 skb, skb->head, skb->data, skb->tail, skb->len);	dbgPRINTmem (dbgflg_usbdfd_ptx, 7, skb->data, skb->len);#endif	// push it down to next layer, handle results	if ((rc = device->xmit_skb (device->interface, skb))) {		switch (rc) {		case -EINVAL:		case -EUNATCH:			dbg_ptx (0, "not attached, send failed: %d", rc);			netproto_tx_carrier_errors (device->interface);			netif_wake_queue (net_dev);			break;		case -ENOMEM:			dbg_ptx (0, "no mem, send failed: %d", rc);			netproto_tx_fifo_errors (device->interface);			netif_wake_queue (net_dev);			break;		case -ECOMM:			dbg_ptx (0, "comm failure, send failed: %d %p", rc, net_dev);			netproto_tx_dropped (device->interface);			break;		}		dev_kfree_skb_any (skb);	} else {		// possibly restart queue		netproto_tx_packets (device->interface, len);		{			read_lock (&device->rwlock);			if ((device->queued_entries < device->max_queue_entries)			    && (device->queued_bytes < device->max_queue_bytes)) {				read_unlock (&device->rwlock);				netif_wake_queue (net_dev);			}			read_unlock (&device->rwlock);		}	}	return 0;}/* Ioctl support functions ************************************************************************  *//* ** netproto_do_ioctl - network device do_ioctl function* @net_dev: pointer to &struct net_device * @rp: pointer to &struct ifreq* @cmd: ioctl cmd* * This handles ioctls actually performed on our device - we must return* -ENOIOCTLCMD for any unrecognized ioctl */static int netproto_do_ioctl (struct net_device *net_dev, struct ifreq *rp, int cmd){	//int             rc;	dbg_pmgmt (1, "%s cmd=%d", net_dev->name, cmd);	return -ENOIOCTLCMD;}/* Proc Filesystem support ********************************************************************* *//* ** netproto_proc_read - implement proc file system read.* @file: file* @buf: buffer* @count: character count* @pos: file position** Standard proc file system read function.** We let upper layers iterate for us, *pos will indicate which device to return* statistics for. */static ssize_t netproto_proc_read (struct file *file, char *buf, size_t count, loff_t * pos){	unsigned long page;	int len = 0;	int index;	struct netproto_dev *dev;	int i;	// get a page, max 4095 bytes of data...	if (!(page = get_free_page (GFP_ATOMIC))) {		return -ENOMEM;	}	len = 0;	index = (*pos)++;	if (index == 0) {		len += sprintf ((char *) page + len,				"          MAC              ESI   VCC         Skbs Forwarded    "				"Stopped     Deferred     TimeInQ uS           Avg Q    QueueLen   MaxQ       Conn\n");		len += sprintf ((char *) page + len,				"%48slo       hi                           lpkt:cel  hpkt:cel     lo   hi   lo  hi    lo  hi\n",				"");	}	// lock and iterate across devices to get access to N'th device, return it's stats	read_lock (&netproto_rwlock);	for (i = 0; i < netproto_devices; i++) {		dev = netproto_device_array[i];		if (index-- == 0) {			// max 4095 bytes of data...			len +=			    sprintf ((char *) page + len,				     "%.16s %2d [%02X:%02X:%02X:%02X:%02X:%02X]",				     dev->net_dev->name, dev->interface, dev->net_dev->dev_addr[0],				     dev->net_dev->dev_addr[1], dev->net_dev->dev_addr[2],				     dev->net_dev->dev_addr[3], dev->net_dev->dev_addr[4],				     dev->net_dev->dev_addr[5]);			len += sprintf ((char *) page + len, " %s ", dev->addr_mac ? "y" : "n");			len += sprintf ((char *) page + len, "[%02d.%02d.%02d]",					(int) (dev->net_dev->mem_start >> 24) & 0xff,					(int) (dev->net_dev->mem_start >> 16) & 0xff,					(int) (dev->net_dev->mem_start) & 0xffff);			len +=			    sprintf ((char *) page + len, " [%6d %2d]", dev->stopped,				     dev->stopped - dev->restarts);			len +=			    sprintf ((char *) page + len, " [%4ld]",				     dev->samples ? ((dev->jiffies * 1000) / dev->samples) : 0);			len +=			    sprintf ((char *) page + len, " [%3ld]",				     dev->samples ? ((dev->avg_queue_entries) / dev->samples) : 0);			len += sprintf ((char *) page + len, " [%3d]", dev->queued_entries);			len += sprintf ((char *) page + len, " [%3d]", dev->max_queue_entries);			len += sprintf ((char *) page + len, "J[%6ld]", dev->jiffies);			len += sprintf ((char *) page + len, "S[%6ld]", dev->samples);			len += sprintf ((char *) page + len, "\n");			break;		}	}	read_unlock (&netproto_rwlock);	if (len > count) {		len = -EINVAL;	}	else if (len > 0 && copy_to_user (buf, (char *) page, len)) {		len = -EFAULT;	}	free_page (page);	return len;}static struct file_operations netproto_proc_operations = {	read:netproto_proc_read,};/* Library Interface functions ***************************************************************** *//* ** netproto_rx_dropped* @int - network interface* */void netproto_rx_dropped (int interface){	struct netproto_dev *device;	if ((interface < netproto_devices) && (device = netproto_device_array[interface])) {		device->stats.rx_dropped++;

⌨️ 快捷键说明

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