Subversion Repositories Kolibri OS

Rev

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

Rev 4423 Rev 5201
Line -... Line 1...
-
 
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
 
2
;;                                                              ;;
-
 
3
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
-
 
4
;; Distributed under terms of the GNU General Public License    ;;
-
 
5
;;                                                              ;;
-
 
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
 
7
 
-
 
8
$Revision: 4850 $
-
 
9
 
-
 
10
 
1
; Functions for USB pipe manipulation: opening/closing, sending data etc.
11
; Functions for USB pipe manipulation: opening/closing, sending data etc.
2
;
12
;
3
USB_STDCALL_VERIFY = 1
13
USB_STDCALL_VERIFY = 1
4
macro stdcall_verify [arg]
14
macro stdcall_verify [arg]
5
{
15
{
Line 11... Line 21...
11
        popad
21
        popad
12
else
22
else
13
        stdcall arg
23
        stdcall arg
14
end if
24
end if
15
}
25
}
-
 
26
if USB_STDCALL_VERIFY
-
 
27
STDCALL_VERIFY_EXTRA = 20h
-
 
28
else
-
 
29
STDCALL_VERIFY_EXTRA = 0
-
 
30
end if
Line 16... Line 31...
16
 
31
 
17
; Initialization of usb_static_ep structure,
32
; Initialization of usb_static_ep structure,
18
; called from controller-specific initialization; edi -> usb_static_ep
33
; called from controller-specific initialization; edi -> usb_static_ep
19
proc usb_init_static_endpoint
34
proc usb_init_static_endpoint
Line 236... Line 251...
236
@@:
251
@@:
237
        push    edx
252
        push    edx
238
        call    mutex_lock
253
        call    mutex_lock
239
        push    ecx
254
        push    ecx
240
; 3b. Let the controller-specific code do its job.
255
; 3b. Let the controller-specific code do its job.
-
 
256
        test    [ebx+usb_pipe.Flags], USB_FLAG_DISABLED
-
 
257
        jnz     @f
-
 
258
        mov     eax, [esi+usb_controller.HardwareFunc]
-
 
259
        call    [eax+usb_hardware_func.DisablePipe]
-
 
260
@@:
241
        mov     eax, [esi+usb_controller.HardwareFunc]
261
        mov     eax, [esi+usb_controller.HardwareFunc]
242
        call    [eax+usb_hardware_func.UnlinkPipe]
262
        call    [eax+usb_hardware_func.UnlinkPipe]
-
 
263
        mov     edx, [ebx+usb_pipe.NextVirt]
-
 
264
        mov     eax, [ebx+usb_pipe.PrevVirt]
-
 
265
        mov     [edx+usb_pipe.PrevVirt], eax
-
 
266
        mov     [eax+usb_pipe.NextVirt], edx
243
; 3c. Release the corresponding lock.
267
; 3c. Release the corresponding lock.
244
        pop     ecx
268
        pop     ecx
245
        call    mutex_unlock
269
        call    mutex_unlock
246
; 4. Put the pipe into wait queue.
270
; 4. Put the pipe into wait queue.
247
        pop     edx
271
        pop     edx
Line 260... Line 284...
260
        call    mutex_unlock
284
        call    mutex_unlock
261
        xor     eax, eax
285
        xor     eax, eax
262
        ret
286
        ret
263
endp
287
endp
Line -... Line 288...
-
 
288
 
-
 
289
; This procedure is called when all transfers are aborted
-
 
290
; either due to call to usb_abort_pipe or due to pipe closing.
-
 
291
; It notifies all callbacks and frees all transfer descriptors.
-
 
292
; ebx -> usb_pipe, esi -> usb_controller, edi -> usb_hardware_func
-
 
293
; three stack parameters: status code for callback functions
-
 
294
; and descriptors where to start and stop.
-
 
295
proc usb_pipe_aborted
-
 
296
virtual at esp
-
 
297
                dd      ?       ; return address
-
 
298
.status         dd      ?       ; USB_STATUS_CLOSED or USB_STATUS_CANCELLED
-
 
