Subversion Repositories Kolibri OS

Rev

Rev 4547 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ; Code for EHCI controllers.
  2.  
  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'
  15.  
  16. ; =============================================================================
  17. ; ================================= Constants =================================
  18. ; =============================================================================
  19. ; EHCI register declarations.
  20. ; Part 1. Capability registers.
  21. ; Base is MMIO from the PCI space.
  22. EhciCapLengthReg    = 0
  23. EhciVersionReg      = 2
  24. EhciStructParamsReg = 4
  25. EhciCapParamsReg    = 8
  26. EhciPortRouteReg    = 0Ch
  27. ; Part 2. Operational registers.
  28. ; Base is (base for part 1) + (value of EhciCapLengthReg).
  29. EhciCommandReg      = 0
  30. EhciStatusReg       = 4
  31. EhciInterruptReg    = 8
  32. EhciFrameIndexReg   = 0Ch
  33. EhciCtrlDataSegReg  = 10h
  34. EhciPeriodicListReg = 14h
  35. EhciAsyncListReg    = 18h
  36. EhciConfigFlagReg   = 40h
  37. EhciPortsReg        = 44h
  38.  
  39. ; Possible values of ehci_pipe.NextQH.Type bitfield.
  40. EHCI_TYPE_ITD  = 0 ; isochronous transfer descriptor
  41. EHCI_TYPE_QH   = 1 ; queue head
  42. EHCI_TYPE_SITD = 2 ; split-transaction isochronous TD
  43. EHCI_TYPE_FSTN = 3 ; frame span traversal node
  44.  
  45. ; =============================================================================
  46. ; ================================ Structures =================================
  47. ; =============================================================================
  48.  
  49. ; Hardware part of EHCI general transfer descriptor.
  50. struct ehci_hardware_td
  51. NextTD          dd      ?
  52. ; Bit 0 is Terminate bit, 1 = there is no next TD.
  53. ; Bits 1-4 must be zero.
  54. ; With masked 5 lower bits, this is the physical address of the next TD, if any.
  55. AlternateNextTD dd      ?
  56. ; Similar to NextTD, used if the transfer terminates with a short packet.
  57. Token           dd      ?
  58. ; 1. Lower byte is Status field:
  59. ; bit 0 = ping state for USB2 endpoints, ERR handshake signal for USB1 endpoints
  60. ; bit 1 = split transaction state, meaningless for USB2 endpoints
  61. ; bit 2 = missed micro-frame
  62. ; bit 3 = transaction error
  63. ; bit 4 = babble detected
  64. ; bit 5 = data buffer error
  65. ; bit 6 = halted
  66. ; bit 7 = active
  67. ; 2. Next two bits (bits 8-9) are PID code, 0 = OUT, 1 = IN, 2 = SETUP.
  68. ; 3. Next two bits (bits 10-11) is ErrorCounter. Initialized as 3, decremented
  69. ;    on each error; if it goes to zero, transaction is stopped.
  70. ; 4. Next 3 bits (bits 12-14) are CurrentPage field.
  71. ; 5. Next bit (bit 15) is InterruptOnComplete bit.
  72. ; 6. Next 15 bits (bits 16-30) are TransferLength field,
  73. ;    number of bytes to transfer.
  74. ; 7. Upper bit (bit 31) is DataToggle bit.
  75. BufferPointers  rd      5
  76. ; The buffer to be transferred can be spanned on up to 5 physical pages.
  77. ; The first item of this array is the physical address of the first byte in
  78. ; the buffer, other items are physical addresses of next pages. Lower 12 bits
  79. ; in other items must be set to zero; ehci_pipe.Overlay reuses some of them.
  80. BufferPointersHigh      rd      5
  81. ; Upper dwords of BufferPointers for controllers with 64-bit memory access.
  82. ; Always zero.
  83. ends
  84.  
  85. ; EHCI general transfer descriptor.
  86. ; * The structure describes transfers to be performed on Control, Bulk or
  87. ;   Interrupt endpoints.
  88. ; * The structure includes two parts, the hardware part and the software part.
  89. ; * The hardware part consists of first 52 bytes and corresponds to
  90. ;   the Queue Element Transfer Descriptor from EHCI specification.
  91. ; * The hardware requires 32-bytes alignment of the hardware part, so
  92. ;   the entire descriptor must be 32-bytes aligned. Since the allocator
  93. ;   (usb_allocate_common) allocates memory sequentially from page start
  94. ;   (aligned on 0x1000 bytes), block size for the allocator must be divisible
  95. ;   by 32; ehci_alloc_td ensures this.
  96. ; * The hardware also requires that the hardware part must not cross page
  97. ;   boundary; the allocator satisfies this automatically.
  98. struct ehci_gtd ehci_hardware_td
  99. Flags                   dd      ?
  100. ; Copy of flags from the call to usb_*_transfer_async.
  101. ends
  102.  
  103. ; EHCI-specific part of a pipe descriptor.
  104. ; * This structure corresponds to the Queue Head from the EHCI specification.
  105. ; * The hardware requires 32-bytes alignment of the hardware part.
  106. ;   Since the allocator (usb_allocate_common) allocates memory sequentially
  107. ;   from page start (aligned on 0x1000 bytes), block size for the allocator
  108. ;   must be divisible by 32; ehci_alloc_pipe ensures this.
  109. ; * The hardware requires also that the hardware part must not cross page
  110. ;   boundary; the allocator satisfies this automatically.
  111. struct ehci_pipe
  112. NextQH                  dd      ?
  113. ; 1. First bit (bit 0) is Terminate bit, 1 = there is no next QH.
  114. ; 2. Next two bits (bits 1-2) are Type field of the next QH,
  115. ;    one of EHCI_TYPE_* constants.
  116. ; 3. Next two bits (bits 3-4) are reserved, must be zero.
  117. ; 4. With masked 5 lower bits, this is the physical address of the next object
  118. ;    to be processed, usually next QH.
  119. Token                   dd      ?
  120. ; 1. Lower 7 bits are DeviceAddress field. This is the address of the
  121. ;    target device on the USB bus.
  122. ; 2. Next bit (bit 7) is Inactivate-on-next-transaction bit. Can be nonzero
  123. ;    only for interrupt/isochronous USB1 endpoints.
  124. ; 3. Next 4 bits (bits 8-11) are Endpoint field. This is the target endpoint
  125. ;    number.
  126. ; 4. Next 2 bits (bits 12-13) are EndpointSpeed field, one of EHCI_SPEED_*.
  127. ; 5. Next bit (bit 14) is DataToggleControl bit,
  128. ;    0 = use DataToggle bit from QH, 1 = from TD.
  129. ; 6. Next bit (bit 15) is Head-of-reclamation-list. The head of Control list
  130. ;    has 1 here, all other QHs have zero.
  131. ; 7. Next 11 bits (bits 16-26) are MaximumPacketLength field for the target
  132. ;    endpoint.
  133. ; 8. Next bit (bit 27) is ControlEndpoint bit, must be 1 for USB1 control
  134. ;    endpoints and 0 for all others.
  135. ; 9. Upper 4 bits (bits 28-31) are NakCountReload field.
  136. ;    Zero for USB1 endpoints, zero for periodic endpoints.
  137. ;    For control/bulk USB2 endpoints, the code sets it to 4,
  138. ;    which is rather arbitrary.
  139. Flags                   dd      ?
  140. ; 1. Lower byte is S-mask, each bit corresponds to one microframe per frame;
  141. ;    bit is set <=> enable transactions in this microframe.
  142. ; 2. Next byte is C-mask, each bit corresponds to one microframe per frame;
  143. ;    bit is set <=> enable complete-split transactions in this microframe.
  144. ;    Meaningful only for USB1 endpoints.
  145. ; 3. Next 14 bits give address of the target device as hub:port, bits 16-22
  146. ;    are the USB address of the hub, bits 23-29 are the port number.
  147. ;    Meaningful only for USB1 endpoints.
  148. ; 4. Upper 2 bits define number of consequetive transactions per micro-frame
  149. ;    which host is allowed to permit for this endpoint.
  150. ;    For control/bulk endpoints, it must be 1.
  151. ;    For periodic endpoints, the value is taken from the endpoint descriptor.
  152. HeadTD                  dd      ?
  153. ; The physical address of the first TD for this pipe.
  154. ; Lower 5 bits must be zero.
  155. Overlay                 ehci_hardware_td        ?
  156. ; Working area for the current TD, if there is any.
  157. ; When TD is retired, it is written to that TD and Overlay is loaded
  158. ; from the new TD, if any.
  159. ends
  160.  
  161. ; This structure describes the static head of every list of pipes.
  162. ; The hardware requires 32-bytes alignment of this structure.
  163. ; All instances of this structure are located sequentially in ehci_controller,
  164. ; ehci_controller is page-aligned, so it is sufficient to make this structure
  165. ; 32-bytes aligned and verify that the first instance is 32-bytes aligned
  166. ; inside ehci_controller.
  167. ; The hardware also requires that 44h bytes (size of 64-bit Queue Head
  168. ; Descriptor) starting at the beginning of this structure must not cross page
  169. ; boundary. If not, most hardware still behaves correctly (in fact, the last
  170. ; dword can have any value and this structure is never written), but on some
  171. ; hardware some things just break in mysterious ways.
  172. struct ehci_static_ep
  173. ; Hardware fields are the same as in ehci_pipe.
  174. ; Only NextQH and Overlay.Token are actually used.
  175. ; NB: some emulators ignore Token.Halted bit (probably assuming that it is set
  176. ; only when device fails and emulation never fails) and always follow
  177. ; [Alternate]NextTD when they see that OverlayToken.Active bit is zero;
  178. ; so it is important to also set [Alternate]NextTD to 1.
  179. NextQH          dd      ?
  180. Token           dd      ?
  181. Flags           dd      ?
  182. HeadTD          dd      ?
  183. NextTD          dd      ?
  184. AlternateNextTD dd      ?
  185. OverlayToken    dd      ?
  186. NextList        dd      ?
  187. SoftwarePart    rd      sizeof.usb_static_ep/4
  188. Bandwidths      rw      8
  189.                 dd      ?
  190. ends
  191.  
  192. if sizeof.ehci_static_ep mod 32
  193. .err ehci_static_ep must be 32-bytes aligned
  194. end if
  195.  
  196. if ehci_static_ep.OverlayToken <> ehci_pipe.Overlay.Token
  197. .err ehci_static_ep.OverlayToken misplaced
  198. end if
  199.  
  200. ; EHCI-specific part of controller data.
  201. ; * The structure includes two parts, the hardware part and the software part.
  202. ; * The hardware part consists of first 4096 bytes and corresponds to
  203. ;   the Periodic Frame List from the EHCI specification.
  204. ; * The hardware requires page-alignment of the hardware part, so
  205. ;   the entire descriptor must be page-aligned.
  206. ;   This structure is allocated with kernel_alloc (see usb_init_controller),
  207. ;   this gives page-aligned data.
  208. ; * The controller is described by both ehci_controller and usb_controller
  209. ;   structures, for each controller there is one ehci_controller and one
  210. ;   usb_controller structure. These structures are located sequentially
  211. ;   in the memory: beginning from some page start, there is ehci_controller
  212. ;   structure - this enforces hardware alignment requirements - and then
  213. ;   usb_controller structure.
  214. ; * The code keeps pointer to usb_controller structure. The ehci_controller
  215. ;   structure is addressed as [ptr + ehci_controller.field - sizeof.ehci_controller].
  216. struct ehci_controller
  217. ; ------------------------------ hardware fields ------------------------------
  218. FrameList               rd      1024
  219. ; Entry n corresponds to the head of the frame list to be executed in
  220. ; the frames n,n+1024,n+2048,n+3072,...
  221. ; The first bit of each entry is Terminate bit, 1 = the frame is empty.
  222. ; Bits 1-2 are Type field, one of EHCI_TYPE_* constants.
  223. ; Bits 3-4 must be zero.
  224. ; With masked 5 lower bits, the entry is a physical address of the first QH/TD
  225. ; to be executed.
  226. ; ------------------------------ software fields ------------------------------
  227. ; Every list has the static head, which is an always halted QH.
  228. ; The following fields are static heads, one per list:
  229. ; 32+16+8+4+2+1 = 63 for Periodic lists, 1 for Control list and 1 for Bulk list.
  230. IntEDs                  ehci_static_ep
  231.                         rb      62 * sizeof.ehci_static_ep
  232. ; Beware.
  233. ; Two following strings ensure that 44h bytes at any static head
  234. ; do not cross page boundary. Without that, the code "works on my machine"...
  235. ; but fails on some hardware in seemingly unrelated ways.
  236. ; One hardware TD (without any software fields) fit in the rest of the page.
  237. ehci_controller.ControlDelta = 2000h - (ehci_controller.IntEDs + 63 * sizeof.ehci_static_ep)
  238. StopQueueTD             ehci_hardware_td
  239. ; Used as AlternateNextTD for transfers when short packet is considered
  240. ; as an error; short packet must stop the queue in this case, not advance
  241. ; to the next transfer.
  242.                         rb      ehci_controller.ControlDelta - sizeof.ehci_hardware_td
  243. ; Padding for page-alignment.
  244. ControlED               ehci_static_ep
  245. BulkED                  ehci_static_ep
  246. MMIOBase1               dd      ?
  247. ; Virtual address of memory-mapped area with part 1 of EHCI registers EhciXxxReg.
  248. MMIOBase2               dd      ?
  249. ; Pointer inside memory-mapped area MMIOBase1; points to part 2 of EHCI registers.
  250. StructuralParams        dd      ?
  251. ; Copy of EhciStructParamsReg value.
  252. CapabilityParams        dd      ?
  253. ; Copy of EhciCapParamsReg value.
  254. DeferredActions         dd      ?
  255. ; Bitmask of events from EhciStatusReg which were observed by the IRQ handler
  256. ; and needs to be processed in the IRQ thread.
  257. PortRoutes              rb      16
  258. ; Companion port route description.
  259. ; Each byte describes routing of one port, value = PCI function.
  260. ; This field must be the last one:
  261. ; UHCI/OHCI code uses this field without knowing the entire structure.
  262. ends
  263.  
  264. if ehci_controller.IntEDs mod 32
  265. .err Static endpoint descriptors must be 32-bytes aligned inside ehci_controller
  266. end if
  267.  
  268. ; Description of #HCI-specific data and functions for
  269. ; controller-independent code.
  270. ; Implements the structure usb_hardware_func from hccommon.inc for EHCI.
  271. iglobal
  272. align 4
  273. ehci_hardware_func:
  274.         dd      USBHC_VERSION
  275.         dd      'EHCI'
  276.         dd      sizeof.ehci_controller
  277.         dd      ehci_kickoff_bios
  278.         dd      ehci_init
  279.         dd      ehci_process_deferred
  280.         dd      ehci_set_device_address
  281.         dd      ehci_get_device_address
  282.         dd      ehci_port_disable
  283.         dd      ehci_new_port.reset
  284.         dd      ehci_set_endpoint_packet_size
  285.         dd      ehci_alloc_pipe
  286.         dd      ehci_free_pipe
  287.         dd      ehci_init_pipe
  288.         dd      ehci_unlink_pipe
  289.         dd      ehci_alloc_td
  290.         dd      ehci_free_td
  291.         dd      ehci_alloc_transfer
  292.         dd      ehci_insert_transfer
  293.         dd      ehci_new_device
  294.         dd      ehci_disable_pipe
  295.         dd      ehci_enable_pipe
  296. ehci_name db    'EHCI',0
  297. endg
  298.  
  299. ; =============================================================================
  300. ; =================================== Code ====================================
  301. ; =============================================================================
  302.  
  303. ; Called once when driver is loading and once at shutdown.
  304. ; When loading, must initialize itself, register itself in the system
  305. ; and return eax = value obtained when registering.
  306. proc start
  307. virtual at esp
  308.                 dd      ? ; return address
  309. .reason         dd      ? ; DRV_ENTRY or DRV_EXIT
  310. .cmdline        dd      ? ; normally NULL
  311. end virtual
  312.         cmp     [.reason], DRV_ENTRY
  313.         jnz     .nothing
  314.         mov     ecx, ehci_ep_mutex
  315.         invoke  MutexInit
  316.         mov     ecx, ehci_gtd_mutex
  317.         invoke  MutexInit
  318.         push    esi edi
  319.         mov     esi, [USBHCFunc]
  320.         mov     edi, usbhc_api
  321.         movi    ecx, sizeof.usbhc_func/4
  322.         rep movsd
  323.         pop     edi esi
  324.         invoke  RegUSBDriver, ehci_name, 0, ehci_hardware_func
  325. .nothing:
  326.         ret
  327. endp
  328.  
  329. ; Controller-specific initialization function.
  330. ; Called from usb_init_controller. Initializes the hardware and
  331. ; EHCI-specific parts of software structures.
  332. ; eax = pointer to ehci_controller to be initialized
  333. ; [ebp-4] = pcidevice
  334. proc ehci_init
  335. ; inherit some variables from the parent (usb_init_controller)
  336. .devfn   equ ebp - 4
  337. .bus     equ ebp - 3
  338. ; 1. Store pointer to ehci_controller for further use.
  339.         push    eax
  340.         mov     edi, eax
  341.         mov     esi, eax
  342. ; 2. Initialize ehci_controller.FrameList.
  343. ; Note that FrameList is located in the beginning of ehci_controller,
  344. ; so esi and edi now point to ehci_controller.FrameList.
  345. ; First 32 entries of FrameList contain physical addresses
  346. ; of first 32 Periodic static heads, further entries duplicate these.
  347. ; See the description of structures for full info.
  348. ; 2a. Get physical address of first static head.
  349. ; Note that 1) it is located in the beginning of a page
  350. ; and 2) first 32 static heads fit in the same page,
  351. ; so one call to get_phys_addr without correction of lower 12 bits
  352. ; is sufficient.
  353. if (ehci_controller.IntEDs / 0x1000) <> ((ehci_controller.IntEDs + 32 * sizeof.ehci_static_ep) / 0x1000)
  354. .err assertion failed
  355. end if
  356. if (ehci_controller.IntEDs mod 0x1000) <> 0
  357. .err assertion failed
  358. end if
  359.         add     eax, ehci_controller.IntEDs
  360.         call    [GetPhysAddr]
  361. ; 2b. Fill first 32 entries.
  362.         inc     eax
  363.         inc     eax     ; set Type to EHCI_TYPE_QH
  364.         movi    ecx, 32
  365.         mov     edx, ecx
  366. @@:
  367.         stosd
  368.         add     eax, sizeof.ehci_static_ep
  369.         loop    @b
  370. ; 2c. Fill the rest entries.
  371.         mov     ecx, 1024 - 32
  372.         rep movsd
  373. ; 3. Initialize static heads ehci_controller.*ED.
  374. ; Use the loop over groups: first group consists of first 32 Periodic
  375. ; descriptors, next group consists of next 16 Periodic descriptors,
  376. ; ..., last group consists of the last Periodic descriptor.
  377. ; 3a. Prepare for the loop.
  378. ; make esi point to the second group, other registers are already set.
  379.         add     esi, 32*4 + 32*sizeof.ehci_static_ep
  380. ; 3b. Loop over groups. On every iteration:
  381. ; edx = size of group, edi = pointer to the current group,
  382. ; esi = pointer to the next group.
  383. .init_static_eds:
  384. ; 3c. Get the size of next group.
  385.         shr     edx, 1
  386. ; 3d. Exit the loop if there is no next group.
  387.         jz      .init_static_eds_done
  388. ; 3e. Initialize the first half of the current group.
  389. ; Advance edi to the second half.
  390.         push    esi
  391.         call    ehci_init_static_ep_group
  392.         pop     esi
  393. ; 3f. Initialize the second half of the current group
  394. ; with the same values.
  395. ; Advance edi to the next group, esi/eax to the next of the next group.
  396.         call    ehci_init_static_ep_group
  397.         jmp     .init_static_eds
  398. .init_static_eds_done:
  399. ; 3g. Initialize the last static head.
  400.         xor     esi, esi
  401.         call    ehci_init_static_endpoint
  402. ; While we are here, initialize StopQueueTD.
  403. if (ehci_controller.StopQueueTD <> ehci_controller.IntEDs + 63 * sizeof.ehci_static_ep)
  404. .err assertion failed
  405. end if
  406.         inc     [edi+ehci_hardware_td.NextTD]   ; 0 -> 1
  407.         inc     [edi+ehci_hardware_td.AlternateNextTD]  ; 0 -> 1
  408. ; leave other fields as zero, including Active bit
  409. ; 3i. Initialize the head of Control list.
  410.         add     edi, ehci_controller.ControlDelta
  411.         lea     esi, [edi+sizeof.ehci_static_ep]
  412.         call    ehci_init_static_endpoint
  413.         or      byte [edi-sizeof.ehci_static_ep+ehci_static_ep.Token+1], 80h
  414. ; 3j. Initialize the head of Bulk list.
  415.         sub     esi, sizeof.ehci_static_ep
  416.         call    ehci_init_static_endpoint
  417. ; 4. Create a virtual memory area to talk with the controller.
  418. ; 4a. Enable memory & bus master access.
  419.         invoke  PciRead16, dword [.bus], dword [.devfn], 4
  420.         or      al, 6
  421.         invoke  PciWrite16, dword [.bus], dword [.devfn], 4, eax
  422. ; 4b. Read memory base address.
  423.         invoke  PciRead32, dword [.bus], dword [.devfn], 10h
  424. ;       DEBUGF 1,'K : phys MMIO %x\n',eax
  425.         and     al, not 0Fh
  426. ; 4c. Create mapping for physical memory. 200h bytes are always sufficient.
  427.         invoke  MapIoMem, eax, 200h, PG_SW+PG_NOCACHE
  428.         test    eax, eax
  429.         jz      .fail
  430. ;       DEBUGF 1,'K : MMIO %x\n',eax
  431. if ehci_controller.MMIOBase1 <> ehci_controller.BulkED + sizeof.ehci_static_ep
  432. .err assertion failed
  433. end if
  434.         stosd   ; fill ehci_controller.MMIOBase1
  435. ; 5. Read basic parameters of the controller.
  436. ; 5a. Structural parameters.
  437.         mov     ebx, [eax+EhciStructParamsReg]
  438. ; 5b. Port routing rules.
  439. ; If bit 7 in HCSPARAMS is set, read and unpack EhciPortRouteReg.
  440. ; Otherwise, bits 11:8 are N_PCC = number of ports per companion,
  441. ; bits 15:12 are number of companions, maybe zero,
  442. ; first N_PCC ports are routed to the first companion and so on.
  443.         xor     esi, esi
  444.         test    bl, bl
  445.         js      .read_routes
  446.         test    bh, 0x0F
  447.         jz      .no_companions
  448.         test    bh, 0xF0
  449.         jz      .no_companions
  450.         xor     edx, edx
  451. .fill_routes:
  452.         movzx   ecx, bh
  453.         and     ecx, 15
  454. @@:
  455.         mov     byte [edi+esi+ehci_controller.PortRoutes-(ehci_controller.MMIOBase1+4)], dl
  456.         inc     esi
  457.         cmp     esi, 16
  458.         jz      .routes_filled
  459.         dec     ecx
  460.         jnz     @b
  461.         movzx   ecx, bh
  462.         shr     ecx, 4
  463.         inc     edx
  464.         cmp     edx, ecx
  465.         jb      .fill_routes
  466. .no_companions:
  467.         mov     byte [edi+esi+ehci_controller.PortRoutes-(ehci_controller.MMIOBase1+4)], 0xFF
  468.         inc     esi
  469.         cmp     esi, 16
  470.         jnz     .no_companions
  471.         jmp     .routes_filled
  472. .read_routes:
  473. rept 2 counter
  474. {
  475.         mov     ecx, [eax+EhciPortRouteReg+(counter-1)*4]
  476. @@:
  477.         mov     edx, ecx
  478.         shr     ecx, 4
  479.         and     edx, 15
  480.         mov     byte [edi+esi+ehci_controller.PortRoutes-(ehci_controller.MMIOBase1+4)], dl
  481.         inc     esi
  482.         cmp     esi, 8*counter
  483.         jnz     @b
  484. }
  485. .routes_filled:
  486. ;        DEBUGF 1,'K : EhciPortRouteReg: %x %x\n',[eax+EhciPortRouteReg],[eax+EhciPortRouteReg+4]
  487. ;        DEBUGF 1,'K : routes:\nK : '
  488. ;rept 8 counter
  489. ;{
  490. ;        DEBUGF 1,' %x',[edi+ehci_controller.PortRoutes-(ehci_controller.MMIOBase1+4)+counter-1]:2
  491. ;}
  492. ;        DEBUGF 1,'\nK : '
  493. ;rept 8 counter
  494. ;{
  495. ;        DEBUGF 1,' %x',[edi+ehci_controller.PortRoutes+8-(ehci_controller.MMIOBase1+4)+counter-1]:2
  496. ;}
  497. ;        DEBUGF 1,'\n'
  498.         movzx   ecx, byte [eax+EhciCapLengthReg]
  499.         mov     edx, [eax+EhciCapParamsReg]
  500.         add     eax, ecx
  501. if ehci_controller.MMIOBase2 <> ehci_controller.MMIOBase1 + 4
  502. .err assertion failed
  503. end if
  504.         stosd   ; fill ehci_controller.MMIOBase2
  505. if ehci_controller.StructuralParams <> ehci_controller.MMIOBase2 + 4
  506. .err assertion failed
  507. end if
  508. if ehci_controller.CapabilityParams <> ehci_controller.StructuralParams + 4
  509. .err assertion failed
  510. end if
  511.         mov     [edi], ebx      ; fill ehci_controller.StructuralParams
  512.         mov     [edi+4], edx    ; fill ehci_controller.CapabilityParams
  513.         DEBUGF 1,'K : HCSPARAMS=%x, HCCPARAMS=%x\n',ebx,edx
  514.         and     ebx, 15
  515.         mov     [edi+usb_controller.NumPorts+sizeof.ehci_controller-ehci_controller.StructuralParams], ebx
  516.         mov     edi, eax
  517. ; now edi = MMIOBase2
  518. ; 6. Transfer the controller to a known state.
  519. ; 6b. Stop the controller if it is running.
  520.         movi    ecx, 10
  521.         test    dword [edi+EhciStatusReg], 1 shl 12
  522.         jnz     .stopped
  523.         and     dword [edi+EhciCommandReg], not 1
  524. @@:
  525.         movi    esi, 1
  526.         invoke  Sleep
  527.         test    dword [edi+EhciStatusReg], 1 shl 12
  528.         jnz     .stopped
  529.         loop    @b
  530.         dbgstr 'Failed to stop EHCI controller'
  531.         jmp     .fail_unmap
  532. .stopped:
  533. ; 6c. Reset the controller. Wait up to 50 ms checking status every 1 ms.
  534.         or      dword [edi+EhciCommandReg], 2
  535.         movi    ecx, 50
  536. @@:
  537.         movi    esi, 1
  538.         invoke  Sleep
  539.         test    dword [edi+EhciCommandReg], 2
  540.         jz      .reset_ok
  541.         loop    @b
  542.         dbgstr 'Failed to reset EHCI controller'
  543.         jmp     .fail_unmap
  544. .reset_ok:
  545. ; 7. Configure the controller.
  546.         pop     esi     ; restore the pointer saved at step 1
  547.         add     esi, sizeof.ehci_controller
  548. ; 7a. If the controller is 64-bit, say to it that all structures are located
  549. ; in first 4G.
  550.         test    byte [esi+ehci_controller.CapabilityParams-sizeof.ehci_controller], 1
  551.         jz      @f
  552.         mov     dword [edi+EhciCtrlDataSegReg], 0
  553. @@:
  554. ; 7b. Hook interrupt and enable appropriate interrupt sources.
  555.         invoke  PciRead8, dword [.bus], dword [.devfn], 3Ch
  556. ; al = IRQ
  557. ;        DEBUGF 1,'K : attaching to IRQ %x\n',al
  558.         movzx   eax, al
  559.         invoke  AttachIntHandler, eax, ehci_irq, esi
  560. ;       mov     dword [edi+EhciStatusReg], 111111b      ; clear status
  561. ; disable Frame List Rollover interrupt, enable all other sources
  562.         mov     dword [edi+EhciInterruptReg], 110111b
  563. ; 7c. Inform the controller of the address of periodic lists head.
  564.         lea     eax, [esi-sizeof.ehci_controller]
  565.         invoke  GetPhysAddr
  566.         mov     dword [edi+EhciPeriodicListReg], eax
  567. ; 7d. Inform the controller of the address of asynchronous lists head.
  568.         lea     eax, [esi+ehci_controller.ControlED-sizeof.ehci_controller]
  569.         invoke  GetPhysAddr
  570.         mov     dword [edi+EhciAsyncListReg], eax
  571. ; 7e. Configure operational details and run the controller.
  572.         mov     dword [edi+EhciCommandReg], \
  573.                 (1 shl 16) + \ ; interrupt threshold = 1 microframe = 0.125ms
  574.                 (0 shl 11) + \ ; disable Async Park Mode
  575.                 (0 shl 8) +  \ ; zero Async Park Mode Count
  576.                 (1 shl 5) +  \ ; Async Schedule Enable
  577.                 (1 shl 4) +  \ ; Periodic Schedule Enable
  578.                 (0 shl 2) +  \ ; 1024 elements in FrameList
  579.                 1              ; Run
  580. ; 7f. Route all ports to this controller, not companion controllers.
  581.         mov     dword [edi+EhciConfigFlagReg], 1
  582.         DEBUGF 1,'K : EHCI controller at %x:%x with %d ports initialized\n',[.bus]:2,[.devfn]:2,[esi+usb_controller.NumPorts]
  583. ; 8. Apply port power, if needed, and disable all ports.
  584.         xor     ecx, ecx
  585. @@:
  586.         mov     dword [edi+EhciPortsReg+ecx*4], 1000h   ; Port Power enabled, all other bits disabled
  587.         inc     ecx
  588.         cmp     ecx, [esi+usb_controller.NumPorts]
  589.         jb      @b
  590.         test    byte [esi+ehci_controller.StructuralParams-sizeof.ehci_controller], 10h
  591.         jz      @f
  592.         push    esi
  593.         movi    esi, 20
  594.         invoke  Sleep
  595.         pop     esi
  596. @@:
  597. ; 9. Return pointer to usb_controller.
  598.         xchg    eax, esi
  599.         ret
  600. ; On error, pop the pointer saved at step 1 and return zero.
  601. ; Note that the main code branch restores the stack at step 7 and never fails
  602. ; after step 7.
  603. .fail_unmap:
  604.         pop     eax
  605.         push    eax
  606.         invoke  FreeKernelSpace, [eax+ehci_controller.MMIOBase1]
  607. .fail:
  608.         pop     ecx
  609.         xor     eax, eax
  610.         ret
  611. endp
  612.  
  613. ; Helper procedure for step 3 of ehci_init, see comments there.
  614. ; Initializes the static head of one list.
  615. ; esi = pointer to the "next" list, edi = pointer to head to initialize.
  616. ; Advances edi to the next head, keeps esi.
  617. proc ehci_init_static_endpoint
  618.         xor     eax, eax
  619.         inc     eax     ; set Terminate bit
  620.         mov     [edi+ehci_static_ep.NextTD], eax
  621.         mov     [edi+ehci_static_ep.AlternateNextTD], eax
  622.         test    esi, esi
  623.         jz      @f
  624.         mov     eax, esi
  625.         invoke  GetPhysAddr
  626.         inc     eax
  627.         inc     eax     ; set Type to EHCI_TYPE_QH
  628. @@:
  629.         mov     [edi+ehci_static_ep.NextQH], eax
  630.         mov     [edi+ehci_static_ep.NextList], esi
  631.         mov     byte [edi+ehci_static_ep.OverlayToken], 1 shl 6 ; halted
  632.         add     edi, ehci_static_ep.SoftwarePart
  633.         mov     eax, [USBHCFunc]
  634.         call    [eax+usbhc_func.usb_init_static_endpoint]
  635.         add     edi, sizeof.ehci_static_ep - ehci_static_ep.SoftwarePart
  636.         ret
  637. endp
  638.  
  639. ; Helper procedure for step 3 of ehci_init, see comments there.
  640. ; Initializes one half of group of static heads.
  641. ; edx = size of the next group = half of size of the group,
  642. ; edi = pointer to the group, esi = pointer to the next group.
  643. ; Advances esi, edi to next group, keeps edx.
  644. proc ehci_init_static_ep_group
  645.         push    edx
  646. @@:
  647.         call    ehci_init_static_endpoint
  648.         add     esi, sizeof.ehci_static_ep
  649.         dec     edx
  650.         jnz     @b
  651.         pop     edx
  652.         ret
  653. endp
  654.  
  655. ; Controller-specific pre-initialization function: take ownership from BIOS.
  656. ; Some BIOSes, although not all of them, use USB controllers themselves
  657. ; to support USB flash drives. In this case,
  658. ; we must notify the BIOS that we don't need that emulation and know how to
  659. ; deal with USB devices.
  660. proc ehci_kickoff_bios
  661. ; 1. Get the physical address of MMIO registers.
  662.         invoke  PciRead32, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], 10h
  663.         and     al, not 0Fh
  664. ; 2. Create mapping for physical memory. 200h bytes are always sufficient.
  665.         invoke  MapIoMem, eax, 200h, PG_SW+PG_NOCACHE
  666.         test    eax, eax
  667.         jz      .nothing
  668.         push    eax     ; push argument for step 8
  669. ; 3. Some BIOSes enable controller interrupts as a result of giving
  670. ; controller away. At this point the system knows nothing about how to serve
  671. ; EHCI interrupts, so such an interrupt will send the system into an infinite
  672. ; loop handling the same IRQ again and again. Thus, we need to block EHCI
  673. ; interrupts. We can't do this at the controller level until step 5,
  674. ; because the controller is currently owned by BIOS, so we block all hardware
  675. ; interrupts on this processor until step 5.
  676.         pushf
  677.         cli
  678. ; 4. Take the ownership over the controller.
  679. ; 4a. Locate take-ownership capability in the PCI configuration space.
  680. ; Limit the loop with 100h iterations; since the entire configuration space is
  681. ; 100h bytes long, hitting this number of iterations means that something is
  682. ; corrupted.
  683. ; Use a value from MMIO as a starting point.
  684.         mov     edx, [eax+EhciCapParamsReg]
  685.         movzx   edi, byte [eax+EhciCapLengthReg]
  686.         add     edi, eax
  687.         push    0
  688.         mov     bl, dh          ; get Extended Capabilities Pointer
  689.         test    bl, bl
  690.         jz      .has_ownership2
  691.         cmp     bl, 40h
  692.         jb      .no_capability
  693. .look_bios_handoff:
  694.         test    bl, 3
  695.         jnz     .no_capability
  696. ; In each iteration, read the current dword,
  697.         invoke  PciRead32, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx
  698. ; check, whether the capability ID is take-ownership ID = 1,
  699.         cmp     al, 1
  700.         jz      .found_bios_handoff
  701. ; if not, advance to next-capability link and continue loop.
  702.         dec     byte [esp]
  703.         jz      .no_capability
  704.         mov     bl, ah
  705.         cmp     bl, 40h
  706.         jae     .look_bios_handoff
  707. .no_capability:
  708.         dbgstr 'warning: cannot locate take-ownership capability'
  709.         jmp     .has_ownership2
  710. .found_bios_handoff:
  711. ; 4b. Check whether BIOS has ownership.
  712. ; Some BIOSes release ownership before loading OS, but forget to unwatch for
  713. ; change-ownership requests; they cannot handle ownership request, so
  714. ; such a request sends the system into infinite loop of handling the same SMI
  715. ; over and over. Avoid this.
  716.         inc     ebx
  717.         inc     ebx
  718.         test    eax, 0x10000
  719.         jz      .has_ownership
  720. ; 4c. Request ownership.
  721.         inc     ebx
  722.         invoke  PciWrite8, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx, 1
  723. ; 4d. Some BIOSes set ownership flag, but forget to watch for change-ownership
  724. ; requests; if so, there is no sense in waiting.
  725.         inc     ebx
  726.         invoke  PciRead32, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx
  727.         dec     ebx
  728.         dec     ebx
  729.         test    ah, 20h
  730.         jz      .force_ownership
  731. ; 4e. Wait for result no more than 1 s, checking for status every 1 ms.
  732. ; If successful, go to 5.
  733.         mov     dword [esp], 1000
  734. @@:
  735.         invoke  PciRead8, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx
  736.         test    al, 1
  737.         jz      .has_ownership
  738.         push    esi
  739.         movi    esi, 1
  740.         invoke  Sleep
  741.         pop     esi
  742.         dec     dword [esp]
  743.         jnz     @b
  744.         dbgstr  'warning: taking EHCI ownership from BIOS timeout'
  745. .force_ownership:
  746. ; 4f. BIOS has not responded within the timeout.
  747. ; Let's just clear BIOS ownership flag and hope that everything will be ok.
  748.         invoke  PciWrite8, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx, 0
  749. .has_ownership:
  750. ; 5. Just in case clear all SMI event sources except change-ownership.
  751.         dbgstr 'has_ownership'
  752.         inc     ebx
  753.         inc     ebx
  754.         invoke  PciRead16, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx
  755.         and     ax, 2000h
  756.         invoke  PciWrite16, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx, eax
  757. .has_ownership2:
  758.         pop     ecx
  759. ; 6. Disable all controller interrupts until the system will be ready to
  760. ; process them.
  761.         mov     dword [edi+EhciInterruptReg], 0
  762. ; 7. Now we can unblock interrupts in the processor.
  763.         popf
  764. ; 8. Release memory mapping created in step 2 and return.
  765.         invoke  FreeKernelSpace
  766. .nothing:
  767.         ret
  768. endp
  769.  
  770. ; IRQ handler for EHCI controllers.
  771. ehci_irq.noint:
  772.         spin_unlock_irqrestore [esi+usb_controller.WaitSpinlock]
  773. ; Not our interrupt: restore registers and return zero.
  774.         xor     eax, eax
  775.         pop     edi esi ebx
  776.         ret
  777.  
  778. proc ehci_irq
  779.         push    ebx esi edi     ; save registers to be cdecl
  780. virtual at esp
  781.         rd      3       ; saved registers
  782.         dd      ?       ; return address
  783. .controller     dd      ?
  784. end virtual
  785. ; 1. ebx will hold whether some deferred processing is needed,
  786. ; that cannot be done from the interrupt handler. Initialize to zero.
  787.         xor     ebx, ebx
  788. ; 2. Get the mask of events which should be processed.
  789.         mov     esi, [.controller]
  790.         mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
  791.         spin_lock_irqsave [esi+usb_controller.WaitSpinlock]
  792.         mov     eax, [edi+EhciStatusReg]
  793. ; 3. Check whether that interrupt has been generated by our controller.
  794. ; (One IRQ can be shared by several devices.)
  795.         and     eax, [edi+EhciInterruptReg]
  796.         jz      .noint
  797. ; 4. Clear the events we know of.
  798. ; Note that this should be done before processing of events:
  799. ; new events could arise while we are processing those, this way we won't lose
  800. ; them (the controller would generate another interrupt after completion
  801. ; of this one).
  802. ;       DEBUGF 1,'K : EHCI interrupt: status = %x\n',eax
  803.         mov     [edi+EhciStatusReg], eax
  804. ; 5. Sanity check.
  805.         test    al, 10h
  806.         jz      @f
  807.         DEBUGF 1,'K : something terrible happened with EHCI %x (%x)\n',esi,al
  808. @@:
  809. ; We can't do too much from an interrupt handler. Inform the processing thread
  810. ; that it should perform appropriate actions.
  811.         or      [esi+ehci_controller.DeferredActions-sizeof.ehci_controller], eax
  812.         spin_unlock_irqrestore [esi+usb_controller.WaitSpinlock]
  813.         inc     ebx
  814.         invoke  usbhc_api.usb_wakeup_if_needed
  815. ; 6. Interrupt processed; return non-zero.
  816.         mov     al, 1
  817.         pop     edi esi ebx     ; restore used registers to be cdecl
  818.         ret
  819. endp
  820.  
  821. ; This procedure is called from usb_set_address_callback
  822. ; and stores USB device address in the ehci_pipe structure.
  823. ; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
  824. proc ehci_set_device_address
  825.         mov     byte [ebx+ehci_pipe.Token-sizeof.ehci_pipe], cl
  826.         jmp     [usbhc_api.usb_subscribe_control]
  827. endp
  828.  
  829. ; This procedure returns USB device address from the ehci_pipe structure.
  830. ; in: esi -> usb_controller, ebx -> usb_pipe
  831. ; out: eax = endpoint address
  832. proc ehci_get_device_address
  833.         mov     eax, [ebx+ehci_pipe.Token-sizeof.ehci_pipe]
  834.         and     eax, 7Fh
  835.         ret
  836. endp
  837.  
  838. ; This procedure is called from usb_set_address_callback
  839. ; if the device does not accept SET_ADDRESS command and needs
  840. ; to be disabled at the port level.
  841. ; in: esi -> usb_controller, ecx = port (zero-based)
  842. proc ehci_port_disable
  843.         mov     eax, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
  844.         and     dword [eax+EhciPortsReg+ecx*4], not (4 or 2Ah)
  845.         ret
  846. endp
  847.  
  848. ; This procedure is called from usb_get_descr8_callback when
  849. ; the packet size for zero endpoint becomes known and
  850. ; stores the packet size in ehci_pipe structure.
  851. ; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size
  852. proc ehci_set_endpoint_packet_size
  853.         mov     eax, [ebx+ehci_pipe.Token-sizeof.ehci_pipe]
  854.         and     eax, not (0x7FF shl 16)
  855.         shl     ecx, 16
  856.         or      eax, ecx
  857.         mov     [ebx+ehci_pipe.Token-sizeof.ehci_pipe], eax
  858. ; Wait until hardware cache is evicted.
  859.         jmp     [usbhc_api.usb_subscribe_control]
  860. endp
  861.  
  862. uglobal
  863. align 4
  864. ; Data for memory allocator, see memory.inc.
  865. ehci_ep_first_page      dd      ?
  866. ehci_ep_mutex           MUTEX
  867. ehci_gtd_first_page     dd      ?
  868. ehci_gtd_mutex          MUTEX
  869. endg
  870.  
  871. ; This procedure allocates memory for pipe.
  872. ; Both hardware+software parts must be allocated, returns pointer to usb_pipe
  873. ; (software part).
  874. proc ehci_alloc_pipe
  875.         push    ebx
  876.         mov     ebx, ehci_ep_mutex
  877.         invoke  usbhc_api.usb_allocate_common, (sizeof.ehci_pipe + sizeof.usb_pipe + 1Fh) and not 1Fh
  878.         test    eax, eax
  879.         jz      @f
  880.         add     eax, sizeof.ehci_pipe
  881. @@:
  882.         pop     ebx
  883.         ret
  884. endp
  885.  
  886. ; This procedure frees memory for pipe allocated by ehci_alloc_pipe.
  887. ; void stdcall with one argument = pointer to usb_pipe.
  888. proc ehci_free_pipe
  889. virtual at esp
  890.         dd      ?       ; return address
  891. .ptr    dd      ?
  892. end virtual
  893.         sub     [.ptr], sizeof.ehci_pipe
  894.         jmp     [usbhc_api.usb_free_common]
  895. endp
  896.  
  897. ; This procedure is called from API usb_open_pipe and processes
  898. ; the controller-specific part of this API. See docs.
  899. ; in: edi -> usb_pipe for target, ecx -> usb_pipe for config pipe,
  900. ; esi -> usb_controller, eax -> usb_gtd for the first TD,
  901. ; [ebp+12] = endpoint, [ebp+16] = maxpacket, [ebp+20] = type
  902. proc ehci_init_pipe
  903. virtual at ebp+8
  904. .config_pipe    dd      ?
  905. .endpoint       dd      ?
  906. .maxpacket      dd      ?
  907. .type           dd      ?
  908. .interval       dd      ?
  909. end virtual
  910. ; 1. Zero all fields in the hardware part.
  911.         push    eax ecx
  912.         sub     edi, sizeof.ehci_pipe
  913.         xor     eax, eax
  914.         movi    ecx, sizeof.ehci_pipe/4
  915.         rep stosd
  916.         pop     ecx eax
  917. ; 2. Setup PID in the first TD and make sure that the it is not active.
  918.         xor     edx, edx
  919.         test    byte [.endpoint], 80h
  920.         setnz   dh
  921.         mov     [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx
  922.         mov     [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1
  923.         mov     [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1
  924. ; 3. Store physical address of the first TD.
  925.         sub     eax, sizeof.ehci_gtd
  926.         call    [GetPhysAddr]
  927.         mov     [edi+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax
  928. ; 4. Fill ehci_pipe.Flags except for S- and C-masks.
  929. ; Copy location from the config pipe.
  930.         mov     eax, [ecx+ehci_pipe.Flags-sizeof.ehci_pipe]
  931.         and     eax, 3FFF0000h
  932. ; Use 1 requests per microframe for control/bulk endpoints,
  933. ; use value from the endpoint descriptor for periodic endpoints
  934.         movi    edx, 1
  935.         test    [.type], 1
  936.         jz      @f
  937.         mov     edx, [.maxpacket]
  938.         shr     edx, 11
  939.         inc     edx
  940. @@:
  941.         shl     edx, 30
  942.         or      eax, edx
  943.         mov     [edi+ehci_pipe.Flags-sizeof.ehci_pipe], eax
  944. ; 5. Fill ehci_pipe.Token.
  945.         mov     eax, [ecx+ehci_pipe.Token-sizeof.ehci_pipe]
  946. ; copy following fields from the config pipe:
  947. ; DeviceAddress, EndpointSpeed, ControlEndpoint if new type is control
  948.         mov     ecx, eax
  949.         and     eax, 307Fh
  950.         and     ecx, 8000000h
  951.         or      ecx, 4000h
  952.         mov     edx, [.endpoint]
  953.         and     edx, 15
  954.         shl     edx, 8
  955.         or      eax, edx
  956.         mov     edx, [.maxpacket]
  957.         shl     edx, 16
  958.         or      eax, edx
  959. ; for control endpoints, use DataToggle from TD, otherwise use DataToggle from QH
  960.         cmp     [.type], CONTROL_PIPE
  961.         jnz     @f
  962.         or      eax, ecx
  963. @@:
  964. ; for control/bulk USB2 endpoints, set NakCountReload to 4
  965.         test    eax, USB_SPEED_HS shl 12
  966.         jz      .nonak
  967.         cmp     [.type], CONTROL_PIPE
  968.         jz      @f
  969.         cmp     [.type], BULK_PIPE
  970.         jnz     .nonak
  971. @@:
  972.         or      eax, 40000000h
  973. .nonak:
  974.         mov     [edi+ehci_pipe.Token-sizeof.ehci_pipe], eax
  975. ; 5. Select the corresponding list and insert to the list.
  976. ; 5a. Use Control list for control pipes, Bulk list for bulk pipes.
  977.         lea     edx, [esi+ehci_controller.ControlED.SoftwarePart-sizeof.ehci_controller]
  978.         cmp     [.type], BULK_PIPE
  979.         jb      .insert ; control pipe
  980.         lea     edx, [esi+ehci_controller.BulkED.SoftwarePart-sizeof.ehci_controller]
  981.         jz      .insert ; bulk pipe
  982. .interrupt_pipe:
  983. ; 5b. For interrupt pipes, let the scheduler select the appropriate list
  984. ; and the appropriate microframe(s) (which goes to S-mask and C-mask)
  985. ; based on the current bandwidth distribution and the requested bandwidth.
  986. ; There are two schedulers, one for high-speed devices,
  987. ; another for split transactions.
  988. ; This could fail if the requested bandwidth is not available;
  989. ; if so, return an error.
  990.         test    word [edi+ehci_pipe.Flags-sizeof.ehci_pipe+2], 3FFFh
  991.         jnz     .interrupt_tt
  992.         call    ehci_select_hs_interrupt_list
  993.         jmp     .interrupt_common
  994. .interrupt_tt:
  995.         call    ehci_select_tt_interrupt_list
  996. .interrupt_common:
  997.         test    edx, edx
  998.         jz      .return0
  999.         mov     word [edi+ehci_pipe.Flags-sizeof.ehci_pipe], ax
  1000. .insert:
  1001.         mov     [edi+usb_pipe.BaseList], edx
  1002. ; Insert to the head of the corresponding list.
  1003. ; Note: inserting to the head guarantees that the list traverse in
  1004. ; ehci_process_updated_schedule, once started, will not interact with new pipes.
  1005. ; However, we still need to ensure that links in the new pipe (edi.NextVirt)
  1006. ; are initialized before links to the new pipe (edx.NextVirt).
  1007. ; 5c. Insert in the list of virtual addresses.
  1008.         mov     ecx, [edx+usb_pipe.NextVirt]
  1009.         mov     [edi+usb_pipe.NextVirt], ecx
  1010.         mov     [edi+usb_pipe.PrevVirt], edx
  1011.         mov     [ecx+usb_pipe.PrevVirt], edi
  1012.         mov     [edx+usb_pipe.NextVirt], edi
  1013. ; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
  1014. ; store the physical address of the new pipe to previous NextQH.
  1015.         mov     ecx, [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart]
  1016.         mov     [edi+ehci_pipe.NextQH-sizeof.ehci_pipe], ecx
  1017.         lea     eax, [edi-sizeof.ehci_pipe]
  1018.         call    [GetPhysAddr]
  1019.         inc     eax
  1020.         inc     eax
  1021.         mov     [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], eax
  1022. ; 6. Return with nonzero eax.
  1023.         ret
  1024. .return0:
  1025.         xor     eax, eax
  1026.         ret
  1027. endp
  1028.  
  1029. ; This function is called from ehci_process_deferred when
  1030. ; a new device was connected at least USB_CONNECT_DELAY ticks
  1031. ; and therefore is ready to be configured.
  1032. ; ecx = port, esi -> ehci_controller, edi -> EHCI MMIO
  1033. proc ehci_new_port
  1034. ; 1. If the device operates at low-speed, just release it to a companion.
  1035.         mov     eax, [edi+EhciPortsReg+ecx*4]
  1036.         DEBUGF 1,'K : EHCI %x port %d state is %x\n',esi,ecx,eax
  1037.         mov     edx, eax
  1038.         and     ah, 0Ch
  1039.         cmp     ah, 4
  1040.         jz      .low_speed
  1041. ; 2. Devices operating at full-speed and high-speed must now have ah == 8.
  1042. ; Some broken hardware asserts both D+ and D- even after initial decoupling;
  1043. ; if so, stop initialization here, no sense in further actions.
  1044.         cmp     ah, 0Ch
  1045.         jz      .se1
  1046. ; 3. If another port is resetting right now, mark this port as 'reset pending'
  1047. ; and return.
  1048.         bts     [esi+usb_controller.PendingPorts], ecx
  1049.         cmp     [esi+usb_controller.ResettingPort], -1
  1050.         jnz     .nothing
  1051.         btr     [esi+usb_controller.PendingPorts], ecx
  1052. ; Otherwise, fall through to ohci_new_port.reset.
  1053.  
  1054. ; This function is called from ehci_new_port and usb_test_pending_port.
  1055. ; It starts reset signalling for the port. Note that in USB first stages
  1056. ; of configuration can not be done for several ports in parallel.
  1057. .reset:
  1058.         push    edi
  1059.         mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
  1060.         mov     eax, [edi+EhciPortsReg+ecx*4]
  1061. ; 1. Store information about resetting hub (roothub) and port.
  1062.         and     [esi+usb_controller.ResettingHub], 0
  1063.         mov     [esi+usb_controller.ResettingPort], cl
  1064. ; 2. Initiate reset signalling.
  1065.         or      ah, 1
  1066.         and     al, not (4 or 2Ah)
  1067.         mov     [edi+EhciPortsReg+ecx*4], eax
  1068. ; 3. Store the current time and set status to 1 = reset signalling active.
  1069.         invoke  GetTimerTicks
  1070.         mov     [esi+usb_controller.ResetTime], eax
  1071.         mov     [esi+usb_controller.ResettingStatus], 1
  1072. ;       dbgstr 'high-speed or full-speed device, resetting'
  1073.         DEBUGF 1,'K : EHCI %x: port %d has HS or FS device, resetting\n',esi,ecx
  1074.         pop     edi
  1075. .nothing:
  1076.         ret
  1077. .low_speed:
  1078. ;       dbgstr 'low-speed device, releasing'
  1079.         DEBUGF 1,'K : EHCI %x: port %d has LS device, releasing\n',esi,ecx
  1080.         or      dh, 20h
  1081.         and     dl, not 2Ah
  1082.         mov     [edi+EhciPortsReg+ecx*4], edx
  1083.         ret
  1084. .se1:
  1085.         dbgstr 'SE1 after connect debounce. Broken hardware?'
  1086.         ret
  1087. endp
  1088.  
  1089. ; This procedure is called from several places in main USB code
  1090. ; and allocates required packets for the given transfer.
  1091. ; ebx = pipe, other parameters are passed through the stack:
  1092. ; buffer,size = data to transfer
  1093. ; flags = same as in usb_open_pipe: bit 0 = allow short transfer, other bits reserved
  1094. ; td = pointer to the current end-of-queue descriptor
  1095. ; direction =
  1096. ;   0000b for normal transfers,
  1097. ;   1000b for control SETUP transfer,
  1098. ;   1101b for control OUT transfer,
  1099. ;   1110b for control IN transfer
  1100. ; returns eax = pointer to the new end-of-queue descriptor
  1101. ; (not included in the queue itself) or 0 on error
  1102. proc ehci_alloc_transfer stdcall uses edi, \
  1103.         buffer:dword, size:dword, flags:dword, td:dword, direction:dword
  1104. locals
  1105. origTD          dd      ?
  1106. packetSize      dd      ?       ; must be last variable, see usb_init_transfer
  1107. endl
  1108. ; 1. Save original value of td:
  1109. ; it will be useful for rollback if something would fail.
  1110.         mov     eax, [td]
  1111.         mov     [origTD], eax
  1112. ; One transfer descriptor can describe up to 5 pages.
  1113. ; In the worst case (when the buffer is something*1000h+0FFFh)
  1114. ; this corresponds to 4001h bytes. If the requested size is
  1115. ; greater, we should split the transfer into several descriptors.
  1116. ; Boundaries to split must be multiples of endpoint transfer size
  1117. ; to avoid short packets except in the end of the transfer.
  1118.         cmp     [size], 4001h
  1119.         jbe     .lastpacket
  1120. ; 2. While the remaining data cannot fit in one descriptor,
  1121. ; allocate full descriptors (of maximal possible size).
  1122. ; 2a. Calculate size of one descriptor: must be a multiple of transfer size
  1123. ; and must be not greater than 4001h.
  1124.         movzx   ecx, word [ebx+ehci_pipe.Token+2-sizeof.ehci_pipe]
  1125.         and     ecx, (1 shl 11) - 1
  1126.         mov     eax, 4001h
  1127.         xor     edx, edx
  1128.         mov     edi, eax
  1129.         div     ecx
  1130.         sub     edi, edx
  1131.         mov     [packetSize], edi
  1132. .fullpackets:
  1133.         call    ehci_alloc_packet
  1134.         test    eax, eax
  1135.         jz      .fail
  1136.         mov     [td], eax
  1137.         add     [buffer], edi
  1138.         sub     [size], edi
  1139.         cmp     [size], 4001h
  1140.         ja      .fullpackets
  1141. ; 3. The remaining data can fit in one packet;
  1142. ; allocate the last descriptor with size = size of remaining data.
  1143. .lastpacket:
  1144.         mov     eax, [size]
  1145.         mov     [packetSize], eax
  1146.         call    ehci_alloc_packet
  1147.         test    eax, eax
  1148.         jz      .fail
  1149. ; 9. Update flags in the last packet.
  1150.         mov     edx, [flags]
  1151.         mov     [ecx+ehci_gtd.Flags-sizeof.ehci_gtd], edx
  1152. ; 10. Fill AlternateNextTD field in all allocated TDs.
  1153. ; If the caller says that short transfer is ok, the queue must advance to
  1154. ; the next descriptor, which is in eax.
  1155. ; Otherwise, the queue should stop, so make AlternateNextTD point to
  1156. ; always-inactive descriptor StopQueueTD.
  1157.         push    eax
  1158.         test    dl, 1
  1159.         jz      .disable_short
  1160.         sub     eax, sizeof.ehci_gtd
  1161.         jmp     @f
  1162. .disable_short:
  1163.         mov     eax, [ebx+usb_pipe.Controller]
  1164.         add     eax, ehci_controller.StopQueueTD - sizeof.ehci_controller
  1165. @@:
  1166.         call    [GetPhysAddr]
  1167.         mov     edx, [origTD]
  1168. @@:
  1169.         cmp     edx, [esp]
  1170.         jz      @f
  1171.         mov     [edx+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], eax
  1172.         mov     edx, [edx+usb_gtd.NextVirt]
  1173.         jmp     @b
  1174. @@:
  1175.         pop     eax
  1176.         ret
  1177. .fail:
  1178.         mov     edi, ehci_hardware_func
  1179.         mov     eax, [td]
  1180.         invoke  usbhc_api.usb_undo_tds, [origTD]
  1181.         xor     eax, eax
  1182.         ret
  1183. endp
  1184.  
  1185. ; Helper procedure for ehci_alloc_transfer.
  1186. ; Allocates and initializes one transfer descriptor.
  1187. ; ebx = pipe, other parameters are passed through the stack;
  1188. ; fills the current last descriptor and
  1189. ; returns eax = next descriptor (not filled).
  1190. proc ehci_alloc_packet
  1191. ; inherit some variables from the parent ehci_alloc_transfer
  1192. virtual at ebp-8
  1193. .origTD         dd      ?
  1194. .packetSize     dd      ?
  1195.                 rd      2
  1196. .buffer         dd      ?
  1197. .transferSize   dd      ?
  1198. .Flags          dd      ?
  1199. .td             dd      ?
  1200. .direction      dd      ?
  1201. end virtual
  1202. ; 1. Allocate the next TD.
  1203.         call    ehci_alloc_td
  1204.         test    eax, eax
  1205.         jz      .nothing
  1206. ; 2. Initialize controller-independent parts of both TDs.
  1207.         push    eax
  1208.         invoke  usbhc_api.usb_init_transfer
  1209.         pop     eax
  1210. ; 3. Copy PID to the new descriptor.
  1211.         mov     edx, [ecx+ehci_gtd.Token-sizeof.ehci_gtd]
  1212.         mov     [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx
  1213.         mov     [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1
  1214.         mov     [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1
  1215. ; 4. Save the returned value (next descriptor).
  1216.         push    eax
  1217. ; 5. Store the physical address of the next descriptor.
  1218.         sub     eax, sizeof.ehci_gtd
  1219.         call    [GetPhysAddr]
  1220.         mov     [ecx+ehci_gtd.NextTD-sizeof.ehci_gtd], eax
  1221. ; 6. For zero-length transfers, store zero in all fields for buffer addresses.
  1222. ; Otherwise, fill them with real values.
  1223.         xor     eax, eax
  1224.         mov     [ecx+ehci_gtd.Flags-sizeof.ehci_gtd], eax
  1225. repeat 10
  1226.         mov     [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd+(%-1)*4], eax
  1227. end repeat
  1228.         cmp     [.packetSize], eax
  1229.         jz      @f
  1230.         mov     eax, [.buffer]
  1231.         call    [GetPhysAddr]
  1232.         mov     [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd], eax
  1233.         and     eax, 0xFFF
  1234.         mov     edx, [.packetSize]
  1235.         add     edx, eax
  1236.         sub     edx, 0x1000
  1237.         jbe     @f
  1238.         mov     eax, [.buffer]
  1239.         add     eax, 0x1000
  1240.         call    [GetPgAddr]
  1241.         mov     [ecx+ehci_gtd.BufferPointers+4-sizeof.ehci_gtd], eax
  1242.         sub     edx, 0x1000
  1243.         jbe     @f
  1244.         mov     eax, [.buffer]
  1245.         add     eax, 0x2000
  1246.         call    [GetPgAddr]
  1247.         mov     [ecx+ehci_gtd.BufferPointers+8-sizeof.ehci_gtd], eax
  1248.         sub     edx, 0x1000
  1249.         jbe     @f
  1250.         mov     eax, [.buffer]
  1251.         add     eax, 0x3000
  1252.         call    [GetPgAddr]
  1253.         mov     [ecx+ehci_gtd.BufferPointers+12-sizeof.ehci_gtd], eax
  1254.         sub     edx, 0x1000
  1255.         jbe     @f
  1256.         mov     eax, [.buffer]
  1257.         add     eax, 0x4000
  1258.         call    [GetPgAddr]
  1259.         mov     [ecx+ehci_gtd.BufferPointers+16-sizeof.ehci_gtd], eax
  1260. @@:
  1261. ; 7. Fill Token field:
  1262. ; set Status = 0 (inactive, ehci_insert_transfer would mark everything active);
  1263. ; keep current PID if [.direction] is zero, use two lower bits of [.direction]
  1264. ; otherwise shifted as (0|1|2) -> (2|0|1);
  1265. ; set error counter to 3;
  1266. ; set current page to 0;
  1267. ; do not interrupt on complete (ehci_insert_transfer sets this bit where needed);
  1268. ; set DataToggle to bit 2 of [.direction].
  1269.         mov     eax, [ecx+ehci_gtd.Token-sizeof.ehci_gtd]
  1270.         and     eax, 300h       ; keep PID code
  1271.         mov     edx, [.direction]
  1272.         test    edx, edx
  1273.         jz      .haspid
  1274.         and     edx, 3
  1275.         dec     edx
  1276.         jns     @f
  1277.         add     edx, 3
  1278. @@:
  1279.         mov     ah, dl
  1280.         mov     edx, [.direction]
  1281.         and     edx, not 3
  1282.         shl     edx, 29
  1283.         or      eax, edx
  1284. .haspid:
  1285.         or      eax, 0C00h
  1286.         mov     edx, [.packetSize]
  1287.         shl     edx, 16
  1288.         or      eax, edx
  1289.         mov     [ecx+ehci_gtd.Token-sizeof.ehci_gtd], eax
  1290. ; 4. Restore the returned value saved in step 2.
  1291.         pop     eax
  1292. .nothing:
  1293.         ret
  1294. endp
  1295.  
  1296. ; This procedure is called from several places in main USB code
  1297. ; and activates the transfer which was previously allocated by
  1298. ; ehci_alloc_transfer.
  1299. ; ecx -> last descriptor for the transfer, ebx -> usb_pipe
  1300. proc ehci_insert_transfer
  1301.         or      byte [ecx+ehci_gtd.Token+1-sizeof.ehci_gtd], 80h  ; set IOC bit
  1302.         mov     eax, [esp+4]
  1303. .activate:
  1304.         or      byte [eax+ehci_gtd.Token-sizeof.ehci_gtd], 80h    ; set Active bit
  1305.         cmp     eax, ecx
  1306.         mov     eax, [eax+usb_gtd.NextVirt]
  1307.         jnz     .activate
  1308.         ret
  1309. endp
  1310.  
  1311. ; This function is called from ehci_process_deferred when
  1312. ; reset signalling for a new device needs to be finished.
  1313. proc ehci_port_reset_done
  1314.         movzx   ecx, [esi+usb_controller.ResettingPort]
  1315.         and     dword [edi+EhciPortsReg+ecx*4], not 12Ah
  1316.         invoke  GetTimerTicks
  1317.         mov     [esi+usb_controller.ResetTime], eax
  1318.         mov     [esi+usb_controller.ResettingStatus], 2
  1319. ;        DEBUGF 1,'K : EHCI %x: reset port %d done\n',esi,ecx
  1320.         ret
  1321. endp
  1322.  
  1323. ; This function is called from ehci_process_deferred when
  1324. ; a new device has been reset, recovered after reset and needs to be configured.
  1325. proc ehci_port_init
  1326. ; 1. Get the status and set it to zero.
  1327. ; If reset has been failed (device disconnected during reset),
  1328. ; continue to next device (if there is one).
  1329.         xor     eax, eax
  1330.         xchg    al, [esi+usb_controller.ResettingStatus]
  1331.         test    al, al
  1332.         jns     @f
  1333.         jmp     [usbhc_api.usb_test_pending_port]
  1334. @@:
  1335. ; 2. Get the port status. High-speed devices should be now enabled,
  1336. ; full-speed devices are left disabled;
  1337. ; if the port is disabled, release it to a companion and continue to
  1338. ; next device (if there is one).
  1339.         movzx   ecx, [esi+usb_controller.ResettingPort]
  1340.         mov     eax, [edi+EhciPortsReg+ecx*4]
  1341.         DEBUGF 1,'K : EHCI %x status of port %d is %x\n',esi,ecx,eax
  1342.         test    al, 4
  1343.         jnz     @f
  1344. ;       DEBUGF 1,'K : USB port disabled after reset, status = %x\n',eax
  1345.         dbgstr 'releasing to companion'
  1346.         or      ah, 20h
  1347.         mov     [edi+EhciPortsReg+ecx*4], eax
  1348.         jmp     [usbhc_api.usb_test_pending_port]
  1349. @@:
  1350. ; 3. Call the worker procedure to notify the protocol layer
  1351. ; about new EHCI device. It is high-speed.
  1352.         movi    eax, USB_SPEED_HS
  1353.         call    ehci_new_device
  1354.         test    eax, eax
  1355.         jnz     .nothing
  1356. ; 4. If something at the protocol layer has failed
  1357. ; (no memory, no bus address), disable the port and stop the initialization.
  1358. .disable_exit:
  1359.         and     dword [edi+EhciPortsReg+ecx*4], not (4 or 2Ah)
  1360.         jmp     [usbhc_api.usb_test_pending_port]
  1361. .nothing:
  1362.         ret
  1363. endp
  1364.  
  1365. ; This procedure is called from ehci_port_init and from hub support code
  1366. ; when a new device is connected and has been reset.
  1367. ; It calls usb_new_device at the protocol layer with correct parameters.
  1368. ; in: esi -> usb_controller, eax = speed.
  1369. proc ehci_new_device
  1370.         push    ebx ecx ; save used registers (ecx is important for ehci_port_init)
  1371. ; 1. Store the speed for the protocol layer.
  1372.         mov     [esi+usb_controller.ResettingSpeed], al
  1373. ; 2. Shift speed bits to the proper place in ehci_pipe.Token.
  1374.         shl     eax, 12
  1375. ; 3. For high-speed devices, go to step 5 with edx = 0.
  1376.         xor     edx, edx
  1377.         cmp     ah, USB_SPEED_HS shl (12-8)
  1378.         jz      .common
  1379. ; 4. For low-speed and full-speed devices, fill address:port
  1380. ; of the last high-speed hub (the closest to the device hub)
  1381. ; for split transactions, and set ControlEndpoint bit in eax;
  1382. ; ehci_init_pipe assumes that the parent pipe is a control pipe.
  1383.         push    eax
  1384.         movzx   ecx, [esi+usb_controller.ResettingPort]
  1385.         mov     edx, [esi+usb_controller.ResettingHub]
  1386.         invoke  usbhc_api.usb_get_tt
  1387.         inc     ecx
  1388.         mov     edx, [edx+ehci_pipe.Token-sizeof.ehci_pipe]
  1389.         shl     ecx, 23
  1390.         and     edx, 7Fh
  1391.         shl     edx, 16
  1392.         or      edx, ecx        ; ehci_pipe.Flags
  1393.         pop     eax
  1394.         or      eax, 1 shl 27   ; ehci_pipe.Token
  1395. .common:
  1396. ; 5. Create pseudo-pipe in the stack.
  1397. ; See ehci_init_pipe: only .Controller, .Token, .Flags fields are used.
  1398.         push    esi     ; usb_pipe.Controller
  1399.         mov     ecx, esp
  1400.         sub     esp, sizeof.ehci_pipe - ehci_pipe.Flags - 4
  1401.         push    edx     ; ehci_pipe.Flags
  1402.         push    eax     ; ehci_pipe.Token
  1403. ; 6. Notify the protocol layer.
  1404.         invoke  usbhc_api.usb_new_device
  1405. ; 7. Cleanup the stack after step 5 and return.
  1406.         add     esp, sizeof.ehci_pipe - ehci_pipe.Flags + 8
  1407.         pop     ecx ebx ; restore used registers
  1408.         ret
  1409. endp
  1410.  
  1411. ; This procedure is called in the USB thread from usb_thread_proc,
  1412. ; processes regular actions and those actions which can't be safely done
  1413. ; from interrupt handler.
  1414. ; Returns maximal time delta before the next call.
  1415. proc ehci_process_deferred
  1416.         push    ebx edi         ; save used registers to be stdcall
  1417.         mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
  1418. ; 1. Get the mask of events to process.
  1419.         xor     eax, eax
  1420.         xchg    eax, [esi+ehci_controller.DeferredActions-sizeof.ehci_controller]
  1421.         push    eax
  1422. ; 2. Initialize the return value.
  1423.         push    -1
  1424. ; Handle roothub events.
  1425. ; 3a. Test whether there are such events.
  1426.         test    al, 4
  1427.         jz      .skip_roothub
  1428. ; Status of some port has changed. Loop over all ports.
  1429. ; 3b. Prepare for the loop: start from port 0.
  1430.         xor     ecx, ecx
  1431. .portloop:
  1432. ; 3c. Get the port status and changes of it.
  1433. ; If there are no changes, just continue to the next port.
  1434.         mov     eax, [edi+EhciPortsReg+ecx*4]
  1435.         test    al, 2Ah
  1436.         jz      .nextport
  1437. ; 3d. Clear change bits and read the status again.
  1438. ; (It is possible, although quite unlikely, that some event occurs between
  1439. ; the first read and the clearing, invalidating the old status. If an event
  1440. ; occurs after the clearing, we will not miss it, looking in the next scan.
  1441.         mov     [edi+EhciPortsReg+ecx*4], eax
  1442.         mov     ebx, eax
  1443.         mov     eax, [edi+EhciPortsReg+ecx*4]
  1444.         DEBUGF 1,'K : EHCI %x: status of port %d changed to %x\n',esi,ecx,ebx
  1445. ; 3e. Handle overcurrent.
  1446. ; Note: that needs work.
  1447.         test    bl, 20h ; overcurrent change
  1448.         jz      .noovercurrent
  1449.         test    al, 10h ; overcurrent active
  1450.         jz      .noovercurrent
  1451.         DEBUGF 1,'K : overcurrent at port %d\n',ecx
  1452. .noovercurrent:
  1453. ; 3f. Handle changing of connection status.
  1454.         test    bl, 2
  1455.         jz      .nocsc
  1456. ; There was a connect or disconnect event at this port.
  1457. ; 3g. Disconnect the old device on this port, if any.
  1458. ; If the port was resetting, indicate fail; later stages will process it.
  1459. ; Ignore connect event immediately after resetting.
  1460.         cmp     [esi+usb_controller.ResettingHub], 0
  1461.         jnz     .csc.noreset
  1462.         cmp     cl, [esi+usb_controller.ResettingPort]
  1463.         jnz     .csc.noreset
  1464.         cmp     [esi+usb_controller.ResettingStatus], 2
  1465.         jnz     @f
  1466.         test    al, 1
  1467.         jnz     .nextport
  1468. @@:
  1469.         mov     [esi+usb_controller.ResettingStatus], -1
  1470. .csc.noreset:
  1471.         bts     [esi+usb_controller.NewDisconnected], ecx
  1472. ; 3h. Change connected status. For the connection event, also store
  1473. ; the connection time; any further processing is permitted only after
  1474. ; USB_CONNECT_DELAY ticks.
  1475.         test    al, 1
  1476.         jz      .disconnect
  1477.         invoke  GetTimerTicks
  1478.         mov     [esi+usb_controller.ConnectedTime+ecx*4], eax
  1479.         bts     [esi+usb_controller.NewConnected], ecx
  1480.         jmp     .nextport
  1481. .disconnect:
  1482.         btr     [esi+usb_controller.NewConnected], ecx
  1483.         jmp     .nextport
  1484. .nocsc:
  1485. ; 3i. Handle port disabling.
  1486. ; Note: that needs work.
  1487.         test    al, 8
  1488.         jz      @f
  1489.         test    al, 4
  1490.         jz      @f
  1491.         DEBUGF 1,'K : port %d disabled\n',ecx
  1492. @@:
  1493. ; 3j. Continue the loop for the next port.
  1494. .nextport:
  1495.         inc     ecx
  1496.         cmp     ecx, [esi+usb_controller.NumPorts]
  1497.         jb      .portloop
  1498. .skip_roothub:
  1499. ; 4. Process disconnect events. This should be done after step 3
  1500. ; (which includes the first stage of disconnect processing).
  1501.         invoke  usbhc_api.usb_disconnect_stage2
  1502. ; 5. Check for previously connected devices.
  1503. ; If there is a connected device which was connected less than
  1504. ; USB_CONNECT_DELAY ticks ago, plan to wake up when the delay will be over.
  1505. ; Otherwise, call ehci_new_port.
  1506. ; This should be done after step 3.
  1507.         xor     ecx, ecx
  1508.         cmp     [esi+usb_controller.NewConnected], ecx
  1509.         jz      .skip_newconnected
  1510. .portloop2:
  1511.         bt      [esi+usb_controller.NewConnected], ecx
  1512.         jnc     .noconnect
  1513.         invoke  GetTimerTicks
  1514.         sub     eax, [esi+usb_controller.ConnectedTime+ecx*4]
  1515.         sub     eax, USB_CONNECT_DELAY
  1516.         jge     .connected
  1517.         neg     eax
  1518.         cmp     [esp], eax
  1519.         jb      .nextport2
  1520.         mov     [esp], eax
  1521.         jmp     .nextport2
  1522. .connected:
  1523.         btr     [esi+usb_controller.NewConnected], ecx
  1524.         call    ehci_new_port
  1525.         jmp     .portloop2
  1526. .noconnect:
  1527. .nextport2:
  1528.         inc     ecx
  1529.         cmp     ecx, [esi+usb_controller.NumPorts]
  1530.         jb      .portloop2
  1531. .skip_newconnected:
  1532. ; 6. Process wait lists.
  1533. ; 6a. Periodic endpoints.
  1534. ; If a request is pending >8 microframes, satisfy it.
  1535. ; If a request is pending <=8 microframes, schedule next wakeup in 0.01s.
  1536.         mov     eax, [esi+usb_controller.WaitPipeRequestPeriodic]
  1537.         cmp     eax, [esi+usb_controller.ReadyPipeHeadPeriodic]
  1538.         jz      .noperiodic
  1539.         mov     edx, [edi+EhciFrameIndexReg]
  1540.         sub     edx, [esi+usb_controller.StartWaitFrame]
  1541.         and     edx, 0x3FFF
  1542.         cmp     edx, 8
  1543.         jbe     @f
  1544.         mov     [esi+usb_controller.ReadyPipeHeadPeriodic], eax
  1545.         jmp     .noperiodic
  1546. @@:
  1547.         pop     eax
  1548.         push    1               ; wakeup in 0.01 sec for next test
  1549. .noperiodic:
  1550. ; 6b. Asynchronous endpoints.
  1551. ; Satisfy a request when InterruptOnAsyncAdvance fired.
  1552.         test    byte [esp+4], 20h
  1553.         jz      @f
  1554. ;        dbgstr 'async advance int'
  1555.         mov     eax, [esi+usb_controller.WaitPipeRequestAsync]
  1556.         mov     [esi+usb_controller.ReadyPipeHeadAsync], eax
  1557. @@:
  1558. ; Some hardware in some (rarely) conditions set the status bit,
  1559. ; but just does not generate the corresponding interrupt.
  1560. ; Force checking the status here.
  1561.         mov     eax, [esi+usb_controller.WaitPipeRequestAsync]
  1562.         cmp     [esi+usb_controller.ReadyPipeHeadAsync], eax
  1563.         jz      .noasync
  1564.         spin_lock_irq [esi+usb_controller.WaitSpinlock]
  1565.         mov     edx, [edi+EhciStatusReg]
  1566.         test    dl, 20h
  1567.         jz      @f
  1568.         mov     dword [edi+EhciStatusReg], 20h
  1569.         and     dword [esi+ehci_controller.DeferredActions-sizeof.ehci_controller], not 20h
  1570.         dbgstr 'warning: async advance int missed'
  1571.         mov     [esi+usb_controller.ReadyPipeHeadAsync], eax
  1572.         spin_unlock_irq [esi+usb_controller.WaitSpinlock]
  1573.         jmp     .noasync
  1574. @@:
  1575.         spin_unlock_irq [esi+usb_controller.WaitSpinlock]
  1576.         cmp     dword [esp], 100
  1577.         jb      .noasync
  1578.         mov     dword [esp], 100
  1579. .noasync:
  1580. ; 7. Finalize transfers processed by hardware.
  1581. ; It is better to perform this step after step 4 (disconnect events),
  1582. ; although not strictly obligatory. This way, an active transfer aborted
  1583. ; due to disconnect would be handled with more specific USB_STATUS_CLOSED,
  1584. ; not USB_STATUS_NORESPONSE.
  1585.         test    byte [esp+4], 3
  1586.         jz      @f
  1587.         call    ehci_process_updated_schedule
  1588. @@:
  1589. ; 8. Test whether reset signalling has been started and should be stopped now.
  1590. ; This must be done after step 7, because completion of some transfer could
  1591. ; result in resetting a new port.
  1592. .test_reset:
  1593. ; 8a. Test whether reset signalling is active.
  1594.         cmp     [esi+usb_controller.ResettingStatus], 1
  1595.         jnz     .no_reset_in_progress
  1596. ; 8b. Yep. Test whether it should be stopped.
  1597.         invoke  GetTimerTicks
  1598.         sub     eax, [esi+usb_controller.ResetTime]
  1599.         sub     eax, USB_RESET_TIME
  1600.         jge     .reset_done
  1601. ; 8c. Not yet, but initiate wakeup in -eax ticks and exit this step.
  1602.         neg     eax
  1603.         cmp     [esp], eax
  1604.         jb      .skip_reset
  1605.         mov     [esp], eax
  1606.         jmp     .skip_reset
  1607. .reset_done:
  1608. ; 8d. Yep, call the worker function and proceed to 8e.
  1609.         call    ehci_port_reset_done
  1610. .no_reset_in_progress:
  1611. ; 8e. Test whether reset process is done, either successful or failed.
  1612.         cmp     [esi+usb_controller.ResettingStatus], 0
  1613.         jz      .skip_reset
  1614. ; 8f. Yep. Test whether it should be stopped.
  1615.         invoke  GetTimerTicks
  1616.         sub     eax, [esi+usb_controller.ResetTime]
  1617.         sub     eax, USB_RESET_RECOVERY_TIME
  1618.         jge     .reset_recovery_done
  1619. ; 8g. Not yet, but initiate wakeup in -eax ticks and exit this step.
  1620.         neg     eax
  1621.         cmp     [esp], eax
  1622.         jb      .skip_reset
  1623.         mov     [esp], eax
  1624.         jmp     .skip_reset
  1625. .reset_recovery_done:
  1626. ; 8h. Yep, call the worker function. This could initiate another reset,
  1627. ; so return to the beginning of this step.
  1628.         call    ehci_port_init
  1629.         jmp     .test_reset
  1630. .skip_reset:
  1631. ; 9. Process wait-done notifications, test for new wait requests.
  1632. ; Note: that must be done after steps 4 and 7 which could create new requests.
  1633. ; 9a. Call the worker function.
  1634.         invoke  usbhc_api.usb_process_wait_lists
  1635. ; 9b. If it reports that an asynchronous endpoint should be removed,
  1636. ; doorbell InterruptOnAsyncAdvance and schedule wakeup in 1s
  1637. ; (sometimes it just does not fire).
  1638.         test    al, 1 shl CONTROL_PIPE
  1639.         jz      @f
  1640.         mov     edx, [esi+usb_controller.WaitPipeListAsync]
  1641.         mov     [esi+usb_controller.WaitPipeRequestAsync], edx
  1642.         or      dword [edi+EhciCommandReg], 1 shl 6
  1643. ;        dbgstr 'async advance doorbell'
  1644.         cmp     dword [esp], 100
  1645.         jb      @f
  1646.         mov     dword [esp], 100
  1647. @@:
  1648. ; 9c. If it reports that a periodic endpoint should be removed,
  1649. ; save the current frame and schedule wakeup in 0.01 sec.
  1650.         test    al, 1 shl INTERRUPT_PIPE
  1651.         jz      @f
  1652.         mov     eax, [esi+usb_controller.WaitPipeListPeriodic]
  1653.         mov     [esi+usb_controller.WaitPipeRequestPeriodic], eax
  1654.         mov     edx, [edi+EhciFrameIndexReg]
  1655.         mov     [esi+usb_controller.StartWaitFrame], edx
  1656.         mov     dword [esp], 1  ; wakeup in 0.01 sec for next test
  1657. @@:
  1658. ; 10. Pop the return value, restore the stack after step 1 and return.
  1659.         pop     eax
  1660.         pop     ecx
  1661.         pop     edi ebx ; restore used registers to be stdcall
  1662.         ret
  1663. endp
  1664.  
  1665. ; This procedure is called in the USB thread from ehci_process_deferred
  1666. ; when EHCI IRQ handler has signalled that new IOC-packet was processed.
  1667. ; It scans all lists for completed packets and calls ehci_process_finalized_td
  1668. ; for those packets.
  1669. proc ehci_process_updated_schedule
  1670. ; Important note: we cannot hold the list lock during callbacks,
  1671. ; because callbacks sometimes open and/or close pipes and thus acquire/release
  1672. ; the corresponding lock itself.
  1673. ; Fortunately, pipes can be finally freed only by another step of
  1674. ; ehci_process_deferred, so all pipes existing at the start of this function
  1675. ; will be valid while this function is running. Some pipes can be removed
  1676. ; from the corresponding list, some pipes can be inserted; insert/remove
  1677. ; functions guarantee that traversing one list yields all pipes that were in
  1678. ; that list at the beginning of the traversing (possibly with some new pipes,
  1679. ; possibly without some new pipes, that doesn't matter).
  1680.         push    edi
  1681. ; 1. Process all Periodic lists.
  1682.         lea     edi, [esi+ehci_controller.IntEDs-sizeof.ehci_controller+ehci_static_ep.SoftwarePart]
  1683.         lea     ebx, [esi+ehci_controller.IntEDs+63*sizeof.ehci_static_ep-sizeof.ehci_controller+ehci_static_ep.SoftwarePart]
  1684. @@:
  1685.         call    ehci_process_updated_list
  1686.         cmp     edi, ebx
  1687.         jnz     @b
  1688. ; 2. Process the Control list.
  1689.         add     edi, ehci_controller.ControlDelta
  1690.         call    ehci_process_updated_list
  1691. ; 3. Process the Bulk list.
  1692.         call    ehci_process_updated_list
  1693. ; 4. Return.
  1694.         pop     edi
  1695.         ret
  1696. endp
  1697.  
  1698. ; This procedure is called from ehci_process_updated_schedule, see comments there.
  1699. ; It processes one list, esi -> usb_controller, edi -> usb_static_ep,
  1700. ; and advances edi to next head.
  1701. proc ehci_process_updated_list
  1702.         push    ebx
  1703. ; 1. Perform the external loop over all pipes.
  1704.         mov     ebx, [edi+usb_static_ep.NextVirt]
  1705. .loop:
  1706.         cmp     ebx, edi
  1707.         jz      .done
  1708. ; store pointer to the next pipe in the stack
  1709.         push    [ebx+usb_static_ep.NextVirt]
  1710. ; 2. For every pipe, perform the internal loop over all descriptors.
  1711. ; All descriptors are organized in the queue; we process items from the start
  1712. ; of the queue until a) the last descriptor (not the part of the queue itself)
  1713. ; or b) an active (not yet processed by the hardware) descriptor is reached.
  1714.         lea     ecx, [ebx+usb_pipe.Lock]
  1715.         invoke  MutexLock
  1716.         mov     ebx, [ebx+usb_pipe.LastTD]
  1717.         push    ebx
  1718.         mov     ebx, [ebx+usb_gtd.NextVirt]
  1719. .tdloop:
  1720. ; 3. For every descriptor, test active flag and check for end-of-queue;
  1721. ; if either of conditions holds, exit from the internal loop.
  1722.         cmp     ebx, [esp]
  1723.         jz      .tddone
  1724.         cmp     byte [ebx+ehci_gtd.Token-sizeof.ehci_gtd], 0
  1725.         js      .tddone
  1726. ; Release the queue lock while processing one descriptor:
  1727. ; callback function could (and often would) schedule another transfer.
  1728.         push    ecx
  1729.         invoke  MutexUnlock
  1730.         call    ehci_process_updated_td
  1731.         pop     ecx
  1732.         invoke  MutexLock
  1733.         jmp     .tdloop
  1734. .tddone:
  1735.         invoke  MutexUnlock
  1736.         pop     ebx
  1737. ; End of internal loop, restore pointer to the next pipe
  1738. ; and continue the external loop.
  1739.         pop     ebx
  1740.         jmp     .loop
  1741. .done:
  1742.         pop     ebx
  1743.         add     edi, sizeof.ehci_static_ep
  1744.         ret
  1745. endp
  1746.  
  1747. ; This procedure is called from ehci_process_updated_list, which is itself
  1748. ; called from ehci_process_updated_schedule, see comments there.
  1749. ; It processes one completed descriptor.
  1750. ; in: ebx -> usb_gtd, out: ebx -> next usb_gtd.
  1751. proc ehci_process_updated_td
  1752. ;       mov     eax, [ebx+usb_gtd.Pipe]
  1753. ;       cmp     [eax+usb_pipe.Type], INTERRUPT_PIPE
  1754. ;       jnz     @f
  1755. ;       DEBUGF 1,'K : finalized TD for pipe %x:\n',eax
  1756. ;       lea     eax, [ebx-sizeof.ehci_gtd]
  1757. ;       DEBUGF 1,'K : %x %x %x %x\n',[eax],[eax+4],[eax+8],[eax+12]
  1758. ;       DEBUGF 1,'K : %x %x %x %x\n',[eax+16],[eax+20],[eax+24],[eax+28]
  1759. ;@@:
  1760. ; 1. Remove this descriptor from the list of descriptors for this pipe.
  1761.         invoke  usbhc_api.usb_unlink_td
  1762. ; 2. Calculate actual number of bytes transferred.
  1763.         mov     eax, [ebx+ehci_gtd.Token-sizeof.ehci_gtd]
  1764.         lea     edx, [eax+eax]
  1765.         shr     edx, 17
  1766.         sub     edx, [ebx+usb_gtd.Length]
  1767.         neg     edx
  1768. ; 3. Check whether we need some special processing beyond notifying the driver.
  1769. ; Transfer errors require special processing.
  1770. ; Short packets require special processing if
  1771. ; a) this is not the last descriptor for transfer stage
  1772. ; (in this case we need to process subsequent descriptors for the stage too)
  1773. ; or b) the caller considers short transfers to be an error.
  1774. ; ehci_alloc_transfer sets bit 0 of ehci_gtd.Flags to 0 if short packet
  1775. ; in this descriptor requires special processing and to 1 otherwise.
  1776. ; If special processing is not needed, advance to 4 with ecx = 0.
  1777. ; Otherwise, go to 6.
  1778.         xor     ecx, ecx
  1779.         test    al, 40h
  1780.         jnz     .error
  1781.         test    byte [ebx+ehci_gtd.Flags-sizeof.ehci_gtd], 1
  1782.         jnz     .notify
  1783.         cmp     edx, [ebx+usb_gtd.Length]
  1784.         jnz     .special
  1785. .notify:
  1786. ; 4. Either the descriptor in ebx was processed without errors,
  1787. ; or all necessary error actions were taken and ebx points to the last
  1788. ; related descriptor.
  1789.         invoke  usbhc_api.usb_process_gtd
  1790. ; 5. Free the current descriptor and return the next one.
  1791.         push    [ebx+usb_gtd.NextVirt]
  1792.         stdcall ehci_free_td, ebx
  1793.         pop     ebx
  1794.         ret
  1795. .error:
  1796.         push    ebx
  1797.         sub     ebx, sizeof.ehci_gtd
  1798.         DEBUGF 1,'K : TD failed:\n'
  1799.         DEBUGF 1,'K : %x %x %x %x\n',[ebx],[ebx+4],[ebx+8],[ebx+12]
  1800.         DEBUGF 1,'K : %x %x %x %x\n',[ebx+16],[ebx+20],[ebx+24],[ebx+28]
  1801.         pop     ebx
  1802.         DEBUGF 1,'K : pipe now:\n'
  1803.         mov     ecx, [ebx+usb_gtd.Pipe]
  1804.         sub     ecx, sizeof.ehci_pipe
  1805.         DEBUGF 1,'K : %x %x %x %x\n',[ecx],[ecx+4],[ecx+8],[ecx+12]
  1806.         DEBUGF 1,'K : %x %x %x %x\n',[ecx+16],[ecx+20],[ecx+24],[ecx+28]
  1807.         DEBUGF 1,'K : %x %x %x %x\n',[ecx+32],[ecx+36],[ecx+40],[ecx+44]
  1808. .special:
  1809. ; 6. Special processing is needed.
  1810. ; 6a. Save the status and length.
  1811.         push    edx
  1812.         push    eax
  1813. ; 6b. Traverse the list of descriptors looking for the final descriptor
  1814. ; for this transfer. Free and unlink non-final descriptors.
  1815. ; Final descriptor will be freed in step 5.
  1816. .look_final:
  1817.         invoke  usbhc_api.usb_is_final_packet
  1818.         jnc     .found_final
  1819.         push    [ebx+usb_gtd.NextVirt]
  1820.         stdcall ehci_free_td, ebx
  1821.         pop     ebx
  1822.         invoke  usbhc_api.usb_unlink_td
  1823.         jmp     .look_final
  1824. .found_final:
  1825. ; 6c. Restore the status saved in 6a and transform it to the error code.
  1826. ; Notes:
  1827. ; * any USB transaction error results in Halted bit; if it is not set,
  1828. ;   but we are here, it must be due to short packet;
  1829. ; * babble is considered a fatal USB transaction error,
  1830. ;   other errors just lead to retrying the transaction;
  1831. ;   if babble is detected, return the corresponding error;
  1832. ; * if several non-fatal errors have occured during transaction retries,
  1833. ;   all corresponding bits are set. In this case, return some error code,
  1834. ;   the order is quite arbitrary.
  1835.         pop     eax     ; status
  1836.         movi    ecx, USB_STATUS_UNDERRUN
  1837.         test    al, 40h         ; not Halted?
  1838.         jz      .know_error
  1839.         mov     cl, USB_STATUS_OVERRUN
  1840.         test    al, 10h         ; Babble detected?
  1841.         jnz     .know_error
  1842.         mov     cl, USB_STATUS_BUFOVERRUN
  1843.         test    al, 20h         ; Data Buffer error?
  1844.         jnz     .know_error
  1845.         mov     cl, USB_STATUS_NORESPONSE
  1846.         test    al, 8           ; Transaction Error?
  1847.         jnz     .know_error
  1848.         mov     cl, USB_STATUS_STALL
  1849. .know_error:
  1850. ; 6d. If error code is USB_STATUS_UNDERRUN and the last TD allows short packets,
  1851. ; it is not an error; in this case, go to 4 with ecx = 0.
  1852.         cmp     ecx, USB_STATUS_UNDERRUN
  1853.         jnz     @f
  1854.         test    byte [ebx+ehci_gtd.Flags-sizeof.ehci_gtd], 1
  1855.         jz      @f
  1856.         xor     ecx, ecx
  1857.         pop     edx     ; length
  1858.         jmp     .notify
  1859. @@:
  1860. ; 6e. Abort the entire transfer.
  1861. ; There are two cases: either there is only one transfer stage
  1862. ; (everything except control transfers), then ebx points to the last TD and
  1863. ; all previous TD were unlinked and dismissed (if possible),
  1864. ; or there are several stages (a control transfer) and ebx points to the last
  1865. ; TD of Data or Status stage (usb_is_final_packet does not stop in Setup stage,
  1866. ; because Setup stage can not produce short packets); for Data stage, we need
  1867. ; to unlink and free (if possible) one more TD and advance ebx to the next one.
  1868.         cmp     [ebx+usb_gtd.Callback], 0
  1869.         jnz     .normal
  1870.         push    ecx
  1871.         push    [ebx+usb_gtd.NextVirt]
  1872.         stdcall ehci_free_td, ebx
  1873.         pop     ebx
  1874.         invoke  usbhc_api.usb_unlink_td
  1875.         pop     ecx
  1876. .normal:
  1877. ; 6f. For bulk/interrupt transfers we have no choice but halt the queue,
  1878. ; the driver should intercede (through some API which is not written yet).
  1879. ; Control pipes normally recover at the next SETUP transaction (first stage
  1880. ; of any control transfer), so we hope on the best and just advance the queue
  1881. ; to the next transfer. (According to the standard, "A control pipe may also
  1882. ; support functional stall as well, but this is not recommended.").
  1883.         mov     edx, [ebx+usb_gtd.Pipe]
  1884.         mov     eax, [ebx+ehci_gtd.NextTD-sizeof.ehci_gtd]
  1885.         or      al, 1
  1886.         mov     [edx+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax
  1887.         mov     [edx+ehci_pipe.Overlay.AlternateNextTD-sizeof.ehci_pipe], eax
  1888.         cmp     [edx+usb_pipe.Type], CONTROL_PIPE
  1889.         jz      .control
  1890. ; Bulk/interrupt transfer; halt the queue.
  1891.         mov     [edx+ehci_pipe.Overlay.Token-sizeof.ehci_pipe], 40h
  1892.         pop     edx
  1893.         jmp     .notify
  1894. ; Control transfer.
  1895. .control:
  1896.         and     [edx+ehci_pipe.Overlay.Token-sizeof.ehci_pipe], 0
  1897.         dec     [edx+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe]
  1898.         pop     edx
  1899.         jmp     .notify
  1900. endp
  1901.  
  1902. ; This procedure unlinks the pipe from the corresponding pipe list.
  1903. ; esi -> usb_controller, ebx -> usb_pipe
  1904. proc ehci_unlink_pipe
  1905.         cmp     [ebx+usb_pipe.Type], INTERRUPT_PIPE
  1906.         jnz     @f
  1907.         test    word [ebx+ehci_pipe.Flags-sizeof.ehci_pipe+2], 3FFFh
  1908.         jnz     .interrupt_fs
  1909.         call    ehci_hs_interrupt_list_unlink
  1910.         jmp     .interrupt_common
  1911. .interrupt_fs:
  1912.         call    ehci_fs_interrupt_list_unlink
  1913. .interrupt_common:
  1914. @@:
  1915.         ret
  1916. endp
  1917.  
  1918. ; This procedure temporarily removes the given pipe from hardware queue.
  1919. ; esi -> usb_controller, ebx -> usb_pipe
  1920. proc ehci_disable_pipe
  1921.         mov     eax, [ebx+ehci_pipe.NextQH-sizeof.ehci_pipe]
  1922.         mov     ecx, [ebx+usb_pipe.PrevVirt]
  1923.         mov     edx, esi
  1924.         sub     edx, ecx
  1925.         cmp     edx, sizeof.ehci_controller
  1926.         jb      .prev_is_static
  1927.         mov     [ecx+ehci_pipe.NextQH-sizeof.ehci_pipe], eax
  1928.         ret
  1929. .prev_is_static:
  1930.         mov     [ecx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], eax
  1931.         ret
  1932. endp
  1933.  
  1934. ; This procedure reinserts the given pipe to hardware queue
  1935. ; after ehci_disable_pipe, with clearing transfer queue.
  1936. ; esi -> usb_controller, ebx -> usb_pipe
  1937. ; edx -> current descriptor, eax -> new last descriptor
  1938. proc ehci_enable_pipe
  1939. ; 1. Clear transfer queue.
  1940. ; 1a. Clear status bits so that the controller will try to advance the queue
  1941. ; without doing anything, keep DataToggle and PID bits.
  1942.         and     [ebx+ehci_pipe.Overlay.Token-sizeof.ehci_pipe], 80000000h
  1943. ; 1b. Set [Alternate]NextTD to physical address of the new last descriptor.
  1944.         sub     eax, sizeof.ehci_gtd
  1945.         invoke  GetPhysAddr
  1946.         mov     [ebx+ehci_pipe.HeadTD-sizeof.ehci_pipe], eax
  1947.         mov     [ebx+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax
  1948.         mov     [ebx+ehci_pipe.Overlay.AlternateNextTD-sizeof.ehci_pipe], eax
  1949. ; 2. Reinsert the pipe to hardware queue.
  1950.         lea     eax, [ebx-sizeof.ehci_pipe]
  1951.         invoke  GetPhysAddr
  1952.         inc     eax
  1953.         inc     eax
  1954.         mov     ecx, [ebx+usb_pipe.PrevVirt]
  1955.         mov     edx, esi
  1956.         sub     edx, ecx
  1957.         cmp     edx, sizeof.ehci_controller
  1958.         jb      .prev_is_static
  1959.         mov     edx, [ecx+ehci_pipe.NextQH-sizeof.ehci_pipe]
  1960.         mov     [ebx+ehci_pipe.NextQH-sizeof.ehci_pipe], edx
  1961.         mov     [ecx+ehci_pipe.NextQH-sizeof.ehci_pipe], eax
  1962.         ret
  1963. .prev_is_static:
  1964.         mov     edx, [ecx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart]
  1965.         mov     [ebx+ehci_pipe.NextQH-sizeof.ehci_pipe], edx
  1966.         mov     [ecx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], eax
  1967.         ret
  1968. endp
  1969.  
  1970. proc ehci_alloc_td
  1971.         push    ebx
  1972.         mov     ebx, ehci_gtd_mutex
  1973.         invoke  usbhc_api.usb_allocate_common, (sizeof.ehci_gtd + sizeof.usb_gtd + 1Fh) and not 1Fh
  1974.         test    eax, eax
  1975.         jz      @f
  1976.         add     eax, sizeof.ehci_gtd
  1977. @@:
  1978.         pop     ebx
  1979.         ret
  1980. endp
  1981.  
  1982. ; This procedure is called from several places from main USB code and
  1983. ; frees all additional data associated with the transfer descriptor.
  1984. ; EHCI has no additional data, so just free ehci_gtd structure.
  1985. proc ehci_free_td
  1986.         sub     dword [esp+4], sizeof.ehci_gtd
  1987.         jmp     [usbhc_api.usb_free_common]
  1988. endp
  1989.  
  1990. include 'ehci_scheduler.inc'
  1991.  
  1992. section '.data' readable writable
  1993. include '../peimport.inc'
  1994. include_debug_strings
  1995. IncludeIGlobals
  1996. IncludeUGlobals
  1997. align 4
  1998. usbhc_api usbhc_func
  1999.