Subversion Repositories Kolibri OS

Rev

Rev 3826 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3826 Rev 4418
Line 8... Line 8...
8
;  * for every millisecond, take all bandwidth scheduled to periodic transfers,
8
;  * for every millisecond, take all bandwidth scheduled to periodic transfers,
9
;  * calculate maximum over all milliseconds,
9
;  * calculate maximum over all milliseconds,
10
;  * select a variant which minimizes that maximum;
10
;  * select a variant which minimizes that maximum;
11
; when removing a pipe, do nothing (except for bookkeeping).
11
; when removing a pipe, do nothing (except for bookkeeping).
Line 12... Line 12...
12
 
12
 
-
 
13
; The caller must provide CONTROLLER_NAME define.
-
 
14
macro define_controller_name name
13
; sanity check: structures in UHCI and OHCI should be the same
15
{
-
 
16
_hci_static_ep.SoftwarePart = name # _static_ep.SoftwarePart
-
 
17
_hci_static_ep.NextList = name # _static_ep.NextList
-
 
18
sizeof._hci_static_ep = sizeof. # name # _static_ep
-
 
19
}
14
if (sizeof.ohci_static_ep=sizeof.uhci_static_ep)&(ohci_static_ep.SoftwarePart=uhci_static_ep.SoftwarePart)&(ohci_static_ep.NextList=uhci_static_ep.NextList)
20
 
15
; Select a list for a new pipe.
21
; Select a list for a new pipe.
16
; in: esi -> usb_controller, maxpacket, type, interval can be found in the stack
22
; in: esi -> usb_controller, maxpacket, type, interval can be found in the stack
17
; in: ecx = 2 * maximal interval = total number of periodic lists + 1
23
; in: ecx = 2 * maximal interval = total number of periodic lists + 1
18
; in: edx -> {u|o}hci_static_ep for the first list
24
; in: edx -> {u|o}hci_static_ep for the first list
Line 63... Line 69...
63
; * the outermost loop checks all variants.
69
; * the outermost loop checks all variants.
64
; 2. Calculate offset between the first list and the first list for the
70
; 2. Calculate offset between the first list and the first list for the
65
; selected interval, in bytes; save in the stack for step 4.
71
; selected interval, in bytes; save in the stack for step 4.
66
        sub     eax, ecx
72
        sub     eax, ecx
67
        sub     eax, ecx
73
        sub     eax, ecx
68
        imul    eax, sizeof.ohci_static_ep
74
        imul    eax, sizeof._hci_static_ep
69
        push    eax
75
        push    eax
70
        imul    ebx, ecx, sizeof.ohci_static_ep
76
        imul    ebx, ecx, sizeof._hci_static_ep
71
; 3. Select the best variant.
77
; 3. Select the best variant.
72
; 3a. The outermost loop.
78
; 3a. The outermost loop.
73
; Prepare for the loop: set the current optimal bandwidth to maximum
79
; Prepare for the loop: set the current optimal bandwidth to maximum
74
; possible value (so that any variant will pass the first comparison),
80
; possible value (so that any variant will pass the first comparison),
75
; calculate delta for the intermediate loop.
81
; calculate delta for the intermediate loop.
Line 88... Line 94...
88
.calc_max_bandwidth:
94
.calc_max_bandwidth:
89
; 3c. The innermost loop. Sum over all lists.
95
; 3c. The innermost loop. Sum over all lists.
90
        xor     eax, eax
96
        xor     eax, eax
91
        push    edx
97
        push    edx
92
.calc_bandwidth:
98
.calc_bandwidth:
93
        add     eax, [edx+ohci_static_ep.SoftwarePart+usb_static_ep.Bandwidth]
99
        add     eax, [edx+_hci_static_ep.SoftwarePart+usb_static_ep.Bandwidth]
94
        mov     edx, [edx+ohci_static_ep.NextList]
100
        mov     edx, [edx+_hci_static_ep.NextList]
95
        test    edx, edx
101
        test    edx, edx
96
        jnz     .calc_bandwidth
102
        jnz     .calc_bandwidth
97
        pop     edx
103
        pop     edx
98
; 3d. The intermediate loop continued: update maximum.
104
; 3d. The intermediate loop continued: update maximum.
99
        cmp     eax, edi
105
        cmp     eax, edi
Line 113... Line 119...
113
        ja      @f
119
        ja      @f
114
        mov     [.bandwidth], edi
120
        mov     [.bandwidth], edi
115
        mov     [.target], edx
121
        mov     [.target], edx
116
@@:
122
@@:
117
; 3g. The outermost loop continued: advance counter.
123
; 3g. The outermost loop continued: advance counter.
118
        add     edx, sizeof.ohci_static_ep
124
        add     edx, sizeof._hci_static_ep
119
        dec     ecx
125
        dec     ecx
120
        jnz     .varloop
126
        jnz     .varloop
121
; 4. Calculate bandwidth for the new pipe.
127
; 4. Calculate bandwidth for the new pipe.
122
        mov     eax, [.maxpacket]
128
        mov     eax, [.maxpacket]
123
        mov     cl, [.speed]
129
        mov     cl, [.speed]
Line 133... Line 139...
133
        mov     ecx, eax
139
        mov     ecx, eax
134
        add     ecx, [.bandwidth]
140
        add     ecx, [.bandwidth]
135
        cmp     ecx, 10800
141
        cmp     ecx, 10800
136
        ja      .no_bandwidth
142
        ja      .no_bandwidth
137
; 7. Convert {o|u}hci_static_ep to usb_static_ep, update bandwidth and return.
143
; 7. Convert {o|u}hci_static_ep to usb_static_ep, update bandwidth and return.
138
        add     edx, ohci_static_ep.SoftwarePart
144
        add     edx, _hci_static_ep.SoftwarePart
139
        add     [edx+usb_static_ep.Bandwidth], eax
145
        add     [edx+usb_static_ep.Bandwidth], eax
140
        pop     edi ebx         ; restore used registers to be stdcall
146
        pop     edi ebx         ; restore used registers to be stdcall
141
        ret
147
        ret
142
.no_bandwidth:
148
.no_bandwidth:
143
        dbgstr 'Periodic bandwidth limit reached'
149
        dbgstr 'Periodic bandwidth limit reached'
144
        xor     edx, edx
150
        xor     edx, edx
145
        pop     edi ebx
151
        pop     edi ebx
146
        ret
152
        ret
147
endp
153
endp
148
; sanity check, part 2
-
 
149
else
-
 
150
.err select_interrupt_list must be different for UHCI and OHCI
-
 
151
end if
-
 
Line 152... Line 154...
152
 
154
 