299
.first_td       dd      ?
-
 
300
.last_td        dd      ?
-
 
301
end virtual
-
 
302
; Loop over all transfers, calling the driver with the given status
-
 
303
; and freeing all descriptors except the last one.
-
 
304
.loop:
-
 
305
        mov     edx, [.first_td]
-
 
306
        cmp     edx, [.last_td]
-
 
307
        jz      .done
-
 
308
        mov     ecx, [edx+usb_gtd.Callback]
-
 
309
        test    ecx, ecx
-
 
310
        jz      .no_callback
-
 
311
        stdcall_verify ecx, ebx, [.status+12+STDCALL_VERIFY_EXTRA], \
-
 
312
                [edx+usb_gtd.Buffer], 0, [edx+usb_gtd.UserData]
-
 
313
        mov     edx, [.first_td]
-
 
314
.no_callback:
-
 
315
        mov     eax, [edx+usb_gtd.NextVirt]
-
 
316
        mov     [.first_td], eax
-
 
317
        stdcall [edi+usb_hardware_func.FreeTD], edx
-
 
318
        jmp     .loop
-
 
319
.done:
-
 
320
        ret     12
-
 
321
endp
264
 
322
 
265
; This procedure is called when a pipe with USB_FLAG_CLOSED is removed from the
323
; This procedure is called when a pipe with USB_FLAG_CLOSED is removed from the
266
; corresponding wait list. It means that the hardware has fully forgot about it.
324
; corresponding wait list. It means that the hardware has fully forgot about it.
267
; ebx -> usb_pipe, esi -> usb_controller
325
; ebx -> usb_pipe, esi -> usb_controller
268
proc usb_pipe_closed
326
proc usb_pipe_closed
269
        push    edi
327
        push    edi
270
        mov     edi, [esi+usb_controller.HardwareFunc]
328
        mov     edi, [esi+usb_controller.HardwareFunc]
271
; 1. Loop over all transfers, calling the driver with USB_STATUS_CLOSED
329
; 1. Notify all registered callbacks with status USB_STATUS_CLOSED, if any,
-
 
330
; and free all transfer descriptors, including the last one.
-
 
331
        lea     ecx, [ebx+usb_pipe.Lock]
272
; and freeing all descriptors.
332
        call    mutex_lock
273
        mov     edx, [ebx+usb_pipe.LastTD]
333
        mov     edx, [ebx+usb_pipe.LastTD]
274
        test    edx, edx
334
        test    edx, edx
275
        jz      .no_transfer
335
        jz      .no_transfer
276
        mov     edx, [edx+usb_gtd.NextVirt]
-
 
277
.transfer_loop:
-
 
278
        cmp     edx, [ebx+usb_pipe.LastTD]
-
 
279
        jz      .transfer_done
-
 
280
        mov     ecx, [edx+usb_gtd.Callback]
-
 
281
        test    ecx, ecx
-
 
282
        jz      .no_callback
336
        mov     eax, [edx+usb_gtd.NextVirt]
283
        push    edx
-
 
284
        stdcall_verify ecx, ebx, USB_STATUS_CLOSED, \
-
 
285
                [edx+usb_gtd.Buffer], 0, [edx+usb_gtd.UserData]
337
        push    edx
286
        pop     edx
338
        push    eax
287
.no_callback:
339
        call    mutex_unlock
288
        push    [edx+usb_gtd.NextVirt]
340
        push    USB_STATUS_CLOSED
289
        stdcall [edi+usb_hardware_func.FreeTD], edx
341
        call    usb_pipe_aborted
290
        pop     edx
342
; It is safe to free LastTD here:
291
        jmp     .transfer_loop
-
 
292
.transfer_done:
343
; usb_*_transfer_async do not enqueue new transfers if USB_FLAG_CLOSED is set.
-
 
344
        stdcall [edi+usb_hardware_func.FreeTD], [ebx+usb_pipe.LastTD]
293
        stdcall [edi+usb_hardware_func.FreeTD], edx
