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 18... | Line 18... | ||
18 | USB_PID_SETUP = 2Dh |
18 | USB_PID_SETUP = 2Dh |
19 | USB_PID_IN = 69h |
19 | USB_PID_IN = 69h |
20 | USB_PID_OUT = 0E1h |
20 | USB_PID_OUT = 0E1h |
21 | ; UHCI does not support an interrupt on root hub status change. We must poll |
21 | ; UHCI does not support an interrupt on root hub status change. We must poll |
22 | ; the controller periodically. This is the period in timer ticks (10ms). |
22 | ; the controller periodically. This is the period in timer ticks (10ms). |
23 | ; We use the value 100 ms: it is valid value for USB hub poll rate (1-255 ms), |
23 | ; We use the value 100 ticks: it is small enough to be responsive to connect |
24 | ; small enough to be responsible to connect events and large enough to not |
24 | ; events and large enough to not load CPU too often. |
25 | ; load CPU too often. |
- | |
26 | UHCI_POLL_INTERVAL = 100 |
25 | UHCI_POLL_INTERVAL = 100 |
27 | ; the following constant is an invalid encoding for length fields in |
26 | ; the following constant is an invalid encoding for length fields in |
28 | ; uhci_gtd; it is used to check whether an inactive TD has been |
27 | ; uhci_gtd; it is used to check whether an inactive TD has been |
29 | ; completed (actual length of the transfer is valid) or not processed at all |
28 | ; completed (actual length of the transfer is valid) or not processed at all |
30 | ; (actual length of the transfer is UHCI_INVALID_LENGTH). |
29 | ; (actual length of the transfer is UHCI_INVALID_LENGTH). |
Line 40... | Line 39... | ||
40 | ; specification with some additional fields. |
39 | ; specification with some additional fields. |
41 | ; * The hardware uses first two fields (8 bytes). Next two fields are used for |
40 | ; * The hardware uses first two fields (8 bytes). Next two fields are used for |
42 | ; software book-keeping. |
41 | ; software book-keeping. |
43 | ; * The hardware requires 16-bytes alignment of the hardware part. |
42 | ; * The hardware requires 16-bytes alignment of the hardware part. |
44 | ; Since the allocator (usb_allocate_common) allocates memory sequentially |
43 | ; Since the allocator (usb_allocate_common) allocates memory sequentially |
45 | ; from page start (aligned on 0x1000 bytes), size of the structure must be |
44 | ; from page start (aligned on 0x1000 bytes), block size for the allocator |
46 | ; divisible by 16. |
45 | ; must be divisible by 16; usb1_allocate_endpoint ensures this. |
47 | struct uhci_pipe |
46 | struct uhci_pipe |
48 | NextQH dd ? |
47 | NextQH dd ? |
49 | ; 1. First bit (bit 0) is Terminate bit. 1 = there is no next QH. |
48 | ; 1. First bit (bit 0) is Terminate bit. 1 = there is no next QH. |
50 | ; 2. Next bit (bit 1) is QH/TD select bit. 1 = NextQH points to QH. |
49 | ; 2. Next bit (bit 1) is QH/TD select bit. 1 = NextQH points to QH. |
51 | ; 3. Next two bits (bits 2-3) are reserved. |
50 | ; 3. Next two bits (bits 2-3) are reserved. |
Line 79... | Line 78... | ||
79 | ; the MaximumLength bitfield encodes maximum packet size, |
78 | ; the MaximumLength bitfield encodes maximum packet size, |
80 | ; the Reserved bit 20 is LowSpeedDevice bit. |
79 | ; the Reserved bit 20 is LowSpeedDevice bit. |
81 | ErrorTD dd ? |
80 | ErrorTD dd ? |
82 | ; Usually NULL. If nonzero, it is a pointer to descriptor which was error'd |
81 | ; Usually NULL. If nonzero, it is a pointer to descriptor which was error'd |
83 | ; and should be freed sometime in the future (the hardware could still use it). |
82 | ; and should be freed sometime in the future (the hardware could still use it). |
84 | SoftwarePart rd sizeof.usb_pipe/4 |
- | |
85 | ; Common part for all controllers, described by usb_pipe structure. |
- | |
86 | ends |
83 | ends |
Line 87... | Line -... | ||
87 | - | ||
88 | if sizeof.uhci_pipe mod 16 |
- | |
89 | .err uhci_pipe must be 16-bytes aligned |
- | |
90 | end if |
- | |
91 | 84 | ||
92 | ; This structure describes the static head of every list of pipes. |
85 | ; This structure describes the static head of every list of pipes. |
93 | ; The hardware requires 16-bytes alignment of this structure. |
86 | ; The hardware requires 16-bytes alignment of this structure. |
94 | ; All instances of this structure are located sequentially in uhci_controller, |
87 | ; All instances of this structure are located sequentially in uhci_controller, |
95 | ; uhci_controller is page-aligned, so it is sufficient to make this structure |
88 | ; uhci_controller is page-aligned, so it is sufficient to make this structure |
Line 165... | Line 158... | ||
165 | ; * The hardware part consists of first 16 bytes and corresponds to the |
158 | ; * The hardware part consists of first 16 bytes and corresponds to the |
166 | ; Transfer Descriptor aka TD from UHCI specification. |
159 | ; Transfer Descriptor aka TD from UHCI specification. |
167 | ; * The hardware requires 16-bytes alignment of the hardware part, so |
160 | ; * The hardware requires 16-bytes alignment of the hardware part, so |
168 | ; the entire descriptor must be 16-bytes aligned. Since the allocator |
161 | ; the entire descriptor must be 16-bytes aligned. Since the allocator |
169 | ; (uhci_allocate_common) allocates memory sequentially from page start |
162 | ; (uhci_allocate_common) allocates memory sequentially from page start |
170 | ; (aligned on 0x1000 bytes), size of the structure must be divisible by 16. |
163 | ; (aligned on 0x1000 bytes), block size for the allocator must be |
- | 164 | ; divisible by 16; usb1_allocate_general_td ensures this. |
|
171 | struct uhci_gtd |
165 | struct uhci_gtd |
172 | NextTD dd ? |
166 | NextTD dd ? |
173 | ; 1. First bit (bit 0) is Terminate bit. 1 = there is no next TD. |
167 | ; 1. First bit (bit 0) is Terminate bit. 1 = there is no next TD. |
174 | ; 2. Next bit (bit 1) is QH/TD select bit. 1 = NextTD points to QH. |
168 | ; 2. Next bit (bit 1) is QH/TD select bit. 1 = NextTD points to QH. |
175 | ; This bit is always set to 0 in the implementation. |
169 | ; This bit is always set to 0 in the implementation. |
Line 229... | Line 223... | ||
229 | ; Usually NULL. If the original buffer crosses a page boundary, this is a |
223 | ; Usually NULL. If the original buffer crosses a page boundary, this is a |
230 | ; pointer to the structure uhci_original_buffer for this request. |
224 | ; pointer to the structure uhci_original_buffer for this request. |
231 | ; bit 0: 1 = short packet is NOT allowed |
225 | ; bit 0: 1 = short packet is NOT allowed |
232 | ; (before the TD is processed, it is the copy of bit 29 of ControlStatus; |
226 | ; (before the TD is processed, it is the copy of bit 29 of ControlStatus; |
233 | ; some controllers modify that bit, so we need a copy in a safe place) |
227 | ; some controllers modify that bit, so we need a copy in a safe place) |
234 | SoftwarePart rd sizeof.usb_gtd/4 |
- | |
235 | ; Software part, common for all controllers. |
- | |
236 | ends |
228 | ends |
Line 237... | Line -... | ||
237 | - | ||
238 | if sizeof.uhci_gtd mod 16 |
- | |
239 | .err uhci_gtd must be 16-bytes aligned |
- | |
240 | end if |
- | |
241 | 229 | ||
242 | ; UHCI requires that the entire transfer buffer should be on one page. |
230 | ; UHCI requires that the entire transfer buffer should be on one page. |
243 | ; If the actual buffer crosses page boundary, uhci_alloc_packet |
231 | ; If the actual buffer crosses page boundary, uhci_alloc_packet |
244 | ; allocates additional memory for buffer for hardware. |
232 | ; allocates additional memory for buffer for hardware. |
245 | ; This structure describes correspondence between two buffers. |
233 | ; This structure describes correspondence between two buffers. |
Line 851... | Line 839... | ||
851 | .tdloop: |
839 | .tdloop: |
852 | ; 3. For every descriptor, test active flag and check for end-of-queue; |
840 | ; 3. For every descriptor, test active flag and check for end-of-queue; |
853 | ; if either of conditions holds, exit from the internal loop. |
841 | ; if either of conditions holds, exit from the internal loop. |
854 | cmp ebx, [esp] |
842 | cmp ebx, [esp] |
855 | jz .tddone |
843 | jz .tddone |
856 | mov eax, [ebx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart] |
844 | mov eax, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd] |
857 | test eax, 1 shl 23 ; active? |
845 | test eax, 1 shl 23 ; active? |
858 | jnz .tddone |
846 | jnz .tddone |
859 | ; Release the queue lock while processing one descriptor: |
847 | ; Release the queue lock while processing one descriptor: |
860 | ; callback function could (and often would) schedule another transfer. |
848 | ; callback function could (and often would) schedule another transfer. |
861 | push ecx |
849 | push ecx |
Line 887... | Line 875... | ||
887 | ; DEBUGF 1,'K : finalized TD:\n' |
875 | ; DEBUGF 1,'K : finalized TD:\n' |
888 | ; DEBUGF 1,'K : %x %x %x %x\n',[ebx-20],[ebx-16],[ebx-12],[ebx-8] |
876 | ; DEBUGF 1,'K : %x %x %x %x\n',[ebx-20],[ebx-16],[ebx-12],[ebx-8] |
889 | ; DEBUGF 1,'K : %x %x %x %x\n',[ebx-4],[ebx],[ebx+4],[ebx+8] |
877 | ; DEBUGF 1,'K : %x %x %x %x\n',[ebx-4],[ebx],[ebx+4],[ebx+8] |
890 | ; 2. If this is IN transfer into special buffer, copy the data |
878 | ; 2. If this is IN transfer into special buffer, copy the data |
891 | ; to target location. |
879 | ; to target location. |
892 | mov edx, [ebx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart] |
880 | mov edx, [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd] |
893 | and edx, not 1 ; clear lsb (used for another goal) |
881 | and edx, not 1 ; clear lsb (used for another goal) |
894 | jz .nocopy |
882 | jz .nocopy |
895 | cmp byte [ebx+uhci_gtd.Token-uhci_gtd.SoftwarePart], USB_PID_IN |
883 | cmp byte [ebx+uhci_gtd.Token-sizeof.uhci_gtd], USB_PID_IN |
896 | jnz .nocopy |
884 | jnz .nocopy |
897 | ; Note: we assume that pointer to buffer is valid in the memory space of |
885 | ; Note: we assume that pointer to buffer is valid in the memory space of |
898 | ; the USB thread. This means that buffer must reside in kernel memory |
886 | ; the USB thread. This means that buffer must reside in kernel memory |
899 | ; (shared by all processes). |
887 | ; (shared by all processes). |
900 | push esi edi |
888 | push esi edi |
901 | mov esi, [edx+uhci_original_buffer.UsedBuffer] |
889 | mov esi, [edx+uhci_original_buffer.UsedBuffer] |
902 | mov edi, [edx+uhci_original_buffer.OrigBuffer] |
890 | mov edi, [edx+uhci_original_buffer.OrigBuffer] |
903 | mov ecx, [ebx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart] |
891 | mov ecx, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd] |
904 | inc ecx |
892 | inc ecx |
905 | and ecx, 7FFh |
893 | and ecx, 7FFh |
906 | mov edx, ecx |
894 | mov edx, ecx |
907 | shr ecx, 2 |
895 | shr ecx, 2 |
908 | and edx, 3 |
896 | and edx, 3 |
Line 911... | Line 899... | ||
911 | rep movsb |
899 | rep movsb |
912 | pop edi esi |
900 | pop edi esi |
913 | .nocopy: |
901 | .nocopy: |
914 | ; 3. Calculate actual number of bytes transferred. |
902 | ; 3. Calculate actual number of bytes transferred. |
915 | ; 3a. Read the state. |
903 | ; 3a. Read the state. |
916 | mov eax, [ebx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart] |
904 | mov eax, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd] |
917 | mov ecx, [ebx+uhci_gtd.Token-uhci_gtd.SoftwarePart] |
905 | mov ecx, [ebx+uhci_gtd.Token-sizeof.uhci_gtd] |
918 | ; 3b. Get number of bytes processed. |
906 | ; 3b. Get number of bytes processed. |
919 | lea edx, [eax+1] |
907 | lea edx, [eax+1] |
920 | and edx, 7FFh |
908 | and edx, 7FFh |
921 | ; 3c. Subtract number of bytes in this packet. |
909 | ; 3c. Subtract number of bytes in this packet. |
922 | add ecx, 1 shl 21 |
910 | add ecx, 1 shl 21 |
Line 936... | Line 924... | ||
936 | ; because the caller disallowed short packets or because the packet is not |
924 | ; because the caller disallowed short packets or because the packet is not |
937 | ; the last one in the corresponding transfer). |
925 | ; the last one in the corresponding transfer). |
938 | xor ecx, ecx |
926 | xor ecx, ecx |
939 | test eax, 1 shl 22 |
927 | test eax, 1 shl 22 |
940 | jnz .error |
928 | jnz .error |
941 | test byte [ebx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], 1 |
929 | test byte [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1 |
942 | jz .notify |
930 | jz .notify |
943 | cmp edx, [ebx+usb_gtd.Length] |
931 | cmp edx, [ebx+usb_gtd.Length] |
944 | jz .notify |
932 | jz .notify |
945 | .error: |
933 | .error: |
946 | ; 5. There was an error while processing this packet. |
934 | ; 5. There was an error while processing this packet. |
947 | ; The hardware has stopped processing the queue. |
935 | ; The hardware has stopped processing the queue. |
948 | DEBUGF 1,'K : TD failed:\n' |
936 | DEBUGF 1,'K : TD failed:\n' |
949 | if uhci_gtd.SoftwarePart <> 20 |
937 | if sizeof.uhci_gtd <> 20 |
950 | .err modify offsets for debug output |
938 | .err modify offsets for debug output |
951 | end if |
939 | end if |
952 | DEBUGF 1,'K : %x %x %x %x\n',[ebx-20],[ebx-16],[ebx-12],[ebx-8] |
940 | DEBUGF 1,'K : %x %x %x %x\n',[ebx-20],[ebx-16],[ebx-12],[ebx-8] |
953 | DEBUGF 1,'K : %x %x %x %x\n',[ebx-4],[ebx],[ebx+4],[ebx+8] |
941 | DEBUGF 1,'K : %x %x %x %x\n',[ebx-4],[ebx],[ebx+4],[ebx+8] |
954 | ; 5a. Save the status and length. |
942 | ; 5a. Save the status and length. |
955 | push edx |
943 | push edx |
956 | push eax |
944 | push eax |
957 | mov eax, [ebx+usb_gtd.Pipe] |
945 | mov eax, [ebx+usb_gtd.Pipe] |
958 | DEBUGF 1,'K : pipe: %x %x\n',[eax+0-uhci_pipe.SoftwarePart],[eax+4-uhci_pipe.SoftwarePart] |
946 | DEBUGF 1,'K : pipe: %x %x\n',[eax+0-sizeof.uhci_pipe],[eax+4-sizeof.uhci_pipe] |
959 | ; 5b. Store the current TD as an error packet. |
947 | ; 5b. Store the current TD as an error packet. |
960 | ; If an error packet is already stored for this pipe, |
948 | ; If an error packet is already stored for this pipe, |
961 | ; it is definitely not used already, so free the old packet. |
949 | ; it is definitely not used already, so free the old packet. |
962 | mov eax, [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart] |
950 | mov eax, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe] |
963 | test eax, eax |
951 | test eax, eax |
964 | jz @f |
952 | jz @f |
965 | stdcall uhci_free_td, eax |
953 | stdcall uhci_free_td, eax |
966 | @@: |
954 | @@: |
967 | mov eax, [ebx+usb_gtd.Pipe] |
955 | mov eax, [ebx+usb_gtd.Pipe] |
968 | mov [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart], ebx |
956 | mov [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe], ebx |
969 | ; 5c. Traverse the list of descriptors looking for the final packet |
957 | ; 5c. Traverse the list of descriptors looking for the final packet |
970 | ; for this transfer. |
958 | ; for this transfer. |
971 | ; Free and unlink non-final descriptors, except the current one. |
959 | ; Free and unlink non-final descriptors, except the current one. |
972 | ; Final descriptor will be freed in step 7. |
960 | ; Final descriptor will be freed in step 7. |
973 | call usb_is_final_packet |
961 | call usb_is_final_packet |
Line 1017... | Line 1005... | ||
1017 | ; as short-packet-is-error to stop controller from further processing |
1005 | ; as short-packet-is-error to stop controller from further processing |
1018 | ; of that stage; we need to restart processing from a TD following the last. |
1006 | ; of that stage; we need to restart processing from a TD following the last. |
1019 | ; After that, go to step 6 with ecx = 0 (no error). |
1007 | ; After that, go to step 6 with ecx = 0 (no error). |
1020 | cmp ecx, USB_STATUS_UNDERRUN |
1008 | cmp ecx, USB_STATUS_UNDERRUN |
1021 | jnz @f |
1009 | jnz @f |
1022 | test byte [ebx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], 1 |
1010 | test byte [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1 |
1023 | jnz @f |
1011 | jnz @f |
1024 | ; The controller has stopped this queue on the error packet. |
1012 | ; The controller has stopped this queue on the error packet. |
1025 | ; Update uhci_pipe.HeadTD to point to the next packet in the queue. |
1013 | ; Update uhci_pipe.HeadTD to point to the next packet in the queue. |
1026 | call uhci_fix_toggle |
1014 | call uhci_fix_toggle |
1027 | xor ecx, ecx |
1015 | xor ecx, ecx |
1028 | .control: |
1016 | .control: |
1029 | mov eax, [ebx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart] |
1017 | mov eax, [ebx+uhci_gtd.NextTD-sizeof.uhci_gtd] |
1030 | and al, not 0xF |
1018 | and al, not 0xF |
1031 | mov edx, [ebx+usb_gtd.Pipe] |
1019 | mov edx, [ebx+usb_gtd.Pipe] |
1032 | mov [edx+uhci_pipe.HeadTD-uhci_pipe.SoftwarePart], eax |
1020 | mov [edx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax |
1033 | pop edx ; length |
1021 | pop edx ; length |
1034 | jmp .notify |
1022 | jmp .notify |
1035 | @@: |
1023 | @@: |
1036 | ; 5f. Abort the entire transfer. |
1024 | ; 5f. Abort the entire transfer. |
1037 | ; There are two cases: either there is only one transfer stage |
1025 | ; There are two cases: either there is only one transfer stage |
Line 1045... | Line 1033... | ||
1045 | jnz .normal |
1033 | jnz .normal |
1046 | ; We cannot free ErrorTD yet, it could still be used by the hardware. |
1034 | ; We cannot free ErrorTD yet, it could still be used by the hardware. |
1047 | push ecx |
1035 | push ecx |
1048 | mov eax, [ebx+usb_gtd.Pipe] |
1036 | mov eax, [ebx+usb_gtd.Pipe] |
1049 | push [ebx+usb_gtd.NextVirt] |
1037 | push [ebx+usb_gtd.NextVirt] |
1050 | cmp ebx, [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart] |
1038 | cmp ebx, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe] |
1051 | jz @f |
1039 | jz @f |
1052 | stdcall uhci_free_td, ebx |
1040 | stdcall uhci_free_td, ebx |
1053 | @@: |
1041 | @@: |
1054 | pop ebx |
1042 | pop ebx |
1055 | call usb_unlink_td |
1043 | call usb_unlink_td |
Line 1063... | Line 1051... | ||
1063 | ; support functional stall as well, but this is not recommended."). |
1051 | ; support functional stall as well, but this is not recommended."). |
1064 | mov edx, [ebx+usb_gtd.Pipe] |
1052 | mov edx, [ebx+usb_gtd.Pipe] |
1065 | cmp [edx+usb_pipe.Type], CONTROL_PIPE |
1053 | cmp [edx+usb_pipe.Type], CONTROL_PIPE |
1066 | jz .control |
1054 | jz .control |
1067 | ; Bulk/interrupt transfer; halt the queue. |
1055 | ; Bulk/interrupt transfer; halt the queue. |
1068 | mov eax, [ebx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart] |
1056 | mov eax, [ebx+uhci_gtd.NextTD-sizeof.uhci_gtd] |
1069 | and al, not 0xF |
1057 | and al, not 0xF |
1070 | inc eax ; set Halted bit |
1058 | inc eax ; set Halted bit |
1071 | mov [edx+uhci_pipe.HeadTD-uhci_pipe.SoftwarePart], eax |
1059 | mov [edx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax |
1072 | pop edx ; restore length saved in step 5a |
1060 | pop edx ; restore length saved in step 5a |
1073 | .notify: |
1061 | .notify: |
1074 | ; 6. Either the descriptor in ebx was processed without errors, |
1062 | ; 6. Either the descriptor in ebx was processed without errors, |
1075 | ; or all necessary error actions were taken and ebx points to the last |
1063 | ; or all necessary error actions were taken and ebx points to the last |
1076 | ; related descriptor. |
1064 | ; related descriptor. |
Line 1092... | Line 1080... | ||
1092 | ; 7. Free the current descriptor (if allowed) and return the next one. |
1080 | ; 7. Free the current descriptor (if allowed) and return the next one. |
1093 | ; 7a. Save pointer to the next descriptor. |
1081 | ; 7a. Save pointer to the next descriptor. |
1094 | push [ebx+usb_gtd.NextVirt] |
1082 | push [ebx+usb_gtd.NextVirt] |
1095 | ; 7b. Free the descriptor, unless it is saved as ErrorTD. |
1083 | ; 7b. Free the descriptor, unless it is saved as ErrorTD. |
1096 | mov eax, [ebx+usb_gtd.Pipe] |
1084 | mov eax, [ebx+usb_gtd.Pipe] |
1097 | cmp [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart], ebx |
1085 | cmp [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe], ebx |
1098 | jz @f |
1086 | jz @f |
1099 | stdcall uhci_free_td, ebx |
1087 | stdcall uhci_free_td, ebx |
1100 | @@: |
1088 | @@: |
1101 | ; 7c. Restore pointer to the next descriptor and return. |
1089 | ; 7c. Restore pointer to the next descriptor and return. |
1102 | pop ebx |
1090 | pop ebx |
Line 1116... | Line 1104... | ||
1116 | cmp [ecx+usb_pipe.Type], CONTROL_PIPE |
1104 | cmp [ecx+usb_pipe.Type], CONTROL_PIPE |
1117 | jz .nothing |
1105 | jz .nothing |
1118 | ; 2. The hardware expects next packet with toggle = (ErrorTD.toggle xor 1), |
1106 | ; 2. The hardware expects next packet with toggle = (ErrorTD.toggle xor 1), |
1119 | ; the current value in next packet is (ebx.toggle xor 1). |
1107 | ; the current value in next packet is (ebx.toggle xor 1). |
1120 | ; Nothing to do if ErrorTD.toggle == ebx.toggle. |
1108 | ; Nothing to do if ErrorTD.toggle == ebx.toggle. |
1121 | mov eax, [ecx+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart] |
1109 | mov eax, [ecx+uhci_pipe.ErrorTD-sizeof.uhci_pipe] |
1122 | mov eax, [eax+uhci_gtd.Token-uhci_gtd.SoftwarePart] |
1110 | mov eax, [eax+uhci_gtd.Token-sizeof.uhci_gtd] |
1123 | xor eax, [ebx+uhci_gtd.Token-uhci_gtd.SoftwarePart] |
1111 | xor eax, [ebx+uhci_gtd.Token-sizeof.uhci_gtd] |
1124 | test eax, 1 shl 19 |
1112 | test eax, 1 shl 19 |
1125 | jz .nothing |
1113 | jz .nothing |
1126 | ; 3. Lock the transfer queue. |
1114 | ; 3. Lock the transfer queue. |
1127 | add ecx, usb_pipe.Lock |
1115 | add ecx, usb_pipe.Lock |
1128 | call mutex_lock |
1116 | call mutex_lock |
1129 | ; 4. Flip the toggle bit in all packets from ebx.NextVirt to ecx.LastTD |
1117 | ; 4. Flip the toggle bit in all packets from ebx.NextVirt to ecx.LastTD |
1130 | ; (inclusive). |
1118 | ; (inclusive). |
1131 | mov eax, [ebx+usb_gtd.NextVirt] |
1119 | mov eax, [ebx+usb_gtd.NextVirt] |
1132 | .loop: |
1120 | .loop: |
1133 | xor byte [eax+uhci_gtd.Token-uhci_gtd.SoftwarePart+2], 1 shl (19-16) |
1121 | xor byte [eax+uhci_gtd.Token-sizeof.uhci_gtd+2], 1 shl (19-16) |
1134 | cmp eax, [ecx+usb_pipe.LastTD-usb_pipe.Lock] |
1122 | cmp eax, [ecx+usb_pipe.LastTD-usb_pipe.Lock] |
1135 | mov eax, [eax+usb_gtd.NextVirt] |
1123 | mov eax, [eax+usb_gtd.NextVirt] |
1136 | jnz .loop |
1124 | jnz .loop |
1137 | ; 5. Flip the toggle bit in uhci_pipe structure. |
1125 | ; 5. Flip the toggle bit in uhci_pipe structure. |
1138 | xor byte [ecx+uhci_pipe.Token-uhci_pipe.SoftwarePart-usb_pipe.Lock+2], 1 shl (19-16) |
1126 | xor byte [ecx+uhci_pipe.Token-sizeof.uhci_pipe-usb_pipe.Lock+2], 1 shl (19-16) |
1139 | or dword [ecx+uhci_pipe.Token-uhci_pipe.SoftwarePart-usb_pipe.Lock], eax |
1127 | or dword [ecx+uhci_pipe.Token-sizeof.uhci_pipe-usb_pipe.Lock], eax |
1140 | ; 6. Unlock the transfer queue. |
1128 | ; 6. Unlock the transfer queue. |
1141 | call mutex_unlock |
1129 | call mutex_unlock |
1142 | .nothing: |
1130 | .nothing: |
1143 | ret |
1131 | ret |
1144 | endp |
1132 | endp |
Line 1336... | Line 1324... | ||
1336 | 1324 | ||
1337 | ; This procedure is called from usb_set_address_callback |
1325 | ; This procedure is called from usb_set_address_callback |
1338 | ; and stores USB device address in the uhci_pipe structure. |
1326 | ; and stores USB device address in the uhci_pipe structure. |
1339 | ; in: esi -> usb_controller, ebx -> usb_pipe, cl = address |
1327 | ; in: esi -> usb_controller, ebx -> usb_pipe, cl = address |
1340 | proc uhci_set_device_address |
1328 | proc uhci_set_device_address |
1341 | mov byte [ebx+uhci_pipe.Token+1-uhci_pipe.SoftwarePart], cl |
1329 | mov byte [ebx+uhci_pipe.Token+1-sizeof.uhci_pipe], cl |
1342 | call usb_subscription_done |
1330 | call usb_subscription_done |
1343 | ret |
1331 | ret |
Line 1344... | Line 1332... | ||
1344 | endp |
1332 | endp |
1345 | 1333 | ||
1346 | ; This procedure returns USB device address from the uhci_pipe structure. |
1334 | ; This procedure returns USB device address from the uhci_pipe structure. |
1347 | ; in: esi -> usb_controller, ebx -> usb_pipe |
1335 | ; in: esi -> usb_controller, ebx -> usb_pipe |
1348 | ; out: eax = endpoint address |
1336 | ; out: eax = endpoint address |
1349 | proc uhci_get_device_address |
1337 | proc uhci_get_device_address |
1350 | mov al, byte [ebx+uhci_pipe.Token+1-uhci_pipe.SoftwarePart] |
1338 | mov al, byte [ebx+uhci_pipe.Token+1-sizeof.uhci_pipe] |
1351 | and eax, 7Fh |
1339 | and eax, 7Fh |
Line 1352... | Line 1340... | ||
1352 | ret |
1340 | ret |
Line 1370... | Line 1358... | ||
1370 | ; stores the packet size in uhci_pipe structure. |
1358 | ; stores the packet size in uhci_pipe structure. |
1371 | ; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size |
1359 | ; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size |
1372 | proc uhci_set_endpoint_packet_size |
1360 | proc uhci_set_endpoint_packet_size |
1373 | dec ecx |
1361 | dec ecx |
1374 | shl ecx, 21 |
1362 | shl ecx, 21 |
1375 | and [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart], (1 shl 21) - 1 |
1363 | and [ebx+uhci_pipe.Token-sizeof.uhci_pipe], (1 shl 21) - 1 |
1376 | or [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart], ecx |
1364 | or [ebx+uhci_pipe.Token-sizeof.uhci_pipe], ecx |
1377 | ; uhci_pipe.Token field is purely for software bookkeeping and does not affect |
1365 | ; uhci_pipe.Token field is purely for software bookkeeping and does not affect |
1378 | ; the hardware; thus, we can continue initialization immediately. |
1366 | ; the hardware; thus, we can continue initialization immediately. |
1379 | call usb_subscription_done |
1367 | call usb_subscription_done |
1380 | ret |
1368 | ret |
1381 | endp |
1369 | endp |
Line 1393... | Line 1381... | ||
1393 | .maxpacket dd ? |
1381 | .maxpacket dd ? |
1394 | .type dd ? |
1382 | .type dd ? |
1395 | .interval dd ? |
1383 | .interval dd ? |
1396 | end virtual |
1384 | end virtual |
1397 | ; 1. Initialize ErrorTD to zero. |
1385 | ; 1. Initialize ErrorTD to zero. |
1398 | and [edi+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart], 0 |
1386 | and [edi+uhci_pipe.ErrorTD-sizeof.uhci_pipe], 0 |
1399 | ; 2. Initialize HeadTD to the physical address of the first TD. |
1387 | ; 2. Initialize HeadTD to the physical address of the first TD. |
1400 | push eax ; store pointer to the first TD for step ? |
1388 | push eax ; store pointer to the first TD for step 4 |
1401 | sub eax, uhci_gtd.SoftwarePart |
1389 | sub eax, sizeof.uhci_gtd |
1402 | call get_phys_addr |
1390 | call get_phys_addr |
1403 | mov [edi+uhci_pipe.HeadTD-uhci_pipe.SoftwarePart], eax |
1391 | mov [edi+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax |
1404 | ; 3. Initialize Token field: |
1392 | ; 3. Initialize Token field: |
1405 | ; take DeviceAddress and LowSpeedDevice from the parent pipe, |
1393 | ; take DeviceAddress and LowSpeedDevice from the parent pipe, |
1406 | ; take Endpoint and MaximumLength fields from API arguments, |
1394 | ; take Endpoint and MaximumLength fields from API arguments, |
1407 | ; set PID depending on pipe type and provided pipe direction, |
1395 | ; set PID depending on pipe type and provided pipe direction, |
1408 | ; set DataToggle to zero. |
1396 | ; set DataToggle to zero. |
1409 | mov eax, [ecx+uhci_pipe.Token-uhci_pipe.SoftwarePart] |
1397 | mov eax, [ecx+uhci_pipe.Token-sizeof.uhci_pipe] |
1410 | and eax, 0x107F00 ; keep DeviceAddress and LowSpeedDevice |
1398 | and eax, 0x107F00 ; keep DeviceAddress and LowSpeedDevice |
1411 | mov edx, [.endpoint] |
1399 | mov edx, [.endpoint] |
1412 | and edx, 15 |
1400 | and edx, 15 |
1413 | shl edx, 15 |
1401 | shl edx, 15 |
1414 | or eax, edx |
1402 | or eax, edx |
Line 1422... | Line 1410... | ||
1422 | mov al, USB_PID_OUT |
1410 | mov al, USB_PID_OUT |
1423 | test byte [.endpoint], 80h |
1411 | test byte [.endpoint], 80h |
1424 | jz @f |
1412 | jz @f |
1425 | mov al, USB_PID_IN |
1413 | mov al, USB_PID_IN |
1426 | @@: |
1414 | @@: |
1427 | mov [edi+uhci_pipe.Token-uhci_pipe.SoftwarePart], eax |
1415 | mov [edi+uhci_pipe.Token-sizeof.uhci_pipe], eax |
1428 | ; 4. Initialize the first TD: |
1416 | ; 4. Initialize the first TD: |
1429 | ; copy Token from uhci_pipe.Token zeroing reserved bit 20, |
1417 | ; copy Token from uhci_pipe.Token zeroing reserved bit 20, |
1430 | ; set ControlStatus for future transfers, bit make it inactive, |
1418 | ; set ControlStatus for future transfers, bit make it inactive, |
1431 | ; set bit 0 in NextTD = "no next TD". |
1419 | ; set bit 0 in NextTD = "no next TD", |
- | 1420 | ; zero OrigBufferInfo. |
|
1432 | pop edx ; restore pointer saved in step 2 |
1421 | pop edx ; restore pointer saved in step 2 |
1433 | mov [edx+uhci_gtd.Token-uhci_gtd.SoftwarePart], eax |
1422 | mov [edx+uhci_gtd.Token-sizeof.uhci_gtd], eax |
1434 | and byte [edx+uhci_gtd.Token+2-uhci_gtd.SoftwarePart], not (1 shl (20-16)) |
1423 | and byte [edx+uhci_gtd.Token+2-sizeof.uhci_gtd], not (1 shl (20-16)) |
1435 | and eax, 1 shl 20 |
1424 | and eax, 1 shl 20 |
1436 | shl eax, 6 |
1425 | shl eax, 6 |
1437 | or eax, UHCI_INVALID_LENGTH + (3 shl 27) |
1426 | or eax, UHCI_INVALID_LENGTH + (3 shl 27) |
1438 | ; not processed, inactive, allow 3 errors |
1427 | ; not processed, inactive, allow 3 errors |
- | 1428 | and [edx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 0 |
|
1439 | mov [edx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart], eax |
1429 | mov [edx+uhci_gtd.ControlStatus-sizeof.uhci_gtd], eax |
1440 | mov [edx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], 1 |
1430 | mov [edx+uhci_gtd.NextTD-sizeof.uhci_gtd], 1 |
1441 | ; 5. Select the corresponding list and insert to the list. |
1431 | ; 5. Select the corresponding list and insert to the list. |
1442 | ; 5a. Use Control list for control pipes, Bulk list for bulk pipes. |
1432 | ; 5a. Use Control list for control pipes, Bulk list for bulk pipes. |
1443 | lea edx, [esi+uhci_controller.ControlED.SoftwarePart-sizeof.uhci_controller] |
1433 | lea edx, [esi+uhci_controller.ControlED.SoftwarePart-sizeof.uhci_controller] |
1444 | cmp [.type], BULK_PIPE |
1434 | cmp [.type], BULK_PIPE |
1445 | jb .insert ; control pipe |
1435 | jb .insert ; control pipe |
Line 1469... | Line 1459... | ||
1469 | mov [ecx+usb_pipe.PrevVirt], edi |
1459 | mov [ecx+usb_pipe.PrevVirt], edi |
1470 | mov [edx+usb_pipe.NextVirt], edi |
1460 | mov [edx+usb_pipe.NextVirt], edi |
1471 | ; 5d. Insert in the hardware list: copy previous NextQH to the new pipe, |
1461 | ; 5d. Insert in the hardware list: copy previous NextQH to the new pipe, |
1472 | ; store the physical address of the new pipe to previous NextQH. |
1462 | ; store the physical address of the new pipe to previous NextQH. |
1473 | mov ecx, [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart] |
1463 | mov ecx, [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart] |
1474 | mov [edi+uhci_pipe.NextQH-uhci_pipe.SoftwarePart], ecx |
1464 | mov [edi+uhci_pipe.NextQH-sizeof.uhci_pipe], ecx |
1475 | lea eax, [edi-uhci_pipe.SoftwarePart] |
1465 | lea eax, [edi-sizeof.uhci_pipe] |
1476 | call get_phys_addr |
1466 | call get_phys_addr |
1477 | inc eax |
1467 | inc eax |
1478 | inc eax |
1468 | inc eax |
1479 | mov [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart], eax |
1469 | mov [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart], eax |
1480 | ; 6. Return with nonzero eax. |
1470 | ; 6. Return with nonzero eax. |
Line 1484... | Line 1474... | ||
1484 | ret |
1474 | ret |
1485 | endp |
1475 | endp |
Line 1486... | Line 1476... | ||
1486 | 1476 | ||
1487 | ; This procedure is called when a pipe is closing (either due to API call |
1477 | ; This procedure is called when a pipe is closing (either due to API call |
1488 | ; or due to disconnect); it unlinks a pipe from the corresponding list. |
1478 | ; or due to disconnect); it unlinks a pipe from the corresponding list. |
1489 | if uhci_static_ep.SoftwarePart <> uhci_pipe.SoftwarePart |
1479 | if uhci_static_ep.SoftwarePart <> sizeof.uhci_pipe |
1490 | .err uhci_unlink_pipe assumes that uhci_static_ep.SoftwarePart == uhci_pipe.SoftwarePart |
1480 | .err uhci_unlink_pipe assumes that uhci_static_ep.SoftwarePart == sizeof.uhci_pipe |
1491 | end if |
1481 | end if |
1492 | proc uhci_unlink_pipe |
1482 | proc uhci_unlink_pipe |
1493 | cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE |
1483 | cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE |
1494 | jnz @f |
1484 | jnz @f |
1495 | mov eax, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart] |
1485 | mov eax, [ebx+uhci_pipe.Token-sizeof.uhci_pipe] |
1496 | cmp al, USB_PID_IN |
1486 | cmp al, USB_PID_IN |
1497 | setz ch |
1487 | setz ch |
1498 | bt eax, 20 |
1488 | bt eax, 20 |
1499 | setc cl |
1489 | setc cl |
Line 1508... | Line 1498... | ||
1508 | mov eax, [ebx+usb_pipe.PrevVirt] |
1498 | mov eax, [ebx+usb_pipe.PrevVirt] |
1509 | mov [edx+usb_pipe.PrevVirt], eax |
1499 | mov [edx+usb_pipe.PrevVirt], eax |
1510 | mov [eax+usb_pipe.NextVirt], edx |
1500 | mov [eax+usb_pipe.NextVirt], edx |
1511 | ; Note: eax could be either usb_pipe or usb_static_ep; |
1501 | ; Note: eax could be either usb_pipe or usb_static_ep; |
1512 | ; fortunately, NextQH and SoftwarePart have same offsets in both. |
1502 | ; fortunately, NextQH and SoftwarePart have same offsets in both. |
1513 | mov edx, [ebx+uhci_pipe.NextQH-uhci_pipe.SoftwarePart] |
1503 | mov edx, [ebx+uhci_pipe.NextQH-sizeof.uhci_pipe] |
1514 | mov [eax+uhci_pipe.NextQH-uhci_pipe.SoftwarePart], edx |
1504 | mov [eax+uhci_pipe.NextQH-sizeof.uhci_pipe], edx |
1515 | ret |
1505 | ret |
1516 | endp |
1506 | endp |
Line 1517... | Line 1507... | ||
1517 | 1507 | ||
1518 | ; Free memory associated with pipe. |
1508 | ; Free memory associated with pipe. |
1519 | ; For UHCI, this includes usb_pipe structure and ErrorTD, if present. |
1509 | ; For UHCI, this includes usb_pipe structure and ErrorTD, if present. |
1520 | proc uhci_free_pipe |
1510 | proc uhci_free_pipe |
1521 | mov eax, [esp+4] |
1511 | mov eax, [esp+4] |
1522 | mov eax, [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart] |
1512 | mov eax, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe] |
1523 | test eax, eax |
1513 | test eax, eax |
1524 | jz @f |
1514 | jz @f |
1525 | stdcall uhci_free_td, eax |
1515 | stdcall uhci_free_td, eax |
1526 | @@: |
1516 | @@: |
Line 1542... | Line 1532... | ||
1542 | mov [origTD], eax |
1532 | mov [origTD], eax |
1543 | ; In UHCI one TD describes one packet, transfers should be split into parts |
1533 | ; In UHCI one TD describes one packet, transfers should be split into parts |
1544 | ; with size <= endpoint max packet size. |
1534 | ; with size <= endpoint max packet size. |
1545 | ; 2. Get the maximum packet size for endpoint from uhci_pipe.Token |
1535 | ; 2. Get the maximum packet size for endpoint from uhci_pipe.Token |
1546 | ; and generate Token field for TDs. |
1536 | ; and generate Token field for TDs. |
1547 | mov edi, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart] |
1537 | mov edi, [ebx+uhci_pipe.Token-sizeof.uhci_pipe] |
1548 | mov eax, edi |
1538 | mov eax, edi |
1549 | shr edi, 21 |
1539 | shr edi, 21 |
1550 | inc edi |
1540 | inc edi |
1551 | ; zero packet size (it will be set for every packet individually), |
1541 | ; zero packet size (it will be set for every packet individually), |
1552 | ; zero reserved bit 20, |
1542 | ; zero reserved bit 20, |
Line 1600... | Line 1590... | ||
1600 | ; if one of them will be short, the software intervention is needed |
1590 | ; if one of them will be short, the software intervention is needed |
1601 | ; to skip remaining packets; uhci_process_finalized_td will handle this |
1591 | ; to skip remaining packets; uhci_process_finalized_td will handle this |
1602 | ; transparently to the caller. |
1592 | ; transparently to the caller. |
1603 | test [flags], 1 |
1593 | test [flags], 1 |
1604 | jz @f |
1594 | jz @f |
1605 | and byte [ecx+uhci_gtd.ControlStatus+3-uhci_gtd.SoftwarePart], not (1 shl (29-24)) |
1595 | and byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], not (1 shl (29-24)) |
1606 | and byte [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], not 1 |
1596 | and byte [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], not 1 |
1607 | @@: |
1597 | @@: |
1608 | ; 6. Update toggle bit in uhci_pipe structure from current value of [token]. |
1598 | ; 6. Update toggle bit in uhci_pipe structure from current value of [token]. |
1609 | mov edx, [token] |
1599 | mov edx, [token] |
1610 | xor edx, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart] |
1600 | xor edx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe] |
1611 | and edx, 1 shl 19 |
1601 | and edx, 1 shl 19 |
1612 | xor [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart], edx |
1602 | xor [ebx+uhci_pipe.Token-sizeof.uhci_pipe], edx |
1613 | .nothing: |
1603 | .nothing: |
1614 | ret |
1604 | ret |
1615 | .fail: |
1605 | .fail: |
1616 | mov edi, uhci_hardware_func |
1606 | mov edi, uhci_hardware_func |
1617 | mov eax, [td] |
1607 | mov eax, [td] |
Line 1650... | Line 1640... | ||
1650 | test edx, -0x1000 |
1640 | test edx, -0x1000 |
1651 | jz .notempbuf |
1641 | jz .notempbuf |
1652 | ; 1c. We need a temporary buffer. Allocate [packetSize]*2 bytes, so that |
1642 | ; 1c. We need a temporary buffer. Allocate [packetSize]*2 bytes, so that |
1653 | ; there must be [packetSize] bytes on one page, |
1643 | ; there must be [packetSize] bytes on one page, |
1654 | ; plus space for a header uhci_original_buffer. |
1644 | ; plus space for a header uhci_original_buffer. |
1655 | push ebx |
- | |
1656 | mov eax, [.packetSize] |
1645 | mov eax, [.packetSize] |
1657 | add eax, eax |
1646 | add eax, eax |
1658 | add eax, sizeof.uhci_original_buffer |
1647 | add eax, sizeof.uhci_original_buffer |
1659 | call malloc |
1648 | call malloc |
1660 | pop ebx |
- | |
1661 | ; 1d. If failed, return zero. |
1649 | ; 1d. If failed, return zero. |
1662 | test eax, eax |
1650 | test eax, eax |
1663 | jz .nothing |
1651 | jz .nothing |
1664 | ; 1e. Test whether [.packetSize] bytes starting from |
1652 | ; 1e. Test whether [.packetSize] bytes starting from |
1665 | ; eax + sizeof.uhci_original_buffer are in the same page. |
1653 | ; eax + sizeof.uhci_original_buffer are in the same page. |
Line 1710... | Line 1698... | ||
1710 | call usb_init_transfer |
1698 | call usb_init_transfer |
1711 | ; 4. Initialize the next TD: |
1699 | ; 4. Initialize the next TD: |
1712 | ; mark it as last one (this will be changed when further packets will be |
1700 | ; mark it as last one (this will be changed when further packets will be |
1713 | ; allocated), copy Token field from uhci_pipe.Token zeroing bit 20, |
1701 | ; allocated), copy Token field from uhci_pipe.Token zeroing bit 20, |
1714 | ; generate ControlStatus field, mark as Active |
1702 | ; generate ControlStatus field, mark as Active |
1715 | ; (for last descriptor, this will be changed by uhci_insert_transfer). |
1703 | ; (for last descriptor, this will be changed by uhci_insert_transfer), |
- | 1704 | ; zero OrigBufferInfo (otherwise uhci_free_td would try to free it). |
|
- | 1705 | and [eax+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 0 |
|
1716 | mov [eax+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], 1 ; no next TD |
1706 | mov [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 1 ; no next TD |
1717 | mov edx, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart] |
1707 | mov edx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe] |
1718 | mov [eax+uhci_gtd.Token-uhci_gtd.SoftwarePart], edx |
1708 | mov [eax+uhci_gtd.Token-sizeof.uhci_gtd], edx |
1719 | and byte [eax+uhci_gtd.Token+2-uhci_gtd.SoftwarePart], not (1 shl (20-16)) |
1709 | and byte [eax+uhci_gtd.Token+2-sizeof.uhci_gtd], not (1 shl (20-16)) |
1720 | and edx, 1 shl 20 |
1710 | and edx, 1 shl 20 |
1721 | shl edx, 6 |
1711 | shl edx, 6 |
1722 | or edx, UHCI_INVALID_LENGTH + (1 shl 23) + (3 shl 27) |
1712 | or edx, UHCI_INVALID_LENGTH + (1 shl 23) + (3 shl 27) |
1723 | ; not processed, active, allow 3 errors |
1713 | ; not processed, active, allow 3 errors |
1724 | mov [eax+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart], edx |
1714 | mov [eax+uhci_gtd.ControlStatus-sizeof.uhci_gtd], edx |
1725 | ; 5. Initialize remaining fields of the current TD. |
1715 | ; 5. Initialize remaining fields of the current TD. |
1726 | ; 5a. Store pointer to the buffer allocated in step 1 (or zero). |
1716 | ; 5a. Store pointer to the buffer allocated in step 1 (or zero). |
1727 | pop [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart] |
1717 | pop [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd] |
1728 | ; 5b. Store physical address of the next TD. |
1718 | ; 5b. Store physical address of the next TD. |
1729 | push eax |
1719 | push eax |
1730 | sub eax, uhci_gtd.SoftwarePart |
1720 | sub eax, sizeof.uhci_gtd |
1731 | call get_phys_addr |
1721 | call get_phys_addr |
1732 | ; use Depth traversal unless this is the first TD in the transfer stage; |
1722 | ; for Control/Bulk pipes, use Depth traversal unless this is the first TD |
- | 1723 | ; in the transfer stage; |
|
1733 | ; uhci_insert_transfer will set Depth traversal for the first TD and clear |
1724 | ; uhci_insert_transfer will set Depth traversal for the first TD and clear |
1734 | ; it in the last TD |
1725 | ; it in the last TD |
- | 1726 | test [ebx+usb_pipe.Type], 1 |
|
- | 1727 | jnz @f |
|
1735 | cmp ecx, [ebx+usb_pipe.LastTD] |
1728 | cmp ecx, [ebx+usb_pipe.LastTD] |
1736 | jz @f |
1729 | jz @f |
1737 | or eax, 4 |
1730 | or eax, 4 |
1738 | @@: |
1731 | @@: |
1739 | mov [ecx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], eax |
1732 | mov [ecx+uhci_gtd.NextTD-sizeof.uhci_gtd], eax |
1740 | ; 5c. Store physical address of the buffer: zero if no data present, |
1733 | ; 5c. Store physical address of the buffer: zero if no data present, |
1741 | ; the temporary buffer if it was allocated, the given buffer otherwise. |
1734 | ; the temporary buffer if it was allocated, the given buffer otherwise. |
1742 | xor eax, eax |
1735 | xor eax, eax |
1743 | cmp [.packetSize], eax |
1736 | cmp [.packetSize], eax |
1744 | jz .hasphysbuf |
1737 | jz .hasphysbuf |
1745 | mov eax, [.buffer] |
1738 | mov eax, [.buffer] |
1746 | mov edx, [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart] |
1739 | mov edx, [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd] |
1747 | test edx, edx |
1740 | test edx, edx |
1748 | jz @f |
1741 | jz @f |
1749 | mov eax, [edx+uhci_original_buffer.UsedBuffer] |
1742 | mov eax, [edx+uhci_original_buffer.UsedBuffer] |
1750 | @@: |
1743 | @@: |
1751 | call get_phys_addr |
1744 | call get_phys_addr |
1752 | .hasphysbuf: |
1745 | .hasphysbuf: |
1753 | mov [ecx+uhci_gtd.Buffer-uhci_gtd.SoftwarePart], eax |
1746 | mov [ecx+uhci_gtd.Buffer-sizeof.uhci_gtd], eax |
1754 | ; 5d. For IN transfers, disallow short packets. |
1747 | ; 5d. For IN transfers, disallow short packets. |
1755 | ; This will be overridden, if needed, by uhci_alloc_transfer. |
1748 | ; This will be overridden, if needed, by uhci_alloc_transfer. |
1756 | mov eax, [.token] |
1749 | mov eax, [.token] |
1757 | mov edx, [.packetSize] |
1750 | mov edx, [.packetSize] |
1758 | dec edx |
1751 | dec edx |
1759 | cmp al, USB_PID_IN |
1752 | cmp al, USB_PID_IN |
1760 | jnz @f |
1753 | jnz @f |
1761 | or byte [ecx+uhci_gtd.ControlStatus+3-uhci_gtd.SoftwarePart], 1 shl (29-24) ; disallow short packets |
1754 | or byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (29-24) ; disallow short packets |
1762 | or byte [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], 1 |
1755 | or byte [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1 |
1763 | @@: |
1756 | @@: |
1764 | ; 5e. Get Token field: combine [.token] with [.packetSize]. |
1757 | ; 5e. Get Token field: combine [.token] with [.packetSize]. |
1765 | shl edx, 21 |
1758 | shl edx, 21 |
1766 | or edx, eax |
1759 | or edx, eax |
1767 | mov [ecx+uhci_gtd.Token-uhci_gtd.SoftwarePart], edx |
1760 | mov [ecx+uhci_gtd.Token-sizeof.uhci_gtd], edx |
1768 | ; 6. Flip toggle bit in [.token]. |
1761 | ; 6. Flip toggle bit in [.token]. |
1769 | xor eax, 1 shl 19 |
1762 | xor eax, 1 shl 19 |
1770 | mov [.token], eax |
1763 | mov [.token], eax |
1771 | ; 7. Return pointer to the next TD. |
1764 | ; 7. Return pointer to the next TD. |
1772 | pop eax |
1765 | pop eax |
Line 1783... | Line 1776... | ||
1783 | ; and activates the transfer which was previously allocated by |
1776 | ; and activates the transfer which was previously allocated by |
1784 | ; uhci_alloc_transfer. |
1777 | ; uhci_alloc_transfer. |
1785 | ; ecx -> last descriptor for the transfer, ebx -> usb_pipe |
1778 | ; ecx -> last descriptor for the transfer, ebx -> usb_pipe |
1786 | proc uhci_insert_transfer |
1779 | proc uhci_insert_transfer |
1787 | ; DEBUGF 1,'K : uhci_insert_transfer: eax=%x, ecx=%x, [esp+4]=%x\n',eax,ecx,[esp+4] |
1780 | ; DEBUGF 1,'K : uhci_insert_transfer: eax=%x, ecx=%x, [esp+4]=%x\n',eax,ecx,[esp+4] |
1788 | and byte [eax+uhci_gtd.ControlStatus+2-uhci_gtd.SoftwarePart], not (1 shl (23-16)) ; clear Active bit |
1781 | and byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], not (1 shl (23-16)) ; clear Active bit |
1789 | or byte [ecx+uhci_gtd.ControlStatus+3-uhci_gtd.SoftwarePart], 1 shl (24-24) ; set InterruptOnComplete bit |
1782 | or byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (24-24) ; set InterruptOnComplete bit |
1790 | mov eax, [esp+4] |
1783 | mov eax, [esp+4] |
1791 | or byte [eax+uhci_gtd.ControlStatus+2-uhci_gtd.SoftwarePart], 1 shl (23-16) ; set Active bit |
1784 | or byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], 1 shl (23-16) ; set Active bit |
- | 1785 | test [ebx+usb_pipe.Type], 1 |
|
- | 1786 | jnz @f |
|
1792 | or byte [eax+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], 4 ; set Depth bit |
1787 | or byte [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 4 ; set Depth bit |
- | 1788 | @@: |
|
1793 | ret |
1789 | ret |
1794 | endp |
1790 | endp |
Line 1795... | Line 1791... | ||
1795 | 1791 | ||
1796 | ; Free all memory associated with one TD. |
1792 | ; Free all memory associated with one TD. |
1797 | ; For UHCI, this includes memory for uhci_gtd itself |
1793 | ; For UHCI, this includes memory for uhci_gtd itself |
1798 | ; and the temporary buffer, if present. |
1794 | ; and the temporary buffer, if present. |
1799 | proc uhci_free_td |
1795 | proc uhci_free_td |
1800 | mov eax, [esp+4] |
1796 | mov eax, [esp+4] |
1801 | mov eax, [eax+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart] |
1797 | mov eax, [eax+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd] |
1802 | and eax, not 1 |
1798 | and eax, not 1 |
1803 | jz .nobuf |
1799 | jz .nobuf |
1804 | push ebx |
1800 | push ebx |
1805 | call free |
1801 | call free |
1806 | pop ebx |
1802 | pop ebx |
1807 | .nobuf: |
1803 | .nobuf: |
1808 | sub dword [esp+4], uhci_gtd.SoftwarePart |
1804 | sub dword [esp+4], sizeof.uhci_gtd |
1809 | jmp usb_free_common |
1805 | jmp usb_free_common |