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

📄 rtl8150.c

📁 linux下的usb接口驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
			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, RTL8150_MAX_MTU, 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);	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;	}	if ((udev->descriptor.idVendor != VENDOR_ID_REALTEK) ||	    (udev->descriptor.idProduct != PRODUCT_ID_RTL8150)) {	    	err("Not the one we are interested about");		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->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 + -