345
        jmp     @f
-
 
346
.no_transfer:
-
 
347
        call    mutex_unlock
294
.no_transfer:
348
@@:
295
; 2. Decrement number of pipes for the device.
349
; 2. Decrement number of pipes for the device.
296
; If this pipe is the last pipe, go to 5.
350
; If this pipe is the last pipe, go to 5.
297
        mov     ecx, [ebx+usb_pipe.DeviceData]
351
        mov     ecx, [ebx+usb_pipe.DeviceData]
298
        call    mutex_lock
352
        call    mutex_lock
Line 340... Line 394...
340
@@:
394
@@:
341
        add     ecx, sizeof.usb_interface_data
395
        add     ecx, sizeof.usb_interface_data
342
        dec     eax
396
        dec     eax
343
        jnz     .notify_loop
397
        jnz     .notify_loop
344
.notify_done:
398
.notify_done:
-
 
399
; 6. Kill the timer, if active.
-
 
400
; (Usually not; possible if device is disconnected
-
 
401
; while processing SET_ADDRESS request).
-
 
402
        mov     eax, [ebx+usb_pipe.DeviceData]
-
 
403
        cmp     [eax+usb_device_data.Timer], 0
-
 
404
        jz      @f
-
 
405
        stdcall cancel_timer_hs, [eax+usb_device_data.Timer]
-
 
406
        mov     [eax+usb_device_data.Timer], 0
-
 
407
@@:
345
; 6. Bus address, if assigned, can now be reused.
408
; 7. Bus address, if assigned, can now be reused.
346
        call    [edi+usb_hardware_func.GetDeviceAddress]
409
        call    [edi+usb_hardware_func.GetDeviceAddress]
347
        test    eax, eax
410
        test    eax, eax
348
        jz      @f
411
        jz      @f
349
        bts     [esi+usb_controller.ExistingAddresses], eax
412
        bts     [esi+usb_controller.ExistingAddresses], eax
350
@@:
413
@@:
351
        dbgstr 'USB device disconnected'
414
        dbgstr 'USB device disconnected'
352
; 7. All drivers have returned from disconnect callback,
415
; 8. All drivers have returned from disconnect callback,
353
; so all drivers should not use any device-related pipes.
416
; so all drivers should not use any device-related pipes.
354
; Free the remaining pipes.
417
; Free the remaining pipes.
355
        mov     eax, [ebx+usb_pipe.DeviceData]
418
        mov     eax, [ebx+usb_pipe.DeviceData]
356
        add     eax, usb_device_data.ClosedPipeList - usb_pipe.NextSibling
419
        add     eax, usb_device_data.ClosedPipeList - usb_pipe.NextSibling
357
        push    eax
420
        push    eax
Line 364... Line 427...
364
        pop     eax
427
        pop     eax
365
        jmp     .free_loop
428
        jmp     .free_loop
366
.free_done:
429
.free_done:
367
        stdcall [edi+usb_hardware_func.FreePipe], ebx
430
        stdcall [edi+usb_hardware_func.FreePipe], ebx
368
        pop     eax
431
        pop     eax
369
; 8. Free the usb_device_data structure.
432
; 9. Free the usb_device_data structure.
370
        sub     eax, usb_device_data.ClosedPipeList - usb_pipe.NextSibling
433
        sub     eax, usb_device_data.ClosedPipeList - usb_pipe.NextSibling
371
        call    free
434
        call    free
372
; 9. Return.
435
; 10. Return.
373
.nothing:
436
.nothing:
374
        pop     edi
437
        pop     edi
375
        ret
438
        ret
376
endp
439
endp
Line -... Line 440...
-
 
440
 
-
 
441
; This procedure is called when a pipe with USB_FLAG_DISABLED is removed from the
-
 
442
; corresponding wait list. It means that the hardware has fully forgot about it.
-
 
443
; ebx -> usb_pipe, esi -> usb_controller
-
 
444
proc usb_pipe_disabled
-
 
445
        push    edi
