Subversion Repositories Kolibri OS

Rev

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

Rev 3826 Rev 4418
Line 1... Line 1...
1
; USB Host Controller support code: hardware-independent part,
1
; USB Host Controller support code: hardware-independent part,
2
; common for all controller types.
2
; common for all controller types.
Line 3... Line -...
3
 
-
 
4
; =============================================================================
-
 
5
; ================================= Constants =================================
-
 
6
; =============================================================================
-
 
7
; USB device must have at least 100ms of stable power before initializing can
-
 
8
; proceed; one timer tick is 10ms, so enforce delay in 10 ticks
-
 
9
USB_CONNECT_DELAY = 10
-
 
10
; USB requires at least 10 ms for reset signalling. Normally, this is one timer
-
 
11
; tick. However, it is possible that we start reset signalling in the end of
-
 
12
; interval between timer ticks and then we test time in the start of the next
-
 
13
; interval; in this case, the delta between [timer_ticks] is 1, but the real
-
 
14
; time passed is significantly less than 10 ms. To avoid this, we add an extra
-
 
15
; tick; this guarantees that at least 10 ms have passed.
-
 
16
USB_RESET_TIME = 2
-
 
17
; USB requires at least 10 ms of reset recovery, a delay between reset
-
 
18
; signalling and any commands to device. Add an extra tick for the same reasons
-
 
19
; as with the previous constant.
-
 
20
USB_RESET_RECOVERY_TIME = 2
-
 
21
 
-
 
22
; =============================================================================
-
 
23
; ================================ Structures =================================
-
 
24
; =============================================================================
-
 
25
; Controller descriptor.
-
 
26
; This structure represents the common (controller-independent) part
-
 
27
; of a controller for the USB code. The corresponding controller-dependent
-
 
28
; part *hci_controller is located immediately before usb_controller.
-
 
29
struct usb_controller
-
 
30
; Two following fields organize all controllers in the global linked list.
-
 
31
Next            dd      ?
-
 
32
Prev            dd      ?
-
 
33
HardwareFunc    dd      ?
-
 
34
; Pointer to usb_hardware_func structure with controller-specific functions.
-
 
35
NumPorts        dd      ?
-
 
36
; Number of ports in the root hub.
-
 
37
SetAddressBuffer        rb      8
-
 
38
; Buffer for USB control command SET_ADDRESS.
-
 
39
ExistingAddresses       rd      128/32
-
 
40
; Bitmask for 128 bits; bit i is cleared <=> address i is free for allocating
-
 
41
; for new devices. Bit 0 is always set.
-
 
42
;
-
 
43
; The hardware is allowed to cache some data from hardware structures.
-
 
44
; Regular operations are designed considering this,
-
 
45
; but sometimes it is required to wait for synchronization of hardware cache
-
 
46
; with modified structures in memory.
-
 
47
; The code keeps two queues of pipes waiting for synchronization,
-
 
48
; one for asynchronous (bulk/control) pipes, one for periodic pipes, hardware
-
 
49
; cache is invalidated under different conditions for those types.
-
 
50
; Both queues are organized in the same way, as single-linked lists.
-
 
51
; There are three special positions: the head of list (new pipes are added
-
 
52
; here), the first pipe to be synchronized at the current iteration,
-
 
53
; the tail of list (all pipes starting from here are synchronized).
-
 
54
WaitPipeListAsync       dd      ?
-
 
55
WaitPipeListPeriodic    dd      ?
-
 
56
; List heads.
-
 
57
WaitPipeRequestAsync    dd      ?
-
 
58
WaitPipeRequestPeriodic dd      ?
-
 
59
; Pending request to hardware to refresh cache for items from WaitPipeList*.
-
 
60
; (Pointers to some items in WaitPipeList* or NULLs).
-
 
61
ReadyPipeHeadAsync      dd      ?
-
 
62
ReadyPipeHeadPeriodic   dd      ?
-
 
63
; Items of RemovingList* which were released by hardware and are ready
-
 
64
; for further processing.
-
 
65
; (Pointers to some items in WaitPipeList* or NULLs).
-
 
