Subversion Repositories Kolibri OS

Rev

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

Rev 4300 Rev 4418
Line 1... Line 1...
1
; Code for EHCI controllers.
1
; Code for EHCI controllers.
-
 
2
 
-
 
3
; Standard driver stuff
-
 
4
format PE DLL native
-
 
5
entry start
-
 
6
__DEBUG__ equ 1
-
 
7
__DEBUG_LEVEL__ equ 1
2
; Note: it should be moved to an external driver,
8
section '.reloc' data readable discardable fixups
3
; it was convenient to have this code compiled into the kernel during initial
9
section '.text' code readable executable
-
 
10
include '../proc32.inc'
-
 
11
include '../struct.inc'
-
 
12
include '../macros.inc'
-
 
13
include '../fdo.inc'
4
; development, but there are no reasons to keep it here.
14
include '../../kernel/trunk/bus/usb/common.inc'
Line 5... Line 15...
5
 
15
 
6
; =============================================================================
16
; =============================================================================
7
; ================================= Constants =================================
17
; ================================= Constants =================================
8
; =============================================================================
18
; =============================================================================
Line 244... Line 254...
244
CapabilityParams        dd      ?
254
CapabilityParams        dd      ?
245
; Copy of EhciCapParamsReg value.
255
; Copy of EhciCapParamsReg value.
246
DeferredActions         dd      ?
256
DeferredActions         dd      ?
247
; Bitmask of events from EhciStatusReg which were observed by the IRQ handler
257
; Bitmask of events from EhciStatusReg which were observed by the IRQ handler
248
; and needs to be processed in the IRQ thread.
258
; and needs to be processed in the IRQ thread.
-
 
259
PortRoutes              rb      16
-
 
260
; Companion port route description.
-
 
261
; Each byte describes routing of one port, value = PCI function.
-
 
262
; This field must be the last one:
-
 
263
; UHCI/OHCI code uses this field without knowing the entire structure.
249
ends
264
ends
Line 250... Line 265...
250
 
265
 
251
if ehci_controller.IntEDs mod 32
266
if ehci_controller.IntEDs mod 32
252
.err Static endpoint descriptors must be 32-bytes aligned inside ehci_controller
267
.err Static endpoint descriptors must be 32-bytes aligned inside ehci_controller
Line 256... Line 271...
256
; controller-independent code.
271
; controller-independent code.
257
; Implements the structure usb_hardware_func from hccommon.inc for EHCI.
272
; Implements the structure usb_hardware_func from hccommon.inc for EHCI.
258
iglobal
273
iglobal
259
align 4
274
align 4
260
ehci_hardware_func:
275
ehci_hardware_func:
-
 
276
        dd      USBHC_VERSION
261
        dd      'EHCI'
277
        dd      'EHCI'
262
        dd      sizeof.ehci_controller
278
        dd      sizeof.ehci_controller
-
 
279
        dd      ehci_kickoff_bios
263
        dd      ehci_init
280
        dd      ehci_init
264
        dd      ehci_process_deferred
281
        dd      ehci_process_deferred
265
        dd      ehci_set_device_address
282
        dd      ehci_set_device_address
266
        dd      ehci_get_device_address
283
        dd      ehci_get_device_address
267
        dd      ehci_port_disable
284
        dd      ehci_port_disable
Line 274... Line 291...
274
        dd      ehci_alloc_td
291
        dd      ehci_alloc_td
275
        dd      ehci_free_td
292
        dd      ehci_free_td
276
        dd      ehci_alloc_transfer
293
        dd      ehci_alloc_transfer
277
        dd      ehci_insert_transfer
294
        dd      ehci_insert_transfer
278
        dd      ehci_new_device
295
        dd      ehci_new_device
-
 
296
ehci_name db    'EHCI',0
279
endg
297
endg
Line 280... Line 298...
280
 
298
 
281
; =============================================================================
299
; =============================================================================
282
; =================================== Code ====================================
300
; =================================== Code ====================================
Line -... Line 301...
-
 
301
; =============================================================================
-
 
302
 
-
 
303
; Called once when driver is loading and once at shutdown.
-
 
304
; When loading, must initialize itself, register itself in the system
-
 
305
; and return eax = value obtained when registering.
-
 
306
proc start
-
 
307
virtual at esp
-
 
308
                dd      ? ; return address
-
 
309
.reason         dd      ? ; DRV_ENTRY or DRV_EXIT
-
 
310
.cmdline        dd      ? ; normally NULL
-
 
311
end virtual
-
 
312
        cmp     [.reason], DRV_ENTRY
-
 
313
        jnz     .nothing
-
 
314
        mov     ecx, ehci_ep_mutex
-
 
315
        invoke  MutexInit
-
 
316
        mov     ecx, ehci_gtd_mutex
-
 
317
        invoke  MutexInit
-
 
318
        push    esi edi
-
 
319
        mov     esi, [USBHCFunc]
-
 
320
        mov     edi, usbhc_api
-
 
321
        movi    ecx, sizeof.usbhc_func/4
-
 
322
        rep movsd
-
 
323
        pop     edi esi
-
 
324
        invoke  RegUSBDriver, ehci_name, 0, ehci_hardware_func
-
 
325
.nothing:
-
 
326
        ret
283
; =============================================================================
327
endp
284
 
328
 
285
; Controller-specific initialization function.
329
; Controller-specific initialization function.
286
; Called from usb_init_controller. Initializes the hardware and
330
; Called from usb_init_controller. Initializes the hardware and
287
; EHCI-specific parts of software structures.
331
; EHCI-specific parts of software structures.
Line 311... Line 355...
311
end if
355
end if
312
if (ehci_controller.IntEDs mod 0x1000) <> 0
356
if (ehci_controller.IntEDs mod 0x1000) <> 0
313
.err assertion failed
357
.err assertion failed
314
end if
358
end if
315
        add     eax, ehci_controller.IntEDs
359
        add     eax, ehci_controller.IntEDs
316
        call    get_phys_addr
360
        call    [GetPhysAddr]
317
; 2b. Fill first 32 entries.
361
; 2b. Fill first 32 entries.
318
        inc     eax
362
        inc     eax
319
        inc     eax     ; set Type to EHCI_TYPE_QH
363
        inc     eax     ; set Type to EHCI_TYPE_QH
320
        movi    ecx, 32
364
        movi    ecx, 32
321
        mov     edx, ecx
365
        mov     edx, ecx
Line 370... Line 414...
370
; 3j. Initialize the head of Bulk list.
414
; 3j. Initialize the head of Bulk list.
371
        sub     esi, sizeof.ehci_static_ep
415
        sub     esi, sizeof.ehci_static_ep
372
        call    ehci_init_static_endpoint
416
        call    ehci_init_static_endpoint
373
; 4. Create a virtual memory area to talk with the controller.
417
; 4. Create a virtual memory area to talk with the controller.
374
; 4a. Enable memory & bus master access.
418
; 4a. Enable memory & bus master access.
375
        mov     ch, [.bus]
-
 
376
        mov     cl, 1
-
 
377
        mov     eax, ecx
-
 
378
        mov     bh, [.devfn]
419
        invoke  PciRead16, dword [.bus], dword [.devfn], 4
379
        mov     bl, 4
-
 
380
        call    pci_read_reg
-
 
381
        or      al, 6
420
        or      al, 6
382
        xchg    eax, ecx
-
 
383
        call    pci_write_reg
421
        invoke  PciWrite16, dword [.bus], dword [.devfn], 4, eax
384
; 4b. Read memory base address.
422
; 4b. Read memory base address.
385
        mov     ah, [.bus]
423
        invoke  PciRead32, dword [.bus], dword [.devfn], 10h
386
        mov     al, 2
-
 
387
        mov     bl, 10h
-
 
388
        call    pci_read_reg
-
 
389
;       DEBUGF 1,'K : phys MMIO %x\n',eax
424
;       DEBUGF 1,'K : phys MMIO %x\n',eax
390
        and     al, not 0Fh
425
        and     al, not 0Fh
391
; 4c. Create mapping for physical memory. 200h bytes are always sufficient.
426
; 4c. Create mapping for physical memory. 200h bytes are always sufficient.
392
        stdcall map_io_mem, eax, 200h, PG_SW+PG_NOCACHE
427
        invoke  MapIoMem, eax, 200h, PG_SW+PG_NOCACHE
393
        test    eax, eax
428
        test    eax, eax
394
        jz      .fail
429
        jz      .fail
395
;       DEBUGF 1,'K : MMIO %x\n',eax
430
;       DEBUGF 1,'K : MMIO %x\n',eax
396
if ehci_controller.MMIOBase1 <> ehci_controller.BulkED + sizeof.ehci_static_ep
431
if ehci_controller.MMIOBase1 <> ehci_controller.BulkED + sizeof.ehci_static_ep
397
.err assertion failed
432
.err assertion failed
398
end if
433
end if
399
        stosd   ; fill ehci_controller.MMIOBase1
434
        stosd   ; fill ehci_controller.MMIOBase1
-
 
435
; 5. Read basic parameters of the controller.
-
 
436
; 5a. Structural parameters.
-
 
437
        mov     ebx, [eax+EhciStructParamsReg]
-
 
438
; 5b. Port routing rules.
-
 
439
; If bit 7 in HCSPARAMS is set, read and unpack EhciPortRouteReg.
-
 
440
; Otherwise, bits 11:8 are N_PCC = number of ports per companion,
-
 
441
; bits 15:12 are number of companions, maybe zero,
-
 
442
; first N_PCC ports are routed to the first companion and so on.
-
 
443
        xor     esi, esi
-
 
444
        test    bl, bl
-
 
445
        js      .read_routes
-
 
446
        test    bh, 0x0F
-
 
447
        jz      .no_companions
-
 
448
        test    bh, 0xF0
