Subversion Repositories Kolibri OS

Rev

Rev 3725 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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