66
NewConnected    dd      ?
-
 
67
; bit mask of recently connected ports of the root hub,
-
 
68
; bit set = a device was recently connected to the corresponding port;
-
 
69
; after USB_CONNECT_DELAY ticks of stable status these ports are moved to
-
 
70
; PendingPorts
-
 
71
NewDisconnected dd      ?
-
 
72
; bit mask of disconnected ports of the root hub,
-
 
73
; bit set = a device in the corresponding port was disconnected,
-
 
74
; disconnect processing is required.
-
 
75
PendingPorts    dd      ?
-
 
76
; bit mask of ports which are ready to be initialized
-
 
77
ControlLock     MUTEX   ?
-
 
78
; mutex which guards all operations with control queue
-
 
79
BulkLock        MUTEX   ?
-
 
80
; mutex which guards all operations with bulk queue
-
 
81
PeriodicLock    MUTEX   ?
-
 
82
; mutex which guards all operations with periodic queues
3
 
83
WaitSpinlock:
-
 
84
; spinlock guarding WaitPipeRequest/ReadyPipeHead (but not WaitPipeList)
-
 
85
StartWaitFrame  dd      ?
-
 
86
; USB frame number when WaitPipeRequest* was registered.
-
 
87
ResettingHub    dd      ?
-
 
88
; Pointer to usb_hub responsible for the currently resetting port, if any.
-
 
89
; NULL for the root hub.
-
 
90
ResettingPort   db      ?
-
 
91
; Port that is currently resetting, 0-based.
-
 
92
ResettingSpeed  db      ?
-
 
93
; Speed of currently resetting device.
-
 
94
ResettingStatus db      ?
4
iglobal
95
; Status of port reset. 0 = no port is resetting, -1 = reset failed,
-
 
96
; 1 = reset in progress, 2 = reset recovery in progress.
-
 
97
                rb      1       ; alignment
-
 
98
ResetTime       dd      ?
-
 
99
; Time when reset signalling or reset recovery has been started.
-
 
100
ConnectedTime   rd      16
-
 
101
; Time, in timer ticks, when the port i has signalled the connect event.
-
 
102
; Valid only if bit i in NewConnected is set.
-
 
103
DevicesByPort   rd      16
-
 
104
; Pointer to usb_pipe for zero endpoint (which serves as device handle)
-
 
105
; for each port.
-
 
106
ends
-
 
107
 
-
 
108
; Interface-specific data. Several interfaces of one device can operate
-
 
109
; independently, each is controlled by some driver and is identified by
-
 
110
; some driver-specific data passed as is to the driver.
-
 
111
struct usb_interface_data
-
 
112
DriverData      dd      ?
-
 
113
; Passed as is to the driver.
-
 
114
DriverFunc      dd      ?
-
 
115
; Pointer to USBSRV structure for the driver.
5
; USB HC support: some functions interesting only for *HCI-drivers.
116
ends
-
 
117
 
-
 
118
; Device-specific data.
6
align 4
119
struct usb_device_data
-
 
120
PipeListLock    MUTEX
-
 
121
; Lock guarding OpenedPipeList. Must be the first item of the structure,
-
 
122
; the code passes pointer to usb_device_data as is to mutex_lock/unlock.
-
 
123
OpenedPipeList  rd      2
-
 
124
; List of all opened pipes for the device.
-
 
125
; Used when the device is disconnected, so all pipes should be closed.
-
 
126
ClosedPipeList  rd      2
-
 
127
; List of all closed, but still valid pipes for the device.
-
 
128
; A pipe closed with USBClosePipe is just deallocated,
-
 
129
; but a pipe closed due to disconnect must remain valid until driver-provided
-
 
130
; disconnect handler returns; this list links all such pipes to deallocate them
7
usb_hc_func:
131
; after disconnect processing.
-
 
132
NumPipes        dd      ?
8
        dd      usb_process_gtd
133
; Number of not-yet-closed pipes.
9
        dd      usb_init_static_endpoint
134
Hub             dd      ?
-
 
135
; NULL if connected to the root hub, pointer to usb_hub otherwise.
-
 