-
 
449
        jz      .no_companions
-
 
450
        xor     edx, edx
-
 
451
.fill_routes:
-
 
452
        movzx   ecx, bh
-
 
453
        and     ecx, 15
-
 
454
@@:
-
 
455
        mov     byte [edi+esi+ehci_controller.PortRoutes-(ehci_controller.MMIOBase1+4)], dl
-
 
456
        inc     esi
-
 
457
        cmp     esi, 16
-
 
458
        jz      .routes_filled
-
 
459
        dec     ecx
-
 
460
        jnz     @b
-
 
461
        movzx   ecx, bh
-
 
462
        shr     ecx, 4
-
 
463
        inc     edx
-
 
464
        cmp     edx, ecx
-
 
465
        jb      .fill_routes
-
 
466
.no_companions:
-
 
467
        mov     byte [edi+esi+ehci_controller.PortRoutes-(ehci_controller.MMIOBase1+4)], 0xFF
-
 
468
        inc     esi
-
 
469
        cmp     esi, 16
-
 
470
        jnz     .no_companions
-
 
471
        jmp     .routes_filled
-
 
472
.read_routes:
-
 
473
rept 2 counter
-
 
474
{
-
 
475
        mov     ecx, [eax+EhciPortRouteReg+(counter-1)*4]
-
 
476
@@:
-
 
477
        mov     edx, ecx
-
 
478
        shr     ecx, 4
-
 
479
        and     edx, 15
-
 
480
        mov     byte [edi+esi+ehci_controller.PortRoutes-(ehci_controller.MMIOBase1+4)], dl
-
 
481
        inc     esi
-
 
482
        cmp     esi, 8*counter
-
 
483
        jnz     @b
-
 
484
}
-
 
485
.routes_filled:
-
 
486
;        DEBUGF 1,'K : EhciPortRouteReg: %x %x\n',[eax+EhciPortRouteReg],[eax+EhciPortRouteReg+4]
-
 
487
;        DEBUGF 1,'K : routes:\nK : '
-
 
488
;rept 8 counter
-
 
489
;{
-
 
490
;        DEBUGF 1,' %x',[edi+ehci_controller.PortRoutes-(ehci_controller.MMIOBase1+4)+counter-1]:2
-
 
491
;}
-
 
492
;        DEBUGF 1,'\nK : '
-
 
493
;rept 8 counter
-
 
494
;{
-
 
495
;        DEBUGF 1,' %x',[edi+ehci_controller.PortRoutes+8-(ehci_controller.MMIOBase1+4)+counter-1]:2
-
 
496
;}
-
 
497
;        DEBUGF 1,'\n'
400
        movzx   ecx, byte [eax+EhciCapLengthReg]
498
        movzx   ecx, byte [eax+EhciCapLengthReg]
401
        mov     edx, [eax+EhciCapParamsReg]
499
        mov     edx, [eax+EhciCapParamsReg]
402
        mov     ebx, [eax+EhciStructParamsReg]
-
 
403
        add     eax, ecx
500
        add     eax, ecx
404
if ehci_controller.MMIOBase2 <> ehci_controller.MMIOBase1 + 4
501
if ehci_controller.MMIOBase2 <> ehci_controller.MMIOBase1 + 4
405
.err assertion failed
502
.err assertion failed
406
end if
503
end if
407
        stosd   ; fill ehci_controller.MMIOBase2
504
        stosd   ; fill ehci_controller.MMIOBase2
Line 424... Line 521...
424
        test    dword [edi+EhciStatusReg], 1 shl 12
521
        test    dword [edi+EhciStatusReg], 1 shl 12
425
        jnz     .stopped
522
        jnz     .stopped
426
        and     dword [edi+EhciCommandReg], not 1
523
        and     dword [edi+EhciCommandReg], not 1
427
@@:
524
@@:
428
        movi    esi, 1
525
        movi    esi, 1
429
        call    delay_ms
526
        invoke  Sleep
430
        test    dword [edi+EhciStatusReg], 1 shl 12
527
        test    dword [edi+EhciStatusReg], 1 shl 12
431
        jnz     .stopped
528
        jnz     .stopped
432
        loop    @b
529
        loop    @b
433
        dbgstr 'Failed to stop EHCI controller'
530
        dbgstr 'Failed to stop EHCI controller'
434
        jmp     .fail_unmap
531
        jmp     .fail_unmap
Line 436... Line 533...
436
; 6c. Reset the controller. Wait up to 50 ms checking status every 1 ms.
533
; 6c. Reset the controller. Wait up to 50 ms checking status every 1 ms.
437
        or      dword [edi+EhciCommandReg], 2
534
        or      dword [edi+EhciCommandReg], 2
438
        movi    ecx, 50
535
        movi    ecx, 50
439
@@:
536
@@:
440
        movi    esi, 1
537
        movi    esi, 1
441
        call    delay_ms
538
        invoke  Sleep
442
        test    dword [edi+EhciCommandReg], 2
539
        test    dword [edi+EhciCommandReg], 2
443
        jz      .reset_ok
540
        jz      .reset_ok
444
        loop    @b
541
        loop    @b
445
        dbgstr 'Failed to reset EHCI controller'
542
        dbgstr 'Failed to reset EHCI controller'
446
        jmp     .fail_unmap
543
        jmp     .fail_unmap
Line 453... Line 550...
453
        test    byte [esi+ehci_controller.CapabilityParams-sizeof.ehci_controller], 1
550
        test    byte [esi+ehci_controller.CapabilityParams-sizeof.ehci_controller], 1
454
        jz      @f
551
        jz      @f
455
        mov     dword [edi+EhciCtrlDataSegReg], 0
552
        mov     dword [edi+EhciCtrlDataSegReg], 0
456
@@:
553
@@:
457
; 7b. Hook interrupt and enable appropriate interrupt sources.
554
; 7b. Hook interrupt and enable appropriate interrupt sources.
458
        mov     ah, [.bus]
-
 
459
        mov     al, 0
-
 
460
        mov     bh, [.devfn]
555
        invoke  PciRead8, dword [.bus], dword [.devfn], 3Ch
461
        mov     bl, 3Ch
-
 
462
        call    pci_read_reg
-
 
463
; al = IRQ
556
; al = IRQ
464
        DEBUGF 1,'K : attaching to IRQ %x\n',al
557
;        DEBUGF 1,'K : attaching to IRQ %x\n',al
465
        movzx   eax, al
558
        movzx   eax, al
466
        stdcall attach_int_handler, eax, ehci_irq, esi
559
        invoke  AttachIntHandler, eax, ehci_irq, esi
467
;       mov     dword [edi+EhciStatusReg], 111111b      ; clear status
560
;       mov     dword [edi+EhciStatusReg], 111111b      ; clear status
468
; disable Frame List Rollover interrupt, enable all other sources
561
; disable Frame List Rollover interrupt, enable all other sources
469
        mov     dword [edi+EhciInterruptReg], 110111b
562
        mov     dword [edi+EhciInterruptReg], 110111b
470
; 7c. Inform the controller of the address of periodic lists head.
563
; 7c. Inform the controller of the address of periodic lists head.
471
        lea     eax, [esi-sizeof.ehci_controller]
564
        lea     eax, [esi-sizeof.ehci_controller]
472
        call    get_phys_addr
565
        invoke  GetPhysAddr
473
        mov     dword [edi+EhciPeriodicListReg], eax
566
        mov     dword [edi+EhciPeriodicListReg], eax
474
; 7d. Inform the controller of the address of asynchronous lists head.
567
; 7d. Inform the controller of the address of asynchronous lists head.
475
        lea     eax, [esi+ehci_controller.ControlED-sizeof.ehci_controller]
568
        lea     eax, [esi+ehci_controller.ControlED-sizeof.ehci_controller]
476
        call    get_phys_addr
569
        invoke  GetPhysAddr
477
        mov     dword [edi+EhciAsyncListReg], eax
570
        mov     dword [edi+EhciAsyncListReg], eax
478
; 7e. Configure operational details and run the controller.
571
; 7e. Configure operational details and run the controller.
479
        mov     dword [edi+EhciCommandReg], \
572
        mov     dword [edi+EhciCommandReg], \
480
                (1 shl 16) + \ ; interrupt threshold = 1 microframe = 0.125ms
573
                (1 shl 16) + \ ; interrupt threshold = 1 microframe = 0.125ms
481
                (0 shl 11) + \ ; disable Async Park Mode
574
                (0 shl 11) + \ ; disable Async Park Mode
Line 496... Line 589...
496
        jb      @b
589
        jb      @b
497
        test    byte [esi+ehci_controller.StructuralParams-sizeof.ehci_controller], 10h
590
        test    byte [esi+ehci_controller.StructuralParams-sizeof.ehci_controller], 10h
498
        jz      @f
591
        jz      @f
499
        push    esi
592
        push    esi
500
        movi    esi, 20
593
        movi    esi, 20
501
        call    delay_ms
594
        invoke  Sleep
502
        pop     esi
595
        pop     esi
503
@@:
596
@@:
504
; 9. Return pointer to usb_controller.
597
; 9. Return pointer to usb_controller.
505
        xchg    eax, esi
598
        xchg    eax, esi
506
        ret
599
        ret
Line 508... Line 601...
508
; Note that the main code branch restores the stack at step 7 and never fails
601
; Note that the main code branch restores the stack at step 7 and never fails
509
; after step 7.
602
; after step 7.
510
.fail_unmap:
603
.fail_unmap:
511
        pop     eax
604
        pop     eax
512
        push    eax
605
        push    eax
513
        stdcall free_kernel_space, [eax+ehci_controller.MMIOBase1]
606
        invoke  FreeKernelSpace, [eax+ehci_controller.MMIOBase1]
514
.fail:
607
.fail:
515
        pop     ecx