153
; Pipe is removing, update the corresponding lists.
155
; Pipe is removing, update the corresponding lists.
154
; We do not reorder anything, so just update book-keeping variable
156
; We do not reorder anything, so just update book-keeping variable
155
; in the list header.
157
; in the list header.
Line 226... Line 228...
226
; 16 bits for PRE packet, 4 bits for hub delay, 8*20 bits for Handshake packet,
228
; 16 bits for PRE packet, 4 bits for hub delay, 8*20 bits for Handshake packet,
227
; 8*2 bits for another inter-packet delay.
229
; 8*2 bits for another inter-packet delay.
228
        lea     eax, [ecx+edx+778]
230
        lea     eax, [ecx+edx+778]
229
        ret
231
        ret
230
endp
232
endp
231
 
-
 
232
; USB2 scheduler.
-
 
233
; There are two parts: high-speed pipes and split-transaction pipes.
-
 
234
;
-
 
235
; High-speed scheduler uses the same algorithm as USB1 scheduler:
-
 
236
; when adding a pipe, optimize the following quantity:
-
 
237
;  * for every microframe, take all bandwidth scheduled to periodic transfers,
-
 
238
;  * calculate maximum over all microframes,
-
 
239
;  * select a variant which minimizes that maximum;
-
 
240
;  * if there are several such variants,
-
 
241
;    prefer those that are closer to end of frame
-
 
242
;    to minimize collisions with split transactions;
-
 
243
; when removing a pipe, do nothing (except for bookkeeping).
-
 
244
; in: esi -> usb_controller
-
 
245
; out: edx -> usb_static_ep, eax = S-Mask
-
 
246
proc ehci_select_hs_interrupt_list
-
 
247
; inherit some variables from usb_open_pipe
-
 
248
virtual at ebp-12
-
 
249
.targetsmask    dd      ?
-
 
250
.bandwidth      dd      ?
-
 
251
.target         dd      ?
-
 
252
                dd      ?
-
 
253
                dd      ?
-
 
254
.config_pipe    dd      ?
-
 
255
.endpoint       dd      ?
-
 
256
.maxpacket      dd      ?
-
 
257
.type           dd      ?
-
 
258
.interval       dd      ?
-
 
259
end virtual
-
 
260
; prolog, initialize local vars
-
 
261
        or      [.bandwidth], -1
-
 
262
        or      [.target], -1
-
 
263
        or      [.targetsmask], -1
-
 
264
        push    ebx edi         ; save used registers to be stdcall
-
 
265
; 1. In EHCI, every list describes one millisecond = 8 microframes.
-
 
266
; Thus, there are two significantly different branches:
-
 
267
; for pipes with interval >= 8 microframes, advance to 2,
-
 
268
; for pipes which should be planned in every frame (one or more microframes),
-
 
269
; go to 9.
-
 
270
; Note: the actual interval for high-speed devices is 2^([.interval]-1),
-
 
271
; (the core specification forbids [.interval] == 0)
-
 
272
        mov     ecx, [.interval]
-
 
273
        dec     ecx
-
 
274
        cmp     ecx, 3
-
 
275
        jb      .every_frame
-
 
276
; 2. Determine the actual interval in milliseconds.
-
 
277
        sub     ecx, 3
-
 
278
        cmp     ecx, 5  ; maximum 32ms
-
 
279
        jbe     @f
-
 
280
        movi    ecx, 5
-
 
281
@@:
-
 
282
; There are four nested loops,
-
 
283
; * Loop #4 (the innermost one) calculates the total periodic bandwidth
-
 
284
;   scheduled in the given microframe of the given millisecond.
-
 
285
; * Loop #3 calculates the maximum over all milliseconds
-
 
286
;   in the given variant, that is the quantity we're trying to minimize.
-
 
287
; * Loops #1 and #2 check all variants;
-
 
288
;   loop #1 is responsible for the target millisecond,
-
 
289
;   loop #2 is responsible for the microframe within millisecond.
-
 
290
; 3. Prepare for loops.
-
 
291
; ebx = number of iterations of loop #1
-
 
292
; [esp] = delta of counter for loop #3, in bytes
-
 
293
; [esp+4] = delta between the first group and the target group, in bytes
-
 
294
        movi    ebx, 1
-
 
295
        movi    edx, sizeof.ehci_static_ep
-
 
296
        shl     ebx, cl
-
 
297
        shl     edx, cl
-
 
298
        mov     eax, 64*sizeof.ehci_static_ep
-
 
299
        sub     eax, edx
-
 
300
        sub     eax, edx
-
 
301
        push    eax
-
 
302
        push    edx
-
 
303
; 4. Select the best variant.
-
 
304
; 4a. Loop #1: initialize counter = pointer to ehci_static_ep for
-
 
305
; the target millisecond in the first group.
-
 
306
        lea     edx, [esi+ehci_controller.IntEDs-sizeof.ehci_controller]
-
 
307
.varloop0:
-
 
308
; 4b. Loop #2: initialize counter = microframe within the target millisecond.
-
 
309
        xor     ecx, ecx
-
 
310
.varloop:
-
 
311
; 4c. Loop #3: save counter of loop #1,
-
 
312
; initialize counter with the value of loop #1 counter,
-
 
313
; initialize maximal bandwidth = zero.
-
 
314
        xor     edi, edi
-
 
315
        push    edx
-
 
316
virtual at esp
-
 
317
.saved_counter1         dd      ?       ; step 4c
-
 
318
.loop3_delta            dd      ?       ; step 3
-
 
319
.target_delta           dd      ?       ; step 3
-
 
320
end virtual
-
 
321
.calc_max_bandwidth:
-
 
322
; 4d. Loop #4: initialize counter with the value of loop #3 counter,
-
 
323
; initialize total bandwidth = zero.
-
 
324
        xor     eax, eax
-
 
325
        push    edx
-
 
326
.calc_bandwidth:
-
 
327
; 4e. Loop #4: add the bandwidth from the current list
-
 
328
; and advance to the next list, while there is one.
-
 
329
        add     ax, [edx+ehci_static_ep.Bandwidths+ecx*2]
-
 
330
        mov     edx, [edx+ehci_static_ep.NextList]
-
 
331
        test    edx, edx
-
 
332
        jnz     .calc_bandwidth
-
 
333
; 4f. Loop #4 end: restore counter of loop #3.
-
 
334
        pop     edx
-
 
335
; 4g. Loop #3: update maximal bandwidth.
-
 
336
        cmp     eax, edi
-
 
337
        jb      @f
-
 
338
        mov     edi, eax
-
 
339
@@:
-
 
340
; 4h. Loop #3: advance the counter and repeat while within the first group.
-
 
341
        lea     eax, [esi+ehci_controller.IntEDs+32*sizeof.ehci_static_ep-sizeof.ehci_controller]
-
 
342
        add     edx, [.loop3_delta]
-
 
343
        cmp     edx, eax
-
 
344
        jb      .calc_max_bandwidth
-
 
