Subversion Repositories Kolibri OS

Rev

Rev 3700 | 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).
3657 clevermous 23
; We use the value 100 ticks: it is small enough to be responsive to connect
3656 clevermous 24
; events and large enough to not load CPU too often.
3520 clevermous 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
3653 clevermous 44
;   from page start (aligned on 0x1000 bytes), block size for the allocator
45
;   must be divisible by 16; usb1_allocate_endpoint ensures this.
3520 clevermous 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
3579 clevermous 122
; the frames n,n+1024,n+2048,n+3072,...
3520 clevermous 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
3653 clevermous 163
;   (aligned on 0x1000 bytes), block size for the allocator must be
164
;   divisible by 16; usb1_allocate_general_td ensures this.
3520 clevermous 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
3598 clevermous 306
        movi    ecx, 32
3520 clevermous 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.
3598 clevermous 406
        movi    ecx, 10
3520 clevermous 407
@@:
408
        push    esi
3598 clevermous 409
        movi    esi, 1
3520 clevermous 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
3598 clevermous 423
        movi    esi, 10
3520 clevermous 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
3653 clevermous 844
        mov     eax, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd]
3520 clevermous 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.
3653 clevermous 880
        mov     edx, [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
3520 clevermous 881
        and     edx, not 1      ; clear lsb (used for another goal)
882
        jz      .nocopy
3653 clevermous 883
        cmp     byte [ebx+uhci_gtd.Token-sizeof.uhci_gtd], USB_PID_IN
3520 clevermous 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]
3653 clevermous 891
        mov     ecx, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd]
3520 clevermous 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.
3653 clevermous 904
        mov     eax, [ebx+uhci_gtd.ControlStatus-sizeof.uhci_gtd]
905
        mov     ecx, [ebx+uhci_gtd.Token-sizeof.uhci_gtd]
3520 clevermous 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
3653 clevermous 929
        test    byte [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1
3520 clevermous 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'
3653 clevermous 937
if sizeof.uhci_gtd <> 20
3520 clevermous 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]
3653 clevermous 946
        DEBUGF 1,'K : pipe: %x %x\n',[eax+0-sizeof.uhci_pipe],[eax+4-sizeof.uhci_pipe]
3520 clevermous 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.
3653 clevermous 950
        mov     eax, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
3520 clevermous 951
        test    eax, eax
952
        jz      @f
953
        stdcall uhci_free_td, eax
954
@@:
955
        mov     eax, [ebx+usb_gtd.Pipe]
3653 clevermous 956
        mov     [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe], ebx
3520 clevermous 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.
3598 clevermous 985
        movi    ecx, USB_STATUS_UNDERRUN
3520 clevermous 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
3653 clevermous 1010
        test    byte [ebx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1
3520 clevermous 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:
3653 clevermous 1017
        mov     eax, [ebx+uhci_gtd.NextTD-sizeof.uhci_gtd]
3520 clevermous 1018
        and     al, not 0xF
1019
        mov     edx, [ebx+usb_gtd.Pipe]
3653 clevermous 1020
        mov     [edx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax
3520 clevermous 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]
3653 clevermous 1038
        cmp     ebx, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
3520 clevermous 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.
3653 clevermous 1056
        mov     eax, [ebx+uhci_gtd.NextTD-sizeof.uhci_gtd]
3520 clevermous 1057
        and     al, not 0xF
1058
        inc     eax     ; set Halted bit
3653 clevermous 1059
        mov     [edx+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax
3520 clevermous 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]
3653 clevermous 1085
        cmp     [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe], ebx
3520 clevermous 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.
3653 clevermous 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]
3520 clevermous 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:
3653 clevermous 1121
        xor     byte [eax+uhci_gtd.Token-sizeof.uhci_gtd+2], 1 shl (19-16)
3520 clevermous 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.
3653 clevermous 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
3520 clevermous 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
3598 clevermous 1246
        movi    esi, 1