608
        pop     ecx
516
        xor     eax, eax
609
        xor     eax, eax
517
        ret
610
        ret
518
endp
611
endp
Line 527... Line 620...
527
        mov     [edi+ehci_static_ep.NextTD], eax
620
        mov     [edi+ehci_static_ep.NextTD], eax
528
        mov     [edi+ehci_static_ep.AlternateNextTD], eax
621
        mov     [edi+ehci_static_ep.AlternateNextTD], eax
529
        test    esi, esi
622
        test    esi, esi
530
        jz      @f
623
        jz      @f
531
        mov     eax, esi
624
        mov     eax, esi
532
        call    get_phys_addr
625
        invoke  GetPhysAddr
533
        inc     eax
626
        inc     eax
534
        inc     eax     ; set Type to EHCI_TYPE_QH
627
        inc     eax     ; set Type to EHCI_TYPE_QH
535
@@:
628
@@:
536
        mov     [edi+ehci_static_ep.NextQH], eax
629
        mov     [edi+ehci_static_ep.NextQH], eax
537
        mov     [edi+ehci_static_ep.NextList], esi
630
        mov     [edi+ehci_static_ep.NextList], esi
538
        mov     byte [edi+ehci_static_ep.OverlayToken], 1 shl 6 ; halted
631
        mov     byte [edi+ehci_static_ep.OverlayToken], 1 shl 6 ; halted
539
        add     edi, ehci_static_ep.SoftwarePart
632
        add     edi, ehci_static_ep.SoftwarePart
-
 
633
        mov     eax, [USBHCFunc]
540
        call    usb_init_static_endpoint
634
        call    [eax+usbhc_func.usb_init_static_endpoint]
541
        add     edi, sizeof.ehci_static_ep - ehci_static_ep.SoftwarePart
635
        add     edi, sizeof.ehci_static_ep - ehci_static_ep.SoftwarePart
542
        ret
636
        ret
543
endp
637
endp
Line 544... Line 638...
544
 
638
 
Line 563... Line 657...
563
; to support USB flash drives. In this case,
657
; to support USB flash drives. In this case,
564
; we must notify the BIOS that we don't need that emulation and know how to
658
; we must notify the BIOS that we don't need that emulation and know how to
565
; deal with USB devices.
659
; deal with USB devices.
566
proc ehci_kickoff_bios
660
proc ehci_kickoff_bios
567
; 1. Get the physical address of MMIO registers.
661
; 1. Get the physical address of MMIO registers.
568
        mov     ah, [esi+PCIDEV.bus]
-
 
569
        mov     bh, [esi+PCIDEV.devfn]
662
        invoke  PciRead32, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], 10h
570
        mov     al, 2
-
 
571
        mov     bl, 10h
-
 
572
        call    pci_read_reg
-
 
573
        and     al, not 0Fh
663
        and     al, not 0Fh
574
; 2. Create mapping for physical memory. 200h bytes are always sufficient.
664
; 2. Create mapping for physical memory. 200h bytes are always sufficient.
575
        stdcall map_io_mem, eax, 200h, PG_SW+PG_NOCACHE
665
        invoke  MapIoMem, eax, 200h, PG_SW+PG_NOCACHE
576
        test    eax, eax
666
        test    eax, eax
577
        jz      .nothing
667
        jz      .nothing
578
        push    eax     ; push argument for step 8
668
        push    eax     ; push argument for step 8
579
; 3. Some BIOSes enable controller interrupts as a result of giving
669
; 3. Some BIOSes enable controller interrupts as a result of giving
580
; controller away. At this point the system knows nothing about how to serve
670
; controller away. At this point the system knows nothing about how to serve
Line 602... Line 692...
602
        jb      .no_capability
692
        jb      .no_capability
603
.look_bios_handoff:
693
.look_bios_handoff:
604
        test    bl, 3
694
        test    bl, 3
605
        jnz     .no_capability
695
        jnz     .no_capability
606
; In each iteration, read the current dword,
696
; In each iteration, read the current dword,
607
        mov     ah, [esi+PCIDEV.bus]
-
 
608
        mov     al, 2
-
 
609
        mov     bh, [esi+PCIDEV.devfn]
697
        invoke  PciRead32, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx
610
        call    pci_read_reg
-
 
611
; check, whether the capability ID is take-ownership ID = 1,
698
; check, whether the capability ID is take-ownership ID = 1,
612
        cmp     al, 1
699
        cmp     al, 1
613
        jz      .found_bios_handoff
700
        jz      .found_bios_handoff
614
; if not, advance to next-capability link and continue loop.
701
; if not, advance to next-capability link and continue loop.
615
        dec     byte [esp]
702
        dec     byte [esp]
Line 630... Line 717...
630
        inc     ebx
717
        inc     ebx
631
        test    eax, 0x10000
718
        test    eax, 0x10000
632
        jz      .has_ownership
719
        jz      .has_ownership
633
; 4c. Request ownership.
720
; 4c. Request ownership.
634
        inc     ebx
721
        inc     ebx
635
        mov     cl, 1
-
 
636
        mov     ah, [esi+PCIDEV.bus]
722
        invoke  PciWrite8, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx, 1
637
        mov     al, 0
-
 
638
        call    pci_write_reg
-
 
639
; 4d. Some BIOSes set ownership flag, but forget to watch for change-ownership
723
; 4d. Some BIOSes set ownership flag, but forget to watch for change-ownership
640
; requests; if so, there is no sense in waiting.
724
; requests; if so, there is no sense in waiting.
641
        inc     ebx
725
        inc     ebx
642
        mov     ah, [esi+PCIDEV.bus]
726
        invoke  PciRead32, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx
643
        mov     al, 2
-
 
644
        call    pci_read_reg
-
 
645
        dec     ebx
727
        dec     ebx
646
        dec     ebx
728
        dec     ebx
647
        test    ah, 20h
729
        test    ah, 20h
648
        jz      .force_ownership
730
        jz      .force_ownership
649
; 4e. Wait for result no more than 1 s, checking for status every 1 ms.
731
; 4e. Wait for result no more than 1 s, checking for status every 1 ms.
650
; If successful, go to 5.
732
; If successful, go to 5.
651
        mov     dword [esp], 1000
733
        mov     dword [esp], 1000
652
@@:
734
@@:
653
        mov     ah, [esi+PCIDEV.bus]
735
        invoke  PciRead8, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx
654
        mov     al, 0
-
 
655
        call    pci_read_reg
-
 
656
        test    al, 1
736
        test    al, 1
657
        jz      .has_ownership
737
        jz      .has_ownership
658
        push    esi
738
        push    esi
659
        movi    esi, 1
739
        movi    esi, 1
660
        call    delay_ms
740
        invoke  Sleep
661
        pop     esi
741
        pop     esi
662
        dec     dword [esp]
742
        dec     dword [esp]
663
        jnz     @b
743
        jnz     @b
664
        dbgstr  'warning: taking EHCI ownership from BIOS timeout'
744
        dbgstr  'warning: taking EHCI ownership from BIOS timeout'
665
.force_ownership:
745
.force_ownership:
666
; 4f. BIOS has not responded within the timeout.
746
; 4f. BIOS has not responded within the timeout.
667
; Let's just clear BIOS ownership flag and hope that everything will be ok.
747
; Let's just clear BIOS ownership flag and hope that everything will be ok.
668
        mov     ah, [esi+PCIDEV.bus]
748
        invoke  PciWrite8, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx, 0
669
        mov     al, 0
-
 
670
        mov     cl, 0
-
 
671
        call    pci_write_reg
-
 
672
.has_ownership:
749
.has_ownership:
673
; 5. Just in case clear all SMI event sources except change-ownership.
750
; 5. Just in case clear all SMI event sources except change-ownership.
674
        dbgstr 'has_ownership'
751
        dbgstr 'has_ownership'
675
        inc     ebx
752
        inc     ebx
676
        inc     ebx
753
        inc     ebx
677
        mov     ah, [esi+PCIDEV.bus]
754
        invoke  PciRead16, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx
678
        mov     al, 2
-
 
679
        mov     ecx, eax
-
 
680
        call    pci_read_reg
-
 
681
        and     ax, 2000h
755
        and     ax, 2000h
682
        xchg    eax, ecx
-
 
683
        call    pci_write_reg
756
        invoke  PciWrite16, dword [esi+PCIDEV.bus], dword [esi+PCIDEV.devfn], ebx, eax
684
.has_ownership2:
757
.has_ownership2:
685
        pop     ecx
758
        pop     ecx
686
; 6. Disable all controller interrupts until the system will be ready to
759
; 6. Disable all controller interrupts until the system will be ready to
687
; process them.
760
; process them.
688
        mov     dword [edi+EhciInterruptReg], 0
761
        mov     dword [edi+EhciInterruptReg], 0
689
; 7. Now we can unblock interrupts in the processor.
762
; 7. Now we can unblock interrupts in the processor.
690
        popf
763
        popf
691
; 8. Release memory mapping created in step 2 and return.
764
; 8. Release memory mapping created in step 2 and return.
692
        call    free_kernel_space
765
        invoke  FreeKernelSpace
693
.nothing:
766
.nothing:
694
        ret
767
        ret
695
endp
768
endp
Line 696... Line 769...
696
 
769
 
Line 715... Line 788...
715
; 2. Get the mask of events which should be processed.
788
; 2. Get the mask of events which should be processed.
716
        mov     esi, [.controller]
789
        mov     esi, [.controller]
717
        mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
790
        mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
718
        spin_lock_irqsave [esi+usb_controller.WaitSpinlock]
791
        spin_lock_irqsave [esi+usb_controller.WaitSpinlock]
719
        mov     eax, [edi+EhciStatusReg]
792
        mov     eax, [edi+EhciStatusReg]
