Subversion Repositories Kolibri OS

Rev

Rev 4429 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4429 Rev 4587
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.
3
 
3
 
4
iglobal
4
iglobal
5
; USB HC support: some functions interesting only for *HCI-drivers.
5
; USB HC support: some functions interesting only for *HCI-drivers.
6
align 4
6
align 4
7
usb_hc_func:
7
usb_hc_func:
8
        dd      usb_process_gtd
8
        dd      usb_process_gtd
9
        dd      usb_init_static_endpoint
9
        dd      usb_init_static_endpoint
10
        dd      usb_wakeup_if_needed
10
        dd      usb_wakeup_if_needed
11
        dd      usb_subscribe_control
11
        dd      usb_subscribe_control
12
        dd      usb_subscription_done
12
        dd      usb_subscription_done
13
        dd      usb_allocate_common
13
        dd      usb_allocate_common
14
        dd      usb_free_common
14
        dd      usb_free_common
15
        dd      usb_td_to_virt
15
        dd      usb_td_to_virt
16
        dd      usb_init_transfer
16
        dd      usb_init_transfer
17
        dd      usb_undo_tds
17
        dd      usb_undo_tds
18
        dd      usb_test_pending_port
18
        dd      usb_test_pending_port
19
        dd      usb_get_tt
19
        dd      usb_get_tt
20
        dd      usb_get_tt_think_time
20
        dd      usb_get_tt_think_time
21
        dd      usb_new_device
21
        dd      usb_new_device
22
        dd      usb_disconnect_stage2
22
        dd      usb_disconnect_stage2
23
        dd      usb_process_wait_lists
23
        dd      usb_process_wait_lists
24
        dd      usb_unlink_td
24
        dd      usb_unlink_td
25
        dd      usb_is_final_packet
25
        dd      usb_is_final_packet
26
        dd      usb_find_ehci_companion
26
        dd      usb_find_ehci_companion
27
endg
27
endg
28
 
28
 
29
; Initializes one controller, called by usb_init for every controller.
29
; Initializes one controller, called by usb_init for every controller.
30
; eax -> PCIDEV structure for the device.
30
; eax -> PCIDEV structure for the device.
31
proc usb_init_controller
31
proc usb_init_controller
32
        push    ebp
32
        push    ebp
33
        mov     ebp, esp
33
        mov     ebp, esp
34
; 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:
35
; 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]
36
        push    dword [eax+PCIDEV.devfn]
37
        push    eax
37
        push    eax
38
        mov     edi, [eax+PCIDEV.owner]
38
        mov     edi, [eax+PCIDEV.owner]
39
        test    edi, edi
39
        test    edi, edi
40
        jz      .nothing
40
        jz      .nothing
41
        mov     edi, [edi+USBSRV.usb_func]
41
        mov     edi, [edi+USBSRV.usb_func]
42
; 2. Allocate *hci_controller + usb_controller.
42
; 2. Allocate *hci_controller + usb_controller.
43
        mov     ebx, [edi+usb_hardware_func.DataSize]
43
        mov     ebx, [edi+usb_hardware_func.DataSize]
44
        add     ebx, sizeof.usb_controller
44
        add     ebx, sizeof.usb_controller
45
        stdcall kernel_alloc, ebx
45
        stdcall kernel_alloc, ebx
46
        test    eax, eax
46
        test    eax, eax
47
        jz      .nothing
47
        jz      .nothing
48
; 3. Zero-initialize both structures.
48
; 3. Zero-initialize both structures.
49
        push    edi eax
49
        push    edi eax
50
        mov     ecx, ebx
50
        mov     ecx, ebx
51
        shr     ecx, 2
51
        shr     ecx, 2
52
        xchg    edi, eax
52
        xchg    edi, eax
53
        xor     eax, eax
53
        xor     eax, eax
54
        rep stosd
54
        rep stosd
55
; 4. Initialize usb_controller structure,
55
; 4. Initialize usb_controller structure,
56
; except data known only to controller-specific code (like NumPorts)
56
; except data known only to controller-specific code (like NumPorts)
57
; and link fields
57
; and link fields
58
; (this structure will be inserted to the overall list at step 6).
58
; (this structure will be inserted to the overall list at step 6).
59
        dec     eax
