Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 3652 → Rev 3653

/kernel/trunk/bus/usb/ohci.inc
44,8 → 44,8
; specification.
; * The hardware requires 16-bytes alignment of the hardware part.
; Since the allocator (usb_allocate_common) allocates memory sequentially
; from page start (aligned on 0x1000 bytes), size of the structure must be
; divisible by 16.
; from page start (aligned on 0x1000 bytes), block size for the allocator
; must be divisible by 16; usb1_allocate_endpoint ensures this.
struct ohci_pipe
; All addresses are physical.
Flags dd ?
95,14 → 95,8
; * There is no "next" list for Bulk and Control lists, they are processed
; separately from others.
; * There is no "next" list for Periodic list for 1ms interval.
SoftwarePart rd sizeof.usb_pipe/4
; Software part, common for all controllers.
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.
; The hardware requires 16-bytes alignment of this structure.
; All instances of this structure are located sequentially in uhci_controller,
204,7 → 198,8
; * The hardware requires 16-bytes alignment of the hardware part, so
; the entire descriptor must be 16-bytes aligned. Since the allocator
; (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
; ------------------------------ hardware fields ------------------------------
; All addresses in this part are physical.
248,15 → 243,9
; Virtual pointer to the next processed TD.
BufEnd dd ?
; Physical address of the last byte in the buffer for this TD.
dd ? ; padding for 16-bytes alignment
SoftwarePart rd sizeof.usb_gtd/4
; Common part for all controllers.
dd ? ; padding to align with uhci_gtd
ends
 
if sizeof.ohci_gtd mod 16
.err ohci_gtd must be 16-bytes aligned
end if
 
; OHCI isochronous transfer descriptor.
; * The structure describes transfers to be performed on Isochronous endpoints.
; * The structure includes two parts, the hardware part and the software part.
726,7 → 715,7
.tdloop:
mov ecx, [eax+ohci_gtd.NextTD]
mov [eax+ohci_gtd.NextTD], ebx
lea ebx, [eax+ohci_gtd.SoftwarePart]
lea ebx, [eax+sizeof.ohci_gtd]
test ecx, ecx
jz .tddone
call usb_td_to_virt
893,7 → 882,7
; and stores USB device address in the ohci_pipe structure.
; in: esi -> usb_controller, ebx -> usb_pipe, cl = 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.
call usb_subscribe_control
ret
903,7 → 892,7
; in: esi -> usb_controller, ebx -> usb_pipe
; out: eax = endpoint 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
ret
endp
923,7 → 912,7
; stores the packet size in ohci_pipe structure.
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = 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.
call usb_subscribe_control
ret
943,20 → 932,20
.interval dd ?
end virtual
; 1. Initialize the queue of transfer descriptors: empty.
sub eax, ohci_gtd.SoftwarePart
sub eax, sizeof.ohci_gtd
call get_phys_addr
mov [edi+ohci_pipe.TailP-ohci_pipe.SoftwarePart], eax
mov [edi+ohci_pipe.HeadP-ohci_pipe.SoftwarePart], eax
mov [edi+ohci_pipe.TailP-sizeof.ohci_pipe], eax
mov [edi+ohci_pipe.HeadP-sizeof.ohci_pipe], eax
; 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
mov edx, [.endpoint]
and edx, 15
shl edx, 7
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 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
jz @f
test byte [.endpoint], 80h
963,7 → 952,7
setnz al
inc eax
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.
; 3a. Use Control list for control pipes, Bulk list for bulk pipes.
992,11 → 981,11
mov [edi+usb_pipe.PrevVirt], edx
mov [ecx+usb_pipe.PrevVirt], edi
mov [edx+usb_pipe.NextVirt], edi
mov ecx, [edx+ohci_pipe.NextED-ohci_pipe.SoftwarePart]
mov [edi+ohci_pipe.NextED-ohci_pipe.SoftwarePart], ecx
lea eax, [edi-ohci_pipe.SoftwarePart]
mov ecx, [edx+ohci_pipe.NextED-sizeof.ohci_pipe]
mov [edi+ohci_pipe.NextED-sizeof.ohci_pipe], ecx
lea eax, [edi-sizeof.ohci_pipe]
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.
ret
.return0:
1094,7 → 1083,7
test eax, eax
jz .fail
; 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
; the last descriptor, but not in others.
; Note: even if the caller says that short transfers are ok,
1104,7 → 1093,7
; transparently to the caller.
test [flags], 1
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
.fail:
1143,24 → 1132,24
; 3. Save the returned value (next descriptor).
push eax
; 4. Store the physical address of the next descriptor.
sub eax, ohci_gtd.SoftwarePart
sub eax, sizeof.ohci_gtd
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.
; Otherwise, fill them with real values.
xor eax, eax
mov [ecx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], eax
mov [ecx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart], eax
mov [ecx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], eax
mov [ecx+ohci_gtd.BufEnd-sizeof.ohci_gtd], eax
cmp [.packetSize], eax
jz @f
mov eax, [.buffer]
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]
add eax, [.packetSize]
dec eax
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:
; - set bufferRounding (bit 18) to zero = disallow short transfers;
1179,7 → 1168,7
and edx, (3 shl 2)
shl edx, 24 - 2
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.
pop eax
.nothing:
1192,8 → 1181,8
; ecx -> last descriptor for the transfer, ebx -> usb_pipe
proc ohci_insert_transfer
; 1. Advance the queue of transfer descriptors.
mov eax, [ecx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart]
mov [ebx+ohci_pipe.TailP-ohci_pipe.SoftwarePart], eax
mov eax, [ecx+ohci_gtd.NextTD-sizeof.ohci_gtd]
mov [ebx+ohci_pipe.TailP-sizeof.ohci_pipe], eax
; 2. For control and bulk pipes, notify the controller that
; there is new work in control/bulk queue respectively.
ohci_notify_new_work:
1393,7 → 1382,7
mov edx, [ebx+usb_gtd.Pipe]
test [edx+usb_pipe.Flags], USB_FLAG_CLOSED
jz @f
lea eax, [ebx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart]
lea eax, [ebx+ohci_gtd.NextTD-sizeof.ohci_gtd]
xor ebx, ebx
jmp .next_td2
@@:
1402,13 → 1391,13
; 3. Get number of bytes that remain to be transferred.
; If CurBufPtr is zero, everything was transferred.
xor edx, edx
cmp [ebx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart], edx
cmp [ebx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd], edx
jz .gotlen
; Otherwise, the remaining length is
; (BufEnd and 0xFFF) - (CurBufPtr and 0xFFF) + 1,
; plus 0x1000 if BufEnd and CurBufPtr are in different pages.
mov edx, [ebx+ohci_gtd.BufEnd-ohci_gtd.SoftwarePart]
mov eax, [ebx+ohci_gtd.CurBufPtr-ohci_gtd.SoftwarePart]
mov edx, [ebx+ohci_gtd.BufEnd-sizeof.ohci_gtd]
mov eax, [ebx+ohci_gtd.CurBufPtr-sizeof.ohci_gtd]
mov ecx, edx
and edx, 0xFFF
inc edx
1425,7 → 1414,7
neg edx
; 4. Check for error. If so, go to 7.
push ebx
mov eax, [ebx+ohci_gtd.Flags-ohci_gtd.SoftwarePart]
mov eax, [ebx+ohci_gtd.Flags-sizeof.ohci_gtd]
shr eax, 28
jnz .error
.notify:
1451,7 → 1440,7
stdcall usb1_free_general_td, ebx
@@:
pop ebx
lea eax, [ebx+ohci_gtd.NextTD-ohci_gtd.SoftwarePart]
lea eax, [ebx+ohci_gtd.NextTD-sizeof.ohci_gtd]
.next_td2:
push ebx
mov ebx, eax
1484,10 → 1473,10
push eax
push edx
; 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-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],[ebx-sizeof.ohci_gtd+4],[ebx-sizeof.ohci_gtd+8],[ebx-sizeof.ohci_gtd+12]
; 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]
; 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
; for this transfer.
; Free and unlink non-final descriptors, except the current one.
1517,18 → 1506,18
; After that, go to step 5 with eax = 0 (no error).
cmp dword [.error_code], USB_STATUS_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
and dword [.error_code], 0
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
.advance_queue:
mov eax, [ebx+usb_gtd.NextVirt]
sub eax, ohci_gtd.SoftwarePart
sub eax, sizeof.ohci_gtd
call get_phys_addr
or eax, edx
mov [ecx+ohci_pipe.HeadP-ohci_pipe.SoftwarePart], eax
mov [ecx+ohci_pipe.HeadP-sizeof.ohci_pipe], eax
push ebx
mov ebx, ecx
call ohci_notify_new_work
1562,7 → 1551,7
; support functional stall as well, but this is not recommended.").
; Advance the transfer queue to the next descriptor.
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
cmp [ecx+usb_pipe.Type], CONTROL_PIPE
jnz @f
1577,7 → 1566,7
proc ohci_unlink_pipe
cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE
jnz @f
mov eax, [ebx+ohci_pipe.Flags-ohci_pipe.SoftwarePart]
mov eax, [ebx+ohci_pipe.Flags-sizeof.ohci_pipe]
bt eax, 13
setc cl
bt eax, 11
1589,7 → 1578,7
mov eax, [ebx+usb_pipe.PrevVirt]
mov [edx+usb_pipe.PrevVirt], eax
mov [eax+usb_pipe.NextVirt], edx
mov edx, [ebx+ohci_pipe.NextED-ohci_pipe.SoftwarePart]
mov [eax+ohci_pipe.NextED-ohci_pipe.SoftwarePart], edx
mov edx, [ebx+ohci_pipe.NextED-sizeof.ohci_pipe]
mov [eax+ohci_pipe.NextED-sizeof.ohci_pipe], edx
ret
endp