720
;       DEBUGF 1,'K : [%d] EHCI status %x\n',[timer_ticks],eax
-
 
721
; 3. Check whether that interrupt has been generated by our controller.
793
; 3. Check whether that interrupt has been generated by our controller.
722
; (One IRQ can be shared by several devices.)
794
; (One IRQ can be shared by several devices.)
723
        and     eax, [edi+EhciInterruptReg]
795
        and     eax, [edi+EhciInterruptReg]
724
        jz      .noint
796
        jz      .noint
725
; 4. Clear the events we know of.
797
; 4. Clear the events we know of.
Line 737... Line 809...
737
; We can't do too much from an interrupt handler. Inform the processing thread
809
; We can't do too much from an interrupt handler. Inform the processing thread
738
; that it should perform appropriate actions.
810
; that it should perform appropriate actions.
739
        or      [esi+ehci_controller.DeferredActions-sizeof.ehci_controller], eax
811
        or      [esi+ehci_controller.DeferredActions-sizeof.ehci_controller], eax
740
        spin_unlock_irqrestore [esi+usb_controller.WaitSpinlock]
812
        spin_unlock_irqrestore [esi+usb_controller.WaitSpinlock]
741
        inc     ebx
813
        inc     ebx
742
        call    usb_wakeup_if_needed
814
        invoke  usbhc_api.usb_wakeup_if_needed
743
; 6. Interrupt processed; return non-zero.
815
; 6. Interrupt processed; return non-zero.
744
        mov     al, 1
816
        mov     al, 1
745
        pop     edi esi ebx     ; restore used registers to be cdecl
817
        pop     edi esi ebx     ; restore used registers to be cdecl
746
        ret
818
        ret
747
endp
819
endp
Line 749... Line 821...
749
; This procedure is called from usb_set_address_callback
821
; This procedure is called from usb_set_address_callback
750
; and stores USB device address in the ehci_pipe structure.
822
; and stores USB device address in the ehci_pipe structure.
751
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
823
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
752
proc ehci_set_device_address
824
proc ehci_set_device_address
753
        mov     byte [ebx+ehci_pipe.Token-sizeof.ehci_pipe], cl
825
        mov     byte [ebx+ehci_pipe.Token-sizeof.ehci_pipe], cl
754
        call    usb_subscribe_control
826
        jmp     [usbhc_api.usb_subscribe_control]
755
        ret
-
 
756
endp
827
endp
Line 757... Line 828...
757
 
828
 
758
; This procedure returns USB device address from the ehci_pipe structure.
829
; This procedure returns USB device address from the ehci_pipe structure.
759
; in: esi -> usb_controller, ebx -> usb_pipe
830
; in: esi -> usb_controller, ebx -> usb_pipe
Line 783... Line 854...
783
        and     eax, not (0x7FF shl 16)
854
        and     eax, not (0x7FF shl 16)
784
        shl     ecx, 16
855
        shl     ecx, 16
785
        or      eax, ecx
856
        or      eax, ecx
786
        mov     [ebx+ehci_pipe.Token-sizeof.ehci_pipe], eax
857
        mov     [ebx+ehci_pipe.Token-sizeof.ehci_pipe], eax
787
; Wait until hardware cache is evicted.
858
; Wait until hardware cache is evicted.
788
        call    usb_subscribe_control
859
        jmp     [usbhc_api.usb_subscribe_control]
789
        ret
-
 
790
endp
860
endp
Line 791... Line 861...
791
 
861
 
792
uglobal
862
uglobal
793
align 4
863
align 4
Line 802... Line 872...
802
; Both hardware+software parts must be allocated, returns pointer to usb_pipe
872
; Both hardware+software parts must be allocated, returns pointer to usb_pipe
803
; (software part).
873
; (software part).
804
proc ehci_alloc_pipe
874
proc ehci_alloc_pipe
805
        push    ebx
875
        push    ebx
806
        mov     ebx, ehci_ep_mutex
876
        mov     ebx, ehci_ep_mutex
807
        stdcall usb_allocate_common, (sizeof.ehci_pipe + sizeof.usb_pipe + 1Fh) and not 1Fh
877
        invoke  usbhc_api.usb_allocate_common, (sizeof.ehci_pipe + sizeof.usb_pipe + 1Fh) and not 1Fh
808
        test    eax, eax
878
        test    eax, eax
809
        jz      @f
879
        jz      @f
810
        add     eax, sizeof.ehci_pipe
880
        add     eax, sizeof.ehci_pipe
811
@@:
881
@@:
812
        pop     ebx
882
        pop     ebx
Line 819... Line 889...
819
virtual at esp
889
virtual at esp
820
        dd      ?       ; return address
890
        dd      ?       ; return address
821
.ptr    dd      ?
891
.ptr    dd      ?
822
end virtual
892
end virtual
823
        sub     [.ptr], sizeof.ehci_pipe
893
        sub     [.ptr], sizeof.ehci_pipe
824
        jmp     usb_free_common
894
        jmp     [usbhc_api.usb_free_common]
825
endp
895
endp
Line 826... Line 896...
826
 
896
 
