1 /*
2 * UHCI-specific debugging code. Invaluable when something
3 * goes wrong, but don't get in my face.
4 *
5 * Kernel visible pointers are surrounded in []'s and bus
6 * visible pointers are surrounded in ()'s
7 *
8 * (C) Copyright 1999 Linus Torvalds
9 * (C) Copyright 1999 Johannes Erdfelt
10 */
11
12 #include <linux/kernel.h>
13 #include <asm/io.h>
14
15 #include "uhci.h"
16
17 void uhci_show_td(struct uhci_td *td)
18 {
19 char *spid;
20
21 printk("%08x ", td->link);
22 printk("e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
23 ((td->status >> 27) & 3),
24 (td->status & TD_CTRL_SPD) ? "SPD " : "",
25 (td->status & TD_CTRL_LS) ? "LS " : "",
26 (td->status & TD_CTRL_IOC) ? "IOC " : "",
27 (td->status & TD_CTRL_ACTIVE) ? "Active " : "",
28 (td->status & TD_CTRL_STALLED) ? "Stalled " : "",
29 (td->status & TD_CTRL_DBUFERR) ? "DataBufErr " : "",
30 (td->status & TD_CTRL_BABBLE) ? "Babble " : "",
31 (td->status & TD_CTRL_NAK) ? "NAK " : "",
32 (td->status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
33 (td->status & TD_CTRL_BITSTUFF) ? "BitStuff " : "",
34 td->status & 0x7ff);
35
36 switch (td->info & 0xff) {
37 case USB_PID_SETUP:
38 spid = "SETUP";
39 break;
40 case USB_PID_OUT:
41 spid = "OUT";
42 break;
43 case USB_PID_IN:
44 spid = "IN";
45 break;
46 default:
47 spid = "?";
48 break;
49 }
50
51 printk("MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ",
52 td->info >> 21,
53 ((td->info >> 19) & 1),
54 (td->info >> 15) & 15,
55 (td->info >> 8) & 127,
56 (td->info & 0xff),
57 spid);
58 printk("(buf=%08x)\n", td->buffer);
59 }
60
61 static void uhci_show_sc(int port, unsigned short status)
62 {
63 printk(" stat%d = %04x %s%s%s%s%s%s%s%s\n",
64 port,
65 status,
66 (status & USBPORTSC_SUSP) ? "PortSuspend " : "",
67 (status & USBPORTSC_PR) ? "PortReset " : "",
68 (status & USBPORTSC_LSDA) ? "LowSpeed " : "",
69 (status & USBPORTSC_RD) ? "ResumeDetect " : "",
70 (status & USBPORTSC_PEC) ? "EnableChange " : "",
71 (status & USBPORTSC_PE) ? "PortEnabled " : "",
72 (status & USBPORTSC_CSC) ? "ConnectChange " : "",
73 (status & USBPORTSC_CCS) ? "PortConnected " : "");
74 }
75
76 void uhci_show_status(struct uhci *uhci)
77 {
78 unsigned int io_addr = uhci->io_addr;
79 unsigned short usbcmd, usbstat, usbint, usbfrnum;
80 unsigned int flbaseadd;
81 unsigned char sof;
82 unsigned short portsc1, portsc2;
83
84 usbcmd = inw(io_addr + 0);
85 usbstat = inw(io_addr + 2);
86 usbint = inw(io_addr + 4);
87 usbfrnum = inw(io_addr + 6);
88 flbaseadd = inl(io_addr + 8);
89 sof = inb(io_addr + 12);
90 portsc1 = inw(io_addr + 16);
91 portsc2 = inw(io_addr + 18);
92
93 printk(" usbcmd = %04x %s%s%s%s%s%s%s%s\n",
94 usbcmd,
95 (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
96 (usbcmd & USBCMD_CF) ? "CF " : "",
97 (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
98 (usbcmd & USBCMD_FGR) ? "FGR " : "",
99 (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
100 (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
101 (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
102 (usbcmd & USBCMD_RS) ? "RS " : "");
103
104 printk(" usbstat = %04x %s%s%s%s%s%s\n",
105 usbstat,
106 (usbstat & USBSTS_HCH) ? "HCHalted " : "",
107 (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
108 (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
109 (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
110 (usbstat & USBSTS_ERROR) ? "USBError " : "",
111 (usbstat & USBSTS_USBINT) ? "USBINT " : "");
112
113 printk(" usbint = %04x\n", usbint);
114 printk(" usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1,
115 0xfff & (4*(unsigned int)usbfrnum));
116 printk(" flbaseadd = %08x\n", flbaseadd);
117 printk(" sof = %02x\n", sof);
118 uhci_show_sc(1, portsc1);
119 uhci_show_sc(2, portsc2);
120 }
121
122 #define uhci_link_to_qh(x) ((struct uhci_qh *) uhci_link_to_td(x))
123
124 struct uhci_td *uhci_link_to_td(unsigned int link)
125 {
126 if (link & UHCI_PTR_TERM)
127 return NULL;
128
129 return bus_to_virt(link & ~UHCI_PTR_BITS);
130 }
131
132 void uhci_show_urb_queue(struct urb *urb)
133 {
134 struct urb_priv *urbp = urb->hcpriv;
135 struct list_head *head, *tmp;
136 int i, checked = 0, prevactive = 0;
137
138 printk(" URB [%p] urbp [%p]\n", urb, urbp);
139
140 if (urbp->qh)
141 printk(" QH [%p]\n", urbp->qh);
142 else
143 printk(" QH [%p] element (%08x) link (%08x)\n", urbp->qh,
144 urbp->qh->element, urbp->qh->link);
145
146 i = 0;
147
148 head = &urbp->list;
149 tmp = head->next;
150 while (tmp != head) {
151 struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
152
153 tmp = tmp->next;
154
155 printk(" td %d: [%p]\n", i++, td);
156 printk(" ");
157 uhci_show_td(td);
158
159 if (i > 10 && !checked && prevactive && tmp != head) {
160 struct list_head *ntmp = tmp;
161 struct uhci_td *ntd = td;
162 int active = 1, ni = i;
163
164 checked = 1;
165
166 while (ntmp != head && ntmp->next != head && active) {
167 ntd = list_entry(ntmp, struct uhci_td, list);
168
169 ntmp = ntmp->next;
170
171 active = ntd->status & TD_CTRL_ACTIVE;
172
173 ni++;
174 }
175
176 if (active && ni > i) {
177 printk(" [skipped %d active TD's]\n", ni - i);
178 tmp = ntmp;
179 td = ntd;
180 i = ni;
181 }
182 }
183
184 prevactive = td->status & TD_CTRL_ACTIVE;
185 }
186 }
187
188 void uhci_show_queue(struct uhci_qh *qh)
189 {
190 struct uhci_td *td, *first;
191 int i = 0, count = 1000;
192
193 if (qh->element & UHCI_PTR_QH)
194 printk(" Element points to QH (bug?)\n");
195
196 if (qh->element & UHCI_PTR_DEPTH)
197 printk(" Depth traverse\n");
198
199 if (qh->element & UHCI_PTR_TERM)
200 printk(" Terminate\n");
201
202 if (!(qh->element & ~UHCI_PTR_BITS)) {
203 printk(" td 0: [NULL]\n");
204 return;
205 }
206
207 first = uhci_link_to_td(qh->element);
208
209 /* Make sure it doesn't runaway */
210 for (td = first; td && count > 0;
211 td = uhci_link_to_td(td->link), --count) {
212 printk(" td %d: [%p]\n", i++, td);
213 printk(" ");
214 uhci_show_td(td);
215
216 if (td == uhci_link_to_td(td->link)) {
217 printk(KERN_ERR "td links to itself!\n");
218 break;
219 }
220 }
221 }
222
223 static int uhci_is_skeleton_td(struct uhci *uhci, struct uhci_td *td)
224 {
225 int j;
226
227 for (j = 0; j < UHCI_NUM_SKELTD; j++)
228 if (td == uhci->skeltd + j)
229 return 1;
230
231 return 0;
232 }
233
234 static int uhci_is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh)
235 {
236 int j;
237
238 for (j = 0; j < UHCI_NUM_SKELQH; j++)
239 if (qh == uhci->skelqh + j)
240 return 1;
241
242 return 0;
243 }
244
245 static const char *td_names[] = {"interrupt1", "interrupt2", "interrupt4",
246 "interrupt8", "interrupt16", "interrupt32",
247 "interrupt64", "interrupt128", "interrupt256" };
248 static const char *qh_names[] = { "control", "bulk" };
249
250 void uhci_show_queues(struct uhci *uhci)
251 {
252 int i, isqh = 0;
253 struct uhci_qh *qh;
254 struct uhci_td *td;
255
256 for (i = 0; i < UHCI_NUMFRAMES; ++i) {
257 int shown = 0;
258
259 td = uhci_link_to_td(uhci->fl->frame[i]);
260 if (td)
261 isqh = uhci->fl->frame[i] & UHCI_PTR_QH;
262 while (td && !isqh) {
263 if (uhci_is_skeleton_td(uhci, td))
264 break;
265
266 if (!shown) {
267 printk(" Frame %d\n", i);
268 shown = 1;
269 }
270
271 printk("[%p] ", td);
272
273 uhci_show_td(td);
274 td = uhci_link_to_td(td->link);
275 if (td)
276 isqh = td->link & UHCI_PTR_QH;
277 }
278 }
279 for (i = 0; i < UHCI_NUM_SKELTD; ++i) {
280 printk(" %s: [%p] (%08x)\n", td_names[i],
281 &uhci->skeltd[i],
282 uhci->skeltd[i].link);
283
284 td = uhci_link_to_td(uhci->skeltd[i].link);
285 if (td)
286 isqh = uhci->skeltd[i].link & UHCI_PTR_QH;
287 while (td && !isqh) {
288 if (uhci_is_skeleton_td(uhci, td))
289 break;
290
291 printk("[%p] ", td);
292
293 uhci_show_td(td);
294 td = uhci_link_to_td(td->link);
295 if (td)
296 isqh = td->link & UHCI_PTR_QH;
297 }
298 }
299 for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
300 printk(" %s: [%p] (%08x) (%08x)\n", qh_names[i],
301 &uhci->skelqh[i],
302 uhci->skelqh[i].link, uhci->skelqh[i].element);
303
304 qh = uhci_link_to_qh(uhci->skelqh[i].link);
305 for (; qh; qh = uhci_link_to_qh(qh->link)) {
306 if (uhci_is_skeleton_qh(uhci, qh))
307 break;
308
309 printk(" [%p] (%08x) (%08x)\n",
310 qh, qh->link, qh->element);
311
312 uhci_show_queue(qh);
313 }
314 }
315 }
316
317
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.