Fasm: Fixed a bug when building programs with the length of the included file name...
[kolibrios.git] / drivers / usb / uhci.asm
blobfdd0220732ea01a0c3a017cff9ed7a504dbe7d4b
1 ; Code for UHCI controllers.
3 ; Standard driver stuff
4 format PE DLL native
5 entry start
6 __DEBUG__ equ 1
7 __DEBUG_LEVEL__ equ 1
8 section '.reloc' data readable discardable fixups
9 section '.text' code readable executable
10 include '../proc32.inc'
11 include '../struct.inc'
12 include '../macros.inc'
13 include '../fdo.inc'
14 include '../../kernel/trunk/bus/usb/common.inc'
16 ; =============================================================================
17 ; ================================= Constants =================================
18 ; =============================================================================
19 ; UHCI register declarations
20 UhciCommandReg = 0
21 UhciStatusReg = 2
22 UhciInterruptReg = 4
23 UhciFrameNumberReg = 6
24 UhciBaseAddressReg = 8
25 UhciSOFModifyReg = 0Ch
26 UhciPort1StatusReg = 10h
27 ; possible PIDs for USB data transfers
28 USB_PID_SETUP = 2Dh
29 USB_PID_IN = 69h
30 USB_PID_OUT = 0E1h
31 ; UHCI does not support an interrupt on root hub status change. We must poll
32 ; the controller periodically. This is the period in timer ticks (10ms).
33 ; We use the value 100 ticks: it is small enough to be responsive to connect
34 ; events and large enough to not load CPU too often.
35 UHCI_POLL_INTERVAL = 100
36 ; the following constant is an invalid encoding for length fields in
37 ; uhci_gtd; it is used to check whether an inactive TD has been
38 ; completed (actual length of the transfer is valid) or not processed at all
39 ; (actual length of the transfer is UHCI_INVALID_LENGTH).
40 ; Valid values are 0-4FFh and 7FFh. We use 700h as an invalid value.
41 UHCI_INVALID_LENGTH = 700h
43 ; =============================================================================
44 ; ================================ Structures =================================
45 ; =============================================================================
47 ; UHCI-specific part of a pipe descriptor.
48 ; * The structure corresponds to the Queue Head aka QH from the UHCI
49 ; specification with some additional fields.
50 ; * The hardware uses first two fields (8 bytes). Next two fields are used for
51 ; software book-keeping.
52 ; * The hardware requires 16-bytes alignment of the hardware part.
53 ; Since the allocator (usb_allocate_common) allocates memory sequentially
54 ; from page start (aligned on 0x1000 bytes), block size for the allocator
55 ; must be divisible by 16; usb1_allocate_endpoint ensures this.
56 struct uhci_pipe
57 NextQH dd ?
58 ; 1. First bit (bit 0) is Terminate bit. 1 = there is no next QH.
59 ; 2. Next bit (bit 1) is QH/TD select bit. 1 = NextQH points to QH.
60 ; 3. Next two bits (bits 2-3) are reserved.
61 ; 4. With masked 4 lower bits, this is the physical address of the next QH in
62 ; the QH list.
63 ; See also the description before NextVirt field of the usb_pipe
64 ; structure. Additionally to that description, the following is specific for
65 ; the UHCI controller:
66 ; * n=10, N=1024. However, this number is quite large.
67 ; * 1024 lists are used only for individual transfer descriptors for
68 ; Isochronous endpoints. This means that the software can sleep up to 1024 ms
69 ; before initiating the next portion of a large isochronous transfer, which
70 ; is a sufficiently large value.
71 ; * We use the 32ms upper limit for interrupt endpoint polling interval.
72 ; This seems to be a reasonable value.
73 ; * The "next" list for last Periodic list is the Control list.
74 ; * The "next" list for Control list is Bulk list and the "next"
75 ; list for Bulk list is Control list. This loop is used for bandwidth
76 ; reclamation: the hardware traverses lists until end-of-frame.
77 HeadTD dd ?
78 ; 1. First bit (bit 0) is Terminate bit. 1 = there is no TDs in this QH.
79 ; 2. Next bit (bit 1) is QH/TD select bit. 1 = HeadTD points to QH.
80 ; 3. Next two bits (bits 2-3) are reserved.
81 ; 4. With masked 4 lower bits, this is the physical address of the first TD in
82 ; the TD queue for this QH.
83 Token dd ?
84 ; This field is a template for uhci_gtd.Token field in transfer
85 ; descriptors. The meaning of individual bits is the same as for
86 ; uhci_gtd.Token, except that PID bitfield is always
87 ; USB_PID_SETUP/IN/OUT for control/in/out pipes,
88 ; the MaximumLength bitfield encodes maximum packet size,
89 ; the Reserved bit 20 is LowSpeedDevice bit.
90 ErrorTD dd ?
91 ; Usually NULL. If nonzero, it is a pointer to descriptor which was error'd
92 ; and should be freed sometime in the future (the hardware could still use it).
93 ends
95 ; This structure describes the static head of every list of pipes.
96 ; The hardware requires 16-bytes alignment of this structure.
97 ; All instances of this structure are located sequentially in uhci_controller,
98 ; uhci_controller is page-aligned, so it is sufficient to make this structure
99 ; 16-bytes aligned and verify that the first instance is 16-bytes aligned
100 ; inside uhci_controller.
101 struct uhci_static_ep
102 NextQH dd ?
103 ; Same as uhci_pipe.NextQH.
104 HeadTD dd ?
105 ; Same as uhci_pipe.HeadTD.
106 NextList dd ?
107 ; Virtual address of the next list.
108 dd ?
109 ; Not used.
110 SoftwarePart rd sizeof.usb_static_ep/4
111 ; Common part for all controllers, described by usb_static_ep structure.
112 dd ?
113 ; Padding for 16-byte alignment.
114 ends
116 if sizeof.uhci_static_ep mod 16
117 .err uhci_static_ep must be 16-bytes aligned
118 end if
120 ; UHCI-specific part of controller data.
121 ; * The structure includes two parts, the hardware part and the software part.
122 ; * The hardware part consists of first 4096 bytes and corresponds to
123 ; the Frame List from UHCI specification.
124 ; * The hardware requires page-alignment of the hardware part, so
125 ; the entire descriptor must be page-aligned.
126 ; This structure is allocated with kernel_alloc (see usb_init_controller),
127 ; this gives page-aligned data.
128 struct uhci_controller
129 ; ------------------------------ hardware fields ------------------------------
130 FrameList rd 1024
131 ; Entry n corresponds to the head of the frame list to be executed in
132 ; the frames n,n+1024,n+2048,n+3072,...
133 ; The first bit of each entry is Terminate bit, 1 = the frame is empty.
134 ; The second bit of each entry is QH/TD select bit, 1 = the entry points to
135 ; QH, 0 = to TD.
136 ; With masked 2 lower bits, the entry is a physical address of the first QH/TD
137 ; to be executed.
138 ; ------------------------------ software fields ------------------------------
139 ; Every list has the static head, which is an always empty QH.
140 ; The following fields are static heads, one per list:
141 ; 32+16+8+4+2+1 = 63 for Periodic lists, 1 for Control list and 1 for Bulk list.
142 IntEDs uhci_static_ep
143 rb 62 * sizeof.uhci_static_ep
144 ControlED uhci_static_ep
145 BulkED uhci_static_ep
146 IOBase dd ?
147 ; Base port in I/O space for UHCI controller.
148 ; UHCI register UhciXxx is addressed as in/out to IOBase + UhciXxx,
149 ; see declarations in the beginning of this source.
150 DeferredActions dd ?
151 ; Bitmask of bits from UhciStatusReg which need to be processed
152 ; by uhci_process_deferred. Bit 0 = a transaction with IOC bit
153 ; has completed. Bit 1 = a transaction has failed. Set by uhci_irq,
154 ; cleared by uhci_process_deferred.
155 LastPollTime dd ?
156 ; See the comment before UHCI_POLL_INTERVAL. This variable keeps the
157 ; last time, in timer ticks, when the polling was done.
158 EhciCompanion dd ?
159 ; Pointer to usb_controller for EHCI companion, if any, or NULL.
160 ends
162 if uhci_controller.IntEDs mod 16
163 .err Static endpoint descriptors must be 16-bytes aligned inside uhci_controller
164 end if
166 ; UHCI general transfer descriptor.
167 ; * The structure describes non-Isochronous data transfers
168 ; for the UHCI controller.
169 ; * The structure includes two parts, the hardware part and the software part.
170 ; * The hardware part consists of first 16 bytes and corresponds to the
171 ; Transfer Descriptor aka TD from UHCI specification.
172 ; * The hardware requires 16-bytes alignment of the hardware part, so
173 ; the entire descriptor must be 16-bytes aligned. Since the allocator
174 ; (uhci_allocate_common) allocates memory sequentially from page start
175 ; (aligned on 0x1000 bytes), block size for the allocator must be
176 ; divisible by 16; usb1_allocate_general_td ensures this.
177 struct uhci_gtd
178 NextTD dd ?
179 ; 1. First bit (bit 0) is Terminate bit. 1 = there is no next TD.
180 ; 2. Next bit (bit 1) is QH/TD select bit. 1 = NextTD points to QH.
181 ; This bit is always set to 0 in the implementation.
182 ; 3. Next bit (bit 2) is Depth/Breadth select bit. 1 = the controller should
183 ; proceed to the NextTD after this TD is complete. 0 = the controller
184 ; should proceed to the next endpoint after this TD is complete.
185 ; The implementation sets this bit to 0 for final stages of all transactions
186 ; and to 1 for other stages.
187 ; 4. Next bit (bit 3) is reserved and must be zero.
188 ; 5. With masked 4 lower bits, this is the physical address of the next TD
189 ; in the TD list.
190 ControlStatus dd ?
191 ; 1. Lower 11 bits (bits 0-10) are ActLen. This is written by the controller
192 ; at the conclusion of a USB transaction to indicate the actual number of
193 ; bytes that were transferred minus 1.
194 ; 2. Next 6 bits (bits 11-16) are reserved.
195 ; 3. Next bit (bit 17) signals Bitstuff error.
196 ; 4. Next bit (bit 18) signals CRC/Timeout error.
197 ; 5. Next bit (bit 19) signals NAK receive.
198 ; 6. Next bit (bit 20) signals Babble error.
199 ; 7. Next bit (bit 21) signals Data Buffer error.
200 ; 8. Next bit (bit 22) signals Stall error.
201 ; 9. Next bit (bit 23) is Active field. 1 = this TD should be processed.
202 ; 10. Next bit (bit 24) is InterruptOnComplete bit. 1 = the controller should
203 ; issue an interrupt on completion of the frame in which this TD is
204 ; executed.
205 ; 11. Next bit (bit 25) is IsochronousSelect bit. 1 = this TD is isochronous.
206 ; 12. Next bit (bit 26) is LowSpeedDevice bit. 1 = this TD is for low-speed.
207 ; 13. Next two bits (bits 27-28) are ErrorCounter field. This field is
208 ; decremented by the controller on every non-fatal error with this TD.
209 ; Babble and Stall are considered fatal errors and immediately deactivate
210 ; the TD without decrementing this field. 0 = no error limit,
211 ; n = deactivate the TD after n errors.
212 ; 14. Next bit (bit 29) is ShortPacketDetect bit. 1 = short packet is an error.
213 ; Note: the specification defines this bit as input for the controller,
214 ; but does not specify the value written by controller.
215 ; Some controllers (e.g. Intel) keep the value, some controllers (e.g. VIA)
216 ; set the value to whether a short packet was actually detected
217 ; (or something like that).
218 ; Thus, we duplicate this bit as bit 0 of OrigBufferInfo.
219 ; 15. Upper two bits (bits 30-31) are reserved.
220 Token dd ?
221 ; 1. Lower 8 bits (bits 0-7) are PID, one of USB_PID_*.
222 ; 2. Next 7 bits (bits 8-14) are DeviceAddress field. This is the address of
223 ; the target device on the USB bus.
224 ; 3. Next 4 bits (bits 15-18) are Endpoint field. This is the target endpoint
225 ; number.
226 ; 4. Next bit (bit 19) is DataToggle bit. n = issue/expect DATAn token.
227 ; 5. Next bit (bit 20) is reserved.
228 ; 6. Upper 11 bits (bits 21-31) are MaximumLength field. This field specifies
229 ; the maximum number of data bytes for the transfer minus 1 byte. Null data
230 ; packet is encoded as 0x7FF, maximum possible non-null data packet is 1280
231 ; bytes, encoded as 0x4FF.
232 Buffer dd ?
233 ; Physical address of the data buffer for this TD.
234 OrigBufferInfo dd ?
235 ; Usually NULL. If the original buffer crosses a page boundary, this is a
236 ; pointer to the structure uhci_original_buffer for this request.
237 ; bit 0: 1 = short packet is NOT allowed
238 ; (before the TD is processed, it is the copy of bit 29 of ControlStatus;
239 ; some controllers modify that bit, so we need a copy in a safe place)
240 ends
242 ; UHCI requires that the entire transfer buffer should be on one page.
243 ; If the actual buffer crosses page boundary, uhci_alloc_packet
244 ; allocates additional memory for buffer for hardware.
245 ; This structure describes correspondence between two buffers.
246 struct uhci_original_buffer
247 OrigBuffer dd ?
248 UsedBuffer dd ?
249 ends
251 ; Description of UHCI-specific data and functions for
252 ; controller-independent code.
253 ; Implements the structure usb_hardware_func from hccommon.inc for UHCI.
254 iglobal
255 align 4
256 uhci_hardware_func:
257 dd USBHC_VERSION
258 dd 'UHCI'
259 dd sizeof.uhci_controller
260 dd uhci_kickoff_bios
261 dd uhci_init
262 dd uhci_process_deferred
263 dd uhci_set_device_address
264 dd uhci_get_device_address
265 dd uhci_port_disable
266 dd uhci_new_port.reset
267 dd uhci_set_endpoint_packet_size
268 dd uhci_alloc_pipe
269 dd uhci_free_pipe
270 dd uhci_init_pipe
271 dd uhci_unlink_pipe
272 dd uhci_alloc_td
273 dd uhci_free_td
274 dd uhci_alloc_transfer
275 dd uhci_insert_transfer
276 dd uhci_new_device
277 dd uhci_disable_pipe
278 dd uhci_enable_pipe
279 uhci_name db 'UHCI',0
280 endg
282 ; =============================================================================
283 ; =================================== Code ====================================
284 ; =============================================================================
286 ; Called once when driver is loading and once at shutdown.
287 ; When loading, must initialize itself, register itself in the system
288 ; and return eax = value obtained when registering.
289 proc start
290 virtual at esp
291 dd ? ; return address
292 .reason dd ? ; DRV_ENTRY or DRV_EXIT
293 .cmdline dd ? ; normally NULL
294 end virtual
295 cmp [.reason], DRV_ENTRY
296 jnz .nothing
297 mov ecx, uhci_ep_mutex
298 and dword [ecx-4], 0
299 invoke MutexInit
300 mov ecx, uhci_gtd_mutex
301 and dword [ecx-4], 0
302 invoke MutexInit
303 push esi edi
304 mov esi, [USBHCFunc]
305 mov edi, usbhc_api
306 movi ecx, sizeof.usbhc_func/4
307 rep movsd
308 pop edi esi
309 invoke RegUSBDriver, uhci_name, 0, uhci_hardware_func
310 .nothing:
312 endp
314 ; Controller-specific initialization function.
315 ; Called from usb_init_controller. Initializes the hardware and
316 ; UHCI-specific parts of software structures.
317 ; eax = pointer to uhci_controller to be initialized
318 ; [ebp-4] = pcidevice
319 proc uhci_init
320 ; inherit some variables from the parent (usb_init_controller)
321 .devfn equ ebp - 4
322 .bus equ ebp - 3
323 ; 1. Store pointer to uhci_controller for further use.
324 push eax
325 mov edi, eax
326 mov esi, eax
327 ; 2. Initialize uhci_controller.FrameList.
328 ; Note that FrameList is located in the beginning of uhci_controller,
329 ; so esi and edi now point to uhci_controller.FrameList.
330 ; First 32 entries of FrameList contain physical addresses
331 ; of first 32 Periodic static heads, further entries duplicate these.
332 ; See the description of structures for full info.
333 ; Note that all static heads fit in one page, so one call to
334 ; get_phys_addr is sufficient.
335 if (uhci_controller.IntEDs / 0x1000) <> (uhci_controller.BulkED / 0x1000)
336 .err assertion failed
337 end if
338 ; 2a. Get physical address of first static head.
339 ; Note that 1) it is located in the beginning of a page
340 ; and 2) all other static heads fit in the same page,
341 ; so one call to get_phys_addr without correction of lower 12 bits
342 ; is sufficient.
343 if (uhci_controller.IntEDs mod 0x1000) <> 0
344 .err assertion failed
345 end if
346 add eax, uhci_controller.IntEDs
347 invoke GetPhysAddr
348 ; 2b. Fill first 32 entries.
349 inc eax
350 inc eax ; set QH bit for uhci_pipe.NextQH
351 movi ecx, 32
352 mov edx, ecx
354 stosd
355 add eax, sizeof.uhci_static_ep
356 loop @b
357 ; 2c. Fill the rest entries.
358 mov ecx, 1024 - 32
359 rep movsd
360 ; 3. Initialize static heads uhci_controller.*ED.
361 ; Use the loop over groups: first group consists of first 32 Periodic
362 ; descriptors, next group consists of next 16 Periodic descriptors,
363 ; ..., last group consists of the last Periodic descriptor.
364 ; 3a. Prepare for the loop.
365 ; make esi point to the second group, other registers are already set.
366 add esi, 32*4 + 32*sizeof.uhci_static_ep
367 ; 3b. Loop over groups. On every iteration:
368 ; edx = size of group, edi = pointer to the current group,
369 ; esi = pointer to the next group, eax = physical address of the next group.
370 .init_static_eds:
371 ; 3c. Get the size of next group.
372 shr edx, 1
373 ; 3d. Exit the loop if there is no next group.
374 jz .init_static_eds_done
375 ; 3e. Initialize the first half of the current group.
376 ; Advance edi to the second half.
377 push eax esi
378 call uhci_init_static_ep_group
379 pop esi eax
380 ; 3f. Initialize the second half of the current group
381 ; with the same values.
382 ; Advance edi to the next group, esi/eax to the next of the next group.
383 call uhci_init_static_ep_group
384 jmp .init_static_eds
385 .init_static_eds_done:
386 ; 3g. Initialize the last static head.
387 xor esi, esi
388 call uhci_init_static_endpoint
389 ; 3i. Initialize the head of Control list.
390 add eax, sizeof.uhci_static_ep
391 call uhci_init_static_endpoint
392 ; 3j. Initialize the head of Bulk list.
393 sub eax, sizeof.uhci_static_ep
394 call uhci_init_static_endpoint
395 ; 4. Get I/O base address and size from PCI bus.
396 ; 4a. Read&save PCI command state.
397 invoke PciRead16, dword [.bus], dword [.devfn], 4
398 push eax
399 ; 4b. Disable IO access.
400 and al, not 1
401 invoke PciWrite16, dword [.bus], dword [.devfn], 4, eax
402 ; 4c. Read&save IO base address.
403 invoke PciRead16, dword [.bus], dword [.devfn], 20h
404 and al, not 3
405 xchg eax, edi
406 ; now edi = IO base
407 ; 4d. Write 0xffff to IO base address.
408 invoke PciWrite16, dword [.bus], dword [.devfn], 20h, -1
409 ; 4e. Read IO base address.
410 invoke PciRead16, dword [.bus], dword [.devfn], 20h
411 and al, not 3
412 cwde
413 not eax
414 inc eax
415 xchg eax, esi
416 ; now esi = IO size
417 ; 4f. Restore IO base address.
418 invoke PciWrite16, dword [.bus], dword [.devfn], 20h, edi
419 ; 4g. Restore PCI command state and enable io & bus master access.
420 pop ecx
421 or ecx, 5
422 invoke PciWrite16, dword [.bus], dword [.devfn], 4, ecx
423 ; 5. Reset the controller.
424 ; 5e. Host reset.
425 mov edx, edi
426 mov ax, 2
427 out dx, ax
428 ; 5f. Wait up to 10ms.
429 movi ecx, 10
431 push esi
432 movi esi, 1
433 invoke Sleep
434 pop esi
435 in ax, dx
436 test al, 2
437 loopnz @b
438 jz @f
439 dbgstr 'UHCI controller reset timeout'
440 jmp .fail
442 if 0
443 ; emergency variant for tests - always wait 10 ms
444 ; wait 10 ms
445 push esi
446 movi esi, 10
447 invoke Sleep
448 pop esi
449 ; clear reset signal
450 xor eax, eax
451 out dx, ax
452 end if
453 .resetok:
454 ; 6. Get number of ports & disable all ports.
455 add esi, edi
456 lea edx, [edi+UhciPort1StatusReg]
457 .scanports:
458 cmp edx, esi
459 jae .doneports
460 in ax, dx
461 cmp ax, 0xFFFF
462 jz .doneports
463 test al, al
464 jns .doneports
465 xor eax, eax
466 out dx, ax
467 inc edx
468 inc edx
469 jmp .scanports
470 .doneports:
471 lea esi, [edx-UhciPort1StatusReg]
472 sub esi, edi
473 shr esi, 1 ; esi = number of ports
474 jnz @f
475 dbgstr 'error: no ports on UHCI controller'
476 jmp .fail
478 ; 7. Setup the rest of uhci_controller.
479 xchg esi, [esp] ; restore the pointer to uhci_controller from the step 1
480 add esi, sizeof.uhci_controller
481 pop [esi+usb_controller.NumPorts]
482 DEBUGF 1,'K : UHCI controller at %x:%x with %d ports initialized\n',[.bus]:2,[.devfn]:2,[esi+usb_controller.NumPorts]
483 mov [esi+uhci_controller.IOBase-sizeof.uhci_controller], edi
484 invoke GetTimerTicks
485 mov [esi+uhci_controller.LastPollTime-sizeof.uhci_controller], eax
486 ; 8. Find the EHCI companion.
487 ; If there is one, check whether all ports are covered by that companion.
488 ; Note: this assumes that EHCI is initialized before USB1 companions.
489 mov ebx, dword [.devfn]
490 invoke usbhc_api.usb_find_ehci_companion
491 mov [esi+uhci_controller.EhciCompanion-sizeof.uhci_controller], eax
492 ; 9. Hook interrupt.
493 invoke PciRead8, dword [.bus], dword [.devfn], 3Ch
494 ; al = IRQ
495 ; DEBUGF 1,'K : UHCI %x: io=%x, irq=%x\n',esi,edi,al
496 movzx eax, al
497 invoke AttachIntHandler, eax, uhci_irq, esi
498 ; 10. Setup controller registers.
499 xor eax, eax
500 mov edx, [esi+uhci_controller.IOBase-sizeof.uhci_controller]
501 ; 10a. UhciStatusReg := 3Fh: clear all status bits
502 ; (for this register 1 clears the corresponding bit, 0 does not change it).
503 inc edx
504 inc edx ; UhciStatusReg == 2
505 mov al, 3Fh
506 out dx, ax
507 ; 10b. UhciInterruptReg := 0Dh.
508 inc edx
509 inc edx ; UhciInterruptReg == 4
510 mov al, 0Dh
511 out dx, ax
512 ; 10c. UhciFrameNumberReg := 0.
513 inc edx
514 inc edx ; UhciFrameNumberReg == 6
515 mov al, 0
516 out dx, ax
517 ; 10d. UhciBaseAddressReg := physical address of uhci_controller.
518 inc edx
519 inc edx ; UhciBaseAddressReg == 8
520 lea eax, [esi-sizeof.uhci_controller]
521 invoke GetPhysAddr
522 out dx, eax
523 ; 10e. UhciCommandReg := Run + Configured + (MaxPacket is 64 bytes)
524 sub edx, UhciBaseAddressReg ; UhciCommandReg == 0
525 mov ax, 0C1h ; Run, Configured, MaxPacket = 64b
526 out dx, ax
527 ; 11. Do initial scan of existing devices.
528 call uhci_poll_roothub
529 ; 12. Return pointer to usb_controller.
530 xchg eax, esi
532 .fail:
533 ; On error, pop the pointer saved at step 1 and return zero.
534 ; Note that the main code branch restores the stack at step 8 and never fails
535 ; after step 8.
536 pop ecx
537 xor eax, eax
539 endp
541 ; Controller-specific pre-initialization function: take ownership from BIOS.
542 ; UHCI has no mechanism to ask the owner politely to release ownership,
543 ; so do it in inpolite way, preventing controller from any SMI activity.
544 proc uhci_kickoff_bios
545 ; 1. Get the I/O address.
546 invoke PciRead16, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], 20h
547 and eax, 0xFFFC
548 xchg eax, edx
549 ; 2. Stop the controller and disable all interrupts.
550 in ax, dx
551 and al, not 1
552 out dx, ax
553 add edx, UhciInterruptReg
554 xor eax, eax
555 out dx, ax
556 ; 3. Disable all bits for SMI routing, clear SMI routing status,
557 ; enable master interrupt bit.
558 invoke PciWrite16, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], 0xC0, 0AF00h
560 endp
562 ; Helper procedure for step 3 of uhci_init.
563 ; Initializes the static head of one list.
564 ; eax = physical address of the "next" list, esi = pointer to the "next" list,
565 ; edi = pointer to head to initialize.
566 ; Advances edi to the next head, keeps eax/esi.
567 proc uhci_init_static_endpoint
568 mov [edi+uhci_static_ep.NextQH], eax
569 mov byte [edi+uhci_static_ep.HeadTD], 1
570 mov [edi+uhci_static_ep.NextList], esi
571 add edi, uhci_static_ep.SoftwarePart
572 invoke usbhc_api.usb_init_static_endpoint
573 add edi, sizeof.uhci_static_ep - uhci_static_ep.SoftwarePart
575 endp
577 ; Helper procedure for step 3 of uhci_init, see comments there.
578 ; Initializes one half of group of static heads.
579 ; edx = size of the next group = half of size of the group,
580 ; edi = pointer to the group, eax = physical address of the next group,
581 ; esi = pointer to the next group.
582 ; Advances eax, esi, edi to next group, keeps edx.
583 proc uhci_init_static_ep_group
584 push edx
586 call uhci_init_static_endpoint
587 add eax, sizeof.uhci_static_ep
588 add esi, sizeof.uhci_static_ep
589 dec edx
590 jnz @b
591 pop edx
593 endp
595 ; IRQ handler for UHCI controllers.
596 uhci_irq.noint:
597 ; Not our interrupt: restore esi and return zero.
598 pop esi
599 xor eax, eax
601 proc uhci_irq
602 push esi ; save used register to be cdecl
603 virtual at esp
604 dd ? ; saved esi
605 dd ? ; return address
606 .controller dd ?
607 end virtual
608 mov esi, [.controller]
609 ; 1. Read UhciStatusReg.
610 mov edx, [esi+uhci_controller.IOBase-sizeof.uhci_controller]
611 inc edx
612 inc edx ; UhciStatusReg == 2
613 in ax, dx
614 ; 2. Test whether it is our interrupt; if so, at least one status bit is set.
615 test al, 0x1F
616 jz .noint
617 ; 3. Clear all status bits.
618 out dx, ax
619 ; 4. Sanity check.
620 test al, 0x3C
621 jz @f
622 DEBUGF 1,'K : something terrible happened with UHCI (%x)\n',al
624 ; 5. We can't do too much from an interrupt handler, e.g. we can't take
625 ; any mutex locks since our code could be called when another code holds the
626 ; lock and has no chance to release it. Thus, only inform the processing thread
627 ; that it should scan the queue and wake it if needed.
628 lock or byte [esi+uhci_controller.DeferredActions-sizeof.uhci_controller], al
629 push ebx
630 xor ebx, ebx
631 inc ebx
632 invoke usbhc_api.usb_wakeup_if_needed
633 pop ebx
634 ; 6. This is our interrupt; return 1.
635 mov al, 1
636 pop esi ; restore used register to be stdcall
638 endp
640 ; This procedure is called in the USB thread from usb_thread_proc,
641 ; processes regular actions and those actions which can't be safely done
642 ; from interrupt handler.
643 ; Returns maximal time delta before the next call.
644 proc uhci_process_deferred
645 push ebx edi ; save used registers to be stdcall
646 ; 1. Initialize the return value.
647 push -1
648 ; 2. Poll the root hub every UHCI_POLL_INTERVAL ticks.
649 ; Also force polling if some transaction has completed with errors;
650 ; the error can be caused by disconnect, try to detect it.
651 test byte [esi+uhci_controller.DeferredActions-sizeof.uhci_controller], 2
652 jnz .force_poll
653 invoke GetTimerTicks
654 sub eax, [esi+uhci_controller.LastPollTime-sizeof.uhci_controller]
655 sub eax, UHCI_POLL_INTERVAL
656 jl .nopoll
657 .force_poll:
658 invoke GetTimerTicks
659 mov [esi+uhci_controller.LastPollTime-sizeof.uhci_controller], eax
660 call uhci_poll_roothub
661 mov eax, -UHCI_POLL_INTERVAL
662 .nopoll:
663 neg eax
664 cmp [esp], eax
665 jb @f
666 mov [esp], eax
668 ; 3. Process wait lists.
669 ; 3a. Test whether there is a wait request.
670 mov eax, [esi+usb_controller.WaitPipeRequestAsync]
671 cmp eax, [esi+usb_controller.ReadyPipeHeadAsync]
672 jnz .check_removed
673 mov eax, [esi+usb_controller.WaitPipeRequestPeriodic]
674 cmp eax, [esi+usb_controller.ReadyPipeHeadPeriodic]
675 jz @f
676 .check_removed:
677 ; 3b. Yep. Find frame and compare it with the saved one.
678 mov edx, [esi+uhci_controller.IOBase-sizeof.uhci_controller]
679 add edx, UhciFrameNumberReg
680 in ax, dx
681 cmp word [esi+usb_controller.StartWaitFrame], ax
682 jnz .removed
683 ; 3c. The same frame; wake up in 0.01 sec.
684 mov dword [esp], 1
685 jmp @f
686 .removed:
687 ; 3d. The frame is changed, old contents is guaranteed to be forgotten.
688 mov eax, [esi+usb_controller.WaitPipeRequestAsync]
689 mov [esi+usb_controller.ReadyPipeHeadAsync], eax
690 mov eax, [esi+usb_controller.WaitPipeRequestPeriodic]
691 mov [esi+usb_controller.ReadyPipeHeadPeriodic], eax
693 ; 4. Process disconnect events. This should be done after step 2
694 ; (which includes the first stage of disconnect processing).
695 invoke usbhc_api.usb_disconnect_stage2
696 ; 5. Test whether USB_CONNECT_DELAY for a connected device is over.
697 ; Call uhci_new_port for all such devices.
698 xor ecx, ecx
699 cmp [esi+usb_controller.NewConnected], ecx
700 jz .skip_newconnected
701 .portloop:
702 bt [esi+usb_controller.NewConnected], ecx
703 jnc .noconnect
704 ; If this port is shared with the EHCI companion and we see the connect event,
705 ; then the device is USB1 dropped by EHCI,
706 ; so EHCI has already waited for debounce delay, we can proceed immediately.
707 cmp [esi+uhci_controller.EhciCompanion-sizeof.uhci_controller], 0
708 jz .portloop.test_time
709 dbgstr 'port is shared with EHCI, skipping initial debounce'
710 jmp .connected
711 .portloop.test_time:
712 invoke GetTimerTicks
713 sub eax, [esi+usb_controller.ConnectedTime+ecx*4]
714 sub eax, USB_CONNECT_DELAY
715 jge .connected
716 neg eax
717 cmp [esp], eax
718 jb .nextport
719 mov [esp], eax
720 jmp .nextport
721 .connected:
722 btr [esi+usb_controller.NewConnected], ecx
723 call uhci_new_port
724 .noconnect:
725 .nextport:
726 inc ecx
727 cmp ecx, [esi+usb_controller.NumPorts]
728 jb .portloop
729 .skip_newconnected:
730 ; 6. Test for processed packets.
731 ; This should be done after step 4, so transfers which were failed due
732 ; to disconnect are marked with the exact reason, not just
733 ; 'device not responding'.
734 xor eax, eax
735 xchg byte [esi+uhci_controller.DeferredActions-sizeof.uhci_controller], al
736 test al, 3
737 jz .noioc
738 call uhci_process_updated_schedule
739 .noioc:
740 ; 7. Test whether reset signalling has been started. If so,
741 ; either should be stopped now (if time is over) or schedule wakeup (otherwise).
742 ; This should be done after step 6, because a completed SET_ADDRESS command
743 ; could result in reset of a new port.
744 .test_reset:
745 ; 7a. Test whether reset signalling is active.
746 cmp [esi+usb_controller.ResettingStatus], 1
747 jnz .no_reset_in_progress
748 ; 7b. Yep. Test whether it should be stopped.
749 invoke GetTimerTicks
750 sub eax, [esi+usb_controller.ResetTime]
751 sub eax, USB_RESET_TIME
752 jge .reset_done
753 ; 7c. Not yet, but initiate wakeup in -eax ticks and exit this step.
754 neg eax
755 cmp [esp], eax
756 jb .skip_reset
757 mov [esp], eax
758 jmp .skip_reset
759 .reset_done:
760 ; 7d. Yep, call the worker function and proceed to 7e.
761 call uhci_port_reset_done
762 .no_reset_in_progress:
763 ; 7e. Test whether reset process is done, either successful or failed.
764 cmp [esi+usb_controller.ResettingStatus], 0
765 jz .skip_reset
766 ; 7f. Yep. Test whether it should be stopped.
767 invoke GetTimerTicks
768 sub eax, [esi+usb_controller.ResetTime]
769 sub eax, USB_RESET_RECOVERY_TIME
770 jge .reset_recovery_done
771 ; 7g. Not yet, but initiate wakeup in -eax ticks and exit this step.
772 neg eax
773 cmp [esp], eax
774 jb .skip_reset
775 mov [esp], eax
776 jmp .skip_reset
777 .reset_recovery_done:
778 ; 7h. Yep, call the worker function. This could initiate another reset,
779 ; so return to the beginning of this step.
780 call uhci_port_init
781 jmp .test_reset
782 .skip_reset:
783 ; 8. Process wait-done notifications, test for new wait requests.
784 ; Note: that must be done after steps 4 and 6 which could create new requests.
785 ; 8a. Call the worker function.
786 invoke usbhc_api.usb_process_wait_lists
787 ; 8b. If no new requests, skip the rest of this step.
788 test eax, eax
789 jz @f
790 ; 8c. UHCI is not allowed to cache anything; we don't know what is
791 ; processed right now, but we can be sure that the controller will not
792 ; use any removed structure starting from the next frame.
793 ; Request removal of everything disconnected until now,
794 ; schedule wakeup in 0.01 sec.
795 mov eax, [esi+usb_controller.WaitPipeListAsync]
796 mov [esi+usb_controller.WaitPipeRequestAsync], eax
797 mov eax, [esi+usb_controller.WaitPipeListPeriodic]
798 mov [esi+usb_controller.WaitPipeRequestPeriodic], eax
799 mov edx, [esi+uhci_controller.IOBase-sizeof.uhci_controller]
800 add edx, UhciFrameNumberReg
801 in ax, dx
802 mov word [esi+usb_controller.StartWaitFrame], ax
803 mov dword [esp], 1
805 ; 9. Return the value from the top of stack.
806 pop eax
807 pop edi ebx ; restore used registers to be stdcall.
809 endp
811 ; This procedure is called in the USB thread from uhci_process_deferred
812 ; when UHCI IRQ handler has signalled that new IOC-packet was processed.
813 ; It scans all lists for completed packets and calls uhci_process_finalized_td
814 ; for those packets.
815 ; in: esi -> usb_controller
816 proc uhci_process_updated_schedule
817 ; Important note: we cannot hold the list lock during callbacks,
818 ; because callbacks sometimes open and/or close pipes and thus acquire/release
819 ; the corresponding lock itself.
820 ; Fortunately, pipes can be finally freed only by another step of
821 ; uhci_process_deferred, so all pipes existing at the start of this function
822 ; will be valid while this function is running. Some pipes can be removed
823 ; from the corresponding list, some pipes can be inserted; insert/remove
824 ; functions guarantee that traversing one list yields all pipes that were in
825 ; that list at the beginning of the traversing (possibly with some new pipes,
826 ; possibly without some new pipes, that doesn't matter).
827 ; 1. Process all Periodic lists.
828 lea edi, [esi+uhci_controller.IntEDs.SoftwarePart-sizeof.uhci_controller]
829 lea ebx, [esi+uhci_controller.IntEDs.SoftwarePart+63*sizeof.uhci_static_ep-sizeof.uhci_controller]
831 call uhci_process_updated_list
832 cmp edi, ebx
833 jnz @b
834 ; 2. Process the Control list.
835 call uhci_process_updated_list
836 ; 3. Process the Bulk list.
837 call uhci_process_updated_list
838 ; 4. Return.
840 endp
842 ; This procedure is called from uhci_process_updated_schedule,
843 ; see comments there.
844 ; It processes one list, esi -> usb_controller, edi -> usb_static_ep,
845 ; and advances edi to the next head.
846 proc uhci_process_updated_list
847 push ebx ; save used register to be stdcall
848 ; 1. Perform the external loop over all pipes.
849 mov ebx, [edi+usb_static_ep.NextVirt]
850 .loop:
851 cmp ebx, edi
852 jz .done
853 ; store pointer to the next pipe in the stack
854 push [ebx+usb_static_ep.NextVirt]
855 ; 2. For every pipe, perform the internal loop over all descriptors.
856 ; All descriptors are organized in the queue; we process items from the start
857 ; of the queue until a) the last descriptor (not the part of the queue itself)
858 ; or b) an active (not yet processed by the hardware) descriptor is reached.
859 lea ecx, [ebx+usb_pipe.Lock]
860 invoke MutexLock
861 mov ebx, [ebx+usb_pipe.LastTD]
862 push ebx
863 mov ebx, [ebx+usb_gtd.NextVirt]
864 .tdloop:
865 ; 3. For every descriptor, test active flag and check for end-of-queue;
866 ; if either of conditions holds, exit from the internal loop.
867 cmp ebx, [esp]
868 jz .tddone
869 mov eax, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd]
870 test eax, 1 shl 23 ; active?
871 jnz .tddone
872 ; Release the queue lock while processing one descriptor:
873 ; callback function could (and often would) schedule another transfer.
874 push ecx
875 invoke MutexUnlock
876 call uhci_process_finalized_td
877 pop ecx
878 invoke MutexLock
879 jmp .tdloop
880 .tddone:
881 invoke MutexUnlock
882 pop ebx
883 ; End of internal loop, restore pointer to the next pipe
884 ; and continue the external loop.
885 pop ebx
886 jmp .loop
887 .done:
888 pop ebx ; restore used register to be stdcall
889 add edi, sizeof.uhci_static_ep
891 endp
893 ; This procedure is called from uhci_process_updated_list, which is itself
894 ; called from uhci_process_updated_schedule, see comments there.
895 ; It processes one completed descriptor.
896 ; in: esi -> usb_controller, ebx -> usb_gtd, out: ebx -> next usb_gtd.
897 proc uhci_process_finalized_td
898 ; 1. Remove this descriptor from the list of descriptors for this pipe.
899 invoke usbhc_api.usb_unlink_td
900 ; DEBUGF 1,'K : finalized TD:\n'
901 ; DEBUGF 1,'K : %x %x %x %x\n',[ebx-20],[ebx-16],[ebx-12],[ebx-8]
902 ; DEBUGF 1,'K : %x %x %x %x\n',[ebx-4],[ebx],[ebx+4],[ebx+8]
903 ; 2. If this is IN transfer into special buffer, copy the data
904 ; to target location.
905 mov edx, [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
906 and edx, not 1 ; clear lsb (used for another goal)
907 jz .nocopy
908 cmp byte [ebx+uhci_gtd.Token-sizeof.uhci_gtd], USB_PID_IN
909 jnz .nocopy
910 ; Note: we assume that pointer to buffer is valid in the memory space of
911 ; the USB thread. This means that buffer must reside in kernel memory
912 ; (shared by all processes).
913 push esi edi
914 mov esi, [edx+uhci_original_buffer.UsedBuffer]
915 mov edi, [edx+uhci_original_buffer.OrigBuffer]
916 mov ecx, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd]
917 inc ecx
918 and ecx, 7FFh
919 mov edx, ecx
920 shr ecx, 2
921 and edx, 3
922 rep movsd
923 mov ecx, edx
924 rep movsb
925 pop edi esi
926 .nocopy:
927 ; 3. Calculate actual number of bytes transferred.
928 ; 3a. Read the state.
929 mov eax, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd]
930 mov ecx, [ebx+uhci_gtd.Token-sizeof.uhci_gtd]
931 ; 3b. Get number of bytes processed.
932 lea edx, [eax+1]
933 and edx, 7FFh
934 ; 3c. Subtract number of bytes in this packet.
935 add ecx, 1 shl 21
936 shr ecx, 21
937 sub edx, ecx
938 ; 3d. Add total length transferred so far.
939 add edx, [ebx+usb_gtd.Length]
940 ; Actions on error and on success are slightly different.
941 ; 4. Test for error. On error, proceed to step 5, otherwise go to step 6
942 ; with ecx = 0 (no error).
943 ; USB transaction error is always considered as such.
944 ; If short packets are not allowed, UHCI controllers do not set an error bit,
945 ; but stop (clear Active bit and do not advance) the queue.
946 ; Short packet is considered as an error if the packet is actually short
947 ; (actual length is less than maximal one) and the code creating the packet
948 ; requested that behaviour (so bit 0 of OrigBufferInfo is set; this could be
949 ; because the caller disallowed short packets or because the packet is not
950 ; the last one in the corresponding transfer).
951 xor ecx, ecx
952 test eax, 1 shl 22
953 jnz .error
954 test byte [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1
955 jz .notify
956 cmp edx, [ebx+usb_gtd.Length]
957 jz .notify
958 .error:
959 ; 5. There was an error while processing this packet.
960 ; The hardware has stopped processing the queue.
961 DEBUGF 1,'K : TD failed:\n'
962 if sizeof.uhci_gtd <> 20
963 .err modify offsets for debug output
964 end if
965 DEBUGF 1,'K : %x %x %x %x\n',[ebx-20],[ebx-16],[ebx-12],[ebx-8]
966 DEBUGF 1,'K : %x %x %x %x\n',[ebx-4],[ebx],[ebx+4],[ebx+8]
967 ; 5a. Save the status and length.
968 push edx
969 push eax
970 mov eax, [ebx+usb_gtd.Pipe]
971 DEBUGF 1,'K : pipe: %x %x\n',[eax+0-sizeof.uhci_pipe],[eax+4-sizeof.uhci_pipe]
972 ; 5b. Store the current TD as an error packet.
973 ; If an error packet is already stored for this pipe,
974 ; it is definitely not used already, so free the old packet.
975 mov eax, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
976 test eax, eax
977 jz @f
978 stdcall uhci_free_td, eax
980 mov eax, [ebx+usb_gtd.Pipe]
981 mov [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe], ebx
982 ; 5c. Traverse the list of descriptors looking for the final packet
983 ; for this transfer.
984 ; Free and unlink non-final descriptors, except the current one.
985 ; Final descriptor will be freed in step 7.
986 invoke usbhc_api.usb_is_final_packet
987 jnc .found_final
988 mov ebx, [ebx+usb_gtd.NextVirt]
989 .look_final:
990 invoke usbhc_api.usb_unlink_td
991 invoke usbhc_api.usb_is_final_packet
992 jnc .found_final
993 push [ebx+usb_gtd.NextVirt]
994 stdcall uhci_free_td, ebx
995 pop ebx
996 jmp .look_final
997 .found_final:
998 ; 5d. Restore the status saved in 5a and transform it to the error code.
999 pop eax ; error code
1000 shr eax, 16
1001 ; Notes:
1002 ; * any USB transaction error results in Stalled bit; if it is not set,
1003 ; but we are here, it must be due to short packet;
1004 ; * babble is considered a fatal USB transaction error,
1005 ; other errors just lead to retrying the transaction;
1006 ; if babble is detected, return the corresponding error;
1007 ; * if several non-fatal errors have occured during transaction retries,
1008 ; all corresponding bits are set. In this case, return some error code,
1009 ; the order is quite arbitrary.
1010 movi ecx, USB_STATUS_UNDERRUN
1011 test al, 1 shl (22-16) ; not Stalled?
1012 jz .know_error
1013 mov cl, USB_STATUS_OVERRUN
1014 test al, 1 shl (20-16) ; Babble detected?
1015 jnz .know_error
1016 mov cl, USB_STATUS_BITSTUFF
1017 test al, 1 shl (17-16) ; Bitstuff error?
1018 jnz .know_error
1019 mov cl, USB_STATUS_NORESPONSE
1020 test al, 1 shl (18-16) ; CRC/TimeOut error?
1021 jnz .know_error
1022 mov cl, USB_STATUS_BUFOVERRUN
1023 test al, 1 shl (21-16) ; Data Buffer error?
1024 jnz .know_error
1025 mov cl, USB_STATUS_STALL
1026 .know_error:
1027 ; 5e. If error code is USB_STATUS_UNDERRUN
1028 ; and the last TD allows short packets, it is not an error.
1029 ; Note: all TDs except the last one in any transfer stage are marked
1030 ; as short-packet-is-error to stop controller from further processing
1031 ; of that stage; we need to restart processing from a TD following the last.
1032 ; After that, go to step 6 with ecx = 0 (no error).
1033 cmp ecx, USB_STATUS_UNDERRUN
1034 jnz @f
1035 test byte [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1
1036 jnz @f
1037 ; The controller has stopped this queue on the error packet.
1038 ; Update uhci_pipe.HeadTD to point to the next packet in the queue.
1039 call uhci_fix_toggle
1040 xor ecx, ecx
1041 .control:
1042 mov eax, [ebx+uhci_gtd.NextTD-sizeof.uhci_gtd]
1043 and al, not 0xF
1044 mov edx, [ebx+usb_gtd.Pipe]
1045 mov [edx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax
1046 pop edx ; length
1047 jmp .notify
1049 ; 5f. Abort the entire transfer.
1050 ; There are two cases: either there is only one transfer stage
1051 ; (everything except control transfers), then ebx points to the last TD and
1052 ; all previous TD were unlinked and dismissed (if possible),
1053 ; or there are several stages (a control transfer) and ebx points to the last
1054 ; TD of Data or Status stage (usb_is_final_packet does not stop in Setup stage,
1055 ; because Setup stage can not produce short packets); for Data stage, we need
1056 ; to unlink and free (if possible) one more TD and advance ebx to the next one.
1057 cmp [ebx+usb_gtd.Callback], 0
1058 jnz .normal
1059 ; We cannot free ErrorTD yet, it could still be used by the hardware.
1060 push ecx
1061 mov eax, [ebx+usb_gtd.Pipe]
1062 push [ebx+usb_gtd.NextVirt]
1063 cmp ebx, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
1064 jz @f
1065 stdcall uhci_free_td, ebx
1067 pop ebx
1068 invoke usbhc_api.usb_unlink_td
1069 pop ecx
1070 .normal:
1071 ; 5g. For bulk/interrupt transfers we have no choice but halt the queue,
1072 ; the driver should intercede (through some API which is not written yet).
1073 ; Control pipes normally recover at the next SETUP transaction (first stage
1074 ; of any control transfer), so we hope on the best and just advance the queue
1075 ; to the next transfer. (According to the standard, "A control pipe may also
1076 ; support functional stall as well, but this is not recommended.").
1077 mov edx, [ebx+usb_gtd.Pipe]
1078 cmp [edx+usb_pipe.Type], CONTROL_PIPE
1079 jz .control
1080 ; Bulk/interrupt transfer; halt the queue.
1081 mov eax, [ebx+uhci_gtd.NextTD-sizeof.uhci_gtd]
1082 and al, not 0xF
1083 inc eax ; set Halted bit
1084 mov [edx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax
1085 pop edx ; restore length saved in step 5a
1086 .notify:
1087 ; 6. Either the descriptor in ebx was processed without errors,
1088 ; or all necessary error actions were taken and ebx points to the last
1089 ; related descriptor.
1090 invoke usbhc_api.usb_process_gtd
1091 ; 7. Free the current descriptor (if allowed) and return the next one.
1092 ; 7a. Save pointer to the next descriptor.
1093 push [ebx+usb_gtd.NextVirt]
1094 ; 7b. Free the descriptor, unless it is saved as ErrorTD.
1095 mov eax, [ebx+usb_gtd.Pipe]
1096 cmp [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe], ebx
1097 jz @f
1098 stdcall uhci_free_td, ebx
1100 ; 7c. Restore pointer to the next descriptor and return.
1101 pop ebx
1103 endp
1105 ; Helper procedure for restarting transfer queue.
1106 ; When transfers are queued, their toggle bit is filled assuming that
1107 ; everything will go without errors. On error, some packets needs to be
1108 ; skipped, so toggle bits may become incorrect.
1109 ; This procedure fixes toggle bits.
1110 ; in: ebx -> last packet to be skipped, ErrorTD -> last processed packet
1111 proc uhci_fix_toggle
1112 ; 1. Nothing to do for control pipes: in that case,
1113 ; toggle bits for different transfer stages are independent.
1114 mov ecx, [ebx+usb_gtd.Pipe]
1115 cmp [ecx+usb_pipe.Type], CONTROL_PIPE
1116 jz .nothing
1117 ; 2. The hardware expects next packet with toggle = (ErrorTD.toggle xor 1),
1118 ; the current value in next packet is (ebx.toggle xor 1).
1119 ; Nothing to do if ErrorTD.toggle == ebx.toggle.
1120 mov eax, [ecx+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
1121 mov eax, [eax+uhci_gtd.Token-sizeof.uhci_gtd]
1122 xor eax, [ebx+uhci_gtd.Token-sizeof.uhci_gtd]
1123 test eax, 1 shl 19
1124 jz .nothing
1125 ; 3. Lock the transfer queue.
1126 add ecx, usb_pipe.Lock
1127 invoke MutexLock
1128 ; 4. Flip the toggle bit in all packets from ebx.NextVirt to ecx.LastTD
1129 ; (inclusive).
1130 mov eax, [ebx+usb_gtd.NextVirt]
1131 .loop:
1132 xor byte [eax+uhci_gtd.Token-sizeof.uhci_gtd+2], 1 shl (19-16)
1133 cmp eax, [ecx+usb_pipe.LastTD-usb_pipe.Lock]
1134 mov eax, [eax+usb_gtd.NextVirt]
1135 jnz .loop
1136 ; 5. Flip the toggle bit in uhci_pipe structure.
1137 xor byte [ecx+uhci_pipe.Token-sizeof.uhci_pipe-usb_pipe.Lock+2], 1 shl (19-16)
1138 ; 6. Unlock the transfer queue.
1139 invoke MutexUnlock
1140 .nothing:
1142 endp
1144 ; This procedure is called in the USB thread from uhci_process_deferred
1145 ; every UHCI_POLL_INTERVAL ticks. It polls the controller for
1146 ; connect/disconnect events.
1147 ; in: esi -> usb_controller
1148 proc uhci_poll_roothub
1149 push ebx ; save used register to be stdcall
1150 ; 1. Prepare for the loop for every port.
1151 xor ecx, ecx
1152 .portloop:
1153 ; 2. Some implementations of UHCI set ConnectStatusChange bit in a response to
1154 ; PortReset. Thus, we must ignore this change for port which is resetting.
1155 cmp cl, [esi+usb_controller.ResettingPort]
1156 jz .nextport
1157 ; 3. Read port status.
1158 mov edx, [esi+uhci_controller.IOBase-sizeof.uhci_controller]
1159 lea edx, [edx+ecx*2+UhciPort1StatusReg]
1160 in ax, dx
1161 ; 4. If no change bits are set, continue to the next port.
1162 test al, 0Ah
1163 jz .nextport
1164 ; 5. Clear change bits and read the status again.
1165 ; (It is possible, although quite unlikely, that some event occurs between
1166 ; the first read and the clearing, invalidating the old status. If an event
1167 ; occurs after the clearing, we will not miss it, looking in the next scan.
1168 out dx, ax
1169 mov ebx, eax
1170 in ax, dx
1171 ; 6. Process connect change notifications.
1172 ; Note: if connect status has changed, ignore enable status change;
1173 ; it is normal to disable a port at disconnect event.
1174 ; Some controllers set enable status change bit, some don't.
1175 test bl, 2
1176 jz .noconnectchange
1177 DEBUGF 1,'K : UHCI %x connect status changed, %x/%x\n',esi,bx,ax
1178 ; yep. Regardless of the current status, note disconnect event;
1179 ; if there is something connected, store the connect time and note connect event.
1180 ; In any way, do not process
1181 bts [esi+usb_controller.NewDisconnected], ecx
1182 test al, 1
1183 jz .disconnect
1184 invoke GetTimerTicks
1185 mov [esi+usb_controller.ConnectedTime+ecx*4], eax
1186 bts [esi+usb_controller.NewConnected], ecx
1187 jmp .nextport
1188 .disconnect:
1189 btr [esi+usb_controller.NewConnected], ecx
1190 jmp .nextport
1191 .noconnectchange:
1192 ; 7. Process enable change notifications.
1193 ; Note: that needs work.
1194 test bl, 8
1195 jz .nextport
1196 test al, 4
1197 jnz .nextport
1198 dbgstr 'Port disabled'
1199 .nextport:
1200 ; 8. Continue the loop for every port.
1201 inc ecx
1202 cmp ecx, [esi+usb_controller.NumPorts]
1203 jb .portloop
1204 pop ebx ; restore used register to be stdcall
1206 endp
1208 ; This procedure is called from uhci_process_deferred when
1209 ; a new device was connected at least USB_CONNECT_DELAY ticks
1210 ; and therefore is ready to be configured.
1211 ; in: esi -> usb_controller, ecx = port (zero-based)
1212 proc uhci_new_port
1213 ; test whether we are configuring another port
1214 ; if so, postpone configuring and return
1215 bts [esi+usb_controller.PendingPorts], ecx
1216 cmp [esi+usb_controller.ResettingPort], -1
1217 jnz .nothing
1218 btr [esi+usb_controller.PendingPorts], ecx
1219 ; fall through to uhci_new_port.reset
1221 ; This function is called from uhci_new_port and uhci_test_pending_port.
1222 ; It starts reset signalling for the port. Note that in USB first stages
1223 ; of configuration can not be done for several ports in parallel.
1224 .reset:
1225 ; 1. Store information about resetting hub (roothub) and port.
1226 and [esi+usb_controller.ResettingHub], 0
1227 mov [esi+usb_controller.ResettingPort], cl
1228 ; 2. Initiate reset signalling.
1229 mov edx, [esi+uhci_controller.IOBase-sizeof.uhci_controller]
1230 lea edx, [edx+ecx*2+UhciPort1StatusReg]
1231 in ax, dx
1232 or ah, 2
1233 out dx, ax
1234 ; 3. Store the current time and set status to 1 = reset signalling active.
1235 invoke GetTimerTicks
1236 mov [esi+usb_controller.ResetTime], eax
1237 mov [esi+usb_controller.ResettingStatus], 1
1238 .nothing:
1240 endp
1242 ; This procedure is called from uhci_process_deferred when
1243 ; reset signalling for a port needs to be finished.
1244 proc uhci_port_reset_done
1245 ; 1. Stop reset signalling.
1246 movzx ecx, [esi+usb_controller.ResettingPort]
1247 mov edx, [esi+uhci_controller.IOBase-sizeof.uhci_controller]
1248 lea edx, [edx+ecx*2+UhciPort1StatusReg]
1249 in ax, dx
1250 DEBUGF 1,'K : UHCI %x status %x/',esi,ax
1251 and ah, not 2
1252 out dx, ax
1253 ; 2. Status bits in UHCI are invalid during reset signalling.
1254 ; Wait a millisecond while status bits become valid again.
1255 push esi
1256 movi esi, 1
1257 invoke Sleep
1258 pop esi
1259 ; 3. ConnectStatus bit is zero during reset and becomes 1 during step 2;
1260 ; some controllers interpret this as a (fake) connect event.
1261 ; Enable port and clear status change notification.
1262 in ax, dx
1263 DEBUGF 1,'%x\n',ax
1264 or al, 6 ; enable port, clear status change
1265 out dx, ax
1266 ; 4. Store the current time and set status to 2 = reset recovery active.
1267 invoke GetTimerTicks
1268 DEBUGF 1,'K : reset done\n'
1269 mov [esi+usb_controller.ResetTime], eax
1270 mov [esi+usb_controller.ResettingStatus], 2
1272 endp
1274 ; This procedure is called from uhci_process_deferred when
1275 ; a new device has been reset, recovered after reset and
1276 ; needs to be configured.
1277 ; in: esi -> usb_controller
1278 proc uhci_port_init
1279 ; 1. Read port status.
1280 mov [esi+usb_controller.ResettingStatus], 0
1281 movzx ecx, [esi+usb_controller.ResettingPort]
1282 mov edx, [esi+uhci_controller.IOBase-sizeof.uhci_controller]
1283 lea edx, [edx+ecx*2+UhciPort1StatusReg]
1284 in ax, dx
1285 DEBUGF 1,'K : UHCI %x status %x\n',esi,ax
1286 ; 2. If the device has been disconnected, stop the initialization.
1287 test al, 1
1288 jnz @f
1289 dbgstr 'USB port disabled after reset'
1290 jmp [usbhc_api.usb_test_pending_port]
1292 ; 3. Copy LowSpeed bit to bit 0 of eax and call the worker procedure
1293 ; to notify the protocol layer about new UHCI device.
1294 push edx
1295 mov al, ah
1296 call uhci_new_device
1297 pop edx
1298 test eax, eax
1299 jnz .nothing
1300 ; 4. If something at the protocol layer has failed
1301 ; (no memory, no bus address), disable the port and stop the initialization.
1302 .disable_exit:
1303 in ax, dx
1304 and al, not 4
1305 out dx, ax ; disable the port
1306 jmp [usbhc_api.usb_test_pending_port]
1307 .nothing:
1309 endp
1311 ; This procedure is called from uhci_port_init and from hub support code
1312 ; when a new device is connected and has been reset.
1313 ; It calls usb_new_device at the protocol layer with correct parameters.
1314 ; in: esi -> usb_controller, eax = speed;
1315 ; UHCI is USB1 device, so only low bit of eax (LowSpeed) is used.
1316 proc uhci_new_device
1317 ; 1. Clear all bits of speed except bit 0.
1318 and eax, 1
1319 ; 2. Store the speed for the protocol layer.
1320 mov [esi+usb_controller.ResettingSpeed], al
1321 ; 3. Create pseudo-pipe in the stack.
1322 ; See uhci_init_pipe: only .Controller and .Token fields are used.
1323 push esi ; fill .Controller field
1324 mov ecx, esp
1325 shl eax, 20 ; bit 20 = LowSpeedDevice
1326 push eax ; ignored (ErrorTD)
1327 push eax ; .Token field: DeviceAddress is zero, bit 20 = LowSpeedDevice
1328 ; 4. Notify the protocol layer.
1329 invoke usbhc_api.usb_new_device
1330 ; 5. Cleanup the stack after step 3 and return.
1331 add esp, 12
1333 endp
1335 ; This procedure is called from usb_set_address_callback
1336 ; and stores USB device address in the uhci_pipe structure.
1337 ; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
1338 proc uhci_set_device_address
1339 mov byte [ebx+uhci_pipe.Token+1-sizeof.uhci_pipe], cl
1340 jmp [usbhc_api.usb_subscription_done]
1341 endp
1343 ; This procedure returns USB device address from the uhci_pipe structure.
1344 ; in: esi -> usb_controller, ebx -> usb_pipe
1345 ; out: eax = endpoint address
1346 proc uhci_get_device_address
1347 mov al, byte [ebx+uhci_pipe.Token+1-sizeof.uhci_pipe]
1348 and eax, 7Fh
1350 endp
1352 ; This procedure is called from usb_set_address_callback
1353 ; if the device does not accept SET_ADDRESS command and needs
1354 ; to be disabled at the port level.
1355 ; in: esi -> usb_controller, ecx = port (zero-based)
1356 proc uhci_port_disable
1357 mov edx, [esi+uhci_controller.IOBase-sizeof.uhci_controller]
1358 lea edx, [edx+UhciPort1StatusReg+ecx*2]
1359 in ax, dx
1360 and al, not 4
1361 out dx, ax
1363 endp
1365 ; This procedure is called from usb_get_descr8_callback when
1366 ; the packet size for zero endpoint becomes known and
1367 ; stores the packet size in uhci_pipe structure.
1368 ; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size
1369 proc uhci_set_endpoint_packet_size
1370 dec ecx
1371 shl ecx, 21
1372 and [ebx+uhci_pipe.Token-sizeof.uhci_pipe], (1 shl 21) - 1
1373 or [ebx+uhci_pipe.Token-sizeof.uhci_pipe], ecx
1374 ; uhci_pipe.Token field is purely for software bookkeeping and does not affect
1375 ; the hardware; thus, we can continue initialization immediately.
1376 jmp [usbhc_api.usb_subscription_done]
1377 endp
1379 ; This procedure is called from API usb_open_pipe and processes
1380 ; the controller-specific part of this API. See docs.
1381 ; in: edi -> usb_pipe for target, ecx -> usb_pipe for config pipe,
1382 ; esi -> usb_controller, eax -> usb_gtd for the first TD,
1383 ; [ebp+12] = endpoint, [ebp+16] = maxpacket, [ebp+20] = type
1384 proc uhci_init_pipe
1385 ; inherit some variables from the parent usb_open_pipe
1386 virtual at ebp-12
1387 .speed db ?
1388 rb 3
1389 .bandwidth dd ?
1390 .target dd ?
1391 rd 2
1392 .config_pipe dd ?
1393 .endpoint dd ?
1394 .maxpacket dd ?
1395 .type dd ?
1396 .interval dd ?
1397 end virtual
1398 ; 1. Initialize ErrorTD to zero.
1399 and [edi+uhci_pipe.ErrorTD-sizeof.uhci_pipe], 0
1400 ; 2. Initialize HeadTD to the physical address of the first TD.
1401 push eax ; store pointer to the first TD for step 4
1402 sub eax, sizeof.uhci_gtd
1403 invoke GetPhysAddr
1404 mov [edi+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax
1405 ; 3. Initialize Token field:
1406 ; take DeviceAddress and LowSpeedDevice from the parent pipe,
1407 ; take Endpoint and MaximumLength fields from API arguments,
1408 ; set PID depending on pipe type and provided pipe direction,
1409 ; set DataToggle to zero.
1410 mov eax, [ecx+uhci_pipe.Token-sizeof.uhci_pipe]
1411 and eax, 0x107F00 ; keep DeviceAddress and LowSpeedDevice
1412 mov edx, [.endpoint]
1413 and edx, 15
1414 shl edx, 15
1415 or eax, edx
1416 mov edx, [.maxpacket]
1417 dec edx
1418 shl edx, 21
1419 or eax, edx
1420 mov al, USB_PID_SETUP
1421 cmp [.type], CONTROL_PIPE
1422 jz @f
1423 mov al, USB_PID_OUT
1424 test byte [.endpoint], 80h
1425 jz @f
1426 mov al, USB_PID_IN
1428 mov [edi+uhci_pipe.Token-sizeof.uhci_pipe], eax
1429 bt eax, 20
1430 setc [.speed]
1431 ; 4. Initialize the first TD:
1432 ; copy Token from uhci_pipe.Token zeroing reserved bit 20,
1433 ; set ControlStatus for future transfers, bit make it inactive,
1434 ; set bit 0 in NextTD = "no next TD",
1435 ; zero OrigBufferInfo.
1436 pop edx ; restore pointer saved in step 2
1437 mov [edx+uhci_gtd.Token-sizeof.uhci_gtd], eax
1438 and byte [edx+uhci_gtd.Token+2-sizeof.uhci_gtd], not (1 shl (20-16))
1439 and eax, 1 shl 20
1440 shl eax, 6
1441 or eax, UHCI_INVALID_LENGTH + (3 shl 27)
1442 ; not processed, inactive, allow 3 errors
1443 and [edx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 0
1444 mov [edx+uhci_gtd.ControlStatus-sizeof.uhci_gtd], eax
1445 mov [edx+uhci_gtd.NextTD-sizeof.uhci_gtd], 1
1446 ; 5. Select the corresponding list and insert to the list.
1447 ; 5a. Use Control list for control pipes, Bulk list for bulk pipes.
1448 lea edx, [esi+uhci_controller.ControlED.SoftwarePart-sizeof.uhci_controller]
1449 cmp [.type], BULK_PIPE
1450 jb .insert ; control pipe
1451 lea edx, [esi+uhci_controller.BulkED.SoftwarePart-sizeof.uhci_controller]
1452 jz .insert ; bulk pipe
1453 .interrupt_pipe:
1454 ; 5b. For interrupt pipes, let the scheduler select the appropriate list
1455 ; based on the current bandwidth distribution and the requested bandwidth.
1456 ; This could fail if the requested bandwidth is not available;
1457 ; if so, return an error.
1458 lea edx, [esi + uhci_controller.IntEDs - sizeof.uhci_controller]
1459 lea eax, [esi + uhci_controller.IntEDs + 32*sizeof.uhci_static_ep - sizeof.uhci_controller]
1460 movi ecx, 64
1461 call usb1_select_interrupt_list
1462 test edx, edx
1463 jz .return0
1464 .insert:
1465 mov [edi+usb_pipe.BaseList], edx
1466 ; Insert to the head of the corresponding list.
1467 ; Note: inserting to the head guarantees that the list traverse in
1468 ; uhci_process_updated_schedule, once started, will not interact with new pipes.
1469 ; However, we still need to ensure that links in the new pipe (edi.NextVirt)
1470 ; are initialized before links to the new pipe (edx.NextVirt).
1471 ; 5c. Insert in the list of virtual addresses.
1472 mov ecx, [edx+usb_pipe.NextVirt]
1473 mov [edi+usb_pipe.NextVirt], ecx
1474 mov [edi+usb_pipe.PrevVirt], edx
1475 mov [ecx+usb_pipe.PrevVirt], edi
1476 mov [edx+usb_pipe.NextVirt], edi
1477 ; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
1478 ; store the physical address of the new pipe to previous NextQH.
1479 mov ecx, [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart]
1480 mov [edi+uhci_pipe.NextQH-sizeof.uhci_pipe], ecx
1481 lea eax, [edi-sizeof.uhci_pipe]
1482 invoke GetPhysAddr
1483 inc eax
1484 inc eax
1485 mov [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart], eax
1486 ; 6. Return with nonzero eax.
1488 .return0:
1489 xor eax, eax
1491 endp
1493 ; This procedure is called when a pipe is closing (either due to API call
1494 ; or due to disconnect); it unlinks a pipe from the corresponding list.
1495 if uhci_static_ep.SoftwarePart <> sizeof.uhci_pipe
1496 .err uhci_unlink_pipe assumes that uhci_static_ep.SoftwarePart == sizeof.uhci_pipe
1497 end if
1498 proc uhci_unlink_pipe
1499 cmp [ebx+usb_pipe.Type], INTERRUPT_PIPE
1500 jnz @f
1501 mov eax, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
1502 cmp al, USB_PID_IN
1503 setz ch
1504 bt eax, 20
1505 setc cl
1506 add eax, 1 shl 21
1507 shr eax, 21
1508 stdcall usb1_interrupt_list_unlink, eax, ecx
1511 endp
1513 ; This procedure temporarily removes the given pipe from hardware queue,
1514 ; keeping it in software lists.
1515 ; esi -> usb_controller, ebx -> usb_pipe
1516 proc uhci_disable_pipe
1517 mov eax, [ebx+uhci_pipe.NextQH-sizeof.uhci_pipe]
1518 mov edx, [ebx+usb_pipe.PrevVirt]
1519 ; Note: edx could be either usb_pipe or usb_static_ep;
1520 ; fortunately, NextQH and SoftwarePart have same offsets in both.
1521 mov [edx+uhci_pipe.NextQH-sizeof.uhci_pipe], eax
1523 endp
1525 ; This procedure reinserts the given pipe from hardware queue
1526 ; after ehci_disable_pipe, with clearing transfer queue.
1527 ; esi -> usb_controller, ebx -> usb_pipe
1528 ; edx -> current descriptor, eax -> new last descriptor
1529 proc uhci_enable_pipe
1530 ; 1. Copy DataToggle bit from edx to pipe.
1531 mov ecx, [edx+uhci_gtd.Token-sizeof.uhci_gtd]
1532 xor ecx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
1533 and ecx, 1 shl 19
1534 xor [ebx+uhci_pipe.Token-sizeof.uhci_pipe], ecx
1535 ; 2. Store new last descriptor as the current HeadTD.
1536 sub eax, sizeof.uhci_gtd
1537 invoke GetPhysAddr
1538 mov [ebx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax
1539 ; 3. Reinsert the pipe to hardware queue.
1540 lea eax, [ebx-sizeof.uhci_pipe]
1541 invoke GetPhysAddr
1542 inc eax
1543 inc eax
1544 mov edx, [ebx+usb_pipe.PrevVirt]
1545 mov ecx, [edx+uhci_pipe.NextQH-sizeof.uhci_pipe]
1546 mov [ebx+uhci_pipe.NextQH-sizeof.uhci_pipe], ecx
1547 mov [edx+uhci_pipe.NextQH-sizeof.uhci_pipe], eax
1549 endp
1551 ; This procedure is called from the several places in main USB code
1552 ; and allocates required packets for the given transfer stage.
1553 ; ebx = pipe, other parameters are passed through the stack
1554 proc uhci_alloc_transfer stdcall uses edi, buffer:dword, size:dword, flags:dword, td:dword, direction:dword
1555 locals
1556 token dd ?
1557 origTD dd ?
1558 packetSize dd ? ; must be the last variable, see usb_init_transfer
1559 endl
1560 ; 1. [td] will be the first packet in the transfer.
1561 ; Save it to allow unrolling if something will fail.
1562 mov eax, [td]
1563 mov [origTD], eax
1564 ; In UHCI one TD describes one packet, transfers should be split into parts
1565 ; with size <= endpoint max packet size.
1566 ; 2. Get the maximum packet size for endpoint from uhci_pipe.Token
1567 ; and generate Token field for TDs.
1568 mov edi, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
1569 mov eax, edi
1570 shr edi, 21
1571 inc edi
1572 ; zero packet size (it will be set for every packet individually),
1573 ; zero reserved bit 20,
1574 and eax, (1 shl 20) - 1
1575 mov [packetSize], edi
1576 ; set the correct PID if it is different from the pipe-wide PID
1577 ; (Data and Status stages of control transfers),
1578 mov ecx, [direction]
1579 and ecx, 3
1580 jz @f
1581 mov al, USB_PID_OUT
1582 dec ecx
1583 jz @f
1584 mov al, USB_PID_IN
1586 ; set the toggle bit for control transfers,
1587 mov ecx, [direction]
1588 test cl, 1 shl 3
1589 jz @f
1590 and ecx, 1 shl 2
1591 and eax, not (1 shl 19)
1592 shl ecx, 19-2
1593 or eax, ecx
1595 ; store the resulting Token in the stack variable.
1596 mov [token], eax
1597 ; 3. While the remaining data cannot fit in one packet,
1598 ; allocate full packets (of maximal possible size).
1599 .fullpackets:
1600 cmp [size], edi
1601 jbe .lastpacket
1602 call uhci_alloc_packet
1603 test eax, eax
1604 jz .fail
1605 mov [td], eax
1606 add [buffer], edi
1607 sub [size], edi
1608 jmp .fullpackets
1609 .lastpacket:
1610 ; 4. The remaining data can fit in one packet;
1611 ; allocate the last packet with size = size of remaining data.
1612 mov eax, [size]
1613 mov [packetSize], eax
1614 call uhci_alloc_packet
1615 test eax, eax
1616 jz .fail
1617 ; 5. Clear 'short packets are not allowed' bit for the last packet,
1618 ; if the caller requested this.
1619 ; Note: even if the caller says that short transfers are ok,
1620 ; all packets except the last one are marked as 'must be complete':
1621 ; if one of them will be short, the software intervention is needed
1622 ; to skip remaining packets; uhci_process_finalized_td will handle this
1623 ; transparently to the caller.
1624 test [flags], 1
1625 jz @f
1626 and byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], not (1 shl (29-24))
1627 and byte [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], not 1
1629 ; 6. Update toggle bit in uhci_pipe structure from current value of [token].
1630 mov edx, [token]
1631 xor edx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
1632 and edx, 1 shl 19
1633 xor [ebx+uhci_pipe.Token-sizeof.uhci_pipe], edx
1634 .nothing:
1636 .fail:
1637 mov edi, uhci_hardware_func
1638 mov eax, [td]
1639 invoke usbhc_api.usb_undo_tds, [origTD]
1640 xor eax, eax
1641 jmp .nothing
1642 endp
1644 ; Helper procedure for uhci_alloc_transfer. Allocates one packet.
1645 proc uhci_alloc_packet
1646 ; inherit some variables from the parent uhci_alloc_transfer
1647 virtual at ebp-12
1648 .token dd ?
1649 .origTD dd ?
1650 .packetSize dd ?
1651 rd 2
1652 .buffer dd ?
1653 .transferSize dd ?
1654 .Flags dd ?
1655 .td dd ?
1656 .direction dd ?
1657 end virtual
1658 ; 1. In UHCI all data for one packet must be on the same page.
1659 ; Thus, if the given buffer splits page boundary, we need a temporary buffer
1660 ; and code that transfers data between the given buffer and the temporary one.
1661 ; 1a. There is no buffer for zero-length packets.
1662 xor eax, eax
1663 cmp [.packetSize], eax
1664 jz .notempbuf
1665 ; 1b. A temporary buffer is not required if the first and the last bytes
1666 ; of the given buffer are the same except lower 12 bits.
1667 mov edx, [.buffer]
1668 add edx, [.packetSize]
1669 dec edx
1670 xor edx, [.buffer]
1671 test edx, -0x1000
1672 jz .notempbuf
1673 ; 1c. We need a temporary buffer. Allocate [packetSize]*2 bytes, so that
1674 ; there must be [packetSize] bytes on one page,
1675 ; plus space for a header uhci_original_buffer.
1676 mov eax, [.packetSize]
1677 add eax, eax
1678 add eax, sizeof.uhci_original_buffer
1679 invoke Kmalloc
1680 ; 1d. If failed, return zero.
1681 test eax, eax
1682 jz .nothing
1683 ; 1e. Test whether [.packetSize] bytes starting from
1684 ; eax + sizeof.uhci_original_buffer are in the same page.
1685 ; If so, use eax + sizeof.uhci_original_buffer as a temporary buffer.
1686 ; Otherwise, use the beginning of the next page as a temporary buffer
1687 ; (since we have overallocated, sufficient space must remain).
1688 lea ecx, [eax+sizeof.uhci_original_buffer]
1689 mov edx, ecx
1690 add edx, [.packetSize]
1691 dec edx
1692 xor edx, ecx
1693 test edx, -0x1000
1694 jz @f
1695 mov ecx, eax
1696 or ecx, 0xFFF
1697 inc ecx
1699 mov [eax+uhci_original_buffer.UsedBuffer], ecx
1700 mov ecx, [.buffer]
1701 mov [eax+uhci_original_buffer.OrigBuffer], ecx
1702 ; 1f. For SETUP and OUT packets, copy data from the given buffer
1703 ; to the temporary buffer now. For IN packets, data go in other direction
1704 ; when the transaction completes.
1705 cmp byte [.token], USB_PID_IN
1706 jz .nocopy
1707 push esi edi
1708 mov esi, ecx
1709 mov edi, [eax+uhci_original_buffer.UsedBuffer]
1710 mov ecx, [.packetSize]
1711 mov edx, ecx
1712 shr ecx, 2
1713 and edx, 3
1714 rep movsd
1715 mov ecx, edx
1716 rep movsb
1717 pop edi esi
1718 .nocopy:
1719 .notempbuf:
1720 ; 2. Allocate the next TD.
1721 push eax
1722 call uhci_alloc_td
1723 pop edx
1724 ; If failed, free the temporary buffer (if it was allocated) and return zero.
1725 test eax, eax
1726 jz .fail
1727 ; 3. Initialize controller-independent parts of both TDs.
1728 push edx
1729 invoke usbhc_api.usb_init_transfer
1730 ; 4. Initialize the next TD:
1731 ; mark it as last one (this will be changed when further packets will be
1732 ; allocated), copy Token field from uhci_pipe.Token zeroing bit 20,
1733 ; generate ControlStatus field, mark as Active
1734 ; (for last descriptor, this will be changed by uhci_insert_transfer),
1735 ; zero OrigBufferInfo (otherwise uhci_free_td would try to free it).
1736 and [eax+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 0
1737 mov [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 1 ; no next TD
1738 mov edx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
1739 mov [eax+uhci_gtd.Token-sizeof.uhci_gtd], edx
1740 and byte [eax+uhci_gtd.Token+2-sizeof.uhci_gtd], not (1 shl (20-16))
1741 and edx, 1 shl 20
1742 shl edx, 6
1743 or edx, UHCI_INVALID_LENGTH + (1 shl 23) + (3 shl 27)
1744 ; not processed, active, allow 3 errors
1745 mov [eax+uhci_gtd.ControlStatus-sizeof.uhci_gtd], edx
1746 ; 5. Initialize remaining fields of the current TD.
1747 ; 5a. Store pointer to the buffer allocated in step 1 (or zero).
1748 pop [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
1749 ; 5b. Store physical address of the next TD.
1750 push eax
1751 sub eax, sizeof.uhci_gtd
1752 invoke GetPhysAddr
1753 ; for Control/Bulk pipes, use Depth traversal unless this is the first TD
1754 ; in the transfer stage;
1755 ; uhci_insert_transfer will set Depth traversal for the first TD and clear
1756 ; it in the last TD
1757 test [ebx+usb_pipe.Type], 1
1758 jnz @f
1759 cmp ecx, [ebx+usb_pipe.LastTD]
1760 jz @f
1761 or eax, 4
1763 mov [ecx+uhci_gtd.NextTD-sizeof.uhci_gtd], eax
1764 ; 5c. Store physical address of the buffer: zero if no data present,
1765 ; the temporary buffer if it was allocated, the given buffer otherwise.
1766 xor eax, eax
1767 cmp [.packetSize], eax
1768 jz .hasphysbuf
1769 mov eax, [.buffer]
1770 mov edx, [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
1771 test edx, edx
1772 jz @f
1773 mov eax, [edx+uhci_original_buffer.UsedBuffer]
1775 invoke GetPhysAddr
1776 .hasphysbuf:
1777 mov [ecx+uhci_gtd.Buffer-sizeof.uhci_gtd], eax
1778 ; 5d. For IN transfers, disallow short packets.
1779 ; This will be overridden, if needed, by uhci_alloc_transfer.
1780 mov eax, [.token]
1781 mov edx, [.packetSize]
1782 dec edx
1783 cmp al, USB_PID_IN
1784 jnz @f
1785 or byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (29-24) ; disallow short packets
1786 or byte [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1
1788 ; 5e. Get Token field: combine [.token] with [.packetSize].
1789 shl edx, 21
1790 or edx, eax
1791 mov [ecx+uhci_gtd.Token-sizeof.uhci_gtd], edx
1792 ; 6. Flip toggle bit in [.token].
1793 xor eax, 1 shl 19
1794 mov [.token], eax
1795 ; 7. Return pointer to the next TD.
1796 pop eax
1797 .nothing:
1799 .fail:
1800 xchg eax, edx
1801 invoke Kfree
1802 xor eax, eax
1804 endp
1806 ; This procedure is called from the several places in main USB code
1807 ; and activates the transfer which was previously allocated by
1808 ; uhci_alloc_transfer.
1809 ; ecx -> last descriptor for the transfer, ebx -> usb_pipe
1810 proc uhci_insert_transfer
1811 ; DEBUGF 1,'K : uhci_insert_transfer: eax=%x, ecx=%x, [esp+4]=%x\n',eax,ecx,[esp+4]
1812 and byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], not (1 shl (23-16)) ; clear Active bit
1813 or byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (24-24) ; set InterruptOnComplete bit
1814 mov eax, [esp+4]
1815 or byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], 1 shl (23-16) ; set Active bit
1816 test [ebx+usb_pipe.Type], 1
1817 jnz @f
1818 or byte [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 4 ; set Depth bit
1821 endp
1823 ; Allocates one endpoint structure for OHCI.
1824 ; Returns pointer to software part (usb_pipe) in eax.
1825 proc uhci_alloc_pipe
1826 push ebx
1827 mov ebx, uhci_ep_mutex
1828 invoke usbhc_api.usb_allocate_common, (sizeof.uhci_pipe + sizeof.usb_pipe + 0Fh) and not 0Fh
1829 test eax, eax
1830 jz @f
1831 add eax, sizeof.uhci_pipe
1833 pop ebx
1835 endp
1837 ; Free memory associated with pipe.
1838 ; For UHCI, this includes usb_pipe structure and ErrorTD, if present.
1839 proc uhci_free_pipe
1840 mov eax, [esp+4]
1841 mov eax, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
1842 test eax, eax
1843 jz @f
1844 stdcall uhci_free_td, eax
1846 sub dword [esp+4], sizeof.uhci_pipe
1847 jmp [usbhc_api.usb_free_common]
1848 endp
1850 ; Allocates one general transfer descriptor structure for UHCI.
1851 ; Returns pointer to software part (usb_gtd) in eax.
1852 proc uhci_alloc_td
1853 push ebx
1854 mov ebx, uhci_gtd_mutex
1855 invoke usbhc_api.usb_allocate_common, (sizeof.uhci_gtd + sizeof.usb_gtd + 0Fh) and not 0Fh
1856 test eax, eax
1857 jz @f
1858 add eax, sizeof.uhci_gtd
1860 pop ebx
1862 endp
1864 ; Free all memory associated with one TD.
1865 ; For UHCI, this includes memory for uhci_gtd itself
1866 ; and the temporary buffer, if present.
1867 proc uhci_free_td
1868 mov eax, [esp+4]
1869 mov eax, [eax+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
1870 and eax, not 1
1871 jz .nobuf
1872 invoke Kfree
1873 .nobuf:
1874 sub dword [esp+4], sizeof.uhci_gtd
1875 jmp [usbhc_api.usb_free_common]
1876 endp
1878 include 'usb1_scheduler.inc'
1879 define_controller_name uhci
1881 section '.data' readable writable
1882 include '../peimport.inc'
1883 include_debug_strings
1884 IncludeIGlobals
1885 IncludeUGlobals
1886 align 4
1887 usbhc_api usbhc_func
1888 uhci_ep_first_page dd ?
1889 uhci_ep_mutex MUTEX
1890 uhci_gtd_first_page dd ?
1891 uhci_gtd_mutex MUTEX