diff options
Diffstat (limited to 'drivers/usb/uhci-debug.h')
-rw-r--r-- | drivers/usb/uhci-debug.h | 399 |
1 files changed, 232 insertions, 167 deletions
diff --git a/drivers/usb/uhci-debug.h b/drivers/usb/uhci-debug.h index 73d16937a..9d715d4d8 100644 --- a/drivers/usb/uhci-debug.h +++ b/drivers/usb/uhci-debug.h @@ -1,195 +1,260 @@ -#ifdef DEBUG +/* + * UHCI-specific debugging code. Invaluable when something + * goes wrong, but don't get in my face. + * + * Kernel visible pointers are surrounded in []'s and bus + * visible pointers are surrounded in ()'s + * + * (C) Copyright 1999 Linus Torvalds + * (C) Copyright 1999 Johannes Erdfelt + */ -static void uhci_show_qh (puhci_desc_t qh) +#include <linux/kernel.h> +#include <asm/io.h> + +#include "uhci.h" + +void uhci_show_td(struct uhci_td * td) { - if (qh->type != QH_TYPE) { - dbg("qh has not QH_TYPE"); - return; - } - dbg("uhci_show_qh %p (%08lX):", qh, virt_to_bus (qh)); + char *spid; - if (qh->hw.qh.head & UHCI_PTR_TERM) - dbg("Head Terminate"); - else { - if (qh->hw.qh.head & UHCI_PTR_QH) - dbg("Head points to QH"); - else - dbg("Head points to TD"); + printk("%08x ", td->link); + printk("e%d %s%s%s%s%s%s%s%s%s%sLength=%x ", + ((td->status >> 27) & 3), + (td->status & TD_CTRL_SPD) ? "SPD " : "", + (td->status & TD_CTRL_LS) ? "LS " : "", + (td->status & TD_CTRL_IOC) ? "IOC " : "", + (td->status & TD_CTRL_ACTIVE) ? "Active " : "", + (td->status & TD_CTRL_STALLED) ? "Stalled " : "", + (td->status & TD_CTRL_DBUFERR) ? "DataBufErr " : "", + (td->status & TD_CTRL_BABBLE) ? "Babble " : "", + (td->status & TD_CTRL_NAK) ? "NAK " : "", + (td->status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", + (td->status & TD_CTRL_BITSTUFF) ? "BitStuff " : "", + td->status & 0x7ff); - dbg("head: %08X", qh->hw.qh.head & ~UHCI_PTR_BITS); - } - if (qh->hw.qh.element & UHCI_PTR_TERM) - dbg("Element Terminate"); - else { - - if (qh->hw.qh.element & UHCI_PTR_QH) - dbg("Element points to QH"); - else - dbg("Element points to TD"); - dbg("element: %08X", qh->hw.qh.element & ~UHCI_PTR_BITS); + switch (td->info & 0xff) { + case USB_PID_SETUP: + spid = "SETUP"; + break; + case USB_PID_OUT: + spid = "OUT"; + break; + case USB_PID_IN: + spid = "IN"; + break; + default: + spid = "?"; + break; } + + printk("MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ", + td->info >> 21, + ((td->info >> 19) & 1), + (td->info >> 15) & 15, + (td->info >> 8) & 127, + (td->info & 0xff), + spid); + printk("(buf=%08x)\n", td->buffer); } -#endif -static void uhci_show_td (puhci_desc_t td) +static void uhci_show_sc(int port, unsigned short status) { - char *spid; - warn("uhci_show_td %p (%08lX) ", td, virt_to_bus (td)); - - switch (td->hw.td.info & 0xff) { - case USB_PID_SETUP: - spid = "SETUP"; - break; - case USB_PID_OUT: - spid = " OUT "; - break; - case USB_PID_IN: - spid = " IN "; - break; - default: - spid = " ? "; - break; - } + printk(" stat%d = %04x %s%s%s%s%s%s%s%s\n", + port, + status, + (status & USBPORTSC_SUSP) ? "PortSuspend " : "", + (status & USBPORTSC_PR) ? "PortReset " : "", + (status & USBPORTSC_LSDA) ? "LowSpeed " : "", + (status & USBPORTSC_RD) ? "ResumeDetect " : "", + (status & USBPORTSC_PEC) ? "EnableChange " : "", + (status & USBPORTSC_PE) ? "PortEnabled " : "", + (status & USBPORTSC_CSC) ? "ConnectChange " : "", + (status & USBPORTSC_CCS) ? "PortConnected " : ""); +} - warn("MaxLen=%02x DT%d EndPt=%x Dev=%x, PID=%x(%s) (buf=%08x)", - td->hw.td.info >> 21, - ((td->hw.td.info >> 19) & 1), - (td->hw.td.info >> 15) & 15, - (td->hw.td.info >> 8) & 127, - (td->hw.td.info & 0xff), - spid, - td->hw.td.buffer); - - warn("Len=%02x e%d %s%s%s%s%s%s%s%s%s%s", - td->hw.td.status & 0x7ff, - ((td->hw.td.status >> 27) & 3), - (td->hw.td.status & TD_CTRL_SPD) ? "SPD " : "", - (td->hw.td.status & TD_CTRL_LS) ? "LS " : "", - (td->hw.td.status & TD_CTRL_IOC) ? "IOC " : "", - (td->hw.td.status & TD_CTRL_ACTIVE) ? "Active " : "", - (td->hw.td.status & TD_CTRL_STALLED) ? "Stalled " : "", - (td->hw.td.status & TD_CTRL_DBUFERR) ? "DataBufErr " : "", - (td->hw.td.status & TD_CTRL_BABBLE) ? "Babble " : "", - (td->hw.td.status & TD_CTRL_NAK) ? "NAK " : "", - (td->hw.td.status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", - (td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : "" - ); -#if 1 - if (td->hw.td.link & UHCI_PTR_TERM) - warn("Link Terminate"); - else { - if (td->hw.td.link & UHCI_PTR_QH) - warn("%s, link points to QH @ %08x", - (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"), - td->hw.td.link & ~UHCI_PTR_BITS); - else - warn("%s, link points to TD @ %08x", - (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"), - td->hw.td.link & ~UHCI_PTR_BITS); - } -#endif +void uhci_show_status(struct uhci *uhci) +{ + unsigned int io_addr = uhci->io_addr; + unsigned short usbcmd, usbstat, usbint, usbfrnum; + unsigned int flbaseadd; + unsigned char sof; + unsigned short portsc1, portsc2; + + usbcmd = inw(io_addr + 0); + usbstat = inw(io_addr + 2); + usbint = inw(io_addr + 4); + usbfrnum = inw(io_addr + 6); + flbaseadd = inl(io_addr + 8); + sof = inb(io_addr + 12); + portsc1 = inw(io_addr + 16); + portsc2 = inw(io_addr + 18); + + printk(" usbcmd = %04x %s%s%s%s%s%s%s%s\n", + usbcmd, + (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ", + (usbcmd & USBCMD_CF) ? "CF " : "", + (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "", + (usbcmd & USBCMD_FGR) ? "FGR " : "", + (usbcmd & USBCMD_EGSM) ? "EGSM " : "", + (usbcmd & USBCMD_GRESET) ? "GRESET " : "", + (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", + (usbcmd & USBCMD_RS) ? "RS " : ""); + + printk(" usbstat = %04x %s%s%s%s%s%s\n", + usbstat, + (usbstat & USBSTS_HCH) ? "HCHalted " : "", + (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "", + (usbstat & USBSTS_HSE) ? "HostSystemError " : "", + (usbstat & USBSTS_RD) ? "ResumeDetect " : "", + (usbstat & USBSTS_ERROR) ? "USBError " : "", + (usbstat & USBSTS_USBINT) ? "USBINT " : ""); + + printk(" usbint = %04x\n", usbint); + printk(" usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1, + 0xfff & (4*(unsigned int)usbfrnum)); + printk(" flbaseadd = %08x\n", flbaseadd); + printk(" sof = %02x\n", sof); + uhci_show_sc(1, portsc1); + uhci_show_sc(2, portsc2); } -#ifdef DEBUG -static void uhci_show_td_queue (puhci_desc_t td) + +#define uhci_link_to_qh(x) ((struct uhci_qh *) uhci_link_to_td(x)) + +struct uhci_td *uhci_link_to_td(unsigned int link) { - dbg("uhci_show_td_queue %p (%08lX):", td, virt_to_bus (td)); - while (1) { - uhci_show_td (td); - if (td->hw.td.link & UHCI_PTR_TERM) - break; - //if(!(td->hw.td.link&UHCI_PTR_DEPTH)) - // break; - if (td != bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS)) - td = bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS); - else { - dbg("td points to itself!"); - break; - } -// schedule(); - } + if (link & UHCI_PTR_TERM) + return NULL; + + return bus_to_virt(link & ~UHCI_PTR_BITS); } -static void uhci_show_queue (puhci_desc_t qh) +void uhci_show_queue(struct uhci_qh *qh) { - dbg("uhci_show_queue %p:", qh); - while (1) { - uhci_show_qh (qh); + struct uhci_td *td, *first; + int i = 0, count = 1000; - if (qh->hw.qh.element & UHCI_PTR_QH) - dbg("Warning: qh->element points to qh!"); - else if (!(qh->hw.qh.element & UHCI_PTR_TERM)) - uhci_show_td_queue (bus_to_virt (qh->hw.qh.element & ~UHCI_PTR_BITS)); + if (qh->element & UHCI_PTR_QH) + printk(" Element points to QH (bug?)\n"); - if (qh->hw.qh.head & UHCI_PTR_TERM) - break; + if (qh->element & UHCI_PTR_DEPTH) + printk(" Depth traverse\n"); - if (qh != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS)) - qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS); - else { - dbg("qh points to itself!"); + if (qh->element & UHCI_PTR_TERM) + printk(" Terminate\n"); + + if (!(qh->element & ~UHCI_PTR_BITS)) { + printk(" td 0: [NULL]\n"); + return; + } + + first = uhci_link_to_td(qh->element); + + /* Make sure it doesn't runaway */ + for (td = first; td && count > 0; + td = uhci_link_to_td(td->link), --count) { + printk(" td %d: [%p]\n", i++, td); + printk(" "); + uhci_show_td(td); + + if (td == uhci_link_to_td(td->link)) { + printk(KERN_ERR "td links to itself!\n"); break; } } } -static void uhci_show_sc (int port, unsigned short status) +static int uhci_is_skeleton_td(struct uhci *uhci, struct uhci_td *td) { - dbg(" stat%d = %04x %s%s%s%s%s%s%s%s", - port, - status, - (status & USBPORTSC_SUSP) ? "PortSuspend " : "", - (status & USBPORTSC_PR) ? "PortReset " : "", - (status & USBPORTSC_LSDA) ? "LowSpeed " : "", - (status & USBPORTSC_RD) ? "ResumeDetect " : "", - (status & USBPORTSC_PEC) ? "EnableChange " : "", - (status & USBPORTSC_PE) ? "PortEnabled " : "", - (status & USBPORTSC_CSC) ? "ConnectChange " : "", - (status & USBPORTSC_CCS) ? "PortConnected " : ""); + int j; + + for (j = 0; j < UHCI_NUM_SKELTD; j++) + if (td == uhci->skeltd + j) + return 1; + + return 0; } -void uhci_show_status (puhci_t s) +static int uhci_is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh) { - unsigned int io_addr = s->io_addr; - unsigned short usbcmd, usbstat, usbint, usbfrnum; - unsigned int flbaseadd; - unsigned char sof; - unsigned short portsc1, portsc2; + int j; + + for (j = 0; j < UHCI_NUM_SKELQH; j++) + if (qh == uhci->skelqh + j) + return 1; - usbcmd = inw (io_addr + 0); - usbstat = inw (io_addr + 2); - usbint = inw (io_addr + 4); - usbfrnum = inw (io_addr + 6); - flbaseadd = inl (io_addr + 8); - sof = inb (io_addr + 12); - portsc1 = inw (io_addr + 16); - portsc2 = inw (io_addr + 18); - - dbg(" usbcmd = %04x %s%s%s%s%s%s%s%s", - usbcmd, - (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ", - (usbcmd & USBCMD_CF) ? "CF " : "", - (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "", - (usbcmd & USBCMD_FGR) ? "FGR " : "", - (usbcmd & USBCMD_EGSM) ? "EGSM " : "", - (usbcmd & USBCMD_GRESET) ? "GRESET " : "", - (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", - (usbcmd & USBCMD_RS) ? "RS " : ""); - - dbg(" usbstat = %04x %s%s%s%s%s%s", - usbstat, - (usbstat & USBSTS_HCH) ? "HCHalted " : "", - (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "", - (usbstat & USBSTS_HSE) ? "HostSystemError " : "", - (usbstat & USBSTS_RD) ? "ResumeDetect " : "", - (usbstat & USBSTS_ERROR) ? "USBError " : "", - (usbstat & USBSTS_USBINT) ? "USBINT " : ""); - - dbg(" usbint = %04x", usbint); - dbg(" usbfrnum = (%d)%03x", (usbfrnum >> 10) & 1, - 0xfff & (4 * (unsigned int) usbfrnum)); - dbg(" flbaseadd = %08x", flbaseadd); - dbg(" sof = %02x", sof); - uhci_show_sc (1, portsc1); - uhci_show_sc (2, portsc2); + return 0; } -#endif + +static const char *td_names[] = {"interrupt1", "interrupt2", "interrupt4", + "interrupt8", "interrupt16", "interrupt32", + "interrupt64", "interrupt128", "interrupt256" }; +static const char *qh_names[] = { "control", "bulk" }; + +void uhci_show_queues(struct uhci *uhci) +{ + int i, isqh; + struct uhci_qh *qh; + struct uhci_td *td; + + for (i = 0; i < UHCI_NUMFRAMES; ++i) { + int shown = 0; + + td = uhci_link_to_td(uhci->fl->frame[i]); + if (td) + isqh = uhci->fl->frame[i] & UHCI_PTR_QH; + while (td && !isqh) { + if (uhci_is_skeleton_td(uhci, td)) + break; + + if (!shown) { + printk(" Frame %d\n", i); + shown = 1; + } + + printk("[%p] ", td); + + uhci_show_td(td); + td = uhci_link_to_td(td->link); + if (td) + isqh = td->link & UHCI_PTR_QH; + } + } + for (i = 0; i < UHCI_NUM_SKELTD; ++i) { + printk(" %s: [%p] (%08x)\n", td_names[i], + &uhci->skeltd[i], + uhci->skeltd[i].link); + + td = uhci_link_to_td(uhci->skeltd[i].link); + if (td) + isqh = uhci->skeltd[i].link & UHCI_PTR_QH; + while (td && !isqh) { + if (uhci_is_skeleton_td(uhci, td)) + break; + + printk("[%p] ", td); + + uhci_show_td(td); + td = uhci_link_to_td(td->link); + if (td) + isqh = td->link & UHCI_PTR_QH; + } + } + for (i = 0; i < UHCI_NUM_SKELQH; ++i) { + printk(" %s: [%p] (%08x) (%08x)\n", qh_names[i], + &uhci->skelqh[i], + uhci->skelqh[i].link, uhci->skelqh[i].element); + + qh = uhci_link_to_qh(uhci->skelqh[i].link); + for (; qh; qh = uhci_link_to_qh(qh->link)) { + if (uhci_is_skeleton_qh(uhci, qh)) + break; + + printk(" [%p] (%08x) (%08x)\n", + qh, qh->link, qh->element); + + uhci_show_queue(qh); + } + } +} + |