Commit 9c998aa83148c75cd734a18958218926313bd54c
1 parent
f530187dbd
Exists in
master
and in
54 other branches
Fix low-level OHCI transfers for ARM920t and MPC5xxx
A new, Windows compatible init sequence was also backported from Linux 2.6, but disabled with #undef NEW_INIT_SEQ as it wouldn't change the behaviour of the memopry sticks we tested. Maybe it's not relevant for mass storage devices. For recerence, see file common/usb.c, function usb_new_device(), section #ifdef NEW_INIT_SEQ.
Showing 9 changed files with 400 additions and 153 deletions Side-by-side Diff
common/cmd_usb.c
... | ... | @@ -448,11 +448,17 @@ |
448 | 448 | block_dev_desc_t *stor_dev; |
449 | 449 | #endif |
450 | 450 | |
451 | - if ((strncmp(argv[1],"reset",5) == 0) || | |
452 | - (strncmp(argv[1],"start",5) == 0)){ | |
451 | + if ((strncmp(argv[1], "reset", 5) == 0) || | |
452 | + (strncmp(argv[1], "start", 5) == 0)){ | |
453 | 453 | usb_stop(); |
454 | 454 | printf("(Re)start USB...\n"); |
455 | - usb_init(); | |
455 | + i = usb_init(); | |
456 | +#ifdef CONFIG_USB_STORAGE | |
457 | + /* try to recognize storage devices immediately */ | |
458 | + if (i >= 0) | |
459 | + usb_stor_curr_dev = usb_stor_scan(1); | |
460 | + | |
461 | +#endif | |
456 | 462 | return 0; |
457 | 463 | } |
458 | 464 | if (strncmp(argv[1],"stop",4) == 0) { |
459 | 465 | |
... | ... | @@ -513,15 +519,18 @@ |
513 | 519 | return 0; |
514 | 520 | } |
515 | 521 | #ifdef CONFIG_USB_STORAGE |
516 | - if (strncmp(argv[1],"scan",4) == 0) { | |
517 | - printf("Scan for storage device:\n"); | |
518 | - usb_stor_curr_dev=usb_stor_scan(1); | |
519 | - if (usb_stor_curr_dev==-1) { | |
520 | - printf("No device found. Not initialized?\n"); | |
521 | - return 1; | |
522 | - } | |
522 | + if (strncmp(argv[1], "scan", 4) == 0) { | |
523 | + printf(" NOTE: this command is obsolete and will be phased out\n"); | |
524 | + printf(" please use 'usb storage' for USB storage devices information\n\n"); | |
525 | + usb_stor_info(); | |
523 | 526 | return 0; |
524 | 527 | } |
528 | + | |
529 | + if (strncmp(argv[1], "stor", 4) == 0) { | |
530 | + usb_stor_info(); | |
531 | + return 0; | |
532 | + } | |
533 | + | |
525 | 534 | if (strncmp(argv[1],"part",4) == 0) { |
526 | 535 | int devno, ok; |
527 | 536 | for (ok=0, devno=0; devno<USB_MAX_STOR_DEV; ++devno) { |
... | ... | @@ -560,8 +569,8 @@ |
560 | 569 | return 1; |
561 | 570 | } |
562 | 571 | } |
563 | - if (strcmp(argv[1],"dev") == 0) { | |
564 | - if (argc==3) { | |
572 | + if (strncmp(argv[1], "dev", 3) == 0) { | |
573 | + if (argc == 3) { | |
565 | 574 | int dev = (int)simple_strtoul(argv[2], NULL, 10); |
566 | 575 | printf ("\nUSB device %d: ", dev); |
567 | 576 | if (dev >= USB_MAX_STOR_DEV) { |
... | ... | @@ -608,7 +617,7 @@ |
608 | 617 | "usb stop [f] - stop USB [f]=force stop\n" |
609 | 618 | "usb tree - show USB device tree\n" |
610 | 619 | "usb info [dev] - show available USB devices\n" |
611 | - "usb scan - (re-)scan USB bus for storage devices\n" | |
620 | + "usb storage - show details of USB storage devices\n" | |
612 | 621 | "usb dev [dev] - show or set current USB storage device\n" |
613 | 622 | "usb part [dev] - print partition table of one or all USB storage devices\n" |
614 | 623 | "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n" |
common/usb.c
... | ... | @@ -37,6 +37,7 @@ |
37 | 37 | #include <common.h> |
38 | 38 | #include <command.h> |
39 | 39 | #include <asm/processor.h> |
40 | +#include <linux/ctype.h> | |
40 | 41 | |
41 | 42 | #if (CONFIG_COMMANDS & CFG_CMD_USB) |
42 | 43 | |
... | ... | @@ -46,7 +47,7 @@ |
46 | 47 | #endif |
47 | 48 | |
48 | 49 | |
49 | -/* #define USB_DEBUG */ | |
50 | +#undef USB_DEBUG | |
50 | 51 | |
51 | 52 | #ifdef USB_DEBUG |
52 | 53 | #define USB_PRINTF(fmt,args...) printf (fmt ,##args) |
... | ... | @@ -70,6 +71,7 @@ |
70 | 71 | int usb_hub_probe(struct usb_device *dev, int ifnum); |
71 | 72 | void usb_hub_reset(void); |
72 | 73 | |
74 | + | |
73 | 75 | /*********************************************************************** |
74 | 76 | * wait_ms |
75 | 77 | */ |
... | ... | @@ -157,6 +159,7 @@ |
157 | 159 | { |
158 | 160 | if((timeout==0)&&(!asynch_allowed)) /* request for a asynch control pipe is not allowed */ |
159 | 161 | return -1; |
162 | + | |
160 | 163 | /* set setup command */ |
161 | 164 | setup_packet.requesttype = requesttype; |
162 | 165 | setup_packet.request = request; |
... | ... | @@ -330,8 +333,7 @@ |
330 | 333 | int usb_clear_halt(struct usb_device *dev, int pipe) |
331 | 334 | { |
332 | 335 | int result; |
333 | - unsigned short status; | |
334 | - int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7); | |
336 | + int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7); | |
335 | 337 | |
336 | 338 | result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
337 | 339 | USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, USB_CNTL_TIMEOUT * 3); |
338 | 340 | |
... | ... | @@ -339,15 +341,14 @@ |
339 | 341 | /* don't clear if failed */ |
340 | 342 | if (result < 0) |
341 | 343 | return result; |
342 | - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | |
343 | - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp, | |
344 | - &status, sizeof(status), USB_CNTL_TIMEOUT * 3); | |
345 | - if (result < 0) | |
346 | - return result; | |
347 | - USB_PRINTF("usb_clear_halt: status 0x%x\n",status); | |
348 | - if (status & 1) | |
349 | - return -1; /* still halted */ | |
344 | + | |
345 | + /* | |
346 | + * NOTE: we do not get status and verify reset was successful | |
347 | + * as some devices are reported to lock up upon this check.. | |
348 | + */ | |
349 | + | |
350 | 350 | usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); |
351 | + | |
351 | 352 | /* toggle is reset on clear */ |
352 | 353 | usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); |
353 | 354 | return 0; |
... | ... | @@ -423,7 +424,7 @@ |
423 | 424 | struct usb_interface_descriptor *if_face = NULL; |
424 | 425 | int ret, i; |
425 | 426 | |
426 | - for (i=0; i<dev->config.bNumInterfaces; i++) { | |
427 | + for (i = 0; i < dev->config.bNumInterfaces; i++) { | |
427 | 428 | if (dev->config.if_desc[i].bInterfaceNumber == interface) { |
428 | 429 | if_face = &dev->config.if_desc[i]; |
429 | 430 | break; |
... | ... | @@ -439,8 +440,6 @@ |
439 | 440 | interface, NULL, 0, USB_CNTL_TIMEOUT * 5)) < 0) |
440 | 441 | return ret; |
441 | 442 | |
442 | - if_face->act_altsetting = (unsigned char)alternate; | |
443 | - usb_set_maxpacket(dev); | |
444 | 443 | return 0; |
445 | 444 | } |
446 | 445 | |
447 | 446 | |
... | ... | @@ -511,11 +510,74 @@ |
511 | 510 | */ |
512 | 511 | int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) |
513 | 512 | { |
514 | - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | |
515 | - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, | |
516 | - (USB_DT_STRING << 8) + index, langid, buf, size, USB_CNTL_TIMEOUT); | |
513 | + int i; | |
514 | + int result; | |
515 | + | |
516 | + for (i = 0; i < 3; ++i) { | |
517 | + /* some devices are flaky */ | |
518 | + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | |
519 | + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, | |
520 | + (USB_DT_STRING << 8) + index, langid, buf, size, | |
521 | + USB_CNTL_TIMEOUT); | |
522 | + | |
523 | + if (result > 0) | |
524 | + break; | |
525 | + } | |
526 | + | |
527 | + return result; | |
517 | 528 | } |
518 | 529 | |
530 | + | |
531 | +static void usb_try_string_workarounds(unsigned char *buf, int *length) | |
532 | +{ | |
533 | + int newlength, oldlength = *length; | |
534 | + | |
535 | + for (newlength = 2; newlength + 1 < oldlength; newlength += 2) | |
536 | + if (!isprint(buf[newlength]) || buf[newlength + 1]) | |
537 | + break; | |
538 | + | |
539 | + if (newlength > 2) { | |
540 | + buf[0] = newlength; | |
541 | + *length = newlength; | |
542 | + } | |
543 | +} | |
544 | + | |
545 | + | |
546 | +static int usb_string_sub(struct usb_device *dev, unsigned int langid, | |
547 | + unsigned int index, unsigned char *buf) | |
548 | +{ | |
549 | + int rc; | |
550 | + | |
551 | + /* Try to read the string descriptor by asking for the maximum | |
552 | + * possible number of bytes */ | |
553 | + rc = usb_get_string(dev, langid, index, buf, 255); | |
554 | + | |
555 | + /* If that failed try to read the descriptor length, then | |
556 | + * ask for just that many bytes */ | |
557 | + if (rc < 2) { | |
558 | + rc = usb_get_string(dev, langid, index, buf, 2); | |
559 | + if (rc == 2) | |
560 | + rc = usb_get_string(dev, langid, index, buf, buf[0]); | |
561 | + } | |
562 | + | |
563 | + if (rc >= 2) { | |
564 | + if (!buf[0] && !buf[1]) | |
565 | + usb_try_string_workarounds(buf, &rc); | |
566 | + | |
567 | + /* There might be extra junk at the end of the descriptor */ | |
568 | + if (buf[0] < rc) | |
569 | + rc = buf[0]; | |
570 | + | |
571 | + rc = rc - (rc & 1); /* force a multiple of two */ | |
572 | + } | |
573 | + | |
574 | + if (rc < 2) | |
575 | + rc = -1; | |
576 | + | |
577 | + return rc; | |
578 | +} | |
579 | + | |
580 | + | |
519 | 581 | /******************************************************************** |
520 | 582 | * usb_string: |
521 | 583 | * Get string index and translate it to ascii. |
... | ... | @@ -535,7 +597,7 @@ |
535 | 597 | |
536 | 598 | /* get langid for strings if it's not yet known */ |
537 | 599 | if (!dev->have_langid) { |
538 | - err = usb_get_string(dev, 0, 0, tbuf, 4); | |
600 | + err = usb_string_sub(dev, 0, 0, tbuf); | |
539 | 601 | if (err < 0) { |
540 | 602 | USB_PRINTF("error getting string descriptor 0 (error=%x)\n",dev->status); |
541 | 603 | return -1; |
542 | 604 | |
543 | 605 | |
... | ... | @@ -550,22 +612,11 @@ |
550 | 612 | dev->devnum, dev->string_langid); |
551 | 613 | } |
552 | 614 | } |
553 | - /* Just ask for a maximum length string and then take the length | |
554 | - * that was returned. */ | |
555 | - err = usb_get_string(dev, dev->string_langid, index, tbuf, 4); | |
556 | - if (err < 0) | |
557 | - return err; | |
558 | - u=tbuf[0]; | |
559 | - USB_PRINTF("Strn Len %d, index %d\n",u,index); | |
560 | 615 | |
561 | - if (u > USB_BUFSIZ) { | |
562 | - USB_PRINTF("usb_string: failed to get string - too long: %d\n", u); | |
563 | - return -1; | |
564 | - } | |
565 | - | |
566 | - err = usb_get_string(dev, dev->string_langid, index, tbuf, u); | |
616 | + err = usb_string_sub(dev, dev->string_langid, index, tbuf); | |
567 | 617 | if (err < 0) |
568 | 618 | return err; |
619 | + | |
569 | 620 | size--; /* leave room for trailing NULL char in output buffer */ |
570 | 621 | for (idx = 0, u = 2; u < err; u += 2) { |
571 | 622 | if (idx >= size) |
572 | 623 | |
... | ... | @@ -641,11 +692,66 @@ |
641 | 692 | /* We still haven't set the Address yet */ |
642 | 693 | addr = dev->devnum; |
643 | 694 | dev->devnum = 0; |
695 | + | |
696 | +#undef NEW_INIT_SEQ | |
697 | +#ifdef NEW_INIT_SEQ | |
698 | + /* this is a Windows scheme of initialization sequence, with double | |
699 | + * reset of the device. Some equipment is said to work only with such | |
700 | + * init sequence; this patch is based on the work by Alan Stern: | |
701 | + * http://sourceforge.net/mailarchive/forum.php?thread_id=5729457&forum_id=5398 | |
702 | + */ | |
703 | + int j; | |
704 | + struct usb_device_descriptor *desc; | |
705 | + int port = -1; | |
706 | + struct usb_device *parent = dev->parent; | |
707 | + unsigned short portstatus; | |
708 | + | |
709 | + /* send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is | |
710 | + * only 18 bytes long, this will terminate with a short packet. But if | |
711 | + * the maxpacket size is 8 or 16 the device may be waiting to transmit | |
712 | + * some more. */ | |
713 | + | |
714 | + desc = (struct usb_device_descriptor *)tmpbuf; | |
715 | + desc->bMaxPacketSize0 = 0; | |
716 | + for (j = 0; j < 3; ++j) { | |
717 | + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); | |
718 | + if (err < 0) { | |
719 | + USB_PRINTF("usb_new_device: 64 byte descr\n"); | |
720 | + break; | |
721 | + } | |
722 | + } | |
723 | + dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0; | |
724 | + | |
725 | + /* find the port number we're at */ | |
726 | + if (parent) { | |
727 | + | |
728 | + for (j = 0; j < parent->maxchild; j++) { | |
729 | + if (parent->children[j] == dev) { | |
730 | + port = j; | |
731 | + break; | |
732 | + } | |
733 | + } | |
734 | + if (port < 0) { | |
735 | + printf("usb_new_device: cannot locate device's port..\n"); | |
736 | + return 1; | |
737 | + } | |
738 | + | |
739 | + /* reset the port for the second time */ | |
740 | + err = hub_port_reset(dev->parent, port, &portstatus); | |
741 | + if (err < 0) { | |
742 | + printf("\n Couldn't reset port %i\n", port); | |
743 | + return 1; | |
744 | + } | |
745 | + } | |
746 | +#else | |
747 | + /* and this is the old and known way of initializing devices */ | |
644 | 748 | err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); |
645 | 749 | if (err < 8) { |
646 | 750 | printf("\n USB device not responding, giving up (status=%lX)\n",dev->status); |
647 | 751 | return 1; |
648 | 752 | } |
753 | +#endif | |
754 | + | |
649 | 755 | dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; |
650 | 756 | dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; |
651 | 757 | switch (dev->descriptor.bMaxPacketSize0) { |
... | ... | @@ -723,7 +829,7 @@ |
723 | 829 | /* device 0 is always present (root hub, so let it analyze) */ |
724 | 830 | dev=usb_alloc_new_device(); |
725 | 831 | usb_new_device(dev); |
726 | - printf("%d USB Devices found\n",dev_index); | |
832 | + printf("%d USB Device(s) found\n",dev_index); | |
727 | 833 | /* insert "driver" if possible */ |
728 | 834 | #ifdef CONFIG_USB_KEYBOARD |
729 | 835 | drv_usb_kbd_init(); |
730 | 836 | |
731 | 837 | |
732 | 838 | |
733 | 839 | |
... | ... | @@ -821,39 +927,15 @@ |
821 | 927 | |
822 | 928 | #define MAX_TRIES 5 |
823 | 929 | |
824 | -void usb_hub_port_connect_change(struct usb_device *dev, int port) | |
930 | +static int hub_port_reset(struct usb_device *dev, int port, | |
931 | + unsigned short *portstat) | |
825 | 932 | { |
826 | - struct usb_device *usb; | |
933 | + int tries; | |
827 | 934 | struct usb_port_status portsts; |
828 | 935 | unsigned short portstatus, portchange; |
829 | - int tries; | |
830 | 936 | |
831 | - /* Check status */ | |
832 | - if (usb_get_port_status(dev, port + 1, &portsts)<0) { | |
833 | - USB_HUB_PRINTF("get_port_status failed\n"); | |
834 | - return; | |
835 | - } | |
836 | 937 | |
837 | - portstatus = swap_16(portsts.wPortStatus); | |
838 | - portchange = swap_16(portsts.wPortChange); | |
839 | - USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus, portchange, | |
840 | - portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed"); | |
841 | - | |
842 | - /* Clear the connection change status */ | |
843 | - usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION); | |
844 | - | |
845 | - /* Disconnect any existing devices under this port */ | |
846 | - if (((!(portstatus & USB_PORT_STAT_CONNECTION)) && | |
847 | - (!(portstatus & USB_PORT_STAT_ENABLE)))|| (dev->children[port])) { | |
848 | - USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n"); | |
849 | - /* Return now if nothing is connected */ | |
850 | - if (!(portstatus & USB_PORT_STAT_CONNECTION)) | |
851 | - return; | |
852 | - } | |
853 | - wait_ms(200); | |
854 | - | |
855 | - /* Reset the port */ | |
856 | - | |
938 | + USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port); | |
857 | 939 | for(tries=0;tries<MAX_TRIES;tries++) { |
858 | 940 | |
859 | 941 | usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); |
... | ... | @@ -861,7 +943,7 @@ |
861 | 943 | |
862 | 944 | if (usb_get_port_status(dev, port + 1, &portsts)<0) { |
863 | 945 | USB_HUB_PRINTF("get_port_status failed status %lX\n",dev->status); |
864 | - return; | |
946 | + return -1; | |
865 | 947 | } |
866 | 948 | portstatus = swap_16(portsts.wPortStatus); |
867 | 949 | portchange = swap_16(portsts.wPortChange); |
868 | 950 | |
869 | 951 | |
... | ... | @@ -873,10 +955,12 @@ |
873 | 955 | (portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0); |
874 | 956 | if ((portchange & USB_PORT_STAT_C_CONNECTION) || |
875 | 957 | !(portstatus & USB_PORT_STAT_CONNECTION)) |
876 | - return; | |
958 | + return -1; | |
877 | 959 | |
878 | - if (portstatus & USB_PORT_STAT_ENABLE) | |
960 | + if (portstatus & USB_PORT_STAT_ENABLE) { | |
961 | + | |
879 | 962 | break; |
963 | + } | |
880 | 964 | |
881 | 965 | wait_ms(200); |
882 | 966 | } |
883 | 967 | |
... | ... | @@ -884,10 +968,52 @@ |
884 | 968 | if (tries==MAX_TRIES) { |
885 | 969 | USB_HUB_PRINTF("Cannot enable port %i after %i retries, disabling port.\n", port+1, MAX_TRIES); |
886 | 970 | USB_HUB_PRINTF("Maybe the USB cable is bad?\n"); |
887 | - return; | |
971 | + return -1; | |
888 | 972 | } |
889 | 973 | |
890 | 974 | usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET); |
975 | + *portstat = portstatus; | |
976 | + return 0; | |
977 | + | |
978 | +} | |
979 | + | |
980 | + | |
981 | +void usb_hub_port_connect_change(struct usb_device *dev, int port) | |
982 | +{ | |
983 | + struct usb_device *usb; | |
984 | + struct usb_port_status portsts; | |
985 | + unsigned short portstatus, portchange; | |
986 | + | |
987 | + /* Check status */ | |
988 | + if (usb_get_port_status(dev, port + 1, &portsts)<0) { | |
989 | + USB_HUB_PRINTF("get_port_status failed\n"); | |
990 | + return; | |
991 | + } | |
992 | + | |
993 | + portstatus = swap_16(portsts.wPortStatus); | |
994 | + portchange = swap_16(portsts.wPortChange); | |
995 | + USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus, portchange, | |
996 | + portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed"); | |
997 | + | |
998 | + /* Clear the connection change status */ | |
999 | + usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION); | |
1000 | + | |
1001 | + /* Disconnect any existing devices under this port */ | |
1002 | + if (((!(portstatus & USB_PORT_STAT_CONNECTION)) && | |
1003 | + (!(portstatus & USB_PORT_STAT_ENABLE)))|| (dev->children[port])) { | |
1004 | + USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n"); | |
1005 | + /* Return now if nothing is connected */ | |
1006 | + if (!(portstatus & USB_PORT_STAT_CONNECTION)) | |
1007 | + return; | |
1008 | + } | |
1009 | + wait_ms(200); | |
1010 | + | |
1011 | + /* Reset the port */ | |
1012 | + if (hub_port_reset(dev, port, &portstatus) < 0) { | |
1013 | + printf("cannot reset port %i!?\n", port + 1); | |
1014 | + return; | |
1015 | + } | |
1016 | + | |
891 | 1017 | wait_ms(200); |
892 | 1018 | |
893 | 1019 | /* Allocate a new device struct for it */ |
common/usb_storage.c
... | ... | @@ -121,7 +121,7 @@ |
121 | 121 | #define UMASS_BBB_CSW_SIZE 13 |
122 | 122 | |
123 | 123 | #define USB_MAX_STOR_DEV 5 |
124 | -static int usb_max_devs; /* number of highest available usb device */ | |
124 | +static int usb_max_devs = 0; /* number of highest available usb device */ | |
125 | 125 | |
126 | 126 | static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV]; |
127 | 127 | |
... | ... | @@ -177,7 +177,24 @@ |
177 | 177 | } |
178 | 178 | |
179 | 179 | /********************************************************************************* |
180 | - * (re)-scan the usb and reports device info | |
180 | + * show info on storage devices; 'usb start/init' must be invoked earlier | |
181 | + * as we only retrieve structures populated during devices initialization | |
182 | + */ | |
183 | +void usb_stor_info(void) | |
184 | +{ | |
185 | + int i; | |
186 | + | |
187 | + if (usb_max_devs > 0) | |
188 | + for (i = 0; i < usb_max_devs; i++) { | |
189 | + printf (" Device %d: ", i); | |
190 | + dev_print(&usb_dev_desc[i]); | |
191 | + } | |
192 | + else | |
193 | + printf("No storage devices, perhaps not 'usb start'ed..?\n"); | |
194 | +} | |
195 | + | |
196 | +/********************************************************************************* | |
197 | + * scan the usb and reports device info | |
181 | 198 | * to the user if mode = 1 |
182 | 199 | * returns current device or -1 if no |
183 | 200 | */ |
... | ... | @@ -190,7 +207,7 @@ |
190 | 207 | memset(usb_stor_buf, 0, sizeof(usb_stor_buf)); |
191 | 208 | |
192 | 209 | if(mode==1) { |
193 | - printf(" scanning bus for storage devices...\n"); | |
210 | + printf(" scanning bus for storage devices... "); | |
194 | 211 | } |
195 | 212 | usb_disable_asynch(1); /* asynch transfer not allowed */ |
196 | 213 | |
... | ... | @@ -202,6 +219,7 @@ |
202 | 219 | usb_dev_desc[i].part_type=PART_TYPE_UNKNOWN; |
203 | 220 | usb_dev_desc[i].block_read=usb_stor_read; |
204 | 221 | } |
222 | + | |
205 | 223 | usb_max_devs=0; |
206 | 224 | for(i=0;i<USB_MAX_DEVICE;i++) { |
207 | 225 | dev=usb_get_dev_index(i); /* get device */ |
208 | 226 | |
209 | 227 | |
210 | 228 | |
... | ... | @@ -211,21 +229,17 @@ |
211 | 229 | } |
212 | 230 | if(usb_storage_probe(dev,0,&usb_stor[usb_max_devs])) { /* ok, it is a storage devices */ |
213 | 231 | /* get info and fill it in */ |
214 | - | |
215 | - if(usb_stor_get_info(dev, &usb_stor[usb_max_devs], &usb_dev_desc[usb_max_devs])) { | |
216 | - if(mode==1) { | |
217 | - printf (" Device %d: ", usb_max_devs); | |
218 | - dev_print(&usb_dev_desc[usb_max_devs]); | |
219 | - } /* if mode */ | |
232 | + if(usb_stor_get_info(dev, &usb_stor[usb_max_devs], &usb_dev_desc[usb_max_devs])) | |
220 | 233 | usb_max_devs++; |
221 | - } /* if get info ok */ | |
222 | 234 | } /* if storage device */ |
223 | 235 | if(usb_max_devs==USB_MAX_STOR_DEV) { |
224 | 236 | printf("max USB Storage Device reached: %d stopping\n",usb_max_devs); |
225 | 237 | break; |
226 | 238 | } |
227 | 239 | } /* for */ |
240 | + | |
228 | 241 | usb_disable_asynch(0); /* asynch transfer allowed */ |
242 | + printf("%d Storage Device(s) found\n", usb_max_devs); | |
229 | 243 | if(usb_max_devs>0) |
230 | 244 | return 0; |
231 | 245 | else |
232 | 246 | |
... | ... | @@ -367,11 +381,13 @@ |
367 | 381 | result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), |
368 | 382 | US_BBB_RESET, USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
369 | 383 | 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT*5); |
384 | + | |
370 | 385 | if((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) |
371 | 386 | { |
372 | 387 | USB_STOR_PRINTF("RESET:stall\n"); |
373 | 388 | return -1; |
374 | 389 | } |
390 | + | |
375 | 391 | /* long wait for reset */ |
376 | 392 | wait_ms(150); |
377 | 393 | USB_STOR_PRINTF("BBB_reset result %d: status %X reset\n",result,us->pusb_dev->status); |
... | ... | @@ -640,7 +656,9 @@ |
640 | 656 | retry = 0; |
641 | 657 | again: |
642 | 658 | USB_STOR_PRINTF("STATUS phase\n"); |
643 | - result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE, &actlen, USB_CNTL_TIMEOUT*5); | |
659 | + result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE, | |
660 | + &actlen, USB_CNTL_TIMEOUT*5); | |
661 | + | |
644 | 662 | /* special handling of STALL in STATUS phase */ |
645 | 663 | if((result < 0) && (retry < 1) && (us->pusb_dev->status & USB_ST_STALLED)) { |
646 | 664 | USB_STOR_PRINTF("STATUS:stall\n"); |
... | ... | @@ -797,7 +815,7 @@ |
797 | 815 | static int usb_inquiry(ccb *srb,struct us_data *ss) |
798 | 816 | { |
799 | 817 | int retry,i; |
800 | - retry=3; | |
818 | + retry=5; | |
801 | 819 | do { |
802 | 820 | memset(&srb->cmd[0],0,12); |
803 | 821 | srb->cmd[0]=SCSI_INQUIRY; |
... | ... | @@ -838,7 +856,7 @@ |
838 | 856 | |
839 | 857 | static int usb_test_unit_ready(ccb *srb,struct us_data *ss) |
840 | 858 | { |
841 | - int retries=10; | |
859 | + int retries = 10; | |
842 | 860 | |
843 | 861 | do { |
844 | 862 | memset(&srb->cmd[0],0,12); |
... | ... | @@ -859,7 +877,7 @@ |
859 | 877 | static int usb_read_capacity(ccb *srb,struct us_data *ss) |
860 | 878 | { |
861 | 879 | int retry; |
862 | - retry=2; /* retries */ | |
880 | + retry = 3; /* retries */ | |
863 | 881 | do { |
864 | 882 | memset(&srb->cmd[0],0,12); |
865 | 883 | srb->cmd[0]=SCSI_RD_CAPAC; |
... | ... | @@ -972,9 +990,6 @@ |
972 | 990 | int protocol = 0; |
973 | 991 | int subclass = 0; |
974 | 992 | |
975 | - | |
976 | - memset(ss, 0, sizeof(struct us_data)); | |
977 | - | |
978 | 993 | /* let's examine the device now */ |
979 | 994 | iface = &dev->config.if_desc[ifnum]; |
980 | 995 | |
... | ... | @@ -996,6 +1011,8 @@ |
996 | 1011 | return 0; |
997 | 1012 | } |
998 | 1013 | |
1014 | + memset(ss, 0, sizeof(struct us_data)); | |
1015 | + | |
999 | 1016 | /* At this point, we know we've got a live one */ |
1000 | 1017 | USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n"); |
1001 | 1018 | |
1002 | 1019 | |
1003 | 1020 | |
1004 | 1021 | |
1005 | 1022 | |
1006 | 1023 | |
1007 | 1024 | |
1008 | 1025 | |
1009 | 1026 | |
1010 | 1027 | |
1011 | 1028 | |
... | ... | @@ -1103,50 +1120,62 @@ |
1103 | 1120 | unsigned char perq,modi; |
1104 | 1121 | unsigned long cap[2]; |
1105 | 1122 | unsigned long *capacity,*blksz; |
1106 | - ccb *pccb=&usb_ccb; | |
1123 | + ccb *pccb = &usb_ccb; | |
1107 | 1124 | |
1108 | - /* For some mysterious reason the 256MB flash disk of Ours Technology, Inc | |
1109 | - * doesn't survive this reset */ | |
1110 | - if (dev->descriptor.idVendor != 0xea0 || dev->descriptor.idProduct != 0x6828) | |
1125 | + /* for some reasons a couple of devices would not survive this reset */ | |
1126 | + if ( | |
1127 | + /* Sony USM256E */ | |
1128 | + (dev->descriptor.idVendor == 0x054c && | |
1129 | + dev->descriptor.idProduct == 0x019e) | |
1130 | + | |
1131 | + || | |
1132 | + /* USB007 Mini-USB2 Flash Drive */ | |
1133 | + (dev->descriptor.idVendor == 0x066f && | |
1134 | + dev->descriptor.idProduct == 0x2010) | |
1135 | + ) | |
1136 | + USB_STOR_PRINTF("usb_stor_get_info: skipping RESET..\n"); | |
1137 | + else | |
1111 | 1138 | ss->transport_reset(ss); |
1112 | - pccb->pdata=usb_stor_buf; | |
1113 | 1139 | |
1114 | - dev_desc->target=dev->devnum; | |
1115 | - pccb->lun=dev_desc->lun; | |
1140 | + pccb->pdata = usb_stor_buf; | |
1141 | + | |
1142 | + dev_desc->target = dev->devnum; | |
1143 | + pccb->lun = dev_desc->lun; | |
1116 | 1144 | USB_STOR_PRINTF(" address %d\n",dev_desc->target); |
1117 | 1145 | |
1118 | 1146 | if(usb_inquiry(pccb,ss)) |
1119 | 1147 | return -1; |
1120 | - perq=usb_stor_buf[0]; | |
1121 | - modi=usb_stor_buf[1]; | |
1122 | - if((perq & 0x1f)==0x1f) { | |
1148 | + | |
1149 | + perq = usb_stor_buf[0]; | |
1150 | + modi = usb_stor_buf[1]; | |
1151 | + if((perq & 0x1f) == 0x1f) { | |
1123 | 1152 | return 0; /* skip unknown devices */ |
1124 | 1153 | } |
1125 | - if((modi&0x80)==0x80) {/* drive is removable */ | |
1126 | - dev_desc->removable=1; | |
1154 | + if((modi&0x80) == 0x80) {/* drive is removable */ | |
1155 | + dev_desc->removable = 1; | |
1127 | 1156 | } |
1128 | 1157 | memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8); |
1129 | 1158 | memcpy(&dev_desc->product[0], &usb_stor_buf[16], 16); |
1130 | 1159 | memcpy(&dev_desc->revision[0], &usb_stor_buf[32], 4); |
1131 | - dev_desc->vendor[8]=0; | |
1132 | - dev_desc->product[16]=0; | |
1133 | - dev_desc->revision[4]=0; | |
1160 | + dev_desc->vendor[8] = 0; | |
1161 | + dev_desc->product[16] = 0; | |
1162 | + dev_desc->revision[4] = 0; | |
1134 | 1163 | USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n",usb_stor_buf[2],usb_stor_buf[3]); |
1135 | 1164 | if(usb_test_unit_ready(pccb,ss)) { |
1136 | 1165 | printf("Device NOT ready\n Request Sense returned %02X %02X %02X\n",pccb->sense_buf[2],pccb->sense_buf[12],pccb->sense_buf[13]); |
1137 | - if(dev_desc->removable==1) { | |
1138 | - dev_desc->type=perq; | |
1166 | + if(dev_desc->removable == 1) { | |
1167 | + dev_desc->type = perq; | |
1139 | 1168 | return 1; |
1140 | 1169 | } |
1141 | 1170 | else |
1142 | 1171 | return 0; |
1143 | 1172 | } |
1144 | - pccb->pdata=(unsigned char *)&cap[0]; | |
1173 | + pccb->pdata = (unsigned char *)&cap[0]; | |
1145 | 1174 | memset(pccb->pdata,0,8); |
1146 | - if(usb_read_capacity(pccb,ss)!=0) { | |
1175 | + if(usb_read_capacity(pccb,ss) != 0) { | |
1147 | 1176 | printf("READ_CAP ERROR\n"); |
1148 | - cap[0]=2880; | |
1149 | - cap[1]=0x200; | |
1177 | + cap[0] = 2880; | |
1178 | + cap[1] = 0x200; | |
1150 | 1179 | } |
1151 | 1180 | USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n",cap[0],cap[1]); |
1152 | 1181 | #if 0 |
1153 | 1182 | |
... | ... | @@ -1166,13 +1195,13 @@ |
1166 | 1195 | (((unsigned long)(cap[1]) & (unsigned long)0xff000000UL) >> 24) )); |
1167 | 1196 | #endif |
1168 | 1197 | /* this assumes bigendian! */ |
1169 | - cap[0]+=1; | |
1170 | - capacity=&cap[0]; | |
1171 | - blksz=&cap[1]; | |
1198 | + cap[0] += 1; | |
1199 | + capacity = &cap[0]; | |
1200 | + blksz = &cap[1]; | |
1172 | 1201 | USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",*capacity,*blksz); |
1173 | - dev_desc->lba=*capacity; | |
1174 | - dev_desc->blksz=*blksz; | |
1175 | - dev_desc->type=perq; | |
1202 | + dev_desc->lba = *capacity; | |
1203 | + dev_desc->blksz = *blksz; | |
1204 | + dev_desc->type = perq; | |
1176 | 1205 | USB_STOR_PRINTF(" address %d\n",dev_desc->target); |
1177 | 1206 | USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type); |
1178 | 1207 |
cpu/arm920t/s3c24x0/usb_ohci.c
... | ... | @@ -94,6 +94,8 @@ |
94 | 94 | int got_rhsc; |
95 | 95 | /* device which was disconnected */ |
96 | 96 | struct usb_device *devgone; |
97 | +/* flag guarding URB transation */ | |
98 | +int urb_finished = 0; | |
97 | 99 | |
98 | 100 | /*-------------------------------------------------------------------------*/ |
99 | 101 | |
... | ... | @@ -398,6 +400,16 @@ |
398 | 400 | return -1; |
399 | 401 | } |
400 | 402 | |
403 | + /* if we have an unfinished URB from previous transaction let's | |
404 | + * fail and scream as quickly as possible so as not to corrupt | |
405 | + * further communication */ | |
406 | + if (!urb_finished) { | |
407 | + err("sohci_submit_job: URB NOT FINISHED"); | |
408 | + return -1; | |
409 | + } | |
410 | + /* we're about to begin a new transaction here so mark the URB unfinished */ | |
411 | + urb_finished = 0; | |
412 | + | |
401 | 413 | /* every endpoint has a ed, locate and fill it */ |
402 | 414 | if (!(ed = ep_add_ed (dev, pipe))) { |
403 | 415 | err("sohci_submit_job: ENOMEM"); |
... | ... | @@ -658,7 +670,6 @@ |
658 | 670 | else |
659 | 671 | td->hwBE = 0; |
660 | 672 | td->hwNextTD = m32_swap (td_pt); |
661 | - td->hwPSW [0] = m16_swap (((__u32)data & 0x0FFF) | 0xE000); | |
662 | 673 | |
663 | 674 | /* append to queue */ |
664 | 675 | td->ed->hwTailP = td->hwNextTD; |
... | ... | @@ -793,6 +804,7 @@ |
793 | 804 | td_rev = td_list; |
794 | 805 | td_list_hc = m32_swap (td_list->hwNextTD) & 0xfffffff0; |
795 | 806 | } |
807 | + | |
796 | 808 | return td_list; |
797 | 809 | } |
798 | 810 | |
... | ... | @@ -826,6 +838,17 @@ |
826 | 838 | stat = cc_to_error[cc]; |
827 | 839 | } |
828 | 840 | |
841 | + /* see if this done list makes for all TD's of current URB, | |
842 | + * and mark the URB finished if so */ | |
843 | + if (++(lurb_priv->td_cnt) == lurb_priv->length) { | |
844 | + if ((ed->state & (ED_OPER | ED_UNLINK))) | |
845 | + urb_finished = 1; | |
846 | + else | |
847 | + dbg("dl_done_list: strange.., ED state %x, ed->state\n"); | |
848 | + } else | |
849 | + dbg("dl_done_list: processing TD %x, len %x\n", lurb_priv->td_cnt, | |
850 | + lurb_priv->length); | |
851 | + | |
829 | 852 | if (ed->state != ED_NEW) { |
830 | 853 | edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0; |
831 | 854 | edTailP = m32_swap (ed->hwTailP); |
... | ... | @@ -1197,6 +1220,8 @@ |
1197 | 1220 | return stat; |
1198 | 1221 | } |
1199 | 1222 | |
1223 | + | |
1224 | + | |
1200 | 1225 | /*-------------------------------------------------------------------------*/ |
1201 | 1226 | |
1202 | 1227 | /* common code for handling submit messages - used for all but root hub */ |
1203 | 1228 | |
1204 | 1229 | |
1205 | 1230 | |
1206 | 1231 | |
1207 | 1232 | |
1208 | 1233 | |
... | ... | @@ -1245,22 +1270,41 @@ |
1245 | 1270 | for (;;) { |
1246 | 1271 | /* check whether the controller is done */ |
1247 | 1272 | stat = hc_interrupt(); |
1273 | + | |
1248 | 1274 | if (stat < 0) { |
1249 | 1275 | stat = USB_ST_CRC_ERR; |
1250 | 1276 | break; |
1251 | 1277 | } |
1252 | - if (stat >= 0 && stat != 0xff) { | |
1278 | + | |
1279 | + /* NOTE: since we are not interrupt driven in U-Boot and always | |
1280 | + * handle only one URB at a time, we cannot assume the | |
1281 | + * transaction finished on the first successful return from | |
1282 | + * hc_interrupt().. unless the flag for current URB is set, | |
1283 | + * meaning that all TD's to/from device got actually | |
1284 | + * transferred and processed. If the current URB is not | |
1285 | + * finished we need to re-iterate this loop so as | |
1286 | + * hc_interrupt() gets called again as there needs to be some | |
1287 | + * more TD's to process still */ | |
1288 | + if ((stat >= 0) && (stat != 0xff) && (urb_finished)) { | |
1253 | 1289 | /* 0xff is returned for an SF-interrupt */ |
1254 | 1290 | break; |
1255 | 1291 | } |
1292 | + | |
1256 | 1293 | if (--timeout) { |
1257 | 1294 | wait_ms(1); |
1295 | + if (!urb_finished) | |
1296 | + dbg("\%"); | |
1297 | + | |
1258 | 1298 | } else { |
1259 | 1299 | err("CTL:TIMEOUT "); |
1300 | + dbg("submit_common_msg: TO status %x\n", stat); | |
1260 | 1301 | stat = USB_ST_CRC_ERR; |
1302 | + urb_finished = 1; | |
1261 | 1303 | break; |
1262 | 1304 | } |
1263 | 1305 | } |
1306 | + | |
1307 | +#if 0 | |
1264 | 1308 | /* we got an Root Hub Status Change interrupt */ |
1265 | 1309 | if (got_rhsc) { |
1266 | 1310 | #ifdef DEBUG |
... | ... | @@ -1282,6 +1326,7 @@ |
1282 | 1326 | devgone = dev; |
1283 | 1327 | } |
1284 | 1328 | } |
1329 | +#endif | |
1285 | 1330 | |
1286 | 1331 | dev->status = stat; |
1287 | 1332 | dev->act_len = transfer_len; |
1288 | 1333 | |
1289 | 1334 | |
... | ... | @@ -1457,16 +1502,26 @@ |
1457 | 1502 | int ints; |
1458 | 1503 | int stat = -1; |
1459 | 1504 | |
1460 | - if ((ohci->hcca->done_head != 0) && !(m32_swap (ohci->hcca->done_head) & 0x01)) { | |
1505 | + if ((ohci->hcca->done_head != 0) && | |
1506 | + !(m32_swap (ohci->hcca->done_head) & 0x01)) { | |
1507 | + | |
1461 | 1508 | ints = OHCI_INTR_WDH; |
1462 | - } else { | |
1463 | - ints = readl (®s->intrstatus); | |
1509 | + | |
1510 | + } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { | |
1511 | + ohci->disabled++; | |
1512 | + err ("%s device removed!", ohci->slot_name); | |
1513 | + return -1; | |
1514 | + | |
1515 | + } else if ((ints &= readl (®s->intrenable)) == 0) { | |
1516 | + dbg("hc_interrupt: returning..\n"); | |
1517 | + return 0xff; | |
1464 | 1518 | } |
1465 | 1519 | |
1466 | 1520 | /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */ |
1467 | 1521 | |
1468 | 1522 | if (ints & OHCI_INTR_RHSC) { |
1469 | 1523 | got_rhsc = 1; |
1524 | + stat = 0xff; | |
1470 | 1525 | } |
1471 | 1526 | |
1472 | 1527 | if (ints & OHCI_INTR_UE) { |
... | ... | @@ -1490,6 +1545,7 @@ |
1490 | 1545 | |
1491 | 1546 | if (ints & OHCI_INTR_WDH) { |
1492 | 1547 | wait_ms(1); |
1548 | + | |
1493 | 1549 | writel (OHCI_INTR_WDH, ®s->intrdisable); |
1494 | 1550 | stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci)); |
1495 | 1551 | writel (OHCI_INTR_WDH, ®s->intrenable); |
... | ... | @@ -1610,6 +1666,8 @@ |
1610 | 1666 | wait_ms(1); |
1611 | 1667 | #endif |
1612 | 1668 | ohci_inited = 1; |
1669 | + urb_finished = 1; | |
1670 | + | |
1613 | 1671 | return 0; |
1614 | 1672 | } |
1615 | 1673 |
cpu/arm920t/s3c24x0/usb_ohci.h
... | ... | @@ -30,7 +30,6 @@ |
30 | 30 | }; |
31 | 31 | |
32 | 32 | /* ED States */ |
33 | - | |
34 | 33 | #define ED_NEW 0x00 |
35 | 34 | #define ED_UNLINK 0x01 |
36 | 35 | #define ED_OPER 0x02 |
... | ... | @@ -104,7 +103,6 @@ |
104 | 103 | __u32 hwNextTD; /* Next TD Pointer */ |
105 | 104 | __u32 hwBE; /* Memory Buffer End Pointer */ |
106 | 105 | |
107 | - __u16 hwPSW[MAXPSW]; | |
108 | 106 | __u8 unused; |
109 | 107 | __u8 index; |
110 | 108 | struct ed *ed; |
cpu/mpc5xxx/usb_ohci.c
... | ... | @@ -98,6 +98,8 @@ |
98 | 98 | int got_rhsc; |
99 | 99 | /* device which was disconnected */ |
100 | 100 | struct usb_device *devgone; |
101 | +/* flag guarding URB transation */ | |
102 | +int urb_finished = 0; | |
101 | 103 | |
102 | 104 | /*-------------------------------------------------------------------------*/ |
103 | 105 | |
... | ... | @@ -402,6 +404,16 @@ |
402 | 404 | return -1; |
403 | 405 | } |
404 | 406 | |
407 | + /* if we have an unfinished URB from previous transaction let's | |
408 | + * fail and scream as quickly as possible so as not to corrupt | |
409 | + * further communication */ | |
410 | + if (!urb_finished) { | |
411 | + err("sohci_submit_job: URB NOT FINISHED"); | |
412 | + return -1; | |
413 | + } | |
414 | + /* we're about to begin a new transaction here so mark the URB unfinished */ | |
415 | + urb_finished = 0; | |
416 | + | |
405 | 417 | /* every endpoint has a ed, locate and fill it */ |
406 | 418 | if (!(ed = ep_add_ed (dev, pipe))) { |
407 | 419 | err("sohci_submit_job: ENOMEM"); |
... | ... | @@ -664,7 +676,6 @@ |
664 | 676 | else |
665 | 677 | td->hwBE = 0; |
666 | 678 | td->hwNextTD = ohci_cpu_to_le32 ((unsigned long)td_pt); |
667 | - td->hwPSW [0] = ohci_cpu_to_le16 (((__u32)data & 0x0FFF) | 0xE000); | |
668 | 679 | |
669 | 680 | /* append to queue */ |
670 | 681 | td->ed->hwTailP = td->hwNextTD; |
... | ... | @@ -673,7 +684,6 @@ |
673 | 684 | /*-------------------------------------------------------------------------*/ |
674 | 685 | |
675 | 686 | /* prepare all TDs of a transfer */ |
676 | - | |
677 | 687 | static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer, |
678 | 688 | int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval) |
679 | 689 | { |
... | ... | @@ -813,7 +823,7 @@ |
813 | 823 | td_t *td_list_next = NULL; |
814 | 824 | ed_t *ed; |
815 | 825 | int cc = 0; |
816 | - int stat = 0xff; | |
826 | + int stat = 0; | |
817 | 827 | /* urb_t *urb; */ |
818 | 828 | urb_priv_t *lurb_priv; |
819 | 829 | __u32 tdINFO, edHeadP, edTailP; |
... | ... | @@ -835,6 +845,7 @@ |
835 | 845 | && (lurb_priv->state != URB_DEL)) { |
836 | 846 | dbg("ConditionCode %#x", cc); |
837 | 847 | stat = cc_to_error[cc]; |
848 | + urb_finished = 1; | |
838 | 849 | } |
839 | 850 | } |
840 | 851 | |
841 | 852 | |
842 | 853 | |
843 | 854 | |
844 | 855 | |
845 | 856 | |
... | ... | @@ -1250,18 +1261,35 @@ |
1250 | 1261 | stat = USB_ST_CRC_ERR; |
1251 | 1262 | break; |
1252 | 1263 | } |
1253 | - if (stat >= 0 && stat < 0xff) { | |
1264 | + | |
1265 | + /* NOTE: since we are not interrupt driven in U-Boot and always | |
1266 | + * handle only one URB at a time, we cannot assume the | |
1267 | + * transaction finished on the first successful return from | |
1268 | + * hc_interrupt().. unless the flag for current URB is set, | |
1269 | + * meaning that all TD's to/from device got actually | |
1270 | + * transferred and processed. If the current URB is not | |
1271 | + * finished we need to re-iterate this loop so as | |
1272 | + * hc_interrupt() gets called again as there needs to be some | |
1273 | + * more TD's to process still */ | |
1274 | + if ((stat >= 0) && (stat != 0xff) && (urb_finished)) { | |
1254 | 1275 | /* 0xff is returned for an SF-interrupt */ |
1255 | 1276 | break; |
1256 | 1277 | } |
1278 | + | |
1257 | 1279 | if (--timeout) { |
1258 | 1280 | wait_ms(1); |
1281 | + if (!urb_finished) | |
1282 | + dbg("\%"); | |
1283 | + | |
1259 | 1284 | } else { |
1260 | 1285 | err("CTL:TIMEOUT "); |
1286 | + dbg("submit_common_msg: TO status %x\n", stat); | |
1261 | 1287 | stat = USB_ST_CRC_ERR; |
1288 | + urb_finished = 1; | |
1262 | 1289 | break; |
1263 | 1290 | } |
1264 | 1291 | } |
1292 | +#if 0 | |
1265 | 1293 | /* we got an Root Hub Status Change interrupt */ |
1266 | 1294 | if (got_rhsc) { |
1267 | 1295 | #ifdef DEBUG |
... | ... | @@ -1283,6 +1311,7 @@ |
1283 | 1311 | devgone = dev; |
1284 | 1312 | } |
1285 | 1313 | } |
1314 | +#endif | |
1286 | 1315 | |
1287 | 1316 | dev->status = stat; |
1288 | 1317 | dev->act_len = transfer_len; |
1289 | 1318 | |
1290 | 1319 | |
... | ... | @@ -1454,17 +1483,27 @@ |
1454 | 1483 | struct ohci_regs *regs = ohci->regs; |
1455 | 1484 | int ints; |
1456 | 1485 | int stat = -1; |
1486 | + | |
1487 | + if ((ohci->hcca->done_head != 0) && | |
1488 | + !(ohci_cpu_to_le32(ohci->hcca->done_head) & 0x01)) { | |
1457 | 1489 | |
1458 | - if ((ohci->hcca->done_head != 0) && !(ohci_cpu_to_le32 (ohci->hcca->done_head) & 0x01)) { | |
1459 | - ints = OHCI_INTR_WDH; | |
1460 | - } else { | |
1461 | - ints = readl (®s->intrstatus); | |
1490 | + ints = OHCI_INTR_WDH; | |
1491 | + | |
1492 | + } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { | |
1493 | + ohci->disabled++; | |
1494 | + err ("%s device removed!", ohci->slot_name); | |
1495 | + return -1; | |
1496 | + | |
1497 | + } else if ((ints &= readl (®s->intrenable)) == 0) { | |
1498 | + dbg("hc_interrupt: returning..\n"); | |
1499 | + return 0xff; | |
1462 | 1500 | } |
1463 | 1501 | |
1464 | 1502 | /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */ |
1465 | 1503 | |
1466 | 1504 | if (ints & OHCI_INTR_RHSC) { |
1467 | 1505 | got_rhsc = 1; |
1506 | + stat = 0xff; | |
1468 | 1507 | } |
1469 | 1508 | |
1470 | 1509 | if (ints & OHCI_INTR_UE) { |
... | ... | @@ -1499,6 +1538,7 @@ |
1499 | 1538 | /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ |
1500 | 1539 | if (ints & OHCI_INTR_SF) { |
1501 | 1540 | unsigned int frame = ohci_cpu_to_le16 (ohci->hcca->frame_no) & 1; |
1541 | + wait_ms(1); | |
1502 | 1542 | writel (OHCI_INTR_SF, ®s->intrdisable); |
1503 | 1543 | if (ohci->ed_rm_list[frame] != NULL) |
1504 | 1544 | writel (OHCI_INTR_SF, ®s->intrenable); |
... | ... | @@ -1589,6 +1629,8 @@ |
1589 | 1629 | ohci_dump (&gohci, 1); |
1590 | 1630 | #endif |
1591 | 1631 | ohci_inited = 1; |
1632 | + urb_finished = 1; | |
1633 | + | |
1592 | 1634 | return 0; |
1593 | 1635 | } |
1594 | 1636 |
cpu/mpc5xxx/usb_ohci.h
include/usb.h
... | ... | @@ -41,7 +41,6 @@ |
41 | 41 | |
42 | 42 | #define USB_CNTL_TIMEOUT 100 /* 100ms timeout */ |
43 | 43 | |
44 | - | |
45 | 44 | /* String descriptor */ |
46 | 45 | struct usb_string_descriptor { |
47 | 46 | unsigned char bLength; |
... | ... | @@ -191,6 +190,7 @@ |
191 | 190 | #define USB_MAX_STOR_DEV 5 |
192 | 191 | block_dev_desc_t *usb_stor_get_dev(int index); |
193 | 192 | int usb_stor_scan(int mode); |
193 | +void usb_stor_info(void); | |
194 | 194 | |
195 | 195 | #endif |
196 | 196 |
include/usb_defs.h
... | ... | @@ -26,20 +26,6 @@ |
26 | 26 | #ifndef _USB_DEFS_H_ |
27 | 27 | #define _USB_DEFS_H_ |
28 | 28 | |
29 | - | |
30 | -/* Everything is aribtrary */ | |
31 | -#define USB_ALTSETTINGALLOC 4 | |
32 | -#define USB_MAXALTSETTING 128 /* Hard limit */ | |
33 | - | |
34 | -#define USB_MAX_DEVICE 32 | |
35 | -#define USB_MAXCONFIG 8 | |
36 | -#define USB_MAXINTERFACES 8 | |
37 | -#define USB_MAXENDPOINTS 16 | |
38 | -#define USB_MAXCHILDREN 8 /* This is arbitrary */ | |
39 | -#define USB_MAX_HUB 16 | |
40 | - | |
41 | -#define USB_CNTL_TIMEOUT 100 /* 100ms timeout */ | |
42 | - | |
43 | 29 | /* USB constants */ |
44 | 30 | |
45 | 31 | /* Device and/or Interface Class codes */ |