Subversion Repositories Kolibri OS

Rev

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