136
TTHub           dd      ?
-
 
137
; Pointer to usb_hub for (the) hub with Transaction Translator for the device,
-
 
138
; NULL if the device operates in the same speed as the controller.
10
        dd      usb_wakeup_if_needed
139
Port            db      ?
-
 
140
; Port on the hub, zero-based.
-
 
141
TTPort          db      ?
-
 
142
; Port on the TTHub, zero-based.
-
 
143
DeviceDescrSize db      ?
11
        dd      usb_subscribe_control
144
; Size of device descriptor.
-
 
145
Speed           db      ?
-
 
146
; Device speed, one of USB_SPEED_*.
-
 
147
NumInterfaces   dd      ?
-
 
148
; Number of interfaces.
-
 
149
ConfigDataSize  dd      ?
-
 
150
; Total size of data associated with the configuration descriptor
-
 
151
; (including the configuration descriptor itself).
-
 
152
Interfaces      dd      ?
-
 
153
; Offset from the beginning of this structure to Interfaces field.
-
 
154
; Variable-length fields:
-
 
155
; DeviceDescriptor:
-
 
156
;  device descriptor starts here
-
 
157
; ConfigDescriptor = DeviceDescriptor + DeviceDescrSize
-
 
158
;  configuration descriptor with all associated data
-
 
159
; Interfaces = ALIGN_UP(ConfigDescriptor + ConfigDataSize, 4)
-
 
160
;  array of NumInterfaces elements of type usb_interface_data
-
 
161
ends
-
 
162
 
-
 
163
usb_device_data.DeviceDescriptor = sizeof.usb_device_data
-
 
164
 
-
 
165
; Description of controller-specific data and functions.
-
 
166
struct usb_hardware_func
12
        dd      usb_subscription_done
167
ID              dd      ?       ; '*HCI'
13
        dd      usb_allocate_common
168
DataSize        dd      ?       ; sizeof(*hci_controller)
14
        dd      usb_free_common
169
Init            dd      ?
-
 
170
; Initialize controller-specific part of controller data.
-
 
171
; in: eax -> *hci_controller to initialize, [ebp-4] = (bus shl 8) + devfn
-
 
172
; out: eax = 0 <=> failed, otherwise eax -> usb_controller
-
 
173
ProcessDeferred dd      ?
-
 
174
; Called regularly from the main loop of USB thread
-
 
175
; (either due to timeout from a previous call, or due to explicit wakeup).
15
        dd      usb_td_to_virt
176
; in: esi -> usb_controller
-
 
177
; out: eax = maximum timeout for next call (-1 = infinity)
-
 
178
SetDeviceAddress        dd      ?
-
 
179
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
-
 
180
GetDeviceAddress        dd      ?
-
 
181
; in: esi -> usb_controller, ebx -> usb_pipe
-
 
182
; out: eax = address
16
        dd      usb_init_transfer
183
PortDisable             dd      ?
-
 
184
; Disable the given port in the root hub.
-
 
185
; in: esi -> usb_controller, ecx = port (zero-based)
-
 
186
InitiateReset           dd      ?
17
        dd      usb_undo_tds
187
; Start reset signalling on the given port.
-
 
188
; in: esi -> usb_controller, ecx = port (zero-based)
-
 
189
SetEndpointPacketSize   dd      ?
-
 
190
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size
18
        dd      usb_test_pending_port
191
AllocPipe               dd      ?
19
        dd      usb_get_tt
192
; out: eax = pointer to allocated usb_pipe
-
 
193
FreePipe                dd      ?
-
 
194
; void stdcall with one argument = pointer to previously allocated usb_pipe
20
        dd      usb_get_tt_think_time
195
InitPipe                dd      ?
-
 
196
; in: edi -> usb_pipe for target, ecx -> usb_pipe for config pipe,
-
 
197
; esi -> usb_controller, eax -> usb_gtd for the first TD,
-
 
198
; [ebp+12] = endpoint, [ebp+16] = maxpacket, [ebp+20] = type
-
 
199
UnlinkPipe              dd      ?
-
 
200
; esi -> usb_controller, ebx -> usb_pipe
21
        dd      usb_new_device
