musb_procfs.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 763 行 · 第 1/2 页

C
763
字号
/****************************************************************** * Copyright 2005 Mentor Graphics Corporation * Copyright (C) 2005-2006 by Texas Instruments * * This file is part of the Inventra Controller Driver for Linux. * * The Inventra Controller Driver for Linux is free software; you * can redistribute it and/or modify it under the terms of the GNU * General Public License version 2 as published by the Free Software * Foundation. * * The Inventra Controller Driver for Linux is distributed in * the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with The Inventra Controller Driver for Linux ; if not, * write to the Free Software Foundation, Inc., 59 Temple Place, * Suite 330, Boston, MA  02111-1307  USA * * ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION * OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE * OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS * MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER. * MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES * OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT.  MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT * SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR * GRAPHICS SUPPORT CUSTOMER. ******************************************************************//* * Inventra Controller Driver (ICD) for Linux. * * The code managing debug files (currently in procfs). */#include <linux/kernel.h>#include <linux/proc_fs.h>#include <linux/seq_file.h>#include <asm/uaccess.h>	/* FIXME remove procfs writes */#include <asm/arch/hardware.h>#include "musbdefs.h"#include "davinci.h"const char *otg_state_string(struct musb *musb){	switch (musb->xceiv.state) {	case OTG_STATE_A_IDLE:		return "a_idle";	case OTG_STATE_A_WAIT_VRISE:	return "a_wait_vrise";	case OTG_STATE_A_WAIT_BCON:	return "a_wait_bcon";	case OTG_STATE_A_HOST:		return "a_host";	case OTG_STATE_A_SUSPEND:	return "a_suspend";	case OTG_STATE_A_PERIPHERAL:	return "a_peripheral";	case OTG_STATE_A_WAIT_VFALL:	return "a_wait_vfall";	case OTG_STATE_A_VBUS_ERR:	return "a_vbus_err";	case OTG_STATE_B_IDLE:		return "b_idle";	case OTG_STATE_B_SRP_INIT:	return "b_srp_init";	case OTG_STATE_B_PERIPHERAL:	return "b_peripheral";	case OTG_STATE_B_WAIT_ACON:	return "b_wait_acon";	case OTG_STATE_B_HOST:		return "b_host";	default:			return "UNDEFINED";	}}static int dump_qh(struct musb_qh *qh, char *buf, unsigned max){	int				count;	int				tmp;	struct usb_host_endpoint	*hep = qh->hep;	struct urb			*urb;	count = snprintf(buf, max, "    qh %p dev%d ep%d%s max%d\n",			qh, qh->dev->devnum, qh->epnum,			({ char *s; switch (qh->type) {			case USB_ENDPOINT_XFER_BULK:				s = "-bulk"; break;			case USB_ENDPOINT_XFER_INT:				s = "-int"; break;			case USB_ENDPOINT_XFER_CONTROL:				s = ""; break;			default:				s = "iso"; break;			}; s; }),			qh->maxpacket);	if (count <= 0)		return 0;	buf += count;	max -= count;	list_for_each_entry(urb, &hep->urb_list, urb_list) {		tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n",				usb_pipein(urb->pipe) ? "in" : "out",				urb, urb->actual_length,				urb->transfer_buffer_length);		if (tmp <= 0)			break;		tmp = min(tmp, (int)max);		count += tmp;		buf += tmp;		max -= tmp;	}	return count;}static intdump_queue(struct list_head *q, char *buf, unsigned max){	int		count = 0;	struct musb_qh	*qh;	list_for_each_entry(qh, q, ring) {		int	tmp;		tmp = dump_qh(qh, buf, max);		if (tmp <= 0)			break;		tmp = min(tmp, (int)max);		count += tmp;		buf += tmp;		max -= tmp;	}	return count;}static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max){	char		*buf = buffer;	int		code = 0;	void __iomem	*regs = ep->hw_ep->regs;	char		*mode = "1buf";	if (ep->is_in) {		if (ep->hw_ep->tx_double_buffered)			mode = "2buf";	} else {		if (ep->hw_ep->rx_double_buffered)			mode = "2buf";	}	do {		struct usb_request	*req;		code = snprintf(buf, max,				"\n%s (hw%d): %s%s, csr %04x maxp %04x\n",				ep->name, ep->bEndNumber,				mode, ep->dma ? " dma" : "",				musb_readw(regs,					(ep->is_in || !ep->bEndNumber)						? MGC_O_HDRC_TXCSR						: MGC_O_HDRC_RXCSR),				musb_readw(regs, ep->is_in						? MGC_O_HDRC_TXMAXP						: MGC_O_HDRC_RXMAXP)				);		if (code <= 0)			break;		code = min(code, (int) max);		buf += code;		max -= code;		if (is_cppi_enabled() && ep->bEndNumber) {			unsigned	cppi = ep->bEndNumber - 1;			void __iomem	*base = ep->pThis->ctrl_base;			unsigned	off1 = cppi << 2;			void __iomem	*ram = base;			char		tmp[16];			if (ep->is_in) {				ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi);				tmp[0] = 0;			} else {				ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi);				snprintf(tmp, sizeof tmp, "%d left, ",					musb_readl(base,					DAVINCI_RXCPPI_BUFCNT0_REG + off1));			}			code = snprintf(buf, max, "%cX DMA%d: %s"					"%08x %08x, %08x %08x; "					"%08x %08x %08x .. %08x\n",				ep->is_in ? 'T' : 'R',				ep->bEndNumber - 1, tmp,				musb_readl(ram, 0 * 4),				musb_readl(ram, 1 * 4),				musb_readl(ram, 2 * 4),				musb_readl(ram, 3 * 4),				musb_readl(ram, 4 * 4),				musb_readl(ram, 5 * 4),				musb_readl(ram, 6 * 4),				musb_readl(ram, 7 * 4));			if (code <= 0)				break;			code = min(code, (int) max);			buf += code;			max -= code;		}		if (list_empty(&ep->req_list)) {			code = snprintf(buf, max, "\t(queue empty)\n");			if (code <= 0)				break;			code = min(code, (int) max);			buf += code;			max -= code;			break;		}		list_for_each_entry (req, &ep->req_list, list) {			code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n",					req,					req->zero ? "zero, " : "",					req->short_not_ok ? "!short, " : "",					req->actual, req->length);			if (code <= 0)				break;			code = min(code, (int) max);			buf += code;			max -= code;		}	} while(0);	return buf - buffer;}static intdump_end_info(struct musb *pThis, u8 bEnd, char *aBuffer, unsigned max){	int			code = 0;	char			*buf = aBuffer;	struct musb_hw_ep	*pEnd = &pThis->aLocalEnd[bEnd];	do {		MGC_SelectEnd(pThis->pRegs, bEnd);		if (is_host_active(pThis)) {			int		dump_rx, dump_tx;			void __iomem	*regs = pEnd->regs;			/* TEMPORARY (!) until we have a real periodic			 * schedule tree ...			 */			if (!bEnd) {				/* control is shared, uses RX queue				 * but (mostly) shadowed tx registers				 */				dump_tx = !list_empty(&pThis->control);				dump_rx = 0;			} else if (pEnd == pThis->bulk_ep) {				dump_tx = !list_empty(&pThis->out_bulk);				dump_rx = !list_empty(&pThis->in_bulk);			} else if (pThis->periodic[bEnd]) {				struct usb_host_endpoint	*hep;				hep = pThis->periodic[bEnd]->hep;				dump_rx = hep->desc.bEndpointAddress						& USB_ENDPOINT_DIR_MASK;				dump_tx = !dump_rx;			} else				break;			/* END TEMPORARY */			if (dump_rx) {				code = snprintf(buf, max,					"\nRX%d: %s rxcsr %04x interval %02x "					"max %04x type %02x; "					"dev %d hub %d port %d"					"\n",					bEnd,					pEnd->rx_double_buffered						? "2buf" : "1buf",					musb_readw(regs, MGC_O_HDRC_RXCSR),					musb_readb(regs, MGC_O_HDRC_RXINTERVAL),					musb_readw(regs, MGC_O_HDRC_RXMAXP),					musb_readb(regs, MGC_O_HDRC_RXTYPE),					/* FIXME:  assumes multipoint */					musb_readb(pThis->pRegs,						MGC_BUSCTL_OFFSET(bEnd,						MGC_O_HDRC_RXFUNCADDR)),					musb_readb(pThis->pRegs,						MGC_BUSCTL_OFFSET(bEnd,						MGC_O_HDRC_RXHUBADDR)),					musb_readb(pThis->pRegs,						MGC_BUSCTL_OFFSET(bEnd,						MGC_O_HDRC_RXHUBPORT))					);				if (code <= 0)					break;				code = min(code, (int) max);				buf += code;				max -= code;				if (is_cppi_enabled()						&& bEnd						&& pEnd->rx_channel) {					unsigned	cppi = bEnd - 1;					unsigned	off1 = cppi << 2;					void __iomem	*base;					void __iomem	*ram;					char		tmp[16];					base = pThis->ctrl_base;					ram = DAVINCI_RXCPPI_STATERAM_OFFSET(							cppi) + base;					snprintf(tmp, sizeof tmp, "%d left, ",						musb_readl(base,						DAVINCI_RXCPPI_BUFCNT0_REG								+ off1));					code = snprintf(buf, max,						"    rx dma%d: %s"						"%08x %08x, %08x %08x; "						"%08x %08x %08x .. %08x\n",						cppi, tmp,						musb_readl(ram, 0 * 4),						musb_readl(ram, 1 * 4),						musb_readl(ram, 2 * 4),						musb_readl(ram, 3 * 4),						musb_readl(ram, 4 * 4),						musb_readl(ram, 5 * 4),						musb_readl(ram, 6 * 4),						musb_readl(ram, 7 * 4));					if (code <= 0)						break;					code = min(code, (int) max);					buf += code;					max -= code;				}				if (pEnd == pThis->bulk_ep						&& !list_empty(							&pThis->in_bulk)) {					code = dump_queue(&pThis->in_bulk,							buf, max);					if (code <= 0)						break;					code = min(code, (int) max);					buf += code;					max -= code;				} else if (pThis->periodic[bEnd]) {					code = dump_qh(pThis->periodic[bEnd],							buf, max);					if (code <= 0)						break;					code = min(code, (int) max);					buf += code;					max -= code;				}			}			if (dump_tx) {				code = snprintf(buf, max,					"\nTX%d: %s txcsr %04x interval %02x "					"max %04x type %02x; "					"dev %d hub %d port %d"					"\n",					bEnd,					pEnd->tx_double_buffered						? "2buf" : "1buf",					musb_readw(regs, MGC_O_HDRC_TXCSR),					musb_readb(regs, MGC_O_HDRC_TXINTERVAL),					musb_readw(regs, MGC_O_HDRC_TXMAXP),					musb_readb(regs, MGC_O_HDRC_TXTYPE),					/* FIXME:  assumes multipoint */					musb_readb(pThis->pRegs,						MGC_BUSCTL_OFFSET(bEnd,						MGC_O_HDRC_TXFUNCADDR)),					musb_readb(pThis->pRegs,						MGC_BUSCTL_OFFSET(bEnd,						MGC_O_HDRC_TXHUBADDR)),					musb_readb(pThis->pRegs,						MGC_BUSCTL_OFFSET(bEnd,						MGC_O_HDRC_TXHUBPORT))					);				if (code <= 0)					break;				code = min(code, (int) max);

⌨️ 快捷键说明

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