Subversion Repositories Kolibri OS

Rev

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