-
 
446
        mov     edi, [esi+usb_controller.HardwareFunc]
-
 
447
; 1. Acquire pipe lock.
-
 
448
        lea     ecx, [ebx+usb_pipe.Lock]
-
 
449
        call    mutex_lock
-
 
450
; 2. Clear USB_FLAG_DISABLED in pipe state.
-
 
451
        and     [ebx+usb_pipe.Flags], not USB_FLAG_DISABLED
-
 
452
; 3. Sanity check: ignore uninitialized pipes.
-
 
453
        cmp     [ebx+usb_pipe.LastTD], 0
-
 
454
        jz      .no_transfer
-
 
455
; 4. Acquire the first and last to-be-cancelled transfer descriptor,
-
 
456
; save them in stack for the step 6,
-
 
457
; ask the controller driver to enable the pipe for hardware,
-
 
458
; removing transfers between first and last to-be-cancelled descriptors.
-
 
459
        lea     ecx, [esi+usb_controller.ControlLock]
-
 
460
        cmp     [ebx+usb_pipe.Type], BULK_PIPE
-
 
461
        jb      @f      ; control pipe
-
 
462
        lea     ecx, [esi+usb_controller.BulkLock]
-
 
463
        jz      @f      ; bulk pipe
-
 
464
        lea     ecx, [esi+usb_controller.PeriodicLock]
-
 
465
@@:
-
 
466
        call    mutex_lock
-
 
467
        mov     eax, [ebx+usb_pipe.BaseList]
-
 
468
        mov     edx, [eax+usb_pipe.NextVirt]
-
 
469
        mov     [ebx+usb_pipe.NextVirt], edx
-
 
470
        mov     [ebx+usb_pipe.PrevVirt], eax
-
 
471
        mov     [edx+usb_pipe.PrevVirt], ebx
-
 
472
        mov     [eax+usb_pipe.NextVirt], ebx
-
 
473
        mov     eax, [ebx+usb_pipe.LastTD]
-
 
474
        mov     edx, [eax+usb_gtd.NextVirt]
-
 
475
        mov     [eax+usb_gtd.NextVirt], eax
-
 
476
        mov     [eax+usb_gtd.PrevVirt], eax
-
 
477
        push    eax
-
 
478
        push    edx
-
 
479
        push    ecx
-
 
480
        call    [edi+usb_hardware_func.EnablePipe]
-
 
481
        pop     ecx
-
 
482
        call    mutex_unlock
-
 
483
; 5. Release pipe lock acquired at step 1.
-
 
484
; Callbacks called at step 6 can insert new transfers,
-
 
485
; so we cannot call usb_pipe_aborted while holding pipe lock.
-
 
486
        lea     ecx, [ebx+usb_pipe.Lock]
-
 
487
        call    mutex_unlock
-
 
488
; 6. Notify all registered callbacks with status USB_STATUS_CANCELLED, if any.
-
 
489
; Two arguments describing transfers range were pushed at step 4.
-
 
490
        push    USB_STATUS_CANCELLED
-
 
491
        call    usb_pipe_aborted
-
 
492
        pop     edi
-
 
493
        ret
-
 
494
.no_transfer:
-
 
495
        call    mutex_unlock
-
 
496
        pop     edi
-
 
497
        ret
-
 
498
endp
377
 
499
 
378
; Part of API for drivers, see documentation for USBNormalTransferAsync.
500
; Part of API for drivers, see documentation for USBNormalTransferAsync.
379
proc usb_normal_transfer_async stdcall uses ebx edi,\
501
proc usb_normal_transfer_async stdcall uses ebx edi,\
380
 pipe:dword, buffer:dword, size:dword, callback:dword, calldata:dword, flags:dword
502
 pipe:dword, buffer:dword, size:dword, callback:dword, calldata:dword, flags:dword
381
; 1. Sanity check: callback must be nonzero.
503
; 1. Sanity check: callback must be nonzero.
Line 506... Line 628...
506
.return0:
628
.return0:
507
        xor     eax, eax