3520 clevermous 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
3653 clevermous 1329
        mov     byte [ebx+uhci_pipe.Token+1-sizeof.uhci_pipe], cl
3520 clevermous 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
3653 clevermous 1338
        mov     al, byte [ebx+uhci_pipe.Token+1-sizeof.uhci_pipe]
3520 clevermous 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
3653 clevermous 1363
        and     [ebx+uhci_pipe.Token-sizeof.uhci_pipe], (1 shl 21) - 1
1364
        or      [ebx+uhci_pipe.Token-sizeof.uhci_pipe], ecx
3520 clevermous 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
3816 clevermous 1378
virtual at ebp-12
1379
.speed          db      ?
1380
                rb      3
1381
.bandwidth      dd      ?
1382
.target         dd      ?
1383
                rd      2
3520 clevermous 1384
.config_pipe    dd      ?
1385
.endpoint       dd      ?
1386
.maxpacket      dd      ?
1387
.type           dd      ?
1388
.interval       dd      ?
1389
end virtual
1390
; 1. Initialize ErrorTD to zero.
3653 clevermous 1391
        and     [edi+uhci_pipe.ErrorTD-sizeof.uhci_pipe], 0
3520 clevermous 1392
; 2. Initialize HeadTD to the physical address of the first TD.
3700 clevermous 1393
        push    eax     ; store pointer to the first TD for step 4
3653 clevermous 1394
        sub     eax, sizeof.uhci_gtd
3520 clevermous 1395
        call    get_phys_addr
3653 clevermous 1396
        mov     [edi+uhci_pipe.HeadTD-sizeof.uhci_pipe], eax
3520 clevermous 1397
; 3. Initialize Token field:
1398
; take DeviceAddress and LowSpeedDevice from the parent pipe,
1399
; take Endpoint and MaximumLength fields from API arguments,
1400
; set PID depending on pipe type and provided pipe direction,
1401
; set DataToggle to zero.
3653 clevermous 1402
        mov     eax, [ecx+uhci_pipe.Token-sizeof.uhci_pipe]
3520 clevermous 1403
        and     eax, 0x107F00   ; keep DeviceAddress and LowSpeedDevice
1404
        mov     edx, [.endpoint]
1405
        and     edx, 15
1406
        shl     edx, 15
1407
        or      eax, edx
1408
        mov     edx, [.maxpacket]
1409
        dec     edx
1410
        shl     edx, 21
1411
        or      eax, edx
1412
        mov     al, USB_PID_SETUP
1413
        cmp     [.type], CONTROL_PIPE
1414
        jz      @f
1415
        mov     al, USB_PID_OUT
1416
        test    byte [.endpoint], 80h
1417
        jz      @f
1418
        mov     al, USB_PID_IN
1419
@@:
3653 clevermous 1420
        mov     [edi+uhci_pipe.Token-sizeof.uhci_pipe], eax
3816 clevermous 1421
        bt      eax, 20
1422
        setc    [.speed]
3520 clevermous 1423
; 4. Initialize the first TD:
1424
; copy Token from uhci_pipe.Token zeroing reserved bit 20,
1425
; set ControlStatus for future transfers, bit make it inactive,
3700 clevermous 1426
; set bit 0 in NextTD = "no next TD",
1427
; zero OrigBufferInfo.
3520 clevermous 1428
        pop     edx     ; restore pointer saved in step 2
3653 clevermous 1429
        mov     [edx+uhci_gtd.Token-sizeof.uhci_gtd], eax
1430
        and     byte [edx+uhci_gtd.Token+2-sizeof.uhci_gtd], not (1 shl (20-16))
3520 clevermous 1431
        and     eax, 1 shl 20
1432
        shl     eax, 6
1433
        or      eax, UHCI_INVALID_LENGTH + (3 shl 27)
1434
                ; not processed, inactive, allow 3 errors
