forked from KolibriOS/kolibrios
simplify source, binary is not affected
git-svn-id: svn://kolibrios.org@3653 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
52556729d6
commit
3d96d33ab7
@ -81,27 +81,21 @@ ends
|
|||||||
; * The hardware requires 32-bytes alignment of the hardware part, so
|
; * The hardware requires 32-bytes alignment of the hardware part, so
|
||||||
; the entire descriptor must be 32-bytes aligned. Since the allocator
|
; the entire descriptor must be 32-bytes aligned. Since the allocator
|
||||||
; (usb_allocate_common) allocates memory sequentially from page start
|
; (usb_allocate_common) allocates memory sequentially from page start
|
||||||
; (aligned on 0x1000 bytes), size of the structure must be divisible by 32.
|
; (aligned on 0x1000 bytes), block size for the allocator must be divisible
|
||||||
|
; by 32; ehci_alloc_td ensures this.
|
||||||
; * The hardware also requires that the hardware part must not cross page
|
; * The hardware also requires that the hardware part must not cross page
|
||||||
; boundary; the allocator satisfies this automatically.
|
; boundary; the allocator satisfies this automatically.
|
||||||
struct ehci_gtd ehci_hardware_td
|
struct ehci_gtd ehci_hardware_td
|
||||||
Flags dd ?
|
Flags dd ?
|
||||||
; Copy of flags from the call to usb_*_transfer_async.
|
; Copy of flags from the call to usb_*_transfer_async.
|
||||||
SoftwarePart rd sizeof.usb_gtd/4
|
|
||||||
; Software part, common for all controllers.
|
|
||||||
rd 3 ; padding
|
|
||||||
ends
|
ends
|
||||||
|
|
||||||
if sizeof.ehci_gtd mod 32
|
|
||||||
.err ehci_gtd must be 32-bytes aligned
|
|
||||||
end if
|
|
||||||
|
|
||||||
; EHCI-specific part of a pipe descriptor.
|
; EHCI-specific part of a pipe descriptor.
|
||||||
; * This structure corresponds to the Queue Head from the EHCI specification.
|
; * This structure corresponds to the Queue Head from the EHCI specification.
|
||||||
; * The hardware requires 32-bytes alignment of the hardware part.
|
; * The hardware requires 32-bytes alignment of the hardware part.
|
||||||
; Since the allocator (usb_allocate_common) allocates memory sequentially
|
; Since the allocator (usb_allocate_common) allocates memory sequentially
|
||||||
; from page start (aligned on 0x1000 bytes), size of the structure must be
|
; from page start (aligned on 0x1000 bytes), block size for the allocator
|
||||||
; divisible by 32.
|
; must be divisible by 32; ehci_alloc_pipe ensures this.
|
||||||
; * The hardware requires also that the hardware part must not cross page
|
; * The hardware requires also that the hardware part must not cross page
|
||||||
; boundary; the allocator satisfies this automatically.
|
; boundary; the allocator satisfies this automatically.
|
||||||
struct ehci_pipe
|
struct ehci_pipe
|
||||||
@ -154,15 +148,8 @@ Overlay ehci_hardware_td ?
|
|||||||
; from the new TD, if any.
|
; from the new TD, if any.
|
||||||
BaseList dd ?
|
BaseList dd ?
|
||||||
; Pointer to head of the corresponding pipe list.
|
; Pointer to head of the corresponding pipe list.
|
||||||
SoftwarePart rd sizeof.usb_pipe/4
|
|
||||||
; Software part, common for all controllers.
|
|
||||||
rd 2 ; padding
|
|
||||||
ends
|
ends
|
||||||
|
|
||||||
if sizeof.ehci_pipe mod 32
|
|
||||||
.err ehci_pipe must be 32-bytes aligned
|
|
||||||
end if
|
|
||||||
|
|
||||||
; This structure describes the static head of every list of pipes.
|
; This structure describes the static head of every list of pipes.
|
||||||
; The hardware requires 32-bytes alignment of this structure.
|
; The hardware requires 32-bytes alignment of this structure.
|
||||||
; All instances of this structure are located sequentially in ehci_controller,
|
; All instances of this structure are located sequentially in ehci_controller,
|
||||||
@ -764,7 +751,7 @@ endp
|
|||||||
; and stores USB device address in the ehci_pipe structure.
|
; and stores USB device address in the ehci_pipe structure.
|
||||||
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
|
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
|
||||||
proc ehci_set_device_address
|
proc ehci_set_device_address
|
||||||
mov byte [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart], cl
|
mov byte [ebx+ehci_pipe.Token-sizeof.ehci_pipe], cl
|
||||||
call usb_subscribe_control
|
call usb_subscribe_control
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -773,7 +760,7 @@ endp
|
|||||||
; in: esi -> usb_controller, ebx -> usb_pipe
|
; in: esi -> usb_controller, ebx -> usb_pipe
|
||||||
; out: eax = endpoint address
|
; out: eax = endpoint address
|
||||||
proc ehci_get_device_address
|
proc ehci_get_device_address
|
||||||
mov eax, [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
|
mov eax, [ebx+ehci_pipe.Token-sizeof.ehci_pipe]
|
||||||
and eax, 7Fh
|
and eax, 7Fh
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -793,11 +780,11 @@ endp
|
|||||||
; stores the packet size in ehci_pipe structure.
|
; stores the packet size in ehci_pipe structure.
|
||||||
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size
|
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size
|
||||||
proc ehci_set_endpoint_packet_size
|
proc ehci_set_endpoint_packet_size
|
||||||
mov eax, [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
|
mov eax, [ebx+ehci_pipe.Token-sizeof.ehci_pipe]
|
||||||
and eax, not (0x7FF shl 16)
|
and eax, not (0x7FF shl 16)
|
||||||
shl ecx, 16
|
shl ecx, 16
|
||||||
or eax, ecx
|
or eax, ecx
|
||||||
mov [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart], eax
|
mov [ebx+ehci_pipe.Token-sizeof.ehci_pipe], eax
|
||||||
; Wait until hardware cache is evicted.
|
; Wait until hardware cache is evicted.
|
||||||
call usb_subscribe_control
|
call usb_subscribe_control
|
||||||
ret
|
ret
|
||||||
@ -818,10 +805,10 @@ endg
|
|||||||
proc ehci_alloc_pipe
|
proc ehci_alloc_pipe
|
||||||
push ebx
|
push ebx
|
||||||
mov ebx, ehci_ep_mutex
|
mov ebx, ehci_ep_mutex
|
||||||
stdcall usb_allocate_common, sizeof.ehci_pipe
|
stdcall usb_allocate_common, (sizeof.ehci_pipe + sizeof.usb_pipe + 1Fh) and not 1Fh
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
add eax, ehci_pipe.SoftwarePart
|
add eax, sizeof.ehci_pipe
|
||||||
@@:
|
@@:
|
||||||
pop ebx
|
pop ebx
|
||||||
ret
|
ret
|
||||||
@ -834,7 +821,7 @@ virtual at esp
|
|||||||
dd ? ; return address
|
dd ? ; return address
|
||||||
.ptr dd ?
|
.ptr dd ?
|
||||||
end virtual
|
end virtual
|
||||||
sub [.ptr], ehci_pipe.SoftwarePart
|
sub [.ptr], sizeof.ehci_pipe
|
||||||
jmp usb_free_common
|
jmp usb_free_common
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -853,25 +840,25 @@ virtual at ebp+8
|
|||||||
end virtual
|
end virtual
|
||||||
; 1. Zero all fields in the hardware part.
|
; 1. Zero all fields in the hardware part.
|
||||||
push eax ecx
|
push eax ecx
|
||||||
sub edi, ehci_pipe.SoftwarePart
|
sub edi, sizeof.ehci_pipe
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
movi ecx, ehci_pipe.SoftwarePart/4
|
movi ecx, sizeof.ehci_pipe/4
|
||||||
rep stosd
|
rep stosd
|
||||||
pop ecx eax
|
pop ecx eax
|
||||||
; 2. Setup PID in the first TD and make sure that the it is not active.
|
; 2. Setup PID in the first TD and make sure that the it is not active.
|
||||||
xor edx, edx
|
xor edx, edx
|
||||||
test byte [.endpoint], 80h
|
test byte [.endpoint], 80h
|
||||||
setnz dh
|
setnz dh
|
||||||
mov [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], edx
|
mov [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx
|
||||||
mov [eax+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], 1
|
mov [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1
|
||||||
mov [eax+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], 1
|
mov [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1
|
||||||
; 3. Store physical address of the first TD.
|
; 3. Store physical address of the first TD.
|
||||||
sub eax, ehci_gtd.SoftwarePart
|
sub eax, sizeof.ehci_gtd
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
mov [edi+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart], eax
|
mov [edi+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax
|
||||||
; 4. Fill ehci_pipe.Flags except for S- and C-masks.
|
; 4. Fill ehci_pipe.Flags except for S- and C-masks.
|
||||||
; Copy location from the config pipe.
|
; Copy location from the config pipe.
|
||||||
mov eax, [ecx+ehci_pipe.Flags-ehci_pipe.SoftwarePart]
|
mov eax, [ecx+ehci_pipe.Flags-sizeof.ehci_pipe]
|
||||||
and eax, 3FFF0000h
|
and eax, 3FFF0000h
|
||||||
; Use 1 requests per microframe for control/bulk endpoints,
|
; Use 1 requests per microframe for control/bulk endpoints,
|
||||||
; use value from the endpoint descriptor for periodic endpoints
|
; use value from the endpoint descriptor for periodic endpoints
|
||||||
@ -884,9 +871,9 @@ end virtual
|
|||||||
@@:
|
@@:
|
||||||
shl edx, 30
|
shl edx, 30
|
||||||
or eax, edx
|
or eax, edx
|
||||||
mov [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart], eax
|
mov [edi+ehci_pipe.Flags-sizeof.ehci_pipe], eax
|
||||||
; 5. Fill ehci_pipe.Token.
|
; 5. Fill ehci_pipe.Token.
|
||||||
mov eax, [ecx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
|
mov eax, [ecx+ehci_pipe.Token-sizeof.ehci_pipe]
|
||||||
; copy following fields from the config pipe:
|
; copy following fields from the config pipe:
|
||||||
; DeviceAddress, EndpointSpeed, ControlEndpoint if new type is control
|
; DeviceAddress, EndpointSpeed, ControlEndpoint if new type is control
|
||||||
mov ecx, eax
|
mov ecx, eax
|
||||||
@ -915,7 +902,7 @@ end virtual
|
|||||||
@@:
|
@@:
|
||||||
or eax, 40000000h
|
or eax, 40000000h
|
||||||
.nonak:
|
.nonak:
|
||||||
mov [edi+ehci_pipe.Token-ehci_pipe.SoftwarePart], eax
|
mov [edi+ehci_pipe.Token-sizeof.ehci_pipe], eax
|
||||||
; 5. Select the corresponding list and insert to the list.
|
; 5. Select the corresponding list and insert to the list.
|
||||||
; 5a. Use Control list for control pipes, Bulk list for bulk pipes.
|
; 5a. Use Control list for control pipes, Bulk list for bulk pipes.
|
||||||
lea edx, [esi+ehci_controller.ControlED.SoftwarePart-sizeof.ehci_controller]
|
lea edx, [esi+ehci_controller.ControlED.SoftwarePart-sizeof.ehci_controller]
|
||||||
@ -931,7 +918,7 @@ end virtual
|
|||||||
; another for split transactions.
|
; another for split transactions.
|
||||||
; This could fail if the requested bandwidth is not available;
|
; This could fail if the requested bandwidth is not available;
|
||||||
; if so, return an error.
|
; if so, return an error.
|
||||||
test word [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart+2], 3FFFh
|
test word [edi+ehci_pipe.Flags-sizeof.ehci_pipe+2], 3FFFh
|
||||||
jnz .interrupt_fs
|
jnz .interrupt_fs
|
||||||
call ehci_select_hs_interrupt_list
|
call ehci_select_hs_interrupt_list
|
||||||
jmp .interrupt_common
|
jmp .interrupt_common
|
||||||
@ -940,9 +927,9 @@ end virtual
|
|||||||
.interrupt_common:
|
.interrupt_common:
|
||||||
test edx, edx
|
test edx, edx
|
||||||
jz .return0
|
jz .return0
|
||||||
mov word [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart], ax
|
mov word [edi+ehci_pipe.Flags-sizeof.ehci_pipe], ax
|
||||||
.insert:
|
.insert:
|
||||||
mov [edi+ehci_pipe.BaseList-ehci_pipe.SoftwarePart], edx
|
mov [edi+ehci_pipe.BaseList-sizeof.ehci_pipe], edx
|
||||||
; Insert to the head of the corresponding list.
|
; Insert to the head of the corresponding list.
|
||||||
; Note: inserting to the head guarantees that the list traverse in
|
; Note: inserting to the head guarantees that the list traverse in
|
||||||
; ehci_process_updated_schedule, once started, will not interact with new pipes.
|
; ehci_process_updated_schedule, once started, will not interact with new pipes.
|
||||||
@ -957,8 +944,8 @@ end virtual
|
|||||||
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
|
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
|
||||||
; store the physical address of the new pipe to previous NextQH.
|
; store the physical address of the new pipe to previous NextQH.
|
||||||
mov ecx, [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart]
|
mov ecx, [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart]
|
||||||
mov [edi+ehci_pipe.NextQH-ehci_pipe.SoftwarePart], ecx
|
mov [edi+ehci_pipe.NextQH-sizeof.ehci_pipe], ecx
|
||||||
lea eax, [edi-ehci_pipe.SoftwarePart]
|
lea eax, [edi-sizeof.ehci_pipe]
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
inc eax
|
inc eax
|
||||||
inc eax
|
inc eax
|
||||||
@ -1084,7 +1071,7 @@ endl
|
|||||||
jz .fail
|
jz .fail
|
||||||
; 9. Update flags in the last packet.
|
; 9. Update flags in the last packet.
|
||||||
mov edx, [flags]
|
mov edx, [flags]
|
||||||
mov [ecx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], edx
|
mov [ecx+ehci_gtd.Flags-sizeof.ehci_gtd], edx
|
||||||
; 10. Fill AlternateNextTD field in all allocated TDs.
|
; 10. Fill AlternateNextTD field in all allocated TDs.
|
||||||
; If the caller says that short transfer is ok, the queue must advance to
|
; If the caller says that short transfer is ok, the queue must advance to
|
||||||
; the next descriptor, which is in eax.
|
; the next descriptor, which is in eax.
|
||||||
@ -1093,7 +1080,7 @@ endl
|
|||||||
push eax
|
push eax
|
||||||
test dl, 1
|
test dl, 1
|
||||||
jz .disable_short
|
jz .disable_short
|
||||||
sub eax, ehci_gtd.SoftwarePart
|
sub eax, sizeof.ehci_gtd
|
||||||
jmp @f
|
jmp @f
|
||||||
.disable_short:
|
.disable_short:
|
||||||
mov eax, [ebx+usb_pipe.Controller]
|
mov eax, [ebx+usb_pipe.Controller]
|
||||||
@ -1104,7 +1091,7 @@ endl
|
|||||||
@@:
|
@@:
|
||||||
cmp edx, [esp]
|
cmp edx, [esp]
|
||||||
jz @f
|
jz @f
|
||||||
mov [edx+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], eax
|
mov [edx+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], eax
|
||||||
mov edx, [edx+usb_gtd.NextVirt]
|
mov edx, [edx+usb_gtd.NextVirt]
|
||||||
jmp @b
|
jmp @b
|
||||||
@@:
|
@@:
|
||||||
@ -1144,28 +1131,28 @@ end virtual
|
|||||||
call usb_init_transfer
|
call usb_init_transfer
|
||||||
pop eax
|
pop eax
|
||||||
; 3. Copy PID to the new descriptor.
|
; 3. Copy PID to the new descriptor.
|
||||||
mov edx, [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart]
|
mov edx, [ecx+ehci_gtd.Token-sizeof.ehci_gtd]
|
||||||
mov [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], edx
|
mov [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx
|
||||||
mov [eax+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], 1
|
mov [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1
|
||||||
mov [eax+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], 1
|
mov [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1
|
||||||
; 4. Save the returned value (next descriptor).
|
; 4. Save the returned value (next descriptor).
|
||||||
push eax
|
push eax
|
||||||
; 5. Store the physical address of the next descriptor.
|
; 5. Store the physical address of the next descriptor.
|
||||||
sub eax, ehci_gtd.SoftwarePart
|
sub eax, sizeof.ehci_gtd
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
mov [ecx+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], eax
|
mov [ecx+ehci_gtd.NextTD-sizeof.ehci_gtd], eax
|
||||||
; 6. For zero-length transfers, store zero in all fields for buffer addresses.
|
; 6. For zero-length transfers, store zero in all fields for buffer addresses.
|
||||||
; Otherwise, fill them with real values.
|
; Otherwise, fill them with real values.
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
mov [ecx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], eax
|
mov [ecx+ehci_gtd.Flags-sizeof.ehci_gtd], eax
|
||||||
repeat 10
|
repeat 10
|
||||||
mov [ecx+ehci_gtd.BufferPointers-ehci_gtd.SoftwarePart+(%-1)*4], eax
|
mov [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd+(%-1)*4], eax
|
||||||
end repeat
|
end repeat
|
||||||
cmp [.packetSize], eax
|
cmp [.packetSize], eax
|
||||||
jz @f
|
jz @f
|
||||||
mov eax, [.buffer]
|
mov eax, [.buffer]
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
mov [ecx+ehci_gtd.BufferPointers-ehci_gtd.SoftwarePart], eax
|
mov [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd], eax
|
||||||
and eax, 0xFFF
|
and eax, 0xFFF
|
||||||
mov edx, [.packetSize]
|
mov edx, [.packetSize]
|
||||||
add edx, eax
|
add edx, eax
|
||||||
@ -1174,25 +1161,25 @@ end repeat
|
|||||||
mov eax, [.buffer]
|
mov eax, [.buffer]
|
||||||
add eax, 0x1000
|
add eax, 0x1000
|
||||||
call get_pg_addr
|
call get_pg_addr
|
||||||
mov [ecx+ehci_gtd.BufferPointers+4-ehci_gtd.SoftwarePart], eax
|
mov [ecx+ehci_gtd.BufferPointers+4-sizeof.ehci_gtd], eax
|
||||||
sub edx, 0x1000
|
sub edx, 0x1000
|
||||||
jbe @f
|
jbe @f
|
||||||
mov eax, [.buffer]
|
mov eax, [.buffer]
|
||||||
add eax, 0x2000
|
add eax, 0x2000
|
||||||
call get_pg_addr
|
call get_pg_addr
|
||||||
mov [ecx+ehci_gtd.BufferPointers+8-ehci_gtd.SoftwarePart], eax
|
mov [ecx+ehci_gtd.BufferPointers+8-sizeof.ehci_gtd], eax
|
||||||
sub edx, 0x1000
|
sub edx, 0x1000
|
||||||
jbe @f
|
jbe @f
|
||||||
mov eax, [.buffer]
|
mov eax, [.buffer]
|
||||||
add eax, 0x3000
|
add eax, 0x3000
|
||||||
call get_pg_addr
|
call get_pg_addr
|
||||||
mov [ecx+ehci_gtd.BufferPointers+12-ehci_gtd.SoftwarePart], eax
|
mov [ecx+ehci_gtd.BufferPointers+12-sizeof.ehci_gtd], eax
|
||||||
sub edx, 0x1000
|
sub edx, 0x1000
|
||||||
jbe @f
|
jbe @f
|
||||||
mov eax, [.buffer]
|
mov eax, [.buffer]
|
||||||
add eax, 0x4000
|
add eax, 0x4000
|
||||||
call get_pg_addr
|
call get_pg_addr
|
||||||
mov [ecx+ehci_gtd.BufferPointers+16-ehci_gtd.SoftwarePart], eax
|
mov [ecx+ehci_gtd.BufferPointers+16-sizeof.ehci_gtd], eax
|
||||||
@@:
|
@@:
|
||||||
; 7. Fill Token field:
|
; 7. Fill Token field:
|
||||||
; set Status = 0 (inactive, ehci_insert_transfer would mark everything active);
|
; set Status = 0 (inactive, ehci_insert_transfer would mark everything active);
|
||||||
@ -1202,7 +1189,7 @@ end repeat
|
|||||||
; set current page to 0;
|
; set current page to 0;
|
||||||
; do not interrupt on complete (ehci_insert_transfer sets this bit where needed);
|
; do not interrupt on complete (ehci_insert_transfer sets this bit where needed);
|
||||||
; set DataToggle to bit 2 of [.direction].
|
; set DataToggle to bit 2 of [.direction].
|
||||||
mov eax, [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart]
|
mov eax, [ecx+ehci_gtd.Token-sizeof.ehci_gtd]
|
||||||
and eax, 300h ; keep PID code
|
and eax, 300h ; keep PID code
|
||||||
mov edx, [.direction]
|
mov edx, [.direction]
|
||||||
test edx, edx
|
test edx, edx
|
||||||
@ -1222,7 +1209,7 @@ end repeat
|
|||||||
mov edx, [.packetSize]
|
mov edx, [.packetSize]
|
||||||
shl edx, 16
|
shl edx, 16
|
||||||
or eax, edx
|
or eax, edx
|
||||||
mov [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart], eax
|
mov [ecx+ehci_gtd.Token-sizeof.ehci_gtd], eax
|
||||||
; 4. Restore the returned value saved in step 2.
|
; 4. Restore the returned value saved in step 2.
|
||||||
pop eax
|
pop eax
|
||||||
.nothing:
|
.nothing:
|
||||||
@ -1234,10 +1221,10 @@ endp
|
|||||||
; ehci_alloc_transfer.
|
; ehci_alloc_transfer.
|
||||||
; ecx -> last descriptor for the transfer, ebx -> usb_pipe
|
; ecx -> last descriptor for the transfer, ebx -> usb_pipe
|
||||||
proc ehci_insert_transfer
|
proc ehci_insert_transfer
|
||||||
or byte [ecx+ehci_gtd.Token+1-ehci_gtd.SoftwarePart], 80h ; set IOC bit
|
or byte [ecx+ehci_gtd.Token+1-sizeof.ehci_gtd], 80h ; set IOC bit
|
||||||
mov eax, [esp+4]
|
mov eax, [esp+4]
|
||||||
.activate:
|
.activate:
|
||||||
or byte [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], 80h ; set Active bit
|
or byte [eax+ehci_gtd.Token-sizeof.ehci_gtd], 80h ; set Active bit
|
||||||
cmp eax, ecx
|
cmp eax, ecx
|
||||||
mov eax, [eax+usb_gtd.NextVirt]
|
mov eax, [eax+usb_gtd.NextVirt]
|
||||||
jnz .activate
|
jnz .activate
|
||||||
@ -1328,7 +1315,7 @@ proc ehci_new_device
|
|||||||
.found_hs_hub:
|
.found_hs_hub:
|
||||||
mov edx, [edx+usb_hub.ConfigPipe]
|
mov edx, [edx+usb_hub.ConfigPipe]
|
||||||
inc ecx
|
inc ecx
|
||||||
mov edx, [edx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
|
mov edx, [edx+ehci_pipe.Token-sizeof.ehci_pipe]
|
||||||
shl ecx, 23
|
shl ecx, 23
|
||||||
and edx, 7Fh
|
and edx, 7Fh
|
||||||
shl edx, 16
|
shl edx, 16
|
||||||
@ -1338,15 +1325,15 @@ proc ehci_new_device
|
|||||||
.common:
|
.common:
|
||||||
; 5. Create pseudo-pipe in the stack.
|
; 5. Create pseudo-pipe in the stack.
|
||||||
; See ehci_init_pipe: only .Controller, .Token, .Flags fields are used.
|
; See ehci_init_pipe: only .Controller, .Token, .Flags fields are used.
|
||||||
push esi ; ehci_pipe.SoftwarePart.Controller
|
push esi ; usb_pipe.Controller
|
||||||
mov ecx, esp
|
mov ecx, esp
|
||||||
sub esp, ehci_pipe.SoftwarePart - ehci_pipe.Flags - 4
|
sub esp, sizeof.ehci_pipe - ehci_pipe.Flags - 4
|
||||||
push edx ; ehci_pipe.Flags
|
push edx ; ehci_pipe.Flags
|
||||||
push eax ; ehci_pipe.Token
|
push eax ; ehci_pipe.Token
|
||||||
; 6. Notify the protocol layer.
|
; 6. Notify the protocol layer.
|
||||||
call usb_new_device
|
call usb_new_device
|
||||||
; 7. Cleanup the stack after step 5 and return.
|
; 7. Cleanup the stack after step 5 and return.
|
||||||
add esp, ehci_pipe.SoftwarePart - ehci_pipe.Flags + 8
|
add esp, sizeof.ehci_pipe - ehci_pipe.Flags + 8
|
||||||
pop ecx ebx ; restore used registers
|
pop ecx ebx ; restore used registers
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -1658,7 +1645,7 @@ proc ehci_process_updated_list
|
|||||||
; if either of conditions holds, exit from the internal loop.
|
; if either of conditions holds, exit from the internal loop.
|
||||||
cmp ebx, [esp]
|
cmp ebx, [esp]
|
||||||
jz .tddone
|
jz .tddone
|
||||||
cmp byte [ebx+ehci_gtd.Token-ehci_gtd.SoftwarePart], 0
|
cmp byte [ebx+ehci_gtd.Token-sizeof.ehci_gtd], 0
|
||||||
js .tddone
|
js .tddone
|
||||||
; Release the queue lock while processing one descriptor:
|
; Release the queue lock while processing one descriptor:
|
||||||
; callback function could (and often would) schedule another transfer.
|
; callback function could (and often would) schedule another transfer.
|
||||||
@ -1690,14 +1677,14 @@ proc ehci_process_updated_td
|
|||||||
; cmp [eax+usb_pipe.Type], INTERRUPT_PIPE
|
; cmp [eax+usb_pipe.Type], INTERRUPT_PIPE
|
||||||
; jnz @f
|
; jnz @f
|
||||||
; DEBUGF 1,'K : finalized TD for pipe %x:\n',eax
|
; DEBUGF 1,'K : finalized TD for pipe %x:\n',eax
|
||||||
; lea eax, [ebx-ehci_gtd.SoftwarePart]
|
; lea eax, [ebx-sizeof.ehci_gtd]
|
||||||
; DEBUGF 1,'K : %x %x %x %x\n',[eax],[eax+4],[eax+8],[eax+12]
|
; DEBUGF 1,'K : %x %x %x %x\n',[eax],[eax+4],[eax+8],[eax+12]
|
||||||
; DEBUGF 1,'K : %x %x %x %x\n',[eax+16],[eax+20],[eax+24],[eax+28]
|
; DEBUGF 1,'K : %x %x %x %x\n',[eax+16],[eax+20],[eax+24],[eax+28]
|
||||||
;@@:
|
;@@:
|
||||||
; 1. Remove this descriptor from the list of descriptors for this pipe.
|
; 1. Remove this descriptor from the list of descriptors for this pipe.
|
||||||
call usb_unlink_td
|
call usb_unlink_td
|
||||||
; 2. Calculate actual number of bytes transferred.
|
; 2. Calculate actual number of bytes transferred.
|
||||||
mov eax, [ebx+ehci_gtd.Token-ehci_gtd.SoftwarePart]
|
mov eax, [ebx+ehci_gtd.Token-sizeof.ehci_gtd]
|
||||||
lea edx, [eax+eax]
|
lea edx, [eax+eax]
|
||||||
shr edx, 17
|
shr edx, 17
|
||||||
sub edx, [ebx+usb_gtd.Length]
|
sub edx, [ebx+usb_gtd.Length]
|
||||||
@ -1715,7 +1702,7 @@ proc ehci_process_updated_td
|
|||||||
xor ecx, ecx
|
xor ecx, ecx
|
||||||
test al, 40h
|
test al, 40h
|
||||||
jnz .error
|
jnz .error
|
||||||
test byte [ebx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], 1
|
test byte [ebx+ehci_gtd.Flags-sizeof.ehci_gtd], 1
|
||||||
jnz .notify
|
jnz .notify
|
||||||
cmp edx, [ebx+usb_gtd.Length]
|
cmp edx, [ebx+usb_gtd.Length]
|
||||||
jnz .special
|
jnz .special
|
||||||
@ -1745,14 +1732,14 @@ proc ehci_process_updated_td
|
|||||||
ret
|
ret
|
||||||
.error:
|
.error:
|
||||||
push ebx
|
push ebx
|
||||||
sub ebx, ehci_gtd.SoftwarePart
|
sub ebx, sizeof.ehci_gtd
|
||||||
DEBUGF 1,'K : TD failed:\n'
|
DEBUGF 1,'K : TD failed:\n'
|
||||||
DEBUGF 1,'K : %x %x %x %x\n',[ebx],[ebx+4],[ebx+8],[ebx+12]
|
DEBUGF 1,'K : %x %x %x %x\n',[ebx],[ebx+4],[ebx+8],[ebx+12]
|
||||||
DEBUGF 1,'K : %x %x %x %x\n',[ebx+16],[ebx+20],[ebx+24],[ebx+28]
|
DEBUGF 1,'K : %x %x %x %x\n',[ebx+16],[ebx+20],[ebx+24],[ebx+28]
|
||||||
pop ebx
|
pop ebx
|
||||||
DEBUGF 1,'K : pipe now:\n'
|
DEBUGF 1,'K : pipe now:\n'
|
||||||
mov ecx, [ebx+usb_gtd.Pipe]
|
mov ecx, [ebx+usb_gtd.Pipe]
|
||||||
sub ecx, ehci_pipe.SoftwarePart
|
sub ecx, sizeof.ehci_pipe
|
||||||
DEBUGF 1,'K : %x %x %x %x\n',[ecx],[ecx+4],[ecx+8],[ecx+12]
|
DEBUGF 1,'K : %x %x %x %x\n',[ecx],[ecx+4],[ecx+8],[ecx+12]
|
||||||
DEBUGF 1,'K : %x %x %x %x\n',[ecx+16],[ecx+20],[ecx+24],[ecx+28]
|
DEBUGF 1,'K : %x %x %x %x\n',[ecx+16],[ecx+20],[ecx+24],[ecx+28]
|
||||||
DEBUGF 1,'K : %x %x %x %x\n',[ecx+32],[ecx+36],[ecx+40],[ecx+44]
|
DEBUGF 1,'K : %x %x %x %x\n',[ecx+32],[ecx+36],[ecx+40],[ecx+44]
|
||||||
@ -1802,7 +1789,7 @@ proc ehci_process_updated_td
|
|||||||
; it is not an error; in this case, go to 4 with ecx = 0.
|
; it is not an error; in this case, go to 4 with ecx = 0.
|
||||||
cmp ecx, USB_STATUS_UNDERRUN
|
cmp ecx, USB_STATUS_UNDERRUN
|
||||||
jnz @f
|
jnz @f
|
||||||
test byte [ebx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], 1
|
test byte [ebx+ehci_gtd.Flags-sizeof.ehci_gtd], 1
|
||||||
jz @f
|
jz @f
|
||||||
xor ecx, ecx
|
xor ecx, ecx
|
||||||
pop edx ; length
|
pop edx ; length
|
||||||
@ -1832,20 +1819,20 @@ proc ehci_process_updated_td
|
|||||||
; to the next transfer. (According to the standard, "A control pipe may also
|
; to the next transfer. (According to the standard, "A control pipe may also
|
||||||
; support functional stall as well, but this is not recommended.").
|
; support functional stall as well, but this is not recommended.").
|
||||||
mov edx, [ebx+usb_gtd.Pipe]
|
mov edx, [ebx+usb_gtd.Pipe]
|
||||||
mov eax, [ebx+ehci_gtd.NextTD-ehci_gtd.SoftwarePart]
|
mov eax, [ebx+ehci_gtd.NextTD-sizeof.ehci_gtd]
|
||||||
or al, 1
|
or al, 1
|
||||||
mov [edx+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart], eax
|
mov [edx+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax
|
||||||
mov [edx+ehci_pipe.Overlay.AlternateNextTD-ehci_pipe.SoftwarePart], eax
|
mov [edx+ehci_pipe.Overlay.AlternateNextTD-sizeof.ehci_pipe], eax
|
||||||
cmp [edx+usb_pipe.Type], CONTROL_PIPE
|
cmp [edx+usb_pipe.Type], CONTROL_PIPE
|
||||||
jz .control
|
jz .control
|
||||||
; Bulk/interrupt transfer; halt the queue.
|
; Bulk/interrupt transfer; halt the queue.
|
||||||
mov [edx+ehci_pipe.Overlay.Token-ehci_pipe.SoftwarePart], 40h
|
mov [edx+ehci_pipe.Overlay.Token-sizeof.ehci_pipe], 40h
|
||||||
pop edx
|
pop edx
|
||||||
jmp .notify
|
jmp .notify
|
||||||
; Control transfer.
|
; Control transfer.
|
||||||
.control:
|
.control:
|
||||||
and [edx+ehci_pipe.Overlay.Token-ehci_pipe.SoftwarePart], 0
|
and [edx+ehci_pipe.Overlay.Token-sizeof.ehci_pipe], 0
|
||||||
dec [edx+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart]
|
dec [edx+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe]
|
||||||
pop edx
|
pop edx
|
||||||
jmp .notify
|
jmp .notify
|
||||||
endp
|
endp
|
||||||
@ -1855,7 +1842,7 @@ endp
|
|||||||
proc ehci_unlink_pipe
|
proc ehci_unlink_pipe
|
||||||
cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE
|
cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE
|
||||||
jnz @f
|
jnz @f
|
||||||
test word [ebx+ehci_pipe.Flags-ehci_pipe.SoftwarePart+2], 3FFFh
|
test word [ebx+ehci_pipe.Flags-sizeof.ehci_pipe+2], 3FFFh
|
||||||
jnz .interrupt_fs
|
jnz .interrupt_fs
|
||||||
call ehci_hs_interrupt_list_unlink
|
call ehci_hs_interrupt_list_unlink
|
||||||
jmp .interrupt_common
|
jmp .interrupt_common
|
||||||
@ -1870,9 +1857,9 @@ proc ehci_unlink_pipe
|
|||||||
mov edx, esi
|
mov edx, esi
|
||||||
sub edx, eax
|
sub edx, eax
|
||||||
cmp edx, sizeof.ehci_controller
|
cmp edx, sizeof.ehci_controller
|
||||||
mov edx, [ebx+ehci_pipe.NextQH-ehci_pipe.SoftwarePart]
|
mov edx, [ebx+ehci_pipe.NextQH-sizeof.ehci_pipe]
|
||||||
jb .prev_is_static
|
jb .prev_is_static
|
||||||
mov [eax+ehci_pipe.NextQH-ehci_pipe.SoftwarePart], edx
|
mov [eax+ehci_pipe.NextQH-sizeof.ehci_pipe], edx
|
||||||
ret
|
ret
|
||||||
.prev_is_static:
|
.prev_is_static:
|
||||||
mov [eax+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], edx
|
mov [eax+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], edx
|
||||||
@ -1882,10 +1869,10 @@ endp
|
|||||||
proc ehci_alloc_td
|
proc ehci_alloc_td
|
||||||
push ebx
|
push ebx
|
||||||
mov ebx, ehci_gtd_mutex
|
mov ebx, ehci_gtd_mutex
|
||||||
stdcall usb_allocate_common, sizeof.ehci_gtd
|
stdcall usb_allocate_common, (sizeof.ehci_gtd + sizeof.usb_gtd + 1Fh) and not 1Fh
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
add eax, ehci_gtd.SoftwarePart
|
add eax, sizeof.ehci_gtd
|
||||||
@@:
|
@@:
|
||||||
pop ebx
|
pop ebx
|
||||||
ret
|
ret
|
||||||
@ -1895,6 +1882,6 @@ endp
|
|||||||
; frees all additional data associated with the transfer descriptor.
|
; frees all additional data associated with the transfer descriptor.
|
||||||
; EHCI has no additional data, so just free ehci_gtd structure.
|
; EHCI has no additional data, so just free ehci_gtd structure.
|
||||||
proc ehci_free_td
|
proc ehci_free_td
|
||||||
sub dword [esp+4], ehci_gtd.SoftwarePart
|
sub dword [esp+4], sizeof.ehci_gtd
|
||||||
jmp usb_free_common
|
jmp usb_free_common
|
||||||
endp
|
endp
|
||||||
|
@ -26,17 +26,17 @@ usb_gtd_mutex MUTEX
|
|||||||
endg
|
endg
|
||||||
|
|
||||||
; sanity check: structures in UHCI and OHCI should be the same for allocation
|
; sanity check: structures in UHCI and OHCI should be the same for allocation
|
||||||
if (sizeof.ohci_pipe=sizeof.uhci_pipe)&(ohci_pipe.SoftwarePart=uhci_pipe.SoftwarePart)
|
if (sizeof.ohci_pipe = sizeof.uhci_pipe)
|
||||||
|
|
||||||
; Allocates one endpoint structure for UHCI/OHCI.
|
; Allocates one endpoint structure for UHCI/OHCI.
|
||||||
; Returns pointer to software part (usb_pipe) in eax.
|
; Returns pointer to software part (usb_pipe) in eax.
|
||||||
proc usb1_allocate_endpoint
|
proc usb1_allocate_endpoint
|
||||||
push ebx
|
push ebx
|
||||||
mov ebx, usb1_ep_mutex
|
mov ebx, usb1_ep_mutex
|
||||||
stdcall usb_allocate_common, sizeof.ohci_pipe
|
stdcall usb_allocate_common, (sizeof.ohci_pipe + sizeof.usb_pipe + 0Fh) and not 0Fh
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
add eax, ohci_pipe.SoftwarePart
|
add eax, sizeof.ohci_pipe
|
||||||
@@:
|
@@:
|
||||||
pop ebx
|
pop ebx
|
||||||
ret
|
ret
|
||||||
@ -45,7 +45,7 @@ endp
|
|||||||
; Free one endpoint structure for UHCI/OHCI.
|
; Free one endpoint structure for UHCI/OHCI.
|
||||||
; Stdcall with one argument, pointer to software part (usb_pipe).
|
; Stdcall with one argument, pointer to software part (usb_pipe).
|
||||||
proc usb1_free_endpoint
|
proc usb1_free_endpoint
|
||||||
sub dword [esp+4], ohci_pipe.SoftwarePart
|
sub dword [esp+4], sizeof.ohci_pipe
|
||||||
jmp usb_free_common
|
jmp usb_free_common
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -55,17 +55,17 @@ else
|
|||||||
end if
|
end if
|
||||||
|
|
||||||
; sanity check: structures in UHCI and OHCI should be the same for allocation
|
; sanity check: structures in UHCI and OHCI should be the same for allocation
|
||||||
if (sizeof.ohci_gtd=sizeof.uhci_gtd)&(ohci_gtd.SoftwarePart=uhci_gtd.SoftwarePart)
|
if (sizeof.ohci_gtd = sizeof.uhci_gtd)
|
||||||
|
|
||||||
; Allocates one general transfer descriptor structure for UHCI/OHCI.
|
; Allocates one general transfer descriptor structure for UHCI/OHCI.
|
||||||
; Returns pointer to software part (usb_gtd) in eax.
|
; Returns pointer to software part (usb_gtd) in eax.
|
||||||
proc usb1_allocate_general_td
|
proc usb1_allocate_general_td
|
||||||
push ebx
|
push ebx
|
||||||
mov ebx, usb_gtd_mutex
|
mov ebx, usb_gtd_mutex
|
||||||
stdcall usb_allocate_common, sizeof.ohci_gtd
|
stdcall usb_allocate_common, (sizeof.ohci_gtd + sizeof.usb_gtd + 0Fh) and not 0Fh
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
add eax, ohci_gtd.SoftwarePart
|
add eax, sizeof.ohci_gtd
|
||||||
@@:
|
@@:
|
||||||
pop ebx
|
pop ebx
|
||||||
ret
|
ret
|
||||||
@ -74,7 +74,7 @@ endp
|
|||||||
; Free one general transfer descriptor structure for UHCI/OHCI.
|
; Free one general transfer descriptor structure for UHCI/OHCI.
|
||||||
; Stdcall with one argument, pointer to software part (usb_gtd).
|
; Stdcall with one argument, pointer to software part (usb_gtd).
|
||||||
proc usb1_free_general_td
|
proc usb1_free_general_td
|
||||||
sub dword [esp+4], ohci_gtd.SoftwarePart
|
sub dword [esp+4], sizeof.ohci_gtd
|
||||||
jmp usb_free_common
|
jmp usb_free_common
|
||||||
endp
|
endp
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ OhciRhPortStatusReg = 54h
|
|||||||
; specification.
|
; specification.
|
||||||
; * The hardware requires 16-bytes alignment of the hardware part.
|
; * The hardware requires 16-bytes alignment of the hardware part.
|
||||||
; Since the allocator (usb_allocate_common) allocates memory sequentially
|
; Since the allocator (usb_allocate_common) allocates memory sequentially
|
||||||
; from page start (aligned on 0x1000 bytes), size of the structure must be
|
; from page start (aligned on 0x1000 bytes), block size for the allocator
|
||||||
; divisible by 16.
|
; must be divisible by 16; usb1_allocate_endpoint ensures this.
|
||||||
struct ohci_pipe
|
struct ohci_pipe
|
||||||
; All addresses are physical.
|
; All addresses are physical.
|
||||||
Flags dd ?
|
Flags dd ?
|
||||||
@ -95,14 +95,8 @@ NextED dd ?
|
|||||||
; * There is no "next" list for Bulk and Control lists, they are processed
|
; * There is no "next" list for Bulk and Control lists, they are processed
|
||||||
; separately from others.
|
; separately from others.
|
||||||
; * There is no "next" list for Periodic list for 1ms interval.
|
; * There is no "next" list for Periodic list for 1ms interval.
|
||||||
SoftwarePart rd sizeof.usb_pipe/4
|
|
||||||
; Software part, common for all controllers.
|
|
||||||
ends
|
ends
|
||||||
|
|
||||||
if sizeof.ohci_pipe mod 16
|
|
||||||
.err ohci_pipe must be 16-bytes aligned
|
|
||||||
end if
|
|
||||||
|
|
||||||
; This structure describes the static head of every list of pipes.
|
; This structure describes the static head of every list of pipes.
|
||||||
; The hardware requires 16-bytes alignment of this structure.
|
; The hardware requires 16-bytes alignment of this structure.
|
||||||
; All instances of this structure are located sequentially in uhci_controller,
|
; All instances of this structure are located sequentially in uhci_controller,
|
||||||
@ -204,7 +198,8 @@ end if
|
|||||||
; * The hardware requires 16-bytes alignment of the hardware part, so
|
; * The hardware requires 16-bytes alignment of the hardware part, so
|
||||||
; the entire descriptor must be 16-bytes aligned. Since the allocator
|
; the entire descriptor must be 16-bytes aligned. Since the allocator
|
||||||
; (usb_allocate_common) allocates memory sequentially from page start
|
; (usb_allocate_common) allocates memory sequentially from page start
|
||||||
; (aligned on 0x1000 bytes), size of the structure must be divisible by 16.
|
; (aligned on 0x1000 bytes), block size for the allocator must be
|
||||||
|
; divisible by 16; usb1_allocate_generic_td ensures this.
|
||||||
struct ohci_gtd
|
struct ohci_gtd
|
||||||
; ------------------------------ hardware fields ------------------------------
|
; ------------------------------ hardware fields ------------------------------
|
||||||
; All addresses in this part are physical.
|
; All addresses in this part are physical.
|
||||||
@ -248,15 +243,9 @@ NextTD dd ?
|
|||||||
; Virtual pointer to the next processed TD.
|
; Virtual pointer to the next processed TD.
|
||||||
BufEnd dd ?
|
BufEnd dd ?
|
||||||
; Physical address of the last byte in the buffer for this TD.
|
; Physical address of the last byte in the buffer for this TD.
|
||||||
dd ? ; padding for 16-bytes alignment
|
dd ? ; padding to align with uhci_gtd
|
||||||
SoftwarePart rd sizeof.usb_gtd/4
|
|
||||||
; Common part for all controllers.
|
|
||||||
ends
|
ends
|
||||||
|
|
||||||
if sizeof.ohci_gtd mod 16
|
|
||||||
.err ohci_gtd must be 16-bytes aligned
|
|
||||||
end if
|
|
||||||
|
|
||||||
; OHCI isochronous transfer descriptor.
|
; OHCI isochronous transfer descriptor.
|
||||||
; * The structure describes transfers to be performed on Isochronous endpoints.
|
; * The structure describes transfers to be performed on Isochronous endpoints.
|
||||||
; * The structure includes two parts, the hardware part and the software part.
|
; * The structure includes two parts, the hardware part and the software part.
|
||||||
@ -726,7 +715,7 @@ end virtual
|
|||||||
.tdloop:
|
.tdloop:
|
||||||
mov ecx, [eax+ohci_gtd.NextTD]
|
mov ecx, [eax+ohci_gtd.NextTD]
|
||||||
mov [eax+ohci_gtd.NextTD], ebx
|
mov [eax+ohci_gtd.NextTD], ebx
|
||||||
lea ebx, [eax+ohci_gtd.SoftwarePart]
|
lea ebx, [eax+sizeof.ohci_gtd]
|
||||||
test ecx, ecx
|
test ecx, ecx
|
||||||
jz .tddone
|
jz .tddone
|
||||||
call usb_td_to_virt
|
call usb_td_to_virt
|
||||||
@ -893,7 +882,7 @@ endp
|
|||||||
; and stores USB device address in the ohci_pipe structure.
|
; and stores USB device address in the ohci_pipe structure.
|
||||||
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
|
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
|
||||||
proc ohci_set_device_address
|
proc ohci_set_device_address
|
||||||
mov byte [ebx+ohci_pipe.Flags-ohci_pipe.SoftwarePart], cl
|
mov byte [ebx+ohci_pipe.Flags-sizeof.ohci_pipe], cl
|
||||||
; Wait until the hardware will forget the old value.
|
; Wait until the hardware will forget the old value.
|
||||||
call usb_subscribe_control
|
call usb_subscribe_control
|
||||||
ret
|
ret
|
||||||
@ -903,7 +892,7 @@ endp
|
|||||||
; in: esi -> usb_controller, ebx -> usb_pipe
|
; in: esi -> usb_controller, ebx -> usb_pipe
|
||||||
; out: eax = endpoint address
|
; out: eax = endpoint address
|
||||||
proc ohci_get_device_address
|
proc ohci_get_device_address
|
||||||
mov eax, [ebx+ohci_pipe.Flags-ohci_pipe.SoftwarePart]
|
mov eax, [ebx+ohci_pipe.Flags-sizeof.ohci_pipe]
|
||||||
and eax, 7Fh
|
and eax, 7Fh
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -923,7 +912,7 @@ endp
|
|||||||
; stores the packet size in ohci_pipe structure.
|
; stores the packet size in ohci_pipe structure.
|
||||||
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size
|
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size
|
||||||
proc ohci_set_endpoint_packet_size
|
proc ohci_set_endpoint_packet_size
|
||||||
mov byte [ebx+ohci_pipe.Flags+2-ohci_pipe.SoftwarePart], cl
|
mov byte [ebx+ohci_pipe.Flags+2-sizeof.ohci_pipe], cl
|
||||||
; Wait until the hardware will forget the old value.
|
; Wait until the hardware will forget the old value.
|
||||||
call usb_subscribe_control
|
call usb_subscribe_control
|
||||||
ret
|
ret
|
||||||
@ -943,27 +932,27 @@ virtual at ebp+8
|
|||||||
.interval dd ?
|
.interval dd ?
|
||||||
end virtual
|
end virtual
|
||||||
; 1. Initialize the queue of transfer descriptors: empty.
|
; 1. Initialize the queue of transfer descriptors: empty.
|
||||||
sub eax, ohci_gtd.SoftwarePart
|
sub eax, sizeof.ohci_gtd
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
mov [edi+ohci_pipe.TailP-ohci_pipe.SoftwarePart], eax
|
mov [edi+ohci_pipe.TailP-sizeof.ohci_pipe], eax
|
||||||
mov [edi+ohci_pipe.HeadP-ohci_pipe.SoftwarePart], eax
|
mov [edi+ohci_pipe.HeadP-sizeof.ohci_pipe], eax
|
||||||
; 2. Generate ohci_pipe.Flags, see the description in ohci_pipe.
|
; 2. Generate ohci_pipe.Flags, see the description in ohci_pipe.
|
||||||
mov eax, [ecx+ohci_pipe.Flags-ohci_pipe.SoftwarePart]
|
mov eax, [ecx+ohci_pipe.Flags-sizeof.ohci_pipe]
|
||||||
and eax, 0x207F ; keep Speed bit and FunctionAddress
|
and eax, 0x207F ; keep Speed bit and FunctionAddress
|
||||||
mov edx, [.endpoint]
|
mov edx, [.endpoint]
|
||||||
and edx, 15
|
and edx, 15
|
||||||
shl edx, 7
|
shl edx, 7
|
||||||
or eax, edx
|
or eax, edx
|
||||||
mov [edi+ohci_pipe.Flags-ohci_pipe.SoftwarePart], eax
|
mov [edi+ohci_pipe.Flags-sizeof.ohci_pipe], eax
|
||||||
mov eax, [.maxpacket]
|
mov eax, [.maxpacket]
|
||||||
mov word [edi+ohci_pipe.Flags+2-ohci_pipe.SoftwarePart], ax
|
mov word [edi+ohci_pipe.Flags+2-sizeof.ohci_pipe], ax
|
||||||
cmp [.type], CONTROL_PIPE
|
cmp [.type], CONTROL_PIPE
|
||||||
jz @f
|
jz @f
|
||||||
test byte [.endpoint], 80h
|
test byte [.endpoint], 80h
|
||||||
setnz al
|
setnz al
|
||||||
inc eax
|
inc eax
|
||||||
shl al, 3
|
shl al, 3
|
||||||
or byte [edi+ohci_pipe.Flags+1-ohci_pipe.SoftwarePart], al
|
or byte [edi+ohci_pipe.Flags+1-sizeof.ohci_pipe], al
|
||||||
@@:
|
@@:
|
||||||
; 3. Insert the new pipe to the corresponding list of endpoints.
|
; 3. Insert the new pipe to the corresponding list of endpoints.
|
||||||
; 3a. Use Control list for control pipes, Bulk list for bulk pipes.
|
; 3a. Use Control list for control pipes, Bulk list for bulk pipes.
|
||||||
@ -992,11 +981,11 @@ end virtual
|
|||||||
mov [edi+usb_pipe.PrevVirt], edx
|
mov [edi+usb_pipe.PrevVirt], edx
|
||||||
mov [ecx+usb_pipe.PrevVirt], edi
|
mov [ecx+usb_pipe.PrevVirt], edi
|
||||||
mov [edx+usb_pipe.NextVirt], edi
|
mov [edx+usb_pipe.NextVirt], edi
|
||||||
mov ecx, [edx+ohci_pipe.NextED-ohci_pipe.SoftwarePart]
|
mov ecx, [edx+ohci_pipe.NextED-sizeof.ohci_pipe]
|
||||||
mov [edi+ohci_pipe.NextED-ohci_pipe.SoftwarePart], ecx
|
mov [edi+ohci_pipe.NextED-sizeof.ohci_pipe], ecx
|
||||||
lea eax, [edi-ohci_pipe.SoftwarePart]
|
lea eax, [edi-sizeof.ohci_pipe]
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
mov [edx+ohci_pipe.NextED-ohci_pipe.SoftwarePart], eax
|
mov [edx+ohci_pipe.NextED-sizeof.ohci_pipe], eax
|
||||||
; 4. Return something non-zero.
|
; 4. Return something non-zero.
|
||||||
ret
|
ret
|
||||||
.return0:
|
.return0:
|
||||||
@ -1094,7 +1083,7 @@ endl
|
|||||||
test eax, eax
|
test eax, eax
|
||||||
jz .fail
|
jz .fail
|
||||||
; 4. Enable an immediate interrupt on completion of the last packet.
|
; 4. Enable an immediate interrupt on completion of the last packet.
|
||||||
and byte [ecx+ohci_gtd.Flags+2-ohci_gtd.SoftwarePart], not (7 shl (21-16))
|
and byte [ecx+ohci_gtd.Flags+2-sizeof.ohci_gtd], not (7 shl (21-16))
|
||||||
; 5. If a short transfer is ok for a caller, set the corresponding bit in
|
; 5. If a short transfer is ok for a caller, set the corresponding bit in
|
||||||
; the last descriptor, but not in others.
|
; the last descriptor, but not in others.
|
||||||
; Note: even if the caller says that short transfers are ok,
|
; Note: even if the caller says that short transfers are ok,
|
||||||
@ -1104,7 +1093,7 @@ endl
|
|||||||
; transparently to the caller.
|
; transparently to the caller.
|
||||||
test [flags], 1
|
test [flags], 1
|
||||||
jz @f
|
jz @f
|
||||||
or byte [ecx+ohci_gtd.Flags+2-ohci_gtd.SoftwarePart], 1 shl (18-16)
|
or byte [ecx+ohci_gtd.Flags+2-sizeof.ohci_gtd], 1 shl (18-16)
|
||||||
@@:
|
@@:
|
||||||
ret
|
ret
|
||||||
.fail:
|
.fail:
|
||||||
@ -1143,24 +1132,24 @@ end virtual
|
|||||||
; 3. Save the returned value (next descriptor).
|
; 3. Save the returned value (next descriptor).
|
||||||
push eax
|
push eax
|
||||||
; 4. Store the physical address of the next descriptor.
|
; 4. Store the physical address of the next descriptor.
|
||||||
sub eax, ohci_gtd.SoftwarePart
|
sub eax, sizeof.ohci_gtd
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
mov [ecx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart], eax
|
mov [ecx+ohci_gtd.NextTD-sizeof.ohci_gtd], eax
|
||||||
; 5. For zero-length transfers, store zero in both fields for buffer addresses.
|
; 5. For zero-length transfers, store zero in both fields for buffer addresses.
|
||||||
; Otherwise, fill them with real values.
|
; Otherwise, fill them with real values.
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
mov [ecx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], eax
|
mov [ecx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], eax
|
||||||
mov [ecx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart], eax
|
mov [ecx+ohci_gtd.BufEnd-sizeof.ohci_gtd], eax
|
||||||
cmp [.packetSize], eax
|
cmp [.packetSize], eax
|
||||||
jz @f
|
jz @f
|
||||||
mov eax, [.buffer]
|
mov eax, [.buffer]
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
mov [ecx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], eax
|
mov [ecx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], eax
|
||||||
mov eax, [.buffer]
|
mov eax, [.buffer]
|
||||||
add eax, [.packetSize]
|
add eax, [.packetSize]
|
||||||
dec eax
|
dec eax
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
mov [ecx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart], eax
|
mov [ecx+ohci_gtd.BufEnd-sizeof.ohci_gtd], eax
|
||||||
@@:
|
@@:
|
||||||
; 6. Generate Flags field:
|
; 6. Generate Flags field:
|
||||||
; - set bufferRounding (bit 18) to zero = disallow short transfers;
|
; - set bufferRounding (bit 18) to zero = disallow short transfers;
|
||||||
@ -1179,7 +1168,7 @@ end virtual
|
|||||||
and edx, (3 shl 2)
|
and edx, (3 shl 2)
|
||||||
shl edx, 24 - 2
|
shl edx, 24 - 2
|
||||||
lea eax, [eax + edx + (7 shl 21) + (15 shl 28)]
|
lea eax, [eax + edx + (7 shl 21) + (15 shl 28)]
|
||||||
mov [ecx+ohci_gtd.Flags-ohci_gtd.SoftwarePart], eax
|
mov [ecx+ohci_gtd.Flags-sizeof.ohci_gtd], eax
|
||||||
; 7. Restore the returned value saved in step 3.
|
; 7. Restore the returned value saved in step 3.
|
||||||
pop eax
|
pop eax
|
||||||
.nothing:
|
.nothing:
|
||||||
@ -1192,8 +1181,8 @@ endp
|
|||||||
; ecx -> last descriptor for the transfer, ebx -> usb_pipe
|
; ecx -> last descriptor for the transfer, ebx -> usb_pipe
|
||||||
proc ohci_insert_transfer
|
proc ohci_insert_transfer
|
||||||
; 1. Advance the queue of transfer descriptors.
|
; 1. Advance the queue of transfer descriptors.
|
||||||
mov eax, [ecx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart]
|
mov eax, [ecx+ohci_gtd.NextTD-sizeof.ohci_gtd]
|
||||||
mov [ebx+ohci_pipe.TailP-ohci_pipe.SoftwarePart], eax
|
mov [ebx+ohci_pipe.TailP-sizeof.ohci_pipe], eax
|
||||||
; 2. For control and bulk pipes, notify the controller that
|
; 2. For control and bulk pipes, notify the controller that
|
||||||
; there is new work in control/bulk queue respectively.
|
; there is new work in control/bulk queue respectively.
|
||||||
ohci_notify_new_work:
|
ohci_notify_new_work:
|
||||||
@ -1393,7 +1382,7 @@ proc ohci_process_finalized_td
|
|||||||
mov edx, [ebx+usb_gtd.Pipe]
|
mov edx, [ebx+usb_gtd.Pipe]
|
||||||
test [edx+usb_pipe.Flags], USB_FLAG_CLOSED
|
test [edx+usb_pipe.Flags], USB_FLAG_CLOSED
|
||||||
jz @f
|
jz @f
|
||||||
lea eax, [ebx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart]
|
lea eax, [ebx+ohci_gtd.NextTD-sizeof.ohci_gtd]
|
||||||
xor ebx, ebx
|
xor ebx, ebx
|
||||||
jmp .next_td2
|
jmp .next_td2
|
||||||
@@:
|
@@:
|
||||||
@ -1402,13 +1391,13 @@ proc ohci_process_finalized_td
|
|||||||
; 3. Get number of bytes that remain to be transferred.
|
; 3. Get number of bytes that remain to be transferred.
|
||||||
; If CurBufPtr is zero, everything was transferred.
|
; If CurBufPtr is zero, everything was transferred.
|
||||||
xor edx, edx
|
xor edx, edx
|
||||||
cmp [ebx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], edx
|
cmp [ebx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], edx
|
||||||
jz .gotlen
|
jz .gotlen
|
||||||
; Otherwise, the remaining length is
|
; Otherwise, the remaining length is
|
||||||
; (BufEnd and 0xFFF) - (CurBufPtr and 0xFFF) + 1,
|
; (BufEnd and 0xFFF) - (CurBufPtr and 0xFFF) + 1,
|
||||||
; plus 0x1000 if BufEnd and CurBufPtr are in different pages.
|
; plus 0x1000 if BufEnd and CurBufPtr are in different pages.
|
||||||
mov edx, [ebx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart]
|
mov edx, [ebx+ohci_gtd.BufEnd-sizeof.ohci_gtd]
|
||||||
mov eax, [ebx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart]
|
mov eax, [ebx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd]
|
||||||
mov ecx, edx
|
mov ecx, edx
|
||||||
and edx, 0xFFF
|
and edx, 0xFFF
|
||||||
inc edx
|
inc edx
|
||||||
@ -1425,7 +1414,7 @@ proc ohci_process_finalized_td
|
|||||||
neg edx
|
neg edx
|
||||||
; 4. Check for error. If so, go to 7.
|
; 4. Check for error. If so, go to 7.
|
||||||
push ebx
|
push ebx
|
||||||
mov eax, [ebx+ohci_gtd.Flags-ohci_gtd.SoftwarePart]
|
mov eax, [ebx+ohci_gtd.Flags-sizeof.ohci_gtd]
|
||||||
shr eax, 28
|
shr eax, 28
|
||||||
jnz .error
|
jnz .error
|
||||||
.notify:
|
.notify:
|
||||||
@ -1451,7 +1440,7 @@ proc ohci_process_finalized_td
|
|||||||
stdcall usb1_free_general_td, ebx
|
stdcall usb1_free_general_td, ebx
|
||||||
@@:
|
@@:
|
||||||
pop ebx
|
pop ebx
|
||||||
lea eax, [ebx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart]
|
lea eax, [ebx+ohci_gtd.NextTD-sizeof.ohci_gtd]
|
||||||
.next_td2:
|
.next_td2:
|
||||||
push ebx
|
push ebx
|
||||||
mov ebx, eax
|
mov ebx, eax
|
||||||
@ -1484,10 +1473,10 @@ proc ohci_process_finalized_td
|
|||||||
push eax
|
push eax
|
||||||
push edx
|
push edx
|
||||||
; DEBUGF 1,'K : TD failed:\n'
|
; DEBUGF 1,'K : TD failed:\n'
|
||||||
; 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]
|
; 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]
|
||||||
; 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]
|
; 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]
|
||||||
; mov eax, [ebx+usb_gtd.Pipe]
|
; mov eax, [ebx+usb_gtd.Pipe]
|
||||||
; 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]
|
; 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]
|
||||||
; 7b. Traverse the list of descriptors looking for the final packet
|
; 7b. Traverse the list of descriptors looking for the final packet
|
||||||
; for this transfer.
|
; for this transfer.
|
||||||
; Free and unlink non-final descriptors, except the current one.
|
; Free and unlink non-final descriptors, except the current one.
|
||||||
@ -1517,18 +1506,18 @@ end virtual
|
|||||||
; After that, go to step 5 with eax = 0 (no error).
|
; After that, go to step 5 with eax = 0 (no error).
|
||||||
cmp dword [.error_code], USB_STATUS_UNDERRUN
|
cmp dword [.error_code], USB_STATUS_UNDERRUN
|
||||||
jnz .no_underrun
|
jnz .no_underrun
|
||||||
test byte [ebx+ohci_gtd.Flags+2-ohci_gtd.SoftwarePart], 1 shl (18-16)
|
test byte [ebx+ohci_gtd.Flags+2-sizeof.ohci_gtd], 1 shl (18-16)
|
||||||
jz .no_underrun
|
jz .no_underrun
|
||||||
and dword [.error_code], 0
|
and dword [.error_code], 0
|
||||||
mov ecx, [ebx+usb_gtd.Pipe]
|
mov ecx, [ebx+usb_gtd.Pipe]
|
||||||
mov edx, [ecx+ohci_pipe.HeadP-ohci_pipe.SoftwarePart]
|
mov edx, [ecx+ohci_pipe.HeadP-sizeof.ohci_pipe]
|
||||||
and edx, 2
|
and edx, 2
|
||||||
.advance_queue:
|
.advance_queue:
|
||||||
mov eax, [ebx+usb_gtd.NextVirt]
|
mov eax, [ebx+usb_gtd.NextVirt]
|
||||||
sub eax, ohci_gtd.SoftwarePart
|
sub eax, sizeof.ohci_gtd
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
or eax, edx
|
or eax, edx
|
||||||
mov [ecx+ohci_pipe.HeadP-ohci_pipe.SoftwarePart], eax
|
mov [ecx+ohci_pipe.HeadP-sizeof.ohci_pipe], eax
|
||||||
push ebx
|
push ebx
|
||||||
mov ebx, ecx
|
mov ebx, ecx
|
||||||
call ohci_notify_new_work
|
call ohci_notify_new_work
|
||||||
@ -1562,7 +1551,7 @@ end virtual
|
|||||||
; support functional stall as well, but this is not recommended.").
|
; support functional stall as well, but this is not recommended.").
|
||||||
; Advance the transfer queue to the next descriptor.
|
; Advance the transfer queue to the next descriptor.
|
||||||
mov ecx, [ebx+usb_gtd.Pipe]
|
mov ecx, [ebx+usb_gtd.Pipe]
|
||||||
mov edx, [ecx+ohci_pipe.HeadP-ohci_pipe.SoftwarePart]
|
mov edx, [ecx+ohci_pipe.HeadP-sizeof.ohci_pipe]
|
||||||
and edx, 2 ; keep toggleCarry bit
|
and edx, 2 ; keep toggleCarry bit
|
||||||
cmp [ecx+usb_pipe.Type], CONTROL_PIPE
|
cmp [ecx+usb_pipe.Type], CONTROL_PIPE
|
||||||
jnz @f
|
jnz @f
|
||||||
@ -1577,7 +1566,7 @@ endp
|
|||||||
proc ohci_unlink_pipe
|
proc ohci_unlink_pipe
|
||||||
cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE
|
cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE
|
||||||
jnz @f
|
jnz @f
|
||||||
mov eax, [ebx+ohci_pipe.Flags-ohci_pipe.SoftwarePart]
|
mov eax, [ebx+ohci_pipe.Flags-sizeof.ohci_pipe]
|
||||||
bt eax, 13
|
bt eax, 13
|
||||||
setc cl
|
setc cl
|
||||||
bt eax, 11
|
bt eax, 11
|
||||||
@ -1589,7 +1578,7 @@ proc ohci_unlink_pipe
|
|||||||
mov eax, [ebx+usb_pipe.PrevVirt]
|
mov eax, [ebx+usb_pipe.PrevVirt]
|
||||||
mov [edx+usb_pipe.PrevVirt], eax
|
mov [edx+usb_pipe.PrevVirt], eax
|
||||||
mov [eax+usb_pipe.NextVirt], edx
|
mov [eax+usb_pipe.NextVirt], edx
|
||||||
mov edx, [ebx+ohci_pipe.NextED-ohci_pipe.SoftwarePart]
|
mov edx, [ebx+ohci_pipe.NextED-sizeof.ohci_pipe]
|
||||||
mov [eax+ohci_pipe.NextED-ohci_pipe.SoftwarePart], edx
|
mov [eax+ohci_pipe.NextED-sizeof.ohci_pipe], edx
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
@ -432,14 +432,14 @@ endp
|
|||||||
; in the list header.
|
; in the list header.
|
||||||
proc ehci_hs_interrupt_list_unlink
|
proc ehci_hs_interrupt_list_unlink
|
||||||
; get target list
|
; get target list
|
||||||
mov edx, [ebx+ehci_pipe.BaseList-ehci_pipe.SoftwarePart]
|
mov edx, [ebx+ehci_pipe.BaseList-sizeof.ehci_pipe]
|
||||||
; TODO: calculate real bandwidth
|
; TODO: calculate real bandwidth
|
||||||
movzx eax, word [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart+2]
|
movzx eax, word [ebx+ehci_pipe.Token-sizeof.ehci_pipe+2]
|
||||||
mov ecx, [ebx+ehci_pipe.Flags-ehci_pipe.SoftwarePart]
|
mov ecx, [ebx+ehci_pipe.Flags-sizeof.ehci_pipe]
|
||||||
and eax, (1 shl 11) - 1
|
and eax, (1 shl 11) - 1
|
||||||
shr ecx, 30
|
shr ecx, 30
|
||||||
imul eax, ecx
|
imul eax, ecx
|
||||||
movzx ecx, byte [ebx+ehci_pipe.Flags-ehci_pipe.SoftwarePart]
|
movzx ecx, byte [ebx+ehci_pipe.Flags-sizeof.ehci_pipe]
|
||||||
add edx, ehci_static_ep.Bandwidths - ehci_static_ep.SoftwarePart
|
add edx, ehci_static_ep.Bandwidths - ehci_static_ep.SoftwarePart
|
||||||
; update bandwidth
|
; update bandwidth
|
||||||
.dec_bandwidth:
|
.dec_bandwidth:
|
||||||
|
@ -42,8 +42,8 @@ UHCI_INVALID_LENGTH = 700h
|
|||||||
; software book-keeping.
|
; software book-keeping.
|
||||||
; * The hardware requires 16-bytes alignment of the hardware part.
|
; * The hardware requires 16-bytes alignment of the hardware part.
|
||||||
; Since the allocator (usb_allocate_common) allocates memory sequentially
|
; Since the allocator (usb_allocate_common) allocates memory sequentially
|
||||||
; from page start (aligned on 0x1000 bytes), size of the structure must be
|
; from page start (aligned on 0x1000 bytes), block size for the allocator
|
||||||
; divisible by 16.
|
; must be divisible by 16; usb1_allocate_endpoint ensures this.
|
||||||
struct uhci_pipe
|
struct uhci_pipe
|
||||||
NextQH dd ?
|
NextQH dd ?
|
||||||
; 1. First bit (bit 0) is Terminate bit. 1 = there is no next QH.
|
; 1. First bit (bit 0) is Terminate bit. 1 = there is no next QH.
|
||||||
@ -81,14 +81,8 @@ Token dd ?
|
|||||||
ErrorTD dd ?
|
ErrorTD dd ?
|
||||||
; Usually NULL. If nonzero, it is a pointer to descriptor which was error'd
|
; Usually NULL. If nonzero, it is a pointer to descriptor which was error'd
|
||||||
; and should be freed sometime in the future (the hardware could still use it).
|
; and should be freed sometime in the future (the hardware could still use it).
|
||||||
SoftwarePart rd sizeof.usb_pipe/4
|
|
||||||
; Common part for all controllers, described by usb_pipe structure.
|
|
||||||
ends
|
ends
|
||||||
|
|
||||||
if sizeof.uhci_pipe mod 16
|
|
||||||
.err uhci_pipe must be 16-bytes aligned
|
|
||||||
end if
|
|
||||||
|
|
||||||
; This structure describes the static head of every list of pipes.
|
; This structure describes the static head of every list of pipes.
|
||||||
; The hardware requires 16-bytes alignment of this structure.
|
; The hardware requires 16-bytes alignment of this structure.
|
||||||
; All instances of this structure are located sequentially in uhci_controller,
|
; All instances of this structure are located sequentially in uhci_controller,
|
||||||
@ -167,7 +161,8 @@ end if
|
|||||||
; * The hardware requires 16-bytes alignment of the hardware part, so
|
; * The hardware requires 16-bytes alignment of the hardware part, so
|
||||||
; the entire descriptor must be 16-bytes aligned. Since the allocator
|
; the entire descriptor must be 16-bytes aligned. Since the allocator
|
||||||
; (uhci_allocate_common) allocates memory sequentially from page start
|
; (uhci_allocate_common) allocates memory sequentially from page start
|
||||||
; (aligned on 0x1000 bytes), size of the structure must be divisible by 16.
|
; (aligned on 0x1000 bytes), block size for the allocator must be
|
||||||
|
; divisible by 16; usb1_allocate_general_td ensures this.
|
||||||
struct uhci_gtd
|
struct uhci_gtd
|
||||||
NextTD dd ?
|
NextTD dd ?
|
||||||
; 1. First bit (bit 0) is Terminate bit. 1 = there is no next TD.
|
; 1. First bit (bit 0) is Terminate bit. 1 = there is no next TD.
|
||||||
@ -231,14 +226,8 @@ OrigBufferInfo dd ?
|
|||||||
; bit 0: 1 = short packet is NOT allowed
|
; bit 0: 1 = short packet is NOT allowed
|
||||||
; (before the TD is processed, it is the copy of bit 29 of ControlStatus;
|
; (before the TD is processed, it is the copy of bit 29 of ControlStatus;
|
||||||
; some controllers modify that bit, so we need a copy in a safe place)
|
; some controllers modify that bit, so we need a copy in a safe place)
|
||||||
SoftwarePart rd sizeof.usb_gtd/4
|
|
||||||
; Software part, common for all controllers.
|
|
||||||
ends
|
ends
|
||||||
|
|
||||||
if sizeof.uhci_gtd mod 16
|
|
||||||
.err uhci_gtd must be 16-bytes aligned
|
|
||||||
end if
|
|
||||||
|
|
||||||
; UHCI requires that the entire transfer buffer should be on one page.
|
; UHCI requires that the entire transfer buffer should be on one page.
|
||||||
; If the actual buffer crosses page boundary, uhci_alloc_packet
|
; If the actual buffer crosses page boundary, uhci_alloc_packet
|
||||||
; allocates additional memory for buffer for hardware.
|
; allocates additional memory for buffer for hardware.
|
||||||
@ -853,7 +842,7 @@ proc uhci_process_updated_list
|
|||||||
; if either of conditions holds, exit from the internal loop.
|
; if either of conditions holds, exit from the internal loop.
|
||||||
cmp ebx, [esp]
|
cmp ebx, [esp]
|
||||||
jz .tddone
|
jz .tddone
|
||||||
mov eax, [ebx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart]
|
mov eax, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd]
|
||||||
test eax, 1 shl 23 ; active?
|
test eax, 1 shl 23 ; active?
|
||||||
jnz .tddone
|
jnz .tddone
|
||||||
; Release the queue lock while processing one descriptor:
|
; Release the queue lock while processing one descriptor:
|
||||||
@ -889,10 +878,10 @@ proc uhci_process_finalized_td
|
|||||||
; DEBUGF 1,'K : %x %x %x %x\n',[ebx-4],[ebx],[ebx+4],[ebx+8]
|
; DEBUGF 1,'K : %x %x %x %x\n',[ebx-4],[ebx],[ebx+4],[ebx+8]
|
||||||
; 2. If this is IN transfer into special buffer, copy the data
|
; 2. If this is IN transfer into special buffer, copy the data
|
||||||
; to target location.
|
; to target location.
|
||||||
mov edx, [ebx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart]
|
mov edx, [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
|
||||||
and edx, not 1 ; clear lsb (used for another goal)
|
and edx, not 1 ; clear lsb (used for another goal)
|
||||||
jz .nocopy
|
jz .nocopy
|
||||||
cmp byte [ebx+uhci_gtd.Token-uhci_gtd.SoftwarePart], USB_PID_IN
|
cmp byte [ebx+uhci_gtd.Token-sizeof.uhci_gtd], USB_PID_IN
|
||||||
jnz .nocopy
|
jnz .nocopy
|
||||||
; Note: we assume that pointer to buffer is valid in the memory space of
|
; Note: we assume that pointer to buffer is valid in the memory space of
|
||||||
; the USB thread. This means that buffer must reside in kernel memory
|
; the USB thread. This means that buffer must reside in kernel memory
|
||||||
@ -900,7 +889,7 @@ proc uhci_process_finalized_td
|
|||||||
push esi edi
|
push esi edi
|
||||||
mov esi, [edx+uhci_original_buffer.UsedBuffer]
|
mov esi, [edx+uhci_original_buffer.UsedBuffer]
|
||||||
mov edi, [edx+uhci_original_buffer.OrigBuffer]
|
mov edi, [edx+uhci_original_buffer.OrigBuffer]
|
||||||
mov ecx, [ebx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart]
|
mov ecx, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd]
|
||||||
inc ecx
|
inc ecx
|
||||||
and ecx, 7FFh
|
and ecx, 7FFh
|
||||||
mov edx, ecx
|
mov edx, ecx
|
||||||
@ -913,8 +902,8 @@ proc uhci_process_finalized_td
|
|||||||
.nocopy:
|
.nocopy:
|
||||||
; 3. Calculate actual number of bytes transferred.
|
; 3. Calculate actual number of bytes transferred.
|
||||||
; 3a. Read the state.
|
; 3a. Read the state.
|
||||||
mov eax, [ebx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart]
|
mov eax, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd]
|
||||||
mov ecx, [ebx+uhci_gtd.Token-uhci_gtd.SoftwarePart]
|
mov ecx, [ebx+uhci_gtd.Token-sizeof.uhci_gtd]
|
||||||
; 3b. Get number of bytes processed.
|
; 3b. Get number of bytes processed.
|
||||||
lea edx, [eax+1]
|
lea edx, [eax+1]
|
||||||
and edx, 7FFh
|
and edx, 7FFh
|
||||||
@ -938,7 +927,7 @@ proc uhci_process_finalized_td
|
|||||||
xor ecx, ecx
|
xor ecx, ecx
|
||||||
test eax, 1 shl 22
|
test eax, 1 shl 22
|
||||||
jnz .error
|
jnz .error
|
||||||
test byte [ebx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], 1
|
test byte [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1
|
||||||
jz .notify
|
jz .notify
|
||||||
cmp edx, [ebx+usb_gtd.Length]
|
cmp edx, [ebx+usb_gtd.Length]
|
||||||
jz .notify
|
jz .notify
|
||||||
@ -946,7 +935,7 @@ proc uhci_process_finalized_td
|
|||||||
; 5. There was an error while processing this packet.
|
; 5. There was an error while processing this packet.
|
||||||
; The hardware has stopped processing the queue.
|
; The hardware has stopped processing the queue.
|
||||||
DEBUGF 1,'K : TD failed:\n'
|
DEBUGF 1,'K : TD failed:\n'
|
||||||
if uhci_gtd.SoftwarePart <> 20
|
if sizeof.uhci_gtd <> 20
|
||||||
.err modify offsets for debug output
|
.err modify offsets for debug output
|
||||||
end if
|
end if
|
||||||
DEBUGF 1,'K : %x %x %x %x\n',[ebx-20],[ebx-16],[ebx-12],[ebx-8]
|
DEBUGF 1,'K : %x %x %x %x\n',[ebx-20],[ebx-16],[ebx-12],[ebx-8]
|
||||||
@ -955,17 +944,17 @@ end if
|
|||||||
push edx
|
push edx
|
||||||
push eax
|
push eax
|
||||||
mov eax, [ebx+usb_gtd.Pipe]
|
mov eax, [ebx+usb_gtd.Pipe]
|
||||||
DEBUGF 1,'K : pipe: %x %x\n',[eax+0-uhci_pipe.SoftwarePart],[eax+4-uhci_pipe.SoftwarePart]
|
DEBUGF 1,'K : pipe: %x %x\n',[eax+0-sizeof.uhci_pipe],[eax+4-sizeof.uhci_pipe]
|
||||||
; 5b. Store the current TD as an error packet.
|
; 5b. Store the current TD as an error packet.
|
||||||
; If an error packet is already stored for this pipe,
|
; If an error packet is already stored for this pipe,
|
||||||
; it is definitely not used already, so free the old packet.
|
; it is definitely not used already, so free the old packet.
|
||||||
mov eax, [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart]
|
mov eax, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
stdcall uhci_free_td, eax
|
stdcall uhci_free_td, eax
|
||||||
@@:
|
@@:
|
||||||
mov eax, [ebx+usb_gtd.Pipe]
|
mov eax, [ebx+usb_gtd.Pipe]
|
||||||
mov [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart], ebx
|
mov [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe], ebx
|
||||||
; 5c. Traverse the list of descriptors looking for the final packet
|
; 5c. Traverse the list of descriptors looking for the final packet
|
||||||
; for this transfer.
|
; for this transfer.
|
||||||
; Free and unlink non-final descriptors, except the current one.
|
; Free and unlink non-final descriptors, except the current one.
|
||||||
@ -1019,17 +1008,17 @@ end if
|
|||||||
; After that, go to step 6 with ecx = 0 (no error).
|
; After that, go to step 6 with ecx = 0 (no error).
|
||||||
cmp ecx, USB_STATUS_UNDERRUN
|
cmp ecx, USB_STATUS_UNDERRUN
|
||||||
jnz @f
|
jnz @f
|
||||||
test byte [ebx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], 1
|
test byte [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1
|
||||||
jnz @f
|
jnz @f
|
||||||
; The controller has stopped this queue on the error packet.
|
; The controller has stopped this queue on the error packet.
|
||||||
; Update uhci_pipe.HeadTD to point to the next packet in the queue.
|
; Update uhci_pipe.HeadTD to point to the next packet in the queue.
|
||||||
call uhci_fix_toggle
|
call uhci_fix_toggle
|
||||||
xor ecx, ecx
|
xor ecx, ecx
|
||||||
.control:
|
.control:
|
||||||
mov eax, [ebx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart]
|
mov eax, [ebx+uhci_gtd.NextTD-sizeof.uhci_gtd]
|
||||||
and al, not 0xF
|
and al, not 0xF
|
||||||
mov edx, [ebx+usb_gtd.Pipe]
|
mov edx, [ebx+usb_gtd.Pipe]
|
||||||
mov [edx+uhci_pipe.HeadTD-uhci_pipe.SoftwarePart], eax
|
mov [edx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax
|
||||||
pop edx ; length
|
pop edx ; length
|
||||||
jmp .notify
|
jmp .notify
|
||||||
@@:
|
@@:
|
||||||
@ -1047,7 +1036,7 @@ end if
|
|||||||
push ecx
|
push ecx
|
||||||
mov eax, [ebx+usb_gtd.Pipe]
|
mov eax, [ebx+usb_gtd.Pipe]
|
||||||
push [ebx+usb_gtd.NextVirt]
|
push [ebx+usb_gtd.NextVirt]
|
||||||
cmp ebx, [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart]
|
cmp ebx, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
|
||||||
jz @f
|
jz @f
|
||||||
stdcall uhci_free_td, ebx
|
stdcall uhci_free_td, ebx
|
||||||
@@:
|
@@:
|
||||||
@ -1065,10 +1054,10 @@ end if
|
|||||||
cmp [edx+usb_pipe.Type], CONTROL_PIPE
|
cmp [edx+usb_pipe.Type], CONTROL_PIPE
|
||||||
jz .control
|
jz .control
|
||||||
; Bulk/interrupt transfer; halt the queue.
|
; Bulk/interrupt transfer; halt the queue.
|
||||||
mov eax, [ebx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart]
|
mov eax, [ebx+uhci_gtd.NextTD-sizeof.uhci_gtd]
|
||||||
and al, not 0xF
|
and al, not 0xF
|
||||||
inc eax ; set Halted bit
|
inc eax ; set Halted bit
|
||||||
mov [edx+uhci_pipe.HeadTD-uhci_pipe.SoftwarePart], eax
|
mov [edx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax
|
||||||
pop edx ; restore length saved in step 5a
|
pop edx ; restore length saved in step 5a
|
||||||
.notify:
|
.notify:
|
||||||
; 6. Either the descriptor in ebx was processed without errors,
|
; 6. Either the descriptor in ebx was processed without errors,
|
||||||
@ -1094,7 +1083,7 @@ end if
|
|||||||
push [ebx+usb_gtd.NextVirt]
|
push [ebx+usb_gtd.NextVirt]
|
||||||
; 7b. Free the descriptor, unless it is saved as ErrorTD.
|
; 7b. Free the descriptor, unless it is saved as ErrorTD.
|
||||||
mov eax, [ebx+usb_gtd.Pipe]
|
mov eax, [ebx+usb_gtd.Pipe]
|
||||||
cmp [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart], ebx
|
cmp [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe], ebx
|
||||||
jz @f
|
jz @f
|
||||||
stdcall uhci_free_td, ebx
|
stdcall uhci_free_td, ebx
|
||||||
@@:
|
@@:
|
||||||
@ -1118,9 +1107,9 @@ proc uhci_fix_toggle
|
|||||||
; 2. The hardware expects next packet with toggle = (ErrorTD.toggle xor 1),
|
; 2. The hardware expects next packet with toggle = (ErrorTD.toggle xor 1),
|
||||||
; the current value in next packet is (ebx.toggle xor 1).
|
; the current value in next packet is (ebx.toggle xor 1).
|
||||||
; Nothing to do if ErrorTD.toggle == ebx.toggle.
|
; Nothing to do if ErrorTD.toggle == ebx.toggle.
|
||||||
mov eax, [ecx+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart]
|
mov eax, [ecx+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
|
||||||
mov eax, [eax+uhci_gtd.Token-uhci_gtd.SoftwarePart]
|
mov eax, [eax+uhci_gtd.Token-sizeof.uhci_gtd]
|
||||||
xor eax, [ebx+uhci_gtd.Token-uhci_gtd.SoftwarePart]
|
xor eax, [ebx+uhci_gtd.Token-sizeof.uhci_gtd]
|
||||||
test eax, 1 shl 19
|
test eax, 1 shl 19
|
||||||
jz .nothing
|
jz .nothing
|
||||||
; 3. Lock the transfer queue.
|
; 3. Lock the transfer queue.
|
||||||
@ -1130,13 +1119,13 @@ proc uhci_fix_toggle
|
|||||||
; (inclusive).
|
; (inclusive).
|
||||||
mov eax, [ebx+usb_gtd.NextVirt]
|
mov eax, [ebx+usb_gtd.NextVirt]
|
||||||
.loop:
|
.loop:
|
||||||
xor byte [eax+uhci_gtd.Token-uhci_gtd.SoftwarePart+2], 1 shl (19-16)
|
xor byte [eax+uhci_gtd.Token-sizeof.uhci_gtd+2], 1 shl (19-16)
|
||||||
cmp eax, [ecx+usb_pipe.LastTD-usb_pipe.Lock]
|
cmp eax, [ecx+usb_pipe.LastTD-usb_pipe.Lock]
|
||||||
mov eax, [eax+usb_gtd.NextVirt]
|
mov eax, [eax+usb_gtd.NextVirt]
|
||||||
jnz .loop
|
jnz .loop
|
||||||
; 5. Flip the toggle bit in uhci_pipe structure.
|
; 5. Flip the toggle bit in uhci_pipe structure.
|
||||||
xor byte [ecx+uhci_pipe.Token-uhci_pipe.SoftwarePart-usb_pipe.Lock+2], 1 shl (19-16)
|
xor byte [ecx+uhci_pipe.Token-sizeof.uhci_pipe-usb_pipe.Lock+2], 1 shl (19-16)
|
||||||
or dword [ecx+uhci_pipe.Token-uhci_pipe.SoftwarePart-usb_pipe.Lock], eax
|
or dword [ecx+uhci_pipe.Token-sizeof.uhci_pipe-usb_pipe.Lock], eax
|
||||||
; 6. Unlock the transfer queue.
|
; 6. Unlock the transfer queue.
|
||||||
call mutex_unlock
|
call mutex_unlock
|
||||||
.nothing:
|
.nothing:
|
||||||
@ -1338,7 +1327,7 @@ endp
|
|||||||
; and stores USB device address in the uhci_pipe structure.
|
; and stores USB device address in the uhci_pipe structure.
|
||||||
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
|
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
|
||||||
proc uhci_set_device_address
|
proc uhci_set_device_address
|
||||||
mov byte [ebx+uhci_pipe.Token+1-uhci_pipe.SoftwarePart], cl
|
mov byte [ebx+uhci_pipe.Token+1-sizeof.uhci_pipe], cl
|
||||||
call usb_subscription_done
|
call usb_subscription_done
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -1347,7 +1336,7 @@ endp
|
|||||||
; in: esi -> usb_controller, ebx -> usb_pipe
|
; in: esi -> usb_controller, ebx -> usb_pipe
|
||||||
; out: eax = endpoint address
|
; out: eax = endpoint address
|
||||||
proc uhci_get_device_address
|
proc uhci_get_device_address
|
||||||
mov al, byte [ebx+uhci_pipe.Token+1-uhci_pipe.SoftwarePart]
|
mov al, byte [ebx+uhci_pipe.Token+1-sizeof.uhci_pipe]
|
||||||
and eax, 7Fh
|
and eax, 7Fh
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -1372,8 +1361,8 @@ endp
|
|||||||
proc uhci_set_endpoint_packet_size
|
proc uhci_set_endpoint_packet_size
|
||||||
dec ecx
|
dec ecx
|
||||||
shl ecx, 21
|
shl ecx, 21
|
||||||
and [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart], (1 shl 21) - 1
|
and [ebx+uhci_pipe.Token-sizeof.uhci_pipe], (1 shl 21) - 1
|
||||||
or [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart], ecx
|
or [ebx+uhci_pipe.Token-sizeof.uhci_pipe], ecx
|
||||||
; uhci_pipe.Token field is purely for software bookkeeping and does not affect
|
; uhci_pipe.Token field is purely for software bookkeeping and does not affect
|
||||||
; the hardware; thus, we can continue initialization immediately.
|
; the hardware; thus, we can continue initialization immediately.
|
||||||
call usb_subscription_done
|
call usb_subscription_done
|
||||||
@ -1395,18 +1384,18 @@ virtual at ebp+8
|
|||||||
.interval dd ?
|
.interval dd ?
|
||||||
end virtual
|
end virtual
|
||||||
; 1. Initialize ErrorTD to zero.
|
; 1. Initialize ErrorTD to zero.
|
||||||
and [edi+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart], 0
|
and [edi+uhci_pipe.ErrorTD-sizeof.uhci_pipe], 0
|
||||||
; 2. Initialize HeadTD to the physical address of the first TD.
|
; 2. Initialize HeadTD to the physical address of the first TD.
|
||||||
push eax ; store pointer to the first TD for step ?
|
push eax ; store pointer to the first TD for step ?
|
||||||
sub eax, uhci_gtd.SoftwarePart
|
sub eax, sizeof.uhci_gtd
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
mov [edi+uhci_pipe.HeadTD-uhci_pipe.SoftwarePart], eax
|
mov [edi+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax
|
||||||
; 3. Initialize Token field:
|
; 3. Initialize Token field:
|
||||||
; take DeviceAddress and LowSpeedDevice from the parent pipe,
|
; take DeviceAddress and LowSpeedDevice from the parent pipe,
|
||||||
; take Endpoint and MaximumLength fields from API arguments,
|
; take Endpoint and MaximumLength fields from API arguments,
|
||||||
; set PID depending on pipe type and provided pipe direction,
|
; set PID depending on pipe type and provided pipe direction,
|
||||||
; set DataToggle to zero.
|
; set DataToggle to zero.
|
||||||
mov eax, [ecx+uhci_pipe.Token-uhci_pipe.SoftwarePart]
|
mov eax, [ecx+uhci_pipe.Token-sizeof.uhci_pipe]
|
||||||
and eax, 0x107F00 ; keep DeviceAddress and LowSpeedDevice
|
and eax, 0x107F00 ; keep DeviceAddress and LowSpeedDevice
|
||||||
mov edx, [.endpoint]
|
mov edx, [.endpoint]
|
||||||
and edx, 15
|
and edx, 15
|
||||||
@ -1424,20 +1413,20 @@ end virtual
|
|||||||
jz @f
|
jz @f
|
||||||
mov al, USB_PID_IN
|
mov al, USB_PID_IN
|
||||||
@@:
|
@@:
|
||||||
mov [edi+uhci_pipe.Token-uhci_pipe.SoftwarePart], eax
|
mov [edi+uhci_pipe.Token-sizeof.uhci_pipe], eax
|
||||||
; 4. Initialize the first TD:
|
; 4. Initialize the first TD:
|
||||||
; copy Token from uhci_pipe.Token zeroing reserved bit 20,
|
; copy Token from uhci_pipe.Token zeroing reserved bit 20,
|
||||||
; set ControlStatus for future transfers, bit make it inactive,
|
; set ControlStatus for future transfers, bit make it inactive,
|
||||||
; set bit 0 in NextTD = "no next TD".
|
; set bit 0 in NextTD = "no next TD".
|
||||||
pop edx ; restore pointer saved in step 2
|
pop edx ; restore pointer saved in step 2
|
||||||
mov [edx+uhci_gtd.Token-uhci_gtd.SoftwarePart], eax
|
mov [edx+uhci_gtd.Token-sizeof.uhci_gtd], eax
|
||||||
and byte [edx+uhci_gtd.Token+2-uhci_gtd.SoftwarePart], not (1 shl (20-16))
|
and byte [edx+uhci_gtd.Token+2-sizeof.uhci_gtd], not (1 shl (20-16))
|
||||||
and eax, 1 shl 20
|
and eax, 1 shl 20
|
||||||
shl eax, 6
|
shl eax, 6
|
||||||
or eax, UHCI_INVALID_LENGTH + (3 shl 27)
|
or eax, UHCI_INVALID_LENGTH + (3 shl 27)
|
||||||
; not processed, inactive, allow 3 errors
|
; not processed, inactive, allow 3 errors
|
||||||
mov [edx+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart], eax
|
mov [edx+uhci_gtd.ControlStatus-sizeof.uhci_gtd], eax
|
||||||
mov [edx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], 1
|
mov [edx+uhci_gtd.NextTD-sizeof.uhci_gtd], 1
|
||||||
; 5. Select the corresponding list and insert to the list.
|
; 5. Select the corresponding list and insert to the list.
|
||||||
; 5a. Use Control list for control pipes, Bulk list for bulk pipes.
|
; 5a. Use Control list for control pipes, Bulk list for bulk pipes.
|
||||||
lea edx, [esi+uhci_controller.ControlED.SoftwarePart-sizeof.uhci_controller]
|
lea edx, [esi+uhci_controller.ControlED.SoftwarePart-sizeof.uhci_controller]
|
||||||
@ -1471,8 +1460,8 @@ end virtual
|
|||||||
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
|
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
|
||||||
; store the physical address of the new pipe to previous NextQH.
|
; store the physical address of the new pipe to previous NextQH.
|
||||||
mov ecx, [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart]
|
mov ecx, [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart]
|
||||||
mov [edi+uhci_pipe.NextQH-uhci_pipe.SoftwarePart], ecx
|
mov [edi+uhci_pipe.NextQH-sizeof.uhci_pipe], ecx
|
||||||
lea eax, [edi-uhci_pipe.SoftwarePart]
|
lea eax, [edi-sizeof.uhci_pipe]
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
inc eax
|
inc eax
|
||||||
inc eax
|
inc eax
|
||||||
@ -1486,13 +1475,13 @@ endp
|
|||||||
|
|
||||||
; This procedure is called when a pipe is closing (either due to API call
|
; This procedure is called when a pipe is closing (either due to API call
|
||||||
; or due to disconnect); it unlinks a pipe from the corresponding list.
|
; or due to disconnect); it unlinks a pipe from the corresponding list.
|
||||||
if uhci_static_ep.SoftwarePart <> uhci_pipe.SoftwarePart
|
if uhci_static_ep.SoftwarePart <> sizeof.uhci_pipe
|
||||||
.err uhci_unlink_pipe assumes that uhci_static_ep.SoftwarePart == uhci_pipe.SoftwarePart
|
.err uhci_unlink_pipe assumes that uhci_static_ep.SoftwarePart == sizeof.uhci_pipe
|
||||||
end if
|
end if
|
||||||
proc uhci_unlink_pipe
|
proc uhci_unlink_pipe
|
||||||
cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE
|
cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE
|
||||||
jnz @f
|
jnz @f
|
||||||
mov eax, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart]
|
mov eax, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
|
||||||
cmp al, USB_PID_IN
|
cmp al, USB_PID_IN
|
||||||
setz ch
|
setz ch
|
||||||
bt eax, 20
|
bt eax, 20
|
||||||
@ -1510,8 +1499,8 @@ proc uhci_unlink_pipe
|
|||||||
mov [eax+usb_pipe.NextVirt], edx
|
mov [eax+usb_pipe.NextVirt], edx
|
||||||
; Note: eax could be either usb_pipe or usb_static_ep;
|
; Note: eax could be either usb_pipe or usb_static_ep;
|
||||||
; fortunately, NextQH and SoftwarePart have same offsets in both.
|
; fortunately, NextQH and SoftwarePart have same offsets in both.
|
||||||
mov edx, [ebx+uhci_pipe.NextQH-uhci_pipe.SoftwarePart]
|
mov edx, [ebx+uhci_pipe.NextQH-sizeof.uhci_pipe]
|
||||||
mov [eax+uhci_pipe.NextQH-uhci_pipe.SoftwarePart], edx
|
mov [eax+uhci_pipe.NextQH-sizeof.uhci_pipe], edx
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -1519,7 +1508,7 @@ endp
|
|||||||
; For UHCI, this includes usb_pipe structure and ErrorTD, if present.
|
; For UHCI, this includes usb_pipe structure and ErrorTD, if present.
|
||||||
proc uhci_free_pipe
|
proc uhci_free_pipe
|
||||||
mov eax, [esp+4]
|
mov eax, [esp+4]
|
||||||
mov eax, [eax+uhci_pipe.ErrorTD-uhci_pipe.SoftwarePart]
|
mov eax, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
stdcall uhci_free_td, eax
|
stdcall uhci_free_td, eax
|
||||||
@ -1544,7 +1533,7 @@ endl
|
|||||||
; with size <= endpoint max packet size.
|
; with size <= endpoint max packet size.
|
||||||
; 2. Get the maximum packet size for endpoint from uhci_pipe.Token
|
; 2. Get the maximum packet size for endpoint from uhci_pipe.Token
|
||||||
; and generate Token field for TDs.
|
; and generate Token field for TDs.
|
||||||
mov edi, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart]
|
mov edi, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
|
||||||
mov eax, edi
|
mov eax, edi
|
||||||
shr edi, 21
|
shr edi, 21
|
||||||
inc edi
|
inc edi
|
||||||
@ -1602,14 +1591,14 @@ endl
|
|||||||
; transparently to the caller.
|
; transparently to the caller.
|
||||||
test [flags], 1
|
test [flags], 1
|
||||||
jz @f
|
jz @f
|
||||||
and byte [ecx+uhci_gtd.ControlStatus+3-uhci_gtd.SoftwarePart], not (1 shl (29-24))
|
and byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], not (1 shl (29-24))
|
||||||
and byte [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], not 1
|
and byte [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], not 1
|
||||||
@@:
|
@@:
|
||||||
; 6. Update toggle bit in uhci_pipe structure from current value of [token].
|
; 6. Update toggle bit in uhci_pipe structure from current value of [token].
|
||||||
mov edx, [token]
|
mov edx, [token]
|
||||||
xor edx, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart]
|
xor edx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
|
||||||
and edx, 1 shl 19
|
and edx, 1 shl 19
|
||||||
xor [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart], edx
|
xor [ebx+uhci_pipe.Token-sizeof.uhci_pipe], edx
|
||||||
.nothing:
|
.nothing:
|
||||||
ret
|
ret
|
||||||
.fail:
|
.fail:
|
||||||
@ -1713,21 +1702,21 @@ end virtual
|
|||||||
; allocated), copy Token field from uhci_pipe.Token zeroing bit 20,
|
; allocated), copy Token field from uhci_pipe.Token zeroing bit 20,
|
||||||
; generate ControlStatus field, mark as Active
|
; generate ControlStatus field, mark as Active
|
||||||
; (for last descriptor, this will be changed by uhci_insert_transfer).
|
; (for last descriptor, this will be changed by uhci_insert_transfer).
|
||||||
mov [eax+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], 1 ; no next TD
|
mov [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 1 ; no next TD
|
||||||
mov edx, [ebx+uhci_pipe.Token-uhci_pipe.SoftwarePart]
|
mov edx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
|
||||||
mov [eax+uhci_gtd.Token-uhci_gtd.SoftwarePart], edx
|
mov [eax+uhci_gtd.Token-sizeof.uhci_gtd], edx
|
||||||
and byte [eax+uhci_gtd.Token+2-uhci_gtd.SoftwarePart], not (1 shl (20-16))
|
and byte [eax+uhci_gtd.Token+2-sizeof.uhci_gtd], not (1 shl (20-16))
|
||||||
and edx, 1 shl 20
|
and edx, 1 shl 20
|
||||||
shl edx, 6
|
shl edx, 6
|
||||||
or edx, UHCI_INVALID_LENGTH + (1 shl 23) + (3 shl 27)
|
or edx, UHCI_INVALID_LENGTH + (1 shl 23) + (3 shl 27)
|
||||||
; not processed, active, allow 3 errors
|
; not processed, active, allow 3 errors
|
||||||
mov [eax+uhci_gtd.ControlStatus-uhci_gtd.SoftwarePart], edx
|
mov [eax+uhci_gtd.ControlStatus-sizeof.uhci_gtd], edx
|
||||||
; 5. Initialize remaining fields of the current TD.
|
; 5. Initialize remaining fields of the current TD.
|
||||||
; 5a. Store pointer to the buffer allocated in step 1 (or zero).
|
; 5a. Store pointer to the buffer allocated in step 1 (or zero).
|
||||||
pop [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart]
|
pop [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
|
||||||
; 5b. Store physical address of the next TD.
|
; 5b. Store physical address of the next TD.
|
||||||
push eax
|
push eax
|
||||||
sub eax, uhci_gtd.SoftwarePart
|
sub eax, sizeof.uhci_gtd
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
; use Depth traversal unless this is the first TD in the transfer stage;
|
; use Depth traversal unless this is the first TD in the transfer stage;
|
||||||
; uhci_insert_transfer will set Depth traversal for the first TD and clear
|
; uhci_insert_transfer will set Depth traversal for the first TD and clear
|
||||||
@ -1736,21 +1725,21 @@ end virtual
|
|||||||
jz @f
|
jz @f
|
||||||
or eax, 4
|
or eax, 4
|
||||||
@@:
|
@@:
|
||||||
mov [ecx+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], eax
|
mov [ecx+uhci_gtd.NextTD-sizeof.uhci_gtd], eax
|
||||||
; 5c. Store physical address of the buffer: zero if no data present,
|
; 5c. Store physical address of the buffer: zero if no data present,
|
||||||
; the temporary buffer if it was allocated, the given buffer otherwise.
|
; the temporary buffer if it was allocated, the given buffer otherwise.
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
cmp [.packetSize], eax
|
cmp [.packetSize], eax
|
||||||
jz .hasphysbuf
|
jz .hasphysbuf
|
||||||
mov eax, [.buffer]
|
mov eax, [.buffer]
|
||||||
mov edx, [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart]
|
mov edx, [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
|
||||||
test edx, edx
|
test edx, edx
|
||||||
jz @f
|
jz @f
|
||||||
mov eax, [edx+uhci_original_buffer.UsedBuffer]
|
mov eax, [edx+uhci_original_buffer.UsedBuffer]
|
||||||
@@:
|
@@:
|
||||||
call get_phys_addr
|
call get_phys_addr
|
||||||
.hasphysbuf:
|
.hasphysbuf:
|
||||||
mov [ecx+uhci_gtd.Buffer-uhci_gtd.SoftwarePart], eax
|
mov [ecx+uhci_gtd.Buffer-sizeof.uhci_gtd], eax
|
||||||
; 5d. For IN transfers, disallow short packets.
|
; 5d. For IN transfers, disallow short packets.
|
||||||
; This will be overridden, if needed, by uhci_alloc_transfer.
|
; This will be overridden, if needed, by uhci_alloc_transfer.
|
||||||
mov eax, [.token]
|
mov eax, [.token]
|
||||||
@ -1758,13 +1747,13 @@ end virtual
|
|||||||
dec edx
|
dec edx
|
||||||
cmp al, USB_PID_IN
|
cmp al, USB_PID_IN
|
||||||
jnz @f
|
jnz @f
|
||||||
or byte [ecx+uhci_gtd.ControlStatus+3-uhci_gtd.SoftwarePart], 1 shl (29-24) ; disallow short packets
|
or byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (29-24) ; disallow short packets
|
||||||
or byte [ecx+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart], 1
|
or byte [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1
|
||||||
@@:
|
@@:
|
||||||
; 5e. Get Token field: combine [.token] with [.packetSize].
|
; 5e. Get Token field: combine [.token] with [.packetSize].
|
||||||
shl edx, 21
|
shl edx, 21
|
||||||
or edx, eax
|
or edx, eax
|
||||||
mov [ecx+uhci_gtd.Token-uhci_gtd.SoftwarePart], edx
|
mov [ecx+uhci_gtd.Token-sizeof.uhci_gtd], edx
|
||||||
; 6. Flip toggle bit in [.token].
|
; 6. Flip toggle bit in [.token].
|
||||||
xor eax, 1 shl 19
|
xor eax, 1 shl 19
|
||||||
mov [.token], eax
|
mov [.token], eax
|
||||||
@ -1785,11 +1774,11 @@ endp
|
|||||||
; ecx -> last descriptor for the transfer, ebx -> usb_pipe
|
; ecx -> last descriptor for the transfer, ebx -> usb_pipe
|
||||||
proc uhci_insert_transfer
|
proc uhci_insert_transfer
|
||||||
; DEBUGF 1,'K : uhci_insert_transfer: eax=%x, ecx=%x, [esp+4]=%x\n',eax,ecx,[esp+4]
|
; DEBUGF 1,'K : uhci_insert_transfer: eax=%x, ecx=%x, [esp+4]=%x\n',eax,ecx,[esp+4]
|
||||||
and byte [eax+uhci_gtd.ControlStatus+2-uhci_gtd.SoftwarePart], not (1 shl (23-16)) ; clear Active bit
|
and byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], not (1 shl (23-16)) ; clear Active bit
|
||||||
or byte [ecx+uhci_gtd.ControlStatus+3-uhci_gtd.SoftwarePart], 1 shl (24-24) ; set InterruptOnComplete bit
|
or byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (24-24) ; set InterruptOnComplete bit
|
||||||
mov eax, [esp+4]
|
mov eax, [esp+4]
|
||||||
or byte [eax+uhci_gtd.ControlStatus+2-uhci_gtd.SoftwarePart], 1 shl (23-16) ; set Active bit
|
or byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], 1 shl (23-16) ; set Active bit
|
||||||
or byte [eax+uhci_gtd.NextTD-uhci_gtd.SoftwarePart], 4 ; set Depth bit
|
or byte [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 4 ; set Depth bit
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -1798,13 +1787,13 @@ endp
|
|||||||
; and the temporary buffer, if present.
|
; and the temporary buffer, if present.
|
||||||
proc uhci_free_td
|
proc uhci_free_td
|
||||||
mov eax, [esp+4]
|
mov eax, [esp+4]
|
||||||
mov eax, [eax+uhci_gtd.OrigBufferInfo-uhci_gtd.SoftwarePart]
|
mov eax, [eax+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
|
||||||
and eax, not 1
|
and eax, not 1
|
||||||
jz .nobuf
|
jz .nobuf
|
||||||
push ebx
|
push ebx
|
||||||
call free
|
call free
|
||||||
pop ebx
|
pop ebx
|
||||||
.nobuf:
|
.nobuf:
|
||||||
sub dword [esp+4], uhci_gtd.SoftwarePart
|
sub dword [esp+4], sizeof.uhci_gtd
|
||||||
jmp usb_free_common
|
jmp usb_free_common
|
||||||
endp
|
endp
|
||||||
|
Loading…
Reference in New Issue
Block a user