59
        dec     eax
60
        mov     [edi+usb_controller.ExistingAddresses+4-sizeof.usb_controller], eax
60
        mov     [edi+usb_controller.ExistingAddresses+4-sizeof.usb_controller], eax
61
        mov     [edi+usb_controller.ExistingAddresses+8-sizeof.usb_controller], eax
61
        mov     [edi+usb_controller.ExistingAddresses+8-sizeof.usb_controller], eax
62
        mov     [edi+usb_controller.ExistingAddresses+12-sizeof.usb_controller], eax
62
        mov     [edi+usb_controller.ExistingAddresses+12-sizeof.usb_controller], eax
63
        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
64
        dec     eax     ; don't allocate zero address
64
        dec     eax     ; don't allocate zero address
65
        mov     [edi+usb_controller.ExistingAddresses-sizeof.usb_controller], eax
65
        mov     [edi+usb_controller.ExistingAddresses-sizeof.usb_controller], eax
66
        mov     eax, [ebp-4]
66
        mov     eax, [ebp-4]
67
        mov     [edi+usb_controller.PCICoordinates-sizeof.usb_controller], eax
67
        mov     [edi+usb_controller.PCICoordinates-sizeof.usb_controller], eax
68
        lea     ecx, [edi+usb_controller.PeriodicLock-sizeof.usb_controller]
68
        lea     ecx, [edi+usb_controller.PeriodicLock-sizeof.usb_controller]
69
        call    mutex_init
69
        call    mutex_init
70
        add     ecx, usb_controller.ControlLock - usb_controller.PeriodicLock
70
        add     ecx, usb_controller.ControlLock - usb_controller.PeriodicLock
71
        call    mutex_init
71
        call    mutex_init
72
        add     ecx, usb_controller.BulkLock - usb_controller.ControlLock
72
        add     ecx, usb_controller.BulkLock - usb_controller.ControlLock
73
        call    mutex_init
73
        call    mutex_init
74
        pop     eax edi
74
        pop     eax edi
75
        mov     [eax+ebx-sizeof.usb_controller+usb_controller.HardwareFunc], edi
75
        mov     [eax+ebx-sizeof.usb_controller+usb_controller.HardwareFunc], edi
76
        push    eax
76
        push    eax
77
; 5. Call controller-specific initialization.
77
; 5. Call controller-specific initialization.
78
; If failed, free memory allocated in step 2 and return.
78
; If failed, free memory allocated in step 2 and return.
79
        call    [edi+usb_hardware_func.Init]
79
        call    [edi+usb_hardware_func.Init]
80
        test    eax, eax
80
        test    eax, eax
81
        jz      .fail
81
        jz      .fail
82
        pop     ecx
82
        pop     ecx
83
; 6. Insert the controller to the global list.
83
; 6. Insert the controller to the global list.
84
        xchg    eax, ebx
84
        xchg    eax, ebx
85
        mov     ecx, usb_controllers_list_mutex
85
        mov     ecx, usb_controllers_list_mutex
86
        call    mutex_lock
86
        call    mutex_lock
87
        mov     edx, usb_controllers_list
87
        mov     edx, usb_controllers_list
88
        mov     eax, [edx+usb_controller.Prev]
88
        mov     eax, [edx+usb_controller.Prev]
89
        mov     [ebx+usb_controller.Next], edx
89
        mov     [ebx+usb_controller.Next], edx
90
        mov     [ebx+usb_controller.Prev], eax
90
        mov     [ebx+usb_controller.Prev], eax
91
        mov     [edx+usb_controller.Prev], ebx
91
        mov     [edx+usb_controller.Prev], ebx
92
        mov     [eax+usb_controller.Next], ebx
92
        mov     [eax+usb_controller.Next], ebx
93
        call    mutex_unlock
93
        call    mutex_unlock
