Subversion Repositories Kolibri OS

Rev

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

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