3700 clevermous 1435
        and     [edx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 0
3653 clevermous 1436
        mov     [edx+uhci_gtd.ControlStatus-sizeof.uhci_gtd], eax
1437
        mov     [edx+uhci_gtd.NextTD-sizeof.uhci_gtd], 1
3520 clevermous 1438
; 5. Select the corresponding list and insert to the list.
1439
; 5a. Use Control list for control pipes, Bulk list for bulk pipes.
1440
        lea     edx, [esi+uhci_controller.ControlED.SoftwarePart-sizeof.uhci_controller]
1441
        cmp     [.type], BULK_PIPE
1442
        jb      .insert ; control pipe
1443
        lea     edx, [esi+uhci_controller.BulkED.SoftwarePart-sizeof.uhci_controller]
1444
        jz      .insert ; bulk pipe
1445
.interrupt_pipe:
1446
; 5b. For interrupt pipes, let the scheduler select the appropriate list
1447
; based on the current bandwidth distribution and the requested bandwidth.
1448
; This could fail if the requested bandwidth is not available;
1449
; if so, return an error.
1450
        lea     edx, [esi + uhci_controller.IntEDs - sizeof.uhci_controller]
1451
        lea     eax, [esi + uhci_controller.IntEDs + 32*sizeof.uhci_static_ep - sizeof.uhci_controller]
3598 clevermous 1452
        movi    ecx, 64
3520 clevermous 1453
        call    usb1_select_interrupt_list
1454
        test    edx, edx
1455
        jz      .return0
1456
.insert:
1457
; Insert to the head of the corresponding list.
1458
; Note: inserting to the head guarantees that the list traverse in
1459
; uhci_process_updated_schedule, once started, will not interact with new pipes.
1460
; However, we still need to ensure that links in the new pipe (edi.NextVirt)
1461
; are initialized before links to the new pipe (edx.NextVirt).
1462
; 5c. Insert in the list of virtual addresses.
1463
        mov     ecx, [edx+usb_pipe.NextVirt]
1464
        mov     [edi+usb_pipe.NextVirt], ecx
1465
        mov     [edi+usb_pipe.PrevVirt], edx
1466
        mov     [ecx+usb_pipe.PrevVirt], edi
1467
        mov     [edx+usb_pipe.NextVirt], edi
1468
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
1469
; store the physical address of the new pipe to previous NextQH.
1470
        mov     ecx, [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart]
3653 clevermous 1471
        mov     [edi+uhci_pipe.NextQH-sizeof.uhci_pipe], ecx
1472
        lea     eax, [edi-sizeof.uhci_pipe]
3520 clevermous 1473
        call    get_phys_addr
1474
        inc     eax
1475
        inc     eax
1476
        mov     [edx+uhci_static_ep.NextQH-uhci_static_ep.SoftwarePart], eax
1477
; 6. Return with nonzero eax.
1478
        ret
1479
.return0:
1480
        xor     eax, eax
1481
        ret
1482
endp
1483
 
1484
; This procedure is called when a pipe is closing (either due to API call
1485
; or due to disconnect); it unlinks a pipe from the corresponding list.
3653 clevermous 1486
if uhci_static_ep.SoftwarePart <> sizeof.uhci_pipe
1487
.err uhci_unlink_pipe assumes that uhci_static_ep.SoftwarePart == sizeof.uhci_pipe
3520 clevermous 1488
end if
1489
proc uhci_unlink_pipe
1490
        cmp     [ebx+usb_pipe.Type], INTERRUPT_PIPE
1491
        jnz     @f
3653 clevermous 1492
        mov     eax, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
3520 clevermous 1493
        cmp     al, USB_PID_IN
1494
        setz    ch
1495
        bt      eax, 20
1496
        setc    cl
1497
        add     eax, 1 shl 21
1498
        shr     eax, 21
1499
        stdcall usb1_interrupt_list_unlink, eax, ecx
1500
@@:
1501
; Note: we need to ensure that NextVirt field of the pipe is not modified;
1502
; this procedure can be called while uhci_process_updated_schedule processes
1503
; the same pipe, and it needs a correct NextVirt field to continue.
1504
        mov     edx, [ebx+usb_pipe.NextVirt]
1505
        mov     eax, [ebx+usb_pipe.PrevVirt]
1506
        mov     [edx+usb_pipe.PrevVirt], eax
1507
        mov     [eax+usb_pipe.NextVirt], edx
1508
; Note: eax could be either usb_pipe or usb_static_ep;
1509
; fortunately, NextQH and SoftwarePart have same offsets in both.
3653 clevermous 1510
        mov     edx, [ebx+uhci_pipe.NextQH-sizeof.uhci_pipe]
1511
        mov     [eax+uhci_pipe.NextQH-sizeof.uhci_pipe], edx
3520 clevermous 1512
        ret
1513
endp
1514
 
1515
; Free memory associated with pipe.
1516
; For UHCI, this includes usb_pipe structure and ErrorTD, if present.
1517
proc uhci_free_pipe
1518
        mov     eax, [esp+4]
3653 clevermous 1519
        mov     eax, [eax+uhci_pipe.ErrorTD-sizeof.uhci_pipe]
3520 clevermous 1520
        test    eax, eax
1521
        jz      @f
1522
        stdcall uhci_free_td, eax
1523
@@:
1524
        jmp     usb1_free_endpoint
1525
endp
1526
 
1527
; This procedure is called from the several places in main USB code
1528
; and allocates required packets for the given transfer stage.
1529
; ebx = pipe, other parameters are passed through the stack
1530
proc uhci_alloc_transfer stdcall uses edi, buffer:dword, size:dword, flags:dword, td:dword, direction:dword
1531
locals
1532
token           dd      ?
1533
origTD          dd      ?
1534
packetSize      dd      ?       ; must be the last variable, see usb_init_transfer
1535
endl
1536
; 1. [td] will be the first packet in the transfer.
1537
; Save it to allow unrolling if something will fail.
1538
        mov     eax, [td]
1539
        mov     [origTD], eax
1540
; In UHCI one TD describes one packet, transfers should be split into parts
1541
; with size <= endpoint max packet size.
1542
; 2. Get the maximum packet size for endpoint from uhci_pipe.Token
1543
; and generate Token field for TDs.
3653 clevermous 1544
        mov     edi, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
3520 clevermous 1545
        mov     eax, edi
1546
        shr     edi, 21
1547
        inc     edi
1548
; zero packet size (it will be set for every packet individually),
1549
; zero reserved bit 20,
1550
        and     eax, (1 shl 20) - 1
1551
        mov     [packetSize], edi
1552
; set the correct PID if it is different from the pipe-wide PID
1553
; (Data and Status stages of control transfers),
1554
        mov     ecx, [direction]
1555
        and     ecx, 3
1556
        jz      @f
1557
        mov     al, USB_PID_OUT
1558
        dec     ecx
1559
        jz      @f
1560
        mov     al, USB_PID_IN
1561
@@:
1562
; set the toggle bit for control transfers,
1563
        mov     ecx, [direction]
1564
        test    cl, 1 shl 3
1565
        jz      @f
1566
        and     ecx, 1 shl 2
1567
        and     eax, not (1 shl 19)
1568
        shl     ecx, 19-2
1569
        or      eax, ecx
1570
@@:
1571
; store the resulting Token in the stack variable.
1572
        mov     [token], eax
1573
; 3. While the remaining data cannot fit in one packet,
1574
; allocate full packets (of maximal possible size).
1575
.fullpackets:
1576
        cmp     [size], edi
1577
        jbe     .lastpacket
1578
        call    uhci_alloc_packet
1579
        test    eax, eax
1580
        jz      .fail
1581
        mov     [td], eax
1582
        add     [buffer], edi
1583
        sub     [size], edi
1584
        jmp     .fullpackets
1585
.lastpacket:
1586
; 4. The remaining data can fit in one packet;
1587
; allocate the last packet with size = size of remaining data.
1588
        mov     eax, [size]
1589
        mov     [packetSize], eax
1590
        call    uhci_alloc_packet
1591
        test    eax, eax
1592
        jz      .fail
1593
; 5. Clear 'short packets are not allowed' bit for the last packet,
1594
; if the caller requested this.
1595
; Note: even if the caller says that short transfers are ok,
1596
; all packets except the last one are marked as 'must be complete':
1597
; if one of them will be short, the software intervention is needed
1598
; to skip remaining packets; uhci_process_finalized_td will handle this
1599
; transparently to the caller.
1600
        test    [flags], 1
1601
        jz      @f
3653 clevermous 1602
        and     byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], not (1 shl (29-24))