94
; 7. Wakeup USB thread to call ProcessDeferred.
94
; 7. Wakeup USB thread to call ProcessDeferred.
95
        call    usb_wakeup
95
        call    usb_wakeup
96
.nothing:
96
.nothing:
97
; 8. Restore pointer to PCIDEV saved in step 1 and return.
97
; 8. Restore pointer to PCIDEV saved in step 1 and return.
98
        pop     eax
98
        pop     eax
99
        leave
99
        leave
100
        ret
100
        ret
101
.fail:
101
.fail:
102
        call    kernel_free
102
        call    kernel_free
103
        jmp     .nothing
103
        jmp     .nothing
104
endp
104
endp
105
 
105
 
106
; Helper function, calculates physical address including offset in page.
106
; Helper function, calculates physical address including offset in page.
107
proc get_phys_addr
107
proc get_phys_addr
108
        push    ecx
108
        push    ecx
109
        mov     ecx, eax
109
        mov     ecx, eax
110
        and     ecx, 0xFFF
110
        and     ecx, 0xFFF
111
        call    get_pg_addr
111
        call    get_pg_addr
112
        add     eax, ecx
112
        add     eax, ecx
113
        pop     ecx
113
        pop     ecx
114
        ret
114
        ret
115
endp
115
endp
116
 
116
 
117
; Put the given control pipe in the wait list;
117
; Put the given control/bulk pipe in the wait list;
118
; called when the pipe structure is changed and a possible hardware cache
118
; called when the pipe structure is changed and a possible hardware cache
119
; needs to be synchronized. When it will be known that the cache is updated,
119
; needs to be synchronized. When it will be known that the cache is updated,
120
; usb_subscription_done procedure will be called.
120
; usb_subscription_done procedure will be called.
121
proc usb_subscribe_control
121
proc usb_subscribe_control
122
        cmp     [ebx+usb_pipe.NextWait], -1
122
        cmp     [ebx+usb_pipe.NextWait], -1
123
        jnz     @f
123
        jnz     @f
124
        mov     eax, [esi+usb_controller.WaitPipeListAsync]
124
        mov     eax, [esi+usb_controller.WaitPipeListAsync]
125
        mov     [ebx+usb_pipe.NextWait], eax
125
        mov     [ebx+usb_pipe.NextWait], eax
126
        mov     [esi+usb_controller.WaitPipeListAsync], ebx
126
        mov     [esi+usb_controller.WaitPipeListAsync], ebx
127
@@:
127
@@:
128
        ret
128
        ret
129
endp
129
endp
-
 
130
 
-
 
131
; Same as usb_subscribe_control, but for interrupt/isochronous pipe.
-
 
132
proc usb_subscribe_periodic
-
 
133
        cmp     [ebx+usb_pipe.NextWait], -1
-
 
134
        jnz     @f
-
 
135
        mov     eax, [esi+usb_controller.WaitPipeListPeriodic]
-
 
136
        mov     [ebx+usb_pipe.NextWait], eax
-
 
137
        mov     [esi+usb_controller.WaitPipeListPeriodic], ebx
-
 
138
@@:
-
 
139
        ret
-
 
140
endp
130
 
141
 
131
; Called after synchronization of hardware cache with software changes.
142
; Called after synchronization of hardware cache with software changes.
132
; Continues process of device enumeration based on when it was delayed
143
; Continues process of device enumeration based on when it was delayed
133
; due to call to usb_subscribe_control.
144
; due to call to usb_subscribe_control.
134
proc usb_subscription_done
145
proc usb_subscription_done
135
        mov     eax, [ebx+usb_pipe.DeviceData]
146
        mov     eax, [ebx+usb_pipe.DeviceData]
136
        cmp     [eax+usb_device_data.DeviceDescrSize], 0
147
        cmp     [eax+usb_device_data.DeviceDescrSize], 0
137
        jz      usb_after_set_address
148
        jz      usb_after_set_address
138
        jmp     usb_after_set_endpoint_size
149
        jmp     usb_after_set_endpoint_size
139
endp
150
endp
140
 
151
 
