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

📄 net2280.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	t = snprintf (next, size, "%s version " DRIVER_VERSION			", chiprev %04x, dma %s\n\n"			"devinit %03x fifoctl %08x gadget '%s'\n"			"pci irqenb0 %02x irqenb1 %08x "			"irqstat0 %04x irqstat1 %08x\n",			driver_name, dev->chiprev,			use_dma				? (use_dma_chaining ? "chaining" : "enabled")				: "disabled",			readl (&dev->regs->devinit),			readl (&dev->regs->fifoctl),			s,			readl (&dev->regs->pciirqenb0),			readl (&dev->regs->pciirqenb1),			readl (&dev->regs->irqstat0),			readl (&dev->regs->irqstat1));	size -= t;	next += t;	/* USB Control Registers */	t1 = readl (&dev->usb->usbctl);	t2 = readl (&dev->usb->usbstat);	if (t1 & (1 << VBUS_PIN)) {		if (t2 & (1 << HIGH_SPEED))			s = "high speed";		else if (dev->gadget.speed == USB_SPEED_UNKNOWN)			s = "powered";		else			s = "full speed";		/* full speed bit (6) not working?? */	} else			s = "not attached";	t = snprintf (next, size,			"stdrsp %08x usbctl %08x usbstat %08x "				"addr 0x%02x (%s)\n",			readl (&dev->usb->stdrsp), t1, t2,			readl (&dev->usb->ouraddr), s);	size -= t;	next += t;	/* PCI Master Control Registers */	/* DMA Control Registers */	/* Configurable EP Control Registers */	for (i = 0; i < 7; i++) {		struct net2280_ep	*ep;		ep = &dev->ep [i];		if (i && !ep->desc)			continue;		t1 = readl (&ep->regs->ep_cfg);		t2 = readl (&ep->regs->ep_rsp) & 0xff;		t = snprintf (next, size,				"\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"					"irqenb %02x\n",				ep->ep.name, t1, t2,				(t2 & (1 << CLEAR_NAK_OUT_PACKETS))					? "NAK " : "",				(t2 & (1 << CLEAR_EP_HIDE_STATUS_PHASE))					? "hide " : "",				(t2 & (1 << CLEAR_EP_FORCE_CRC_ERROR))					? "CRC " : "",				(t2 & (1 << CLEAR_INTERRUPT_MODE))					? "interrupt " : "",				(t2 & (1<<CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE))					? "status " : "",				(t2 & (1 << CLEAR_NAK_OUT_PACKETS_MODE))					? "NAKmode " : "",				(t2 & (1 << CLEAR_ENDPOINT_TOGGLE))					? "DATA1 " : "DATA0 ",				(t2 & (1 << CLEAR_ENDPOINT_HALT))					? "HALT " : "",				readl (&ep->regs->ep_irqenb));		size -= t;		next += t;		t = snprintf (next, size,				"\tstat %08x avail %04x "				"(ep%d%s-%s)%s\n",				readl (&ep->regs->ep_stat),				readl (&ep->regs->ep_avail),				t1 & 0x0f, DIR_STRING (t1),				type_string (t1 >> 8),				ep->stopped ? "*" : "");		size -= t;		next += t;		if (!ep->dma)			continue;		t = snprintf (next, size,				"  dma\tctl %08x stat %08x count %08x\n"				"\taddr %08x desc %08x\n",				readl (&ep->dma->dmactl),				readl (&ep->dma->dmastat),				readl (&ep->dma->dmacount),				readl (&ep->dma->dmaaddr),				readl (&ep->dma->dmadesc));		size -= t;		next += t;	}	/* Indexed Registers */		// none yet 	/* Statistics */	t = snprintf (next, size, "\nirqs:  ");	size -= t;	next += t;	for (i = 0; i < 7; i++) {		struct net2280_ep	*ep;		ep = &dev->ep [i];		if (i && !ep->irqs)			continue;		t = snprintf (next, size, " %s/%lu", ep->ep.name, ep->irqs);		size -= t;		next += t;	}	t = snprintf (next, size, "\n");	size -= t;	next += t;	spin_unlock_irqrestore (&dev->lock, flags);	return PAGE_SIZE - size;}static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);static ssize_tshow_queues (struct device *_dev, char *buf){	struct net2280		*dev;	char			*next;	unsigned		size;	unsigned long		flags;	int			i;	dev = dev_get_drvdata (_dev);	next = buf;	size = PAGE_SIZE;	spin_lock_irqsave (&dev->lock, flags);	for (i = 0; i < 7; i++) {		struct net2280_ep		*ep = &dev->ep [i];		struct net2280_request		*req;		int				t;		if (i != 0) {			const struct usb_endpoint_descriptor	*d;			d = ep->desc;			if (!d)				continue;			t = d->bEndpointAddress;			t = snprintf (next, size,				"\n%s (ep%d%s-%s) max %04x %s fifo %d\n",				ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK,				(t & USB_DIR_IN) ? "in" : "out",				({ char *val;				 switch (d->bmAttributes & 0x03) {				 case USB_ENDPOINT_XFER_BULK:				 	val = "bulk"; break;				 case USB_ENDPOINT_XFER_INT:				 	val = "intr"; break;				 default:				 	val = "iso"; break;				 }; val; }),				le16_to_cpu (d->wMaxPacketSize) & 0x1fff,				ep->dma ? "dma" : "pio", ep->fifo_size				);		} else /* ep0 should only have one transfer queued */			t = snprintf (next, size, "ep0 max 64 pio %s\n",					ep->is_in ? "in" : "out");		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) {			if (ep->dma && req->td_dma == readl (&ep->dma->dmadesc))				t = snprintf (next, size,					"\treq %p len %d/%d "					"buf %p (dmacount %08x)\n",					&req->req, req->req.actual,					req->req.length, req->req.buf,					readl (&ep->dma->dmacount));			else				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;			if (ep->dma) {				struct net2280_dma	*td;				td = req->td;				t = snprintf (next, size, "\t    td %08x "					" count %08x buf %08x desc %08x\n",					req->td_dma, td->dmacount,					td->dmaaddr, td->dmadesc);				if (t <= 0 || t > size)					goto done;				size -= t;				next += t;			}		}	}done:	spin_unlock_irqrestore (&dev->lock, flags);	return PAGE_SIZE - size;}static DEVICE_ATTR (queues, S_IRUGO, show_queues, NULL);#else#define device_create_file(a,b)	do {} while (0)#define device_remove_file	device_create_file#endif/*-------------------------------------------------------------------------*//* another driver-specific mode might be a request type doing dma * to/from another device fifo instead of to/from memory. */static void set_fifo_mode (struct net2280 *dev, int mode){	/* keeping high bits preserves BAR2 */	writel ((0xffff << PCI_BASE2_RANGE) | mode, &dev->regs->fifoctl);	/* always ep-{a,b,e,f} ... maybe not ep-c or ep-d */	INIT_LIST_HEAD (&dev->gadget.ep_list);	list_add_tail (&dev->ep [1].ep.ep_list, &dev->gadget.ep_list);	list_add_tail (&dev->ep [2].ep.ep_list, &dev->gadget.ep_list);	switch (mode) {	case 0:		list_add_tail (&dev->ep [3].ep.ep_list, &dev->gadget.ep_list);		list_add_tail (&dev->ep [4].ep.ep_list, &dev->gadget.ep_list);		dev->ep [1].fifo_size = dev->ep [2].fifo_size = 1024;		break;	case 1:		dev->ep [1].fifo_size = dev->ep [2].fifo_size = 2048;		break;	case 2:		list_add_tail (&dev->ep [3].ep.ep_list, &dev->gadget.ep_list);		dev->ep [1].fifo_size = 2048;		dev->ep [2].fifo_size = 1024;		break;	}	/* fifo sizes for ep0, ep-c, ep-d, ep-e, and ep-f never change */	list_add_tail (&dev->ep [5].ep.ep_list, &dev->gadget.ep_list);	list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list);}/** * net2280_set_fifo_mode - change allocation of fifo buffers * @gadget: access to the net2280 device that will be updated * @mode: 0 for default, four 1kB buffers (ep-a through ep-d); * 	1 for two 2kB buffers (ep-a and ep-b only); * 	2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c). * * returns zero on success, else negative errno.  when this succeeds, * the contents of gadget->ep_list may have changed. * * you may only call this function when endpoints a-d are all disabled. * use it whenever extra hardware buffering can help performance, such * as before enabling "high bandwidth" interrupt endpoints that use * maxpacket bigger than 512 (when double buffering would otherwise * be unavailable). */int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode){	int			i;	struct net2280		*dev;	int			status = 0;	unsigned long		flags;	if (!gadget)		return -ENODEV;	dev = container_of (gadget, struct net2280, gadget);	spin_lock_irqsave (&dev->lock, flags);	for (i = 1; i <= 4; i++)		if (dev->ep [i].desc) {			status = -EINVAL;			break;		}	if (mode < 0 || mode > 2)		status = -EINVAL;	if (status == 0)		set_fifo_mode (dev, mode);	spin_unlock_irqrestore (&dev->lock, flags);	if (status == 0) {		if (mode == 1)			DEBUG (dev, "fifo:  ep-a 2K, ep-b 2K\n");		else if (mode == 2)			DEBUG (dev, "fifo:  ep-a 2K, ep-b 1K, ep-c 1K\n");		/* else all are 1K */	}	return status;}EXPORT_SYMBOL (net2280_set_fifo_mode);/*-------------------------------------------------------------------------*//* keeping it simple: * - one bus driver, initted first; * - one function driver, initted second * * most of the work to support multiple net2280 controllers would * be to associate this gadget driver (yes?) with all of them, or * perhaps to bind specific drivers to specific devices. */static struct net2280	*the_controller;static void usb_reset (struct net2280 *dev){	u32	tmp;	/* force immediate bus disconnect, and synch through pci */	writel (0, &dev->usb->usbctl);	dev->gadget.speed = USB_SPEED_UNKNOWN;	(void) readl (&dev->usb->usbctl);	net2280_led_init (dev);	/* disable automatic responses, and irqs */	writel (0, &dev->usb->stdrsp);	writel (0, &dev->regs->pciirqenb0);	writel (0, &dev->regs->pciirqenb1);	/* clear old dma and irq state */	for (tmp = 0; tmp < 4; tmp++) {		struct net2280_ep	*ep = &dev->ep [tmp + 1];		if (ep->dma)			abort_dma (ep);	}	writel (~0, &dev->regs->irqstat0),	writel (~(1 << SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1),	/* reset, and enable pci */	tmp = readl (&dev->regs->devinit)		| (1 << PCI_ENABLE)		| (1 << FIFO_SOFT_RESET)		| (1 << USB_SOFT_RESET)		| (1 << M8051_RESET);	writel (tmp, &dev->regs->devinit);	/* standard fifo and endpoint allocations */	set_fifo_mode (dev, (fifo_mode <= 2) ? fifo_mode : 0);}static void usb_reinit (struct net2280 *dev){	u32	tmp;	int	init_dma;	/* use_dma changes are ignored till next device re-init */	init_dma = use_dma;	/* basic endpoint init */	for (tmp = 0; tmp < 7; tmp++) {		struct net2280_ep	*ep = &dev->ep [tmp];		ep->ep.name = ep_name [tmp];		ep->dev = dev;		ep->num = tmp;		if (tmp > 0 && tmp <= 4) {			ep->fifo_size = 1024;			if (init_dma)				ep->dma = &dev->dma [tmp - 1];		} else			ep->fifo_size = 64;		ep->regs = &dev->epregs [tmp];		ep_reset (dev->regs, ep);	}	dev->ep [0].ep.maxpacket = 64;	dev->ep [5].ep.maxpacket = 64;	dev->ep [6].ep.maxpacket = 64;	dev->gadget.ep0 = &dev->ep [0].ep;	dev->ep [0].stopped = 0;	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);	/* we want to prevent lowlevel/insecure access from the USB host,	 * but erratum 0119 means this enable bit is ignored	 */	for (tmp = 0; tmp < 5; tmp++)		writel (EP_DONTUSE, &dev->dep [tmp].dep_cfg);}static void ep0_start (struct net2280 *dev){	writel (  (1 << CLEAR_EP_HIDE_STATUS_PHASE)		| (1 << CLEAR_NAK_OUT_PACKETS)		| (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)		, &dev->epregs [0].ep_rsp);	/*	 * hardware optionally handles a bunch of standard requests	 * that the API hides from drivers anyway.  have it do so.	 * endpoint status/features are handled in software, to	 * help pass tests for some dubious behavior.	 */	writel (  (1 << SET_TEST_MODE)		| (1 << SET_ADDRESS)		| (1 << DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP)		| (1 << GET_DEVICE_STATUS)		| (1 << GET_INTERFACE_STATUS)		, &dev->usb->stdrsp);	writel (  (1 << USB_ROOT_PORT_WAKEUP_ENABLE)		| (1 << SELF_POWERED_USB_DEVICE)		| (1 << REMOTE_WAKEUP_SUPPORT)		| (1 << USB_DETECT_ENABLE)		| (1 << SELF_POWERED_STATUS)		, &dev->usb->usbctl);	/* enable irqs so we can see ep0 and general operation  */	writel (  (1 << SETUP_PACKET_INTERRUPT_ENABLE)		| (1 << ENDPOINT_0_INTERRUPT_ENABLE)		, &dev->regs->pciirqenb0);	writel (  (1 << PCI_INTERRUPT_ENABLE)		| (1 << PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE)		| (1 << PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE)		| (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE)		| (1 << VBUS_INTERRUPT_ENABLE)		| (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE)		, &dev->regs->pciirqenb1);	/* don't leave any writes posted */	(void) readl (&dev->usb->usbctl);}/* 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 net2280		*dev = the_controller;	int			retval;	unsigned		i;	/* insist on high speed support from the driver, since	 * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE)	 * "must not be used in normal operation"	 */	if (!driver			|| driver->speed != USB_SPEED_HIGH			|| !driver->bind			|| !driver->unbind			|| !driver->setup)		return -EINVAL;	if (!dev)		return -ENODEV;	if (dev->driver)		return -EBUSY;	for (i = 0; i < 7; i++)		dev->ep [i].irqs = 0;	/* hook up the driver ... */	dev->driver = driver;

⌨️ 快捷键说明

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