Subversion Repositories Kolibri OS

Rev

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