1603
        and     byte [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], not 1
3520 clevermous 1604
@@:
1605
; 6. Update toggle bit in uhci_pipe structure from current value of [token].
1606
        mov     edx, [token]
3653 clevermous 1607
        xor     edx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
3520 clevermous 1608
        and     edx, 1 shl 19
3653 clevermous 1609
        xor     [ebx+uhci_pipe.Token-sizeof.uhci_pipe], edx
3520 clevermous 1610
.nothing:
1611
        ret
1612
.fail:
1613
        mov     edi, uhci_hardware_func
1614
        mov     eax, [td]
1615
        stdcall usb_undo_tds, [origTD]
1616
        xor     eax, eax
1617
        jmp     .nothing
1618
endp
1619
 
1620
; Helper procedure for uhci_alloc_transfer. Allocates one packet.
1621
proc uhci_alloc_packet
1622
; inherit some variables from the parent uhci_alloc_transfer
1623
virtual at ebp-12
1624
.token          dd      ?
1625
.origTD         dd      ?
1626
.packetSize     dd      ?
1627
                rd      2
1628
.buffer         dd      ?
1629
.transferSize   dd      ?
1630
.Flags          dd      ?
1631
.td             dd      ?
1632
.direction      dd      ?
1633
end virtual
1634
; 1. In UHCI all data for one packet must be on the same page.
1635
; Thus, if the given buffer splits page boundary, we need a temporary buffer
1636
; and code that transfers data between the given buffer and the temporary one.
1637
; 1a. There is no buffer for zero-length packets.
1638
        xor     eax, eax
