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

📄 catc.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (!q->dir && q->buf && q->len)		memcpy(catc->ctrl_buf, q->buf, q->len);	if ((status = usb_submit_urb(catc->ctrl_urb, GFP_KERNEL)))		err("submit(ctrl_urb) status %d", status);}static void catc_ctrl_done(struct urb *urb, struct pt_regs *regs){	struct catc *catc = urb->context;	struct ctrl_queue *q;	unsigned long flags;	if (urb->status)		dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length);	spin_lock_irqsave(&catc->ctrl_lock, flags);	q = catc->ctrl_queue + catc->ctrl_tail;	if (q->dir) {		if (q->buf && q->len)			memcpy(q->buf, catc->ctrl_buf, q->len);		else			q->buf = catc->ctrl_buf;	}	if (q->callback)		q->callback(catc, q);	catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1);	if (catc->ctrl_head != catc->ctrl_tail)		catc_ctrl_run(catc);	else		clear_bit(CTRL_RUNNING, &catc->flags);	spin_unlock_irqrestore(&catc->ctrl_lock, flags);}static int catc_ctrl_async(struct catc *catc, u8 dir, u8 request, u16 value,	u16 index, void *buf, int len, void (*callback)(struct catc *catc, struct ctrl_queue *q)){	struct ctrl_queue *q;	int retval = 0;	unsigned long flags;	spin_lock_irqsave(&catc->ctrl_lock, flags);		q = catc->ctrl_queue + catc->ctrl_head;	q->dir = dir;	q->request = request;	q->value = value;	q->index = index;	q->buf = buf;	q->len = len;	q->callback = callback;	catc->ctrl_head = (catc->ctrl_head + 1) & (CTRL_QUEUE - 1);	if (catc->ctrl_head == catc->ctrl_tail) {		err("ctrl queue full");		catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1);		retval = -1;	}	if (!test_and_set_bit(CTRL_RUNNING, &catc->flags))		catc_ctrl_run(catc);	spin_unlock_irqrestore(&catc->ctrl_lock, flags);	return retval;}/* * Statistics. */static void catc_stats_done(struct catc *catc, struct ctrl_queue *q){	int index = q->index - EthStats;	u16 data, last;	catc->stats_buf[index] = *((char *)q->buf);	if (index & 1)		return;	data = ((u16)catc->stats_buf[index] << 8) | catc->stats_buf[index + 1];	last = catc->stats_vals[index >> 1];	switch (index) {		case TxSingleColl:		case TxMultiColl:			catc->stats.collisions += data - last;			break;		case TxExcessColl:			catc->stats.tx_aborted_errors += data - last;			catc->stats.tx_errors += data - last;			break;		case RxFramErr:			catc->stats.rx_frame_errors += data - last;			catc->stats.rx_errors += data - last;			break;	}	catc->stats_vals[index >> 1] = data;}static void catc_stats_timer(unsigned long data){	struct catc *catc = (void *) data;	int i;	for (i = 0; i < 8; i++)		catc_get_reg_async(catc, EthStats + 7 - i, catc_stats_done);	mod_timer(&catc->timer, jiffies + STATS_UPDATE);}static struct net_device_stats *catc_get_stats(struct net_device *netdev){	struct catc *catc = netdev_priv(netdev);	return &catc->stats;}/* * Receive modes. Broadcast, Multicast, Promisc. */static void catc_multicast(unsigned char *addr, u8 *multicast){	u32 crc;	crc = ether_crc_le(6, addr);	multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);}static void catc_set_multicast_list(struct net_device *netdev){	struct catc *catc = netdev_priv(netdev);	struct dev_mc_list *mc;	u8 broadcast[6];	u8 rx = RxEnable | RxPolarity | RxMultiCast;	int i;	memset(broadcast, 0xff, 6);	memset(catc->multicast, 0, 64);	catc_multicast(broadcast, catc->multicast);	catc_multicast(netdev->dev_addr, catc->multicast);	if (netdev->flags & IFF_PROMISC) {		memset(catc->multicast, 0xff, 64);		rx |= (!catc->is_f5u011) ? RxPromisc : AltRxPromisc;	} 	if (netdev->flags & IFF_ALLMULTI) {		memset(catc->multicast, 0xff, 64);	} else {		for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) {			u32 crc = ether_crc_le(6, mc->dmi_addr);			if (!catc->is_f5u011) {				catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);			} else {				catc->multicast[7-(crc >> 29)] |= 1 << ((crc >> 26) & 7);			}		}	}	if (!catc->is_f5u011) {		catc_set_reg_async(catc, RxUnit, rx);		catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);	} else {		f5u011_mchash_async(catc, catc->multicast);		if (catc->rxmode[0] != rx) {			catc->rxmode[0] = rx;			dbg("Setting RX mode to %2.2X %2.2X", catc->rxmode[0], catc->rxmode[1]);			f5u011_rxmode_async(catc, catc->rxmode);		}	}}static void catc_get_drvinfo(struct net_device *dev,			     struct ethtool_drvinfo *info){	struct catc *catc = netdev_priv(dev);	strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN);	strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);	usb_make_path (catc->usbdev, info->bus_info, sizeof info->bus_info);}static int catc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct catc *catc = netdev_priv(dev);	if (!catc->is_f5u011)		return -EOPNOTSUPP;	cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_TP;	cmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_TP;	cmd->speed = SPEED_10;	cmd->duplex = DUPLEX_HALF;	cmd->port = PORT_TP; 	cmd->phy_address = 0;	cmd->transceiver = XCVR_INTERNAL;	cmd->autoneg = AUTONEG_DISABLE;	cmd->maxtxpkt = 1;	cmd->maxrxpkt = 1;	return 0;}static struct ethtool_ops ops = {	.get_drvinfo = catc_get_drvinfo,	.get_settings = catc_get_settings,	.get_link = ethtool_op_get_link};/* * Open, close. */static int catc_open(struct net_device *netdev){	struct catc *catc = netdev_priv(netdev);	int status;	catc->irq_urb->dev = catc->usbdev;	if ((status = usb_submit_urb(catc->irq_urb, GFP_KERNEL)) < 0) {		err("submit(irq_urb) status %d", status);		return -1;	}	netif_start_queue(netdev);	if (!catc->is_f5u011)		mod_timer(&catc->timer, jiffies + STATS_UPDATE);	return 0;}static int catc_stop(struct net_device *netdev){	struct catc *catc = netdev_priv(netdev);	netif_stop_queue(netdev);	if (!catc->is_f5u011)		del_timer_sync(&catc->timer);	usb_kill_urb(catc->rx_urb);	usb_kill_urb(catc->tx_urb);	usb_kill_urb(catc->irq_urb);	usb_kill_urb(catc->ctrl_urb);	return 0;}/* * USB probe, disconnect. */static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id){	struct usb_device *usbdev = interface_to_usbdev(intf);	struct net_device *netdev;	struct catc *catc;	u8 broadcast[6];	int i, pktsz;	if (usb_set_interface(usbdev,			intf->altsetting->desc.bInterfaceNumber, 1)) {                err("Can't set altsetting 1.");		return -EIO;	}	netdev = alloc_etherdev(sizeof(struct catc));	if (!netdev)		return -ENOMEM;	catc = netdev_priv(netdev);	netdev->open = catc_open;	netdev->hard_start_xmit = catc_hard_start_xmit;	netdev->stop = catc_stop;	netdev->get_stats = catc_get_stats;	netdev->tx_timeout = catc_tx_timeout;	netdev->watchdog_timeo = TX_TIMEOUT;	netdev->set_multicast_list = catc_set_multicast_list;	SET_ETHTOOL_OPS(netdev, &ops);	catc->usbdev = usbdev;	catc->netdev = netdev;	spin_lock_init(&catc->tx_lock);	spin_lock_init(&catc->ctrl_lock);	init_timer(&catc->timer);	catc->timer.data = (long) catc;	catc->timer.function = catc_stats_timer;	catc->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);	catc->tx_urb = usb_alloc_urb(0, GFP_KERNEL);	catc->rx_urb = usb_alloc_urb(0, GFP_KERNEL);	catc->irq_urb = usb_alloc_urb(0, GFP_KERNEL);	if ((!catc->ctrl_urb) || (!catc->tx_urb) || 	    (!catc->rx_urb) || (!catc->irq_urb)) {		err("No free urbs available.");		if (catc->ctrl_urb)			usb_free_urb(catc->ctrl_urb);		if (catc->tx_urb)			usb_free_urb(catc->tx_urb);		if (catc->rx_urb)			usb_free_urb(catc->rx_urb);		if (catc->irq_urb)			usb_free_urb(catc->irq_urb);		free_netdev(netdev);		return -ENOMEM;	}	/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */	if (le16_to_cpu(usbdev->descriptor.idVendor) == 0x0423 && 	    le16_to_cpu(usbdev->descriptor.idProduct) == 0xa &&	    le16_to_cpu(catc->usbdev->descriptor.bcdDevice) == 0x0130) {		dbg("Testing for f5u011");		catc->is_f5u011 = 1;				atomic_set(&catc->recq_sz, 0);		pktsz = RX_PKT_SZ;	} else {		pktsz = RX_MAX_BURST * (PKT_SZ + 2);	}		usb_fill_control_urb(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),		NULL, NULL, 0, catc_ctrl_done, catc);	usb_fill_bulk_urb(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1),		NULL, 0, catc_tx_done, catc);	usb_fill_bulk_urb(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),		catc->rx_buf, pktsz, catc_rx_done, catc);	usb_fill_int_urb(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),                catc->irq_buf, 2, catc_irq_done, catc, 1);	if (!catc->is_f5u011) {		dbg("Checking memory size\n");		i = 0x12345678;		catc_write_mem(catc, 0x7a80, &i, 4);		i = 0x87654321;			catc_write_mem(catc, 0xfa80, &i, 4);		catc_read_mem(catc, 0x7a80, &i, 4);	  		switch (i) {		case 0x12345678:			catc_set_reg(catc, TxBufCount, 8);			catc_set_reg(catc, RxBufCount, 32);			dbg("64k Memory\n");			break;		default:			warn("Couldn't detect memory size, assuming 32k");		case 0x87654321:			catc_set_reg(catc, TxBufCount, 4);			catc_set_reg(catc, RxBufCount, 16);			dbg("32k Memory\n");			break;		}	  		dbg("Getting MAC from SEEROM.");	  		catc_get_mac(catc, netdev->dev_addr);				dbg("Setting MAC into registers.");	  		for (i = 0; i < 6; i++)			catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);				dbg("Filling the multicast list.");	  		memset(broadcast, 0xff, 6);		catc_multicast(broadcast, catc->multicast);		catc_multicast(netdev->dev_addr, catc->multicast);		catc_write_mem(catc, 0xfa80, catc->multicast, 64);				dbg("Clearing error counters.");				for (i = 0; i < 8; i++)			catc_set_reg(catc, EthStats + i, 0);		catc->last_stats = jiffies;				dbg("Enabling.");				catc_set_reg(catc, MaxBurst, RX_MAX_BURST);		catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);		catc_set_reg(catc, LEDCtrl, LEDLink);		catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);	} else {		dbg("Performing reset\n");		catc_reset(catc);		catc_get_mac(catc, netdev->dev_addr);				dbg("Setting RX Mode");		catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast;		catc->rxmode[1] = 0;		f5u011_rxmode(catc, catc->rxmode);	}	dbg("Init done.");	printk(KERN_INFO "%s: %s USB Ethernet at usb-%s-%s, ",	       netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate",	       usbdev->bus->bus_name, usbdev->devpath);	for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);	printk("%2.2x.\n", netdev->dev_addr[i]);	usb_set_intfdata(intf, catc);	SET_NETDEV_DEV(netdev, &intf->dev);	if (register_netdev(netdev) != 0) {		usb_set_intfdata(intf, NULL);		usb_free_urb(catc->ctrl_urb);		usb_free_urb(catc->tx_urb);		usb_free_urb(catc->rx_urb);		usb_free_urb(catc->irq_urb);		free_netdev(netdev);		return -EIO;	}	return 0;}static void catc_disconnect(struct usb_interface *intf){	struct catc *catc = usb_get_intfdata(intf);	usb_set_intfdata(intf, NULL);	if (catc) {		unregister_netdev(catc->netdev);		usb_free_urb(catc->ctrl_urb);		usb_free_urb(catc->tx_urb);		usb_free_urb(catc->rx_urb);		usb_free_urb(catc->irq_urb);		free_netdev(catc->netdev);	}}/* * Module functions and tables. */static struct usb_device_id catc_id_table [] = {	{ USB_DEVICE(0x0423, 0xa) },	/* CATC Netmate, Belkin F5U011 */	{ USB_DEVICE(0x0423, 0xc) },	/* CATC Netmate II, Belkin F5U111 */	{ USB_DEVICE(0x08d1, 0x1) },	/* smartBridges smartNIC */	{ }};MODULE_DEVICE_TABLE(usb, catc_id_table);static struct usb_driver catc_driver = {	.owner =	THIS_MODULE,	.name =		driver_name,	.probe =	catc_probe,	.disconnect =	catc_disconnect,	.id_table =	catc_id_table,};static int __init catc_init(void){	int result = usb_register(&catc_driver);	if (result == 0)		info(DRIVER_VERSION " " DRIVER_DESC);	return result;}static void __exit catc_exit(void){	usb_deregister(&catc_driver);}module_init(catc_init);module_exit(catc_exit);

⌨️ 快捷键说明

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