141
; This function is called when a new device has either passed
152
; This function is called when a new device has either passed
142
; or failed first stages of configuration, so the next device
153
; or failed first stages of configuration, so the next device
143
; can enter configuration process.
154
; can enter configuration process.
144
proc usb_test_pending_port
155
proc usb_test_pending_port
145
        mov     [esi+usb_controller.ResettingPort], -1
156
        mov     [esi+usb_controller.ResettingPort], -1
146
        cmp     [esi+usb_controller.PendingPorts], 0
157
        cmp     [esi+usb_controller.PendingPorts], 0
147
        jz      .nothing
158
        jz      .nothing
148
        bsf     ecx, [esi+usb_controller.PendingPorts]
159
        bsf     ecx, [esi+usb_controller.PendingPorts]
149
        btr     [esi+usb_controller.PendingPorts], ecx
160
        btr     [esi+usb_controller.PendingPorts], ecx
150
        mov     eax, [esi+usb_controller.HardwareFunc]
161
        mov     eax, [esi+usb_controller.HardwareFunc]
151
        jmp     [eax+usb_hardware_func.InitiateReset]
162
        jmp     [eax+usb_hardware_func.InitiateReset]
152
.nothing:
163
.nothing:
153
        ret
164
        ret
154
endp
165
endp
155
 
166
 
156
; This procedure is regularly called from controller-specific ProcessDeferred,
167
; This procedure is regularly called from controller-specific ProcessDeferred,
157
; it checks whether there are disconnected events and if so, process them.
168
; it checks whether there are disconnected events and if so, process them.
158
proc usb_disconnect_stage2
169
proc usb_disconnect_stage2
159
        bsf     ecx, [esi+usb_controller.NewDisconnected]
170
        bsf     ecx, [esi+usb_controller.NewDisconnected]
160
        jz      .nothing
171
        jz      .nothing
161
        lock btr [esi+usb_controller.NewDisconnected], ecx
172
        lock btr [esi+usb_controller.NewDisconnected], ecx
162
        btr     [esi+usb_controller.PendingPorts], ecx
173
        btr     [esi+usb_controller.PendingPorts], ecx
163
        xor     ebx, ebx
174
        xor     ebx, ebx
164
        xchg    ebx, [esi+usb_controller.DevicesByPort+ecx*4]
175
        xchg    ebx, [esi+usb_controller.DevicesByPort+ecx*4]
165
        test    ebx, ebx
176
        test    ebx, ebx
166
        jz      usb_disconnect_stage2
177
        jz      usb_disconnect_stage2
167
        call    usb_device_disconnected
178
        call    usb_device_disconnected
168
        jmp     usb_disconnect_stage2
179
        jmp     usb_disconnect_stage2
169
.nothing:
180
.nothing:
170
        ret
181
        ret
171
endp
182
endp
172
 
183
 
173
; Initial stage of disconnect processing: called when device is disconnected.
184
; Initial stage of disconnect processing: called when device is disconnected.
174
proc usb_device_disconnected
185
proc usb_device_disconnected
175
; Loop over all pipes, close everything, wait until hardware reacts.
186
; Loop over all pipes, close everything, wait until hardware reacts.
176
; The final handling is done in usb_pipe_closed.
187
; The final handling is done in usb_pipe_closed.
177
        push    ebx
188
        push    ebx
178
        mov     ecx, [ebx+usb_pipe.DeviceData]
189
        mov     ecx, [ebx+usb_pipe.DeviceData]
179
        call    mutex_lock
190
        call    mutex_lock
180
        lea     eax, [ecx+usb_device_data.OpenedPipeList-usb_pipe.NextSibling]
191
        lea     eax, [ecx+usb_device_data.OpenedPipeList-usb_pipe.NextSibling]
181
        push    eax
192
        push    eax
182
        mov     ebx, [eax+usb_pipe.NextSibling]
193
        mov     ebx, [eax+usb_pipe.NextSibling]
183
.pipe_loop:
194
.pipe_loop:
184
        call    usb_close_pipe_nolock
195
        call    usb_close_pipe_nolock
185
        mov     ebx, [ebx+usb_pipe.NextSibling]
