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

📄 rtl8150.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (c) 2002 Petko Manolov (petkan@users.sourceforge.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */#include <linux/config.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/signal.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/mii.h>#include <linux/ethtool.h>#include <linux/usb.h>#include <asm/uaccess.h>/* Version Information */#define DRIVER_VERSION "v0.6.2 (2004/08/27)"#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"#define DRIVER_DESC "rtl8150 based usb-ethernet driver"#define	IDR			0x0120#define	MAR			0x0126#define	CR			0x012e#define	TCR			0x012f#define	RCR			0x0130#define	TSR			0x0132#define	RSR			0x0133#define	CON0			0x0135#define	CON1			0x0136#define	MSR			0x0137#define	PHYADD			0x0138#define	PHYDAT			0x0139#define	PHYCNT			0x013b#define	GPPC			0x013d#define	BMCR			0x0140#define	BMSR			0x0142#define	ANAR			0x0144#define	ANLP			0x0146#define	AER			0x0148#define CSCR			0x014C  /* This one has the link status */#define CSCR_LINK_STATUS	(1 << 3)#define	IDR_EEPROM		0x1202#define	PHY_READ		0#define	PHY_WRITE		0x20#define	PHY_GO			0x40#define	MII_TIMEOUT		10#define	INTBUFSIZE		8#define	RTL8150_REQT_READ	0xc0#define	RTL8150_REQT_WRITE	0x40#define	RTL8150_REQ_GET_REGS	0x05#define	RTL8150_REQ_SET_REGS	0x05/* Transmit status register errors */#define TSR_ECOL		(1<<5)#define TSR_LCOL		(1<<4)#define TSR_LOSS_CRS		(1<<3)#define TSR_JBR			(1<<2)#define TSR_ERRORS		(TSR_ECOL | TSR_LCOL | TSR_LOSS_CRS | TSR_JBR)/* Receive status register errors */#define RSR_CRC			(1<<2)#define RSR_FAE			(1<<1)#define RSR_ERRORS		(RSR_CRC | RSR_FAE)/* Media status register definitions */#define MSR_DUPLEX		(1<<4)#define MSR_SPEED		(1<<3)#define MSR_LINK		(1<<2)/* Interrupt pipe data */#define INT_TSR			0x00#define INT_RSR			0x01#define INT_MSR			0x02#define INT_WAKSR		0x03#define INT_TXOK_CNT		0x04#define INT_RXLOST_CNT		0x05#define INT_CRERR_CNT		0x06#define INT_COL_CNT		0x07/* Transmit status register errors */#define TSR_ECOL		(1<<5)#define TSR_LCOL		(1<<4)#define TSR_LOSS_CRS		(1<<3)#define TSR_JBR			(1<<2)#define TSR_ERRORS		(TSR_ECOL | TSR_LCOL | TSR_LOSS_CRS | TSR_JBR)/* Receive status register errors */#define RSR_CRC			(1<<2)#define RSR_FAE			(1<<1)#define RSR_ERRORS		(RSR_CRC | RSR_FAE)/* Media status register definitions */#define MSR_DUPLEX		(1<<4)#define MSR_SPEED		(1<<3)#define MSR_LINK		(1<<2)/* Interrupt pipe data */#define INT_TSR			0x00#define INT_RSR			0x01#define INT_MSR			0x02#define INT_WAKSR		0x03#define INT_TXOK_CNT		0x04#define INT_RXLOST_CNT		0x05#define INT_CRERR_CNT		0x06#define INT_COL_CNT		0x07#define	RTL8150_MTU		1540#define	RTL8150_TX_TIMEOUT	(HZ)#define	RX_SKB_POOL_SIZE	4/* rtl8150 flags */#define	RTL8150_HW_CRC		0#define	RX_REG_SET		1#define	RTL8150_UNPLUG		2#define	RX_URB_FAIL		3/* Define these values to match your device */#define VENDOR_ID_REALTEK		0x0bda#define	VENDOR_ID_MELCO			0x0411#define VENDOR_ID_MICRONET		0x3980#define	VENDOR_ID_LONGSHINE		0x07b8#define PRODUCT_ID_RTL8150		0x8150#define	PRODUCT_ID_LUAKTX		0x0012#define	PRODUCT_ID_LCS8138TX		0x401a#define PRODUCT_ID_SP128AR		0x0003#undef	EEPROM_WRITE/* table of devices that work with this driver */static struct usb_device_id rtl8150_table[] = {	{USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8150)},	{USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)},	{USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)},	{USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)},	{}};MODULE_DEVICE_TABLE(usb, rtl8150_table);struct rtl8150 {	unsigned long flags;	struct usb_device *udev;	struct tasklet_struct tl;	struct net_device_stats stats;	struct net_device *netdev;	struct urb *rx_urb, *tx_urb, *intr_urb, *ctrl_urb;	struct sk_buff *tx_skb, *rx_skb;	struct sk_buff *rx_skb_pool[RX_SKB_POOL_SIZE];	spinlock_t rx_pool_lock;	struct usb_ctrlrequest dr;	int intr_interval;	__le16 rx_creg;	u8 *intr_buff;	u8 phy;};typedef struct rtl8150 rtl8150_t;static void fill_skb_pool(rtl8150_t *);static void free_skb_pool(rtl8150_t *);static inline struct sk_buff *pull_skb(rtl8150_t *);static void rtl8150_disconnect(struct usb_interface *intf);static int rtl8150_probe(struct usb_interface *intf,			   const struct usb_device_id *id);static const char driver_name [] = "rtl8150";static struct usb_driver rtl8150_driver = {	.owner =	THIS_MODULE,	.name =		driver_name,	.probe =	rtl8150_probe,	.disconnect =	rtl8150_disconnect,	.id_table =	rtl8150_table,};/*****	device related part of the code***/static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data){	return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),			       RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,			       indx, 0, data, size, 500);}static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data){	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),			       RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,			       indx, 0, data, size, 500);}static void ctrl_callback(struct urb *urb, struct pt_regs *regs){	rtl8150_t *dev;	switch (urb->status) {	case 0:		break;	case -EINPROGRESS:		break;	case -ENOENT:		break;	default:		warn("ctrl urb status %d", urb->status);	}	dev = urb->context;	clear_bit(RX_REG_SET, &dev->flags);}static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size){	int ret;	if (test_bit(RX_REG_SET, &dev->flags))		return -EAGAIN;	dev->dr.bRequestType = RTL8150_REQT_WRITE;	dev->dr.bRequest = RTL8150_REQ_SET_REGS;	dev->dr.wValue = cpu_to_le16(indx);	dev->dr.wIndex = 0;	dev->dr.wLength = cpu_to_le16(size);	dev->ctrl_urb->transfer_buffer_length = size;	usb_fill_control_urb(dev->ctrl_urb, dev->udev,			 usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr,			 &dev->rx_creg, size, ctrl_callback, dev);	if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC)))		err("control request submission failed: %d", ret);	else		set_bit(RX_REG_SET, &dev->flags);	return ret;}static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg){	int i;	u8 data[3], tmp;	data[0] = phy;	data[1] = data[2] = 0;	tmp = indx | PHY_READ | PHY_GO;	i = 0;	set_registers(dev, PHYADD, sizeof(data), data);	set_registers(dev, PHYCNT, 1, &tmp);	do {		get_registers(dev, PHYCNT, 1, data);	} while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT));	if (i < MII_TIMEOUT) {		get_registers(dev, PHYDAT, 2, data);		*reg = data[0] | (data[1] << 8);		return 0;	} else		return 1;}static int write_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 reg){	int i;	u8 data[3], tmp;	data[0] = phy;	*(data + 1) = cpu_to_le16p(&reg);	tmp = indx | PHY_WRITE | PHY_GO;	i = 0;	set_registers(dev, PHYADD, sizeof(data), data);	set_registers(dev, PHYCNT, 1, &tmp);	do {		get_registers(dev, PHYCNT, 1, data);	} while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT));	if (i < MII_TIMEOUT)		return 0;	else		return 1;}static inline void set_ethernet_addr(rtl8150_t * dev){	u8 node_id[6];	get_registers(dev, IDR, sizeof(node_id), node_id);	memcpy(dev->netdev->dev_addr, node_id, sizeof(node_id));}static int rtl8150_set_mac_address(struct net_device *netdev, void *p){	struct sockaddr *addr = p;	rtl8150_t *dev = netdev_priv(netdev);	int i;	if (netif_running(netdev))		return -EBUSY;	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);	dbg("%s: Setting MAC address to ", netdev->name);	for (i = 0; i < 5; i++)		dbg("%02X:", netdev->dev_addr[i]);	dbg("%02X\n", netdev->dev_addr[i]);	/* Set the IDR registers. */	set_registers(dev, IDR, sizeof(netdev->dev_addr), netdev->dev_addr);#ifdef EEPROM_WRITE	{	u8 cr;	/* Get the CR contents. */	get_registers(dev, CR, 1, &cr);	/* Set the WEPROM bit (eeprom write enable). */	cr |= 0x20;	set_registers(dev, CR, 1, &cr);	/* Write the MAC address into eeprom. Eeprom writes must be word-sized,	   so we need to split them up. */	for (i = 0; i * 2 < netdev->addr_len; i++) {		set_registers(dev, IDR_EEPROM + (i * 2), 2, 		netdev->dev_addr + (i * 2));	}	/* Clear the WEPROM bit (preventing accidental eeprom writes). */	cr &= 0xdf;	set_registers(dev, CR, 1, &cr);	}#endif	return 0;}static int rtl8150_reset(rtl8150_t * dev){	u8 data = 0x10;	int i = HZ;	set_registers(dev, CR, 1, &data);	do {		get_registers(dev, CR, 1, &data);	} while ((data & 0x10) && --i);	return (i > 0) ? 1 : 0;}static int alloc_all_urbs(rtl8150_t * dev){	dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL);	if (!dev->rx_urb)		return 0;	dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL);	if (!dev->tx_urb) {		usb_free_urb(dev->rx_urb);		return 0;	}	dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);	if (!dev->intr_urb) {		usb_free_urb(dev->rx_urb);		usb_free_urb(dev->tx_urb);		return 0;	}	dev->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);	if (!dev->intr_urb) {		usb_free_urb(dev->rx_urb);		usb_free_urb(dev->tx_urb);		usb_free_urb(dev->intr_urb);		return 0;	}	return 1;}static void free_all_urbs(rtl8150_t * dev){	usb_free_urb(dev->rx_urb);	usb_free_urb(dev->tx_urb);	usb_free_urb(dev->intr_urb);	usb_free_urb(dev->ctrl_urb);}static void unlink_all_urbs(rtl8150_t * dev){	usb_kill_urb(dev->rx_urb);	usb_kill_urb(dev->tx_urb);	usb_kill_urb(dev->intr_urb);	usb_kill_urb(dev->ctrl_urb);}static inline struct sk_buff *pull_skb(rtl8150_t *dev){	struct sk_buff *skb;	int i;	for (i = 0; i < RX_SKB_POOL_SIZE; i++) {		if (dev->rx_skb_pool[i]) {			skb = dev->rx_skb_pool[i];			dev->rx_skb_pool[i] = NULL;			return skb;		}	}	return NULL;}static void read_bulk_callback(struct urb *urb, struct pt_regs *regs){	rtl8150_t *dev;	unsigned pkt_len, res;	struct sk_buff *skb;	struct net_device *netdev;	u16 rx_stat;	dev = urb->context;	if (!dev)		return;	if (test_bit(RTL8150_UNPLUG, &dev->flags))		return;	netdev = dev->netdev;	if (!netif_device_present(netdev))		return;	switch (urb->status) {	case 0:		break;	case -ENOENT:		return;	/* the urb is in unlink state */	case -ETIMEDOUT:		warn("may be reset is needed?..");		goto goon;	default:		warn("Rx status %d", urb->status);		goto goon;	}	if (!dev->rx_skb)		goto resched;	/* protect against short packets (tell me why we got some?!?) */	if (urb->actual_length < 4)		goto goon;	res = urb->actual_length;	rx_stat = le16_to_cpu(*(__le16 *)(urb->transfer_buffer + res - 4));	pkt_len = res - 4;	skb_put(dev->rx_skb, pkt_len);	dev->rx_skb->protocol = eth_type_trans(dev->rx_skb, netdev);	netif_rx(dev->rx_skb);	dev->stats.rx_packets++;	dev->stats.rx_bytes += pkt_len;	spin_lock(&dev->rx_pool_lock);	skb = pull_skb(dev);	spin_unlock(&dev->rx_pool_lock);	if (!skb)		goto resched;	dev->rx_skb = skb;goon:	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);	if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {		set_bit(RX_URB_FAIL, &dev->flags);		goto resched;	} else {		clear_bit(RX_URB_FAIL, &dev->flags);

⌨️ 快捷键说明

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