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

📄 dev.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (ifr->ifr_hwaddr.sa_family!=dev->type)				return -EINVAL;			if (!netif_device_present(dev))				return -ENODEV;			err = dev->set_mac_address(dev, &ifr->ifr_hwaddr);			if (!err)				notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);			return err;					case SIOCSIFHWBROADCAST:			if (ifr->ifr_hwaddr.sa_family!=dev->type)				return -EINVAL;			memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, MAX_ADDR_LEN);			notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);			return 0;		case SIOCGIFMAP:			ifr->ifr_map.mem_start=dev->mem_start;			ifr->ifr_map.mem_end=dev->mem_end;			ifr->ifr_map.base_addr=dev->base_addr;			ifr->ifr_map.irq=dev->irq;			ifr->ifr_map.dma=dev->dma;			ifr->ifr_map.port=dev->if_port;			return 0;					case SIOCSIFMAP:			if (dev->set_config) {				if (!netif_device_present(dev))					return -ENODEV;				return dev->set_config(dev,&ifr->ifr_map);			}			return -EOPNOTSUPP;					case SIOCADDMULTI:			if (dev->set_multicast_list == NULL ||			    ifr->ifr_hwaddr.sa_family != AF_UNSPEC)				return -EINVAL;			if (!netif_device_present(dev))				return -ENODEV;			dev_mc_add(dev,ifr->ifr_hwaddr.sa_data, dev->addr_len, 1);			return 0;		case SIOCDELMULTI:			if (dev->set_multicast_list == NULL ||			    ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)				return -EINVAL;			if (!netif_device_present(dev))				return -ENODEV;			dev_mc_delete(dev,ifr->ifr_hwaddr.sa_data,dev->addr_len, 1);			return 0;		case SIOCGIFINDEX:			ifr->ifr_ifindex = dev->ifindex;			return 0;		case SIOCGIFTXQLEN:			ifr->ifr_qlen = dev->tx_queue_len;			return 0;		case SIOCSIFTXQLEN:			if (ifr->ifr_qlen<0)				return -EINVAL;			dev->tx_queue_len = ifr->ifr_qlen;			return 0;		case SIOCSIFNAME:			if (dev->flags&IFF_UP)				return -EBUSY;			if (__dev_get_by_name(ifr->ifr_newname))				return -EEXIST;			memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);			dev->name[IFNAMSIZ-1] = 0;			notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);			return 0;#ifdef WIRELESS_EXT		case SIOCGIWSTATS:			return dev_iwstats(dev, ifr);#endif	/* WIRELESS_EXT */		/*		 *	Unknown or private ioctl		 */		default:			if ((cmd >= SIOCDEVPRIVATE &&			    cmd <= SIOCDEVPRIVATE + 15) ||			    cmd == SIOCBONDENSLAVE ||			    cmd == SIOCBONDRELEASE ||			    cmd == SIOCBONDSETHWADDR ||			    cmd == SIOCBONDSLAVEINFOQUERY ||			    cmd == SIOCBONDINFOQUERY ||			    cmd == SIOCBONDCHANGEACTIVE ||			    cmd == SIOCETHTOOL ||			    cmd == SIOCGMIIPHY ||			    cmd == SIOCGMIIREG ||			    cmd == SIOCSMIIREG) {				if (dev->do_ioctl) {					if (!netif_device_present(dev))						return -ENODEV;					return dev->do_ioctl(dev, ifr, cmd);				}				return -EOPNOTSUPP;			}#ifdef WIRELESS_EXT			if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {				if (dev->do_ioctl) {					if (!netif_device_present(dev))						return -ENODEV;					return dev->do_ioctl(dev, ifr, cmd);				}				return -EOPNOTSUPP;			}#endif	/* WIRELESS_EXT */	}	return -EINVAL;}/* *	This function handles all "interface"-type I/O control requests. The actual *	'doing' part of this is dev_ifsioc above. *//** *	dev_ioctl	-	network device ioctl *	@cmd: command to issue *	@arg: pointer to a struct ifreq in user space * *	Issue ioctl functions to devices. This is normally called by the *	user space syscall interfaces but can sometimes be useful for  *	other purposes. The return value is the return from the syscall if *	positive or a negative errno code on error. */int dev_ioctl(unsigned int cmd, void *arg){	struct ifreq ifr;	int ret;	char *colon;	/* One special case: SIOCGIFCONF takes ifconf argument	   and requires shared lock, because it sleeps writing	   to user space.	 */	   	if (cmd == SIOCGIFCONF) {		rtnl_shlock();		ret = dev_ifconf((char *) arg);		rtnl_shunlock();		return ret;	}	if (cmd == SIOCGIFNAME) {		return dev_ifname((struct ifreq *)arg);	}	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))		return -EFAULT;	ifr.ifr_name[IFNAMSIZ-1] = 0;	colon = strchr(ifr.ifr_name, ':');	if (colon)		*colon = 0;	/*	 *	See which interface the caller is talking about. 	 */	 	switch(cmd) 	{		/*		 *	These ioctl calls:		 *	- can be done by all.		 *	- atomic and do not require locking.		 *	- return a value		 */		 		case SIOCGIFFLAGS:		case SIOCGIFMETRIC:		case SIOCGIFMTU:		case SIOCGIFHWADDR:		case SIOCGIFSLAVE:		case SIOCGIFMAP:		case SIOCGIFINDEX:		case SIOCGIFTXQLEN:			dev_load(ifr.ifr_name);			read_lock(&dev_base_lock);			ret = dev_ifsioc(&ifr, cmd);			read_unlock(&dev_base_lock);			if (!ret) {				if (colon)					*colon = ':';				if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))					return -EFAULT;			}			return ret;		/*		 *	These ioctl calls:		 *	- require superuser power.		 *	- require strict serialization.		 *	- return a value		 */		 		case SIOCETHTOOL:		case SIOCGMIIPHY:		case SIOCGMIIREG:			if (!capable(CAP_NET_ADMIN))				return -EPERM;			dev_load(ifr.ifr_name);			dev_probe_lock();			rtnl_lock();			ret = dev_ifsioc(&ifr, cmd);			rtnl_unlock();			dev_probe_unlock();			if (!ret) {				if (colon)					*colon = ':';				if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))					return -EFAULT;			}			return ret;		/*		 *	These ioctl calls:		 *	- require superuser power.		 *	- require strict serialization.		 *	- do not return a value		 */		 		case SIOCSIFFLAGS:		case SIOCSIFMETRIC:		case SIOCSIFMTU:		case SIOCSIFMAP:		case SIOCSIFHWADDR:		case SIOCSIFSLAVE:		case SIOCADDMULTI:		case SIOCDELMULTI:		case SIOCSIFHWBROADCAST:		case SIOCSIFTXQLEN:		case SIOCSIFNAME:		case SIOCSMIIREG:		case SIOCBONDENSLAVE:		case SIOCBONDRELEASE:		case SIOCBONDSETHWADDR:		case SIOCBONDSLAVEINFOQUERY:		case SIOCBONDINFOQUERY:		case SIOCBONDCHANGEACTIVE:			if (!capable(CAP_NET_ADMIN))				return -EPERM;			dev_load(ifr.ifr_name);			dev_probe_lock();			rtnl_lock();			ret = dev_ifsioc(&ifr, cmd);			rtnl_unlock();			dev_probe_unlock();			return ret;			case SIOCGIFMEM:			/* Get the per device memory space. We can add this but currently			   do not support it */		case SIOCSIFMEM:			/* Set the per device memory buffer space. Not applicable in our case */		case SIOCSIFLINK:			return -EINVAL;		/*		 *	Unknown or private ioctl.		 */			 		default:			if (cmd >= SIOCDEVPRIVATE &&			    cmd <= SIOCDEVPRIVATE + 15) {				dev_load(ifr.ifr_name);				dev_probe_lock();				rtnl_lock();				ret = dev_ifsioc(&ifr, cmd);				rtnl_unlock();				dev_probe_unlock();				if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))					return -EFAULT;				return ret;			}#ifdef WIRELESS_EXT			/* Take care of Wireless Extensions */			if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {				/* If command is `set a parameter', or				 * `get the encoding parameters', check if				 * the user has the right to do it */				if (IW_IS_SET(cmd) || (cmd == SIOCGIWENCODE)) {					if(!capable(CAP_NET_ADMIN))						return -EPERM;				}				dev_load(ifr.ifr_name);				rtnl_lock();				ret = dev_ifsioc(&ifr, cmd);				rtnl_unlock();				if (!ret && IW_IS_GET(cmd) &&				    copy_to_user(arg, &ifr, sizeof(struct ifreq)))					return -EFAULT;				return ret;			}#endif	/* WIRELESS_EXT */			return -EINVAL;	}}/** *	dev_new_index	-	allocate an ifindex * *	Returns a suitable unique value for a new device interface *	number.  The caller must hold the rtnl semaphore or the *	dev_base_lock to be sure it remains unique. */ int dev_new_index(void){	static int ifindex;	for (;;) {		if (++ifindex <= 0)			ifindex=1;		if (__dev_get_by_index(ifindex) == NULL)			return ifindex;	}}static int dev_boot_phase = 1;/** *	register_netdevice	- register a network device *	@dev: device to register *	 *	Take a completed network device structure and add it to the kernel *	interfaces. A %NETDEV_REGISTER message is sent to the netdev notifier *	chain. 0 is returned on success. A negative errno code is returned *	on a failure to set up the device, or if the name is a duplicate. * *	Callers must hold the rtnl semaphore.  See the comment at the *	end of Space.c for details about the locking.  You may want *	register_netdev() instead of this. * *	BUGS: *	The locking appears insufficient to guarantee two parallel registers *	will not get the same name. */int net_dev_init(void);int register_netdevice(struct net_device *dev){	struct net_device *d, **dp;#ifdef CONFIG_NET_DIVERT	int ret;#endif	spin_lock_init(&dev->queue_lock);	spin_lock_init(&dev->xmit_lock);	dev->xmit_lock_owner = -1;#ifdef CONFIG_NET_FASTROUTE	dev->fastpath_lock=RW_LOCK_UNLOCKED;#endif	if (dev_boot_phase)		net_dev_init();#ifdef CONFIG_NET_DIVERT	ret = alloc_divert_blk(dev);	if (ret)		return ret;#endif /* CONFIG_NET_DIVERT */		dev->iflink = -1;	/* Init, if this function is available */	if (dev->init && dev->init(dev) != 0) {#ifdef CONFIG_NET_DIVERT		free_divert_blk(dev);#endif		return -EIO;	}	dev->ifindex = dev_new_index();	if (dev->iflink == -1)		dev->iflink = dev->ifindex;	/* Check for existence, and append to tail of chain */	for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {		if (d == dev || strcmp(d->name, dev->name) == 0) {#ifdef CONFIG_NET_DIVERT			free_divert_blk(dev);#endif			return -EEXIST;		}	}	/*	 *	nil rebuild_header routine,	 *	that should be never called and used as just bug trap.	 */	if (dev->rebuild_header == NULL)		dev->rebuild_header = default_rebuild_header;	/*	 *	Default initial state at registry is that the	 *	device is present.	 */	set_bit(__LINK_STATE_PRESENT, &dev->state);	dev->next = NULL;	dev_init_scheduler(dev);	write_lock_bh(&dev_base_lock);	*dp = dev;	dev_hold(dev);	dev->deadbeaf = 0;	write_unlock_bh(&dev_base_lock);	/* Notify protocols, that a new device appeared. */	notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);	net_run_sbin_hotplug(dev, "register");	return 0;}/** *	netdev_finish_unregister - complete unregistration *	@dev: device * *	Destroy and free a dead device. A value of zero is returned on *	success. */ int netdev_finish_unregister(struct net_device *dev){	BUG_TRAP(dev->ip_ptr==NULL);	BUG_TRAP(dev->ip6_ptr==NULL);	BUG_TRAP(dev->dn_ptr==NULL);	if (!dev->deadbeaf) {		printk(KERN_ERR "Freeing alive device %p, %s\n", dev, dev->name);		return 0;	}#ifdef NET_REFCNT_DEBUG	printk(KERN_DEBUG "netdev_finish_unregister: %s%s.\n", dev->name,	       (dev->features & NETIF_F_DYNALLOC)?"":", old style");#endif	if (dev->destructor)		dev->destructor(dev);	if (dev->features & NETIF_F_DYNALLOC)		kfree(dev);	return 0;}/** *	unregister_netdevice - remove device from the kernel *	@dev: device * *	This function shuts down a device interface and removes it *	from the kernel tables. On success 0 is returned, on a failure *	a negative errno code is returned. * *	Callers must hold the rtnl semaphore.  See the comment at the *	end of Space.c for details about the locking.  You may want *	unregister_netdev() instead of this. */int unregister_netdevice(struct net_device *dev){	unsigned long now, warning_time;	struct net_device *d, **dp;	/* If device is running, close it first. */	if (dev->flags & IFF_UP)		dev_close(dev);	BUG_TRAP(dev->deadbeaf==0);	dev->deadbeaf = 1;	/* And unlink it from device chain. */	for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) {		if (d == dev) {			write_lock_bh(&dev_base_lock);			*dp = d->next;			write_unlock_bh(&dev_base_lock);			break;		}	}	if (d == NULL) {		printk(KERN_DEBUG "unregister_netdevice: device %s/%p never was registered\n", dev->name, dev);		return -ENODEV;	}	/* Synchronize to net_rx_action. */	br_write_lock_bh(BR_NETPROTO_LOCK);	br_write_unlock_bh(BR_NETPROTO_LOCK);	if (dev_boot_phase == 0) {#ifdef CONFIG_NET_FASTROUTE		dev_clear_fastroute(dev);#endif		/* Shutdown queueing discipline. */		dev_shutdown(dev);		net_run_sbin_hotplug(dev, "unregister");		/* Notify protocols, that we are about to destroy		   this device. They should clean all the things.		 */		notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);		/*		 *	Flush the multicast chain		 */		dev_mc_discard(dev);	}	if (dev->uninit)		dev->uninit(dev);	/* Notifier chain MUST detach us from master device. */	BUG_TRAP(dev->master==NULL);#ifdef CONFIG_NET_DIVERT	free_divert_blk(dev);#endif	i

⌨️ 快捷键说明

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