196
        mov     ebx, [ebx+usb_pipe.NextSibling]
186
        cmp     ebx, [esp]
197
        cmp     ebx, [esp]
187
        jnz     .pipe_loop
198
        jnz     .pipe_loop
188
        pop     eax
199
        pop     eax
189
        pop     ebx
200
        pop     ebx
190
        mov     ecx, [ebx+usb_pipe.DeviceData]
201
        mov     ecx, [ebx+usb_pipe.DeviceData]
191
        call    mutex_unlock
202
        call    mutex_unlock
192
        ret
203
        ret
193
endp
204
endp
194
 
205
 
195
; Called from controller-specific ProcessDeferred,
206
; Called from controller-specific ProcessDeferred,
196
; processes wait-pipe-done notifications,
207
; processes wait-pipe-done notifications,
197
; returns whether there are more items in wait queues.
208
; returns whether there are more items in wait queues.
198
; in: esi -> usb_controller
209
; in: esi -> usb_controller
199
; out: eax = bitmask of pipe types with non-empty wait queue
210
; out: eax = bitmask of pipe types with non-empty wait queue
200
proc usb_process_wait_lists
211
proc usb_process_wait_lists
201
        xor     edx, edx
212
        xor     edx, edx
202
        push    edx
213
        push    edx
203
        call    usb_process_one_wait_list
214
        call    usb_process_one_wait_list
204
        jnc     @f
215
        jnc     @f
205
        or      byte [esp], 1 shl CONTROL_PIPE
216
        or      byte [esp], 1 shl CONTROL_PIPE
206
@@:
217
@@:
207
        movi    edx, 4
218
        movi    edx, 4
208
        call    usb_process_one_wait_list
219
        call    usb_process_one_wait_list
209
        jnc     @f
220
        jnc     @f
210
        or      byte [esp], 1 shl INTERRUPT_PIPE
221
        or      byte [esp], 1 shl INTERRUPT_PIPE
211
@@:
222
@@:
212
        xor     edx, edx
223
        xor     edx, edx
213
        call    usb_process_one_wait_list
224
        call    usb_process_one_wait_list
214
        jnc     @f
225
        jnc     @f
215
        or      byte [esp], 1 shl CONTROL_PIPE
226
        or      byte [esp], 1 shl CONTROL_PIPE
216
@@:
227
@@:
217
        pop     eax
228
        pop     eax
218
        ret
229
        ret
219
endp
230
endp
220
 
231
 
221
; Helper procedure for usb_process_wait_lists;
232
; Helper procedure for usb_process_wait_lists;
222
; does the same for one wait queue.
233
; does the same for one wait queue.
223
; in: esi -> usb_controller,
234
; in: esi -> usb_controller,
224
; edx=0 for *Async, edx=4 for *Periodic list
235
; edx=0 for *Async, edx=4 for *Periodic list
225
; out: CF = issue new request
236
; out: CF = issue new request
226
proc usb_process_one_wait_list
237
proc usb_process_one_wait_list
227
; 1. Check whether there is a pending request. If so, do nothing.
238
; 1. Check whether there is a pending request. If so, do nothing.
228
        mov     ebx, [esi+usb_controller.WaitPipeRequestAsync+edx]
239
        mov     ebx, [esi+usb_controller.WaitPipeRequestAsync+edx]
229
        cmp     ebx, [esi+usb_controller.ReadyPipeHeadAsync+edx]
240
        cmp     ebx, [esi+usb_controller.ReadyPipeHeadAsync+edx]
230
        clc
241
        clc
231
        jnz     .nothing
242
        jnz     .nothing
232
; 2. Check whether there are new data. If so, issue a new request.
243
; 2. Check whether there are new data. If so, issue a new request.
233
        cmp     ebx, [esi+usb_controller.WaitPipeListAsync+edx]
244
        cmp     ebx, [esi+usb_controller.WaitPipeListAsync+edx]
234
        stc
245
        stc
235
        jnz     .nothing
246
        jnz     .nothing
236
        test    ebx, ebx
247
        test    ebx, ebx