1639
        cmp     [.packetSize], eax
1640
        jz      .notempbuf
1641
; 1b. A temporary buffer is not required if the first and the last bytes
1642
; of the given buffer are the same except lower 12 bits.
1643
        mov     edx, [.buffer]
1644
        add     edx, [.packetSize]
1645
        dec     edx
1646
        xor     edx, [.buffer]
1647
        test    edx, -0x1000
1648
        jz      .notempbuf
1649
; 1c. We need a temporary buffer. Allocate [packetSize]*2 bytes, so that
1650
; there must be [packetSize] bytes on one page,
1651
; plus space for a header uhci_original_buffer.
1652
        mov     eax, [.packetSize]
1653
        add     eax, eax
1654
        add     eax, sizeof.uhci_original_buffer
1655
        call    malloc
1656
; 1d. If failed, return zero.
1657
        test    eax, eax
1658
        jz      .nothing
1659
; 1e. Test whether [.packetSize] bytes starting from
1660
; eax + sizeof.uhci_original_buffer are in the same page.
1661
; If so, use eax + sizeof.uhci_original_buffer as a temporary buffer.
1662
; Otherwise, use the beginning of the next page as a temporary buffer
1663
; (since we have overallocated, sufficient space must remain).
1664
        lea     ecx, [eax+sizeof.uhci_original_buffer]
1665
        mov     edx, ecx
1666
        add     edx, [.packetSize]
1667
        dec     edx