345
; 4i. Loop #3 end: restore counter of loop #1.
-
 
346
        pop     edx
-
 
347
; 4j. Loop #2: if the current variant is better (maybe not strictly)
-
 
348
; then the previous optimum, update the optimal bandwidth and the target.
-
 
349
        cmp     edi, [.bandwidth]
-
 
350
        ja      @f
-
 
351
        jb      .update
-
 
352
        cmp     ecx, [.targetsmask]
-
 
353
        jb      @f
-
 
354
.update:
-
 
355
        mov     [.bandwidth], edi
-
 
356
        mov     [.target], edx
-
 
357
        mov     [.targetsmask], ecx
-
 
358
@@:
-
 
359
; 4k. Loop #2: continue 8 times for every microframe.
-
 
360
        inc     ecx
-
 
361
        cmp     ecx, 8
-
 
362
        jb      .varloop
-
 
363
; 4l. Loop #1: advance counter and repeat ebx times,
-
 
364
; ebx was calculated in step 3.
-
 
365
        add     edx, sizeof.ehci_static_ep
-
 
366
        dec     ebx
-
 
367
        jnz     .varloop0
-
 
368
; 5. Calculate bandwidth for the new pipe.
-
 
369
        mov     eax, [.maxpacket]
-
 
370
        call    calc_hs_bandwidth
-
 
371
        mov     ecx, [.maxpacket]
-
 
372
        shr     ecx, 11
-
 
373
        inc     ecx
-
 
374
        and     ecx, 3
-
 
375
        imul    eax, ecx
-
 
376
; 6. Get the pointer to the best list.
-
 
377
        pop     edx             ; restore value from step 3
-
 
378
        pop     edx             ; get delta calculated in step 3
-
 
379
        add     edx, [.target]
-
 
380
; 7. Check that bandwidth for the new pipe plus old bandwidth
-
 
381
; still fits to maximum allowed by the core specification
-
 
382
; current [.bandwidth] + new bandwidth <= limit;
-
 
383
; USB2 specification allows maximum 60000*80% bit times for periodic microframe
-
 
384
        mov     ecx, [.bandwidth]
-
 
385
        add     ecx, eax
-
 
386
        cmp     ecx, 48000
-
 
387
        ja      .no_bandwidth
-
 
388
; 8. Convert {o|u}hci_static_ep to usb_static_ep, update bandwidth and return.
-
 
389
        mov     ecx, [.targetsmask]
-
 
390
        add     [edx+ehci_static_ep.Bandwidths+ecx*2], ax
-
 
391
        add     edx, ehci_static_ep.SoftwarePart
-
 
392
        movi    eax, 1
-
 
393
        shl     eax, cl
-
 
394
        pop     edi ebx         ; restore used registers to be stdcall
-
 
395
        ret
-
 
396
.no_bandwidth:
-
 
397
        dbgstr 'Periodic bandwidth limit reached'
-
 
398
        xor     eax, eax
-
 
399
        xor     edx, edx
-
 
400
        pop     edi ebx
-
 
401
        ret
-
 
402
.every_frame:
-
 
403
; The pipe should be scheduled every frame in two or more microframes.
-
 
404
; 9. Calculate maximal bandwidth for every microframe: three nested loops.
-
 
405
; 9a. The outermost loop: ebx = microframe to calculate.
-
 
406
        xor     ebx, ebx
-
 
407
.calc_all_bandwidths:
-
 
408
; 9b. The intermediate loop:
-
 
409
; edx = pointer to ehci_static_ep in the first group, [esp] = counter,
-
 
410
; edi = maximal bandwidth
-
 
411
        lea     edx, [esi+ehci_controller.IntEDs-sizeof.ehci_controller]
-
 
412
        xor     edi, edi
-
 
413
        push    32
-
 
414
.calc_max_bandwidth2:
-
 
415
; 9c. The innermost loop: calculate bandwidth for the given microframe
-
 
416
; in the given frame.
-
 
417
        xor     eax, eax
-
 
418
        push    edx
-
 
419
.calc_bandwidth2:
-
 
420
        add     ax, [edx+ehci_static_ep.Bandwidths+ebx*2]
-
 
421
        mov     edx, [edx+ehci_static_ep.NextList]
-
 
422
        test    edx, edx
-
 
423
        jnz     .calc_bandwidth2
-
 
424
        pop     edx
-
 
425
; 9d. The intermediate loop continued: update maximal bandwidth.
-
 
426
        cmp     eax, edi
-
 
427
        jb      @f
-
 
428
        mov     edi, eax
-
 
429
@@:
-
 
430
        add     edx, sizeof.ehci_static_ep
-
 
431
        dec     dword [esp]
-
 
432
        jnz     .calc_max_bandwidth2
-
 
433
        pop     eax
-
 
434
; 9e. Push the calculated maximal bandwidth and continue the outermost loop.
-
 
435
        push    edi
-
 
436
        inc     ebx
-
 
437
        cmp     ebx, 8
-
 
438
        jb      .calc_all_bandwidths
-
 
439
virtual at esp
-
 
440
.bandwidth7     dd      ?
-
 
441
.bandwidth6     dd      ?
-
 
442
.bandwidth5     dd      ?
-
 
443
.bandwidth4     dd      ?
-
 
444
.bandwidth3     dd      ?
-
 
445
.bandwidth2     dd      ?
-
 
446
.bandwidth1     dd      ?
-
 
447
.bandwidth0     dd      ?
-
 
448
end virtual
-
 
449
; 10. Select the best variant.
-
 
450
; edx = S-Mask = bitmask of scheduled microframes
-
 
451
        movi    edx, 0x11
-
 
452
        cmp     ecx, 1
-
 
453
        ja      @f
-
 
454
        mov     dl, 0x55
-
 
455
        jz      @f
-
 
456
        mov     dl, 0xFF
-
 
457
@@:
-
 
458
; try all variants edx, edx shl 1, edx shl 2, ...
-
 
459
; while they fit in the lower byte (8 microframes per frame)
-
 
460
.select_best_mframe:
-
 
461
        xor     edi, edi
-
 
462
        mov     ecx, edx
-
 
463
        mov     eax, esp
-
 
464
.calc_mframe:
-
 
465
        add     cl, cl
-
 
466
        jnc     @f
-
 
467
        cmp     edi, [eax]
-
 
468
        jae     @f
-
 
469
        mov     edi, [eax]
-
 
470
@@:
-
 
471
        add     eax, 4
-
 
472
        test    cl, cl
-
 
473
        jnz     .calc_mframe
-
 
474
        cmp     [.bandwidth], edi
-
 
475
        jb      @f
-
 
476
        mov     [.bandwidth], edi
-
 
477
        mov     [.targetsmask], edx
-
 
478
@@:
-
 
479
        add     dl, dl
-
 
480
        jnc     .select_best_mframe
