Rev 3626 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3626 | Rev 3725 | ||
---|---|---|---|
Line 79... | Line 79... | ||
79 | ; * The hardware part consists of first 52 bytes and corresponds to |
79 | ; * The hardware part consists of first 52 bytes and corresponds to |
80 | ; the Queue Element Transfer Descriptor from EHCI specification. |
80 | ; the Queue Element Transfer Descriptor from EHCI specification. |
81 | ; * The hardware requires 32-bytes alignment of the hardware part, so |
81 | ; * The hardware requires 32-bytes alignment of the hardware part, so |
82 | ; the entire descriptor must be 32-bytes aligned. Since the allocator |
82 | ; the entire descriptor must be 32-bytes aligned. Since the allocator |
83 | ; (usb_allocate_common) allocates memory sequentially from page start |
83 | ; (usb_allocate_common) allocates memory sequentially from page start |
84 | ; (aligned on 0x1000 bytes), size of the structure must be divisible by 32. |
84 | ; (aligned on 0x1000 bytes), block size for the allocator must be divisible |
- | 85 | ; by 32; ehci_alloc_td ensures this. |
|
85 | ; * The hardware also requires that the hardware part must not cross page |
86 | ; * The hardware also requires that the hardware part must not cross page |
86 | ; boundary; the allocator satisfies this automatically. |
87 | ; boundary; the allocator satisfies this automatically. |
87 | struct ehci_gtd ehci_hardware_td |
88 | struct ehci_gtd ehci_hardware_td |
88 | Flags dd ? |
89 | Flags dd ? |
89 | ; Copy of flags from the call to usb_*_transfer_async. |
90 | ; Copy of flags from the call to usb_*_transfer_async. |
90 | SoftwarePart rd sizeof.usb_gtd/4 |
- | |
91 | ; Software part, common for all controllers. |
- | |
92 | rd 3 ; padding |
- | |
93 | ends |
91 | ends |
Line 94... | Line -... | ||
94 | - | ||
95 | if sizeof.ehci_gtd mod 32 |
- | |
96 | .err ehci_gtd must be 32-bytes aligned |
- | |
97 | end if |
- | |
98 | 92 | ||
99 | ; EHCI-specific part of a pipe descriptor. |
93 | ; EHCI-specific part of a pipe descriptor. |
100 | ; * This structure corresponds to the Queue Head from the EHCI specification. |
94 | ; * This structure corresponds to the Queue Head from the EHCI specification. |
101 | ; * The hardware requires 32-bytes alignment of the hardware part. |
95 | ; * The hardware requires 32-bytes alignment of the hardware part. |
102 | ; Since the allocator (usb_allocate_common) allocates memory sequentially |
96 | ; Since the allocator (usb_allocate_common) allocates memory sequentially |
103 | ; from page start (aligned on 0x1000 bytes), size of the structure must be |
97 | ; from page start (aligned on 0x1000 bytes), block size for the allocator |
104 | ; divisible by 32. |
98 | ; must be divisible by 32; ehci_alloc_pipe ensures this. |
105 | ; * The hardware requires also that the hardware part must not cross page |
99 | ; * The hardware requires also that the hardware part must not cross page |
106 | ; boundary; the allocator satisfies this automatically. |
100 | ; boundary; the allocator satisfies this automatically. |
107 | struct ehci_pipe |
101 | struct ehci_pipe |
108 | NextQH dd ? |
102 | NextQH dd ? |
Line 152... | Line 146... | ||
152 | ; Working area for the current TD, if there is any. |
146 | ; Working area for the current TD, if there is any. |
153 | ; When TD is retired, it is written to that TD and Overlay is loaded |
147 | ; When TD is retired, it is written to that TD and Overlay is loaded |
154 | ; from the new TD, if any. |
148 | ; from the new TD, if any. |
155 | BaseList dd ? |
149 | BaseList dd ? |
156 | ; Pointer to head of the corresponding pipe list. |
150 | ; Pointer to head of the corresponding pipe list. |
157 | SoftwarePart rd sizeof.usb_pipe/4 |
- | |
158 | ; Software part, common for all controllers. |
- | |
159 | rd 2 ; padding |
- | |
160 | ends |
151 | ends |
Line 161... | Line -... | ||
161 | - | ||
162 | if sizeof.ehci_pipe mod 32 |
- | |
163 | .err ehci_pipe must be 32-bytes aligned |
- | |
164 | end if |
- | |
165 | 152 | ||
166 | ; This structure describes the static head of every list of pipes. |
153 | ; This structure describes the static head of every list of pipes. |
167 | ; The hardware requires 32-bytes alignment of this structure. |
154 | ; The hardware requires 32-bytes alignment of this structure. |
168 | ; All instances of this structure are located sequentially in ehci_controller, |
155 | ; All instances of this structure are located sequentially in ehci_controller, |
169 | ; ehci_controller is page-aligned, so it is sufficient to make this structure |
156 | ; ehci_controller is page-aligned, so it is sufficient to make this structure |
Line 762... | Line 749... | ||
762 | 749 | ||
763 | ; This procedure is called from usb_set_address_callback |
750 | ; This procedure is called from usb_set_address_callback |
764 | ; and stores USB device address in the ehci_pipe structure. |
751 | ; and stores USB device address in the ehci_pipe structure. |
765 | ; in: esi -> usb_controller, ebx -> usb_pipe, cl = address |
752 | ; in: esi -> usb_controller, ebx -> usb_pipe, cl = address |
766 | proc ehci_set_device_address |
753 | proc ehci_set_device_address |
767 | mov byte [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart], cl |
754 | mov byte [ebx+ehci_pipe.Token-sizeof.ehci_pipe], cl |
768 | call usb_subscribe_control |
755 | call usb_subscribe_control |
769 | ret |
756 | ret |
Line 770... | Line 757... | ||
770 | endp |
757 | endp |
771 | 758 | ||
772 | ; This procedure returns USB device address from the ehci_pipe structure. |
759 | ; This procedure returns USB device address from the ehci_pipe structure. |
773 | ; in: esi -> usb_controller, ebx -> usb_pipe |
760 | ; in: esi -> usb_controller, ebx -> usb_pipe |
774 | ; out: eax = endpoint address |
761 | ; out: eax = endpoint address |
775 | proc ehci_get_device_address |
762 | proc ehci_get_device_address |
776 | mov eax, [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart] |
763 | mov eax, [ebx+ehci_pipe.Token-sizeof.ehci_pipe] |
777 | and eax, 7Fh |
764 | and eax, 7Fh |
Line 778... | Line 765... | ||
778 | ret |
765 | ret |
Line 791... | Line 778... | ||
791 | ; This procedure is called from usb_get_descr8_callback when |
778 | ; This procedure is called from usb_get_descr8_callback when |
792 | ; the packet size for zero endpoint becomes known and |
779 | ; the packet size for zero endpoint becomes known and |
793 | ; stores the packet size in ehci_pipe structure. |
780 | ; stores the packet size in ehci_pipe structure. |
794 | ; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size |
781 | ; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size |
795 | proc ehci_set_endpoint_packet_size |
782 | proc ehci_set_endpoint_packet_size |
796 | mov eax, [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart] |
783 | mov eax, [ebx+ehci_pipe.Token-sizeof.ehci_pipe] |
797 | and eax, not (0x7FF shl 16) |
784 | and eax, not (0x7FF shl 16) |
798 | shl ecx, 16 |
785 | shl ecx, 16 |
799 | or eax, ecx |
786 | or eax, ecx |
800 | mov [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart], eax |
787 | mov [ebx+ehci_pipe.Token-sizeof.ehci_pipe], eax |
801 | ; Wait until hardware cache is evicted. |
788 | ; Wait until hardware cache is evicted. |
802 | call usb_subscribe_control |
789 | call usb_subscribe_control |
803 | ret |
790 | ret |
804 | endp |
791 | endp |
Line 816... | Line 803... | ||
816 | ; Both hardware+software parts must be allocated, returns pointer to usb_pipe |
803 | ; Both hardware+software parts must be allocated, returns pointer to usb_pipe |
817 | ; (software part). |
804 | ; (software part). |
818 | proc ehci_alloc_pipe |
805 | proc ehci_alloc_pipe |
819 | push ebx |
806 | push ebx |
820 | mov ebx, ehci_ep_mutex |
807 | mov ebx, ehci_ep_mutex |
821 | stdcall usb_allocate_common, sizeof.ehci_pipe |
808 | stdcall usb_allocate_common, (sizeof.ehci_pipe + sizeof.usb_pipe + 1Fh) and not 1Fh |
822 | test eax, eax |
809 | test eax, eax |
823 | jz @f |
810 | jz @f |
824 | add eax, ehci_pipe.SoftwarePart |
811 | add eax, sizeof.ehci_pipe |
825 | @@: |
812 | @@: |
826 | pop ebx |
813 | pop ebx |
827 | ret |
814 | ret |
828 | endp |
815 | endp |
Line 832... | Line 819... | ||
832 | proc ehci_free_pipe |
819 | proc ehci_free_pipe |
833 | virtual at esp |
820 | virtual at esp |
834 | dd ? ; return address |
821 | dd ? ; return address |
835 | .ptr dd ? |
822 | .ptr dd ? |
836 | end virtual |
823 | end virtual |
837 | sub [.ptr], ehci_pipe.SoftwarePart |
824 | sub [.ptr], sizeof.ehci_pipe |
838 | jmp usb_free_common |
825 | jmp usb_free_common |
839 | endp |
826 | endp |
Line 840... | Line 827... | ||
840 | 827 | ||
841 | ; This procedure is called from API usb_open_pipe and processes |
828 | ; This procedure is called from API usb_open_pipe and processes |
Line 851... | Line 838... | ||
851 | .type dd ? |
838 | .type dd ? |
852 | .interval dd ? |
839 | .interval dd ? |
853 | end virtual |
840 | end virtual |
854 | ; 1. Zero all fields in the hardware part. |
841 | ; 1. Zero all fields in the hardware part. |
855 | push eax ecx |
842 | push eax ecx |
856 | sub edi, ehci_pipe.SoftwarePart |
843 | sub edi, sizeof.ehci_pipe |
857 | xor eax, eax |
844 | xor eax, eax |
858 | movi ecx, ehci_pipe.SoftwarePart/4 |
845 | movi ecx, sizeof.ehci_pipe/4 |
859 | rep stosd |
846 | rep stosd |
860 | pop ecx eax |
847 | pop ecx eax |
861 | ; 2. Setup PID in the first TD and make sure that the it is not active. |
848 | ; 2. Setup PID in the first TD and make sure that the it is not active. |
862 | xor edx, edx |
849 | xor edx, edx |
863 | test byte [.endpoint], 80h |
850 | test byte [.endpoint], 80h |
864 | setnz dh |
851 | setnz dh |
865 | mov [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], edx |
852 | mov [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx |
866 | mov [eax+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], 1 |
853 | mov [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1 |
867 | mov [eax+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], 1 |
854 | mov [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1 |
868 | ; 3. Store physical address of the first TD. |
855 | ; 3. Store physical address of the first TD. |
869 | sub eax, ehci_gtd.SoftwarePart |
856 | sub eax, sizeof.ehci_gtd |
870 | call get_phys_addr |
857 | call get_phys_addr |
871 | mov [edi+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart], eax |
858 | mov [edi+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax |
872 | ; 4. Fill ehci_pipe.Flags except for S- and C-masks. |
859 | ; 4. Fill ehci_pipe.Flags except for S- and C-masks. |
873 | ; Copy location from the config pipe. |
860 | ; Copy location from the config pipe. |
874 | mov eax, [ecx+ehci_pipe.Flags-ehci_pipe.SoftwarePart] |
861 | mov eax, [ecx+ehci_pipe.Flags-sizeof.ehci_pipe] |
875 | and eax, 3FFF0000h |
862 | and eax, 3FFF0000h |
876 | ; Use 1 requests per microframe for control/bulk endpoints, |
863 | ; Use 1 requests per microframe for control/bulk endpoints, |
877 | ; use value from the endpoint descriptor for periodic endpoints |
864 | ; use value from the endpoint descriptor for periodic endpoints |
878 | movi edx, 1 |
865 | movi edx, 1 |
879 | test [.type], 1 |
866 | test [.type], 1 |
Line 882... | Line 869... | ||
882 | shr edx, 11 |
869 | shr edx, 11 |
883 | inc edx |
870 | inc edx |
884 | @@: |
871 | @@: |
885 | shl edx, 30 |
872 | shl edx, 30 |
886 | or eax, edx |
873 | or eax, edx |
887 | mov [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart], eax |
874 | mov [edi+ehci_pipe.Flags-sizeof.ehci_pipe], eax |
888 | ; 5. Fill ehci_pipe.Token. |
875 | ; 5. Fill ehci_pipe.Token. |
889 | mov eax, [ecx+ehci_pipe.Token-ehci_pipe.SoftwarePart] |
876 | mov eax, [ecx+ehci_pipe.Token-sizeof.ehci_pipe] |
890 | ; copy following fields from the config pipe: |
877 | ; copy following fields from the config pipe: |
891 | ; DeviceAddress, EndpointSpeed, ControlEndpoint if new type is control |
878 | ; DeviceAddress, EndpointSpeed, ControlEndpoint if new type is control |
892 | mov ecx, eax |
879 | mov ecx, eax |
893 | and eax, 307Fh |
880 | and eax, 307Fh |
894 | and ecx, 8000000h |
881 | and ecx, 8000000h |
Line 913... | Line 900... | ||
913 | cmp [.type], BULK_PIPE |
900 | cmp [.type], BULK_PIPE |
914 | jnz .nonak |
901 | jnz .nonak |
915 | @@: |
902 | @@: |
916 | or eax, 40000000h |
903 | or eax, 40000000h |
917 | .nonak: |
904 | .nonak: |
918 | mov [edi+ehci_pipe.Token-ehci_pipe.SoftwarePart], eax |
905 | mov [edi+ehci_pipe.Token-sizeof.ehci_pipe], eax |
919 | ; 5. Select the corresponding list and insert to the list. |
906 | ; 5. Select the corresponding list and insert to the list. |
920 | ; 5a. Use Control list for control pipes, Bulk list for bulk pipes. |
907 | ; 5a. Use Control list for control pipes, Bulk list for bulk pipes. |
921 | lea edx, [esi+ehci_controller.ControlED.SoftwarePart-sizeof.ehci_controller] |
908 | lea edx, [esi+ehci_controller.ControlED.SoftwarePart-sizeof.ehci_controller] |
922 | cmp [.type], BULK_PIPE |
909 | cmp [.type], BULK_PIPE |
923 | jb .insert ; control pipe |
910 | jb .insert ; control pipe |
Line 929... | Line 916... | ||
929 | ; based on the current bandwidth distribution and the requested bandwidth. |
916 | ; based on the current bandwidth distribution and the requested bandwidth. |
930 | ; There are two schedulers, one for high-speed devices, |
917 | ; There are two schedulers, one for high-speed devices, |
931 | ; another for split transactions. |
918 | ; another for split transactions. |
932 | ; This could fail if the requested bandwidth is not available; |
919 | ; This could fail if the requested bandwidth is not available; |
933 | ; if so, return an error. |
920 | ; if so, return an error. |
934 | test word [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart+2], 3FFFh |
921 | test word [edi+ehci_pipe.Flags-sizeof.ehci_pipe+2], 3FFFh |
935 | jnz .interrupt_fs |
922 | jnz .interrupt_fs |
936 | call ehci_select_hs_interrupt_list |
923 | call ehci_select_hs_interrupt_list |
937 | jmp .interrupt_common |
924 | jmp .interrupt_common |
938 | .interrupt_fs: |
925 | .interrupt_fs: |
939 | call ehci_select_fs_interrupt_list |
926 | call ehci_select_fs_interrupt_list |
940 | .interrupt_common: |
927 | .interrupt_common: |
941 | test edx, edx |
928 | test edx, edx |
942 | jz .return0 |
929 | jz .return0 |
943 | mov word [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart], ax |
930 | mov word [edi+ehci_pipe.Flags-sizeof.ehci_pipe], ax |
944 | .insert: |
931 | .insert: |
945 | mov [edi+ehci_pipe.BaseList-ehci_pipe.SoftwarePart], edx |
932 | mov [edi+ehci_pipe.BaseList-sizeof.ehci_pipe], edx |
946 | ; Insert to the head of the corresponding list. |
933 | ; Insert to the head of the corresponding list. |
947 | ; Note: inserting to the head guarantees that the list traverse in |
934 | ; Note: inserting to the head guarantees that the list traverse in |
948 | ; ehci_process_updated_schedule, once started, will not interact with new pipes. |
935 | ; ehci_process_updated_schedule, once started, will not interact with new pipes. |
949 | ; However, we still need to ensure that links in the new pipe (edi.NextVirt) |
936 | ; However, we still need to ensure that links in the new pipe (edi.NextVirt) |
950 | ; are initialized before links to the new pipe (edx.NextVirt). |
937 | ; are initialized before links to the new pipe (edx.NextVirt). |
Line 955... | Line 942... | ||
955 | mov [ecx+usb_pipe.PrevVirt], edi |
942 | mov [ecx+usb_pipe.PrevVirt], edi |
956 | mov [edx+usb_pipe.NextVirt], edi |
943 | mov [edx+usb_pipe.NextVirt], edi |
957 | ; 5d. Insert in the hardware list: copy previous NextQH to the new pipe, |
944 | ; 5d. Insert in the hardware list: copy previous NextQH to the new pipe, |
958 | ; store the physical address of the new pipe to previous NextQH. |
945 | ; store the physical address of the new pipe to previous NextQH. |
959 | mov ecx, [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart] |
946 | mov ecx, [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart] |
960 | mov [edi+ehci_pipe.NextQH-ehci_pipe.SoftwarePart], ecx |
947 | mov [edi+ehci_pipe.NextQH-sizeof.ehci_pipe], ecx |
961 | lea eax, [edi-ehci_pipe.SoftwarePart] |
948 | lea eax, [edi-sizeof.ehci_pipe] |
962 | call get_phys_addr |
949 | call get_phys_addr |
963 | inc eax |
950 | inc eax |
964 | inc eax |
951 | inc eax |
965 | mov [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], eax |
952 | mov [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], eax |
966 | ; 6. Return with nonzero eax. |
953 | ; 6. Return with nonzero eax. |
Line 1056... | Line 1043... | ||
1056 | ; One transfer descriptor can describe up to 5 pages. |
1043 | ; One transfer descriptor can describe up to 5 pages. |
1057 | ; In the worst case (when the buffer is something*1000h+0FFFh) |
1044 | ; In the worst case (when the buffer is something*1000h+0FFFh) |
1058 | ; this corresponds to 4001h bytes. If the requested size is |
1045 | ; this corresponds to 4001h bytes. If the requested size is |
1059 | ; greater, we should split the transfer into several descriptors. |
1046 | ; greater, we should split the transfer into several descriptors. |
1060 | ; Boundaries to split must be multiples of endpoint transfer size |
1047 | ; Boundaries to split must be multiples of endpoint transfer size |
1061 | ; to avoid short packets except in the end of the transfer, |
1048 | ; to avoid short packets except in the end of the transfer. |
- | 1049 | cmp [size], 4001h |
|
1062 | ; 4000h is always a good value. |
1050 | jbe .lastpacket |
1063 | ; 2. While the remaining data cannot fit in one descriptor, |
1051 | ; 2. While the remaining data cannot fit in one descriptor, |
1064 | ; allocate full descriptors (of maximal possible size). |
1052 | ; allocate full descriptors (of maximal possible size). |
- | 1053 | ; 2a. Calculate size of one descriptor: must be a multiple of transfer size |
|
- | 1054 | ; and must be not greater than 4001h. |
|
- | 1055 | movzx ecx, word [ebx+ohci_pipe.Flags+2-sizeof.ohci_pipe] |
|
1065 | mov edi, 4000h |
1056 | mov eax, 4001h |
- | 1057 | xor edx, edx |
|
- | 1058 | mov edi, eax |
|
- | 1059 | div ecx |
|
- | 1060 | sub edi, edx |
|
1066 | mov [packetSize], edi |
1061 | mov [packetSize], edi |
1067 | .fullpackets: |
1062 | .fullpackets: |
1068 | cmp [size], edi |
- | |
1069 | jbe .lastpacket |
- | |
1070 | call ehci_alloc_packet |
1063 | call ehci_alloc_packet |
1071 | test eax, eax |
1064 | test eax, eax |
1072 | jz .fail |
1065 | jz .fail |
1073 | mov [td], eax |
1066 | mov [td], eax |
1074 | add [buffer], edi |
1067 | add [buffer], edi |
1075 | sub [size], edi |
1068 | sub [size], edi |
- | 1069 | cmp [size], 4001h |
|
1076 | jmp .fullpackets |
1070 | ja .fullpackets |
1077 | ; 3. The remaining data can fit in one packet; |
1071 | ; 3. The remaining data can fit in one packet; |
1078 | ; allocate the last descriptor with size = size of remaining data. |
1072 | ; allocate the last descriptor with size = size of remaining data. |
1079 | .lastpacket: |
1073 | .lastpacket: |
1080 | mov eax, [size] |
1074 | mov eax, [size] |
1081 | mov [packetSize], eax |
1075 | mov [packetSize], eax |
1082 | call ehci_alloc_packet |
1076 | call ehci_alloc_packet |
1083 | test eax, eax |
1077 | test eax, eax |
1084 | jz .fail |
1078 | jz .fail |
1085 | ; 9. Update flags in the last packet. |
1079 | ; 9. Update flags in the last packet. |
1086 | mov edx, [flags] |
1080 | mov edx, [flags] |
1087 | mov [ecx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], edx |
1081 | mov [ecx+ehci_gtd.Flags-sizeof.ehci_gtd], edx |
1088 | ; 10. Fill AlternateNextTD field in all allocated TDs. |
1082 | ; 10. Fill AlternateNextTD field in all allocated TDs. |
1089 | ; If the caller says that short transfer is ok, the queue must advance to |
1083 | ; If the caller says that short transfer is ok, the queue must advance to |
1090 | ; the next descriptor, which is in eax. |
1084 | ; the next descriptor, which is in eax. |
1091 | ; Otherwise, the queue should stop, so make AlternateNextTD point to |
1085 | ; Otherwise, the queue should stop, so make AlternateNextTD point to |
1092 | ; always-inactive descriptor StopQueueTD. |
1086 | ; always-inactive descriptor StopQueueTD. |
1093 | push eax |
1087 | push eax |
1094 | test dl, 1 |
1088 | test dl, 1 |
1095 | jz .disable_short |
1089 | jz .disable_short |
1096 | sub eax, ehci_gtd.SoftwarePart |
1090 | sub eax, sizeof.ehci_gtd |
1097 | jmp @f |
1091 | jmp @f |
1098 | .disable_short: |
1092 | .disable_short: |
1099 | mov eax, [ebx+usb_pipe.Controller] |
1093 | mov eax, [ebx+usb_pipe.Controller] |
1100 | add eax, ehci_controller.StopQueueTD - sizeof.ehci_controller |
1094 | add eax, ehci_controller.StopQueueTD - sizeof.ehci_controller |
1101 | @@: |
1095 | @@: |
1102 | call get_phys_addr |
1096 | call get_phys_addr |
1103 | mov edx, [origTD] |
1097 | mov edx, [origTD] |
1104 | @@: |
1098 | @@: |
1105 | cmp edx, [esp] |
1099 | cmp edx, [esp] |
1106 | jz @f |
1100 | jz @f |
1107 | mov [edx+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], eax |
1101 | mov [edx+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], eax |
1108 | mov edx, [edx+usb_gtd.NextVirt] |
1102 | mov edx, [edx+usb_gtd.NextVirt] |
1109 | jmp @b |
1103 | jmp @b |
1110 | @@: |
1104 | @@: |
1111 | pop eax |
1105 | pop eax |
1112 | ret |
1106 | ret |
Line 1142... | Line 1136... | ||
1142 | ; 2. Initialize controller-independent parts of both TDs. |
1136 | ; 2. Initialize controller-independent parts of both TDs. |
1143 | push eax |
1137 | push eax |
1144 | call usb_init_transfer |
1138 | call usb_init_transfer |
1145 | pop eax |
1139 | pop eax |
1146 | ; 3. Copy PID to the new descriptor. |
1140 | ; 3. Copy PID to the new descriptor. |
1147 | mov edx, [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart] |
1141 | mov edx, [ecx+ehci_gtd.Token-sizeof.ehci_gtd] |
1148 | mov [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], edx |
1142 | mov [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx |
1149 | mov [eax+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], 1 |
1143 | mov [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1 |
1150 | mov [eax+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], 1 |
1144 | mov [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1 |
1151 | ; 4. Save the returned value (next descriptor). |
1145 | ; 4. Save the returned value (next descriptor). |
1152 | push eax |
1146 | push eax |
1153 | ; 5. Store the physical address of the next descriptor. |
1147 | ; 5. Store the physical address of the next descriptor. |
1154 | sub eax, ehci_gtd.SoftwarePart |
1148 | sub eax, sizeof.ehci_gtd |
1155 | call get_phys_addr |
1149 | call get_phys_addr |
1156 | mov [ecx+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], eax |
1150 | mov [ecx+ehci_gtd.NextTD-sizeof.ehci_gtd], eax |
1157 | ; 6. For zero-length transfers, store zero in all fields for buffer addresses. |
1151 | ; 6. For zero-length transfers, store zero in all fields for buffer addresses. |
1158 | ; Otherwise, fill them with real values. |
1152 | ; Otherwise, fill them with real values. |
1159 | xor eax, eax |
1153 | xor eax, eax |
1160 | mov [ecx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], eax |
1154 | mov [ecx+ehci_gtd.Flags-sizeof.ehci_gtd], eax |
1161 | repeat 10 |
1155 | repeat 10 |
1162 | mov [ecx+ehci_gtd.BufferPointers-ehci_gtd.SoftwarePart+(%-1)*4], eax |
1156 | mov [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd+(%-1)*4], eax |
1163 | end repeat |
1157 | end repeat |
1164 | cmp [.packetSize], eax |
1158 | cmp [.packetSize], eax |
1165 | jz @f |
1159 | jz @f |
1166 | mov eax, [.buffer] |
1160 | mov eax, [.buffer] |
1167 | call get_phys_addr |
1161 | call get_phys_addr |
1168 | mov [ecx+ehci_gtd.BufferPointers-ehci_gtd.SoftwarePart], eax |
1162 | mov [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd], eax |
1169 | and eax, 0xFFF |
1163 | and eax, 0xFFF |
1170 | mov edx, [.packetSize] |
1164 | mov edx, [.packetSize] |
1171 | add edx, eax |
1165 | add edx, eax |
1172 | sub edx, 0x1000 |
1166 | sub edx, 0x1000 |
1173 | jbe @f |
1167 | jbe @f |
1174 | mov eax, [.buffer] |
1168 | mov eax, [.buffer] |
1175 | add eax, 0x1000 |
1169 | add eax, 0x1000 |
1176 | call get_pg_addr |
1170 | call get_pg_addr |
1177 | mov [ecx+ehci_gtd.BufferPointers+4-ehci_gtd.SoftwarePart], eax |
1171 | mov [ecx+ehci_gtd.BufferPointers+4-sizeof.ehci_gtd], eax |
1178 | sub edx, 0x1000 |
1172 | sub edx, 0x1000 |
1179 | jbe @f |
1173 | jbe @f |
1180 | mov eax, [.buffer] |
1174 | mov eax, [.buffer] |
1181 | add eax, 0x2000 |
1175 | add eax, 0x2000 |
1182 | call get_pg_addr |
1176 | call get_pg_addr |
1183 | mov [ecx+ehci_gtd.BufferPointers+8-ehci_gtd.SoftwarePart], eax |
1177 | mov [ecx+ehci_gtd.BufferPointers+8-sizeof.ehci_gtd], eax |
1184 | sub edx, 0x1000 |
1178 | sub edx, 0x1000 |
1185 | jbe @f |
1179 | jbe @f |
1186 | mov eax, [.buffer] |
1180 | mov eax, [.buffer] |
1187 | add eax, 0x3000 |
1181 | add eax, 0x3000 |
1188 | call get_pg_addr |
1182 | call get_pg_addr |
1189 | mov [ecx+ehci_gtd.BufferPointers+12-ehci_gtd.SoftwarePart], eax |
1183 | mov [ecx+ehci_gtd.BufferPointers+12-sizeof.ehci_gtd], eax |
1190 | sub edx, 0x1000 |
1184 | sub edx, 0x1000 |
1191 | jbe @f |
1185 | jbe @f |
1192 | mov eax, [.buffer] |
1186 | mov eax, [.buffer] |
1193 | add eax, 0x4000 |
1187 | add eax, 0x4000 |
1194 | call get_pg_addr |
1188 | call get_pg_addr |
1195 | mov [ecx+ehci_gtd.BufferPointers+16-ehci_gtd.SoftwarePart], eax |
1189 | mov [ecx+ehci_gtd.BufferPointers+16-sizeof.ehci_gtd], eax |
1196 | @@: |
1190 | @@: |
1197 | ; 7. Fill Token field: |
1191 | ; 7. Fill Token field: |
1198 | ; set Status = 0 (inactive, ehci_insert_transfer would mark everything active); |
1192 | ; set Status = 0 (inactive, ehci_insert_transfer would mark everything active); |
1199 | ; keep current PID if [.direction] is zero, use two lower bits of [.direction] |
1193 | ; keep current PID if [.direction] is zero, use two lower bits of [.direction] |
1200 | ; otherwise shifted as (0|1|2) -> (2|0|1); |
1194 | ; otherwise shifted as (0|1|2) -> (2|0|1); |
1201 | ; set error counter to 3; |
1195 | ; set error counter to 3; |
1202 | ; set current page to 0; |
1196 | ; set current page to 0; |
1203 | ; do not interrupt on complete (ehci_insert_transfer sets this bit where needed); |
1197 | ; do not interrupt on complete (ehci_insert_transfer sets this bit where needed); |
1204 | ; set DataToggle to bit 2 of [.direction]. |
1198 | ; set DataToggle to bit 2 of [.direction]. |
1205 | mov eax, [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart] |
1199 | mov eax, [ecx+ehci_gtd.Token-sizeof.ehci_gtd] |
1206 | and eax, 300h ; keep PID code |
1200 | and eax, 300h ; keep PID code |
1207 | mov edx, [.direction] |
1201 | mov edx, [.direction] |
1208 | test edx, edx |
1202 | test edx, edx |
1209 | jz .haspid |
1203 | jz .haspid |
1210 | and edx, 3 |
1204 | and edx, 3 |
Line 1220... | Line 1214... | ||
1220 | .haspid: |
1214 | .haspid: |
1221 | or eax, 0C00h |
1215 | or eax, 0C00h |
1222 | mov edx, [.packetSize] |
1216 | mov edx, [.packetSize] |
1223 | shl edx, 16 |
1217 | shl edx, 16 |
1224 | or eax, edx |
1218 | or eax, edx |
1225 | mov [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart], eax |
1219 | mov [ecx+ehci_gtd.Token-sizeof.ehci_gtd], eax |
1226 | ; 4. Restore the returned value saved in step 2. |
1220 | ; 4. Restore the returned value saved in step 2. |
1227 | pop eax |
1221 | pop eax |
1228 | .nothing: |
1222 | .nothing: |
1229 | ret |
1223 | ret |
1230 | endp |
1224 | endp |
Line 1232... | Line 1226... | ||
1232 | ; This procedure is called from several places in main USB code |
1226 | ; This procedure is called from several places in main USB code |
1233 | ; and activates the transfer which was previously allocated by |
1227 | ; and activates the transfer which was previously allocated by |
1234 | ; ehci_alloc_transfer. |
1228 | ; ehci_alloc_transfer. |
1235 | ; ecx -> last descriptor for the transfer, ebx -> usb_pipe |
1229 | ; ecx -> last descriptor for the transfer, ebx -> usb_pipe |
1236 | proc ehci_insert_transfer |
1230 | proc ehci_insert_transfer |
1237 | or byte [ecx+ehci_gtd.Token+1-ehci_gtd.SoftwarePart], 80h ; set IOC bit |
1231 | or byte [ecx+ehci_gtd.Token+1-sizeof.ehci_gtd], 80h ; set IOC bit |
1238 | mov eax, [esp+4] |
1232 | mov eax, [esp+4] |
1239 | .activate: |
1233 | .activate: |
1240 | or byte [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], 80h ; set Active bit |
1234 | or byte [eax+ehci_gtd.Token-sizeof.ehci_gtd], 80h ; set Active bit |
1241 | cmp eax, ecx |
1235 | cmp eax, ecx |
1242 | mov eax, [eax+usb_gtd.NextVirt] |
1236 | mov eax, [eax+usb_gtd.NextVirt] |
1243 | jnz .activate |
1237 | jnz .activate |
1244 | ret |
1238 | ret |
1245 | endp |
1239 | endp |
Line 1326... | Line 1320... | ||
1326 | mov edx, [eax+usb_device_data.Hub] |
1320 | mov edx, [eax+usb_device_data.Hub] |
1327 | jmp .find_hs_hub |
1321 | jmp .find_hs_hub |
1328 | .found_hs_hub: |
1322 | .found_hs_hub: |
1329 | mov edx, [edx+usb_hub.ConfigPipe] |
1323 | mov edx, [edx+usb_hub.ConfigPipe] |
1330 | inc ecx |
1324 | inc ecx |
1331 | mov edx, [edx+ehci_pipe.Token-ehci_pipe.SoftwarePart] |
1325 | mov edx, [edx+ehci_pipe.Token-sizeof.ehci_pipe] |
1332 | shl ecx, 23 |
1326 | shl ecx, 23 |
1333 | and edx, 7Fh |
1327 | and edx, 7Fh |
1334 | shl edx, 16 |
1328 | shl edx, 16 |
1335 | or edx, ecx ; ehci_pipe.Flags |
1329 | or edx, ecx ; ehci_pipe.Flags |
1336 | pop eax |
1330 | pop eax |
1337 | or eax, 1 shl 27 ; ehci_pipe.Token |
1331 | or eax, 1 shl 27 ; ehci_pipe.Token |
1338 | .common: |
1332 | .common: |
1339 | ; 5. Create pseudo-pipe in the stack. |
1333 | ; 5. Create pseudo-pipe in the stack. |
1340 | ; See ehci_init_pipe: only .Controller, .Token, .Flags fields are used. |
1334 | ; See ehci_init_pipe: only .Controller, .Token, .Flags fields are used. |
1341 | push esi ; ehci_pipe.SoftwarePart.Controller |
1335 | push esi ; usb_pipe.Controller |
1342 | mov ecx, esp |
1336 | mov ecx, esp |
1343 | sub esp, ehci_pipe.SoftwarePart - ehci_pipe.Flags - 4 |
1337 | sub esp, sizeof.ehci_pipe - ehci_pipe.Flags - 4 |
1344 | push edx ; ehci_pipe.Flags |
1338 | push edx ; ehci_pipe.Flags |
1345 | push eax ; ehci_pipe.Token |
1339 | push eax ; ehci_pipe.Token |
1346 | ; 6. Notify the protocol layer. |
1340 | ; 6. Notify the protocol layer. |
1347 | call usb_new_device |
1341 | call usb_new_device |
1348 | ; 7. Cleanup the stack after step 5 and return. |
1342 | ; 7. Cleanup the stack after step 5 and return. |
1349 | add esp, ehci_pipe.SoftwarePart - ehci_pipe.Flags + 8 |
1343 | add esp, sizeof.ehci_pipe - ehci_pipe.Flags + 8 |
1350 | pop ecx ebx ; restore used registers |
1344 | pop ecx ebx ; restore used registers |
1351 | ret |
1345 | ret |
1352 | endp |
1346 | endp |
Line 1353... | Line 1347... | ||
1353 | 1347 | ||
Line 1656... | Line 1650... | ||
1656 | .tdloop: |
1650 | .tdloop: |
1657 | ; 3. For every descriptor, test active flag and check for end-of-queue; |
1651 | ; 3. For every descriptor, test active flag and check for end-of-queue; |
1658 | ; if either of conditions holds, exit from the internal loop. |
1652 | ; if either of conditions holds, exit from the internal loop. |
1659 | cmp ebx, [esp] |
1653 | cmp ebx, [esp] |
1660 | jz .tddone |
1654 | jz .tddone |
1661 | cmp byte [ebx+ehci_gtd.Token-ehci_gtd.SoftwarePart], 0 |
1655 | cmp byte [ebx+ehci_gtd.Token-sizeof.ehci_gtd], 0 |
1662 | js .tddone |
1656 | js .tddone |
1663 | ; Release the queue lock while processing one descriptor: |
1657 | ; Release the queue lock while processing one descriptor: |
1664 | ; callback function could (and often would) schedule another transfer. |
1658 | ; callback function could (and often would) schedule another transfer. |
1665 | push ecx |
1659 | push ecx |
1666 | call mutex_unlock |
1660 | call mutex_unlock |
Line 1688... | Line 1682... | ||
1688 | proc ehci_process_updated_td |
1682 | proc ehci_process_updated_td |
1689 | ; mov eax, [ebx+usb_gtd.Pipe] |
1683 | ; mov eax, [ebx+usb_gtd.Pipe] |
1690 | ; cmp [eax+usb_pipe.Type], INTERRUPT_PIPE |
1684 | ; cmp [eax+usb_pipe.Type], INTERRUPT_PIPE |
1691 | ; jnz @f |
1685 | ; jnz @f |
1692 | ; DEBUGF 1,'K : finalized TD for pipe %x:\n',eax |
1686 | ; DEBUGF 1,'K : finalized TD for pipe %x:\n',eax |
1693 | ; lea eax, [ebx-ehci_gtd.SoftwarePart] |
1687 | ; lea eax, [ebx-sizeof.ehci_gtd] |
1694 | ; DEBUGF 1,'K : %x %x %x %x\n',[eax],[eax+4],[eax+8],[eax+12] |
1688 | ; DEBUGF 1,'K : %x %x %x %x\n',[eax],[eax+4],[eax+8],[eax+12] |
1695 | ; DEBUGF 1,'K : %x %x %x %x\n',[eax+16],[eax+20],[eax+24],[eax+28] |
1689 | ; DEBUGF 1,'K : %x %x %x %x\n',[eax+16],[eax+20],[eax+24],[eax+28] |
1696 | ;@@: |
1690 | ;@@: |
1697 | ; 1. Remove this descriptor from the list of descriptors for this pipe. |
1691 | ; 1. Remove this descriptor from the list of descriptors for this pipe. |
1698 | call usb_unlink_td |
1692 | call usb_unlink_td |
1699 | ; 2. Calculate actual number of bytes transferred. |
1693 | ; 2. Calculate actual number of bytes transferred. |
1700 | mov eax, [ebx+ehci_gtd.Token-ehci_gtd.SoftwarePart] |
1694 | mov eax, [ebx+ehci_gtd.Token-sizeof.ehci_gtd] |
1701 | lea edx, [eax+eax] |
1695 | lea edx, [eax+eax] |
1702 | shr edx, 17 |
1696 | shr edx, 17 |
1703 | sub edx, [ebx+usb_gtd.Length] |
1697 | sub edx, [ebx+usb_gtd.Length] |
1704 | neg edx |
1698 | neg edx |
1705 | ; 3. Check whether we need some special processing beyond notifying the driver. |
1699 | ; 3. Check whether we need some special processing beyond notifying the driver. |
Line 1713... | Line 1707... | ||
1713 | ; If special processing is not needed, advance to 4 with ecx = 0. |
1707 | ; If special processing is not needed, advance to 4 with ecx = 0. |
1714 | ; Otherwise, go to 6. |
1708 | ; Otherwise, go to 6. |
1715 | xor ecx, ecx |
1709 | xor ecx, ecx |
1716 | test al, 40h |
1710 | test al, 40h |
1717 | jnz .error |
1711 | jnz .error |
1718 | test byte [ebx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], 1 |
1712 | test byte [ebx+ehci_gtd.Flags-sizeof.ehci_gtd], 1 |
1719 | jnz .notify |
1713 | jnz .notify |
1720 | cmp edx, [ebx+usb_gtd.Length] |
1714 | cmp edx, [ebx+usb_gtd.Length] |
1721 | jnz .special |
1715 | jnz .special |
1722 | .notify: |
1716 | .notify: |
1723 | ; 4. Either the descriptor in ebx was processed without errors, |
1717 | ; 4. Either the descriptor in ebx was processed without errors, |
Line 1743... | Line 1737... | ||
1743 | stdcall ehci_free_td, ebx |
1737 | stdcall ehci_free_td, ebx |
1744 | pop ebx |
1738 | pop ebx |
1745 | ret |
1739 | ret |
1746 | .error: |
1740 | .error: |
1747 | push ebx |
1741 | push ebx |
1748 | sub ebx, ehci_gtd.SoftwarePart |
1742 | sub ebx, sizeof.ehci_gtd |
1749 | DEBUGF 1,'K : TD failed:\n' |
1743 | DEBUGF 1,'K : TD failed:\n' |
1750 | DEBUGF 1,'K : %x %x %x %x\n',[ebx],[ebx+4],[ebx+8],[ebx+12] |
1744 | DEBUGF 1,'K : %x %x %x %x\n',[ebx],[ebx+4],[ebx+8],[ebx+12] |
1751 | DEBUGF 1,'K : %x %x %x %x\n',[ebx+16],[ebx+20],[ebx+24],[ebx+28] |
1745 | DEBUGF 1,'K : %x %x %x %x\n',[ebx+16],[ebx+20],[ebx+24],[ebx+28] |
1752 | pop ebx |
1746 | pop ebx |
1753 | DEBUGF 1,'K : pipe now:\n' |
1747 | DEBUGF 1,'K : pipe now:\n' |
1754 | mov ecx, [ebx+usb_gtd.Pipe] |
1748 | mov ecx, [ebx+usb_gtd.Pipe] |
1755 | sub ecx, ehci_pipe.SoftwarePart |
1749 | sub ecx, sizeof.ehci_pipe |
1756 | DEBUGF 1,'K : %x %x %x %x\n',[ecx],[ecx+4],[ecx+8],[ecx+12] |
1750 | DEBUGF 1,'K : %x %x %x %x\n',[ecx],[ecx+4],[ecx+8],[ecx+12] |
1757 | DEBUGF 1,'K : %x %x %x %x\n',[ecx+16],[ecx+20],[ecx+24],[ecx+28] |
1751 | DEBUGF 1,'K : %x %x %x %x\n',[ecx+16],[ecx+20],[ecx+24],[ecx+28] |
1758 | DEBUGF 1,'K : %x %x %x %x\n',[ecx+32],[ecx+36],[ecx+40],[ecx+44] |
1752 | DEBUGF 1,'K : %x %x %x %x\n',[ecx+32],[ecx+36],[ecx+40],[ecx+44] |
1759 | .special: |
1753 | .special: |
1760 | ; 6. Special processing is needed. |
1754 | ; 6. Special processing is needed. |
Line 1800... | Line 1794... | ||
1800 | .know_error: |
1794 | .know_error: |
1801 | ; 6d. If error code is USB_STATUS_UNDERRUN and the last TD allows short packets, |
1795 | ; 6d. If error code is USB_STATUS_UNDERRUN and the last TD allows short packets, |
1802 | ; it is not an error; in this case, go to 4 with ecx = 0. |
1796 | ; it is not an error; in this case, go to 4 with ecx = 0. |
1803 | cmp ecx, USB_STATUS_UNDERRUN |
1797 | cmp ecx, USB_STATUS_UNDERRUN |
1804 | jnz @f |
1798 | jnz @f |
1805 | test byte [ebx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], 1 |
1799 | test byte [ebx+ehci_gtd.Flags-sizeof.ehci_gtd], 1 |
1806 | jz @f |
1800 | jz @f |
1807 | xor ecx, ecx |
1801 | xor ecx, ecx |
1808 | pop edx ; length |
1802 | pop edx ; length |
1809 | jmp .notify |
1803 | jmp .notify |
1810 | @@: |
1804 | @@: |
Line 1830... | Line 1824... | ||
1830 | ; Control pipes normally recover at the next SETUP transaction (first stage |
1824 | ; Control pipes normally recover at the next SETUP transaction (first stage |
1831 | ; of any control transfer), so we hope on the best and just advance the queue |
1825 | ; of any control transfer), so we hope on the best and just advance the queue |
1832 | ; to the next transfer. (According to the standard, "A control pipe may also |
1826 | ; to the next transfer. (According to the standard, "A control pipe may also |
1833 | ; support functional stall as well, but this is not recommended."). |
1827 | ; support functional stall as well, but this is not recommended."). |
1834 | mov edx, [ebx+usb_gtd.Pipe] |
1828 | mov edx, [ebx+usb_gtd.Pipe] |
1835 | mov eax, [ebx+ehci_gtd.NextTD-ehci_gtd.SoftwarePart] |
1829 | mov eax, [ebx+ehci_gtd.NextTD-sizeof.ehci_gtd] |
1836 | or al, 1 |
1830 | or al, 1 |
1837 | mov [edx+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart], eax |
1831 | mov [edx+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax |
1838 | mov [edx+ehci_pipe.Overlay.AlternateNextTD-ehci_pipe.SoftwarePart], eax |
1832 | mov [edx+ehci_pipe.Overlay.AlternateNextTD-sizeof.ehci_pipe], eax |
1839 | cmp [edx+usb_pipe.Type], CONTROL_PIPE |
1833 | cmp [edx+usb_pipe.Type], CONTROL_PIPE |
1840 | jz .control |
1834 | jz .control |
1841 | ; Bulk/interrupt transfer; halt the queue. |
1835 | ; Bulk/interrupt transfer; halt the queue. |
1842 | mov [edx+ehci_pipe.Overlay.Token-ehci_pipe.SoftwarePart], 40h |
1836 | mov [edx+ehci_pipe.Overlay.Token-sizeof.ehci_pipe], 40h |
1843 | pop edx |
1837 | pop edx |
1844 | jmp .notify |
1838 | jmp .notify |
1845 | ; Control transfer. |
1839 | ; Control transfer. |
1846 | .control: |
1840 | .control: |
1847 | and [edx+ehci_pipe.Overlay.Token-ehci_pipe.SoftwarePart], 0 |
1841 | and [edx+ehci_pipe.Overlay.Token-sizeof.ehci_pipe], 0 |
1848 | dec [edx+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart] |
1842 | dec [edx+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe] |
1849 | pop edx |
1843 | pop edx |
1850 | jmp .notify |
1844 | jmp .notify |
1851 | endp |
1845 | endp |
Line 1852... | Line 1846... | ||
1852 | 1846 | ||
1853 | ; This procedure unlinks the pipe from the corresponding pipe list. |
1847 | ; This procedure unlinks the pipe from the corresponding pipe list. |
1854 | ; esi -> usb_controller, ebx -> usb_pipe |
1848 | ; esi -> usb_controller, ebx -> usb_pipe |
1855 | proc ehci_unlink_pipe |
1849 | proc ehci_unlink_pipe |
1856 | cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE |
1850 | cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE |
1857 | jnz @f |
1851 | jnz @f |
1858 | test word [ebx+ehci_pipe.Flags-ehci_pipe.SoftwarePart+2], 3FFFh |
1852 | test word [ebx+ehci_pipe.Flags-sizeof.ehci_pipe+2], 3FFFh |
1859 | jnz .interrupt_fs |
1853 | jnz .interrupt_fs |
1860 | call ehci_hs_interrupt_list_unlink |
1854 | call ehci_hs_interrupt_list_unlink |
1861 | jmp .interrupt_common |
1855 | jmp .interrupt_common |
1862 | .interrupt_fs: |
1856 | .interrupt_fs: |
Line 1868... | Line 1862... | ||
1868 | mov [edx+usb_pipe.PrevVirt], eax |
1862 | mov [edx+usb_pipe.PrevVirt], eax |
1869 | mov [eax+usb_pipe.NextVirt], edx |
1863 | mov [eax+usb_pipe.NextVirt], edx |
1870 | mov edx, esi |
1864 | mov edx, esi |
1871 | sub edx, eax |
1865 | sub edx, eax |
1872 | cmp edx, sizeof.ehci_controller |
1866 | cmp edx, sizeof.ehci_controller |
1873 | mov edx, [ebx+ehci_pipe.NextQH-ehci_pipe.SoftwarePart] |
1867 | mov edx, [ebx+ehci_pipe.NextQH-sizeof.ehci_pipe] |
1874 | jb .prev_is_static |
1868 | jb .prev_is_static |
1875 | mov [eax+ehci_pipe.NextQH-ehci_pipe.SoftwarePart], edx |
1869 | mov [eax+ehci_pipe.NextQH-sizeof.ehci_pipe], edx |
1876 | ret |
1870 | ret |
1877 | .prev_is_static: |
1871 | .prev_is_static: |
1878 | mov [eax+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], edx |
1872 | mov [eax+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], edx |
1879 | ret |
1873 | ret |
1880 | endp |
1874 | endp |
Line 1881... | Line 1875... | ||
1881 | 1875 | ||
1882 | proc ehci_alloc_td |
1876 | proc ehci_alloc_td |
1883 | push ebx |
1877 | push ebx |
1884 | mov ebx, ehci_gtd_mutex |
1878 | mov ebx, ehci_gtd_mutex |
1885 | stdcall usb_allocate_common, sizeof.ehci_gtd |
1879 | stdcall usb_allocate_common, (sizeof.ehci_gtd + sizeof.usb_gtd + 1Fh) and not 1Fh |
1886 | test eax, eax |
1880 | test eax, eax |
1887 | jz @f |
1881 | jz @f |
1888 | add eax, ehci_gtd.SoftwarePart |
1882 | add eax, sizeof.ehci_gtd |
1889 | @@: |
1883 | @@: |
1890 | pop ebx |
1884 | pop ebx |
1891 | ret |
1885 | ret |
Line 1892... | Line 1886... | ||
1892 | endp |
1886 | endp |
1893 | 1887 | ||
1894 | ; This procedure is called from several places from main USB code and |
1888 | ; This procedure is called from several places from main USB code and |
1895 | ; frees all additional data associated with the transfer descriptor. |
1889 | ; frees all additional data associated with the transfer descriptor. |
1896 | ; EHCI has no additional data, so just free ehci_gtd structure. |
1890 | ; EHCI has no additional data, so just free ehci_gtd structure. |
1897 | proc ehci_free_td |
1891 | proc ehci_free_td |
1898 | sub dword [esp+4], ehci_gtd.SoftwarePart |
1892 | sub dword [esp+4], sizeof.ehci_gtd |