Signed-off-by: Daniel Mack <dan...@caiaq.de>
---
 drivers/usb/ohci_dbg.c |  297 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 297 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/ohci_dbg.c

diff --git a/drivers/usb/ohci_dbg.c b/drivers/usb/ohci_dbg.c
new file mode 100644
index 0000000..8df83cb
--- /dev/null
+++ b/drivers/usb/ohci_dbg.c
@@ -0,0 +1,297 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ *
+ * Implementation taken from U-Boot sources,
+ * copyright (c) 1999-2007
+ *
+ *   Zhang Wei, Freescale Semiconductor, Inc. <wei.zh...@freescale.com>
+ *   Gary Jennejohn, DENX Software Engineering <ga...@denx.de>
+ *   Roman Weissgaerber <wei...@vienna.at>
+ *   David Brownell
+ *
+ * Port to libpayload by Daniel Mack <dan...@caiaq.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <libpayload-config.h>
+
+#include <usb/usb.h>
+#include <arch/virtual.h>
+#include <arch/endian.h>
+
+#include "ohci.h"
+#include "ohci_rh.h"
+
+#ifdef DEBUG
+
+static int sohci_get_current_frame_number(ohci_t *ohci)
+{
+       return readl(&ohci->hcca->frame_no);
+}
+
+static const char *ep_type_to_str(endpoint_t *ep)
+{
+       switch (ep->type) {
+       case CONTROL:           return "CONTROL";       break;
+       case BULK:              return "BULK";          break;
+       case INTERRUPT:         return "INTERRUPT";     break;
+       case ISOCHRONOUS:       return "ISOCHRONOUS";   break;
+       }
+
+       return "BOGUS";
+}
+
+void pkt_print(urb_priv_t *urb, void *setup, const char *str, int verbose)
+{
+       endpoint_t *ep = urb->ep;
+       usbdev_t *dev = ep->dev;
+       ohci_t *ohci = OHCI_INST(dev->controller);
+
+       dbg("%s URB:[%4x] dev:%2lu,ep:%2lu-%c,type:%s,len:%d/%d\n",
+                       str,
+                       sohci_get_current_frame_number(ohci),
+                       dev->address,
+                       ep->endpoint,
+                       (ep->direction == OUT) ? 'O':
+                               (ep->direction == SETUP) ? 'S' : 'I',
+                       ep_type_to_str(ep),
+                       (urb ? urb->actual_length : 0),
+                       urb->transfer_buffer_length);
+
+       if (!verbose)
+               return;
+
+       if (ep->direction != IN) {
+               int i, len;
+
+               if (ep->type == CONTROL) {
+                       printf( "%s: cmd(8):\n", __func__);
+                       for (i = 0; i < 8 ; i++)
+                               printf(" %02x", ((u8 *) setup) [i]);
+                       printf("\n");
+               }
+
+               if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) {
+                       printf("%s: data(%d/%d):",
+                               __func__,
+                               urb->actual_length,
+                               urb->transfer_buffer_length);
+                       len = (ep->direction == OUT) ? urb->actual_length : 0;
+
+                       for (i = 0; i < 16 && i < len; i++)
+                               printf(" %02x", ((u8 *) 
urb->transfer_buffer)[i]);
+
+                       printf("%s\n", i < len ? "...": "");
+               }
+       }
+}
+
+/* prints non-empty branches of the int ed tree inclusive iso eds */
+void ep_print_int_eds(ohci_t *ohci, const char *str)
+{
+       int i, j;
+       volatile u32 *ed_p;
+
+       for (i = 0; i < 32; i++) {
+               j = 5;
+               ed_p = &(ohci->hcca->int_table[i]);
+               if (!*ed_p)
+                       continue;
+
+               dbg("%s: %s branch int %d (%x):", __func__, str, i, i);
+               while (*ed_p && j--) {
+                       ohci_ed_t *ed = (ohci_ed_t *) le32_to_cpu(ed_p);
+                       dbg(" ed: %4x;", ed->hwINFO);
+                       ed_p = &ed->hwNextED;
+               }
+               dbg("\n");
+       }
+}
+
+static void ohci_dump_intr_mask(char *label, u32 mask)
+{
+       dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s\n",
+               label,
+               mask,
+               (mask & OHCI_INTR_MIE) ? " MIE" : "",
+               (mask & OHCI_INTR_OC) ? " OC" : "",
+               (mask & OHCI_INTR_RHSC) ? " RHSC" : "",
+               (mask & OHCI_INTR_FNO) ? " FNO" : "",
+               (mask & OHCI_INTR_UE) ? " UE" : "",
+               (mask & OHCI_INTR_RD) ? " RD" : "",
+               (mask & OHCI_INTR_SF) ? " SF" : "",
+               (mask & OHCI_INTR_WDH) ? " WDH" : "",
+               (mask & OHCI_INTR_SO) ? " SO" : ""
+               );
+}
+
+static void print_eds(const char *label, u32 value)
+{
+       ohci_ed_t *ed = phys_to_virt(value);
+       u32 hwNext;
+
+       if (!value)
+               return;
+
+       dbg("%s @%p: hwINFO %08x hwTailP %08x hwHeadP %08x hwNextED %08x\n",
+               label, ed, ed->hwINFO, ed->hwTailP, ed->hwHeadP, ed->hwNextED);
+
+       hwNext = ed->hwHeadP & ~0xf;
+
+       while (hwNext) {
+               ohci_td_t *td = phys_to_virt(hwNext);
+               dbg(" --- TD @%p: hwINFO %08x hwCBP %08x hwBE %08x hwNextTD 
%08x ",
+                       td, td->hwINFO, td->hwCBP, td->hwBE, td->hwNextTD);
+
+               if (td->hwCBP) {
+                       u8 *buf = phys_to_virt(td->hwCBP);
+                       dbg("(%02x %02x %02x %02x %02x %02x %02x %02x)",
+                               buf[0], buf[1], buf[2], buf[3],
+                               buf[4], buf[5], buf[6], buf[7]);
+               }
+
+               dbg("\n");
+
+               hwNext = td->hwNextTD;
+       }
+}
+
+static char *hcfs2string(int state)
+{
+       switch (state) {
+       case OHCI_USB_RESET:    return "reset";
+       case OHCI_USB_RESUME:   return "resume";
+       case OHCI_USB_OPER:     return "operational";
+       case OHCI_USB_SUSPEND:  return "suspend";
+       }
+
+       return "?";
+}
+
+/* dump control and status registers */
+static void ohci_dump_status(ohci_t *ohci)
+{
+       u32 temp;
+       struct ohci_regs *regs = ohci->regs;
+
+       temp = readl(&regs->control);
+       dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", temp,
+               (temp & OHCI_CTRL_RWE) ? " RWE" : "",
+               (temp & OHCI_CTRL_RWC) ? " RWC" : "",
+               (temp & OHCI_CTRL_IR) ? " IR" : "",
+               hcfs2string(temp & OHCI_CTRL_HCFS),
+               (temp & OHCI_CTRL_BLE) ? " BLE" : "",
+               (temp & OHCI_CTRL_CLE) ? " CLE" : "",
+               (temp & OHCI_CTRL_IE) ? " IE" : "",
+               (temp & OHCI_CTRL_PLE) ? " PLE" : "",
+               temp & OHCI_CTRL_CBSR
+               );
+
+       temp = readl(&regs->cmdstatus);
+       dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s\n", temp,
+               (temp & OHCI_SOC) >> 16,
+               (temp & OHCI_OCR) ? " OCR" : "",
+               (temp & OHCI_BLF) ? " BLF" : "",
+               (temp & OHCI_CLF) ? " CLF" : "",
+               (temp & OHCI_HCR) ? " HCR" : ""
+               );
+
+       ohci_dump_intr_mask("intrstatus", readl(&regs->intrstatus));
+       ohci_dump_intr_mask("intrenable", readl(&regs->intrenable));
+
+       print_eds("ed_periodcurrent",   readl(&regs->ed_periodcurrent));
+       print_eds("ed_controlhead",     readl(&regs->ed_controlhead));
+       print_eds("ed_controlcurrent",  readl(&regs->ed_controlcurrent));
+       print_eds("ed_bulkhead",        readl(&regs->ed_bulkhead));
+       print_eds("ed_bulkcurrent",     readl(&regs->ed_bulkcurrent));
+       print_eds("donehead",           readl(&regs->donehead));
+}
+
+void ohci_dump_roothub(ohci_t *ohci, int verbose)
+{
+       u32 temp, ndp, i;
+
+       temp = roothub_a(ohci);
+       ndp = (temp & RH_A_NDP) & 0xf;
+
+       if (verbose) {
+               dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
+                       ((temp & RH_A_POTPGT) >> 24) & 0xff,
+                       (temp & RH_A_NOCP) ? " NOCP" : "",
+                       (temp & RH_A_OCPM) ? " OCPM" : "",
+                       (temp & RH_A_DT)   ? " DT"   : "",
+                       (temp & RH_A_NPS)  ? " NPS"  : "",
+                       (temp & RH_A_PSM)  ? " PSM"  : "",
+                       ndp
+                       );
+               temp = roothub_b(ohci);
+               dbg("roothub.b: %08x PPCM=%04x DR=%04x\n",
+                       temp,
+                       (temp & RH_B_PPCM) >> 16,
+                       (temp & RH_B_DR)
+                       );
+               temp = roothub_status(ohci);
+               dbg("roothub.status: %08x%s%s%s%s%s%s\n",
+                       temp,
+                       (temp & RH_HS_CRWE) ? " CRWE" : "",
+                       (temp & RH_HS_OCIC) ? " OCIC" : "",
+                       (temp & RH_HS_LPSC) ? " LPSC" : "",
+                       (temp & RH_HS_DRWE) ? " DRWE" : "",
+                       (temp & RH_HS_OCI)  ? " OCI"  : "",
+                       (temp & RH_HS_LPS)  ? " LPS"  : ""
+                       );
+       }
+
+       for (i = 0; i < ndp; i++) {
+               temp = roothub_portstatus(ohci, i);
+               dbg("roothub.portstatus[%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n",
+                       i,
+                       temp,
+                       (temp & RH_PS_PRSC) ? " PRSC" : "",
+                       (temp & RH_PS_OCIC) ? " OCIC" : "",
+                       (temp & RH_PS_PSSC) ? " PSSC" : "",
+                       (temp & RH_PS_PESC) ? " PESC" : "",
+                       (temp & RH_PS_CSC) ? " CSC" : "",
+
+                       (temp & RH_PS_LSDA) ? " LSDA" : "",
+                       (temp & RH_PS_PPS) ? " PPS" : "",
+                       (temp & RH_PS_PRS) ? " PRS" : "",
+                       (temp & RH_PS_POCI) ? " POCI" : "",
+                       (temp & RH_PS_PSS) ? " PSS" : "",
+
+                       (temp & RH_PS_PES) ? " PES" : "",
+                       (temp & RH_PS_CCS) ? " CCS" : ""
+                       );
+       }
+}
+
+void ohci_dump(ohci_t *ohci, int verbose)
+{
+       dbg("----------------------\n");
+       dbg("OHCI @%p ohci state:", ohci->regs);
+
+       ohci_dump_status(ohci);
+
+       if (verbose)
+               ep_print_int_eds(ohci, "hcca");
+
+       dbg("hcca frame #%04x\n", ohci->hcca->frame_no);
+       ohci_dump_roothub(ohci, 1);
+       dbg("----------------------\n");
+}
+
+#endif /* DEBUG */
-- 
1.6.0.4


-- 
coreboot mailing list: coreboot@coreboot.org
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to