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

📄 sir_dev.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Check problems */	if(spin_is_locked(&dev->tx_lock)) {		IRDA_DEBUG(3, "%s(), write not completed\n", __FUNCTION__);	}	/* serialize with write completion */	spin_lock_irqsave(&dev->tx_lock, flags);        /* Copy skb to tx_buff while wrapping, stuffing and making CRC */	dev->tx_buff.len = async_wrap_skb(skb, dev->tx_buff.data, dev->tx_buff.truesize); 	/* transmission will start now - disable receive.	 * if we are just in the middle of an incoming frame,	 * treat it as collision. probably it's a good idea to	 * reset the rx_buf OUTSIDE_FRAME in this case too?	 */	atomic_set(&dev->enable_rx, 0);	if (unlikely(sirdev_is_receiving(dev)))		dev->stats.collisions++;	actual = dev->drv->do_write(dev, dev->tx_buff.data, dev->tx_buff.len);	if (likely(actual > 0)) {		dev->tx_skb = skb;		ndev->trans_start = jiffies;		dev->tx_buff.data += actual;		dev->tx_buff.len -= actual;	}	else if (unlikely(actual < 0)) {		/* could be dropped later when we have tx_timeout to recover */		ERROR("%s: drv->do_write failed (%d)\n", __FUNCTION__, actual);		dev_kfree_skb_any(skb);		dev->stats.tx_errors++;		      		dev->stats.tx_dropped++;		      		netif_wake_queue(ndev);	}	spin_unlock_irqrestore(&dev->tx_lock, flags);	return 0;}/* called from network layer with rtnl hold */static int sirdev_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd){	struct if_irda_req *irq = (struct if_irda_req *) rq;	struct sir_dev *dev = ndev->priv;	int ret = 0;	ASSERT(dev != NULL, return -1;);	IRDA_DEBUG(3, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, ndev->name, cmd);		switch (cmd) {	case SIOCSBANDWIDTH: /* Set bandwidth */		if (!capable(CAP_NET_ADMIN))			ret = -EPERM;		else			ret = sirdev_schedule_speed(dev, irq->ifr_baudrate);		/* cannot sleep here for completion		 * we are called from network layer with rtnl hold		 */		break;	case SIOCSDONGLE: /* Set dongle */		if (!capable(CAP_NET_ADMIN))			ret = -EPERM;		else			ret = sirdev_schedule_dongle_open(dev, irq->ifr_dongle);		/* cannot sleep here for completion		 * we are called from network layer with rtnl hold		 */		break;	case SIOCSMEDIABUSY: /* Set media busy */		if (!capable(CAP_NET_ADMIN))			ret = -EPERM;		else			irda_device_set_media_busy(dev->netdev, TRUE);		break;	case SIOCGRECEIVING: /* Check if we are receiving right now */		irq->ifr_receiving = sirdev_is_receiving(dev);		break;	case SIOCSDTRRTS:		if (!capable(CAP_NET_ADMIN))			ret = -EPERM;		else			ret = sirdev_schedule_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);		/* cannot sleep here for completion		 * we are called from network layer with rtnl hold		 */		break;	case SIOCSMODE:#if 0		if (!capable(CAP_NET_ADMIN))			ret = -EPERM;		else			ret = sirdev_schedule_mode(dev, irq->ifr_mode);		/* cannot sleep here for completion		 * we are called from network layer with rtnl hold		 */		break;#endif	default:		ret = -EOPNOTSUPP;	}		return ret;}/* ----------------------------------------------------------------------------- */#define SIRBUF_ALLOCSIZE 4269	/* worst case size of a wrapped IrLAP frame */static int sirdev_alloc_buffers(struct sir_dev *dev){	dev->tx_buff.truesize = SIRBUF_ALLOCSIZE;	dev->rx_buff.truesize = IRDA_SKB_MAX_MTU; 	/* Bootstrap ZeroCopy Rx */	dev->rx_buff.skb = __dev_alloc_skb(dev->rx_buff.truesize, GFP_KERNEL);	if (dev->rx_buff.skb == NULL)		return -ENOMEM;	skb_reserve(dev->rx_buff.skb, 1);	dev->rx_buff.head = dev->rx_buff.skb->data;	dev->tx_buff.head = kmalloc(dev->tx_buff.truesize, GFP_KERNEL);	if (dev->tx_buff.head == NULL) {		kfree_skb(dev->rx_buff.skb);		dev->rx_buff.skb = NULL;		dev->rx_buff.head = NULL;		return -ENOMEM;	}	dev->tx_buff.data = dev->tx_buff.head;	dev->rx_buff.data = dev->rx_buff.head;	dev->tx_buff.len = 0;	dev->rx_buff.len = 0;	dev->rx_buff.in_frame = FALSE;	dev->rx_buff.state = OUTSIDE_FRAME;	return 0;};static void sirdev_free_buffers(struct sir_dev *dev){	if (dev->rx_buff.skb)		kfree_skb(dev->rx_buff.skb);	if (dev->tx_buff.head)		kfree(dev->tx_buff.head);	dev->rx_buff.head = dev->tx_buff.head = NULL;	dev->rx_buff.skb = NULL;}static int sirdev_open(struct net_device *ndev){	struct sir_dev *dev = ndev->priv;	const struct sir_driver *drv = dev->drv;	if (!drv)		return -ENODEV;	/* increase the reference count of the driver module before doing serious stuff */	if (!try_module_get(drv->owner))		return -ESTALE;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);	if (sirdev_alloc_buffers(dev))		goto errout_dec;	if (!dev->drv->start_dev  ||  dev->drv->start_dev(dev))		goto errout_free;	sirdev_enable_rx(dev);	dev->raw_tx = 0;	netif_start_queue(ndev);	dev->irlap = irlap_open(ndev, &dev->qos, dev->hwname);	if (!dev->irlap)		goto errout_stop;	netif_wake_queue(ndev);	IRDA_DEBUG(2, "%s - done, speed = %d\n", __FUNCTION__, dev->speed);	return 0;errout_stop:	atomic_set(&dev->enable_rx, 0);	if (dev->drv->stop_dev)		dev->drv->stop_dev(dev);errout_free:	sirdev_free_buffers(dev);errout_dec:	module_put(drv->owner);	return -EAGAIN;}static int sirdev_close(struct net_device *ndev){	struct sir_dev *dev = ndev->priv;	const struct sir_driver *drv;//	IRDA_DEBUG(0, "%s\n", __FUNCTION__);	netif_stop_queue(ndev);	down(&dev->fsm.sem);		/* block on pending config completion */	atomic_set(&dev->enable_rx, 0);	if (unlikely(!dev->irlap))		goto out;	irlap_close(dev->irlap);	dev->irlap = NULL;	drv = dev->drv;	if (unlikely(!drv  ||  !dev->priv))		goto out;	if (drv->stop_dev)		drv->stop_dev(dev);	sirdev_free_buffers(dev);	module_put(drv->owner);out:	dev->speed = 0;	up(&dev->fsm.sem);	return 0;}/* ----------------------------------------------------------------------------- */struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *name){	struct net_device *ndev;	struct sir_dev *dev;	IRDA_DEBUG(0, "%s - %s\n", __FUNCTION__, name);	/* instead of adding tests to protect against drv->do_write==NULL	 * at several places we refuse to create a sir_dev instance for	 * drivers which don't implement do_write.	 */	if (!drv ||  !drv->do_write)		return NULL;	/*	 *  Allocate new instance of the device	 */	ndev = alloc_irdadev(sizeof(*dev));	if (ndev == NULL) {		ERROR("%s - Can't allocate memory for IrDA control block!\n", __FUNCTION__);		goto out;	}	dev = ndev->priv;	irda_init_max_qos_capabilies(&dev->qos);	dev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;	dev->qos.min_turn_time.bits = drv->qos_mtt_bits;	irda_qos_bits_to_value(&dev->qos);	strncpy(dev->hwname, name, sizeof(dev->hwname)-1);	atomic_set(&dev->enable_rx, 0);	dev->tx_skb = NULL;	spin_lock_init(&dev->tx_lock);	init_MUTEX(&dev->fsm.sem);	INIT_LIST_HEAD(&dev->fsm.rq.lh_request);	dev->fsm.rq.pending = 0;	init_timer(&dev->fsm.rq.timer);	dev->drv = drv;	dev->netdev = ndev;	SET_MODULE_OWNER(ndev);	/* Override the network functions we need to use */	ndev->hard_start_xmit = sirdev_hard_xmit;	ndev->open = sirdev_open;	ndev->stop = sirdev_close;	ndev->get_stats = sirdev_get_stats;	ndev->do_ioctl = sirdev_ioctl;	if (register_netdev(ndev)) {		ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);		goto out_freenetdev;	}	return dev;out_freenetdev:	free_netdev(ndev);out:	return NULL;}int sirdev_put_instance(struct sir_dev *dev){	int err = 0;	IRDA_DEBUG(0, "%s\n", __FUNCTION__);	atomic_set(&dev->enable_rx, 0);	netif_carrier_off(dev->netdev);	netif_device_detach(dev->netdev);	if (dev->dongle_drv)		err = sirdev_schedule_dongle_close(dev);	if (err)		ERROR("%s - error %d\n", __FUNCTION__, err);	sirdev_close(dev->netdev);	down(&dev->fsm.sem);	dev->fsm.state = SIRDEV_STATE_DEAD;	/* mark staled */	dev->dongle_drv = NULL;	dev->priv = NULL;	up(&dev->fsm.sem);	/* Remove netdevice */	unregister_netdev(dev->netdev);	free_netdev(dev->netdev);	return 0;}

⌨️ 快捷键说明

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