629
        xor     eax, eax
508
        ret
630
        ret
509
endp
631
endp
Line -... Line 632...
-
 
632
 
-
 
633
; Part of API for drivers, see documentation for USBAbortPipe.
-
 
634
proc usb_abort_pipe
-
 
635
        push    ebx esi ; save used registers to be stdcall
-
 
636
virtual at esp
-
 
637
                rd      2 ; saved registers
-
 
638
                dd      ? ; return address
-
 
639
.pipe           dd      ?
-
 
640
end virtual
-
 
641
        mov     ebx, [.pipe]
-
 
642
; 1. Acquire pipe lock.
-
 
643
        lea     ecx, [ebx+usb_pipe.Lock]
-
 
644
        call    mutex_lock
-
 
645
; 2. If the pipe is already closed or abort is in progress,
-
 
646
; just release pipe lock and return.
-
 
647
        test    [ebx+usb_pipe.Flags], USB_FLAG_CLOSED + USB_FLAG_DISABLED
-
 
648
        jnz     .nothing
-
 
649
; 3. Mark the pipe as aborting.
-
 
650
        or      [ebx+usb_pipe.Flags], USB_FLAG_DISABLED
-
 
651
; 4. We cannot do anything except adding new transfers concurrently with hardware.
-
 
652
; Ask the controller driver to (temporarily) remove the pipe from hardware queue.
-
 
653
        mov     esi, [ebx+usb_pipe.Controller]
-
 
654
; 4a. Acquire queue lock.
-
 
655
        lea     ecx, [esi+usb_controller.ControlLock]
-
 
656
        cmp     [ebx+usb_pipe.Type], BULK_PIPE
-
 
657
        jb      @f      ; control pipe
-
 
658
        lea     ecx, [esi+usb_controller.BulkLock]
-
 
659
        jz      @f      ; bulk pipe
-
 
660
        lea     ecx, [esi+usb_controller.PeriodicLock]
-
 
661
@@:
-
 
662
        call    mutex_lock
-
 
663
        push    ecx
-
 
664
; 4b. Call the driver.
-
 
665
        mov     eax, [esi+usb_controller.HardwareFunc]
-
 
666
        call    [eax+usb_hardware_func.DisablePipe]
-
 
667
; 4c. Remove the pipe from software list.
-
 
668
        mov     eax, [ebx+usb_pipe.NextVirt]
-
 
669
        mov     edx, [ebx+usb_pipe.PrevVirt]
-
 
670
        mov     [eax+usb_pipe.PrevVirt], edx
-
 
671
        mov     [edx+usb_pipe.NextVirt], eax
-
 
672
; 4c. Register the pipe in corresponding wait list.
-
 
673
        test    [ebx+usb_pipe.Type], 1
-
 
674
        jz      .control_bulk
-
 
675
        call    usb_subscribe_periodic
-
 
676
        jmp     @f
-
 
677
.control_bulk:
-
 
678
        call    usb_subscribe_control
-
 
679
@@:
-
 
680
; 4d. Release queue lock.
-
 
681
        pop     ecx
-
 
682
        call    mutex_unlock
-
 
683
; 4e. Notify the USB thread about new work.
-
 
684
        push    ebx esi edi
-
 
685
        call    usb_wakeup
-
 
686
        pop     edi esi ebx
-
 
687
; That's all for now. To be continued in usb_pipe_disabled.
-
 
688
; 5. Release pipe lock acquired at step 1 and return.
-
 
689
.nothing:
-
 
690
        lea     ecx, [ebx+usb_pipe.Lock]
-
 
691
        call    mutex_unlock
-
 
692
        pop     esi ebx
-
 
693
        ret     4
-
 
694
endp
510
 
695
 
511
; Part of API for drivers, see documentation for USBGetParam.
696
; Part of API for drivers, see documentation for USBGetParam.
512
proc usb_get_param
697
proc usb_get_param
513
virtual at esp
698
virtual at esp
514
                dd      ?       ; return address
699
                dd      ?       ; return address