Subversion Repositories Kolibri OS

Rev

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

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