237
        jz      .nothing
248
        jz      .nothing
238
; 3. Clear all lists.
249
; 3. Clear all lists.
239
        xor     ecx, ecx
250
        xor     ecx, ecx
240
        mov     [esi+usb_controller.WaitPipeListAsync+edx], ecx
251
        mov     [esi+usb_controller.WaitPipeListAsync+edx], ecx
241
        mov     [esi+usb_controller.WaitPipeRequestAsync+edx], ecx
252
        mov     [esi+usb_controller.WaitPipeRequestAsync+edx], ecx
242
        mov     [esi+usb_controller.ReadyPipeHeadAsync+edx], ecx
253
        mov     [esi+usb_controller.ReadyPipeHeadAsync+edx], ecx
243
; 4. Loop over all pipes from the wait list.
254
; 4. Loop over all pipes from the wait list.
244
.pipe_loop:
255
.pipe_loop:
245
; For every pipe:
256
; For every pipe:
246
; 5. Save edx and next pipe in the list.
257
; 5. Save edx and next pipe in the list.
247
        push    edx
258
        push    edx
248
        push    [ebx+usb_pipe.NextWait]
259
        push    [ebx+usb_pipe.NextWait]
249
; 6. If USB_FLAG_EXTRA_WAIT is set, reinsert the pipe to the list and continue.
260
; 6. If USB_FLAG_EXTRA_WAIT is set, reinsert the pipe to the list and continue.
250
        test    [ebx+usb_pipe.Flags], USB_FLAG_EXTRA_WAIT
261
        test    [ebx+usb_pipe.Flags], USB_FLAG_EXTRA_WAIT
251
        jz      .process
262
        jz      .process
252
        mov     eax, [esi+usb_controller.WaitPipeListAsync+edx]
263
        mov     eax, [esi+usb_controller.WaitPipeListAsync+edx]
253
        mov     [ebx+usb_pipe.NextWait], eax
264
        mov     [ebx+usb_pipe.NextWait], eax
254
        mov     [esi+usb_controller.WaitPipeListAsync+edx], ebx
265
        mov     [esi+usb_controller.WaitPipeListAsync+edx], ebx
255
        jmp     .continue
266
        jmp     .continue
256
.process:
267
.process:
257
; 7. Call the handler depending on USB_FLAG_CLOSED.
268
; 7. Call the handler depending on USB_FLAG_CLOSED and USB_FLAG_DISABLED.
258
        or      [ebx+usb_pipe.NextWait], -1
269
        or      [ebx+usb_pipe.NextWait], -1
259
        test    [ebx+usb_pipe.Flags], USB_FLAG_CLOSED
270
        test    [ebx+usb_pipe.Flags], USB_FLAG_CLOSED
260
        jz      .nodisconnect
271
        jz      .nodisconnect
261
        call    usb_pipe_closed
272
        call    usb_pipe_closed
262
        jmp     .continue
273
        jmp     .continue
263
.nodisconnect:
274
.nodisconnect:
-
 
275
        test    [ebx+usb_pipe.Flags], USB_FLAG_DISABLED
-
 
276
        jz      .nodisabled
-
 
277
        call    usb_pipe_disabled
-
 
278
        jmp     .continue
-
 
279
.nodisabled:
264
        call    usb_subscription_done
280
        call    usb_subscription_done
265
.continue:
281
.continue:
266
; 8. Restore edx and next pipe saved in step 5 and continue the loop.
282
; 8. Restore edx and next pipe saved in step 5 and continue the loop.
267
        pop     ebx
283
        pop     ebx
268
        pop     edx
284
        pop     edx
269
        test    ebx, ebx
285
        test    ebx, ebx
270
        jnz     .pipe_loop
286
        jnz     .pipe_loop
271
.check_new_work:
287
.check_new_work:
272
; 9. Set CF depending on whether WaitPipeList* is nonzero.
288
; 9. Set CF depending on whether WaitPipeList* is nonzero.
273
        cmp     [esi+usb_controller.WaitPipeListAsync+edx], 1
