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

📄 usbnet.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	u16			status;	u16			*vp = kmalloc (sizeof (u16), GFP_KERNEL);	if (!vp)		return -ENOMEM;	retval = nc_register_read (dev, REG_STATUS, vp);	status = *vp;	kfree (vp);	if (retval != 0) {		dbg ("%s net1080_check_conn read - %d", dev->net->name, retval);		return retval;	}	if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER)		return -ENOLINK;	return 0;}static void nc_flush_complete (struct urb *urb, struct pt_regs *regs){	kfree (urb->context);	usb_free_urb(urb);}static void nc_ensure_sync (struct usbnet *dev){	dev->frame_errors++;	if (dev->frame_errors > 5) {		struct urb		*urb;		struct usb_ctrlrequest	*req;		int			status;		/* Send a flush */		urb = usb_alloc_urb (0, SLAB_ATOMIC);		if (!urb)			return;		req = kmalloc (sizeof *req, GFP_ATOMIC);		if (!req) {			usb_free_urb (urb);			return;		}		req->bRequestType = USB_DIR_OUT			| USB_TYPE_VENDOR			| USB_RECIP_DEVICE;		req->bRequest = REQUEST_REGISTER;		req->wValue = cpu_to_le16 (USBCTL_FLUSH_THIS				| USBCTL_FLUSH_OTHER);		req->wIndex = cpu_to_le16 (REG_USBCTL);		req->wLength = cpu_to_le16 (0);		/* queue an async control request, we don't need		 * to do anything when it finishes except clean up.		 */		usb_fill_control_urb (urb, dev->udev,			usb_sndctrlpipe (dev->udev, 0),			(unsigned char *) req,			NULL, 0,			nc_flush_complete, req);		status = usb_submit_urb (urb, GFP_ATOMIC);		if (status) {			kfree (req);			usb_free_urb (urb);			return;		}		devdbg (dev, "flush net1080; too many framing errors");		dev->frame_errors = 0;	}}static int net1080_rx_fixup (struct usbnet *dev, struct sk_buff *skb){	struct nc_header	*header;	struct nc_trailer	*trailer;	if (!(skb->len & 0x01)			|| MIN_FRAMED > skb->len			|| skb->len > FRAMED_SIZE (dev->net->mtu)) {		dev->stats.rx_frame_errors++;		dbg ("rx framesize %d range %d..%d mtu %d", skb->len,			(int)MIN_FRAMED, (int)FRAMED_SIZE (dev->net->mtu),			dev->net->mtu);		nc_ensure_sync (dev);		return 0;	}	header = (struct nc_header *) skb->data;	le16_to_cpus (&header->hdr_len);	le16_to_cpus (&header->packet_len);	if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) {		dev->stats.rx_frame_errors++;		dbg ("packet too big, %d", header->packet_len);		nc_ensure_sync (dev);		return 0;	} else if (header->hdr_len < MIN_HEADER) {		dev->stats.rx_frame_errors++;		dbg ("header too short, %d", header->hdr_len);		nc_ensure_sync (dev);		return 0;	} else if (header->hdr_len > MIN_HEADER) {		// out of band data for us?		dbg ("header OOB, %d bytes",			header->hdr_len - MIN_HEADER);		nc_ensure_sync (dev);		// switch (vendor/product ids) { ... }	}	skb_pull (skb, header->hdr_len);	trailer = (struct nc_trailer *)		(skb->data + skb->len - sizeof *trailer);	skb_trim (skb, skb->len - sizeof *trailer);	if ((header->packet_len & 0x01) == 0) {		if (skb->data [header->packet_len] != PAD_BYTE) {			dev->stats.rx_frame_errors++;			dbg ("bad pad");			return 0;		}		skb_trim (skb, skb->len - 1);	}	if (skb->len != header->packet_len) {		dev->stats.rx_frame_errors++;		dbg ("bad packet len %d (expected %d)",			skb->len, header->packet_len);		nc_ensure_sync (dev);		return 0;	}	if (header->packet_id != get_unaligned (&trailer->packet_id)) {		dev->stats.rx_fifo_errors++;		dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",			header->packet_id, trailer->packet_id);		return 0;	}#if 0	devdbg (dev, "frame <rx h %d p %d id %d", header->hdr_len,		header->packet_len, header->packet_id);#endif	dev->frame_errors = 0;	return 1;}static struct sk_buff *net1080_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags){	int			padlen;	struct sk_buff		*skb2;	padlen = ((skb->len + sizeof (struct nc_header)			+ sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;	if (!skb_cloned (skb)) {		int	headroom = skb_headroom (skb);		int	tailroom = skb_tailroom (skb);		if ((padlen + sizeof (struct nc_trailer)) <= tailroom			    && sizeof (struct nc_header) <= headroom)			/* There's enough head and tail room */			return skb;		if ((sizeof (struct nc_header) + padlen					+ sizeof (struct nc_trailer)) <				(headroom + tailroom)) {			/* There's enough total room, so just readjust */			skb->data = memmove (skb->head						+ sizeof (struct nc_header),					    skb->data, skb->len);			skb->tail = skb->data + skb->len;			return skb;		}	}	/* Create a new skb to use with the correct size */	skb2 = skb_copy_expand (skb,				sizeof (struct nc_header),				sizeof (struct nc_trailer) + padlen,				flags);	dev_kfree_skb_any (skb);	return skb2;}static const struct driver_info	net1080_info = {	.description =	"NetChip TurboCONNECT",	.flags =	FLAG_FRAMING_NC,	.reset =	net1080_reset,	.check_connect =net1080_check_connect,	.rx_fixup =	net1080_rx_fixup,	.tx_fixup =	net1080_tx_fixup,};#endif /* CONFIG_USB_NET1080 */#ifdef CONFIG_USB_PL2301#define	HAVE_HARDWARE/*------------------------------------------------------------------------- * * Prolific PL-2301/PL-2302 driver ... http://www.prolifictech.com * * The protocol and handshaking used here should be bug-compatible * with the Linux 2.2 "plusb" driver, by Deti Fliegl. * *-------------------------------------------------------------------------*//* * Bits 0-4 can be used for software handshaking; they're set from * one end, cleared from the other, "read" with the interrupt byte. */#define	PL_S_EN		(1<<7)		/* (feature only) suspend enable *//* reserved bit -- rx ready (6) ? */#define	PL_TX_READY	(1<<5)		/* (interrupt only) transmit ready */#define	PL_RESET_OUT	(1<<4)		/* reset output pipe */#define	PL_RESET_IN	(1<<3)		/* reset input pipe */#define	PL_TX_C		(1<<2)		/* transmission complete */#define	PL_TX_REQ	(1<<1)		/* transmission received */#define	PL_PEER_E	(1<<0)		/* peer exists */static inline intpl_vendor_req (struct usbnet *dev, u8 req, u8 val, u8 index){	return usb_control_msg (dev->udev,		usb_rcvctrlpipe (dev->udev, 0),		req,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		val, index,		NULL, 0,		CONTROL_TIMEOUT_JIFFIES);}static inline intpl_clear_QuickLink_features (struct usbnet *dev, int val){	return pl_vendor_req (dev, 1, (u8) val, 0);}static inline intpl_set_QuickLink_features (struct usbnet *dev, int val){	return pl_vendor_req (dev, 3, (u8) val, 0);}/*-------------------------------------------------------------------------*/static int pl_reset (struct usbnet *dev){	/* some units seem to need this reset, others reject it utterly.	 * FIXME be more like "naplink" or windows drivers.	 */	(void) pl_set_QuickLink_features (dev,		PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E);	return 0;}static const struct driver_info	prolific_info = {	.description =	"Prolific PL-2301/PL-2302",	.flags =	FLAG_NO_SETINT,		/* some PL-2302 versions seem to fail usb_set_interface() */	.reset =	pl_reset,};#endif /* CONFIG_USB_PL2301 */#ifdef CONFIG_USB_KC2190#define HAVE_HARDWAREstatic const struct driver_info kc2190_info = {	.description =  "KC Technology KC-190",};#endif /* CONFIG_USB_KC2190 */#ifdef	CONFIG_USB_ARMLINUX#define	HAVE_HARDWARE/*------------------------------------------------------------------------- * * Intel's SA-1100 chip integrates basic USB support, and is used * in PDAs like some iPaqs, the Yopy, some Zaurus models, and more. * When they run Linux, arch/arm/mach-sa1100/usb-eth.c may be used to * network using minimal USB framing data. * * This describes the driver currently in standard ARM Linux kernels. * The Zaurus uses a different driver (see later). * * PXA25x and PXA210 use XScale cores (ARM v5TE) with better USB support * and different USB endpoint numbering than the SA1100 devices.  The * mach-pxa/usb-eth.c driver re-uses the device ids from mach-sa1100 * so we rely on the endpoint descriptors. * *-------------------------------------------------------------------------*/static const struct driver_info	linuxdev_info = {	.description =	"Linux Device",	.check_connect = always_connected,};static const struct driver_info	yopy_info = {	.description =	"Yopy",	.check_connect = always_connected,};static const struct driver_info	blob_info = {	.description =	"Boot Loader OBject",	.check_connect = always_connected,};#endif	/* CONFIG_USB_ARMLINUX */#ifdef CONFIG_USB_ZAURUS#define	HAVE_HARDWARE#include <linux/crc32.h>/*------------------------------------------------------------------------- * * Zaurus is also a SA-1110 based PDA, but one using a different driver * (and framing) for its USB slave/gadget controller than the case above. * * For the current version of that driver, the main way that framing is * nonstandard (also from perspective of the CDC ethernet model!) is a * crc32, added to help detect when some sa1100 usb-to-memory DMA errata * haven't been fully worked around. * * PXA based models use the same framing, and also can't implement * set_interface properly. * *-------------------------------------------------------------------------*/static struct sk_buff *zaurus_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags){	int			padlen;	struct sk_buff		*skb2;	padlen = 2;	if (!skb_cloned (skb)) {		int	tailroom = skb_tailroom (skb);		if ((padlen + 4) <= tailroom)			goto done;	}	skb2 = skb_copy_expand (skb, 0, 4 + padlen, flags);	dev_kfree_skb_any (skb);	skb = skb2;	if (skb) {		u32		fcs;done:		fcs = crc32_le (~0, skb->data, skb->len);		fcs = ~fcs;		*skb_put (skb, 1) = fcs       & 0xff;		*skb_put (skb, 1) = (fcs>> 8) & 0xff;		*skb_put (skb, 1) = (fcs>>16) & 0xff;		*skb_put (skb, 1) = (fcs>>24) & 0xff;	}	return skb;}static const struct driver_info	zaurus_sl5x00_info = {	.description =	"Sharp Zaurus SL-5x00",	.flags =	FLAG_FRAMING_Z,	.check_connect = always_connected,	.bind =		generic_cdc_bind,	.unbind =	cdc_unbind,	.tx_fixup = 	zaurus_tx_fixup,};#define	ZAURUS_STRONGARM_INFO	((unsigned long)&zaurus_sl5x00_info)static const struct driver_info	zaurus_pxa_info = {	.description =	"Sharp Zaurus, PXA-2xx based",	.flags =	FLAG_FRAMING_Z,	.check_connect = always_connected,	.bind =		generic_cdc_bind,	.unbind =	cdc_unbind,	.tx_fixup = 	zaurus_tx_fixup,};#define	ZAURUS_PXA_INFO		((unsigned long)&zaurus_pxa_info)static const struct driver_info	olympus_mxl_info = {	.description =	"Olympus R1000",	.flags =	FLAG_FRAMING_Z,	.check_connect = always_connected,	.bind =		generic_cdc_bind,	.unbind =	cdc_unbind,	.tx_fixup = 	zaurus_tx_fixup,};#define	OLYMPUS_MXL_INFO	((unsigned long)&olympus_mxl_info)#else/* blacklist all those devices */#define	ZAURUS_STRONGARM_INFO	0#define	ZAURUS_PXA_INFO		0#define	OLYMPUS_MXL_INFO	0#endif/*------------------------------------------------------------------------- * * Network Device Driver (peer link to "Host Device", from USB host) * *-------------------------------------------------------------------------*/static int usbnet_change_mtu (struct net_device *net, int new_mtu){	struct usbnet	*dev = netdev_priv(net);	if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)		return -EINVAL;#ifdef	CONFIG_USB_NET1080	if (((dev->driver_info->flags) & FLAG_FRAMING_NC)) {		if (FRAMED_SIZE (new_mtu) > MAX_PACKET)			return -EINVAL;	}#endif#ifdef	CONFIG_USB_GENESYS	if (((dev->driver_info->flags) & FLAG_FRAMING_GL)			&& new_mtu > GL_MAX_PACKET_LEN)		return -EINVAL;#endif	// no second zero-length packet read wanted after mtu-sized packets	if (((new_mtu + sizeof (struct ethhdr)) % dev->maxpacket) == 0)		return -EDOM;	net->mtu = new_mtu;	return 0;}/*-------------------------------------------------------------------------*/static struct net_device_stats *usbnet_get_stats (struct net_device *net){	struct usbnet	*dev = netdev_priv(net);	return &dev->stats;}/*-------------------------------------------------------------------------*//* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from * completion callbacks.  2.5 should have fixed those bugs... */static void defer_bh (struct usbnet *dev, struct sk_buff *skb){	struct sk_buff_head	*list = skb->list;	unsigned long		flags;	spin_lock_irqsave (&list->lock, flags);	__skb_unlink (skb, list);	spin_unlock (&list->lock);	spin_lock (&dev->done.lock);	__skb_queue_tail (&dev->done, skb);	if (dev->done.qlen == 1)		tasklet_schedule (&dev->bh);	spin_unlock_irqrestore (&dev->done.lock, flags);}/* some work can't be done in tasklets, so we use keventd * * NOTE:  annoying asymmetry:  if it's active, schedule_work() fails, * but tasklet_schedule() doesn't.  hope the failure is rare. */static void defer_kevent (struct usbnet *dev, int work){	set_bit (work, &dev->flags);	if (!schedule_work (&dev->kevent))		deverr (dev, "kevent %d may have been dropped", work);	else		devdbg (dev, "kevent %d scheduled", work);}/*-------------------------------------------------------------------------*/static void rx_complete (struct

⌨️ 快捷键说明

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