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

📄 rtl8150.c

📁 ep9315平台下USB驱动的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	dev = urb->context;	if (!dev)		return;	if (!netif_device_present(dev->netdev))		return;	if (urb->status)		info("%s: Tx status %d", dev->netdev->name, urb->status);	dev->netdev->trans_start = jiffies;	netif_wake_queue(dev->netdev);}void intr_callback(struct urb *urb){	rtl8150_t *dev;	dev = urb->context;	if (!dev)		return;	switch (urb->status) {	case 0:		break;	case -ENOENT:		return;	default:		info("%s: intr status %d", dev->netdev->name, urb->status);	}}/*****	network related part of the code***/static int enable_net_traffic(rtl8150_t * dev){	u8 cr, tcr, rcr, msr;	if (rtl8150_reset(dev)) {		warn("%s - device reset failed", __FUNCTION__);	}	dev->rx_creg = rcr = 0x9e;	/* bit7=1 attach Rx info at the end */	tcr = 0xd8;	cr = 0x0c;	set_registers(dev, RCR, 1, &rcr);	set_registers(dev, TCR, 1, &tcr);	set_registers(dev, CR, 1, &cr);	get_registers(dev, MSR, 1, &msr);	return 0;}static void disable_net_traffic(rtl8150_t * dev){	u8 cr;	get_registers(dev, CR, 1, &cr);	cr &= 0xf3;	set_registers(dev, CR, 1, &cr);}static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev){	return &((rtl8150_t *) dev->priv)->stats;}static void rtl8150_tx_timeout(struct net_device *netdev){	rtl8150_t *dev;	dev = netdev->priv;	if (!dev)		return;	warn("%s: Tx timeout.", netdev->name);	dev->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;	usb_unlink_urb(dev->tx_urb);	dev->stats.tx_errors++;}static void rtl8150_set_multicast(struct net_device *netdev){	rtl8150_t *dev;	dev = netdev->priv;	netif_stop_queue(netdev);	if (netdev->flags & IFF_PROMISC) {		dev->rx_creg |= 0x0001;		info("%s: promiscuous mode", netdev->name);	} else if ((netdev->mc_count > multicast_filter_limit) ||		   (netdev->flags & IFF_ALLMULTI)) {		dev->rx_creg &= 0xfffe;		dev->rx_creg |= 0x0002;		info("%s: allmulti set", netdev->name);	} else {		/* ~RX_MULTICAST, ~RX_PROMISCUOUS */		dev->rx_creg &= 0x00fc;	}	async_set_registers(dev, RCR, 2, &dev->rx_creg);	netif_wake_queue(netdev);}static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev){	rtl8150_t *dev;	int count, res;	netif_stop_queue(netdev);	dev = netdev->priv;	count = (skb->len < 60) ? 60 : skb->len;	count = (count & 0x3f) ? count : count + 1;	memcpy(dev->tx_buff, skb->data, skb->len);	FILL_BULK_URB(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2),		      dev->tx_buff, count, write_bulk_callback, dev);	dev->tx_urb->transfer_buffer_length = count;	if ((res = usb_submit_urb(dev->tx_urb))) {		warn("failed tx_urb %d\n", res);		dev->stats.tx_errors++;		netif_start_queue(netdev);	} else {		dev->stats.tx_packets++;		dev->stats.tx_bytes += skb->len;		netdev->trans_start = jiffies;	}	dev_kfree_skb(skb);	return 0;}static int rtl8150_open(struct net_device *netdev){	rtl8150_t *dev;	int res;	dev = netdev->priv;	if (dev == NULL) {		return -ENODEV;	}	down(&dev->sem);	set_registers(dev, IDR, 6, netdev->dev_addr);		FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),		      dev->rx_buff, RTL8150_MAX_MTU, read_bulk_callback, dev);	if ((res = usb_submit_urb(dev->rx_urb)))		warn("%s: rx_urb submit failed: %d", __FUNCTION__, res);	FILL_INT_URB(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3),		     dev->intr_buff, sizeof(dev->intr_buff), intr_callback,		     dev, dev->intr_interval);	if ((res = usb_submit_urb(dev->intr_urb)))		warn("%s: intr_urb submit failed: %d", __FUNCTION__, res);	netif_start_queue(netdev);	enable_net_traffic(dev);	up(&dev->sem);	return res;}static int rtl8150_close(struct net_device *netdev){	rtl8150_t *dev;	int res = 0;	dev = netdev->priv;	if (!dev)		return -ENODEV;	down(&dev->sem);	if (!test_bit(RTL8150_UNPLUG, &dev->flags))		disable_net_traffic(dev);	unlink_all_urbs(dev);	netif_stop_queue(netdev);	up(&dev->sem);	return res;}static int rtl8150_ethtool_ioctl(struct net_device *netdev, void *uaddr){	rtl8150_t *dev;	int cmd;	char tmp[128];	dev = netdev->priv;	if (get_user(cmd, (int *) uaddr))		return -EFAULT;	switch (cmd) {	case ETHTOOL_GDRVINFO:{			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };			strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN);			strncpy(info.version, DRIVER_VERSION,				ETHTOOL_BUSINFO_LEN);			sprintf(tmp, "usb%d:%d", dev->udev->bus->busnum,				dev->udev->devnum);			strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);			if (copy_to_user(uaddr, &info, sizeof(info)))				return -EFAULT;			return 0;		}	case ETHTOOL_GSET:{			struct ethtool_cmd ecmd;			short lpa, bmcr;			if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))				return -EFAULT;			ecmd.supported = (SUPPORTED_10baseT_Half |					  SUPPORTED_10baseT_Full |					  SUPPORTED_100baseT_Half |					  SUPPORTED_100baseT_Full |					  SUPPORTED_Autoneg |					  SUPPORTED_TP | SUPPORTED_MII);			ecmd.port = PORT_TP;			ecmd.transceiver = XCVR_INTERNAL;			ecmd.phy_address = dev->phy;			get_registers(dev, BMCR, 2, &bmcr);			get_registers(dev, ANLP, 2, &lpa);			if (bmcr & BMCR_ANENABLE) {				ecmd.autoneg = AUTONEG_ENABLE;				ecmd.speed =				    (lpa & (LPA_100HALF | LPA_100FULL)) ?				    SPEED_100 : SPEED_10;				if (ecmd.speed == SPEED_100)					ecmd.duplex = (lpa & LPA_100FULL) ?					    DUPLEX_FULL : DUPLEX_HALF;				else					ecmd.duplex = (lpa & LPA_10FULL) ?					    DUPLEX_FULL : DUPLEX_HALF;			} else {				ecmd.autoneg = AUTONEG_DISABLE;				ecmd.speed = (bmcr & BMCR_SPEED100) ?				    SPEED_100 : SPEED_10;				ecmd.duplex = (bmcr & BMCR_FULLDPLX) ?				    DUPLEX_FULL : DUPLEX_HALF;			}			if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))				return -EFAULT;			return 0;		}	case ETHTOOL_SSET:		return -ENOTSUPP;	case ETHTOOL_GLINK:{			struct ethtool_value edata = { ETHTOOL_GLINK };			edata.data = netif_carrier_ok(netdev);			if (copy_to_user(uaddr, &edata, sizeof(edata)))				return -EFAULT;			return 0;		}	default:		return -EOPNOTSUPP;	}}static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd){	rtl8150_t *dev;	u16 *data;	int res;	dev = netdev->priv;	data = (u16 *) & rq->ifr_data;	res = 0;	down(&dev->sem);	switch (cmd) {	case SIOCETHTOOL:		res = rtl8150_ethtool_ioctl(netdev, rq->ifr_data);		break;	case SIOCDEVPRIVATE:		data[0] = dev->phy;	case SIOCDEVPRIVATE + 1:		read_mii_word(dev, dev->phy, (data[1] & 0x1f), &data[3]);		break;	case SIOCDEVPRIVATE + 2:		if (!capable(CAP_NET_ADMIN)) {			up(&dev->sem);			return -EPERM;		}		write_mii_word(dev, dev->phy, (data[1] & 0x1f), data[2]);		break;	default:		res = -EOPNOTSUPP;	}	up(&dev->sem);	return res;}static void *rtl8150_probe(struct usb_device *udev, unsigned int ifnum,			   const struct usb_device_id *id){	rtl8150_t *dev;	struct net_device *netdev;	udev->config[0].bConfigurationValue = 1;	if (usb_set_configuration(udev, udev->config[0].bConfigurationValue)) {		err("usb_set_configuration() failed");		return NULL;	}	dev = kmalloc(sizeof(rtl8150_t), GFP_KERNEL);	if (!dev) {		err("Out of memory");		goto exit;	} else		memset(dev, 0, sizeof(rtl8150_t));	netdev = init_etherdev(NULL, 0);	if (!netdev) {		kfree(dev);		err("Oh boy, out of memory again?!?");		dev = NULL;		goto exit;	}	init_MUTEX(&dev->sem);	dev->udev = udev;	dev->netdev = netdev;	SET_MODULE_OWNER(netdev);	netdev->priv = dev;	netdev->open = rtl8150_open;	netdev->stop = rtl8150_close;	netdev->do_ioctl = rtl8150_ioctl;	netdev->watchdog_timeo = RTL8150_TX_TIMEOUT;	netdev->tx_timeout = rtl8150_tx_timeout;	netdev->hard_start_xmit = rtl8150_start_xmit;	netdev->set_multicast_list = rtl8150_set_multicast;	netdev->set_mac_address = rtl8150_set_mac_address;	netdev->get_stats = rtl8150_netdev_stats;	netdev->mtu = RTL8150_MTU;	dev->intr_interval = 100;	/* 100ms */	if (rtl8150_reset(dev) || !alloc_all_urbs(dev)) {		err("couldn't reset the device");		free_all_urbs(dev);		unregister_netdev(dev->netdev);		kfree(netdev);		kfree(dev);		dev = NULL;		goto exit;	}	set_ethernet_addr(dev);	/* let's not be very nasty :-) */	info("%s: rtl8150 is detected", netdev->name);exit:	return dev;}static void rtl8150_disconnect(struct usb_device *udev, void *ptr){	rtl8150_t *dev;	dev = ptr;	set_bit(RTL8150_UNPLUG, &dev->flags);	unregister_netdev(dev->netdev);	unlink_all_urbs(dev);	free_all_urbs(dev);	kfree(dev->netdev);	kfree(dev);	dev->netdev = NULL;	dev = NULL;}static int __init usb_rtl8150_init(void){	info(DRIVER_DESC " " DRIVER_VERSION);	return usb_register(&rtl8150_driver);}static void __exit usb_rtl8150_exit(void){	usb_deregister(&rtl8150_driver);}module_init(usb_rtl8150_init);module_exit(usb_rtl8150_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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