289
        cmp     [esi+usb_controller.WaitPipeListAsync+edx], 1
274
        cmc
290
        cmc
275
.nothing:
291
.nothing:
276
        ret
292
        ret
277
endp
293
endp
278
 
294
 
279
; Called from USB1 controller-specific initialization.
295
; Called from USB1 controller-specific initialization.
280
; Finds EHCI companion controller for given USB1 controller.
296
; Finds EHCI companion controller for given USB1 controller.
281
; in: bl = PCI device:function for USB1 controller, bh = PCI bus
297
; in: bl = PCI device:function for USB1 controller, bh = PCI bus
282
; out: eax -> usb_controller for EHCI companion
298
; out: eax -> usb_controller for EHCI companion
283
proc usb_find_ehci_companion
299
proc usb_find_ehci_companion
284
; 1. Loop over all registered controllers.
300
; 1. Loop over all registered controllers.
285
        mov     eax, usb_controllers_list
301
        mov     eax, usb_controllers_list
286
.next:
302
.next:
287
        mov     eax, [eax+usb_controller.Next]
303
        mov     eax, [eax+usb_controller.Next]
288
        cmp     eax, usb_controllers_list
304
        cmp     eax, usb_controllers_list
289
        jz      .notfound
305
        jz      .notfound
290
; 2. For every controller, check the type, ignore everything that is not EHCI.
306
; 2. For every controller, check the type, ignore everything that is not EHCI.
291
        mov     edx, [eax+usb_controller.HardwareFunc]
307
        mov     edx, [eax+usb_controller.HardwareFunc]
292
        cmp     [edx+usb_hardware_func.ID], 'EHCI'
308
        cmp     [edx+usb_hardware_func.ID], 'EHCI'
293
        jnz     .next
309
        jnz     .next
294
; 3. For EHCI controller, compare PCI coordinates with input data:
310
; 3. For EHCI controller, compare PCI coordinates with input data:
295
; bus and device must be the same, function can be different.
311
; bus and device must be the same, function can be different.
296
        mov     edx, [eax+usb_controller.PCICoordinates]
312
        mov     edx, [eax+usb_controller.PCICoordinates]
297
        xor     edx, ebx
313
        xor     edx, ebx
298
        cmp     dx, 8
314
        cmp     dx, 8
299
        jae     .next
315
        jae     .next
300
        ret
316
        ret
301
.notfound:
317
.notfound:
302
        xor     eax, eax
318
        xor     eax, eax
303
        ret
319
        ret
304
endp
320
endp
305
 
321
 
306
; Find Transaction Translator hub and port for the given device.
322
; Find Transaction Translator hub and port for the given device.
307
; in: edx = parent hub for the device, ecx = port for the device
323
; 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.
324
; out: edx = TT hub for the device, ecx = TT port for the device.
309
proc usb_get_tt
325
proc usb_get_tt
310
; If the parent hub is high-speed, it is TT for the device.
326
; 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
327
; Otherwise, the parent hub itself is behind TT, and the device
312
; has the same TT hub+port as the parent hub.
328
; has the same TT hub+port as the parent hub.
313
        mov     eax, [edx+usb_hub.ConfigPipe]
329
        mov     eax, [edx+usb_hub.ConfigPipe]
314
        mov     eax, [eax+usb_pipe.DeviceData]
330
        mov     eax, [eax+usb_pipe.DeviceData]
315
        cmp     [eax+usb_device_data.Speed], USB_SPEED_HS
331
        cmp     [eax+usb_device_data.Speed], USB_SPEED_HS
316
        jz      @f
332
        jz      @f
317
        movzx   ecx, [eax+usb_device_data.TTPort]
333
        movzx   ecx, [eax+usb_device_data.TTPort]
318
        mov     edx, [eax+usb_device_data.TTHub]
334
        mov     edx, [eax+usb_device_data.TTHub]
319
@@:
335
@@:
320
        mov     edx, [edx+usb_hub.ConfigPipe]
336
        mov     edx, [edx+usb_hub.ConfigPipe]
321
        ret
337
        ret
322
endp
338
endp