-
 
481
; 11. Restore stack after step 9.
-
 
482
        add     esp, 8*4
-
 
483
; 12. Get the pointer to the target list (responsible for every microframe).
-
 
484
        lea     edx, [esi+ehci_controller.IntEDs.SoftwarePart+62*sizeof.ehci_static_ep-sizeof.ehci_controller]
-
 
485
; 13. Calculate bandwidth on the bus.
-
 
486
        mov     eax, [.maxpacket]
-
 
487
        call    calc_hs_bandwidth
-
 
488
        mov     ecx, [.maxpacket]
-
 
489
        shr     ecx, 11
-
 
490
        inc     ecx
-
 
491
        and     ecx, 3
-
 
492
        imul    eax, ecx
-
 
493
; 14. Check that current [.bandwidth] + new bandwidth <= limit;
-
 
494
; USB2 specification allows maximum 60000*80% bit times for periodic microframe.
-
 
495
        mov     ecx, [.bandwidth]
-
 
496
        add     ecx, eax
-
 
497
        cmp     ecx, 48000
-
 
498
        ja      .no_bandwidth
-
 
499
; 15. Update bandwidths including the new pipe.
-
 
500
        mov     ecx, [.targetsmask]
-
 
501
        lea     edi, [edx+ehci_static_ep.Bandwidths-ehci_static_ep.SoftwarePart]
-
 
502
.update_bandwidths:
-
 
503
        shr     ecx, 1
-
 
504
        jnc     @f
-
 
505
        add     [edi], ax
-
 
506
@@:
-
 
507
        add     edi, 2
-
 
508
        test    ecx, ecx
-
 
509
        jnz     .update_bandwidths
-
 
510
; 16. Return target list and target S-Mask.
-
 
511
        mov     eax, [.targetsmask]
-
 
512
        pop     edi ebx         ; restore used registers to be stdcall
-
 
513
        ret
-
 
514
endp
-
 
515
 
-
 
516
; Pipe is removing, update the corresponding lists.
-
 
517
; We do not reorder anything, so just update book-keeping variable
-
 
518
; in the list header.
-
 
519
proc ehci_hs_interrupt_list_unlink
-
 
520
        movzx   eax, word [ebx+ehci_pipe.Token-sizeof.ehci_pipe+2]
-
 
521
; calculate bandwidth
-
 
522
        call    calc_hs_bandwidth
-
 
523
        mov     ecx, [ebx+ehci_pipe.Flags-sizeof.ehci_pipe]
-
 
524
        shr     ecx, 30
-
 
525
        imul    eax, ecx
-
 
526
        movzx   ecx, byte [ebx+ehci_pipe.Flags-sizeof.ehci_pipe]
-
 
527
; get target list
-
 
528
        mov     edx, [ebx+ehci_pipe.BaseList-sizeof.ehci_pipe]
-
 
529
; update bandwidth
-
 
530
.dec_bandwidth:
-
 
531
        shr     ecx, 1
-
 
532
        jnc     @f
-
 
533
        sub     word [edx+ehci_static_ep.Bandwidths - ehci_static_ep.SoftwarePart], ax
-
 
534
@@:
-
 
535
        add     edx, 2
-
 
536
        test    ecx, ecx
-
 
537
        jnz     .dec_bandwidth
-
 
538
; return
-
 
539
        ret
-
 
540
endp
-
 
541
 
-
 
542
; Helper procedure for USB2 scheduler: calculate bandwidth on the bus.
-
 
543
; in: low 11 bits of eax = payload size in bytes
-
 
544
; out: eax = maximal bandwidth in HS-bits
-
 
545
proc calc_hs_bandwidth
-
 
546
        and     eax, (1 shl 11) - 1     ; get payload for one transaction
-
 
547
        add     eax, 3  ; add 3 bytes for other fields in data packet, PID+CRC16
-
 
548
; Multiply by 8 for bytes -> bits and then by 7/6 to accomodate bit stuffing;
-
 
549
; total 28/3 = 9+1/3
-
 
550
        mov     edx, 55555556h
-
 
551
        lea     ecx, [eax*9]
-
 
552
        mul     edx
-
 
553
; Add 989 extra bits: 68 bits for Token packet (32 for SYNC, 24 for token+address,
-
 
554
; 4 extra bits for possible bit stuffing in token+address, 8 for EOP),
-
 
555
; 736 bits for bus turn-around, 40 bits for SYNC+EOP in Data packet,
-
 
556
; 8 bits for inter-packet delay, 49 bits for Handshake packet,
-
 
557
; 88 bits for another inter-packet delay.
-
 
558
        lea     eax, [ecx+edx+989]
-
 
559
        ret
-
 
560
endp
-
 
561
 
-
 
562
; Split-transaction scheduler (aka TT scheduler, TT stands for Transaction
-
 
563
; Translator, section 11.14 of the core spec) needs to schedule three event
-
 
564
; types on two buses: Start-Split and Complete-Split on HS bus and normal
-
 
565
; transaction on FS/LS bus.
-
 
566
; Assume that FS/LS bus is more restricted and more important to be scheduled
-
 
567
; uniformly, so select the variant which minimizes maximal used bandwidth
-
 
568
; on FS/LS bus and does not overflow HS bus.
-
 
569
; If there are several such variants, prefer variants which is closest to
-
 
570
; start of frame, and within the same microframe consider HS bandwidth
-
 
571
; utilization as a last criteria.
-
 
572
 
-
 
573
; The procedure ehci_select_tt_interrupt_list has been splitted into several
-
 
574
; macro, each representing a logical step of the procedure,
-
 
575
; to simplify understanding what is going on. Consider all the following macro
-
 
576
; as logical parts of one procedure, they are meaningless outside the context.
-
 
577
 
-
 
578
; Given a frame, calculate bandwidth occupied by already opened pipes
-
 
579
; in every microframe.
-
 
580
; Look for both HS and FS/LS buses: there are 16 words of information,
-
 
581
; 8 for HS bus, 8 for FS/LS bus, for every microframe.
-
 
582
; Since we count already opened pipes, the total bandwidth in every microframe
-
 
583
; is less than 60000 bits (and even 60000*80% bits), otherwise the scheduler
-
 
584
; would not allow to open those pipes.
-
 
585
; edi -> first list for the frame
-
 
586
macro tt_calc_bandwidth_in_frame
-
 
