1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92#include <common.h>
93#include <pci.h>
94
95#ifdef CONFIG_USB_UHCI
96
97#include <usb.h>
98#include "usb_uhci.h"
99
100#define USB_MAX_TEMP_TD 128
101#define USB_MAX_TEMP_INT_TD 32
102
103
104#undef USB_UHCI_DEBUG
105
106#ifdef USB_UHCI_DEBUG
107#define USB_UHCI_PRINTF(fmt,args...) printf (fmt ,##args)
108#else
109#define USB_UHCI_PRINTF(fmt,args...)
110#endif
111
112
113static int irqvec = -1;
114unsigned int usb_base_addr;
115
116static uhci_td_t td_int[8];
117static uhci_qh_t qh_cntrl;
118static uhci_qh_t qh_bulk;
119static uhci_qh_t qh_end;
120static uhci_td_t td_last;
121
122
123static uhci_td_t tmp_td[USB_MAX_TEMP_TD];
124static uhci_td_t tmp_int_td[USB_MAX_TEMP_INT_TD];
125
126static unsigned long framelist[1024] __attribute__ ((aligned (0x1000)));
127
128static struct virt_root_hub rh;
129
130
131
132
133int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
134 void *buffer, int transfer_len,struct devrequest *setup);
135
136
137
138
139
140void usb_fill_td(uhci_td_t* td,unsigned long link,unsigned long status,
141 unsigned long info, unsigned long buffer, unsigned long dev)
142{
143 td->link=swap_32(link);
144 td->status=swap_32(status);
145 td->info=swap_32(info);
146 td->buffer=swap_32(buffer);
147 td->dev_ptr=dev;
148}
149
150
151
152
153
154
155void usb_fill_qh(uhci_qh_t* qh,unsigned long head,unsigned long element)
156{
157 qh->head=swap_32(head);
158 qh->element=swap_32(element);
159 qh->dev_ptr=0L;
160}
161
162
163
164unsigned long usb_uhci_td_stat(unsigned long status)
165{
166 unsigned long result=0;
167 result |= (status & TD_CTRL_NAK) ? USB_ST_NAK_REC : 0;
168 result |= (status & TD_CTRL_STALLED) ? USB_ST_STALLED : 0;
169 result |= (status & TD_CTRL_DBUFERR) ? USB_ST_BUF_ERR : 0;
170 result |= (status & TD_CTRL_BABBLE) ? USB_ST_BABBLE_DET : 0;
171 result |= (status & TD_CTRL_CRCTIMEO) ? USB_ST_CRC_ERR : 0;
172 result |= (status & TD_CTRL_BITSTUFF) ? USB_ST_BIT_ERR : 0;
173 result |= (status & TD_CTRL_ACTIVE) ? USB_ST_NOT_PROC : 0;
174 return result;
175}
176
177
178
179
180int usb_get_td_status(uhci_td_t *td,struct usb_device *dev)
181{
182 unsigned long temp,info;
183 unsigned long stat;
184 uhci_td_t *mytd=td;
185
186 if(dev->devnum==rh.devnum)
187 return 0;
188 dev->act_len=0;
189 stat=0;
190 do {
191 temp=swap_32((unsigned long)mytd->status);
192 stat=usb_uhci_td_stat(temp);
193 info=swap_32((unsigned long)mytd->info);
194 if(((info & 0xff)!= USB_PID_SETUP) &&
195 (((info >> 21) & 0x7ff)!= 0x7ff) &&
196 (temp & 0x7FF)!=0x7ff)
197 {
198 dev->act_len+=(temp & 0x7FF) + 1;
199 }
200 if(stat) {
201 dev->status=stat;
202 return -1;
203 }
204 temp=swap_32((unsigned long)mytd->link);
205 mytd=(uhci_td_t *)(temp & 0xfffffff0);
206 }while((temp & 0x1)==0);
207 dev->status=stat;
208 return 0;
209}
210
211
212
213
214
215
216
217
218
219
220int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
221 int transfer_len,struct devrequest *setup)
222{
223 unsigned long destination, status;
224 int maxsze = usb_maxpacket(dev, pipe);
225 unsigned long dataptr;
226 int len;
227 int pktsze;
228 int i=0;
229
230 if (!maxsze) {
231 USB_UHCI_PRINTF("uhci_submit_control_urb: pipesize for pipe %lx is zero\n", pipe);
232 return -1;
233 }
234 if(((pipe>>8)&0x7f)==rh.devnum) {
235
236 return uhci_submit_rh_msg(dev,pipe,buffer,transfer_len,setup);
237 }
238 USB_UHCI_PRINTF("uhci_submit_control start len %x, maxsize %x\n",transfer_len,maxsze);
239
240 destination = (pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
241
242 status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
243
244
245 usb_fill_td(&tmp_td[i],UHCI_PTR_TERM ,status, destination | (7 << 21),(unsigned long)setup,(unsigned long)dev);
246#if 0
247 {
248 char *sp=(char *)setup;
249 printf("SETUP to pipe %lx: %x %x %x %x %x %x %x %x\n", pipe,
250 sp[0],sp[1],sp[2],sp[3],sp[4],sp[5],sp[6],sp[7]);
251 }
252#endif
253 dataptr = (unsigned long)buffer;
254 len=transfer_len;
255
256
257
258 destination = (pipe & PIPE_DEVEP_MASK) | ((pipe & USB_DIR_IN)==0 ? USB_PID_OUT : USB_PID_IN);
259 while (len > 0) {
260
261 pktsze = len;
262 i++;
263 if (pktsze > maxsze)
264 pktsze = maxsze;
265 destination ^= 1 << TD_TOKEN_TOGGLE;
266 usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status, destination | ((pktsze - 1) << 21),dataptr,(unsigned long)dev);
267 tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]);
268
269 dataptr += pktsze;
270 len -= pktsze;
271 }
272
273
274
275
276 destination &= ~UHCI_PID;
277 if (((pipe & USB_DIR_IN)==0) || (transfer_len == 0))
278 destination |= USB_PID_IN;
279 else
280 destination |= USB_PID_OUT;
281 destination |= 1 << TD_TOKEN_TOGGLE;
282 i++;
283 status &=~TD_CTRL_SPD;
284
285 usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21),0,(unsigned long)dev);
286 tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]);
287
288 USB_UHCI_PRINTF("uhci_submit_control end (%d tmp_tds used)\n",i);
289
290 qh_cntrl.element=0xffffffffL;
291
292 qh_cntrl.dev_ptr=(unsigned long)dev;
293
294 qh_cntrl.element=swap_32((unsigned long)&tmp_td[0]);
295 return 0;
296}
297
298
299
300
301int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len)
302{
303 unsigned long destination, status,info;
304 unsigned long dataptr;
305 int maxsze = usb_maxpacket(dev, pipe);
306 int len;
307 int i=0;
308
309 if(transfer_len < 0) {
310 printf("Negative transfer length in submit_bulk\n");
311 return -1;
312 }
313 if (!maxsze)
314 return -1;
315
316 destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
317
318 status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
319
320
321 len = transfer_len;
322 dataptr = (unsigned long)buffer;
323 do {
324 int pktsze = len;
325 if (pktsze > maxsze)
326 pktsze = maxsze;
327
328 info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) |
329 (usb_gettoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
330
331 if((len-pktsze)==0)
332 status |= TD_CTRL_IOC;
333
334 usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status, info,dataptr,(unsigned long)dev);
335 if(i>0)
336 tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]);
337 i++;
338 dataptr += pktsze;
339 len -= pktsze;
340 usb_dotoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
341 } while (len > 0);
342
343 qh_bulk.element=0xffffffffL;
344
345 qh_bulk.dev_ptr=(unsigned long)dev;
346
347 qh_bulk.element=swap_32((unsigned long)&tmp_td[0]);
348 return 0;
349}
350
351
352
353
354uhci_td_t *uhci_alloc_int_td(void)
355{
356 int i;
357 for(i=0;i<USB_MAX_TEMP_INT_TD;i++) {
358 if(tmp_int_td[i].dev_ptr==0)
359 return &tmp_int_td[i];
360 }
361 return NULL;
362}
363
364#if 0
365void uhci_show_temp_int_td(void)
366{
367 int i;
368 for(i=0;i<USB_MAX_TEMP_INT_TD;i++) {
369 if((tmp_int_td[i].dev_ptr&0x01)!=0x1L)
370 printf("temp_td %d is assigned to dev %lx\n",i,tmp_int_td[i].dev_ptr);
371 }
372 printf("all others temp_tds are free\n");
373}
374#endif
375
376
377
378int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len, int interval)
379{
380 int nint, n;
381 unsigned long status, destination;
382 unsigned long info,tmp;
383 uhci_td_t *mytd;
384 if (interval < 0 || interval >= 256)
385 return -1;
386
387 if (interval == 0)
388 nint = 0;
389 else {
390 for (nint = 0, n = 1; nint <= 8; nint++, n += n)
391 {
392 if(interval < n) {
393 interval = n / 2;
394 break;
395 }
396 }
397 nint--;
398 }
399
400 USB_UHCI_PRINTF("Rounded interval to %i, chain %i\n", interval, nint);
401 mytd=uhci_alloc_int_td();
402 if(mytd==NULL) {
403 printf("No free INT TDs found\n");
404 return -1;
405 }
406 status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | (3 << 27);
407
408
409
410 destination =(pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe) | (((transfer_len - 1) & 0x7ff) << 21);
411
412 info = destination | (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << TD_TOKEN_TOGGLE);
413 tmp = swap_32(td_int[nint].link);
414 usb_fill_td(mytd,tmp,status, info,(unsigned long)buffer,(unsigned long)dev);
415
416 tmp = swap_32((unsigned long)mytd);
417 td_int[nint].link=tmp;
418
419 usb_dotoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
420
421 return 0;
422}
423
424
425
426
427
428
429void reset_hc(void)
430{
431
432
433 out16r( usb_base_addr + USBPORTSC1,0x0204);
434 out16r( usb_base_addr + USBPORTSC2,0x0204);
435 out16r( usb_base_addr + USBCMD,USBCMD_GRESET | USBCMD_RS);
436
437 out16r(usb_base_addr + USBINTR,0);
438 mdelay(50);
439 out16r( usb_base_addr + USBCMD,0);
440 mdelay(10);
441}
442
443void start_hc(void)
444{
445 int timeout = 1000;
446
447 while(in16r(usb_base_addr + USBCMD) & USBCMD_HCRESET) {
448 if (!--timeout) {
449 printf("USBCMD_HCRESET timed out!\n");
450 break;
451 }
452 }
453
454 out16r(usb_base_addr + USBINTR,USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP);
455
456 out16r(usb_base_addr + USBFRNUM,0);
457
458 out32r(usb_base_addr+USBFLBASEADD,(unsigned long)&framelist);
459
460 out16r(usb_base_addr + USBCMD,USBCMD_RS | USBCMD_CF | USBCMD_MAXP);
461}
462
463
464
465void usb_init_skel(void)
466{
467 unsigned long temp;
468 int n;
469
470 for(n=0;n<USB_MAX_TEMP_INT_TD;n++)
471 tmp_int_td[n].dev_ptr=0L;
472
473 usb_fill_td(&td_last,UHCI_PTR_TERM,TD_CTRL_IOC ,0,0,0L);
474
475
476 usb_fill_qh(&qh_end,UHCI_PTR_TERM,(unsigned long)&td_last);
477
478 temp=(unsigned long)&qh_end;
479 usb_fill_qh(&qh_bulk,temp | UHCI_PTR_QH,UHCI_PTR_TERM);
480
481 temp=(unsigned long)&qh_bulk;
482 usb_fill_qh(&qh_cntrl, temp | UHCI_PTR_QH,UHCI_PTR_TERM);
483
484 temp=(unsigned long)&qh_cntrl;
485 usb_fill_td(&td_int[0],temp | UHCI_PTR_QH,0,0,0,0L);
486 temp=(unsigned long)&td_int[0];
487 for(n=1; n<8; n++)
488 usb_fill_td(&td_int[n],temp,0,0,0,0L);
489 for (n = 0; n < 1024; n++) {
490
491 int m, o;
492 if ((n&127)==127)
493 framelist[n]= swap_32((unsigned long)&td_int[0]);
494 else
495 for (o = 1, m = 2; m <= 128; o++, m += m)
496 if ((n & (m - 1)) == ((m - 1) / 2))
497 framelist[n]= swap_32((unsigned long)&td_int[o]);
498 }
499}
500
501
502
503
504void usb_check_skel(void)
505{
506 struct usb_device *dev;
507
508 if(qh_cntrl.dev_ptr!=0)
509 {
510 dev=(struct usb_device *)qh_cntrl.dev_ptr;
511 usb_get_td_status(&tmp_td[0],dev);
512 if(!(dev->status & USB_ST_NOT_PROC)) {
513 qh_cntrl.dev_ptr=0;
514 }
515 }
516
517 if(qh_bulk.dev_ptr!=0)
518 {
519 dev=(struct usb_device *)qh_bulk.dev_ptr;
520 usb_get_td_status(&tmp_td[0],dev);
521 if(!(dev->status & USB_ST_NOT_PROC)) {
522 qh_bulk.dev_ptr=0;
523 }
524 }
525}
526
527
528
529
530
531void usb_check_int_chain(void)
532{
533 int i,res;
534 unsigned long link,status;
535 struct usb_device *dev;
536 uhci_td_t *td,*prevtd;
537
538 for(i=0;i<8;i++) {
539 prevtd = &td_int[i];
540 link=swap_32(td_int[i].link) & 0xfffffff0;
541 td=(uhci_td_t *)link;
542
543
544
545
546 while(((i>0) && (link != (unsigned long)&td_int[0])) ||
547 ((i==0) && !(swap_32(td->link) & UHCI_PTR_QH)))
548 {
549
550 status=swap_32(td->status);
551 if((td->dev_ptr!=0L) && !(status & TD_CTRL_ACTIVE)) {
552
553 dev=(struct usb_device *)td->dev_ptr;
554 dev->irq_act_len=((status & 0x7FF)==0x7FF) ? 0 : (status & 0x7FF) + 1;
555 dev->irq_status=usb_uhci_td_stat(status);
556 res=dev->irq_handle(dev);
557 if(res==1) {
558
559 status|=TD_CTRL_ACTIVE;
560 td->status=swap_32(status);
561 prevtd=td;
562 }
563 else {
564 prevtd->link=td->link;
565
566 td->dev_ptr=0L;
567 }
568 }
569 link=swap_32(td->link) & 0xfffffff0;
570 td=(uhci_td_t *)link;
571 }
572 }
573}
574
575
576
577
578void handle_usb_interrupt(void)
579{
580 unsigned short status;
581
582
583
584
585
586
587 status = in16r(usb_base_addr + USBSTS);
588
589 if (!status)
590 return;
591 if (status != 1) {
592
593 if ((status&0x20) && ((in16r(usb_base_addr+USBCMD) && USBCMD_RS)==0)) {
594 out16r(usb_base_addr + USBCMD, USBCMD_RS | in16r(usb_base_addr + USBCMD));
595 }
596 }
597 usb_check_int_chain();
598 usb_check_skel();
599 out16r(usb_base_addr+USBSTS,status);
600}
601
602
603
604
605int usb_lowlevel_init(void)
606{
607 unsigned char temp;
608 int busdevfunc;
609
610 busdevfunc=pci_find_device(USB_UHCI_VEND_ID,USB_UHCI_DEV_ID,0);
611 if(busdevfunc==-1) {
612 printf("Error USB UHCI (%04X,%04X) not found\n",USB_UHCI_VEND_ID,USB_UHCI_DEV_ID);
613 return -1;
614 }
615 pci_read_config_byte(busdevfunc,PCI_INTERRUPT_LINE,&temp);
616 irqvec = temp;
617 irq_free_handler(irqvec);
618 USB_UHCI_PRINTF("Interrupt Line = %d, is %d\n",irqvec);
619 pci_read_config_byte(busdevfunc,PCI_INTERRUPT_PIN,&temp);
620 USB_UHCI_PRINTF("Interrupt Pin = %ld\n",temp);
621 pci_read_config_dword(busdevfunc,PCI_BASE_ADDRESS_4,&usb_base_addr);
622 USB_UHCI_PRINTF("IO Base Address = 0x%lx\n",usb_base_addr);
623 usb_base_addr&=0xFFFFFFF0;
624 usb_base_addr+=CONFIG_SYS_ISA_IO_BASE_ADDRESS;
625 rh.devnum = 0;
626 usb_init_skel();
627 reset_hc();
628 start_hc();
629 irq_install_handler(irqvec, (interrupt_handler_t *)handle_usb_interrupt, NULL);
630 return 0;
631}
632
633
634
635int usb_lowlevel_stop(void)
636{
637 if(irqvec==-1)
638 return 1;
639 irq_free_handler(irqvec);
640 reset_hc();
641 irqvec = -1;
642 return 0;
643}
644
645
646
647
648
649#undef USB_RH_DEBUG
650
651#ifdef USB_RH_DEBUG
652#define USB_RH_PRINTF(fmt,args...) printf (fmt ,##args)
653static void usb_display_wValue(unsigned short wValue,unsigned short wIndex);
654static void usb_display_Req(unsigned short req);
655#else
656#define USB_RH_PRINTF(fmt,args...)
657static void usb_display_wValue(unsigned short wValue,unsigned short wIndex) {}
658static void usb_display_Req(unsigned short req) {}
659#endif
660
661static unsigned char root_hub_dev_des[] =
662{
663 0x12,
664 0x01,
665 0x00,
666 0x01,
667 0x09,
668 0x00,
669 0x00,
670 0x08,
671 0x00,
672 0x00,
673 0x00,
674 0x00,
675 0x00,
676 0x00,
677 0x01,
678 0x00,
679 0x00,
680 0x01
681};
682
683
684
685static unsigned char root_hub_config_des[] =
686{
687 0x09,
688 0x02,
689 0x19,
690 0x00,
691 0x01,
692 0x01,
693 0x00,
694 0x40,
695
696 0x00,
697
698
699 0x09,
700 0x04,
701 0x00,
702 0x00,
703 0x01,
704 0x09,
705 0x00,
706 0x00,
707 0x00,
708
709
710 0x07,
711 0x05,
712 0x81,
713 0x03,
714 0x08,
715 0x00,
716 0xff
717};
718
719
720static unsigned char root_hub_hub_des[] =
721{
722 0x09,
723 0x29,
724 0x02,
725 0x00,
726 0x00,
727 0x01,
728 0x00,
729 0x00,
730 0xff
731};
732
733static unsigned char root_hub_str_index0[] =
734{
735 0x04,
736 0x03,
737 0x09,
738 0x04,
739};
740
741static unsigned char root_hub_str_index1[] =
742{
743 28,
744 0x03,
745 'U',
746 0,
747 'H',
748 0,
749 'C',
750 0,
751 'I',
752 0,
753 ' ',
754 0,
755 'R',
756 0,
757 'o',
758 0,
759 'o',
760 0,
761 't',
762 0,
763 ' ',
764 0,
765 'H',
766 0,
767 'u',
768 0,
769 'b',
770 0,
771};
772
773
774
775
776
777
778
779int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len,struct devrequest *cmd)
780{
781 void *data = buffer;
782 int leni = transfer_len;
783 int len = 0;
784 int status = 0;
785 int stat = 0;
786 int i;
787
788 unsigned short cstatus;
789
790 unsigned short bmRType_bReq;
791 unsigned short wValue;
792 unsigned short wIndex;
793 unsigned short wLength;
794
795 if (usb_pipeint(pipe)) {
796 printf("Root-Hub submit IRQ: NOT implemented\n");
797#if 0
798 uhci->rh.urb = urb;
799 uhci->rh.send = 1;
800 uhci->rh.interval = urb->interval;
801 rh_init_int_timer (urb);
802#endif
803 return 0;
804 }
805 bmRType_bReq = cmd->requesttype | cmd->request << 8;
806 wValue = swap_16(cmd->value);
807 wIndex = swap_16(cmd->index);
808 wLength = swap_16(cmd->length);
809 usb_display_Req(bmRType_bReq);
810 for (i = 0; i < 8; i++)
811 rh.c_p_r[i] = 0;
812 USB_RH_PRINTF("Root-Hub: adr: %2x cmd(%1x): %02x%02x %04x %04x %04x\n",
813 dev->devnum, 8, cmd->requesttype,cmd->request, wValue, wIndex, wLength);
814
815 switch (bmRType_bReq) {
816
817
818
819
820
821
822
823
824 case RH_GET_STATUS:
825 *(unsigned short *) data = swap_16(1);
826 len=2;
827 break;
828 case RH_GET_STATUS | RH_INTERFACE:
829 *(unsigned short *) data = swap_16(0);
830 len=2;
831 break;
832 case RH_GET_STATUS | RH_ENDPOINT:
833 *(unsigned short *) data = swap_16(0);
834 len=2;
835 break;
836 case RH_GET_STATUS | RH_CLASS:
837 *(unsigned long *) data = swap_32(0);
838 len=4;
839 break;
840 case RH_GET_STATUS | RH_OTHER | RH_CLASS:
841
842 status = in16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1));
843 cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
844 ((status & USBPORTSC_PEC) >> (3 - 1)) |
845 (rh.c_p_r[wIndex - 1] << (0 + 4));
846 status = (status & USBPORTSC_CCS) |
847 ((status & USBPORTSC_PE) >> (2 - 1)) |
848 ((status & USBPORTSC_SUSP) >> (12 - 2)) |
849 ((status & USBPORTSC_PR) >> (9 - 4)) |
850 (1 << 8) |
851 ((status & USBPORTSC_LSDA) << (-8 + 9));
852
853 *(unsigned short *) data = swap_16(status);
854 *(unsigned short *) (data + 2) = swap_16(cstatus);
855 len=4;
856 break;
857 case RH_CLEAR_FEATURE | RH_ENDPOINT:
858 switch (wValue) {
859 case (RH_ENDPOINT_STALL):
860 len=0;
861 break;
862 }
863 break;
864
865 case RH_CLEAR_FEATURE | RH_CLASS:
866 switch (wValue) {
867 case (RH_C_HUB_OVER_CURRENT):
868 len=0;
869 break;
870 }
871 break;
872
873 case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
874 usb_display_wValue(wValue,wIndex);
875 switch (wValue) {
876 case (RH_PORT_ENABLE):
877 status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
878 status = (status & 0xfff5) & ~USBPORTSC_PE;
879 out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
880 len=0;
881 break;
882 case (RH_PORT_SUSPEND):
883 status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
884 status = (status & 0xfff5) & ~USBPORTSC_SUSP;
885 out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
886 len=0;
887 break;
888 case (RH_PORT_POWER):
889 len=0;
890 break;
891 case (RH_C_PORT_CONNECTION):
892 status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
893 status = (status & 0xfff5) | USBPORTSC_CSC;
894 out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
895 len=0;
896 break;
897 case (RH_C_PORT_ENABLE):
898 status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
899 status = (status & 0xfff5) | USBPORTSC_PEC;
900 out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
901 len=0;
902 break;
903 case (RH_C_PORT_SUSPEND):
904
905 len=0;
906 break;
907 case (RH_C_PORT_OVER_CURRENT):
908 len=0;
909 break;
910 case (RH_C_PORT_RESET):
911 rh.c_p_r[wIndex - 1] = 0;
912 len=0;
913 break;
914 }
915 break;
916 case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
917 usb_display_wValue(wValue,wIndex);
918 switch (wValue) {
919 case (RH_PORT_SUSPEND):
920 status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
921 status = (status & 0xfff5) | USBPORTSC_SUSP;
922 out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
923 len=0;
924 break;
925 case (RH_PORT_RESET):
926 status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
927 status = (status & 0xfff5) | USBPORTSC_PR;
928 out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
929 mdelay(10);
930 status = (status & 0xfff5) & ~USBPORTSC_PR;
931 out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
932 udelay(10);
933 status = (status & 0xfff5) | USBPORTSC_PE;
934 out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
935 mdelay(10);
936 status = (status & 0xfff5) | 0xa;
937 out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
938 len=0;
939 break;
940 case (RH_PORT_POWER):
941 len=0;
942 break;
943 case (RH_PORT_ENABLE):
944 status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
945 status = (status & 0xfff5) | USBPORTSC_PE;
946 out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
947 len=0;
948 break;
949 }
950 break;
951
952 case RH_SET_ADDRESS:
953 rh.devnum = wValue;
954 len=0;
955 break;
956 case RH_GET_DESCRIPTOR:
957 switch ((wValue & 0xff00) >> 8) {
958 case (0x01):
959 i=sizeof(root_hub_config_des);
960 status=i > wLength ? wLength : i;
961 len = leni > status ? status : leni;
962 memcpy (data, root_hub_dev_des, len);
963 break;
964 case (0x02):
965 i=sizeof(root_hub_config_des);
966 status=i > wLength ? wLength : i;
967 len = leni > status ? status : leni;
968 memcpy (data, root_hub_config_des, len);
969 break;
970 case (0x03):
971 if(wValue==0x0300) {
972 i=sizeof(root_hub_str_index0);
973 status = i > wLength ? wLength : i;
974 len = leni > status ? status : leni;
975 memcpy (data, root_hub_str_index0, len);
976 break;
977 }
978 if(wValue==0x0301) {
979 i=sizeof(root_hub_str_index1);
980 status = i > wLength ? wLength : i;
981 len = leni > status ? status : leni;
982 memcpy (data, root_hub_str_index1, len);
983 break;
984 }
985 stat = USB_ST_STALLED;
986 }
987 break;
988
989 case RH_GET_DESCRIPTOR | RH_CLASS:
990 root_hub_hub_des[2] = 2;
991 i=sizeof(root_hub_hub_des);
992 status= i > wLength ? wLength : i;
993 len = leni > status ? status : leni;
994 memcpy (data, root_hub_hub_des, len);
995 break;
996 case RH_GET_CONFIGURATION:
997 *(unsigned char *) data = 0x01;
998 len = 1;
999 break;
1000 case RH_SET_CONFIGURATION:
1001 len=0;
1002 break;
1003 default:
1004 stat = USB_ST_STALLED;
1005 }
1006 USB_RH_PRINTF("Root-Hub stat %lx port1: %x port2: %x\n\n",stat,
1007 in16r(usb_base_addr + USBPORTSC1), in16r(usb_base_addr + USBPORTSC2));
1008 dev->act_len=len;
1009 dev->status=stat;
1010 return stat;
1011
1012}
1013
1014
1015
1016
1017
1018#ifdef USB_RH_DEBUG
1019
1020static void usb_display_Req(unsigned short req)
1021{
1022 USB_RH_PRINTF("- Root-Hub Request: ");
1023 switch (req) {
1024 case RH_GET_STATUS:
1025 USB_RH_PRINTF("Get Status ");
1026 break;
1027 case RH_GET_STATUS | RH_INTERFACE:
1028 USB_RH_PRINTF("Get Status Interface ");
1029 break;
1030 case RH_GET_STATUS | RH_ENDPOINT:
1031 USB_RH_PRINTF("Get Status Endpoint ");
1032 break;
1033 case RH_GET_STATUS | RH_CLASS:
1034 USB_RH_PRINTF("Get Status Class");
1035 break;
1036 case RH_GET_STATUS | RH_OTHER | RH_CLASS:
1037 USB_RH_PRINTF("Get Status Class Others");
1038 break;
1039 case RH_CLEAR_FEATURE | RH_ENDPOINT:
1040 USB_RH_PRINTF("Clear Feature Endpoint ");
1041 break;
1042 case RH_CLEAR_FEATURE | RH_CLASS:
1043 USB_RH_PRINTF("Clear Feature Class ");
1044 break;
1045 case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
1046 USB_RH_PRINTF("Clear Feature Other Class ");
1047 break;
1048 case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
1049 USB_RH_PRINTF("Set Feature Other Class ");
1050 break;
1051 case RH_SET_ADDRESS:
1052 USB_RH_PRINTF("Set Address ");
1053 break;
1054 case RH_GET_DESCRIPTOR:
1055 USB_RH_PRINTF("Get Descriptor ");
1056 break;
1057 case RH_GET_DESCRIPTOR | RH_CLASS:
1058 USB_RH_PRINTF("Get Descriptor Class ");
1059 break;
1060 case RH_GET_CONFIGURATION:
1061 USB_RH_PRINTF("Get Configuration ");
1062 break;
1063 case RH_SET_CONFIGURATION:
1064 USB_RH_PRINTF("Get Configuration ");
1065 break;
1066 default:
1067 USB_RH_PRINTF("****UNKNOWN**** 0x%04X ",req);
1068 }
1069 USB_RH_PRINTF("\n");
1070
1071}
1072
1073static void usb_display_wValue(unsigned short wValue,unsigned short wIndex)
1074{
1075 switch (wValue) {
1076 case (RH_PORT_ENABLE):
1077 USB_RH_PRINTF("Root-Hub: Enable Port %d\n",wIndex);
1078 break;
1079 case (RH_PORT_SUSPEND):
1080 USB_RH_PRINTF("Root-Hub: Suspend Port %d\n",wIndex);
1081 break;
1082 case (RH_PORT_POWER):
1083 USB_RH_PRINTF("Root-Hub: Port Power %d\n",wIndex);
1084 break;
1085 case (RH_C_PORT_CONNECTION):
1086 USB_RH_PRINTF("Root-Hub: C Port Connection Port %d\n",wIndex);
1087 break;
1088 case (RH_C_PORT_ENABLE):
1089 USB_RH_PRINTF("Root-Hub: C Port Enable Port %d\n",wIndex);
1090 break;
1091 case (RH_C_PORT_SUSPEND):
1092 USB_RH_PRINTF("Root-Hub: C Port Suspend Port %d\n",wIndex);
1093 break;
1094 case (RH_C_PORT_OVER_CURRENT):
1095 USB_RH_PRINTF("Root-Hub: C Port Over Current Port %d\n",wIndex);
1096 break;
1097 case (RH_C_PORT_RESET):
1098 USB_RH_PRINTF("Root-Hub: C Port reset Port %d\n",wIndex);
1099 break;
1100 default:
1101 USB_RH_PRINTF("Root-Hub: unknown %x %x\n",wValue,wIndex);
1102 break;
1103 }
1104}
1105
1106#endif
1107
1108
1109#ifdef USB_UHCI_DEBUG
1110
1111static int usb_display_td(uhci_td_t *td)
1112{
1113 unsigned long tmp;
1114 int valid;
1115
1116 printf("TD at %p:\n",td);
1117
1118 tmp=swap_32(td->link);
1119 printf("Link points to 0x%08lX, %s first, %s, %s\n",tmp&0xfffffff0,
1120 ((tmp & 0x4)==0x4) ? "Depth" : "Breath",
1121 ((tmp & 0x2)==0x2) ? "QH" : "TD",
1122 ((tmp & 0x1)==0x1) ? "invalid" : "valid");
1123 valid=((tmp & 0x1)==0x0);
1124 tmp=swap_32(td->status);
1125 printf(" %s %ld Errors %s %s %s \n %s %s %s %s %s %s\n Len 0x%lX\n",
1126 (((tmp>>29)&0x1)==0x1) ? "SPD Enable" : "SPD Disable",
1127 ((tmp>>28)&0x3),
1128 (((tmp>>26)&0x1)==0x1) ? "Low Speed" : "Full Speed",
1129 (((tmp>>25)&0x1)==0x1) ? "ISO " : "",
1130 (((tmp>>24)&0x1)==0x1) ? "IOC " : "",
1131 (((tmp>>23)&0x1)==0x1) ? "Active " : "Inactive ",
1132 (((tmp>>22)&0x1)==0x1) ? "Stalled" : "",
1133 (((tmp>>21)&0x1)==0x1) ? "Data Buffer Error" : "",
1134 (((tmp>>20)&0x1)==0x1) ? "Babble" : "",
1135 (((tmp>>19)&0x1)==0x1) ? "NAK" : "",
1136 (((tmp>>18)&0x1)==0x1) ? "Bitstuff Error" : "",
1137 (tmp&0x7ff));
1138 tmp=swap_32(td->info);
1139 printf(" MaxLen 0x%lX\n",((tmp>>21)&0x7FF));
1140 printf(" %s Endpoint 0x%lX Dev Addr 0x%lX PID 0x%lX\n",((tmp>>19)&0x1)==0x1 ? "TOGGLE" : "",
1141 ((tmp>>15)&0xF),((tmp>>8)&0x7F),tmp&0xFF);
1142 tmp=swap_32(td->buffer);
1143 printf(" Buffer 0x%08lX\n",tmp);
1144 printf(" DEV %08lX\n",td->dev_ptr);
1145 return valid;
1146}
1147
1148
1149void usb_show_td(int max)
1150{
1151 int i;
1152 if(max>0) {
1153 for(i=0;i<max;i++) {
1154 usb_display_td(&tmp_td[i]);
1155 }
1156 }
1157 else {
1158 i=0;
1159 do {
1160 printf("tmp_td[%d]\n",i);
1161 }while(usb_display_td(&tmp_td[i++]));
1162 }
1163}
1164
1165
1166#endif
1167#endif
1168
1169
1170