827
; This procedure is called from API usb_open_pipe and processes
897
; This procedure is called from API usb_open_pipe and processes
828
; the controller-specific part of this API. See docs.
898
; the controller-specific part of this API. See docs.
Line 851... Line 921...
851
        mov     [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx
921
        mov     [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx
852
        mov     [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1
922
        mov     [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1
853
        mov     [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1
923
        mov     [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1
854
; 3. Store physical address of the first TD.
924
; 3. Store physical address of the first TD.
855
        sub     eax, sizeof.ehci_gtd
925
        sub     eax, sizeof.ehci_gtd
856
        call    get_phys_addr
926
        call    [GetPhysAddr]
857
        mov     [edi+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax
927
        mov     [edi+ehci_pipe.Overlay.NextTD-sizeof.ehci_pipe], eax
858
; 4. Fill ehci_pipe.Flags except for S- and C-masks.
928
; 4. Fill ehci_pipe.Flags except for S- and C-masks.
859
; Copy location from the config pipe.
929
; Copy location from the config pipe.
860
        mov     eax, [ecx+ehci_pipe.Flags-sizeof.ehci_pipe]
930
        mov     eax, [ecx+ehci_pipe.Flags-sizeof.ehci_pipe]
861
        and     eax, 3FFF0000h
931
        and     eax, 3FFF0000h
Line 943... Line 1013...
943
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
1013
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
944
; store the physical address of the new pipe to previous NextQH.
1014
; store the physical address of the new pipe to previous NextQH.
945
        mov     ecx, [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart]
1015
        mov     ecx, [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart]
946
        mov     [edi+ehci_pipe.NextQH-sizeof.ehci_pipe], ecx
1016
        mov     [edi+ehci_pipe.NextQH-sizeof.ehci_pipe], ecx
947
        lea     eax, [edi-sizeof.ehci_pipe]
1017
        lea     eax, [edi-sizeof.ehci_pipe]
948
        call    get_phys_addr
1018
        call    [GetPhysAddr]
949
        inc     eax
1019
        inc     eax
950
        inc     eax
1020
        inc     eax
951
        mov     [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], eax
1021
        mov     [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], eax
952
; 6. Return with nonzero eax.
1022
; 6. Return with nonzero eax.
953
        ret
1023
        ret
Line 961... Line 1031...
961
; and therefore is ready to be configured.
1031
; and therefore is ready to be configured.
962
; ecx = port, esi -> ehci_controller, edi -> EHCI MMIO
1032
; ecx = port, esi -> ehci_controller, edi -> EHCI MMIO
963
proc ehci_new_port
1033
proc ehci_new_port
964
; 1. If the device operates at low-speed, just release it to a companion.
1034
; 1. If the device operates at low-speed, just release it to a companion.
965
        mov     eax, [edi+EhciPortsReg+ecx*4]
1035
        mov     eax, [edi+EhciPortsReg+ecx*4]
966
        DEBUGF 1,'K : [%d] EHCI %x port %d state is %x\n',[timer_ticks],esi,ecx,eax
1036
        DEBUGF 1,'K : EHCI %x port %d state is %x\n',esi,ecx,eax
967
        mov     edx, eax
1037
        mov     edx, eax
968
        and     ah, 0Ch
1038
        and     ah, 0Ch
969
        cmp     ah, 4
1039
        cmp     ah, 4
970
        jz      .low_speed
1040
        jz      .low_speed
971
; 2. Devices operating at full-speed and high-speed must now have ah == 8.
1041
; 2. Devices operating at full-speed and high-speed must now have ah == 8.
Line 994... Line 1064...
994
; 2. Initiate reset signalling.
1064
; 2. Initiate reset signalling.
995
        or      ah, 1
1065
        or      ah, 1
996
        and     al, not (4 or 2Ah)
1066
        and     al, not (4 or 2Ah)
997
        mov     [edi+EhciPortsReg+ecx*4], eax
1067
        mov     [edi+EhciPortsReg+ecx*4], eax
998
; 3. Store the current time and set status to 1 = reset signalling active.
1068
; 3. Store the current time and set status to 1 = reset signalling active.
999
        mov     eax, [timer_ticks]
1069
        invoke  GetTimerTicks
1000
        mov     [esi+usb_controller.ResetTime], eax
1070
        mov     [esi+usb_controller.ResetTime], eax
1001
        mov     [esi+usb_controller.ResettingStatus], 1
1071
        mov     [esi+usb_controller.ResettingStatus], 1
1002
;       dbgstr 'high-speed or full-speed device, resetting'
1072
;       dbgstr 'high-speed or full-speed device, resetting'
1003
        DEBUGF 1,'K : [%d] EHCI %x: port %d has HS or FS device, resetting\n',[timer_ticks],esi,ecx
1073
        DEBUGF 1,'K : EHCI %x: port %d has HS or FS device, resetting\n',esi,ecx
1004
        pop     edi
1074
        pop     edi
1005
.nothing:
1075
.nothing:
1006
        ret
1076
        ret
1007
.low_speed:
1077
.low_speed:
1008
;       dbgstr 'low-speed device, releasing'
1078
;       dbgstr 'low-speed device, releasing'
1009
        DEBUGF 1,'K : [%d] EHCI %x: port %d has LS device, releasing\n',[timer_ticks],esi,ecx
1079
        DEBUGF 1,'K : EHCI %x: port %d has LS device, releasing\n',esi,ecx
1010
        or      dh, 20h
1080
        or      dh, 20h
1011
        and     dl, not 2Ah
1081
        and     dl, not 2Ah
1012
        mov     [edi+EhciPortsReg+ecx*4], edx
1082
        mov     [edi+EhciPortsReg+ecx*4], edx
1013
        ret
1083
        ret
1014
.se1:
1084
.se1:
Line 1049... Line 1119...
1049
        jbe     .lastpacket
1119
        jbe     .lastpacket
1050
; 2. While the remaining data cannot fit in one descriptor,
1120
; 2. While the remaining data cannot fit in one descriptor,
1051
; allocate full descriptors (of maximal possible size).
1121
; allocate full descriptors (of maximal possible size).
1052
; 2a. Calculate size of one descriptor: must be a multiple of transfer size
1122
; 2a. Calculate size of one descriptor: must be a multiple of transfer size
1053
; and must be not greater than 4001h.
1123
; and must be not greater than 4001h.
1054
        movzx   ecx, word [ebx+ohci_pipe.Flags+2-sizeof.ohci_pipe]
1124
        movzx   ecx, word [ebx+ehci_pipe.Token+2-sizeof.ehci_pipe]
-
 
1125
        and     ecx, (1 shl 11) - 1
1055
        mov     eax, 4001h
1126
        mov     eax, 4001h
1056
        xor     edx, edx
1127
        xor     edx, edx
1057
        mov     edi, eax
1128
        mov     edi, eax
1058
        div     ecx
1129
        div     ecx
1059
        sub     edi, edx
1130
        sub     edi, edx
Line 1090... Line 1161...
1090
        jmp     @f
1161
        jmp     @f
1091
.disable_short:
1162
.disable_short:
1092
        mov     eax, [ebx+usb_pipe.Controller]
1163
        mov     eax, [ebx+usb_pipe.Controller]
1093
        add     eax, ehci_controller.StopQueueTD - sizeof.ehci_controller
1164
        add     eax, ehci_controller.StopQueueTD - sizeof.ehci_controller
1094
@@:
1165
@@:
1095
        call    get_phys_addr
1166
        call    [GetPhysAddr]
1096
        mov     edx, [origTD]
1167
        mov     edx, [origTD]
1097
@@:
1168
@@:
1098
        cmp     edx, [esp]
1169
        cmp     edx, [esp]
1099
        jz      @f
1170
        jz      @f
1100
        mov     [edx+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], eax
1171
        mov     [edx+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], eax
Line 1104... Line 1175...
1104
        pop     eax
1175
        pop     eax
1105
        ret
1176
        ret
1106
.fail:
1177
.fail:
1107
        mov     edi, ehci_hardware_func
1178
        mov     edi, ehci_hardware_func
1108
        mov     eax, [td]
1179
        mov     eax, [td]
1109
        stdcall usb_undo_tds, [origTD]
1180
        invoke  usbhc_api.usb_undo_tds, [origTD]
1110
        xor     eax, eax
1181
        xor     eax, eax
1111
        ret
1182
        ret
1112
endp
1183
endp
Line 1113... Line 1184...
1113
 
1184
 
Line 1132... Line 1203...
1132
        call    ehci_alloc_td
1203
        call    ehci_alloc_td
1133
        test    eax, eax
1204
        test    eax, eax
1134
        jz      .nothing
1205
        jz      .nothing
1135
; 2. Initialize controller-independent parts of both TDs.
1206
; 2. Initialize controller-independent parts of both TDs.
1136
        push    eax
1207
        push    eax
1137
        call    usb_init_transfer
1208
        invoke  usbhc_api.usb_init_transfer
1138
        pop     eax
1209
        pop     eax
1139
; 3. Copy PID to the new descriptor.
1210
; 3. Copy PID to the new descriptor.
1140
        mov     edx, [ecx+ehci_gtd.Token-sizeof.ehci_gtd]
1211
        mov     edx, [ecx+ehci_gtd.Token-sizeof.ehci_gtd]
1141
        mov     [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx
1212
        mov     [eax+ehci_gtd.Token-sizeof.ehci_gtd], edx
1142
        mov     [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1
1213
        mov     [eax+ehci_gtd.NextTD-sizeof.ehci_gtd], 1
1143
        mov     [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1
1214
        mov     [eax+ehci_gtd.AlternateNextTD-sizeof.ehci_gtd], 1
1144
; 4. Save the returned value (next descriptor).
1215
; 4. Save the returned value (next descriptor).
1145
        push    eax
1216
        push    eax
1146
; 5. Store the physical address of the next descriptor.
1217
; 5. Store the physical address of the next descriptor.
1147
        sub     eax, sizeof.ehci_gtd
1218
        sub     eax, sizeof.ehci_gtd
1148
        call    get_phys_addr
1219
        call    [GetPhysAddr]
1149
        mov     [ecx+ehci_gtd.NextTD-sizeof.ehci_gtd], eax
1220
        mov     [ecx+ehci_gtd.NextTD-sizeof.ehci_gtd], eax
1150
; 6. For zero-length transfers, store zero in all fields for buffer addresses.
1221
; 6. For zero-length transfers, store zero in all fields for buffer addresses.
1151
; Otherwise, fill them with real values.
1222
; Otherwise, fill them with real values.
1152
        xor     eax, eax
1223
        xor     eax, eax
1153
        mov     [ecx+ehci_gtd.Flags-sizeof.ehci_gtd], eax
1224
        mov     [ecx+ehci_gtd.Flags-sizeof.ehci_gtd], eax
Line 1155... Line 1226...
1155
        mov     [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd+(%-1)*4], eax
1226
        mov     [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd+(%-1)*4], eax
1156
end repeat
1227
end repeat
1157
        cmp     [.packetSize], eax
1228
        cmp     [.packetSize], eax
1158
        jz      @f
1229
        jz      @f
1159
        mov     eax, [.buffer]
1230
        mov     eax, [.buffer]
1160
        call    get_phys_addr
1231
        call    [GetPhysAddr]
1161
        mov     [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd], eax
1232
        mov     [ecx+ehci_gtd.BufferPointers-sizeof.ehci_gtd], eax
1162
        and     eax, 0xFFF
1233
        and     eax, 0xFFF
1163
        mov     edx, [.packetSize]
1234
        mov     edx, [.packetSize]
1164
        add     edx, eax
1235
        add     edx, eax
1165
        sub     edx, 0x1000
1236
        sub     edx, 0x1000
1166
        jbe     @f
1237
        jbe     @f
1167
        mov     eax, [.buffer]
1238
        mov     eax, [.buffer]
1168
        add     eax, 0x1000
1239
        add     eax, 0x1000
1169
        call    get_pg_addr
1240
        call    [GetPgAddr]
1170
        mov     [ecx+ehci_gtd.BufferPointers+4-sizeof.ehci_gtd], eax
1241
        mov     [ecx+ehci_gtd.BufferPointers+4-sizeof.ehci_gtd], eax
1171
        sub     edx, 0x1000
1242
        sub     edx, 0x1000
1172
        jbe     @f
1243
        jbe     @f
1173
        mov     eax, [.buffer]
1244
        mov     eax, [.buffer]
1174
        add     eax, 0x2000
1245
        add     eax, 0x2000
1175
        call    get_pg_addr
1246
        call    [GetPgAddr]
1176
        mov     [ecx+ehci_gtd.BufferPointers+8-sizeof.ehci_gtd], eax
1247
        mov     [ecx+ehci_gtd.BufferPointers+8-sizeof.ehci_gtd], eax
1177
        sub     edx, 0x1000
1248
        sub     edx, 0x1000
1178
        jbe     @f
1249
        jbe     @f
1179
        mov     eax, [.buffer]
1250
        mov     eax, [.buffer]
1180
        add     eax, 0x3000
1251
        add     eax, 0x3000
1181
        call    get_pg_addr
1252
        call    [GetPgAddr]
1182
        mov     [ecx+ehci_gtd.BufferPointers+12-sizeof.ehci_gtd], eax
1253
        mov     [ecx+ehci_gtd.BufferPointers+12-sizeof.ehci_gtd], eax
1183
        sub     edx, 0x1000
1254
        sub     edx, 0x1000
1184
        jbe     @f
1255
        jbe     @f
1185
        mov     eax, [.buffer]
1256
        mov     eax, [.buffer]
1186
        add     eax, 0x4000
1257
        add     eax, 0x4000
1187
        call    get_pg_addr
1258
        call    [GetPgAddr]
1188
        mov     [ecx+ehci_gtd.BufferPointers+16-sizeof.ehci_gtd], eax
1259
        mov     [ecx+ehci_gtd.BufferPointers+16-sizeof.ehci_gtd], eax
1189
@@:
1260
@@:
1190
; 7. Fill Token field:
1261
; 7. Fill Token field:
1191
; set Status = 0 (inactive, ehci_insert_transfer would mark everything active);
1262
; set Status = 0 (inactive, ehci_insert_transfer would mark everything active);
1192
; keep current PID if [.direction] is zero, use two lower bits of [.direction]
1263
; keep current PID if [.direction] is zero, use two lower bits of [.direction]
Line 1240... Line 1311...
1240
; This function is called from ehci_process_deferred when
1311
; This function is called from ehci_process_deferred when
1241
; reset signalling for a new device needs to be finished.
1312
; reset signalling for a new device needs to be finished.
1242
proc ehci_port_reset_done
1313
proc ehci_port_reset_done
1243
        movzx   ecx, [esi+usb_controller.ResettingPort]
1314
        movzx   ecx, [esi+usb_controller.ResettingPort]
1244
        and     dword [edi+EhciPortsReg+ecx*4], not 12Ah
1315
        and     dword [edi+EhciPortsReg+ecx*4], not 12Ah
1245
        mov     eax, [timer_ticks]
1316
        invoke  GetTimerTicks
1246
        mov     [esi+usb_controller.ResetTime], eax
1317
        mov     [esi+usb_controller.ResetTime], eax
1247
        mov     [esi+usb_controller.ResettingStatus], 2
1318
        mov     [esi+usb_controller.ResettingStatus], 2
1248
        DEBUGF 1,'K : [%d] EHCI %x: reset port %d done\n',[timer_ticks],esi,ecx
1319
;        DEBUGF 1,'K : EHCI %x: reset port %d done\n',esi,ecx
1249
        ret
1320
        ret
1250
endp
1321
endp
Line 1251... Line 1322...
1251
 
1322
 
1252
; This function is called from ehci_process_deferred when
1323
; This function is called from ehci_process_deferred when
Line 1256... Line 1327...
1256
; If reset has been failed (device disconnected during reset),
1327
; If reset has been failed (device disconnected during reset),
1257
; continue to next device (if there is one).
1328
; continue to next device (if there is one).
1258
        xor     eax, eax
1329
        xor     eax, eax
1259
        xchg    al, [esi+usb_controller.ResettingStatus]
1330
        xchg    al, [esi+usb_controller.ResettingStatus]
1260
        test    al, al
1331
        test    al, al
-
 
1332
        jns     @f
1261
        js      usb_test_pending_port
1333
        jmp     [usbhc_api.usb_test_pending_port]
-
 
1334
@@:
1262
; 2. Get the port status. High-speed devices should be now enabled,
1335
; 2. Get the port status. High-speed devices should be now enabled,
1263
; full-speed devices are left disabled;
1336
; full-speed devices are left disabled;
1264
; if the port is disabled, release it to a companion and continue to
1337
; if the port is disabled, release it to a companion and continue to
1265
; next device (if there is one).
1338
; next device (if there is one).
1266
        movzx   ecx, [esi+usb_controller.ResettingPort]
1339
        movzx   ecx, [esi+usb_controller.ResettingPort]
1267
        mov     eax, [edi+EhciPortsReg+ecx*4]
1340
        mov     eax, [edi+EhciPortsReg+ecx*4]
1268
        DEBUGF 1,'K : [%d] EHCI %x status of port %d is %x\n',[timer_ticks],esi,ecx,eax
1341
        DEBUGF 1,'K : EHCI %x status of port %d is %x\n',esi,ecx,eax
1269
        test    al, 4
1342
        test    al, 4
1270
        jnz     @f
1343
        jnz     @f
1271
;       DEBUGF 1,'K : USB port disabled after reset, status = %x\n',eax
1344
;       DEBUGF 1,'K : USB port disabled after reset, status = %x\n',eax
1272
        dbgstr 'releasing to companion'
1345
        dbgstr 'releasing to companion'
1273
        or      ah, 20h
1346
        or      ah, 20h
1274
        mov     [edi+EhciPortsReg+ecx*4], eax
1347
        mov     [edi+EhciPortsReg+ecx*4], eax
1275
        jmp     usb_test_pending_port
1348
        jmp     [usbhc_api.usb_test_pending_port]
1276
@@:
1349
@@:
1277
; 3. Call the worker procedure to notify the protocol layer
1350
; 3. Call the worker procedure to notify the protocol layer
1278
; about new EHCI device. It is high-speed.
1351
; about new EHCI device. It is high-speed.
1279
        movi    eax, USB_SPEED_HS
1352
        movi    eax, USB_SPEED_HS
1280
        call    ehci_new_device
1353
        call    ehci_new_device
Line 1282... Line 1355...
1282
        jnz     .nothing
1355
        jnz     .nothing
1283
; 4. If something at the protocol layer has failed
1356
; 4. If something at the protocol layer has failed
1284
; (no memory, no bus address), disable the port and stop the initialization.
1357
; (no memory, no bus address), disable the port and stop the initialization.
1285
.disable_exit:
1358
.disable_exit:
1286
        and     dword [edi+EhciPortsReg+ecx*4], not (4 or 2Ah)
1359
        and     dword [edi+EhciPortsReg+ecx*4], not (4 or 2Ah)
1287
        jmp     usb_test_pending_port
1360
        jmp     [usbhc_api.usb_test_pending_port]
1288
.nothing:
1361
.nothing:
1289
        ret
1362
        ret
1290
endp
1363
endp
Line 1291... Line 1364...
1291
 
1364
 
Line 1305... Line 1378...
1305
        jz      .common
1378
        jz      .common
1306
; 4. For low-speed and full-speed devices, fill address:port
1379
; 4. For low-speed and full-speed devices, fill address:port
1307
; of the last high-speed hub (the closest to the device hub)
1380
; of the last high-speed hub (the closest to the device hub)
1308
; for split transactions, and set ControlEndpoint bit in eax;
1381
; for split transactions, and set ControlEndpoint bit in eax;
1309
; ehci_init_pipe assumes that the parent pipe is a control pipe.
1382
; ehci_init_pipe assumes that the parent pipe is a control pipe.
-
 
1383
        push    eax
1310
        movzx   ecx, [esi+usb_controller.ResettingPort]
1384
        movzx   ecx, [esi+usb_controller.ResettingPort]
1311
        mov     edx, [esi+usb_controller.ResettingHub]
1385
        mov     edx, [esi+usb_controller.ResettingHub]
1312
; If the parent hub is high-speed, it is TT for the device.
-
 
1313
; Otherwise, the parent hub itself is behind TT, and the device
-
 
1314
; has the same TT hub+port as the parent hub.
-
 
1315
        push    eax
-
 
1316
        mov     eax, [edx+usb_hub.ConfigPipe]
-
 
1317
        mov     eax, [eax+usb_pipe.DeviceData]
-
 
1318
        cmp     [eax+usb_device_data.Speed], USB_SPEED_HS
-
 
1319
        jz      @f
-
 
1320
        movzx   ecx, [eax+usb_device_data.TTPort]
1386
        invoke  usbhc_api.usb_get_tt
1321
        mov     edx, [eax+usb_device_data.TTHub]
-
 
1322
@@:
-
 
1323
        mov     edx, [edx+usb_hub.ConfigPipe]
-
 
1324
        inc     ecx
1387
        inc     ecx
1325
        mov     edx, [edx+ehci_pipe.Token-sizeof.ehci_pipe]
1388
        mov     edx, [edx+ehci_pipe.Token-sizeof.ehci_pipe]
1326
        shl     ecx, 23
1389
        shl     ecx, 23
1327
        and     edx, 7Fh
1390
        and     edx, 7Fh
1328
        shl     edx, 16
1391
        shl     edx, 16
Line 1336... Line 1399...
1336
        mov     ecx, esp
1399
        mov     ecx, esp
1337
        sub     esp, sizeof.ehci_pipe - ehci_pipe.Flags - 4
1400
        sub     esp, sizeof.ehci_pipe - ehci_pipe.Flags - 4
1338
        push    edx     ; ehci_pipe.Flags
1401
        push    edx     ; ehci_pipe.Flags
1339
        push    eax     ; ehci_pipe.Token
1402
        push    eax     ; ehci_pipe.Token
1340
; 6. Notify the protocol layer.
1403
; 6. Notify the protocol layer.
1341
        call    usb_new_device
1404
        invoke  usbhc_api.usb_new_device
1342
; 7. Cleanup the stack after step 5 and return.
1405
; 7. Cleanup the stack after step 5 and return.
1343
        add     esp, sizeof.ehci_pipe - ehci_pipe.Flags + 8
1406
        add     esp, sizeof.ehci_pipe - ehci_pipe.Flags + 8
1344
        pop     ecx ebx ; restore used registers
1407
        pop     ecx ebx ; restore used registers
1345
        ret
1408
        ret
1346
endp
1409
endp
Line 1376... Line 1439...
1376
; the first read and the clearing, invalidating the old status. If an event
1439
; the first read and the clearing, invalidating the old status. If an event
1377
; occurs after the clearing, we will not miss it, looking in the next scan.
1440
; occurs after the clearing, we will not miss it, looking in the next scan.
1378
        mov     [edi+EhciPortsReg+ecx*4], eax
1441
        mov     [edi+EhciPortsReg+ecx*4], eax
1379
        mov     ebx, eax
1442
        mov     ebx, eax
1380
        mov     eax, [edi+EhciPortsReg+ecx*4]
1443
        mov     eax, [edi+EhciPortsReg+ecx*4]
1381
        DEBUGF 1,'K : [%d] EHCI %x: status of port %d changed to %x\n',[timer_ticks],esi,ecx,ebx
1444
        DEBUGF 1,'K : EHCI %x: status of port %d changed to %x\n',esi,ecx,ebx
1382
; 3e. Handle overcurrent.
1445
; 3e. Handle overcurrent.
1383
; Note: that needs work.
1446
; Note: that needs work.
1384
        test    bl, 20h ; overcurrent change
1447
        test    bl, 20h ; overcurrent change
1385
        jz      .noovercurrent
1448
        jz      .noovercurrent
1386
        test    al, 10h ; overcurrent active
1449
        test    al, 10h ; overcurrent active
Line 1409... Line 1472...
1409
; 3h. Change connected status. For the connection event, also store
1472
; 3h. Change connected status. For the connection event, also store
1410
; the connection time; any further processing is permitted only after
1473
; the connection time; any further processing is permitted only after
1411
; USB_CONNECT_DELAY ticks.
1474
; USB_CONNECT_DELAY ticks.
1412
        test    al, 1
1475
        test    al, 1
1413
        jz      .disconnect
1476
        jz      .disconnect
1414
        mov     eax, [timer_ticks]
1477
        invoke  GetTimerTicks
1415
        mov     [esi+usb_controller.ConnectedTime+ecx*4], eax
1478
        mov     [esi+usb_controller.ConnectedTime+ecx*4], eax
1416
        bts     [esi+usb_controller.NewConnected], ecx
1479
        bts     [esi+usb_controller.NewConnected], ecx
1417
        jmp     .nextport
1480
        jmp     .nextport
1418
.disconnect:
1481
.disconnect:
1419
        btr     [esi+usb_controller.NewConnected], ecx
1482
        btr     [esi+usb_controller.NewConnected], ecx
Line 1433... Line 1496...
1433
        cmp     ecx, [esi+usb_controller.NumPorts]
1496
        cmp     ecx, [esi+usb_controller.NumPorts]
1434
        jb      .portloop
1497
        jb      .portloop
1435
.skip_roothub:
1498
.skip_roothub:
1436
; 4. Process disconnect events. This should be done after step 3
1499
; 4. Process disconnect events. This should be done after step 3
1437
; (which includes the first stage of disconnect processing).
1500
; (which includes the first stage of disconnect processing).
1438
        call    usb_disconnect_stage2
1501
        invoke  usbhc_api.usb_disconnect_stage2
1439
; 5. Check for previously connected devices.
1502
; 5. Check for previously connected devices.
1440
; If there is a connected device which was connected less than
1503
; If there is a connected device which was connected less than
1441
; USB_CONNECT_DELAY ticks ago, plan to wake up when the delay will be over.
1504
; USB_CONNECT_DELAY ticks ago, plan to wake up when the delay will be over.
1442
; Otherwise, call ehci_new_port.
1505
; Otherwise, call ehci_new_port.
1443
; This should be done after step 3.
1506
; This should be done after step 3.
Line 1445... Line 1508...
1445
        cmp     [esi+usb_controller.NewConnected], ecx
1508
        cmp     [esi+usb_controller.NewConnected], ecx
1446
        jz      .skip_newconnected
1509
        jz      .skip_newconnected
1447
.portloop2:
1510
.portloop2:
1448
        bt      [esi+usb_controller.NewConnected], ecx
1511
        bt      [esi+usb_controller.NewConnected], ecx
1449
        jnc     .noconnect
1512
        jnc     .noconnect
1450
        mov     eax, [timer_ticks]
1513
        invoke  GetTimerTicks
1451
        sub     eax, [esi+usb_controller.ConnectedTime+ecx*4]
1514
        sub     eax, [esi+usb_controller.ConnectedTime+ecx*4]
1452
        sub     eax, USB_CONNECT_DELAY
1515
        sub     eax, USB_CONNECT_DELAY
1453
        jge     .connected
1516
        jge     .connected
1454
        neg     eax
1517
        neg     eax
1455
        cmp     [esp], eax
1518
        cmp     [esp], eax
Line 1486... Line 1549...
1486
.noperiodic:
1549
.noperiodic:
1487
; 6b. Asynchronous endpoints.
1550
; 6b. Asynchronous endpoints.
1488
; Satisfy a request when InterruptOnAsyncAdvance fired.
1551
; Satisfy a request when InterruptOnAsyncAdvance fired.
1489
        test    byte [esp+4], 20h
1552
        test    byte [esp+4], 20h
1490
        jz      @f
1553
        jz      @f
1491
        dbgstr 'async advance int'
1554
;        dbgstr 'async advance int'
1492
        mov     eax, [esi+usb_controller.WaitPipeRequestAsync]
1555
        mov     eax, [esi+usb_controller.WaitPipeRequestAsync]
1493
        mov     [esi+usb_controller.ReadyPipeHeadAsync], eax
1556
        mov     [esi+usb_controller.ReadyPipeHeadAsync], eax
1494
@@:
1557
@@:
1495
; Some hardware in some (rarely) conditions set the status bit,
1558
; Some hardware in some (rarely) conditions set the status bit,
1496
; but just does not generate the corresponding interrupt.
1559
; but just does not generate the corresponding interrupt.
Line 1529... Line 1592...
1529
.test_reset:
1592
.test_reset:
1530
; 8a. Test whether reset signalling is active.
1593
; 8a. Test whether reset signalling is active.
1531
        cmp     [esi+usb_controller.ResettingStatus], 1
1594
        cmp     [esi+usb_controller.ResettingStatus], 1
1532
        jnz     .no_reset_in_progress
1595
        jnz     .no_reset_in_progress
1533
; 8b. Yep. Test whether it should be stopped.
1596
; 8b. Yep. Test whether it should be stopped.
1534
        mov     eax, [timer_ticks]
1597
        invoke  GetTimerTicks
1535
        sub     eax, [esi+usb_controller.ResetTime]
1598
        sub     eax, [esi+usb_controller.ResetTime]
1536
        sub     eax, USB_RESET_TIME
1599
        sub     eax, USB_RESET_TIME
1537
        jge     .reset_done
1600
        jge     .reset_done
1538
; 8c. Not yet, but initiate wakeup in -eax ticks and exit this step.
1601
; 8c. Not yet, but initiate wakeup in -eax ticks and exit this step.
1539
        neg     eax
1602
        neg     eax
Line 1547... Line 1610...
1547
.no_reset_in_progress:
1610
.no_reset_in_progress:
1548
; 8e. Test whether reset process is done, either successful or failed.
1611
; 8e. Test whether reset process is done, either successful or failed.
1549
        cmp     [esi+usb_controller.ResettingStatus], 0
1612
        cmp     [esi+usb_controller.ResettingStatus], 0
1550
        jz      .skip_reset
1613
        jz      .skip_reset
1551
; 8f. Yep. Test whether it should be stopped.
1614
; 8f. Yep. Test whether it should be stopped.
1552
        mov     eax, [timer_ticks]
1615
        invoke  GetTimerTicks
1553
        sub     eax, [esi+usb_controller.ResetTime]
1616
        sub     eax, [esi+usb_controller.ResetTime]
1554
        sub     eax, USB_RESET_RECOVERY_TIME
1617
        sub     eax, USB_RESET_RECOVERY_TIME
1555
        jge     .reset_recovery_done
1618
        jge     .reset_recovery_done
1556
; 8g. Not yet, but initiate wakeup in -eax ticks and exit this step.
1619
; 8g. Not yet, but initiate wakeup in -eax ticks and exit this step.
1557
        neg     eax
1620
        neg     eax
Line 1566... Line 1629...
1566
        jmp     .test_reset
1629
        jmp     .test_reset
1567
.skip_reset:
1630
.skip_reset:
1568
; 9. Process wait-done notifications, test for new wait requests.
1631
; 9. Process wait-done notifications, test for new wait requests.
1569
; Note: that must be done after steps 4 and 7 which could create new requests.
1632
; Note: that must be done after steps 4 and 7 which could create new requests.
1570
; 9a. Call the worker function.
1633
; 9a. Call the worker function.
1571
        call    usb_process_wait_lists
1634
        invoke  usbhc_api.usb_process_wait_lists
1572
; 9b. If it reports that an asynchronous endpoint should be removed,
1635
; 9b. If it reports that an asynchronous endpoint should be removed,
1573
; doorbell InterruptOnAsyncAdvance and schedule wakeup in 1s
1636
; doorbell InterruptOnAsyncAdvance and schedule wakeup in 1s
1574
; (sometimes it just does not fire).
1637
; (sometimes it just does not fire).
1575
        test    al, 1 shl CONTROL_PIPE
1638
        test    al, 1 shl CONTROL_PIPE
1576
        jz      @f
1639
        jz      @f
1577
        mov     edx, [esi+usb_controller.WaitPipeListAsync]
1640
        mov     edx, [esi+usb_controller.WaitPipeListAsync]
1578
        mov     [esi+usb_controller.WaitPipeRequestAsync], edx
1641
        mov     [esi+usb_controller.WaitPipeRequestAsync], edx
1579
        or      dword [edi+EhciCommandReg], 1 shl 6
1642
        or      dword [edi+EhciCommandReg], 1 shl 6
1580
        dbgstr 'async advance doorbell'
1643
;        dbgstr 'async advance doorbell'
1581
        cmp     dword [esp], 100
1644
        cmp     dword [esp], 100
1582
        jb      @f
1645
        jb      @f
1583
        mov     dword [esp], 100
1646
        mov     dword [esp], 100
1584
@@:
1647
@@:
1585
; 9c. If it reports that a periodic endpoint should be removed,
1648
; 9c. If it reports that a periodic endpoint should be removed,
Line 1647... Line 1710...
1647
; 2. For every pipe, perform the internal loop over all descriptors.
1710
; 2. For every pipe, perform the internal loop over all descriptors.
1648
; All descriptors are organized in the queue; we process items from the start
1711
; All descriptors are organized in the queue; we process items from the start
1649
; of the queue until a) the last descriptor (not the part of the queue itself)
1712
; of the queue until a) the last descriptor (not the part of the queue itself)
1650
; or b) an active (not yet processed by the hardware) descriptor is reached.
1713
; or b) an active (not yet processed by the hardware) descriptor is reached.
1651
        lea     ecx, [ebx+usb_pipe.Lock]
1714
        lea     ecx, [ebx+usb_pipe.Lock]
1652
        call    mutex_lock
1715
        invoke  MutexLock
1653
        mov     ebx, [ebx+usb_pipe.LastTD]
1716
        mov     ebx, [ebx+usb_pipe.LastTD]
1654
        push    ebx
1717
        push    ebx
1655
        mov     ebx, [ebx+usb_gtd.NextVirt]
1718
        mov     ebx, [ebx+usb_gtd.NextVirt]
1656
.tdloop:
1719
.tdloop:
1657
; 3. For every descriptor, test active flag and check for end-of-queue;
1720
; 3. For every descriptor, test active flag and check for end-of-queue;
Line 1661... Line 1724...
1661
        cmp     byte [ebx+ehci_gtd.Token-sizeof.ehci_gtd], 0
1724
        cmp     byte [ebx+ehci_gtd.Token-sizeof.ehci_gtd], 0
1662
        js      .tddone
1725
        js      .tddone
1663
; Release the queue lock while processing one descriptor:
1726
; Release the queue lock while processing one descriptor:
1664
; callback function could (and often would) schedule another transfer.
1727
; callback function could (and often would) schedule another transfer.
1665
        push    ecx
1728
        push    ecx
1666
        call    mutex_unlock
1729
        invoke  MutexUnlock
1667
        call    ehci_process_updated_td
1730
        call    ehci_process_updated_td
1668
        pop     ecx
1731
        pop     ecx
1669
        call    mutex_lock
1732
        invoke  MutexLock
1670
        jmp     .tdloop
1733
        jmp     .tdloop
1671
.tddone:
1734
.tddone:
1672
        call    mutex_unlock
1735
        invoke  MutexUnlock
1673
        pop     ebx
1736
        pop     ebx
1674
; End of internal loop, restore pointer to the next pipe
1737
; End of internal loop, restore pointer to the next pipe
1675
; and continue the external loop.
1738
; and continue the external loop.
1676
        pop     ebx
1739
        pop     ebx
1677
        jmp     .loop
1740
        jmp     .loop
Line 1693... Line 1756...
1693
;       lea     eax, [ebx-sizeof.ehci_gtd]
1756
;       lea     eax, [ebx-sizeof.ehci_gtd]
1694
;       DEBUGF 1,'K : %x %x %x %x\n',[eax],[eax+4],[eax+8],[eax+12]
1757
;       DEBUGF 1,'K : %x %x %x %x\n',[eax],[eax+4],[eax+8],[eax+12]
1695
;       DEBUGF 1,'K : %x %x %x %x\n',[eax+16],[eax+20],[eax+24],[eax+28]
1758
;       DEBUGF 1,'K : %x %x %x %x\n',[eax+16],[eax+20],[eax+24],[eax+28]
1696
;@@:
1759
;@@:
1697
; 1. Remove this descriptor from the list of descriptors for this pipe.
1760
; 1. Remove this descriptor from the list of descriptors for this pipe.
1698
        call    usb_unlink_td
1761
        invoke  usbhc_api.usb_unlink_td
1699
; 2. Calculate actual number of bytes transferred.
1762
; 2. Calculate actual number of bytes transferred.
1700
        mov     eax, [ebx+ehci_gtd.Token-sizeof.ehci_gtd]
1763
        mov     eax, [ebx+ehci_gtd.Token-sizeof.ehci_gtd]
1701
        lea     edx, [eax+eax]
1764
        lea     edx, [eax+eax]
1702
        shr     edx, 17
1765
        shr     edx, 17
1703
        sub     edx, [ebx+usb_gtd.Length]
1766
        sub     edx, [ebx+usb_gtd.Length]
Line 1721... Line 1784...
1721
        jnz     .special
1784
        jnz     .special
1722
.notify:
1785
.notify:
1723
; 4. Either the descriptor in ebx was processed without errors,
1786
; 4. Either the descriptor in ebx was processed without errors,
1724
; or all necessary error actions were taken and ebx points to the last
1787
; or all necessary error actions were taken and ebx points to the last
1725
; related descriptor.
1788
; related descriptor.
1726
; 4a. Test whether it is the last descriptor in the transfer
-
 
1727
; <=> it has an associated callback.
-
 
1728
        mov     eax, [ebx+usb_gtd.Callback]
-
 
1729
        test    eax, eax
-
 
1730
        jz      .nocallback
-
 
1731
; 4b. It has an associated callback; call it with corresponding parameters.
-
 
1732
        stdcall_verify eax, [ebx+usb_gtd.Pipe], ecx, \
-
 
1733
                [ebx+usb_gtd.Buffer], edx, [ebx+usb_gtd.UserData]
-
 
1734
        jmp     .callback
-
 
1735
.nocallback:
-
 
1736
; 4c. It is an intermediate descriptor. Add its length to the length
-
 
1737
; in the following descriptor.
-
 
1738
        mov     eax, [ebx+usb_gtd.NextVirt]
1789
        invoke  usbhc_api.usb_process_gtd
1739
        add     [eax+usb_gtd.Length], edx
-
 
1740
.callback:
-
 
1741
; 5. Free the current descriptor and return the next one.
1790
; 5. Free the current descriptor and return the next one.
1742
        push    [ebx+usb_gtd.NextVirt]
1791
        push    [ebx+usb_gtd.NextVirt]
1743
        stdcall ehci_free_td, ebx
1792
        stdcall ehci_free_td, ebx
1744
        pop     ebx
1793
        pop     ebx
1745
        ret
1794
        ret
Line 1763... Line 1812...
1763
        push    eax
1812
        push    eax
1764
; 6b. Traverse the list of descriptors looking for the final descriptor
1813
; 6b. Traverse the list of descriptors looking for the final descriptor
1765
; for this transfer. Free and unlink non-final descriptors.
1814
; for this transfer. Free and unlink non-final descriptors.
1766
; Final descriptor will be freed in step 5.
1815
; Final descriptor will be freed in step 5.
1767
.look_final:
1816
.look_final:
1768
        call    usb_is_final_packet
1817
        invoke  usbhc_api.usb_is_final_packet
1769
        jnc     .found_final
1818
        jnc     .found_final
1770
        push    [ebx+usb_gtd.NextVirt]
1819
        push    [ebx+usb_gtd.NextVirt]
1771
        stdcall ehci_free_td, ebx
1820
        stdcall ehci_free_td, ebx
1772
        pop     ebx
1821
        pop     ebx
1773
        call    usb_unlink_td
1822
        invoke  usbhc_api.usb_unlink_td
1774
        jmp     .look_final
1823
        jmp     .look_final
1775
.found_final:
1824
.found_final:
1776
; 6c. Restore the status saved in 6a and transform it to the error code.
1825
; 6c. Restore the status saved in 6a and transform it to the error code.
1777
; Notes:
1826
; Notes:
1778
; * any USB transaction error results in Halted bit; if it is not set,
1827
; * any USB transaction error results in Halted bit; if it is not set,
Line 1820... Line 1869...
1820
        jnz     .normal
1869
        jnz     .normal
1821
        push    ecx
1870
        push    ecx
1822
        push    [ebx+usb_gtd.NextVirt]
1871
        push    [ebx+usb_gtd.NextVirt]
1823
        stdcall ehci_free_td, ebx
1872
        stdcall ehci_free_td, ebx
1824
        pop     ebx
1873
        pop     ebx
1825
        call    usb_unlink_td
1874
        invoke  usbhc_api.usb_unlink_td
1826
        pop     ecx
1875
        pop     ecx
1827
.normal:
1876
.normal:
1828
; 6f. For bulk/interrupt transfers we have no choice but halt the queue,
1877
; 6f. For bulk/interrupt transfers we have no choice but halt the queue,
1829
; the driver should intercede (through some API which is not written yet).
1878
; the driver should intercede (through some API which is not written yet).
1830
; Control pipes normally recover at the next SETUP transaction (first stage
1879
; Control pipes normally recover at the next SETUP transaction (first stage
Line 1880... Line 1929...
1880
endp
1929
endp
Line 1881... Line 1930...
1881
 
1930
 
1882
proc ehci_alloc_td
1931
proc ehci_alloc_td
1883
        push    ebx
1932
        push    ebx
1884
        mov     ebx, ehci_gtd_mutex
1933
        mov     ebx, ehci_gtd_mutex
1885
        stdcall usb_allocate_common, (sizeof.ehci_gtd + sizeof.usb_gtd + 1Fh) and not 1Fh
1934
        invoke  usbhc_api.usb_allocate_common, (sizeof.ehci_gtd + sizeof.usb_gtd + 1Fh) and not 1Fh
1886
        test    eax, eax
1935
        test    eax, eax
1887
        jz      @f
1936
        jz      @f
1888
        add     eax, sizeof.ehci_gtd
1937
        add     eax, sizeof.ehci_gtd
1889
@@:
1938
@@:
Line 1894... Line 1943...
1894
; This procedure is called from several places from main USB code and
1943
; This procedure is called from several places from main USB code and
1895
; frees all additional data associated with the transfer descriptor.
1944
; frees all additional data associated with the transfer descriptor.
1896
; EHCI has no additional data, so just free ehci_gtd structure.
1945
; EHCI has no additional data, so just free ehci_gtd structure.
1897
proc ehci_free_td
1946
proc ehci_free_td
1898
        sub     dword [esp+4], sizeof.ehci_gtd
1947
        sub     dword [esp+4], sizeof.ehci_gtd
1899
        jmp     usb_free_common
1948
        jmp     [usbhc_api.usb_free_common]
1900
endp
1949
endp
-
 
1950
 
-
 
1951
include 'ehci_scheduler.inc'
-
 
1952
 
-
 
1953
section '.data' readable writable
-
 
1954
include '../peimport.inc'
-
 
1955
include_debug_strings
-
 
1956
IncludeIGlobals
-
 
1957
IncludeUGlobals
-
 
1958
align 4
-
 
1959
usbhc_api usbhc_func