201
AllocTD                 dd      ?
22
        dd      usb_disconnect_stage2
202
; out: eax = pointer to allocated usb_gtd
23
        dd      usb_process_wait_lists
203
FreeTD                  dd      ?
-
 
204
; void stdcall with one argument = pointer to previously allocated usb_gtd
-
 
205
AllocTransfer           dd      ?
-
 
206
; Allocate and initialize one stage of a transfer.
-
 
207
; ebx -> usb_pipe, other parameters are passed through the stack:
-
 
208
; buffer,size = data to transfer
24
        dd      usb_unlink_td
209
; flags = same as in usb_open_pipe:
-
 
210
;   bit 0 = allow short transfer, other bits reserved
-
 
211
; td = pointer to the current end-of-queue descriptor
-
 
212
; direction =
-
 
213
;   0000b for normal transfers,
-
 
214
;   1000b for control SETUP transfer,
-
 
215
;   1101b for control OUT transfer,
-
 
216
;   1110b for control IN transfer
-
 
217
; returns eax = pointer to the new end-of-queue descriptor
-
 
218
; (not included in the queue itself) or 0 on error
-
 
219
InsertTransfer          dd      ?
-
 
220
; Activate previously initialized transfer (maybe with multiple stages).
-
 
221
; esi -> usb_controller, ebx -> usb_pipe,
-
 
222
; [esp+4] -> first usb_gtd for the transfer,
-
 
223
; ecx -> last descriptor for the transfer
-
 
224
NewDevice               dd      ?
-
 
225
; Initiate configuration of a new device (create pseudo-pipe describing that
25
        dd      usb_is_final_packet
226
; device and call usb_new_device).
-
 
227
; esi -> usb_controller, eax = speed (one of USB_SPEED_* constants).
26
        dd      usb_find_ehci_companion
228
ends
-
 
229
 
-
 
230
; =============================================================================
-
 
231
; =================================== Code ====================================
-
 
Line 232... Line 27...
232
; =============================================================================
27
endg
233
 
28
 
234
; Initializes one controller, called by usb_init for every controller.
29
; Initializes one controller, called by usb_init for every controller.
235
; edi -> usb_hardware_func, eax -> PCIDEV structure for the device.
30
; eax -> PCIDEV structure for the device.
236
proc usb_init_controller
31
proc usb_init_controller
237
        push    ebp
32
        push    ebp
238
        mov     ebp, esp
33
        mov     ebp, esp
239
; 1. Store in the stack PCI coordinates and save pointer to PCIDEV:
34
; 1. Store in the stack PCI coordinates and save pointer to PCIDEV:
240
; make [ebp-4] = (bus shl 8) + devfn, used by controller-specific Init funcs.
35
; make [ebp-4] = (bus shl 8) + devfn, used by controller-specific Init funcs.
-
 
36
        push    dword [eax+PCIDEV.devfn]
-
 
37
        push    eax
-
 
38
        mov     edi, [eax+PCIDEV.owner]
-
 
39
        test    edi, edi
241
        push    dword [eax+PCIDEV.devfn]
40
        jz      .nothing
242
        push    eax
41
        mov     edi, [edi+USBSRV.usb_func]
243
; 2. Allocate *hci_controller + usb_controller.
42
; 2. Allocate *hci_controller + usb_controller.
244
        mov     ebx, [edi+usb_hardware_func.DataSize]
43
        mov     ebx, [edi+usb_hardware_func.DataSize]
245
        add     ebx, sizeof.usb_controller
44
        add     ebx, sizeof.usb_controller
Line 262... Line 61...
262
        mov     [edi+usb_controller.ExistingAddresses+8-sizeof.usb_controller], eax
61
        mov     [edi+usb_controller.ExistingAddresses+8-sizeof.usb_controller], eax
263
        mov     [edi+usb_controller.ExistingAddresses+12-sizeof.usb_controller], eax
62
        mov     [edi+usb_controller.ExistingAddresses+12-sizeof.usb_controller], eax
264
        mov     [edi+usb_controller.ResettingPort-sizeof.usb_controller], al    ; no resetting port