587
{
-
 
588
local .lists, .pipes, .pipes_done, .carry
-
 
589
; 1. Zero everything.
-
 
590
        xor     eax, eax
-
 
591
        mov     edx, edi
-
 
592
repeat 4
-
 
593
        mov     dword [.budget+(%-1)*4], eax
-
 
594
end repeat
-
 
595
repeat 4
-
 
596
        mov     dword [.hs_bandwidth+(%-1)*4], eax
-
 
597
end repeat
-
 
598
        mov     [.total_budget], ax
-
 
599
; Loop over all lists for the given frame.
-
 
600
.lists:
-
 
601
; 2. Total HS bandwidth for all pipes in one list is kept inside list header,
-
 
602
; add it. Note that overflow is impossible, so we may add entire dwords.
-
 
603
        mov     ebx, [edx+ehci_static_ep.SoftwarePart+usb_static_ep.NextVirt]
-
 
604
repeat 4
-
 
605
        mov     eax, dword [edx+ehci_static_ep.Bandwidths+(%-1)*4]
-
 
606
        add     dword [.hs_bandwidth+(%-1)*4], eax
-
 
607
end repeat
-
 
608
; Loop over all pipes in the given list.
-
 
609
        add     edx, ehci_static_ep.SoftwarePart
-
 
610
.pipes:
-
 
611
        cmp     ebx, edx
-
 
612
        jz      .pipes_done
-
 
613
; 3. For every pipe in every list for the given frame:
-
 
614
; 3a. Check whether the pipe resides on the same FS/LS bus as the new pipe.
-
 
615
; If not, skip this pipe.
-
 
616
        mov     eax, [ebx+usb_pipe.DeviceData]
-
 
617
        mov     eax, [eax+usb_device_data.TTHub]
-
 
618
        cmp     eax, [.tthub]
-
 
619
        jnz     @f
-
 
620
; 3b. Calculate FS/LS budget for the opened pipe.
-
 
621
; Note that eax = TTHub after 3a.
-
 
622
        call    tt_calc_budget
-
 
623
; 3c. Update total budget: add the value from 3b
-
 
624
; to the budget of the first microframe scheduled for this pipe.
-
 
625
        bsf     ecx, [ebx+ehci_pipe.Flags-sizeof.ehci_pipe]
-
 
626
        add     [.budget+ecx*2], ax
-
 
627
@@:
-
 
628
        mov     ebx, [ebx+usb_pipe.NextVirt]
-
 
629
        jmp     .pipes
-
 
630
.pipes_done:
-
 
631
        mov     edx, [edx+ehci_static_ep.NextList-ehci_static_ep.SoftwarePart]
-
 
632
        test    edx, edx
-
 
633
        jnz     .lists
-
 
634
; 4. If the budget for some microframe is exceeded, carry it to the following
-
 
635
; microframe(s). The actual size of one microframe is 187.5 raw bytes;
-
 
636
; the core spec says that 188 bytes should be scheduled in every microframe.
-
 
637
        xor     eax, eax
-
 
638
        xor     ecx, ecx
-
 
639
.carry:
-
 
640
        xor     edx, edx
-
 
641
        add     ax, [.budget+ecx*2]
-
 
642
        cmp     ax, 188
-
 
643
        jbe     @f
-
 
644
        mov     dx, ax
-
 
645
        mov     ax, 188
-
 
646
        sub     dx, ax
-
 
647
@@:
-
 
648
        mov     [.budget+ecx*2], ax
-
 
649
        add     [.total_budget], ax
-
 
650
        mov     ax, dx
-
 
651
        inc     ecx
-
 
652
        cmp     ecx, 8
-
 
653
        jb      .carry
-
 
654
}
-
 
655
 
-
 
656
; Checks whether the new pipe fits in the existing FS budget
-
 
657
; starting from the given microframe. If not, mark the microframe
-
 
658
; as impossible for scheduling.
-
 
659
; in: ecx = microframe
-
 
660
macro tt_exclude_microframe_if_no_budget
-
 
661
{
-
 
662
local .loop, .good, .bad
-
 
663
; 1. If the new budget plus the current budget does not exceed 188 bytes,
-
 
664
; the variant is possible.
-
 
665
        mov     ax, [.budget+ecx*2]
-
 
666
        mov     edx, ecx
-
 
667
        add     ax, [.new_budget]
-
 
668
        sub     ax, 188
-
 
669
        jbe     .good
-
 
670
; 2. Otherwise,
-
 
671
; a) nothing should be scheduled in some following microframes,
-
 
672
; b) after adding the new budget everything should fit in first 6 microframes,
-
 
673
;    this guarantees that even in the worst case 90% limit is satisfied.
-
 
674
.loop:
-
 
675
        cmp     edx, 5
-
 
676
        jae     .bad
-
 
677
        cmp     [.budget+(edx+1)*2], 0
-
 
678
        jnz     .bad
-
 
679
        inc     edx
-
 
680
        sub     ax, 188
-
 
681
        ja      .loop
-
 
682
.bad:
-
 
683
        btr     [.possible_microframes], ecx
-
 
684
.good:
-
 
685
}
-
 
686
 
-
 
687
; Calculate data corresponding to the particular scheduling variant for the new pipe.
-
 
688
; Data describe the current scheduling state collected over all frames touched
-
 
689
; by the given variant: maximal HS bandwidth, maximal FS/LS budget,
-
 
690
; which microframes fit in the current FS/LS budget for all frames.
-
 
691
macro tt_calc_statistics_for_one_variant
-
 
692
{
-
 
693
local .frames, .microframes
-
 
694
; 1. Initialize: zero maximal bandwidth,
-
 
695
; first 6 microframes are possible for scheduling.
-
 
696
        xor     eax, eax
-
 
697
repeat 4
-
 
698
        mov     dword [.max_hs_bandwidth+(%-1)*4], eax
-
 
699
end repeat
-
 
700
        mov     [.max_fs_bandwidth], ax
-
 
701
        mov     [.possible_microframes], 0x3F
-
 
702
; Loop over all frames starting with [.variant] advancing by [.variant_delta].
-
 
703
        mov     edi, [.variant]
-
 
704
.frames:
-
 
705
; 2. Calculate statistics for one frame.
-
 
706
        tt_calc_bandwidth_in_frame
-
 
707
; 3. Update maximal FS budget.
-
 
708
        mov     ax, [.total_budget]
-
 
709
        cmp     ax, [.max_fs_bandwidth]
-
 
710
        jb      @f
-
 
711
        mov     [.max_fs_bandwidth], ax
-
 
712
@@:
-
 
713
; 4. For every microframe, update maximal HS bandwidth
-
 
714
; and check whether the microframe is allowed for scheduling.
-
 
715
        xor     ecx, ecx
-
 
716
.microframes:
-
 
717
        mov     ax, [.hs_bandwidth+ecx*2]
-
 
718
        cmp     ax, [.max_hs_bandwidth+ecx*2]
-
 
719
        jb      @f
-
 
720
        mov     [.max_hs_bandwidth+ecx*2], ax
-
 
721
@@:
-
 
722
        tt_exclude_microframe_if_no_budget
-
 
723
        inc     ecx
-
 
724
        cmp     ecx, 8
-
 
725
        jb      .microframes
-
 
726
; Stop loop when outside of first descriptor group.
-
 
727
        lea     eax, [esi+ehci_controller.IntEDs+32*sizeof.ehci_static_ep-sizeof.ehci_controller]
-
 
728
        add     edi, [.variant_delta]
-
 
729
        cmp     edi, eax
-
 
730
        jb      .frames
-
 
731
}
-
 
