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

📄 catc.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	dr->request = q->request;	dr->requesttype = 0x40 | q->dir;	dr->value = cpu_to_le16(q->value);	dr->index = cpu_to_le16(q->index);	dr->length = cpu_to_le16(q->len);        urb->pipe = q->dir ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0);	urb->transfer_buffer_length = q->len;	urb->transfer_buffer = catc->ctrl_buf;	urb->setup_packet = (void *) dr;	urb->dev = usbdev;	if (!q->dir && q->buf && q->len)		memcpy(catc->ctrl_buf, q->buf, q->len);	if ((status = usb_submit_urb(&catc->ctrl_urb)))		err("submit(ctrl_urb) status %d", status);}static void catc_ctrl_done(struct urb *urb){	struct catc *catc = urb->context;	struct ctrl_queue *q;	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;	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;	return &catc->stats;}/* * Receive modes. Broadcast, Multicast, Promisc. */static void catc_multicast(unsigned char *addr, u8 *multicast){	unsigned int crc = 0xffffffff;	u8 byte, idx, bit;        for (idx = 0; idx < 6; idx++)                for (byte = *addr++, bit = 0; bit < 8; bit++, byte >>= 1)                        crc = (crc >> 1) ^ (((crc ^ byte) & 1) ? 0xedb88320U : 0);	multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);}static void catc_set_multicast_list(struct net_device *netdev){	struct catc *catc = netdev->priv;	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 |= RxPromisc;	} 	if (netdev->flags & IFF_ALLMULTI)		memset(catc->multicast, 0xff, 64);	for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next)		catc_multicast(mc->dmi_addr, catc->multicast);	catc_set_reg_async(catc, RxUnit, rx);	catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);}/* * Open, close. */static int catc_open(struct net_device *netdev){	struct catc *catc = netdev->priv;	int status;	catc->irq_urb.dev = catc->usbdev;	if ((status = usb_submit_urb(&catc->irq_urb)) < 0) {		err("submit(irq_urb) status %d", status);		return -1;	}	netif_start_queue(netdev);	mod_timer(&catc->timer, jiffies + STATS_UPDATE);	return 0;}static int catc_stop(struct net_device *netdev){	struct catc *catc = netdev->priv;	netif_stop_queue(netdev);	del_timer_sync(&catc->timer);	usb_unlink_urb(&catc->rx_urb);	usb_unlink_urb(&catc->tx_urb);	usb_unlink_urb(&catc->irq_urb);	usb_unlink_urb(&catc->ctrl_urb);	return 0;}/* * USB probe, disconnect. */static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const struct usb_device_id *id){	struct net_device *netdev;	struct catc *catc;	u8 broadcast[6];	int i;	if (usb_set_interface(usbdev, ifnum, 1)) {                err("Can't set altsetting 1.");		return NULL;	}	catc = kmalloc(sizeof(struct catc), GFP_KERNEL);	memset(catc, 0, sizeof(struct catc));	netdev = init_etherdev(0, 0);	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;	netdev->priv = catc;	catc->usbdev = usbdev;	catc->netdev = netdev;	catc->tx_lock = SPIN_LOCK_UNLOCKED;	catc->ctrl_lock = SPIN_LOCK_UNLOCKED;	init_timer(&catc->timer);	catc->timer.data = (long) catc;	catc->timer.function = catc_stats_timer;	FILL_CONTROL_URB(&catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),		NULL, NULL, 0, catc_ctrl_done, catc);	FILL_BULK_URB(&catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1),		NULL, 0, catc_tx_done, catc);	FILL_BULK_URB(&catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),		catc->rx_buf, RX_MAX_BURST * (PKT_SZ + 2), catc_rx_done, catc);	FILL_INT_URB(&catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),                catc->irq_buf, 2, catc_irq_done, catc, 1);	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, 8);	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);	dbg("Init done.");	printk(KERN_INFO "%s: CATC EL1210A NetMate USB Ethernet at usb%d:%d.%d, ",		netdev->name, usbdev->bus->busnum, usbdev->devnum, ifnum);	for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);	printk("%2.2x.\n", netdev->dev_addr[i]);	return catc;}static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr){	struct catc *catc = dev_ptr;	unregister_netdev(catc->netdev);	kfree(catc->netdev);	kfree(catc);}/* * Module functions and tables. */static struct usb_device_id catc_id_table [] = {	{ USB_DEVICE(0x0423, 0xa) },	/* CATC Netmate */	{ 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 = {	name:		"catc",	probe:		catc_probe,	disconnect:	catc_disconnect,	id_table:	catc_id_table,};static int __init catc_init(void){	info(DRIVER_VERSION " " DRIVER_DESC);	usb_register(&catc_driver);	return 0;}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 + -