1668
        xor     edx, ecx
1669
        test    edx, -0x1000
1670
        jz      @f
1671
        mov     ecx, eax
1672
        or      ecx, 0xFFF
1673
        inc     ecx
1674
@@:
1675
        mov     [eax+uhci_original_buffer.UsedBuffer], ecx
1676
        mov     ecx, [.buffer]
1677
        mov     [eax+uhci_original_buffer.OrigBuffer], ecx
1678
; 1f. For SETUP and OUT packets, copy data from the given buffer
1679
; to the temporary buffer now. For IN packets, data go in other direction
1680
; when the transaction completes.
1681
        cmp     byte [.token], USB_PID_IN
1682
        jz      .nocopy
1683
        push    esi edi
1684
        mov     esi, ecx
1685
        mov     edi, [eax+uhci_original_buffer.UsedBuffer]
1686
        mov     ecx, [.packetSize]
1687
        mov     edx, ecx
1688
        shr     ecx, 2
1689
        and     edx, 3
1690
        rep movsd
1691
        mov     ecx, edx
1692
        rep movsb
1693
        pop     edi esi
1694
.nocopy:
1695
.notempbuf:
1696
; 2. Allocate the next TD.
1697
        push    eax
1698
        call    usb1_allocate_general_td
1699
        pop     edx
1700
; If failed, free the temporary buffer (if it was allocated) and return zero.
1701
        test    eax, eax
1702
        jz      .fail
1703
; 3. Initialize controller-independent parts of both TDs.
1704
        push    edx
1705
        call    usb_init_transfer