732
 
-
 
733
struct usb_split_info
-
 
734
microframe_mask         dd      ?       ; lower byte is S-mask, second byte is C-mask
-
 
735
ssplit_bandwidth        dd      ?
-
 
736
csplit_bandwidth        dd      ?
-
 
737
ends
-
 
738
 
-
 
739
; Check whether the current variant and the current microframe are allowed
-
 
740
; for scheduling. If so, check whether they are better than the previously
-
 
741
; selected variant+microframe, if any. If so, update the previously selected
-
 
742
; variant+microframe to current ones.
-
 
743
; ecx = microframe, [.variant] = variant
-
 
744
macro tt_check_variant_microframe
-
 
745
{
-
 
746
local .nothing, .update, .ssplit, .csplit, .csplit_done
-
 
747
; 1. If the current microframe does not fit in existing FS budget, do nothing.
-
 
748
        bt      [.possible_microframes], ecx
-
 
749
        jnc     .nothing
-
 
750
; 2. Calculate maximal HS bandwidth over all affected microframes.
-
 
751
; 2a. Start-split phase: one or more microframes starting with ecx,
-
 
752
; coded in lower byte of .info.microframe_mask.
-
 
753
        xor     ebx, ebx
-
 
754
        xor     edx, edx
-
 
755
.ssplit:
-
 
756
        lea     eax, [ecx+edx]
-
 
757
        movzx   eax, [.max_hs_bandwidth+eax*2]
-
 
758
        add     eax, [.info.ssplit_bandwidth]
-
 
759
        cmp     ebx, eax
-
 
760
        ja      @f
-
 
761
        mov     ebx, eax
-
 
762
@@:
-
 
763
        inc     edx
-
 
764
        bt      [.info.microframe_mask], edx
-
 
765
        jc      .ssplit
-
 
766
; 2b. Complete-split phase: zero or more microframes starting with
-
 
767
; ecx+(last start-split microframe)+2,
-
 
768
; coded in second byte of .info.microframe_mask.
-
 
769
        add     edx, 8
-
 
770
.csplit:
-
 
771
        inc     edx
-
 
772
        bt      [.info.microframe_mask], edx
-
 
773
        jnc     .csplit_done
-
 
774
        lea     eax, [ecx+edx]
-
 
775
        cmp     eax, 8
-
 
776
        jae     .csplit_done
-
 
777
        movzx   eax, [.max_hs_bandwidth+(eax-8)*2]
-
 
778
        add     eax, [.info.csplit_bandwidth]
-
 
779
        cmp     ebx, eax
-
 
780
        ja      .csplit
-
 
781
        mov     ebx, eax
-
 
782
        jmp     .csplit
-
 
783
.csplit_done:
-
 
784
; 3. Check that current HS bandwidth + new bandwidth <= limit;
-
 
785
; USB2 specification allows maximum 60000*80% bit times for periodic microframe.
-
 
786
        cmp     ebx, 48000
-
 
787
        ja      .nothing
-
 
788
; 4. This variant is possible for scheduling.
-
 
789
; Check whether it is better than the currently selected one.
-
 
790
; 4a. The primary criteria: FS/LS bandwidth.
-
 
791
        mov     ax, [.max_fs_bandwidth]
-
 
792
        cmp     ax, [.best_fs_bandwidth]
-
 
793
        ja      .nothing
-
 
794
        jb      .update
-
 
795
; 4b. The secondary criteria: prefer microframes which are closer to start of frame.
-
 
796
        cmp     ecx, [.targetsmask]
-
 
797
        ja      .nothing
-
 
798
        jb      .update
-
 
799
; 4c. The last criteria: HS bandwidth.
-
 
800
        cmp     ebx, [.bandwidth]
-
 
801
        ja      .nothing
-
 
802
.update:
-
 
803
; 5. This variant is better than the previously selected.
-
 
804
; Update the best variant with current data.
-
 
805
        mov     [.best_fs_bandwidth], ax
-
 
806
        mov     [.bandwidth], ebx
-
 
807
        mov     [.targetsmask], ecx
-
 
808
        mov     eax, [.variant]
-
 
809
        mov     [.target], eax
-
 
810
.nothing:
-
 
811
}
-
 
812
 
-
 
813
; TT scheduler: add new pipe.
-
 
814
; in: esi -> usb_controller, edi -> usb_pipe
-
 
815
; out: edx -> usb_static_ep, eax = S-Mask
-
 
816
proc ehci_select_tt_interrupt_list
-
 
817
virtual at ebp-12-.local_vars_size
-
 
818
.local_vars_start:
-
 
819
.info                   usb_split_info
-
 
820
.new_budget             dw      ?
-
 
821
.total_budget           dw      ?
-
 
822
.possible_microframes   dd      ?
-
 
823
.tthub                  dd      ?
-
 
824
.budget                 rw      8
-
 
825
.hs_bandwidth           rw      8
-
 
826
.max_hs_bandwidth       rw      8
-
 
827
.max_fs_bandwidth       dw      ?
-
 
828
.best_fs_bandwidth      dw      ?
-
 
829
.variant                dd      ?
-
 
830
.variant_delta          dd      ?
-
 
831
.target_delta           dd      ?
-
 
832
.local_vars_size = $ - .local_vars_start
-
 
833
 
-
 
834
.targetsmask    dd      ?
-
 
835
.bandwidth      dd      ?
-
 
836
.target         dd      ?
-
 
837
                dd      ?
-
 
838
                dd      ?
-
 
839
.config_pipe    dd      ?
-
 
840
.endpoint       dd      ?
-
 
841
.maxpacket      dd      ?
-
 
842
.type           dd      ?
-
 
843
.interval       dd      ?
-
 
844
end virtual
-
 
845
        mov     eax, [edi+ehci_pipe.Token-sizeof.ehci_pipe]
-
 
846
        shr     eax, 16
-
 
847
        and     eax, (1 shl 11) - 1
-
 
848
        push    ebx edi
-
 
849
; 1. Compute the real interval. FS/LS devices encode the interval as
-
 
850
; number of milliseconds. Use the maximal power of two that is not greater than
-
 
851
; the given interval and EHCI scheduling area = 32 frames.
-
 
852
        cmp     [.interval], 1
-
 
853
        adc     [.interval], 0
-
 
854
        mov     ecx, 64
-
 
855
        mov     eax, 64 * sizeof.ehci_static_ep
-
 
856
@@:
-
 
857
        shr     ecx, 1
