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

📄 superh_udc.c

📁 LINUX2.4.18内核下的usb GADGET驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		     ctrl_inb(USBEPSZ0O), ctrl_inb(USBEPSZ1),		     ctrl_inb(USBDASTS), ctrl_inb(USBDMA));	size -= t;	next += t;	t = snprintf(next, size,		     "epstl %02X, xvercr %02X\n",		     ctrl_inb(USBEPSTL), ctrl_inb(USBXVERCR));	size -= t;	next += t;	if (!is_usb_connected || !dev->driver)		goto done;	t = snprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu; irq0s %lu; irq1s %lu\n\n",		dev->stats.write.bytes, dev->stats.write.ops,		dev->stats.read.bytes, dev->stats.read.ops,		dev->stats.irq0s, dev->stats.irq1s);	size -= t;	next += t;	/* dump endpoint queues */	for (i = 0; i < 4; i++) {		struct superh_ep	*ep = &dev->ep [i];		struct superh_request	*req;		int			t;		if (i != 0) {			const struct usb_endpoint_descriptor	*d;			d = ep->desc;			if (!d)				continue;			t = snprintf(next, size,				"%s max %d %s\n",				ep->ep.name, le16_to_cpu (d->wMaxPacketSize),				(ep->dma >= 0) ? "dma" : "pio");		} else /* ep0 should only have one transfer queued */			t = snprintf(next, size, "ep0 max 8 pio\n");		if (t <= 0 || t > size)			goto done;		size -= t;		next += t;		if (list_empty(&ep->queue)) {			t = snprintf(next, size, "\t(nothing queued)\n");			if (t <= 0 || t > size)				goto done;			size -= t;			next += t;			continue;		}		list_for_each_entry(req, &ep->queue, queue) {#ifdef	USE_DMA			if (ep->dma >= 0 && req->queue.prev == &ep->queue)				t = snprintf(next, size,					"\treq %p len %d/%d "					"buf %p (dma%d dcmd %08x)\n",					&req->req, req->req.actual,					req->req.length, req->req.buf,					ep->dma, DCMD(ep->dma)					// low 13 bits == bytes-to-go					);			else#endif				t = snprintf(next, size,					"\treq %p len %d/%d buf %p\n",					&req->req, req->req.actual,					req->req.length, req->req.buf);			if (t <= 0 || t > size)				goto done;			size -= t;			next += t;		}	}done:	local_irq_restore(flags);	return count - size;}#endif	/* UDC_PROC_FILE *//*-------------------------------------------------------------------------*//* * 	udc_disable - disable USB device controller */static void udc_disable(struct superh_udc *dev){	/* block all irqs */	ctrl_outb( 0, USBIER0);	ctrl_outb( 0, USBIER1);	/* Disable the USB module */	or_b(0x80, STBCR3);		/* Disable the USB clock */	ctrl_outw(0xA500, UCLKCR);	ep0_idle (dev);	dev->gadget.speed = USB_SPEED_UNKNOWN;}/* * 	udc_reinit - initialize software state */static void udc_reinit(struct superh_udc *dev){	u32	i;	/* device/ep0 records init */	INIT_LIST_HEAD (&dev->gadget.ep_list);	dev->gadget.ep0 = &dev->ep[0].ep;	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);	dev->ep0state = EP0_IDLE;	/* basic endpoint records init */	for (i = 0; i < 4; i++) {		struct superh_ep *ep = &dev->ep[i];		ep->ep.name = ep_name[i];		ep->ep.ops = &superh_ep_ops;		if (i != 0)			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);		ep->dev = dev;		ep->desc = 0;		ep->stopped = 0;		ep->halted = 0;		ep->dma = -1;		INIT_LIST_HEAD (&ep->queue);		/* address may need USB_DIR_IN, attributes likely wrong */		ep->bEndpointAddress = i;		ep->bmAttributes = USB_ENDPOINT_XFER_BULK;	}	/* TODO at least from here on, static initialization	 * would work just as well and would need less code space	 */	/* ep0 == control */	dev->ep[ 0].ep.maxpacket   = EP0_FIFO_SIZE;	dev->ep[ 0].data_present_mask = EP0i_DE;	dev->ep[ 0].stall_mask = EP0_STL;	dev->ep[ 0].interrupt_mask = EP0o_TS | EP0i_TR | EP0i_TS;	dev->ep[ 0].interrupt_reg = USBIER0;	dev->ep[ 0].clear_mask = EP0i_CLEAR | EP0o_CLEAR;	dev->ep[ 0].fifo_reg = 0;	dev->ep[ 0].packet_enable_mask = 0;	dev->ep[ 1].ep.maxpacket   = BULK_FIFO_SIZE;	dev->ep[ 1].bEndpointAddress |= USB_DIR_OUT;	dev->ep[ 1].data_present_mask = 0x00;	dev->ep[ 1].stall_mask = EP1_STL;	dev->ep[ 1].interrupt_mask = EP1_FULL;	dev->ep[ 1].interrupt_reg = USBIER0;	dev->ep[ 1].clear_mask = EP1_CLEAR;	dev->ep[ 1].fifo_reg = 0;	dev->ep[ 1].packet_enable_mask = 0;	dev->ep[ 2].ep.maxpacket   = BULK_FIFO_SIZE;	dev->ep[ 2].bEndpointAddress |= USB_DIR_IN;	dev->ep[ 2].data_present_mask = EP2_DE;	dev->ep[ 2].stall_mask = EP2_STL;	dev->ep[ 2].interrupt_mask = EP2_TR | EP2_EMPTY;	dev->ep[ 2].interrupt_reg = USBIER0;	dev->ep[ 2].clear_mask = EP2_CLEAR;	dev->ep[ 2].fifo_reg = USBEPDR2;	dev->ep[ 2].packet_enable_mask = EP2_PKTE;	dev->ep[ 3].ep.maxpacket   = INT_FIFO_SIZE;	dev->ep[ 3].bEndpointAddress |= USB_DIR_IN;	dev->ep[ 3].data_present_mask = EP3_DE;	dev->ep[ 3].stall_mask = EP3_STL;	dev->ep[ 3].interrupt_mask = EP3_TR | EP3_TS;	dev->ep[ 3].interrupt_reg = USBIER1;	dev->ep[ 3].clear_mask = EP3_CLEAR;	dev->ep[ 3].fifo_reg = USBEPDR3;	dev->ep[ 3].packet_enable_mask = EP3_PKTE;}/* until it's enabled, this UDC should be completely invisible * to any USB host. */static void udc_enable (struct superh_udc *dev){#if defined(CONFIG_CPU_SUBTYPE_SH7727)	// Reset and then Select Function USB1_pwr_en out (USB) c.f. Section 26, Table 26.1 PTE2	and_w(PN_PB2_MSK, PECR);	or_w(PN_PB2_OF, PECR);	// Reset and then Select Function UCLK c.f. Section 26, Table 26.1, PTD6	and_w(PN_PB6_MSK, PDCR);	or_w(PN_PB6_OF, PDCR);	// Stop USB module prior to setting clocks c.f. Section 9.2.3	and_b(~MSTP14, STBCR3);	or_b(MSTP14, STBCR3);	// Select external clock, 1/1 divisor c.f. Section 11.3.1	or_b(USBDIV_11|USBCKS_EC, EXCPGCR);	// Start USB c.f. Section 9.2.3	and_b(~MSTP14, STBCR3);	// Disable pullup c.f. Section 23.5.19	or_b(PULLUP_E, USBDMA);	//and_b(~PULLUP_E, USBDMA);	// Set port 1 to function, disabled c.f. Section 22.2.1	or_w(USB_TRANS_TRAN | USB_SEL_FUNC, EXPFC);	// Enable pullup c.f. Section 23.5.19a	and_b(~PULLUP_E, USBDMA);	//or_b(PULLUP_E, USBDMA);#elif defined(CONFIG_CPU_SUBTYPE_SH7705)	/* Disable the USB module */	or_b(0x80, STBCR3);		/* Set the clock to external & enable */	ctrl_outw(0xA5E0, UCLKCR);	/* Enable the USB module */	and_b(0x7f, STBCR3);	/* Enable USB pins. */	ctrl_outw(0x01FD, PMCR);	/* VBUS */	or_b(PULLUP_E, PMDR);#endif	dev->gadget.speed = USB_SPEED_UNKNOWN;	dev->stats.irqs = 0;	dev->stats.irq0s = 0;	dev->stats.irq1s = 0;	// reset fifo's and stall's	or_b( EP3_CLEAR | EP1_CLEAR | EP2_CLEAR | EP0o_CLEAR | EP0i_CLEAR, USBFCLR);	or_b(0, USBEPSTL);	/* Setup interrupt priority by using the interrupt select registers */	ctrl_outb(F0_LOW, USBISR0);	ctrl_outb(F1_LOW, USBISR1);	/* Enable some interrupts */	or_b( BRST | SETUP_TS | EP0o_TS | EP0i_TR | EP0i_TS, USBIER0);	or_b( VBUSF, USBIER1);}/* when a driver is successfully registered, it will receive * control requests including set_configuration(), which enables * non-control requests.  then usb traffic follows until a * disconnect is reported.  then a host may connect again, or * the driver might get unbound. */int usb_gadget_register_driver(struct usb_gadget_driver *driver){	struct superh_udc	*dev = the_controller;	int			retval;	if (!driver	    /*|| driver->speed != USB_SPEED_FULL			|| !driver->bind			|| !driver->unbind			|| !driver->disconnect			|| !driver->setup*/)		return -EINVAL;	if (!dev)		return -ENODEV;	if (dev->driver)		return -EBUSY;	/* first hook up the driver ... */	dev->driver = driver;	retval = driver->bind(&dev->gadget);	if (retval) {		DMSG("bind to driver %s --> error %d\n",				driver->driver.name, retval);		dev->driver = 0;		return retval;	}	/* ... then enable host detection and ep0; and we're ready	 * for set_configuration as well as eventual disconnect.	 * NOTE:  this shouldn't power up until later.	 */	udc_enable(dev);	DMSG("registered gadget driver '%s'\n", driver->driver.name);	dump_state(dev);	return 0;}EXPORT_SYMBOL(usb_gadget_register_driver);static voidstop_activity(struct superh_udc *dev, struct usb_gadget_driver *driver){	int i;	/* don't disconnect drivers more than once */	if (dev->gadget.speed == USB_SPEED_UNKNOWN)		driver = 0;	dev->gadget.speed = USB_SPEED_UNKNOWN;	/* prevent new request submissions, kill any outstanding requests  */	for (i = 0; i < 4; i++) {		struct superh_ep *ep = &dev->ep[i];		ep->stopped = 1;		nuke(ep, -ESHUTDOWN);	}	del_timer_sync(&dev->timer);	/* report disconnect; the driver is already quiesced */	if (driver)		driver->disconnect(&dev->gadget);	/* re-init driver-visible data structures */	udc_reinit(dev);}int usb_gadget_unregister_driver(struct usb_gadget_driver *driver){	struct superh_udc	*dev = the_controller;	if (!dev)		return -ENODEV;	if (!driver || driver != dev->driver)		return -EINVAL;	local_irq_disable();	udc_disable(dev);	stop_activity(dev, driver);	driver->unbind(&dev->gadget);	dev->driver = 0;	local_irq_enable();	DMSG("unregistered gadget driver '%s'\n", driver->driver.name);	dump_state(dev);	return 0;}EXPORT_SYMBOL(usb_gadget_unregister_driver);/*-------------------------------------------------------------------------*/#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,40)MODULE_DESCRIPTION(driver_desc);#endifMODULE_AUTHOR("Julian Back");MODULE_LICENSE("GPL");/* *	cleanup - free resources allocated during init */static void /*__exit and */ __init cleanup(void){	struct superh_udc *dev = the_controller;	if (!dev)		return;	udc_disable(dev);#ifdef	UDC_PROC_FILE	remove_proc_entry(proc_node_name, NULL);#endif	usb_gadget_unregister_driver(dev->driver);	if (dev->got_irq0) {		free_irq(USBF0_IRQ, dev);		dev->got_irq0 = 0;	}	if (dev->got_irq1) {		free_irq(USBF1_IRQ, dev);		dev->got_irq1 = 0;	}	the_controller = 0;}module_exit (cleanup);/* * 	init - allocate resources */static int __init init(void){	static struct superh_udc memory;	struct superh_udc *dev;	int retval;	printk(KERN_DEBUG "%s: version %s\n", driver_name, DRIVER_VERSION);	/* initialize data */	dev = &memory;	memset(dev, 0, sizeof *dev);	dev->gadget.ops = &superh_udc_ops;	dev->gadget.name = driver_name;	dev->gadget.dev.bus_id = "udc";	dev->gadget.speed = USB_SPEED_UNKNOWN;	dev->vbusmn = 0;	atomic_set(&dev->in_interrupt, 0);	the_controller = dev;	udc_disable(dev);	udc_reinit(dev);	/* irq setup after old hardware state is cleaned up */	retval = request_irq(USBF0_IRQ, superh_udc_irq_f0,			     0/*SA_INTERRUPT | SA_SAMPLE_RANDOM*/,			     driver_name, dev);	if (retval != 0) {		printk(KERN_ERR "%s: can't get irq %i, err %d\n",		       driver_name, USBF0_IRQ, retval);		goto failed;	}	dev->got_irq0 = 1;	retval = request_irq(USBF1_IRQ, superh_udc_irq_f1,			     0/*SA_INTERRUPT | SA_SAMPLE_RANDOM*/,			     driver_name, dev);	if (retval != 0) {		printk(KERN_ERR "%s: can't get irq %i, err %d\n",		       driver_name, USBF1_IRQ, retval);		goto failed;	}	dev->got_irq1 = 1;	printk(KERN_INFO "%s, IRQs %d %d\n", driver_desc,	       USBF0_IRQ, USBF1_IRQ);	dump_state(dev);	dev->setup_countdown = DEFAULT_SETUP_COUNT;#ifdef	UDC_PROC_FILE	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);#endif	return 0;failed:	cleanup();	return retval;}module_init (init);

⌨️ 快捷键说明

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