Subversion Repositories Kolibri OS

Rev

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

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