-
 
858
        cmp     [.interval], ecx
-
 
859
        jb      @b
-
 
860
        mov     [.interval], ecx
-
 
861
; 2. Compute variables for further calculations.
-
 
862
; 2a. [.variant_delta] is delta between two lists from the first group
-
 
863
; that correspond to the same variant.
-
 
864
        imul    ecx, sizeof.ehci_static_ep
-
 
865
        mov     [.variant_delta], ecx
-
 
866
; 2b. [.target_delta] is delta between the final answer from the group
-
 
867
; corresponding to [.interval] and the item from the first group.
-
 
868
        sub     eax, ecx
-
 
869
        sub     eax, ecx
-
 
870
        mov     [.target_delta], eax
-
 
871
; 2c. [.variant] is the first list from the first group that corresponds
-
 
872
; to the current variant.
-
 
873
        lea     eax, [esi+ehci_controller.IntEDs-sizeof.ehci_controller]
-
 
874
        mov     [.variant], eax
-
 
875
; 2d. [.tthub] identifies TT hub for new pipe, [.new_budget] is FS budget
-
 
876
; for new pipe.
-
 
877
        mov     eax, [edi+usb_pipe.DeviceData]
-
 
878
        mov     eax, [eax+usb_device_data.TTHub]
-
 
879
        mov     ebx, edi
-
 
880
        mov     [.tthub], eax
-
 
881
        call    tt_calc_budget
-
 
882
        mov     [.new_budget], ax
-
 
883
; 2e. [.usb_split_info] describes bandwidth used by new pipe on HS bus.
-
 
884
        lea     edi, [.info]
-
 
885
        call    tt_fill_split_info
-
 
886
        test    eax, eax
-
 
887
        jz      .no_bandwidth
-
 
888
; 2f. There is no best variant yet, put maximal possible values,
-
 
889
; so any variant would be better than the "current".
-
 
890
        or      [.best_fs_bandwidth], -1
-
 
891
        or      [.target], -1
-
 
892
        or      [.bandwidth], -1
-
 
893
        or      [.targetsmask], -1
-
 
894
; 3. Loop over all variants, for every variant decide whether it is acceptable,
-
 
895
; select the best variant from all acceptable variants.
-
 
896
.check_variants:
-
 
897
        tt_calc_statistics_for_one_variant
-
 
898
        xor     ecx, ecx
-
 
899
.check_microframes:
-
 
900
        tt_check_variant_microframe
-
 
901
        inc     ecx
-
 
902
        cmp     ecx, 6
-
 
903
        jb      .check_microframes
-
 
904
        add     [.variant], sizeof.ehci_static_ep
-
 
905
        dec     [.interval]
-
 
906
        jnz     .check_variants
-
 
907
; 4. If there is no acceptable variants, return error.
-
 
908
        mov     ecx, [.targetsmask]
-
 
909
        mov     edx, [.target]
-
 
910
        cmp     ecx, -1
-
 
911
        jz      .no_bandwidth
-
 
912
; 5. Calculate the answer: edx -> selected list, eax = S-Mask and C-Mask.
-
 
913
        mov     eax, [.info.microframe_mask]
-
 
914
        add     edx, [.target_delta]
-
 
915
        shl     eax, cl
-
 
916
        and     eax, 0xFFFF
-
 
917
; 6. Update HS bandwidths in the selected list.
-
 
918
        xor     ecx, ecx
-
 
919
        mov     ebx, [.info.ssplit_bandwidth]
-
 
920
.update_ssplit:
-
 
921
        bt      eax, ecx
-
 
922
        jnc     @f
-
 
923
        add     [edx+ehci_static_ep.Bandwidths+ecx*2], bx
-
 
924
@@:
-
 
925
        inc     ecx
-
 
926
        cmp     ecx, 8
-
 
927
        jb      .update_ssplit
-
 
928
        mov     ebx, [.info.csplit_bandwidth]
-
 
929
.update_csplit:
-
 
930
        bt      eax, ecx
-
 
931
        jnc     @f
-
 
932
        add     [edx+ehci_static_ep.Bandwidths+(ecx-8)*2], bx
-
 
933
@@:
-
 
934
        inc     ecx
-
 
935
        cmp     ecx, 16
-
 
936
        jb      .update_csplit
-
 
937
; 7. Return.
-
 
938
        add     edx, ehci_static_ep.SoftwarePart
-
 
939
        pop     edi ebx
-
 
940
        ret
-
 
941
.no_bandwidth:
-
 
942
        dbgstr 'Periodic bandwidth limit reached'
-
 
943
        xor     eax, eax
-
 
944
        xor     edx, edx
-
 
945
        pop     edi ebx
-
 
946
        ret
-
 
947
endp
-
 
948
 
-
 
949
; Pipe is removing, update the corresponding lists.
-
 
950
; We do not reorder anything, so just update book-keeping variable
-
 
951
; in the list header.
-
 
952
proc ehci_fs_interrupt_list_unlink
-
 
953
; calculate bandwidth
-
 
954
        push    edi
-
 
955
        sub     esp, sizeof.usb_split_info
-
 
956
        mov     edi, esp
-
 
957
        call    tt_fill_split_info
-
 
958
; get target list
-
 
959
        mov     edx, [ebx+ehci_pipe.BaseList-sizeof.ehci_pipe]
-
 
960
; update bandwidth for Start-Split
-
 
961
        mov     eax, [edi+usb_split_info.ssplit_bandwidth]
-
 
962
        xor     ecx, ecx
-
 
963
.dec_bandwidth_1:
-
 
964
        bt      [ebx+ehci_pipe.Flags-sizeof.ehci_pipe], ecx
-
 
965
        jnc     @f
-
 
966
        sub     word [edx+ecx*2+ehci_static_ep.Bandwidths - ehci_static_ep.SoftwarePart], ax
-
 
967
@@:
-
 
968
        inc     ecx
-
 
969
        cmp     ecx, 8
-
 
970
        jb      .dec_bandwidth_1
-
 
971
; update bandwidth for Complete-Split
-
 
972
        mov     eax, [edi+usb_split_info.csplit_bandwidth]
-
 
973
.dec_bandwidth_2:
-
 
974
        bt      [ebx+ehci_pipe.Flags-sizeof.ehci_pipe], ecx
-
 
975
        jnc     @f
-
 
976
        sub     word [edx+(ecx-8)*2+ehci_static_ep.Bandwidths - ehci_static_ep.SoftwarePart], ax
-
 
977
@@:
-
 
978
        inc     ecx
-
 
979
        cmp     ecx, 16
-
 
980
        jb      .dec_bandwidth_2
-
 
981
        add     esp, sizeof.usb_split_info
-
 
982
        pop     edi
-
 
983
        ret
-
 
984
endp
-
 
985
 
-
 