1706
; 4. Initialize the next TD:
1707
; mark it as last one (this will be changed when further packets will be
1708
; allocated), copy Token field from uhci_pipe.Token zeroing bit 20,
1709
; generate ControlStatus field, mark as Active
3699 clevermous 1710
; (for last descriptor, this will be changed by uhci_insert_transfer),
1711
; zero OrigBufferInfo (otherwise uhci_free_td would try to free it).
1712
        and     [eax+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 0
3653 clevermous 1713
        mov     [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 1  ; no next TD
1714
        mov     edx, [ebx+uhci_pipe.Token-sizeof.uhci_pipe]
1715
        mov     [eax+uhci_gtd.Token-sizeof.uhci_gtd], edx
1716
        and     byte [eax+uhci_gtd.Token+2-sizeof.uhci_gtd], not (1 shl (20-16))
3520 clevermous 1717
        and     edx, 1 shl 20
1718
        shl     edx, 6
1719
        or      edx, UHCI_INVALID_LENGTH + (1 shl 23) + (3 shl 27)
1720
                ; not processed, active, allow 3 errors
3653 clevermous 1721
        mov     [eax+uhci_gtd.ControlStatus-sizeof.uhci_gtd], edx
3520 clevermous 1722
; 5. Initialize remaining fields of the current TD.
1723
; 5a. Store pointer to the buffer allocated in step 1 (or zero).
3653 clevermous 1724
        pop     [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
3520 clevermous 1725
; 5b. Store physical address of the next TD.
1726
        push    eax
3653 clevermous 1727
        sub     eax, sizeof.uhci_gtd
3520 clevermous 1728
        call    get_phys_addr
3656 clevermous 1729
; for Control/Bulk pipes, use Depth traversal unless this is the first TD
1730
; in the transfer stage;
3520 clevermous 1731
; uhci_insert_transfer will set Depth traversal for the first TD and clear
1732
; it in the last TD
3656 clevermous 1733
        test    [ebx+usb_pipe.Type], 1
1734
        jnz     @f
3520 clevermous 1735
        cmp     ecx, [ebx+usb_pipe.LastTD]
1736
        jz      @f
1737
        or      eax, 4
1738
@@:
3653 clevermous 1739
        mov     [ecx+uhci_gtd.NextTD-sizeof.uhci_gtd], eax
3520 clevermous 1740
; 5c. Store physical address of the buffer: zero if no data present,
1741
; the temporary buffer if it was allocated, the given buffer otherwise.
1742
        xor     eax, eax
1743
        cmp     [.packetSize], eax
1744
        jz      .hasphysbuf
1745
        mov     eax, [.buffer]
3653 clevermous 1746
        mov     edx, [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
3520 clevermous 1747
        test    edx, edx
1748
        jz      @f
1749
        mov     eax, [edx+uhci_original_buffer.UsedBuffer]
1750
@@:
1751
        call    get_phys_addr
1752
.hasphysbuf:
3653 clevermous 1753
        mov     [ecx+uhci_gtd.Buffer-sizeof.uhci_gtd], eax
3520 clevermous 1754
; 5d. For IN transfers, disallow short packets.
1755
; This will be overridden, if needed, by uhci_alloc_transfer.
1756
        mov     eax, [.token]
1757
        mov     edx, [.packetSize]
1758
        dec     edx
1759
        cmp     al, USB_PID_IN
1760
        jnz     @f
3653 clevermous 1761
        or      byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (29-24)        ; disallow short packets
1762
        or      byte [ecx+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd], 1
3520 clevermous 1763
@@:
1764
; 5e. Get Token field: combine [.token] with [.packetSize].
1765
        shl     edx, 21
1766
        or      edx, eax
3653 clevermous 1767
        mov     [ecx+uhci_gtd.Token-sizeof.uhci_gtd], edx
3520 clevermous 1768
; 6. Flip toggle bit in [.token].
1769
        xor     eax, 1 shl 19
1770
        mov     [.token], eax
1771
; 7. Return pointer to the next TD.
1772
        pop     eax
1773
.nothing:
1774
        ret
1775
.fail:
1776
        xchg    eax, edx
1777
        call    free
1778
        xor     eax, eax
1779
        ret
1780
endp
1781
 
1782
; This procedure is called from the several places in main USB code
1783
; and activates the transfer which was previously allocated by
1784
; uhci_alloc_transfer.
1785
; ecx -> last descriptor for the transfer, ebx -> usb_pipe
1786
proc uhci_insert_transfer
1787
;       DEBUGF 1,'K : uhci_insert_transfer: eax=%x, ecx=%x, [esp+4]=%x\n',eax,ecx,[esp+4]
3653 clevermous 1788
        and     byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], not (1 shl (23-16))  ; clear Active bit
1789
        or      byte [ecx+uhci_gtd.ControlStatus+3-sizeof.uhci_gtd], 1 shl (24-24)        ; set InterruptOnComplete bit
3520 clevermous 1790
        mov     eax, [esp+4]
3653 clevermous 1791
        or      byte [eax+uhci_gtd.ControlStatus+2-sizeof.uhci_gtd], 1 shl (23-16)        ; set Active bit
3656 clevermous 1792
        test    [ebx+usb_pipe.Type], 1
1793
        jnz     @f
3653 clevermous 1794
        or      byte [eax+uhci_gtd.NextTD-sizeof.uhci_gtd], 4     ; set Depth bit
3656 clevermous 1795
@@:
3520 clevermous 1796
        ret
1797
endp
1798
 
1799
; Free all memory associated with one TD.
1800
; For UHCI, this includes memory for uhci_gtd itself
1801
; and the temporary buffer, if present.
1802
proc uhci_free_td
1803
        mov     eax, [esp+4]
3653 clevermous 1804
        mov     eax, [eax+uhci_gtd.OrigBufferInfo-sizeof.uhci_gtd]
3520 clevermous 1805
        and     eax, not 1
1806
        jz      .nobuf
1807
        push    ebx
1808
        call    free
1809
        pop     ebx
1810
.nobuf:
3653 clevermous 1811
        sub     dword [esp+4], sizeof.uhci_gtd
3520 clevermous 1812
        jmp     usb_free_common
1813
endp