1 ; Code for UHCI controllers.
3 ; Standard driver stuff
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'
14 include '../../kernel/trunk/bus/usb/common.inc'
16 ; =============================================================================
17 ; ================================= Constants =================================
18 ; =============================================================================
19 ; UHCI register declarations
23 UhciFrameNumberReg
= 6
24 UhciBaseAddressReg
= 8
25 UhciSOFModifyReg
= 0Ch
26 UhciPort1StatusReg
= 10h
27 ; possible PIDs for USB data transfers
31 ; UHCI does not support an interrupt on root hub status change. We must poll
32 ; the controller periodically. This is the period in timer ticks (10ms).
33 ; We use the value 100 ticks: it is small enough to be responsive to connect
34 ; events and large enough to not load CPU too often.
35 UHCI_POLL_INTERVAL
= 100
36 ; the following constant is an invalid encoding for length fields in
37 ; uhci_gtd; it is used to check whether an inactive TD has been
38 ; completed (actual length of the transfer is valid) or not processed at all
39 ; (actual length of the transfer is UHCI_INVALID_LENGTH).
40 ; Valid values are 0-4FFh and 7FFh. We use 700h as an invalid value.
41 UHCI_INVALID_LENGTH
= 700h
43 ; =============================================================================
44 ; ================================ Structures =================================
45 ; =============================================================================
47 ; UHCI-specific part of a pipe descriptor.
48 ; * The structure corresponds to the Queue Head aka QH from the UHCI
49 ; specification with some additional fields.
50 ; * The hardware uses first two fields (8 bytes). Next two fields are used for
51 ; software book-keeping.
52 ; * The hardware requires 16-bytes alignment of the hardware part.
53 ; Since the allocator (usb_allocate_common) allocates memory sequentially
54 ; from page start (aligned on 0x1000 bytes), block size for the allocator
55 ; must be divisible by 16; usb1_allocate_endpoint ensures this.
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
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.
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.
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.
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).
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
103 ; Same as uhci_pipe.NextQH.
105 ; Same as uhci_pipe.HeadTD.
107 ; Virtual address of the next list.
110 SoftwarePart rd sizeof.usb_static_ep
/4
111 ; Common part for all controllers, described by usb_static_ep structure.
113 ; Padding for 16-byte alignment.
116 if sizeof.uhci_static_ep
mod 16
117 .err uhci_static_ep must be
16-bytes aligned
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 ------------------------------
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
136 ; With masked 2 lower bits, the entry is a physical address of the first QH/TD
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
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.
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.
156 ; See the comment before UHCI_POLL_INTERVAL. This variable keeps the
157 ; last time, in timer ticks, when the polling was done.
159 ; Pointer to usb_controller for EHCI companion, if any, or NULL.
162 if uhci_controller.IntEDs
mod 16
163 .err Static endpoint descriptors must be
16-bytes aligned inside uhci_controller
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.
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
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
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.
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
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.
233 ; Physical address of the data buffer for this TD.
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)
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
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.
259 dd sizeof.uhci_controller
262 dd uhci_process_deferred
263 dd uhci_set_device_address
264 dd uhci_get_device_address
266 dd uhci_new_port.reset
267 dd uhci_set_endpoint_packet_size
274 dd uhci_alloc_transfer
275 dd uhci_insert_transfer
279 uhci_name
db 'UHCI',0
282 ; =============================================================================
283 ; =================================== Code ====================================
284 ; =============================================================================
286 ; Called once when driver is loading and once at shutdown.
287 ; When loading, must initialize itself, register itself in the system
288 ; and return eax = value obtained when registering.
291 dd ? ; return address
292 .reason
dd ? ; DRV_ENTRY or DRV_EXIT
293 .cmdline
dd ? ; normally NULL
295 cmp [.reason
], DRV_ENTRY
297 mov ecx, uhci_ep_mutex
300 mov ecx, uhci_gtd_mutex
306 movi
ecx, sizeof.usbhc_func
/4
309 invoke RegUSBDriver
, uhci_name
, 0, uhci_hardware_func
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
320 ; inherit some variables from the parent (usb_init_controller)
323 ; 1. Store pointer to uhci_controller for further use.
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
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
343 if
(uhci_controller.IntEDs
mod 0x1000) <> 0
344 .err assertion failed
346 add eax, uhci_controller.IntEDs
348 ; 2b. Fill first 32 entries.
350 inc eax ; set QH bit for uhci_pipe.NextQH
355 add eax, sizeof.uhci_static_ep
357 ; 2c. Fill the rest entries.
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.
371 ; 3c. Get the size of next group.
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.
378 call uhci_init_static_ep_group
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
385 .
init_static_eds_done:
386 ; 3g. Initialize the last static head.
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
399 ; 4b. Disable IO access.
401 invoke PciWrite16
, dword [.bus
], dword [.devfn
], 4, eax
402 ; 4c. Read&save IO base address.
403 invoke PciRead16
, dword [.bus
], dword [.devfn
], 20h
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
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.
422 invoke PciWrite16
, dword [.bus
], dword [.devfn
], 4, ecx
423 ; 5. Reset the controller.
428 ; 5f. Wait up to 10ms.
439 dbgstr
'UHCI controller reset timeout'
443 ; emergency variant for tests - always wait 10 ms
454 ; 6. Get number of ports & disable all ports.
456 lea edx, [edi+UhciPort1StatusReg
]
471 lea esi, [edx-UhciPort1StatusReg
]
473 shr esi, 1 ; esi = number of ports
475 dbgstr
'error: no ports on UHCI controller'
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
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
493 invoke PciRead8
, dword [.bus
], dword [.devfn
], 3Ch
495 ; DEBUGF 1,'K : UHCI %x: io=%x, irq=%x\n',esi,edi,al
497 invoke AttachIntHandler
, eax, uhci_irq
, esi
498 ; 10. Setup controller registers.
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).
504 inc edx ; UhciStatusReg == 2
507 ; 10b. UhciInterruptReg := 0Dh.
509 inc edx ; UhciInterruptReg == 4
512 ; 10c. UhciFrameNumberReg := 0.
514 inc edx ; UhciFrameNumberReg == 6
517 ; 10d. UhciBaseAddressReg := physical address of uhci_controller.
519 inc edx ; UhciBaseAddressReg == 8
520 lea eax, [esi-sizeof.uhci_controller
]
523 ; 10e. UhciCommandReg := Run + Configured + (MaxPacket is 64 bytes)
524 sub edx, UhciBaseAddressReg
; UhciCommandReg == 0
525 mov ax, 0C1h
; Run, Configured, MaxPacket = 64b
527 ; 11. Do initial scan of existing devices.
528 call uhci_poll_roothub
529 ; 12. Return pointer to usb_controller.
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
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
549 ; 2. Stop the controller and disable all interrupts.
553 add edx, UhciInterruptReg
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
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
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
586 call uhci_init_static_endpoint
587 add eax, sizeof.uhci_static_ep
588 add esi, sizeof.uhci_static_ep
595 ; IRQ handler for UHCI controllers.
597 ; Not our interrupt: restore esi and return zero.
602 push esi ; save used register to be cdecl
605 dd ? ; return address
608 mov esi, [.controller
]
609 ; 1. Read UhciStatusReg.
610 mov edx, [esi+uhci_controller.IOBase
-sizeof.uhci_controller
]
612 inc edx ; UhciStatusReg == 2
614 ; 2. Test whether it is our interrupt; if so, at least one status bit is set.
617 ; 3. Clear all status bits.
622 DEBUGF
1,'K : something terrible happened with UHCI (%x)\n',al
624 ; 5. We can't do too much from an interrupt handler, e.g. we can't take
625 ; any mutex locks since our code could be called when another code holds the
626 ; lock and has no chance to release it. Thus, only inform the processing thread
627 ; that it should scan the queue and wake it if needed.
628 lock or byte [esi+uhci_controller.DeferredActions
-sizeof.uhci_controller
], al
632 invoke usbhc_api.usb_wakeup_if_needed
634 ; 6. This is our interrupt; return 1.
636 pop esi ; restore used register to be stdcall
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.
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
654 sub eax, [esi+uhci_controller.LastPollTime
-sizeof.uhci_controller
]
655 sub eax, UHCI_POLL_INTERVAL
659 mov [esi+uhci_controller.LastPollTime
-sizeof.uhci_controller
], eax
660 call uhci_poll_roothub
661 mov eax, -UHCI_POLL_INTERVAL
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
]
673 mov eax, [esi+usb_controller.WaitPipeRequestPeriodic
]
674 cmp eax, [esi+usb_controller.ReadyPipeHeadPeriodic
]
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
681 cmp word [esi+usb_controller.StartWaitFrame
], ax
683 ; 3c. The same frame; wake up in 0.01 sec.
687 ; 3d. The frame is changed, old contents is guaranteed to be forgotten.
688 mov eax, [esi+usb_controller.WaitPipeRequestAsync
]
689 mov [esi+usb_controller.ReadyPipeHeadAsync
], eax
690 mov eax, [esi+usb_controller.WaitPipeRequestPeriodic
]
691 mov [esi+usb_controller.ReadyPipeHeadPeriodic
], eax
693 ; 4. Process disconnect events. This should be done after step 2
694 ; (which includes the first stage of disconnect processing).
695 invoke usbhc_api.usb_disconnect_stage2
696 ; 5. Test whether USB_CONNECT_DELAY for a connected device is over.
697 ; Call uhci_new_port for all such devices.
699 cmp [esi+usb_controller.NewConnected
], ecx
700 jz .skip_newconnected
702 bt [esi+usb_controller.NewConnected
], ecx
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'
713 sub eax, [esi+usb_controller.ConnectedTime
+ecx*4]
714 sub eax, USB_CONNECT_DELAY
722 btr [esi+usb_controller.NewConnected
], ecx
727 cmp ecx, [esi+usb_controller.NumPorts
]
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'.
735 xchg byte [esi+uhci_controller.DeferredActions
-sizeof.uhci_controller
], al
738 call uhci_process_updated_schedule
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.
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.
750 sub eax, [esi+usb_controller.ResetTime
]
751 sub eax, USB_RESET_TIME
753 ; 7c. Not yet, but initiate wakeup in -eax ticks and exit this step.
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
766 ; 7f. Yep. Test whether it should be stopped.
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.
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.
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.
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
802 mov word [esi+usb_controller.StartWaitFrame
], ax
805 ; 9. Return the value from the top of stack.
807 pop edi ebx ; restore used registers to be stdcall.
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
815 ; in: esi -> usb_controller
816 proc uhci_process_updated_schedule
817 ; Important note: we cannot hold the list lock during callbacks,
818 ; because callbacks sometimes open and/or close pipes and thus acquire/release
819 ; the corresponding lock itself.
820 ; Fortunately, pipes can be finally freed only by another step of
821 ; uhci_process_deferred, so all pipes existing at the start of this function
822 ; will be valid while this function is running. Some pipes can be removed
823 ; from the corresponding list, some pipes can be inserted; insert/remove
824 ; functions guarantee that traversing one list yields all pipes that were in
825 ; that list at the beginning of the traversing (possibly with some new pipes,
826 ; possibly without some new pipes, that doesn't matter).
827 ; 1. Process all Periodic lists.
828 lea edi, [esi+uhci_controller.IntEDs.SoftwarePart
-sizeof.uhci_controller
]
829 lea ebx, [esi+uhci_controller.IntEDs.SoftwarePart
+63*sizeof.uhci_static_ep
-sizeof.uhci_controller
]
831 call uhci_process_updated_list
834 ; 2. Process the Control list.
835 call uhci_process_updated_list
836 ; 3. Process the Bulk list.
837 call uhci_process_updated_list
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
]
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]
861 mov ebx, [ebx+usb_pipe.LastTD
]
863 mov ebx, [ebx+usb_gtd.NextVirt
]
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.
869 mov eax, [ebx+uhci_gtd.ControlStatus
-sizeof.uhci_gtd
]
870 test eax, 1 shl 23 ; active?
872 ; Release the queue lock while processing one descriptor:
873 ; callback function could (and often would) schedule another transfer.
876 call uhci_process_finalized_td
883 ; End of internal loop, restore pointer to the next pipe
884 ; and continue the external loop.
888 pop ebx ; restore used register to be stdcall
889 add edi, sizeof.uhci_static_ep
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)
908 cmp byte [ebx+uhci_gtd.Token
-sizeof.uhci_gtd
], USB_PID_IN
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).
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
]
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.
934 ; 3c. Subtract number of bytes in this packet.
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).
954 test byte [ebx+uhci_gtd.OrigBufferInfo
-sizeof.uhci_gtd
], 1
956 cmp edx, [ebx+usb_gtd.
Length]
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
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.
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
]
978 stdcall uhci_free_td
, eax
980 mov eax, [ebx+usb_gtd.Pipe
]
981 mov [eax+uhci_pipe.ErrorTD
-sizeof.uhci_pipe
], ebx
982 ; 5c. Traverse the list of descriptors looking for the final packet
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
988 mov ebx, [ebx+usb_gtd.NextVirt
]
990 invoke usbhc_api.usb_unlink_td
991 invoke usbhc_api.usb_is_final_packet
993 push [ebx+usb_gtd.NextVirt
]
994 stdcall uhci_free_td
, ebx
998 ; 5d. Restore the status saved in 5a and transform it to the error code.
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?
1013 mov cl, USB_STATUS_OVERRUN
1014 test al, 1 shl (20-16) ; Babble detected?
1016 mov cl, USB_STATUS_BITSTUFF
1017 test al, 1 shl (17-16) ; Bitstuff error?
1019 mov cl, USB_STATUS_NORESPONSE
1020 test al, 1 shl (18-16) ; CRC/TimeOut error?
1022 mov cl, USB_STATUS_BUFOVERRUN
1023 test al, 1 shl (21-16) ; Data Buffer error?
1025 mov cl, USB_STATUS_STALL
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
1035 test byte [ebx+uhci_gtd.OrigBufferInfo
-sizeof.uhci_gtd
], 1
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
1042 mov eax, [ebx+uhci_gtd.NextTD
-sizeof.uhci_gtd
]
1044 mov edx, [ebx+usb_gtd.Pipe
]
1045 mov [edx+uhci_pipe.HeadTD
-sizeof.uhci_pipe
], eax
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
1059 ; We cannot free ErrorTD yet, it could still be used by the hardware.
1061 mov eax, [ebx+usb_gtd.Pipe
]
1062 push [ebx+usb_gtd.NextVirt
]
1063 cmp ebx, [eax+uhci_pipe.ErrorTD
-sizeof.uhci_pipe
]
1065 stdcall uhci_free_td
, ebx
1068 invoke usbhc_api.usb_unlink_td
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
1080 ; Bulk/interrupt transfer; halt the queue.
1081 mov eax, [ebx+uhci_gtd.NextTD
-sizeof.uhci_gtd
]
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
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
1098 stdcall uhci_free_td
, ebx
1100 ; 7c. Restore pointer to the next descriptor and return.
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
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
]
1125 ; 3. Lock the transfer queue.
1126 add ecx, usb_pipe.
Lock
1128 ; 4. Flip the toggle bit in all packets from ebx.NextVirt to ecx.LastTD
1130 mov eax, [ebx+usb_gtd.NextVirt
]
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
]
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.
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.
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
]
1157 ; 3. Read port status.
1158 mov edx, [esi+uhci_controller.IOBase
-sizeof.uhci_controller
]
1159 lea edx, [edx+ecx*2+UhciPort1StatusReg
]
1161 ; 4. If no change bits are set, continue to the next port.
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.
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.
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
1184 invoke GetTimerTicks
1185 mov [esi+usb_controller.ConnectedTime
+ecx*4], eax
1186 bts [esi+usb_controller.NewConnected
], ecx
1189 btr [esi+usb_controller.NewConnected
], ecx
1192 ; 7. Process enable change notifications.
1193 ; Note: that needs work.
1198 dbgstr
'Port disabled'
1200 ; 8. Continue the loop for every port.
1202 cmp ecx, [esi+usb_controller.NumPorts
]
1204 pop ebx ; restore used register to be stdcall
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)
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
1218 btr [esi+usb_controller.PendingPorts
], ecx
1219 ; fall through to uhci_new_port.reset
1221 ; This function is called from uhci_new_port and uhci_test_pending_port.
1222 ; It starts reset signalling for the port. Note that in USB first stages
1223 ; of configuration can not be done for several ports in parallel.
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
]
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
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
]
1250 DEBUGF
1,'K : UHCI %x status %x/',esi,ax
1253 ; 2. Status bits in UHCI are invalid during reset signalling.
1254 ; Wait a millisecond while status bits become valid again.
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.
1264 or al, 6 ; enable port, clear status change
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
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
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
]
1285 DEBUGF
1,'K : UHCI %x status %x\n',esi,ax
1286 ; 2. If the device has been disconnected, stop the initialization.
1289 dbgstr
'USB port disabled after reset'
1290 jmp [usbhc_api.usb_test_pending_port
]
1292 ; 3. Copy LowSpeed bit to bit 0 of eax and call the worker procedure
1293 ; to notify the protocol layer about new UHCI device.
1296 call uhci_new_device
1300 ; 4. If something at the protocol layer has failed
1301 ; (no memory, no bus address), disable the port and stop the initialization.
1305 out dx, ax ; disable the port
1306 jmp [usbhc_api.usb_test_pending_port
]
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.
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
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.
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
]
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
]
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]
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
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
]
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
1385 ; inherit some variables from the parent usb_open_pipe
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
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
]
1416 mov edx, [.maxpacket
]
1420 mov al, USB_PID_SETUP
1421 cmp [.
type], CONTROL_PIPE
1424 test byte [.endpoint
], 80h
1428 mov [edi+uhci_pipe.Token
-sizeof.uhci_pipe
], eax
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))
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
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
]
1461 call usb1_select_interrupt_list
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
]
1485 mov [edx+uhci_static_ep.NextQH
-uhci_static_ep.SoftwarePart
], eax
1486 ; 6. Return with nonzero eax.
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
1498 proc uhci_unlink_pipe
1499 cmp [ebx+usb_pipe.
Type], INTERRUPT_PIPE
1501 mov eax, [ebx+uhci_pipe.Token
-sizeof.uhci_pipe
]
1508 stdcall usb1_interrupt_list_unlink
, eax, ecx
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
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
]
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
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
]
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
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
1558 packetSize
dd ? ; must be the last variable, see usb_init_transfer
1560 ; 1. [td] will be the first packet in the transfer.
1561 ; Save it to allow unrolling if something will fail.
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
]
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
]
1586 ; set the toggle bit for control transfers,
1587 mov ecx, [direction
]
1591 and eax, not (1 shl 19)
1595 ; store the resulting Token in the stack variable.
1597 ; 3. While the remaining data cannot fit in one packet,
1598 ; allocate full packets (of maximal possible size).
1602 call uhci_alloc_packet
1610 ; 4. The remaining data can fit in one packet;
1611 ; allocate the last packet with size = size of remaining data.
1613 mov [packetSize
], eax
1614 call uhci_alloc_packet
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.
1626 and byte [ecx+uhci_gtd.ControlStatus
+3-sizeof.uhci_gtd
], not (1 shl (29-24))
1627 and byte [ecx+uhci_gtd.OrigBufferInfo
-sizeof.uhci_gtd
], not 1
1629 ; 6. Update toggle bit in uhci_pipe structure from current value of [token].
1631 xor edx, [ebx+uhci_pipe.Token
-sizeof.uhci_pipe
]
1633 xor [ebx+uhci_pipe.Token
-sizeof.uhci_pipe
], edx
1637 mov edi, uhci_hardware_func
1639 invoke usbhc_api.usb_undo_tds
, [origTD
]
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
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.
1663 cmp [.packetSize
], eax
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.
1668 add edx, [.packetSize
]
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
]
1678 add eax, sizeof.uhci_original_buffer
1680 ; 1d. If failed, return zero.
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
]
1690 add edx, [.packetSize
]
1699 mov [eax+uhci_original_buffer.UsedBuffer
], ecx
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
1709 mov edi, [eax+uhci_original_buffer.UsedBuffer
]
1710 mov ecx, [.packetSize
]
1720 ; 2. Allocate the next TD.
1724 ; If failed, free the temporary buffer (if it was allocated) and return zero.
1727 ; 3. Initialize controller-independent parts of both TDs.
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))
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.
1751 sub eax, sizeof.uhci_gtd
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
1757 test [ebx+usb_pipe.
Type], 1
1759 cmp ecx, [ebx+usb_pipe.LastTD
]
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.
1767 cmp [.packetSize
], eax
1770 mov edx, [ecx+uhci_gtd.OrigBufferInfo
-sizeof.uhci_gtd
]
1773 mov eax, [edx+uhci_original_buffer.UsedBuffer
]
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.
1781 mov edx, [.packetSize
]
1785 or byte [ecx+uhci_gtd.ControlStatus
+3-sizeof.uhci_gtd
], 1 shl (29-24) ; disallow short packets
1786 or byte [ecx+uhci_gtd.OrigBufferInfo
-sizeof.uhci_gtd
], 1
1788 ; 5e. Get Token field: combine [.token] with [.packetSize].
1791 mov [ecx+uhci_gtd.Token
-sizeof.uhci_gtd
], edx
1792 ; 6. Flip toggle bit in [.token].
1795 ; 7. Return pointer to the next TD.
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
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
1818 or byte [eax+uhci_gtd.NextTD
-sizeof.uhci_gtd
], 4 ; set Depth bit
1823 ; Allocates one endpoint structure for OHCI.
1824 ; Returns pointer to software part (usb_pipe) in eax.
1825 proc uhci_alloc_pipe
1827 mov ebx, uhci_ep_mutex
1828 invoke usbhc_api.usb_allocate_common
, (sizeof.uhci_pipe
+ sizeof.usb_pipe
+ 0Fh
) and not 0Fh
1831 add eax, sizeof.uhci_pipe
1837 ; Free memory associated with pipe.
1838 ; For UHCI, this includes usb_pipe structure and ErrorTD, if present.
1841 mov eax, [eax+uhci_pipe.ErrorTD
-sizeof.uhci_pipe
]
1844 stdcall uhci_free_td
, eax
1846 sub dword [esp+4], sizeof.uhci_pipe
1847 jmp [usbhc_api.usb_free_common
]
1850 ; Allocates one general transfer descriptor structure for UHCI.
1851 ; Returns pointer to software part (usb_gtd) in eax.
1854 mov ebx, uhci_gtd_mutex
1855 invoke usbhc_api.usb_allocate_common
, (sizeof.uhci_gtd
+ sizeof.usb_gtd
+ 0Fh
) and not 0Fh
1858 add eax, sizeof.uhci_gtd
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.
1869 mov eax, [eax+uhci_gtd.OrigBufferInfo
-sizeof.uhci_gtd
]
1874 sub dword [esp+4], sizeof.uhci_gtd
1875 jmp [usbhc_api.usb_free_common
]
1878 include 'usb1_scheduler.inc'
1879 define_controller_name uhci
1881 section '.data' readable writable
1882 include '../peimport.inc'
1883 include_debug_strings
1887 usbhc_api usbhc_func
1888 uhci_ep_first_page
dd ?
1890 uhci_gtd_first_page
dd ?
1891 uhci_gtd_mutex MUTEX