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 + -
显示快捷键?