diff --git a/kernel/trunk/bus/usb/ehci.inc b/kernel/trunk/bus/usb/ehci.inc index 7257de1aee..4986e29c61 100644 --- a/kernel/trunk/bus/usb/ehci.inc +++ b/kernel/trunk/bus/usb/ehci.inc @@ -1045,22 +1045,29 @@ endl ; this corresponds to 4001h bytes. If the requested size is ; greater, we should split the transfer into several descriptors. ; Boundaries to split must be multiples of endpoint transfer size -; to avoid short packets except in the end of the transfer, -; 4000h is always a good value. +; to avoid short packets except in the end of the transfer. + cmp [size], 4001h + jbe .lastpacket ; 2. While the remaining data cannot fit in one descriptor, ; allocate full descriptors (of maximal possible size). - mov edi, 4000h +; 2a. Calculate size of one descriptor: must be a multiple of transfer size +; and must be not greater than 4001h. + movzx ecx, word [ebx+ohci_pipe.Flags+2-sizeof.ohci_pipe] + mov eax, 4001h + xor edx, edx + mov edi, eax + div ecx + sub edi, edx mov [packetSize], edi .fullpackets: - cmp [size], edi - jbe .lastpacket call ehci_alloc_packet test eax, eax jz .fail mov [td], eax add [buffer], edi sub [size], edi - jmp .fullpackets + cmp [size], 4001h + ja .fullpackets ; 3. The remaining data can fit in one packet; ; allocate the last descriptor with size = size of remaining data. .lastpacket: diff --git a/kernel/trunk/bus/usb/ohci.inc b/kernel/trunk/bus/usb/ohci.inc index 00d971a212..0cb85b4a02 100644 --- a/kernel/trunk/bus/usb/ohci.inc +++ b/kernel/trunk/bus/usb/ohci.inc @@ -1058,22 +1058,30 @@ endl ; this corresponds to 1001h bytes. If the requested size is ; greater, we should split the transfer into several descriptors. ; Boundaries to split must be multiples of endpoint transfer size -; to avoid short packets except in the end of the transfer, -; 1000h is always a good value. +; to avoid short packets except in the end of the transfer. + cmp [size], 1001h + jbe .lastpacket ; 2. While the remaining data cannot fit in one packet, -; allocate page-sized descriptors. - mov edi, 1000h +; allocate full-sized descriptors. +; 2a. Calculate size of one descriptor: must be a multiple of transfer size +; and must be not greater than 1001h. + movzx ecx, word [ebx+ohci_pipe.Flags+2-sizeof.ohci_pipe] + mov eax, 1001h + xor edx, edx + mov edi, eax + div ecx + sub edi, edx +; 2b. Allocate in loop. mov [packetSize], edi .fullpackets: - cmp [size], edi - jbe .lastpacket call ohci_alloc_packet test eax, eax jz .fail mov [td], eax add [buffer], edi sub [size], edi - jmp .fullpackets + cmp [size], 1001h + ja .fullpackets ; 3. The remaining data can fit in one descriptor; ; allocate the last descriptor with size = size of remaining data. .lastpacket: diff --git a/kernel/trunk/bus/usb/uhci.inc b/kernel/trunk/bus/usb/uhci.inc index f2ef56b382..4f179d35b0 100644 --- a/kernel/trunk/bus/usb/uhci.inc +++ b/kernel/trunk/bus/usb/uhci.inc @@ -20,9 +20,8 @@ USB_PID_IN = 69h USB_PID_OUT = 0E1h ; UHCI does not support an interrupt on root hub status change. We must poll ; the controller periodically. This is the period in timer ticks (10ms). -; We use the value 100 ms: it is valid value for USB hub poll rate (1-255 ms), -; small enough to be responsible to connect events and large enough to not -; load CPU too often. +; We use the value 100 ticks: it is small enough to be responsible to connect +; events and large enough to not load CPU too often. UHCI_POLL_INTERVAL = 100 ; the following constant is an invalid encoding for length fields in ; uhci_gtd; it is used to check whether an inactive TD has been @@ -1718,9 +1717,12 @@ end virtual push eax sub eax, sizeof.uhci_gtd call get_phys_addr -; use Depth traversal unless this is the first TD in the transfer stage; +; for Control/Bulk pipes, 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 ; it in the last TD + test [ebx+usb_pipe.Type], 1 + jnz @f cmp ecx, [ebx+usb_pipe.LastTD] jz @f or eax, 4 @@ -1778,7 +1780,10 @@ proc uhci_insert_transfer or byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (24-24) ; set InterruptOnComplete bit mov eax, [esp+4] or byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], 1 shl (23-16) ; set Active bit + test [ebx+usb_pipe.Type], 1 + jnz @f or byte [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 4 ; set Depth bit +@@: ret endp