986
; Helper procedure for ehci_select_tt_interrupt_list.
-
 
987
; Calculates "best-case budget" according to the core spec,
-
 
988
; that is, number of bytes (not bits) corresponding to "optimistic" transaction
-
 
989
; time, including inter-packet delays/bus turn-around time,
-
 
990
; but without bit stuffing and timers drift.
-
 
991
; One extra TT-specific delay is added: TT think time from the hub descriptor.
-
 
992
; Similar to calc_usb1_bandwidth with corresponding changes.
-
 
993
; eax -> usb_hub with TT, ebx -> usb_pipe
-
 
994
proc tt_calc_budget
-
 
995
        movzx   ecx, [eax+usb_hub.HubCharacteristics]
-
 
996
        shr     ecx, 5
-
 
997
        and     ecx, 3  ; 1+ecx = TT think time in FS-bytes
-
 
998
        mov     eax, [ebx+ehci_pipe.Token-sizeof.ehci_pipe]
-
 
999
        shr     eax, 16
-
 
1000
        and     eax, (1 shl 11) - 1     ; get data length
-
 
1001
        bt      [ebx+ehci_pipe.Token-sizeof.ehci_pipe], 12
-
 
1002
        jc      .low_speed
-
 
1003
; Full-speed interrupt IN/OUT:
-
 
1004
; 33 bits for Token packet (8 for SYNC, 24 for token+address, 3 for EOP),
-
 
1005
; 18 bits for bus turn-around, 11 bits for SYNC+EOP in Data packet,
-
 
1006
; 2 bits for inter-packet delay, 19 bits for Handshake packet,
-
 
1007
; 2 bits for another inter-packet delay. 85 bits total, pad to 11 bytes.
-
 
1008
        lea     eax, [eax+11+ecx+1]
-
 
1009
; 1 byte is minimal TT think time in addition to ecx.
-
 
1010
        ret
-
 
1011
.low_speed:
-
 
1012
; Low-speed interrupt IN/OUT:
-
 
1013
; multiply by 8 for LS -> FS,
-
 
1014
; add 85 bytes as in full-speed interrupt and extra 5 bytes for two PRE packets
-
 
1015
; and two hub delays.
-
 
1016
; 1 byte is minimal TT think time in addition to ecx.
-
 
1017
        lea     eax, [eax*8+90+ecx+1]
-
 
1018
        ret
-
 
1019
endp
-
 
1020
 
-
 
1021
; Helper procedure for TT scheduler.
-
 
1022
; Calculates Start-Split/Complete-Split masks and HS bandwidths.
-
 
1023
; ebx -> usb_pipe, edi -> usb_split_info
-
 
1024
proc tt_fill_split_info
-
 
1025
; Interrupt endpoints.
-
 
1026
; The core spec says in 5.7.3 "Interrupt Transfer Packet Size Constraints" that:
-
 
1027
; The maximum allowable interrupt data payload size is 64 bytes or less for full-speed.
-
 
1028
; Low-speed devices are limited to eight bytes or less maximum data payload size.
-
 
1029
; This is important for scheduling, it guarantees that in any case transaction fits
-
 
1030
; in two microframes (usually one, two if transaction has started too late in the first
-
 
1031
; microframe), so check it.
-
 
1032
        mov     eax, [ebx+ehci_pipe.Token-sizeof.ehci_pipe]
-
 
1033
        mov     ecx, 8
-
 
1034
        bt      eax, 12
-
 
1035
        jc      @f
-
 
1036
        mov     ecx, 64
-
 
1037
@@:
-
 
1038
        shr     eax, 16
-
 
1039
        and     eax, (1 shl 11) - 1     ; get data length
-
 
1040
        cmp     eax, ecx
-
 
1041
        ja      .error
-
 
1042
        add     eax, 3  ; add 3 bytes for other fields in data packet, PID+CRC16
-
 
1043
; Multiply by 8 for bytes -> bits and then by 7/6 to accomodate bit stuffing;
-
 
1044
; total 28/3 = 9+1/3
-
 
1045
        mov     edx, 55555556h
-
 
1046
        lea     ecx, [eax*9]
-
 
1047
        mul     edx
-
 
1048
; One start-split, three complete-splits (unless the last is too far,
-
 
1049
; but this is handled by the caller).
-
 
1050
        mov     eax, [ebx+usb_pipe.LastTD]
-
 
1051
        mov     [edi+usb_split_info.microframe_mask], 0x1C01
-
 
1052
; Structure and HS bandwidth of packets depends on the direction.
-
 
1053
        bt      [eax+ehci_gtd.Token-sizeof.ehci_gtd], 8
-
 
1054
        jc      .interrupt_in
-
 
1055
.interrupt_out:
-
 
1056
; Start-Split phase:
-
 
1057
; 77 bits for SPLIT packet (32 for SYNC, 8 for EOP, 32 for data, 5 for bit stuffing),
-
 
1058
; 88 bits for inter-packet delay, 68 bits for Token packet,
-
 
1059
; 88 bits for inter-packet delay, 40 bits for SYNC+EOP in Data packet,
-
 
1060
; 88 bits for last inter-packet delay, total 449 bits.
-
 
1061
        lea     eax, [edx+ecx+449]
-
 
1062
        mov     [edi+usb_split_info.ssplit_bandwidth], eax
-
 
1063
; Complete-Split phase:
-
 
1064
; 77 bits for SPLIT packet,
-
 
1065
; 88 bits for inter-packet delay, 68 bits for Token packet,
-
 
1066
; 736 bits for bus turn-around, 49 bits for Handshake packet,
-
 
1067
; 8 bits for inter-packet delay, total 1026 bits.
-
 
1068
        mov     [edi+usb_split_info.csplit_bandwidth], 1026
-
 
1069
        ret
-
 
1070
.interrupt_in:
-
 
1071
; Start-Split phase:
-
 
1072
; 77 bits for SPLIT packet, 88 bits for inter-packet delay,
-
 
1073
; 68 bits for Token packet, 88 bits for another inter-packet delay,
-
 
1074
; total 321 bits.
-
 
1075
        mov     [edi+usb_split_info.ssplit_bandwidth], 321
-
 
1076
; Complete-Split phase:
-
 
1077
; 77 bits for SPLIT packet, 88 bits for inter-packet delay,
-
 
1078
; 68 bits for Token packet, 736 bits for bus turn-around,
-
 
1079
; 40 bits for SYNC+EOP in Data packet, 8 bits for inter-packet delay,
-
 
1080
; total 1017 bits.
-
 
1081
        lea     eax, [edx+ecx+1017]
-
 
1082
        mov     [edi+usb_split_info.csplit_bandwidth], eax
-
 
1083
        ret
-
 
1084
.error:
-
 
1085
        xor     eax, eax
-
 
1086
        ret
-
 
1087
endp
-