63
        mov     [edi+usb_controller.ResettingPort-sizeof.usb_controller], al    ; no resetting port
265
        dec     eax     ; don't allocate zero address
64
        dec     eax     ; don't allocate zero address
266
        mov     [edi+usb_controller.ExistingAddresses-sizeof.usb_controller], eax
65
        mov     [edi+usb_controller.ExistingAddresses-sizeof.usb_controller], eax
-
 
66
        mov     eax, [ebp-4]
-
 
67
        mov     [edi+usb_controller.PCICoordinates-sizeof.usb_controller], eax
267
        lea     ecx, [edi+usb_controller.PeriodicLock-sizeof.usb_controller]
68
        lea     ecx, [edi+usb_controller.PeriodicLock-sizeof.usb_controller]
268
        call    mutex_init
69
        call    mutex_init
269
        add     ecx, usb_controller.ControlLock - usb_controller.PeriodicLock
70
        add     ecx, usb_controller.ControlLock - usb_controller.PeriodicLock
270
        call    mutex_init
71
        call    mutex_init
271
        add     ecx, usb_controller.BulkLock - usb_controller.ControlLock
72
        add     ecx, usb_controller.BulkLock - usb_controller.ControlLock
Line 472... Line 273...
472
        cmp     [esi+usb_controller.WaitPipeListAsync+edx], 1
273
        cmp     [esi+usb_controller.WaitPipeListAsync+edx], 1
473
        cmc
274
        cmc
474
.nothing:
275
.nothing:
475
        ret
276
        ret
476
endp
277
endp
-
 
278
 
-
 
279
; Called from USB1 controller-specific initialization.
-
 
280
; Finds EHCI companion controller for given USB1 controller.
-
 
281
; in: bl = PCI device:function for USB1 controller, bh = PCI bus
-
 
282
; out: eax -> usb_controller for EHCI companion
-
 
283
proc usb_find_ehci_companion
-
 
284
; 1. Loop over all registered controllers.
-
 
285
        mov     eax, usb_controllers_list
-
 
286
.next:
-
 
287
        mov     eax, [eax+usb_controller.Next]
-
 
288
        cmp     eax, usb_controllers_list
-
 
289
        jz      .notfound
-
 
290
; 2. For every controller, check the type, ignore everything that is not EHCI.
-
 
291
        mov     edx, [eax+usb_controller.HardwareFunc]
-
 
292
        cmp     [edx+usb_hardware_func.ID], 'EHCI'
-
 
293
        jnz     .next
-
 
294
; 3. For EHCI controller, compare PCI coordinates with input data:
-
 
295
; bus and device must be the same, function can be different.
-
 
296
        mov     edx, [eax+usb_controller.PCICoordinates]
-
 
297
        xor     edx, ebx
-
 
298
        cmp     dx, 8
-
 
299
        jae     .next
-
 
300
        ret
-
 
301
.notfound:
-
 
302
        xor     eax, eax
-
 
303
        ret
-
 
304
endp
-
 
305
 
-
 
306
; Find Transaction Translator hub and port for the given device.
-
 
307
; in: edx = parent hub for the device, ecx = port for the device
-
 
308
; out: edx = TT hub for the device, ecx = TT port for the device.
-
 
309
proc usb_get_tt
-
 
310
; If the parent hub is high-speed, it is TT for the device.
-
 
311
; Otherwise, the parent hub itself is behind TT, and the device
-
 
312
; has the same TT hub+port as the parent hub.
-
 
313
        mov     eax, [edx+usb_hub.ConfigPipe]
-
 
314
        mov     eax, [eax+usb_pipe.DeviceData]
-
 
315
        cmp     [eax+usb_device_data.Speed], USB_SPEED_HS
-
 
316
        jz      @f
-
 
317
        movzx   ecx, [eax+usb_device_data.TTPort]
-
 
318
        mov     edx, [eax+usb_device_data.TTHub]
-
 
319
@@:
-
 
320
        mov     edx, [edx+usb_hub.ConfigPipe]
-
 
321
        ret
-
 
322
endp