Rev 3598 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3598 | Rev 3653 | ||
---|---|---|---|
Line 42... | Line 42... | ||
42 | ; OHCI-specific part of a pipe descriptor. |
42 | ; OHCI-specific part of a pipe descriptor. |
43 | ; * This structure corresponds to the Endpoint Descriptor aka ED from the OHCI |
43 | ; * This structure corresponds to the Endpoint Descriptor aka ED from the OHCI |
44 | ; specification. |
44 | ; specification. |
45 | ; * The hardware requires 16-bytes alignment of the hardware part. |
45 | ; * The hardware requires 16-bytes alignment of the hardware part. |
46 | ; Since the allocator (usb_allocate_common) allocates memory sequentially |
46 | ; Since the allocator (usb_allocate_common) allocates memory sequentially |
47 | ; from page start (aligned on 0x1000 bytes), size of the structure must be |
47 | ; from page start (aligned on 0x1000 bytes), block size for the allocator |
48 | ; divisible by 16. |
48 | ; must be divisible by 16; usb1_allocate_endpoint ensures this. |
49 | struct ohci_pipe |
49 | struct ohci_pipe |
50 | ; All addresses are physical. |
50 | ; All addresses are physical. |
51 | Flags dd ? |
51 | Flags dd ? |
52 | ; 1. Lower 7 bits (bits 0-6) are FunctionAddress. This is the USB address of |
52 | ; 1. Lower 7 bits (bits 0-6) are FunctionAddress. This is the USB address of |
53 | ; the function containing the endpoint that this ED controls. |
53 | ; the function containing the endpoint that this ED controls. |
Line 93... | Line 93... | ||
93 | ; * The 1ms periodic list also serves Isochronous endpoints, which should be |
93 | ; * The 1ms periodic list also serves Isochronous endpoints, which should be |
94 | ; in the end of the list. |
94 | ; in the end of the list. |
95 | ; * There is no "next" list for Bulk and Control lists, they are processed |
95 | ; * There is no "next" list for Bulk and Control lists, they are processed |
96 | ; separately from others. |
96 | ; separately from others. |
97 | ; * There is no "next" list for Periodic list for 1ms interval. |
97 | ; * There is no "next" list for Periodic list for 1ms interval. |
98 | SoftwarePart rd sizeof.usb_pipe/4 |
- | |
99 | ; Software part, common for all controllers. |
- | |
100 | ends |
98 | ends |
Line 101... | Line -... | ||
101 | - | ||
102 | if sizeof.ohci_pipe mod 16 |
- | |
103 | .err ohci_pipe must be 16-bytes aligned |
- | |
104 | end if |
- | |
105 | 99 | ||
106 | ; This structure describes the static head of every list of pipes. |
100 | ; This structure describes the static head of every list of pipes. |
107 | ; The hardware requires 16-bytes alignment of this structure. |
101 | ; The hardware requires 16-bytes alignment of this structure. |
108 | ; All instances of this structure are located sequentially in uhci_controller, |
102 | ; All instances of this structure are located sequentially in uhci_controller, |
109 | ; uhci_controller is page-aligned, so it is sufficient to make this structure |
103 | ; uhci_controller is page-aligned, so it is sufficient to make this structure |
Line 202... | Line 196... | ||
202 | ; * The hardware part consists of first 16 bytes and corresponds to |
196 | ; * The hardware part consists of first 16 bytes and corresponds to |
203 | ; the General Transfer Descriptor aka general TD from OHCI specification. |
197 | ; the General Transfer Descriptor aka general TD from OHCI specification. |
204 | ; * The hardware requires 16-bytes alignment of the hardware part, so |
198 | ; * The hardware requires 16-bytes alignment of the hardware part, so |
205 | ; the entire descriptor must be 16-bytes aligned. Since the allocator |
199 | ; the entire descriptor must be 16-bytes aligned. Since the allocator |
206 | ; (usb_allocate_common) allocates memory sequentially from page start |
200 | ; (usb_allocate_common) allocates memory sequentially from page start |
207 | ; (aligned on 0x1000 bytes), size of the structure must be divisible by 16. |
201 | ; (aligned on 0x1000 bytes), block size for the allocator must be |
- | 202 | ; divisible by 16; usb1_allocate_generic_td ensures this. |
|
208 | struct ohci_gtd |
203 | struct ohci_gtd |
209 | ; ------------------------------ hardware fields ------------------------------ |
204 | ; ------------------------------ hardware fields ------------------------------ |
210 | ; All addresses in this part are physical. |
205 | ; All addresses in this part are physical. |
211 | Flags dd ? |
206 | Flags dd ? |
212 | ; 1. Lower 18 bits (bits 0-17) are ignored and not modified by the hardware. |
207 | ; 1. Lower 18 bits (bits 0-17) are ignored and not modified by the hardware. |
Line 246... | Line 241... | ||
246 | ; Physical address of the previous processed TD. |
241 | ; Physical address of the previous processed TD. |
247 | ; When the descriptor is processed by the IRQ handler, but not yet completed: |
242 | ; When the descriptor is processed by the IRQ handler, but not yet completed: |
248 | ; Virtual pointer to the next processed TD. |
243 | ; Virtual pointer to the next processed TD. |
249 | BufEnd dd ? |
244 | BufEnd dd ? |
250 | ; Physical address of the last byte in the buffer for this TD. |
245 | ; Physical address of the last byte in the buffer for this TD. |
251 | dd ? ; padding for 16-bytes alignment |
- | |
252 | SoftwarePart rd sizeof.usb_gtd/4 |
246 | dd ? ; padding to align with uhci_gtd |
253 | ; Common part for all controllers. |
- | |
254 | ends |
247 | ends |
Line 255... | Line -... | ||
255 | - | ||
256 | if sizeof.ohci_gtd mod 16 |
- | |
257 | .err ohci_gtd must be 16-bytes aligned |
- | |
258 | end if |
- | |
259 | 248 | ||
260 | ; OHCI isochronous transfer descriptor. |
249 | ; OHCI isochronous transfer descriptor. |
261 | ; * The structure describes transfers to be performed on Isochronous endpoints. |
250 | ; * The structure describes transfers to be performed on Isochronous endpoints. |
262 | ; * The structure includes two parts, the hardware part and the software part. |
251 | ; * The structure includes two parts, the hardware part and the software part. |
263 | ; * The hardware part consists of first 32 bytes and corresponds to |
252 | ; * The hardware part consists of first 32 bytes and corresponds to |
Line 724... | Line 713... | ||
724 | ; edx = virtual pointer to the last item.NextTD (first in the reverse list) |
713 | ; edx = virtual pointer to the last item.NextTD (first in the reverse list) |
725 | ; ebx = virtual pointer to the next item (previous in the reverse list) |
714 | ; ebx = virtual pointer to the next item (previous in the reverse list) |
726 | .tdloop: |
715 | .tdloop: |
727 | mov ecx, [eax+ohci_gtd.NextTD] |
716 | mov ecx, [eax+ohci_gtd.NextTD] |
728 | mov [eax+ohci_gtd.NextTD], ebx |
717 | mov [eax+ohci_gtd.NextTD], ebx |
729 | lea ebx, [eax+ohci_gtd.SoftwarePart] |
718 | lea ebx, [eax+sizeof.ohci_gtd] |
730 | test ecx, ecx |
719 | test ecx, ecx |
731 | jz .tddone |
720 | jz .tddone |
732 | call usb_td_to_virt |
721 | call usb_td_to_virt |
733 | test eax, eax |
722 | test eax, eax |
734 | jnz .tdloop |
723 | jnz .tdloop |
Line 891... | Line 880... | ||
891 | 880 | ||
892 | ; This procedure is called from usb_set_address_callback |
881 | ; This procedure is called from usb_set_address_callback |
893 | ; and stores USB device address in the ohci_pipe structure. |
882 | ; and stores USB device address in the ohci_pipe structure. |
894 | ; in: esi -> usb_controller, ebx -> usb_pipe, cl = address |
883 | ; in: esi -> usb_controller, ebx -> usb_pipe, cl = address |
895 | proc ohci_set_device_address |
884 | proc ohci_set_device_address |
896 | mov byte [ebx+ohci_pipe.Flags-ohci_pipe.SoftwarePart], cl |
885 | mov byte [ebx+ohci_pipe.Flags-sizeof.ohci_pipe], cl |
897 | ; Wait until the hardware will forget the old value. |
886 | ; Wait until the hardware will forget the old value. |
898 | call usb_subscribe_control |
887 | call usb_subscribe_control |
899 | ret |
888 | ret |
Line 900... | Line 889... | ||
900 | endp |
889 | endp |
901 | 890 | ||
902 | ; This procedure returns USB device address from the usb_pipe structure. |
891 | ; This procedure returns USB device address from the usb_pipe structure. |
903 | ; in: esi -> usb_controller, ebx -> usb_pipe |
892 | ; in: esi -> usb_controller, ebx -> usb_pipe |
904 | ; out: eax = endpoint address |
893 | ; out: eax = endpoint address |
905 | proc ohci_get_device_address |
894 | proc ohci_get_device_address |
906 | mov eax, [ebx+ohci_pipe.Flags-ohci_pipe.SoftwarePart] |
895 | mov eax, [ebx+ohci_pipe.Flags-sizeof.ohci_pipe] |
907 | and eax, 7Fh |
896 | and eax, 7Fh |
Line 908... | Line 897... | ||
908 | ret |
897 | ret |
Line 921... | Line 910... | ||
921 | ; This procedure is called from usb_get_descr8_callback when |
910 | ; This procedure is called from usb_get_descr8_callback when |
922 | ; the packet size for zero endpoint becomes known and |
911 | ; the packet size for zero endpoint becomes known and |
923 | ; stores the packet size in ohci_pipe structure. |
912 | ; stores the packet size in ohci_pipe structure. |
924 | ; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size |
913 | ; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size |
925 | proc ohci_set_endpoint_packet_size |
914 | proc ohci_set_endpoint_packet_size |
926 | mov byte [ebx+ohci_pipe.Flags+2-ohci_pipe.SoftwarePart], cl |
915 | mov byte [ebx+ohci_pipe.Flags+2-sizeof.ohci_pipe], cl |
927 | ; Wait until the hardware will forget the old value. |
916 | ; Wait until the hardware will forget the old value. |
928 | call usb_subscribe_control |
917 | call usb_subscribe_control |
929 | ret |
918 | ret |
930 | endp |
919 | endp |
Line 941... | Line 930... | ||
941 | .maxpacket dd ? |
930 | .maxpacket dd ? |
942 | .type dd ? |
931 | .type dd ? |
943 | .interval dd ? |
932 | .interval dd ? |
944 | end virtual |
933 | end virtual |
945 | ; 1. Initialize the queue of transfer descriptors: empty. |
934 | ; 1. Initialize the queue of transfer descriptors: empty. |
946 | sub eax, ohci_gtd.SoftwarePart |
935 | sub eax, sizeof.ohci_gtd |
947 | call get_phys_addr |
936 | call get_phys_addr |
948 | mov [edi+ohci_pipe.TailP-ohci_pipe.SoftwarePart], eax |
937 | mov [edi+ohci_pipe.TailP-sizeof.ohci_pipe], eax |
949 | mov [edi+ohci_pipe.HeadP-ohci_pipe.SoftwarePart], eax |
938 | mov [edi+ohci_pipe.HeadP-sizeof.ohci_pipe], eax |
950 | ; 2. Generate ohci_pipe.Flags, see the description in ohci_pipe. |
939 | ; 2. Generate ohci_pipe.Flags, see the description in ohci_pipe. |
951 | mov eax, [ecx+ohci_pipe.Flags-ohci_pipe.SoftwarePart] |
940 | mov eax, [ecx+ohci_pipe.Flags-sizeof.ohci_pipe] |
952 | and eax, 0x207F ; keep Speed bit and FunctionAddress |
941 | and eax, 0x207F ; keep Speed bit and FunctionAddress |
953 | mov edx, [.endpoint] |
942 | mov edx, [.endpoint] |
954 | and edx, 15 |
943 | and edx, 15 |
955 | shl edx, 7 |
944 | shl edx, 7 |
956 | or eax, edx |
945 | or eax, edx |
957 | mov [edi+ohci_pipe.Flags-ohci_pipe.SoftwarePart], eax |
946 | mov [edi+ohci_pipe.Flags-sizeof.ohci_pipe], eax |
958 | mov eax, [.maxpacket] |
947 | mov eax, [.maxpacket] |
959 | mov word [edi+ohci_pipe.Flags+2-ohci_pipe.SoftwarePart], ax |
948 | mov word [edi+ohci_pipe.Flags+2-sizeof.ohci_pipe], ax |
960 | cmp [.type], CONTROL_PIPE |
949 | cmp [.type], CONTROL_PIPE |
961 | jz @f |
950 | jz @f |
962 | test byte [.endpoint], 80h |
951 | test byte [.endpoint], 80h |
963 | setnz al |
952 | setnz al |
964 | inc eax |
953 | inc eax |
965 | shl al, 3 |
954 | shl al, 3 |
966 | or byte [edi+ohci_pipe.Flags+1-ohci_pipe.SoftwarePart], al |
955 | or byte [edi+ohci_pipe.Flags+1-sizeof.ohci_pipe], al |
967 | @@: |
956 | @@: |
968 | ; 3. Insert the new pipe to the corresponding list of endpoints. |
957 | ; 3. Insert the new pipe to the corresponding list of endpoints. |
969 | ; 3a. Use Control list for control pipes, Bulk list for bulk pipes. |
958 | ; 3a. Use Control list for control pipes, Bulk list for bulk pipes. |
970 | lea edx, [esi+ohci_controller.ControlED.SoftwarePart-sizeof.ohci_controller] |
959 | lea edx, [esi+ohci_controller.ControlED.SoftwarePart-sizeof.ohci_controller] |
971 | cmp [.type], BULK_PIPE |
960 | cmp [.type], BULK_PIPE |
Line 990... | Line 979... | ||
990 | mov ecx, [edx+usb_pipe.NextVirt] |
979 | mov ecx, [edx+usb_pipe.NextVirt] |
991 | mov [edi+usb_pipe.NextVirt], ecx |
980 | mov [edi+usb_pipe.NextVirt], ecx |
992 | mov [edi+usb_pipe.PrevVirt], edx |
981 | mov [edi+usb_pipe.PrevVirt], edx |
993 | mov [ecx+usb_pipe.PrevVirt], edi |
982 | mov [ecx+usb_pipe.PrevVirt], edi |
994 | mov [edx+usb_pipe.NextVirt], edi |
983 | mov [edx+usb_pipe.NextVirt], edi |
995 | mov ecx, [edx+ohci_pipe.NextED-ohci_pipe.SoftwarePart] |
984 | mov ecx, [edx+ohci_pipe.NextED-sizeof.ohci_pipe] |
996 | mov [edi+ohci_pipe.NextED-ohci_pipe.SoftwarePart], ecx |
985 | mov [edi+ohci_pipe.NextED-sizeof.ohci_pipe], ecx |
997 | lea eax, [edi-ohci_pipe.SoftwarePart] |
986 | lea eax, [edi-sizeof.ohci_pipe] |
998 | call get_phys_addr |
987 | call get_phys_addr |
999 | mov [edx+ohci_pipe.NextED-ohci_pipe.SoftwarePart], eax |
988 | mov [edx+ohci_pipe.NextED-sizeof.ohci_pipe], eax |
1000 | ; 4. Return something non-zero. |
989 | ; 4. Return something non-zero. |
1001 | ret |
990 | ret |
1002 | .return0: |
991 | .return0: |
1003 | xor eax, eax |
992 | xor eax, eax |
1004 | ret |
993 | ret |
Line 1092... | Line 1081... | ||
1092 | mov [packetSize], eax |
1081 | mov [packetSize], eax |
1093 | call ohci_alloc_packet |
1082 | call ohci_alloc_packet |
1094 | test eax, eax |
1083 | test eax, eax |
1095 | jz .fail |
1084 | jz .fail |
1096 | ; 4. Enable an immediate interrupt on completion of the last packet. |
1085 | ; 4. Enable an immediate interrupt on completion of the last packet. |
1097 | and byte [ecx+ohci_gtd.Flags+2-ohci_gtd.SoftwarePart], not (7 shl (21-16)) |
1086 | and byte [ecx+ohci_gtd.Flags+2-sizeof.ohci_gtd], not (7 shl (21-16)) |
1098 | ; 5. If a short transfer is ok for a caller, set the corresponding bit in |
1087 | ; 5. If a short transfer is ok for a caller, set the corresponding bit in |
1099 | ; the last descriptor, but not in others. |
1088 | ; the last descriptor, but not in others. |
1100 | ; Note: even if the caller says that short transfers are ok, |
1089 | ; Note: even if the caller says that short transfers are ok, |
1101 | ; all packets except the last one are marked as 'must be complete': |
1090 | ; all packets except the last one are marked as 'must be complete': |
1102 | ; if one of them will be short, the software intervention is needed |
1091 | ; if one of them will be short, the software intervention is needed |
1103 | ; to skip remaining packets; ohci_process_finalized_td will handle this |
1092 | ; to skip remaining packets; ohci_process_finalized_td will handle this |
1104 | ; transparently to the caller. |
1093 | ; transparently to the caller. |
1105 | test [flags], 1 |
1094 | test [flags], 1 |
1106 | jz @f |
1095 | jz @f |
1107 | or byte [ecx+ohci_gtd.Flags+2-ohci_gtd.SoftwarePart], 1 shl (18-16) |
1096 | or byte [ecx+ohci_gtd.Flags+2-sizeof.ohci_gtd], 1 shl (18-16) |
1108 | @@: |
1097 | @@: |
1109 | ret |
1098 | ret |
1110 | .fail: |
1099 | .fail: |
1111 | mov edi, ohci_hardware_func |
1100 | mov edi, ohci_hardware_func |
1112 | mov eax, [td] |
1101 | mov eax, [td] |
Line 1141... | Line 1130... | ||
1141 | call usb_init_transfer |
1130 | call usb_init_transfer |
1142 | pop eax |
1131 | pop eax |
1143 | ; 3. Save the returned value (next descriptor). |
1132 | ; 3. Save the returned value (next descriptor). |
1144 | push eax |
1133 | push eax |
1145 | ; 4. Store the physical address of the next descriptor. |
1134 | ; 4. Store the physical address of the next descriptor. |
1146 | sub eax, ohci_gtd.SoftwarePart |
1135 | sub eax, sizeof.ohci_gtd |
1147 | call get_phys_addr |
1136 | call get_phys_addr |
1148 | mov [ecx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart], eax |
1137 | mov [ecx+ohci_gtd.NextTD-sizeof.ohci_gtd], eax |
1149 | ; 5. For zero-length transfers, store zero in both fields for buffer addresses. |
1138 | ; 5. For zero-length transfers, store zero in both fields for buffer addresses. |
1150 | ; Otherwise, fill them with real values. |
1139 | ; Otherwise, fill them with real values. |
1151 | xor eax, eax |
1140 | xor eax, eax |
1152 | mov [ecx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], eax |
1141 | mov [ecx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], eax |
1153 | mov [ecx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart], eax |
1142 | mov [ecx+ohci_gtd.BufEnd-sizeof.ohci_gtd], eax |
1154 | cmp [.packetSize], eax |
1143 | cmp [.packetSize], eax |
1155 | jz @f |
1144 | jz @f |
1156 | mov eax, [.buffer] |
1145 | mov eax, [.buffer] |
1157 | call get_phys_addr |
1146 | call get_phys_addr |
1158 | mov [ecx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], eax |
1147 | mov [ecx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], eax |
1159 | mov eax, [.buffer] |
1148 | mov eax, [.buffer] |
1160 | add eax, [.packetSize] |
1149 | add eax, [.packetSize] |
1161 | dec eax |
1150 | dec eax |
1162 | call get_phys_addr |
1151 | call get_phys_addr |
1163 | mov [ecx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart], eax |
1152 | mov [ecx+ohci_gtd.BufEnd-sizeof.ohci_gtd], eax |
1164 | @@: |
1153 | @@: |
1165 | ; 6. Generate Flags field: |
1154 | ; 6. Generate Flags field: |
1166 | ; - set bufferRounding (bit 18) to zero = disallow short transfers; |
1155 | ; - set bufferRounding (bit 18) to zero = disallow short transfers; |
1167 | ; for the last transfer in a row, ohci_alloc_transfer would set the real value; |
1156 | ; for the last transfer in a row, ohci_alloc_transfer would set the real value; |
1168 | ; - set Direction (bits 19-20) to lower 2 bits of [.direction]; |
1157 | ; - set Direction (bits 19-20) to lower 2 bits of [.direction]; |
Line 1177... | Line 1166... | ||
1177 | and eax, 3 |
1166 | and eax, 3 |
1178 | shl eax, 19 |
1167 | shl eax, 19 |
1179 | and edx, (3 shl 2) |
1168 | and edx, (3 shl 2) |
1180 | shl edx, 24 - 2 |
1169 | shl edx, 24 - 2 |
1181 | lea eax, [eax + edx + (7 shl 21) + (15 shl 28)] |
1170 | lea eax, [eax + edx + (7 shl 21) + (15 shl 28)] |
1182 | mov [ecx+ohci_gtd.Flags-ohci_gtd.SoftwarePart], eax |
1171 | mov [ecx+ohci_gtd.Flags-sizeof.ohci_gtd], eax |
1183 | ; 7. Restore the returned value saved in step 3. |
1172 | ; 7. Restore the returned value saved in step 3. |
1184 | pop eax |
1173 | pop eax |
1185 | .nothing: |
1174 | .nothing: |
1186 | ret |
1175 | ret |
1187 | endp |
1176 | endp |
Line 1190... | Line 1179... | ||
1190 | ; and activates the transfer which was previously allocated by |
1179 | ; and activates the transfer which was previously allocated by |
1191 | ; ohci_alloc_transfer. |
1180 | ; ohci_alloc_transfer. |
1192 | ; ecx -> last descriptor for the transfer, ebx -> usb_pipe |
1181 | ; ecx -> last descriptor for the transfer, ebx -> usb_pipe |
1193 | proc ohci_insert_transfer |
1182 | proc ohci_insert_transfer |
1194 | ; 1. Advance the queue of transfer descriptors. |
1183 | ; 1. Advance the queue of transfer descriptors. |
1195 | mov eax, [ecx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart] |
1184 | mov eax, [ecx+ohci_gtd.NextTD-sizeof.ohci_gtd] |
1196 | mov [ebx+ohci_pipe.TailP-ohci_pipe.SoftwarePart], eax |
1185 | mov [ebx+ohci_pipe.TailP-sizeof.ohci_pipe], eax |
1197 | ; 2. For control and bulk pipes, notify the controller that |
1186 | ; 2. For control and bulk pipes, notify the controller that |
1198 | ; there is new work in control/bulk queue respectively. |
1187 | ; there is new work in control/bulk queue respectively. |
1199 | ohci_notify_new_work: |
1188 | ohci_notify_new_work: |
1200 | mov edx, [ebx+usb_pipe.Controller] |
1189 | mov edx, [ebx+usb_pipe.Controller] |
1201 | mov edx, [edx+ohci_controller.MMIOBase-sizeof.ohci_controller] |
1190 | mov edx, [edx+ohci_controller.MMIOBase-sizeof.ohci_controller] |
Line 1391... | Line 1380... | ||
1391 | ; disconnect; if so, the callback will be called by usb_pipe_closed with |
1380 | ; disconnect; if so, the callback will be called by usb_pipe_closed with |
1392 | ; correct status, so go to step 6 with ebx = 0 (do not free the TD). |
1381 | ; correct status, so go to step 6 with ebx = 0 (do not free the TD). |
1393 | mov edx, [ebx+usb_gtd.Pipe] |
1382 | mov edx, [ebx+usb_gtd.Pipe] |
1394 | test [edx+usb_pipe.Flags], USB_FLAG_CLOSED |
1383 | test [edx+usb_pipe.Flags], USB_FLAG_CLOSED |
1395 | jz @f |
1384 | jz @f |
1396 | lea eax, [ebx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart] |
1385 | lea eax, [ebx+ohci_gtd.NextTD-sizeof.ohci_gtd] |
1397 | xor ebx, ebx |
1386 | xor ebx, ebx |
1398 | jmp .next_td2 |
1387 | jmp .next_td2 |
1399 | @@: |
1388 | @@: |
1400 | ; 2. Remove the descriptor from the descriptors queue. |
1389 | ; 2. Remove the descriptor from the descriptors queue. |
1401 | call usb_unlink_td |
1390 | call usb_unlink_td |
1402 | ; 3. Get number of bytes that remain to be transferred. |
1391 | ; 3. Get number of bytes that remain to be transferred. |
1403 | ; If CurBufPtr is zero, everything was transferred. |
1392 | ; If CurBufPtr is zero, everything was transferred. |
1404 | xor edx, edx |
1393 | xor edx, edx |
1405 | cmp [ebx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], edx |
1394 | cmp [ebx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], edx |
1406 | jz .gotlen |
1395 | jz .gotlen |
1407 | ; Otherwise, the remaining length is |
1396 | ; Otherwise, the remaining length is |
1408 | ; (BufEnd and 0xFFF) - (CurBufPtr and 0xFFF) + 1, |
1397 | ; (BufEnd and 0xFFF) - (CurBufPtr and 0xFFF) + 1, |
1409 | ; plus 0x1000 if BufEnd and CurBufPtr are in different pages. |
1398 | ; plus 0x1000 if BufEnd and CurBufPtr are in different pages. |
1410 | mov edx, [ebx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart] |
1399 | mov edx, [ebx+ohci_gtd.BufEnd-sizeof.ohci_gtd] |
1411 | mov eax, [ebx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart] |
1400 | mov eax, [ebx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd] |
1412 | mov ecx, edx |
1401 | mov ecx, edx |
1413 | and edx, 0xFFF |
1402 | and edx, 0xFFF |
1414 | inc edx |
1403 | inc edx |
1415 | xor ecx, eax |
1404 | xor ecx, eax |
1416 | and ecx, -0x1000 |
1405 | and ecx, -0x1000 |
Line 1423... | Line 1412... | ||
1423 | ; The actual length is Length - (remaining length). |
1412 | ; The actual length is Length - (remaining length). |
1424 | sub edx, [ebx+usb_gtd.Length] |
1413 | sub edx, [ebx+usb_gtd.Length] |
1425 | neg edx |
1414 | neg edx |
1426 | ; 4. Check for error. If so, go to 7. |
1415 | ; 4. Check for error. If so, go to 7. |
1427 | push ebx |
1416 | push ebx |
1428 | mov eax, [ebx+ohci_gtd.Flags-ohci_gtd.SoftwarePart] |
1417 | mov eax, [ebx+ohci_gtd.Flags-sizeof.ohci_gtd] |
1429 | shr eax, 28 |
1418 | shr eax, 28 |
1430 | jnz .error |
1419 | jnz .error |
1431 | .notify: |
1420 | .notify: |
1432 | ; 5. Successful completion. |
1421 | ; 5. Successful completion. |
1433 | ; 5a. Check whether this descriptor has an associated callback. |
1422 | ; 5a. Check whether this descriptor has an associated callback. |
Line 1449... | Line 1438... | ||
1449 | cmp ebx, [esp] |
1438 | cmp ebx, [esp] |
1450 | jz @f |
1439 | jz @f |
1451 | stdcall usb1_free_general_td, ebx |
1440 | stdcall usb1_free_general_td, ebx |
1452 | @@: |
1441 | @@: |
1453 | pop ebx |
1442 | pop ebx |
1454 | lea eax, [ebx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart] |
1443 | lea eax, [ebx+ohci_gtd.NextTD-sizeof.ohci_gtd] |
1455 | .next_td2: |
1444 | .next_td2: |
1456 | push ebx |
1445 | push ebx |
1457 | mov ebx, eax |
1446 | mov ebx, eax |
1458 | lea edx, [esi+ohci_controller.DoneList-sizeof.ohci_controller] |
1447 | lea edx, [esi+ohci_controller.DoneList-sizeof.ohci_controller] |
1459 | xor ecx, ecx ; no next item |
1448 | xor ecx, ecx ; no next item |
Line 1482... | Line 1471... | ||
1482 | ; The hardware has stopped processing the queue. |
1471 | ; The hardware has stopped processing the queue. |
1483 | ; 7a. Save status and length. |
1472 | ; 7a. Save status and length. |
1484 | push eax |
1473 | push eax |
1485 | push edx |
1474 | push edx |
1486 | ; DEBUGF 1,'K : TD failed:\n' |
1475 | ; DEBUGF 1,'K : TD failed:\n' |
1487 | ; DEBUGF 1,'K : %x %x %x %x\n',[ebx-ohci_gtd.SoftwarePart],[ebx-ohci_gtd.SoftwarePart+4],[ebx-ohci_gtd.SoftwarePart+8],[ebx-ohci_gtd.SoftwarePart+12] |
1476 | ; DEBUGF 1,'K : %x %x %x %x\n',[ebx-sizeof.ohci_gtd],[ebx-sizeof.ohci_gtd+4],[ebx-sizeof.ohci_gtd+8],[ebx-sizeof.ohci_gtd+12] |
1488 | ; DEBUGF 1,'K : %x %x %x %x\n',[ebx-ohci_gtd.SoftwarePart+16],[ebx-ohci_gtd.SoftwarePart+20],[ebx-ohci_gtd.SoftwarePart+24],[ebx-ohci_gtd.SoftwarePart+28] |
1477 | ; DEBUGF 1,'K : %x %x %x %x\n',[ebx-sizeof.ohci_gtd+16],[ebx-sizeof.ohci_gtd+20],[ebx-sizeof.ohci_gtd+24],[ebx-sizeof.ohci_gtd+28] |
1489 | ; mov eax, [ebx+usb_gtd.Pipe] |
1478 | ; mov eax, [ebx+usb_gtd.Pipe] |
1490 | ; DEBUGF 1,'K : pipe: %x %x %x %x\n',[eax-ohci_pipe.SoftwarePart],[eax-ohci_pipe.SoftwarePart+4],[eax-ohci_pipe.SoftwarePart+8],[eax-ohci_pipe.SoftwarePart+12] |
1479 | ; DEBUGF 1,'K : pipe: %x %x %x %x\n',[eax-sizeof.ohci_pipe],[eax-sizeof.ohci_pipe+4],[eax-sizeof.ohci_pipe+8],[eax-sizeof.ohci_pipe+12] |
1491 | ; 7b. Traverse the list of descriptors looking for the final packet |
1480 | ; 7b. Traverse the list of descriptors looking for the final packet |
1492 | ; for this transfer. |
1481 | ; for this transfer. |
1493 | ; Free and unlink non-final descriptors, except the current one. |
1482 | ; Free and unlink non-final descriptors, except the current one. |
1494 | ; Final descriptor will be freed in step 6. |
1483 | ; Final descriptor will be freed in step 6. |
1495 | call usb_is_final_packet |
1484 | call usb_is_final_packet |
Line 1515... | Line 1504... | ||
1515 | ; as short-packet-is-error to stop controller from further processing |
1504 | ; as short-packet-is-error to stop controller from further processing |
1516 | ; of that stage; we need to restart processing from a TD following the last. |
1505 | ; of that stage; we need to restart processing from a TD following the last. |
1517 | ; After that, go to step 5 with eax = 0 (no error). |
1506 | ; After that, go to step 5 with eax = 0 (no error). |
1518 | cmp dword [.error_code], USB_STATUS_UNDERRUN |
1507 | cmp dword [.error_code], USB_STATUS_UNDERRUN |
1519 | jnz .no_underrun |
1508 | jnz .no_underrun |
1520 | test byte [ebx+ohci_gtd.Flags+2-ohci_gtd.SoftwarePart], 1 shl (18-16) |
1509 | test byte [ebx+ohci_gtd.Flags+2-sizeof.ohci_gtd], 1 shl (18-16) |
1521 | jz .no_underrun |
1510 | jz .no_underrun |
1522 | and dword [.error_code], 0 |
1511 | and dword [.error_code], 0 |
1523 | mov ecx, [ebx+usb_gtd.Pipe] |
1512 | mov ecx, [ebx+usb_gtd.Pipe] |
1524 | mov edx, [ecx+ohci_pipe.HeadP-ohci_pipe.SoftwarePart] |
1513 | mov edx, [ecx+ohci_pipe.HeadP-sizeof.ohci_pipe] |
1525 | and edx, 2 |
1514 | and edx, 2 |
1526 | .advance_queue: |
1515 | .advance_queue: |
1527 | mov eax, [ebx+usb_gtd.NextVirt] |
1516 | mov eax, [ebx+usb_gtd.NextVirt] |
1528 | sub eax, ohci_gtd.SoftwarePart |
1517 | sub eax, sizeof.ohci_gtd |
1529 | call get_phys_addr |
1518 | call get_phys_addr |
1530 | or eax, edx |
1519 | or eax, edx |
1531 | mov [ecx+ohci_pipe.HeadP-ohci_pipe.SoftwarePart], eax |
1520 | mov [ecx+ohci_pipe.HeadP-sizeof.ohci_pipe], eax |
1532 | push ebx |
1521 | push ebx |
1533 | mov ebx, ecx |
1522 | mov ebx, ecx |
1534 | call ohci_notify_new_work |
1523 | call ohci_notify_new_work |
1535 | pop ebx |
1524 | pop ebx |
1536 | pop edx eax |
1525 | pop edx eax |
Line 1560... | Line 1549... | ||
1560 | ; of any control transfer), so we hope on the best and just advance the queue |
1549 | ; of any control transfer), so we hope on the best and just advance the queue |
1561 | ; to the next transfer. (According to the standard, "A control pipe may also |
1550 | ; to the next transfer. (According to the standard, "A control pipe may also |
1562 | ; support functional stall as well, but this is not recommended."). |
1551 | ; support functional stall as well, but this is not recommended."). |
1563 | ; Advance the transfer queue to the next descriptor. |
1552 | ; Advance the transfer queue to the next descriptor. |
1564 | mov ecx, [ebx+usb_gtd.Pipe] |
1553 | mov ecx, [ebx+usb_gtd.Pipe] |
1565 | mov edx, [ecx+ohci_pipe.HeadP-ohci_pipe.SoftwarePart] |
1554 | mov edx, [ecx+ohci_pipe.HeadP-sizeof.ohci_pipe] |
1566 | and edx, 2 ; keep toggleCarry bit |
1555 | and edx, 2 ; keep toggleCarry bit |
1567 | cmp [ecx+usb_pipe.Type], CONTROL_PIPE |
1556 | cmp [ecx+usb_pipe.Type], CONTROL_PIPE |
1568 | jnz @f |
1557 | jnz @f |
1569 | inc edx ; set Halted bit |
1558 | inc edx ; set Halted bit |
1570 | @@: |
1559 | @@: |
Line 1575... | Line 1564... | ||
1575 | ; or due to disconnect); it unlinks the pipe from the corresponding list. |
1564 | ; or due to disconnect); it unlinks the pipe from the corresponding list. |
1576 | ; esi -> usb_controller, ebx -> usb_pipe |
1565 | ; esi -> usb_controller, ebx -> usb_pipe |
1577 | proc ohci_unlink_pipe |
1566 | proc ohci_unlink_pipe |
1578 | cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE |
1567 | cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE |
1579 | jnz @f |
1568 | jnz @f |
1580 | mov eax, [ebx+ohci_pipe.Flags-ohci_pipe.SoftwarePart] |
1569 | mov eax, [ebx+ohci_pipe.Flags-sizeof.ohci_pipe] |
1581 | bt eax, 13 |
1570 | bt eax, 13 |
1582 | setc cl |
1571 | setc cl |
1583 | bt eax, 11 |
1572 | bt eax, 11 |
1584 | setc ch |
1573 | setc ch |
1585 | shr eax, 16 |
1574 | shr eax, 16 |
Line 1587... | Line 1576... | ||
1587 | @@: |
1576 | @@: |
1588 | mov edx, [ebx+usb_pipe.NextVirt] |
1577 | mov edx, [ebx+usb_pipe.NextVirt] |
1589 | mov eax, [ebx+usb_pipe.PrevVirt] |
1578 | mov eax, [ebx+usb_pipe.PrevVirt] |
1590 | mov [edx+usb_pipe.PrevVirt], eax |
1579 | mov [edx+usb_pipe.PrevVirt], eax |
1591 | mov [eax+usb_pipe.NextVirt], edx |
1580 | mov [eax+usb_pipe.NextVirt], edx |
1592 | mov edx, [ebx+ohci_pipe.NextED-ohci_pipe.SoftwarePart] |
1581 | mov edx, [ebx+ohci_pipe.NextED-sizeof.ohci_pipe] |
1593 | mov [eax+ohci_pipe.NextED-ohci_pipe.SoftwarePart], edx |
1582 | mov [eax+ohci_pipe.NextED-sizeof.ohci_pipe], edx |
1594 | ret |
1583 | ret |
1595 | endp>=>> |
1584 | endp>=>> |