Subversion Repositories Kolibri OS

Rev

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

Rev 3578 Rev 3598
1
; Code for EHCI controllers.
1
; Code for EHCI controllers.
2
; Note: it should be moved to an external driver,
2
; Note: it should be moved to an external driver,
3
; it was convenient to have this code compiled into the kernel during initial
3
; it was convenient to have this code compiled into the kernel during initial
4
; development, but there are no reasons to keep it here.
4
; development, but there are no reasons to keep it here.
5
 
5
 
6
; =============================================================================
6
; =============================================================================
7
; ================================= Constants =================================
7
; ================================= Constants =================================
8
; =============================================================================
8
; =============================================================================
9
; EHCI register declarations.
9
; EHCI register declarations.
10
; Part 1. Capability registers.
10
; Part 1. Capability registers.
11
; Base is MMIO from the PCI space.
11
; Base is MMIO from the PCI space.
12
EhciCapLengthReg    = 0
12
EhciCapLengthReg    = 0
13
EhciVersionReg      = 2
13
EhciVersionReg      = 2
14
EhciStructParamsReg = 4
14
EhciStructParamsReg = 4
15
EhciCapParamsReg    = 8
15
EhciCapParamsReg    = 8
16
EhciPortRouteReg    = 0Ch
16
EhciPortRouteReg    = 0Ch
17
; Part 2. Operational registers.
17
; Part 2. Operational registers.
18
; Base is (base for part 1) + (value of EhciCapLengthReg).
18
; Base is (base for part 1) + (value of EhciCapLengthReg).
19
EhciCommandReg      = 0
19
EhciCommandReg      = 0
20
EhciStatusReg       = 4
20
EhciStatusReg       = 4
21
EhciInterruptReg    = 8
21
EhciInterruptReg    = 8
22
EhciFrameIndexReg   = 0Ch
22
EhciFrameIndexReg   = 0Ch
23
EhciCtrlDataSegReg  = 10h
23
EhciCtrlDataSegReg  = 10h
24
EhciPeriodicListReg = 14h
24
EhciPeriodicListReg = 14h
25
EhciAsyncListReg    = 18h
25
EhciAsyncListReg    = 18h
26
EhciConfigFlagReg   = 40h
26
EhciConfigFlagReg   = 40h
27
EhciPortsReg        = 44h
27
EhciPortsReg        = 44h
28
 
28
 
29
; Possible values of ehci_pipe.NextQH.Type bitfield.
29
; Possible values of ehci_pipe.NextQH.Type bitfield.
30
EHCI_TYPE_ITD  = 0 ; isochronous transfer descriptor
30
EHCI_TYPE_ITD  = 0 ; isochronous transfer descriptor
31
EHCI_TYPE_QH   = 1 ; queue head
31
EHCI_TYPE_QH   = 1 ; queue head
32
EHCI_TYPE_SITD = 2 ; split-transaction isochronous TD
32
EHCI_TYPE_SITD = 2 ; split-transaction isochronous TD
33
EHCI_TYPE_FSTN = 3 ; frame span traversal node
33
EHCI_TYPE_FSTN = 3 ; frame span traversal node
34
 
34
 
35
; =============================================================================
35
; =============================================================================
36
; ================================ Structures =================================
36
; ================================ Structures =================================
37
; =============================================================================
37
; =============================================================================
38
 
38
 
39
; Hardware part of EHCI general transfer descriptor.
39
; Hardware part of EHCI general transfer descriptor.
40
struct ehci_hardware_td
40
struct ehci_hardware_td
41
NextTD          dd      ?
41
NextTD          dd      ?
42
; Bit 0 is Terminate bit, 1 = there is no next TD.
42
; Bit 0 is Terminate bit, 1 = there is no next TD.
43
; Bits 1-4 must be zero.
43
; Bits 1-4 must be zero.
44
; With masked 5 lower bits, this is the physical address of the next TD, if any.
44
; With masked 5 lower bits, this is the physical address of the next TD, if any.
45
AlternateNextTD dd      ?
45
AlternateNextTD dd      ?
46
; Similar to NextTD, used if the transfer terminates with a short packet.
46
; Similar to NextTD, used if the transfer terminates with a short packet.
47
Token           dd      ?
47
Token           dd      ?
48
; 1. Lower byte is Status field:
48
; 1. Lower byte is Status field:
49
; bit 0 = ping state for USB2 endpoints, ERR handshake signal for USB1 endpoints
49
; bit 0 = ping state for USB2 endpoints, ERR handshake signal for USB1 endpoints
50
; bit 1 = split transaction state, meaningless for USB2 endpoints
50
; bit 1 = split transaction state, meaningless for USB2 endpoints
51
; bit 2 = missed micro-frame
51
; bit 2 = missed micro-frame
52
; bit 3 = transaction error
52
; bit 3 = transaction error
53
; bit 4 = babble detected
53
; bit 4 = babble detected
54
; bit 5 = data buffer error
54
; bit 5 = data buffer error
55
; bit 6 = halted
55
; bit 6 = halted
56
; bit 7 = active
56
; bit 7 = active
57
; 2. Next two bits (bits 8-9) are PID code, 0 = OUT, 1 = IN, 2 = SETUP.
57
; 2. Next two bits (bits 8-9) are PID code, 0 = OUT, 1 = IN, 2 = SETUP.
58
; 3. Next two bits (bits 10-11) is ErrorCounter. Initialized as 3, decremented
58
; 3. Next two bits (bits 10-11) is ErrorCounter. Initialized as 3, decremented
59
;    on each error; if it goes to zero, transaction is stopped.
59
;    on each error; if it goes to zero, transaction is stopped.
60
; 4. Next 3 bits (bits 12-14) are CurrentPage field.
60
; 4. Next 3 bits (bits 12-14) are CurrentPage field.
61
; 5. Next bit (bit 15) is InterruptOnComplete bit.
61
; 5. Next bit (bit 15) is InterruptOnComplete bit.
62
; 6. Next 15 bits (bits 16-30) are TransferLength field,
62
; 6. Next 15 bits (bits 16-30) are TransferLength field,
63
;    number of bytes to transfer.
63
;    number of bytes to transfer.
64
; 7. Upper bit (bit 31) is DataToggle bit.
64
; 7. Upper bit (bit 31) is DataToggle bit.
65
BufferPointers  rd      5
65
BufferPointers  rd      5
66
; The buffer to be transferred can be spanned on up to 5 physical pages.
66
; The buffer to be transferred can be spanned on up to 5 physical pages.
67
; The first item of this array is the physical address of the first byte in
67
; The first item of this array is the physical address of the first byte in
68
; the buffer, other items are physical addresses of next pages. Lower 12 bits
68
; the buffer, other items are physical addresses of next pages. Lower 12 bits
69
; in other items must be set to zero; ehci_pipe.Overlay reuses some of them.
69
; in other items must be set to zero; ehci_pipe.Overlay reuses some of them.
70
BufferPointersHigh      rd      5
70
BufferPointersHigh      rd      5
71
; Upper dwords of BufferPointers for controllers with 64-bit memory access.
71
; Upper dwords of BufferPointers for controllers with 64-bit memory access.
72
; Always zero.
72
; Always zero.
73
ends
73
ends
74
 
74
 
75
; EHCI general transfer descriptor.
75
; EHCI general transfer descriptor.
76
; * The structure describes transfers to be performed on Control, Bulk or
76
; * The structure describes transfers to be performed on Control, Bulk or
77
;   Interrupt endpoints.
77
;   Interrupt endpoints.
78
; * The structure includes two parts, the hardware part and the software part.
78
; * The structure includes two parts, the hardware part and the software part.
79
; * The hardware part consists of first 52 bytes and corresponds to
79
; * The hardware part consists of first 52 bytes and corresponds to
80
;   the Queue Element Transfer Descriptor from EHCI specification.
80
;   the Queue Element Transfer Descriptor from EHCI specification.
81
; * The hardware requires 32-bytes alignment of the hardware part, so
81
; * The hardware requires 32-bytes alignment of the hardware part, so
82
;   the entire descriptor must be 32-bytes aligned. Since the allocator
82
;   the entire descriptor must be 32-bytes aligned. Since the allocator
83
;   (usb_allocate_common) allocates memory sequentially from page start
83
;   (usb_allocate_common) allocates memory sequentially from page start
84
;   (aligned on 0x1000 bytes), size of the structure must be divisible by 32.
84
;   (aligned on 0x1000 bytes), size of the structure must be divisible by 32.
85
; * The hardware also requires that the hardware part must not cross page
85
; * The hardware also requires that the hardware part must not cross page
86
;   boundary; the allocator satisfies this automatically.
86
;   boundary; the allocator satisfies this automatically.
87
struct ehci_gtd ehci_hardware_td
87
struct ehci_gtd ehci_hardware_td
88
Flags                   dd      ?
88
Flags                   dd      ?
89
; Copy of flags from the call to usb_*_transfer_async.
89
; Copy of flags from the call to usb_*_transfer_async.
90
SoftwarePart            rd      sizeof.usb_gtd/4
90
SoftwarePart            rd      sizeof.usb_gtd/4
91
; Software part, common for all controllers.
91
; Software part, common for all controllers.
92
                        rd      3       ; padding
92
                        rd      3       ; padding
93
ends
93
ends
94
 
94
 
95
if sizeof.ehci_gtd mod 32
95
if sizeof.ehci_gtd mod 32
96
.err ehci_gtd must be 32-bytes aligned
96
.err ehci_gtd must be 32-bytes aligned
97
end if
97
end if
98
 
98
 
99
; EHCI-specific part of a pipe descriptor.
99
; EHCI-specific part of a pipe descriptor.
100
; * This structure corresponds to the Queue Head from the EHCI specification.
100
; * This structure corresponds to the Queue Head from the EHCI specification.
101
; * The hardware requires 32-bytes alignment of the hardware part.
101
; * The hardware requires 32-bytes alignment of the hardware part.
102
;   Since the allocator (usb_allocate_common) allocates memory sequentially
102
;   Since the allocator (usb_allocate_common) allocates memory sequentially
103
;   from page start (aligned on 0x1000 bytes), size of the structure must be
103
;   from page start (aligned on 0x1000 bytes), size of the structure must be
104
;   divisible by 32.
104
;   divisible by 32.
105
; * The hardware requires also that the hardware part must not cross page
105
; * The hardware requires also that the hardware part must not cross page
106
;   boundary; the allocator satisfies this automatically.
106
;   boundary; the allocator satisfies this automatically.
107
struct ehci_pipe
107
struct ehci_pipe
108
NextQH                  dd      ?
108
NextQH                  dd      ?
109
; 1. First bit (bit 0) is Terminate bit, 1 = there is no next QH.
109
; 1. First bit (bit 0) is Terminate bit, 1 = there is no next QH.
110
; 2. Next two bits (bits 1-2) are Type field of the next QH,
110
; 2. Next two bits (bits 1-2) are Type field of the next QH,
111
;    one of EHCI_TYPE_* constants.
111
;    one of EHCI_TYPE_* constants.
112
; 3. Next two bits (bits 3-4) are reserved, must be zero.
112
; 3. Next two bits (bits 3-4) are reserved, must be zero.
113
; 4. With masked 5 lower bits, this is the physical address of the next object
113
; 4. With masked 5 lower bits, this is the physical address of the next object
114
;    to be processed, usually next QH.
114
;    to be processed, usually next QH.
115
Token                   dd      ?
115
Token                   dd      ?
116
; 1. Lower 7 bits are DeviceAddress field. This is the address of the
116
; 1. Lower 7 bits are DeviceAddress field. This is the address of the
117
;    target device on the USB bus.
117
;    target device on the USB bus.
118
; 2. Next bit (bit 7) is Inactivate-on-next-transaction bit. Can be nonzero
118
; 2. Next bit (bit 7) is Inactivate-on-next-transaction bit. Can be nonzero
119
;    only for interrupt/isochronous USB1 endpoints.
119
;    only for interrupt/isochronous USB1 endpoints.
120
; 3. Next 4 bits (bits 8-11) are Endpoint field. This is the target endpoint
120
; 3. Next 4 bits (bits 8-11) are Endpoint field. This is the target endpoint
121
;    number.
121
;    number.
122
; 4. Next 2 bits (bits 12-13) are EndpointSpeed field, one of EHCI_SPEED_*.
122
; 4. Next 2 bits (bits 12-13) are EndpointSpeed field, one of EHCI_SPEED_*.
123
; 5. Next bit (bit 14) is DataToggleControl bit,
123
; 5. Next bit (bit 14) is DataToggleControl bit,
124
;    0 = use DataToggle bit from QH, 1 = from TD.
124
;    0 = use DataToggle bit from QH, 1 = from TD.
125
; 6. Next bit (bit 15) is Head-of-reclamation-list. The head of Control list
125
; 6. Next bit (bit 15) is Head-of-reclamation-list. The head of Control list
126
;    has 1 here, all other QHs have zero.
126
;    has 1 here, all other QHs have zero.
127
; 7. Next 11 bits (bits 16-26) are MaximumPacketLength field for the target
127
; 7. Next 11 bits (bits 16-26) are MaximumPacketLength field for the target
128
;    endpoint.
128
;    endpoint.
129
; 8. Next bit (bit 27) is ControlEndpoint bit, must be 1 for USB1 control
129
; 8. Next bit (bit 27) is ControlEndpoint bit, must be 1 for USB1 control
130
;    endpoints and 0 for all others.
130
;    endpoints and 0 for all others.
131
; 9. Upper 4 bits (bits 28-31) are NakCountReload field.
131
; 9. Upper 4 bits (bits 28-31) are NakCountReload field.
132
;    Zero for USB1 endpoints, zero for periodic endpoints.
132
;    Zero for USB1 endpoints, zero for periodic endpoints.
133
;    For control/bulk USB2 endpoints, the code sets it to 4,
133
;    For control/bulk USB2 endpoints, the code sets it to 4,
134
;    which is rather arbitrary.
134
;    which is rather arbitrary.
135
Flags                   dd      ?
135
Flags                   dd      ?
136
; 1. Lower byte is S-mask, each bit corresponds to one microframe per frame;
136
; 1. Lower byte is S-mask, each bit corresponds to one microframe per frame;
137
;    bit is set <=> enable transactions in this microframe.
137
;    bit is set <=> enable transactions in this microframe.
138
; 2. Next byte is C-mask, each bit corresponds to one microframe per frame;
138
; 2. Next byte is C-mask, each bit corresponds to one microframe per frame;
139
;    bit is set <=> enable complete-split transactions in this microframe.
139
;    bit is set <=> enable complete-split transactions in this microframe.
140
;    Meaningful only for USB1 endpoints.
140
;    Meaningful only for USB1 endpoints.
141
; 3. Next 14 bits give address of the target device as hub:port, bits 16-22
141
; 3. Next 14 bits give address of the target device as hub:port, bits 16-22
142
;    are the USB address of the hub, bits 23-29 are the port number.
142
;    are the USB address of the hub, bits 23-29 are the port number.
143
;    Meaningful only for USB1 endpoints.
143
;    Meaningful only for USB1 endpoints.
144
; 4. Upper 2 bits define number of consequetive transactions per micro-frame
144
; 4. Upper 2 bits define number of consequetive transactions per micro-frame
145
;    which host is allowed to permit for this endpoint.
145
;    which host is allowed to permit for this endpoint.
146
;    For control/bulk endpoints, it must be 1.
146
;    For control/bulk endpoints, it must be 1.
147
;    For periodic endpoints, the value is taken from the endpoint descriptor.
147
;    For periodic endpoints, the value is taken from the endpoint descriptor.
148
HeadTD                  dd      ?
148
HeadTD                  dd      ?
149
; The physical address of the first TD for this pipe.
149
; The physical address of the first TD for this pipe.
150
; Lower 5 bits must be zero.
150
; Lower 5 bits must be zero.
151
Overlay                 ehci_hardware_td        ?
151
Overlay                 ehci_hardware_td        ?
152
; Working area for the current TD, if there is any.
152
; Working area for the current TD, if there is any.
153
; When TD is retired, it is written to that TD and Overlay is loaded
153
; When TD is retired, it is written to that TD and Overlay is loaded
154
; from the new TD, if any.
154
; from the new TD, if any.
155
BaseList                dd      ?
155
BaseList                dd      ?
156
; Pointer to head of the corresponding pipe list.
156
; Pointer to head of the corresponding pipe list.
157
SoftwarePart            rd      sizeof.usb_pipe/4
157
SoftwarePart            rd      sizeof.usb_pipe/4
158
; Software part, common for all controllers.
158
; Software part, common for all controllers.
159
                        rd      2       ; padding
159
                        rd      2       ; padding
160
ends
160
ends
161
 
161
 
162
if sizeof.ehci_pipe mod 32
162
if sizeof.ehci_pipe mod 32
163
.err ehci_pipe must be 32-bytes aligned
163
.err ehci_pipe must be 32-bytes aligned
164
end if
164
end if
165
 
165
 
166
; This structure describes the static head of every list of pipes.
166
; This structure describes the static head of every list of pipes.
167
; The hardware requires 32-bytes alignment of this structure.
167
; The hardware requires 32-bytes alignment of this structure.
168
; All instances of this structure are located sequentially in ehci_controller,
168
; All instances of this structure are located sequentially in ehci_controller,
169
; ehci_controller is page-aligned, so it is sufficient to make this structure
169
; ehci_controller is page-aligned, so it is sufficient to make this structure
170
; 32-bytes aligned and verify that the first instance is 32-bytes aligned
170
; 32-bytes aligned and verify that the first instance is 32-bytes aligned
171
; inside ehci_controller.
171
; inside ehci_controller.
172
; The hardware also requires that 44h bytes (size of 64-bit Queue Head
172
; The hardware also requires that 44h bytes (size of 64-bit Queue Head
173
; Descriptor) starting at the beginning of this structure must not cross page
173
; Descriptor) starting at the beginning of this structure must not cross page
174
; boundary. If not, most hardware still behaves correctly (in fact, the last
174
; boundary. If not, most hardware still behaves correctly (in fact, the last
175
; dword can have any value and this structure is never written), but on some
175
; dword can have any value and this structure is never written), but on some
176
; hardware some things just break in mysterious ways.
176
; hardware some things just break in mysterious ways.
177
struct ehci_static_ep
177
struct ehci_static_ep
178
; Hardware fields are the same as in ehci_pipe.
178
; Hardware fields are the same as in ehci_pipe.
179
; Only NextQH and Overlay.Token are actually used.
179
; Only NextQH and Overlay.Token are actually used.
180
; NB: some emulators ignore Token.Halted bit (probably assuming that it is set
180
; NB: some emulators ignore Token.Halted bit (probably assuming that it is set
181
; only when device fails and emulation never fails) and always follow
181
; only when device fails and emulation never fails) and always follow
182
; [Alternate]NextTD when they see that OverlayToken.Active bit is zero;
182
; [Alternate]NextTD when they see that OverlayToken.Active bit is zero;
183
; so it is important to also set [Alternate]NextTD to 1.
183
; so it is important to also set [Alternate]NextTD to 1.
184
NextQH          dd      ?
184
NextQH          dd      ?
185
Token           dd      ?
185
Token           dd      ?
186
Flags           dd      ?
186
Flags           dd      ?
187
HeadTD          dd      ?
187
HeadTD          dd      ?
188
NextTD          dd      ?
188
NextTD          dd      ?
189
AlternateNextTD dd      ?
189
AlternateNextTD dd      ?
190
OverlayToken    dd      ?
190
OverlayToken    dd      ?
191
NextList        dd      ?
191
NextList        dd      ?
192
SoftwarePart    rd      sizeof.usb_static_ep/4
192
SoftwarePart    rd      sizeof.usb_static_ep/4
193
Bandwidths      rw      8
193
Bandwidths      rw      8
194
                dd      ?
194
                dd      ?
195
ends
195
ends
196
 
196
 
197
if sizeof.ehci_static_ep mod 32
197
if sizeof.ehci_static_ep mod 32
198
.err ehci_static_ep must be 32-bytes aligned
198
.err ehci_static_ep must be 32-bytes aligned
199
end if
199
end if
200
 
200
 
201
if ehci_static_ep.OverlayToken <> ehci_pipe.Overlay.Token
201
if ehci_static_ep.OverlayToken <> ehci_pipe.Overlay.Token
202
.err ehci_static_ep.OverlayToken misplaced
202
.err ehci_static_ep.OverlayToken misplaced
203
end if
203
end if
204
 
204
 
205
; EHCI-specific part of controller data.
205
; EHCI-specific part of controller data.
206
; * The structure includes two parts, the hardware part and the software part.
206
; * The structure includes two parts, the hardware part and the software part.
207
; * The hardware part consists of first 4096 bytes and corresponds to
207
; * The hardware part consists of first 4096 bytes and corresponds to
208
;   the Periodic Frame List from the EHCI specification.
208
;   the Periodic Frame List from the EHCI specification.
209
; * The hardware requires page-alignment of the hardware part, so
209
; * The hardware requires page-alignment of the hardware part, so
210
;   the entire descriptor must be page-aligned.
210
;   the entire descriptor must be page-aligned.
211
;   This structure is allocated with kernel_alloc (see usb_init_controller),
211
;   This structure is allocated with kernel_alloc (see usb_init_controller),
212
;   this gives page-aligned data.
212
;   this gives page-aligned data.
213
; * The controller is described by both ehci_controller and usb_controller
213
; * The controller is described by both ehci_controller and usb_controller
214
;   structures, for each controller there is one ehci_controller and one
214
;   structures, for each controller there is one ehci_controller and one
215
;   usb_controller structure. These structures are located sequentially
215
;   usb_controller structure. These structures are located sequentially
216
;   in the memory: beginning from some page start, there is ehci_controller
216
;   in the memory: beginning from some page start, there is ehci_controller
217
;   structure - this enforces hardware alignment requirements - and then
217
;   structure - this enforces hardware alignment requirements - and then
218
;   usb_controller structure.
218
;   usb_controller structure.
219
; * The code keeps pointer to usb_controller structure. The ehci_controller
219
; * The code keeps pointer to usb_controller structure. The ehci_controller
220
;   structure is addressed as [ptr + ehci_controller.field - sizeof.ehci_controller].
220
;   structure is addressed as [ptr + ehci_controller.field - sizeof.ehci_controller].
221
struct ehci_controller
221
struct ehci_controller
222
; ------------------------------ hardware fields ------------------------------
222
; ------------------------------ hardware fields ------------------------------
223
FrameList               rd      1024
223
FrameList               rd      1024
224
; Entry n corresponds to the head of the frame list to be executed in
224
; Entry n corresponds to the head of the frame list to be executed in
225
; the frames n,n+1024,n+2048,n+3072,...
225
; the frames n,n+1024,n+2048,n+3072,...
226
; The first bit of each entry is Terminate bit, 1 = the frame is empty.
226
; The first bit of each entry is Terminate bit, 1 = the frame is empty.
227
; Bits 1-2 are Type field, one of EHCI_TYPE_* constants.
227
; Bits 1-2 are Type field, one of EHCI_TYPE_* constants.
228
; Bits 3-4 must be zero.
228
; Bits 3-4 must be zero.
229
; With masked 5 lower bits, the entry is a physical address of the first QH/TD
229
; With masked 5 lower bits, the entry is a physical address of the first QH/TD
230
; to be executed.
230
; to be executed.
231
; ------------------------------ software fields ------------------------------
231
; ------------------------------ software fields ------------------------------
232
; Every list has the static head, which is an always halted QH.
232
; Every list has the static head, which is an always halted QH.
233
; The following fields are static heads, one per list:
233
; The following fields are static heads, one per list:
234
; 32+16+8+4+2+1 = 63 for Periodic lists, 1 for Control list and 1 for Bulk list.
234
; 32+16+8+4+2+1 = 63 for Periodic lists, 1 for Control list and 1 for Bulk list.
235
IntEDs                  ehci_static_ep
235
IntEDs                  ehci_static_ep
236
                        rb      62 * sizeof.ehci_static_ep
236
                        rb      62 * sizeof.ehci_static_ep
237
; Beware.
237
; Beware.
238
; Two following strings ensure that 44h bytes at any static head
238
; Two following strings ensure that 44h bytes at any static head
239
; do not cross page boundary. Without that, the code "works on my machine"...
239
; do not cross page boundary. Without that, the code "works on my machine"...
240
; but fails on some hardware in seemingly unrelated ways.
240
; but fails on some hardware in seemingly unrelated ways.
241
; One hardware TD (without any software fields) fit in the rest of the page.
241
; One hardware TD (without any software fields) fit in the rest of the page.
242
ehci_controller.ControlDelta = 2000h - (ehci_controller.IntEDs + 63 * sizeof.ehci_static_ep)
242
ehci_controller.ControlDelta = 2000h - (ehci_controller.IntEDs + 63 * sizeof.ehci_static_ep)
243
StopQueueTD             ehci_hardware_td
243
StopQueueTD             ehci_hardware_td
244
; Used as AlternateNextTD for transfers when short packet is considered
244
; Used as AlternateNextTD for transfers when short packet is considered
245
; as an error; short packet must stop the queue in this case, not advance
245
; as an error; short packet must stop the queue in this case, not advance
246
; to the next transfer.
246
; to the next transfer.
247
                        rb      ehci_controller.ControlDelta - sizeof.ehci_hardware_td
247
                        rb      ehci_controller.ControlDelta - sizeof.ehci_hardware_td
248
; Padding for page-alignment.
248
; Padding for page-alignment.
249
ControlED               ehci_static_ep
249
ControlED               ehci_static_ep
250
BulkED                  ehci_static_ep
250
BulkED                  ehci_static_ep
251
MMIOBase1               dd      ?
251
MMIOBase1               dd      ?
252
; Virtual address of memory-mapped area with part 1 of EHCI registers EhciXxxReg.
252
; Virtual address of memory-mapped area with part 1 of EHCI registers EhciXxxReg.
253
MMIOBase2               dd      ?
253
MMIOBase2               dd      ?
254
; Pointer inside memory-mapped area MMIOBase1; points to part 2 of EHCI registers.
254
; Pointer inside memory-mapped area MMIOBase1; points to part 2 of EHCI registers.
255
StructuralParams        dd      ?
255
StructuralParams        dd      ?
256
; Copy of EhciStructParamsReg value.
256
; Copy of EhciStructParamsReg value.
257
CapabilityParams        dd      ?
257
CapabilityParams        dd      ?
258
; Copy of EhciCapParamsReg value.
258
; Copy of EhciCapParamsReg value.
259
DeferredActions         dd      ?
259
DeferredActions         dd      ?
260
; Bitmask of events from EhciStatusReg which were observed by the IRQ handler
260
; Bitmask of events from EhciStatusReg which were observed by the IRQ handler
261
; and needs to be processed in the IRQ thread.
261
; and needs to be processed in the IRQ thread.
262
ends
262
ends
263
 
263
 
264
if ehci_controller.IntEDs mod 32
264
if ehci_controller.IntEDs mod 32
265
.err Static endpoint descriptors must be 32-bytes aligned inside ehci_controller
265
.err Static endpoint descriptors must be 32-bytes aligned inside ehci_controller
266
end if
266
end if
267
 
267
 
268
; Description of #HCI-specific data and functions for
268
; Description of #HCI-specific data and functions for
269
; controller-independent code.
269
; controller-independent code.
270
; Implements the structure usb_hardware_func from hccommon.inc for EHCI.
270
; Implements the structure usb_hardware_func from hccommon.inc for EHCI.
271
iglobal
271
iglobal
272
align 4
272
align 4
273
ehci_hardware_func:
273
ehci_hardware_func:
274
        dd      'EHCI'
274
        dd      'EHCI'
275
        dd      sizeof.ehci_controller
275
        dd      sizeof.ehci_controller
276
        dd      ehci_init
276
        dd      ehci_init
277
        dd      ehci_process_deferred
277
        dd      ehci_process_deferred
278
        dd      ehci_set_device_address
278
        dd      ehci_set_device_address
279
        dd      ehci_get_device_address
279
        dd      ehci_get_device_address
280
        dd      ehci_port_disable
280
        dd      ehci_port_disable
281
        dd      ehci_new_port.reset
281
        dd      ehci_new_port.reset
282
        dd      ehci_set_endpoint_packet_size
282
        dd      ehci_set_endpoint_packet_size
283
        dd      ehci_alloc_pipe
283
        dd      ehci_alloc_pipe
284
        dd      ehci_free_pipe
284
        dd      ehci_free_pipe
285
        dd      ehci_init_pipe
285
        dd      ehci_init_pipe
286
        dd      ehci_unlink_pipe
286
        dd      ehci_unlink_pipe
287
        dd      ehci_alloc_td
287
        dd      ehci_alloc_td
288
        dd      ehci_free_td
288
        dd      ehci_free_td
289
        dd      ehci_alloc_transfer
289
        dd      ehci_alloc_transfer
290
        dd      ehci_insert_transfer
290
        dd      ehci_insert_transfer
291
        dd      ehci_new_device
291
        dd      ehci_new_device
292
endg
292
endg
293
 
293
 
294
; =============================================================================
294
; =============================================================================
295
; =================================== Code ====================================
295
; =================================== Code ====================================
296
; =============================================================================
296
; =============================================================================
297
 
297
 
298
; Controller-specific initialization function.
298
; Controller-specific initialization function.
299
; Called from usb_init_controller. Initializes the hardware and
299
; Called from usb_init_controller. Initializes the hardware and
300
; EHCI-specific parts of software structures.
300
; EHCI-specific parts of software structures.
301
; eax = pointer to ehci_controller to be initialized
301
; eax = pointer to ehci_controller to be initialized
302
; [ebp-4] = pcidevice
302
; [ebp-4] = pcidevice
303
proc ehci_init
303
proc ehci_init
304
; inherit some variables from the parent (usb_init_controller)
304
; inherit some variables from the parent (usb_init_controller)
305
.devfn   equ ebp - 4
305
.devfn   equ ebp - 4
306
.bus     equ ebp - 3
306
.bus     equ ebp - 3
307
; 1. Store pointer to ehci_controller for further use.
307
; 1. Store pointer to ehci_controller for further use.
308
        push    eax
308
        push    eax
309
        mov     edi, eax
309
        mov     edi, eax
310
        mov     esi, eax
310
        mov     esi, eax
311
; 2. Initialize ehci_controller.FrameList.
311
; 2. Initialize ehci_controller.FrameList.
312
; Note that FrameList is located in the beginning of ehci_controller,
312
; Note that FrameList is located in the beginning of ehci_controller,
313
; so esi and edi now point to ehci_controller.FrameList.
313
; so esi and edi now point to ehci_controller.FrameList.
314
; First 32 entries of FrameList contain physical addresses
314
; First 32 entries of FrameList contain physical addresses
315
; of first 32 Periodic static heads, further entries duplicate these.
315
; of first 32 Periodic static heads, further entries duplicate these.
316
; See the description of structures for full info.
316
; See the description of structures for full info.
317
; 2a. Get physical address of first static head.
317
; 2a. Get physical address of first static head.
318
; Note that 1) it is located in the beginning of a page
318
; Note that 1) it is located in the beginning of a page
319
; and 2) first 32 static heads fit in the same page,
319
; and 2) first 32 static heads fit in the same page,
320
; so one call to get_phys_addr without correction of lower 12 bits
320
; so one call to get_phys_addr without correction of lower 12 bits
321
; is sufficient.
321
; is sufficient.
322
if (ehci_controller.IntEDs / 0x1000) <> ((ehci_controller.IntEDs + 32 * sizeof.ehci_static_ep) / 0x1000)
322
if (ehci_controller.IntEDs / 0x1000) <> ((ehci_controller.IntEDs + 32 * sizeof.ehci_static_ep) / 0x1000)
323
.err assertion failed
323
.err assertion failed
324
end if
324
end if
325
if (ehci_controller.IntEDs mod 0x1000) <> 0
325
if (ehci_controller.IntEDs mod 0x1000) <> 0
326
.err assertion failed
326
.err assertion failed
327
end if
327
end if
328
        add     eax, ehci_controller.IntEDs
328
        add     eax, ehci_controller.IntEDs
329
        call    get_phys_addr
329
        call    get_phys_addr
330
; 2b. Fill first 32 entries.
330
; 2b. Fill first 32 entries.
331
        inc     eax
331
        inc     eax
332
        inc     eax     ; set Type to EHCI_TYPE_QH
332
        inc     eax     ; set Type to EHCI_TYPE_QH
333
        push    32
-
 
334
        pop     ecx
333
        movi    ecx, 32
335
        mov     edx, ecx
334
        mov     edx, ecx
336
@@:
335
@@:
337
        stosd
336
        stosd
338
        add     eax, sizeof.ehci_static_ep
337
        add     eax, sizeof.ehci_static_ep
339
        loop    @b
338
        loop    @b
340
; 2c. Fill the rest entries.
339
; 2c. Fill the rest entries.
341
        mov     ecx, 1024 - 32
340
        mov     ecx, 1024 - 32
342
        rep movsd
341
        rep movsd
343
; 3. Initialize static heads ehci_controller.*ED.
342
; 3. Initialize static heads ehci_controller.*ED.
344
; Use the loop over groups: first group consists of first 32 Periodic
343
; Use the loop over groups: first group consists of first 32 Periodic
345
; descriptors, next group consists of next 16 Periodic descriptors,
344
; descriptors, next group consists of next 16 Periodic descriptors,
346
; ..., last group consists of the last Periodic descriptor.
345
; ..., last group consists of the last Periodic descriptor.
347
; 3a. Prepare for the loop.
346
; 3a. Prepare for the loop.
348
; make esi point to the second group, other registers are already set.
347
; make esi point to the second group, other registers are already set.
349
        add     esi, 32*4 + 32*sizeof.ehci_static_ep
348
        add     esi, 32*4 + 32*sizeof.ehci_static_ep
350
; 3b. Loop over groups. On every iteration:
349
; 3b. Loop over groups. On every iteration:
351
; edx = size of group, edi = pointer to the current group,
350
; edx = size of group, edi = pointer to the current group,
352
; esi = pointer to the next group.
351
; esi = pointer to the next group.
353
.init_static_eds:
352
.init_static_eds:
354
; 3c. Get the size of next group.
353
; 3c. Get the size of next group.
355
        shr     edx, 1
354
        shr     edx, 1
356
; 3d. Exit the loop if there is no next group.
355
; 3d. Exit the loop if there is no next group.
357
        jz      .init_static_eds_done
356
        jz      .init_static_eds_done
358
; 3e. Initialize the first half of the current group.
357
; 3e. Initialize the first half of the current group.
359
; Advance edi to the second half.
358
; Advance edi to the second half.
360
        push    esi
359
        push    esi
361
        call    ehci_init_static_ep_group
360
        call    ehci_init_static_ep_group
362
        pop     esi
361
        pop     esi
363
; 3f. Initialize the second half of the current group
362
; 3f. Initialize the second half of the current group
364
; with the same values.
363
; with the same values.
365
; Advance edi to the next group, esi/eax to the next of the next group.
364
; Advance edi to the next group, esi/eax to the next of the next group.
366
        call    ehci_init_static_ep_group
365
        call    ehci_init_static_ep_group
367
        jmp     .init_static_eds
366
        jmp     .init_static_eds
368
.init_static_eds_done:
367
.init_static_eds_done:
369
; 3g. Initialize the last static head.
368
; 3g. Initialize the last static head.
370
        xor     esi, esi
369
        xor     esi, esi
371
        call    ehci_init_static_endpoint
370
        call    ehci_init_static_endpoint
372
; While we are here, initialize StopQueueTD.
371
; While we are here, initialize StopQueueTD.
373
if (ehci_controller.StopQueueTD <> ehci_controller.IntEDs + 63 * sizeof.ehci_static_ep)
372
if (ehci_controller.StopQueueTD <> ehci_controller.IntEDs + 63 * sizeof.ehci_static_ep)
374
.err assertion failed
373
.err assertion failed
375
end if
374
end if
376
        inc     [edi+ehci_hardware_td.NextTD]   ; 0 -> 1
375
        inc     [edi+ehci_hardware_td.NextTD]   ; 0 -> 1
377
        inc     [edi+ehci_hardware_td.AlternateNextTD]  ; 0 -> 1
376
        inc     [edi+ehci_hardware_td.AlternateNextTD]  ; 0 -> 1
378
; leave other fields as zero, including Active bit
377
; leave other fields as zero, including Active bit
379
; 3i. Initialize the head of Control list.
378
; 3i. Initialize the head of Control list.
380
        add     edi, ehci_controller.ControlDelta
379
        add     edi, ehci_controller.ControlDelta
381
        lea     esi, [edi+sizeof.ehci_static_ep]
380
        lea     esi, [edi+sizeof.ehci_static_ep]
382
        call    ehci_init_static_endpoint
381
        call    ehci_init_static_endpoint
383
        or      byte [edi-sizeof.ehci_static_ep+ehci_static_ep.Token+1], 80h
382
        or      byte [edi-sizeof.ehci_static_ep+ehci_static_ep.Token+1], 80h
384
; 3j. Initialize the head of Bulk list.
383
; 3j. Initialize the head of Bulk list.
385
        sub     esi, sizeof.ehci_static_ep
384
        sub     esi, sizeof.ehci_static_ep
386
        call    ehci_init_static_endpoint
385
        call    ehci_init_static_endpoint
387
; 4. Create a virtual memory area to talk with the controller.
386
; 4. Create a virtual memory area to talk with the controller.
388
; 4a. Enable memory & bus master access.
387
; 4a. Enable memory & bus master access.
389
        mov     ch, [.bus]
388
        mov     ch, [.bus]
390
        mov     cl, 1
389
        mov     cl, 1
391
        mov     eax, ecx
390
        mov     eax, ecx
392
        mov     bh, [.devfn]
391
        mov     bh, [.devfn]
393
        mov     bl, 4
392
        mov     bl, 4
394
        call    pci_read_reg
393
        call    pci_read_reg
395
        or      al, 6
394
        or      al, 6
396
        xchg    eax, ecx
395
        xchg    eax, ecx
397
        call    pci_write_reg
396
        call    pci_write_reg
398
; 4b. Read memory base address.
397
; 4b. Read memory base address.
399
        mov     ah, [.bus]
398
        mov     ah, [.bus]
400
        mov     al, 2
399
        mov     al, 2
401
        mov     bl, 10h
400
        mov     bl, 10h
402
        call    pci_read_reg
401
        call    pci_read_reg
403
;       DEBUGF 1,'K : phys MMIO %x\n',eax
402
;       DEBUGF 1,'K : phys MMIO %x\n',eax
404
        and     al, not 0Fh
403
        and     al, not 0Fh
405
; 4c. Create mapping for physical memory. 200h bytes are always sufficient.
404
; 4c. Create mapping for physical memory. 200h bytes are always sufficient.
406
        stdcall map_io_mem, eax, 200h, PG_SW+PG_NOCACHE
405
        stdcall map_io_mem, eax, 200h, PG_SW+PG_NOCACHE
407
        test    eax, eax
406
        test    eax, eax
408
        jz      .fail
407
        jz      .fail
409
;       DEBUGF 1,'K : MMIO %x\n',eax
408
;       DEBUGF 1,'K : MMIO %x\n',eax
410
if ehci_controller.MMIOBase1 <> ehci_controller.BulkED + sizeof.ehci_static_ep
409
if ehci_controller.MMIOBase1 <> ehci_controller.BulkED + sizeof.ehci_static_ep
411
.err assertion failed
410
.err assertion failed
412
end if
411
end if
413
        stosd   ; fill ehci_controller.MMIOBase1
412
        stosd   ; fill ehci_controller.MMIOBase1
414
        movzx   ecx, byte [eax+EhciCapLengthReg]
413
        movzx   ecx, byte [eax+EhciCapLengthReg]
415
        mov     edx, [eax+EhciCapParamsReg]
414
        mov     edx, [eax+EhciCapParamsReg]
416
        mov     ebx, [eax+EhciStructParamsReg]
415
        mov     ebx, [eax+EhciStructParamsReg]
417
        add     eax, ecx
416
        add     eax, ecx
418
if ehci_controller.MMIOBase2 <> ehci_controller.MMIOBase1 + 4
417
if ehci_controller.MMIOBase2 <> ehci_controller.MMIOBase1 + 4
419
.err assertion failed
418
.err assertion failed
420
end if
419
end if
421
        stosd   ; fill ehci_controller.MMIOBase2
420
        stosd   ; fill ehci_controller.MMIOBase2
422
if ehci_controller.StructuralParams <> ehci_controller.MMIOBase2 + 4
421
if ehci_controller.StructuralParams <> ehci_controller.MMIOBase2 + 4
423
.err assertion failed
422
.err assertion failed
424
end if
423
end if
425
if ehci_controller.CapabilityParams <> ehci_controller.StructuralParams + 4
424
if ehci_controller.CapabilityParams <> ehci_controller.StructuralParams + 4
426
.err assertion failed
425
.err assertion failed
427
end if
426
end if
428
        mov     [edi], ebx      ; fill ehci_controller.StructuralParams
427
        mov     [edi], ebx      ; fill ehci_controller.StructuralParams
429
        mov     [edi+4], edx    ; fill ehci_controller.CapabilityParams
428
        mov     [edi+4], edx    ; fill ehci_controller.CapabilityParams
430
        DEBUGF 1,'K : HCSPARAMS=%x, HCCPARAMS=%x\n',ebx,edx
429
        DEBUGF 1,'K : HCSPARAMS=%x, HCCPARAMS=%x\n',ebx,edx
431
        and     ebx, 15
430
        and     ebx, 15
432
        mov     [edi+usb_controller.NumPorts+sizeof.ehci_controller-ehci_controller.StructuralParams], ebx
431
        mov     [edi+usb_controller.NumPorts+sizeof.ehci_controller-ehci_controller.StructuralParams], ebx
433
        mov     edi, eax
432
        mov     edi, eax
434
; now edi = MMIOBase2
433
; now edi = MMIOBase2
435
; 6. Transfer the controller to a known state.
434
; 6. Transfer the controller to a known state.
436
; 6b. Stop the controller if it is running.
435
; 6b. Stop the controller if it is running.
437
        push    10
-
 
438
        pop     ecx
436
        movi    ecx, 10
439
        test    dword [edi+EhciStatusReg], 1 shl 12
437
        test    dword [edi+EhciStatusReg], 1 shl 12
440
        jnz     .stopped
438
        jnz     .stopped
441
        and     dword [edi+EhciCommandReg], not 1
439
        and     dword [edi+EhciCommandReg], not 1
442
@@:
440
@@:
443
        push    1
-
 
444
        pop     esi
441
        movi    esi, 1
445
        call    delay_ms
442
        call    delay_ms
446
        test    dword [edi+EhciStatusReg], 1 shl 12
443
        test    dword [edi+EhciStatusReg], 1 shl 12
447
        jnz     .stopped
444
        jnz     .stopped
448
        loop    @b
445
        loop    @b
449
        dbgstr 'Failed to stop EHCI controller'
446
        dbgstr 'Failed to stop EHCI controller'
450
        jmp     .fail_unmap
447
        jmp     .fail_unmap
451
.stopped:
448
.stopped:
452
; 6c. Reset the controller. Wait up to 50 ms checking status every 1 ms.
449
; 6c. Reset the controller. Wait up to 50 ms checking status every 1 ms.
453
        or      dword [edi+EhciCommandReg], 2
450
        or      dword [edi+EhciCommandReg], 2
454
        push    50
-
 
455
        pop     ecx
451
        movi    ecx, 50
456
@@:
452
@@:
457
        push    1
-
 
458
        pop     esi
453
        movi    esi, 1
459
        call    delay_ms
454
        call    delay_ms
460
        test    dword [edi+EhciCommandReg], 2
455
        test    dword [edi+EhciCommandReg], 2
461
        jz      .reset_ok
456
        jz      .reset_ok
462
        loop    @b
457
        loop    @b
463
        dbgstr 'Failed to reset EHCI controller'
458
        dbgstr 'Failed to reset EHCI controller'
464
        jmp     .fail_unmap
459
        jmp     .fail_unmap
465
.reset_ok:
460
.reset_ok:
466
; 7. Configure the controller.
461
; 7. Configure the controller.
467
        pop     esi     ; restore the pointer saved at step 1
462
        pop     esi     ; restore the pointer saved at step 1
468
        add     esi, sizeof.ehci_controller
463
        add     esi, sizeof.ehci_controller
469
; 7a. If the controller is 64-bit, say to it that all structures are located
464
; 7a. If the controller is 64-bit, say to it that all structures are located
470
; in first 4G.
465
; in first 4G.
471
        test    byte [esi+ehci_controller.CapabilityParams-sizeof.ehci_controller], 1
466
        test    byte [esi+ehci_controller.CapabilityParams-sizeof.ehci_controller], 1
472
        jz      @f
467
        jz      @f
473
        mov     dword [edi+EhciCtrlDataSegReg], 0
468
        mov     dword [edi+EhciCtrlDataSegReg], 0
474
@@:
469
@@:
475
; 7b. Hook interrupt and enable appropriate interrupt sources.
470
; 7b. Hook interrupt and enable appropriate interrupt sources.
476
        mov     ah, [.bus]
471
        mov     ah, [.bus]
477
        mov     al, 0
472
        mov     al, 0
478
        mov     bh, [.devfn]
473
        mov     bh, [.devfn]
479
        mov     bl, 3Ch
474
        mov     bl, 3Ch
480
        call    pci_read_reg
475
        call    pci_read_reg
481
; al = IRQ
476
; al = IRQ
482
        DEBUGF 1,'K : attaching to IRQ %x\n',al
477
        DEBUGF 1,'K : attaching to IRQ %x\n',al
483
        movzx   eax, al
478
        movzx   eax, al
484
        stdcall attach_int_handler, eax, ehci_irq, esi
479
        stdcall attach_int_handler, eax, ehci_irq, esi
485
;       mov     dword [edi+EhciStatusReg], 111111b      ; clear status
480
;       mov     dword [edi+EhciStatusReg], 111111b      ; clear status
486
; disable Frame List Rollover interrupt, enable all other sources
481
; disable Frame List Rollover interrupt, enable all other sources
487
        mov     dword [edi+EhciInterruptReg], 110111b
482
        mov     dword [edi+EhciInterruptReg], 110111b
488
; 7c. Inform the controller of the address of periodic lists head.
483
; 7c. Inform the controller of the address of periodic lists head.
489
        lea     eax, [esi-sizeof.ehci_controller]
484
        lea     eax, [esi-sizeof.ehci_controller]
490
        call    get_phys_addr
485
        call    get_phys_addr
491
        mov     dword [edi+EhciPeriodicListReg], eax
486
        mov     dword [edi+EhciPeriodicListReg], eax
492
; 7d. Inform the controller of the address of asynchronous lists head.
487
; 7d. Inform the controller of the address of asynchronous lists head.
493
        lea     eax, [esi+ehci_controller.ControlED-sizeof.ehci_controller]
488
        lea     eax, [esi+ehci_controller.ControlED-sizeof.ehci_controller]
494
        call    get_phys_addr
489
        call    get_phys_addr
495
        mov     dword [edi+EhciAsyncListReg], eax
490
        mov     dword [edi+EhciAsyncListReg], eax
496
; 7e. Configure operational details and run the controller.
491
; 7e. Configure operational details and run the controller.
497
        mov     dword [edi+EhciCommandReg], \
492
        mov     dword [edi+EhciCommandReg], \
498
                (1 shl 16) + \ ; interrupt threshold = 1 microframe = 0.125ms
493
                (1 shl 16) + \ ; interrupt threshold = 1 microframe = 0.125ms
499
                (0 shl 11) + \ ; disable Async Park Mode
494
                (0 shl 11) + \ ; disable Async Park Mode
500
                (0 shl 8) +  \ ; zero Async Park Mode Count
495
                (0 shl 8) +  \ ; zero Async Park Mode Count
501
                (1 shl 5) +  \ ; Async Schedule Enable
496
                (1 shl 5) +  \ ; Async Schedule Enable
502
                (1 shl 4) +  \ ; Periodic Schedule Enable
497
                (1 shl 4) +  \ ; Periodic Schedule Enable
503
                (0 shl 2) +  \ ; 1024 elements in FrameList
498
                (0 shl 2) +  \ ; 1024 elements in FrameList
504
                1              ; Run
499
                1              ; Run
505
; 7f. Route all ports to this controller, not companion controllers.
500
; 7f. Route all ports to this controller, not companion controllers.
506
        mov     dword [edi+EhciConfigFlagReg], 1
501
        mov     dword [edi+EhciConfigFlagReg], 1
507
        DEBUGF 1,'K : EHCI controller at %x:%x with %d ports initialized\n',[.bus]:2,[.devfn]:2,[esi+usb_controller.NumPorts]
502
        DEBUGF 1,'K : EHCI controller at %x:%x with %d ports initialized\n',[.bus]:2,[.devfn]:2,[esi+usb_controller.NumPorts]
508
; 8. Apply port power, if needed, and disable all ports.
503
; 8. Apply port power, if needed, and disable all ports.
509
        xor     ecx, ecx
504
        xor     ecx, ecx
510
@@:
505
@@:
511
        mov     dword [edi+EhciPortsReg+ecx*4], 1000h   ; Port Power enabled, all other bits disabled
506
        mov     dword [edi+EhciPortsReg+ecx*4], 1000h   ; Port Power enabled, all other bits disabled
512
        inc     ecx
507
        inc     ecx
513
        cmp     ecx, [esi+usb_controller.NumPorts]
508
        cmp     ecx, [esi+usb_controller.NumPorts]
514
        jb      @b
509
        jb      @b
515
        test    byte [esi+ehci_controller.StructuralParams-sizeof.ehci_controller], 10h
510
        test    byte [esi+ehci_controller.StructuralParams-sizeof.ehci_controller], 10h
516
        jz      @f
511
        jz      @f
517
        push    esi
512
        push    esi
518
        push    20
-
 
519
        pop     esi
513
        movi    esi, 20
520
        call    delay_ms
514
        call    delay_ms
521
        pop     esi
515
        pop     esi
522
@@:
516
@@:
523
; 9. Return pointer to usb_controller.
517
; 9. Return pointer to usb_controller.
524
        xchg    eax, esi
518
        xchg    eax, esi
525
        ret
519
        ret
526
; On error, pop the pointer saved at step 1 and return zero.
520
; On error, pop the pointer saved at step 1 and return zero.
527
; Note that the main code branch restores the stack at step 7 and never fails
521
; Note that the main code branch restores the stack at step 7 and never fails
528
; after step 7.
522
; after step 7.
529
.fail_unmap:
523
.fail_unmap:
530
        pop     eax
524
        pop     eax
531
        push    eax
525
        push    eax
532
        stdcall free_kernel_space, [eax+ehci_controller.MMIOBase1]
526
        stdcall free_kernel_space, [eax+ehci_controller.MMIOBase1]
533
.fail:
527
.fail:
534
        pop     ecx
528
        pop     ecx
535
        xor     eax, eax
529
        xor     eax, eax
536
        ret
530
        ret
537
endp
531
endp
538
 
532
 
539
; Helper procedure for step 3 of ehci_init, see comments there.
533
; Helper procedure for step 3 of ehci_init, see comments there.
540
; Initializes the static head of one list.
534
; Initializes the static head of one list.
541
; esi = pointer to the "next" list, edi = pointer to head to initialize.
535
; esi = pointer to the "next" list, edi = pointer to head to initialize.
542
; Advances edi to the next head, keeps esi.
536
; Advances edi to the next head, keeps esi.
543
proc ehci_init_static_endpoint
537
proc ehci_init_static_endpoint
544
        xor     eax, eax
538
        xor     eax, eax
545
        inc     eax     ; set Terminate bit
539
        inc     eax     ; set Terminate bit
546
        mov     [edi+ehci_static_ep.NextTD], eax
540
        mov     [edi+ehci_static_ep.NextTD], eax
547
        mov     [edi+ehci_static_ep.AlternateNextTD], eax
541
        mov     [edi+ehci_static_ep.AlternateNextTD], eax
548
        test    esi, esi
542
        test    esi, esi
549
        jz      @f
543
        jz      @f
550
        mov     eax, esi
544
        mov     eax, esi
551
        call    get_phys_addr
545
        call    get_phys_addr
552
        inc     eax
546
        inc     eax
553
        inc     eax     ; set Type to EHCI_TYPE_QH
547
        inc     eax     ; set Type to EHCI_TYPE_QH
554
@@:
548
@@:
555
        mov     [edi+ehci_static_ep.NextQH], eax
549
        mov     [edi+ehci_static_ep.NextQH], eax
556
        mov     [edi+ehci_static_ep.NextList], esi
550
        mov     [edi+ehci_static_ep.NextList], esi
557
        mov     byte [edi+ehci_static_ep.OverlayToken], 1 shl 6 ; halted
551
        mov     byte [edi+ehci_static_ep.OverlayToken], 1 shl 6 ; halted
558
        add     edi, ehci_static_ep.SoftwarePart
552
        add     edi, ehci_static_ep.SoftwarePart
559
        call    usb_init_static_endpoint
553
        call    usb_init_static_endpoint
560
        add     edi, sizeof.ehci_static_ep - ehci_static_ep.SoftwarePart
554
        add     edi, sizeof.ehci_static_ep - ehci_static_ep.SoftwarePart
561
        ret
555
        ret
562
endp
556
endp
563
 
557
 
564
; Helper procedure for step 3 of ehci_init, see comments there.
558
; Helper procedure for step 3 of ehci_init, see comments there.
565
; Initializes one half of group of static heads.
559
; Initializes one half of group of static heads.
566
; edx = size of the next group = half of size of the group,
560
; edx = size of the next group = half of size of the group,
567
; edi = pointer to the group, esi = pointer to the next group.
561
; edi = pointer to the group, esi = pointer to the next group.
568
; Advances esi, edi to next group, keeps edx.
562
; Advances esi, edi to next group, keeps edx.
569
proc ehci_init_static_ep_group
563
proc ehci_init_static_ep_group
570
        push    edx
564
        push    edx
571
@@:
565
@@:
572
        call    ehci_init_static_endpoint
566
        call    ehci_init_static_endpoint
573
        add     esi, sizeof.ehci_static_ep
567
        add     esi, sizeof.ehci_static_ep
574
        dec     edx
568
        dec     edx
575
        jnz     @b
569
        jnz     @b
576
        pop     edx
570
        pop     edx
577
        ret
571
        ret
578
endp
572
endp
579
 
573
 
580
; Controller-specific pre-initialization function: take ownership from BIOS.
574
; Controller-specific pre-initialization function: take ownership from BIOS.
581
; Some BIOSes, although not all of them, use USB controllers themselves
575
; Some BIOSes, although not all of them, use USB controllers themselves
582
; to support USB flash drives. In this case,
576
; to support USB flash drives. In this case,
583
; we must notify the BIOS that we don't need that emulation and know how to
577
; we must notify the BIOS that we don't need that emulation and know how to
584
; deal with USB devices.
578
; deal with USB devices.
585
proc ehci_kickoff_bios
579
proc ehci_kickoff_bios
586
; 1. Get the physical address of MMIO registers.
580
; 1. Get the physical address of MMIO registers.
587
        mov     ah, [esi+PCIDEV.bus]
581
        mov     ah, [esi+PCIDEV.bus]
588
        mov     bh, [esi+PCIDEV.devfn]
582
        mov     bh, [esi+PCIDEV.devfn]
589
        mov     al, 2
583
        mov     al, 2
590
        mov     bl, 10h
584
        mov     bl, 10h
591
        call    pci_read_reg
585
        call    pci_read_reg
592
        and     al, not 0Fh
586
        and     al, not 0Fh
593
; 2. Create mapping for physical memory. 200h bytes are always sufficient.
587
; 2. Create mapping for physical memory. 200h bytes are always sufficient.
594
        stdcall map_io_mem, eax, 200h, PG_SW+PG_NOCACHE
588
        stdcall map_io_mem, eax, 200h, PG_SW+PG_NOCACHE
595
        test    eax, eax
589
        test    eax, eax
596
        jz      .nothing
590
        jz      .nothing
597
        push    eax     ; push argument for step 8
591
        push    eax     ; push argument for step 8
598
; 3. Some BIOSes enable controller interrupts as a result of giving
592
; 3. Some BIOSes enable controller interrupts as a result of giving
599
; controller away. At this point the system knows nothing about how to serve
593
; controller away. At this point the system knows nothing about how to serve
600
; EHCI interrupts, so such an interrupt will send the system into an infinite
594
; EHCI interrupts, so such an interrupt will send the system into an infinite
601
; loop handling the same IRQ again and again. Thus, we need to block EHCI
595
; loop handling the same IRQ again and again. Thus, we need to block EHCI
602
; interrupts. We can't do this at the controller level until step 5,
596
; interrupts. We can't do this at the controller level until step 5,
603
; because the controller is currently owned by BIOS, so we block all hardware
597
; because the controller is currently owned by BIOS, so we block all hardware
604
; interrupts on this processor until step 5.
598
; interrupts on this processor until step 5.
605
        pushf
599
        pushf
606
        cli
600
        cli
607
; 4. Take the ownership over the controller.
601
; 4. Take the ownership over the controller.
608
; 4a. Locate take-ownership capability in the PCI configuration space.
602
; 4a. Locate take-ownership capability in the PCI configuration space.
609
; Limit the loop with 100h iterations; since the entire configuration space is
603
; Limit the loop with 100h iterations; since the entire configuration space is
610
; 100h bytes long, hitting this number of iterations means that something is
604
; 100h bytes long, hitting this number of iterations means that something is
611
; corrupted.
605
; corrupted.
612
; Use a value from MMIO as a starting point.
606
; Use a value from MMIO as a starting point.
613
        mov     edx, [eax+EhciCapParamsReg]
607
        mov     edx, [eax+EhciCapParamsReg]
614
        DEBUGF 1,'K : edx=%x\n',edx
608
        DEBUGF 1,'K : edx=%x\n',edx
615
        movzx   edi, byte [eax+EhciCapLengthReg]
609
        movzx   edi, byte [eax+EhciCapLengthReg]
616
        add     edi, eax
610
        add     edi, eax
617
        push    0
611
        push    0
618
        mov     bl, dh          ; get Extended Capabilities Pointer
612
        mov     bl, dh          ; get Extended Capabilities Pointer
619
        test    bl, bl
613
        test    bl, bl
620
        jz      .has_ownership2
614
        jz      .has_ownership2
621
        cmp     bl, 40h
615
        cmp     bl, 40h
622
        jb      .no_capability
616
        jb      .no_capability
623
.look_bios_handoff:
617
.look_bios_handoff:
624
        test    bl, 3
618
        test    bl, 3
625
        jnz     .no_capability
619
        jnz     .no_capability
626
; In each iteration, read the current dword,
620
; In each iteration, read the current dword,
627
        mov     ah, [esi+PCIDEV.bus]
621
        mov     ah, [esi+PCIDEV.bus]
628
        mov     al, 2
622
        mov     al, 2
629
        mov     bh, [esi+PCIDEV.devfn]
623
        mov     bh, [esi+PCIDEV.devfn]
630
        call    pci_read_reg
624
        call    pci_read_reg
631
; check, whether the capability ID is take-ownership ID = 1,
625
; check, whether the capability ID is take-ownership ID = 1,
632
        cmp     al, 1
626
        cmp     al, 1
633
        jz      .found_bios_handoff
627
        jz      .found_bios_handoff
634
; if not, advance to next-capability link and continue loop.
628
; if not, advance to next-capability link and continue loop.
635
        dec     byte [esp]
629
        dec     byte [esp]
636
        jz      .no_capability
630
        jz      .no_capability
637
        mov     bl, ah
631
        mov     bl, ah
638
        cmp     bl, 40h
632
        cmp     bl, 40h
639
        jae     .look_bios_handoff
633
        jae     .look_bios_handoff
640
.no_capability:
634
.no_capability:
641
        dbgstr 'warning: cannot locate take-ownership capability'
635
        dbgstr 'warning: cannot locate take-ownership capability'
642
        jmp     .has_ownership2
636
        jmp     .has_ownership2
643
.found_bios_handoff:
637
.found_bios_handoff:
644
; 4b. Check whether BIOS has ownership.
638
; 4b. Check whether BIOS has ownership.
645
; Some BIOSes release ownership before loading OS, but forget to unwatch for
639
; Some BIOSes release ownership before loading OS, but forget to unwatch for
646
; change-ownership requests; they cannot handle ownership request, so
640
; change-ownership requests; they cannot handle ownership request, so
647
; such a request sends the system into infinite loop of handling the same SMI
641
; such a request sends the system into infinite loop of handling the same SMI
648
; over and over. Avoid this.
642
; over and over. Avoid this.
649
        inc     ebx
643
        inc     ebx
650
        inc     ebx
644
        inc     ebx
651
        test    eax, 0x10000
645
        test    eax, 0x10000
652
        jz      .has_ownership
646
        jz      .has_ownership
653
; 4c. Request ownership.
647
; 4c. Request ownership.
654
        inc     ebx
648
        inc     ebx
655
        mov     cl, 1
649
        mov     cl, 1
656
        mov     ah, [esi+PCIDEV.bus]
650
        mov     ah, [esi+PCIDEV.bus]
657
        mov     al, 0
651
        mov     al, 0
658
        call    pci_write_reg
652
        call    pci_write_reg
659
; 4d. Some BIOSes set ownership flag, but forget to watch for change-ownership
653
; 4d. Some BIOSes set ownership flag, but forget to watch for change-ownership
660
; requests; if so, there is no sense in waiting.
654
; requests; if so, there is no sense in waiting.
661
        inc     ebx
655
        inc     ebx
662
        mov     ah, [esi+PCIDEV.bus]
656
        mov     ah, [esi+PCIDEV.bus]
663
        mov     al, 2
657
        mov     al, 2
664
        call    pci_read_reg
658
        call    pci_read_reg
665
        dec     ebx
659
        dec     ebx
666
        dec     ebx
660
        dec     ebx
667
        test    ah, 20h
661
        test    ah, 20h
668
        jz      .force_ownership
662
        jz      .force_ownership
669
; 4e. Wait for result no more than 1 s, checking for status every 1 ms.
663
; 4e. Wait for result no more than 1 s, checking for status every 1 ms.
670
; If successful, go to 5.
664
; If successful, go to 5.
671
        mov     dword [esp], 1000
665
        mov     dword [esp], 1000
672
@@:
666
@@:
673
        mov     ah, [esi+PCIDEV.bus]
667
        mov     ah, [esi+PCIDEV.bus]
674
        mov     al, 0
668
        mov     al, 0
675
        call    pci_read_reg
669
        call    pci_read_reg
676
        test    al, 1
670
        test    al, 1
677
        jz      .has_ownership
671
        jz      .has_ownership
678
        push    esi
672
        push    esi
679
        push    1
-
 
680
        pop     esi
673
        movi    esi, 1
681
        call    delay_ms
674
        call    delay_ms
682
        pop     esi
675
        pop     esi
683
        dec     dword [esp]
676
        dec     dword [esp]
684
        jnz     @b
677
        jnz     @b
685
        dbgstr  'warning: taking EHCI ownership from BIOS timeout'
678
        dbgstr  'warning: taking EHCI ownership from BIOS timeout'
686
.force_ownership:
679
.force_ownership:
687
; 4f. BIOS has not responded within the timeout.
680
; 4f. BIOS has not responded within the timeout.
688
; Let's just clear BIOS ownership flag and hope that everything will be ok.
681
; Let's just clear BIOS ownership flag and hope that everything will be ok.
689
        mov     ah, [esi+PCIDEV.bus]
682
        mov     ah, [esi+PCIDEV.bus]
690
        mov     al, 0
683
        mov     al, 0
691
        mov     cl, 0
684
        mov     cl, 0
692
        call    pci_write_reg
685
        call    pci_write_reg
693
.has_ownership:
686
.has_ownership:
694
; 5. Just in case clear all SMI event sources except change-ownership.
687
; 5. Just in case clear all SMI event sources except change-ownership.
695
        dbgstr 'has_ownership'
688
        dbgstr 'has_ownership'
696
        inc     ebx
689
        inc     ebx
697
        inc     ebx
690
        inc     ebx
698
        mov     ah, [esi+PCIDEV.bus]
691
        mov     ah, [esi+PCIDEV.bus]
699
        mov     al, 2
692
        mov     al, 2
700
        mov     ecx, eax
693
        mov     ecx, eax
701
        call    pci_read_reg
694
        call    pci_read_reg
702
        and     ax, 2000h
695
        and     ax, 2000h
703
        xchg    eax, ecx
696
        xchg    eax, ecx
704
        call    pci_write_reg
697
        call    pci_write_reg
705
.has_ownership2:
698
.has_ownership2:
706
        pop     ecx
699
        pop     ecx
707
; 6. Disable all controller interrupts until the system will be ready to
700
; 6. Disable all controller interrupts until the system will be ready to
708
; process them.
701
; process them.
709
        mov     dword [edi+EhciInterruptReg], 0
702
        mov     dword [edi+EhciInterruptReg], 0
710
; 7. Now we can unblock interrupts in the processor.
703
; 7. Now we can unblock interrupts in the processor.
711
        popf
704
        popf
712
; 8. Release memory mapping created in step 2 and return.
705
; 8. Release memory mapping created in step 2 and return.
713
        call    free_kernel_space
706
        call    free_kernel_space
714
.nothing:
707
.nothing:
715
        ret
708
        ret
716
endp
709
endp
717
 
710
 
718
; IRQ handler for EHCI controllers.
711
; IRQ handler for EHCI controllers.
719
ehci_irq.noint:
712
ehci_irq.noint:
720
        spin_unlock_irqrestore [esi+usb_controller.WaitSpinlock]
713
        spin_unlock_irqrestore [esi+usb_controller.WaitSpinlock]
721
; Not our interrupt: restore registers and return zero.
714
; Not our interrupt: restore registers and return zero.
722
        xor     eax, eax
715
        xor     eax, eax
723
        pop     edi esi ebx
716
        pop     edi esi ebx
724
        ret
717
        ret
725
 
718
 
726
proc ehci_irq
719
proc ehci_irq
727
        push    ebx esi edi     ; save registers to be cdecl
720
        push    ebx esi edi     ; save registers to be cdecl
728
virtual at esp
721
virtual at esp
729
        rd      3       ; saved registers
722
        rd      3       ; saved registers
730
        dd      ?       ; return address
723
        dd      ?       ; return address
731
.controller     dd      ?
724
.controller     dd      ?
732
end virtual
725
end virtual
733
; 1. ebx will hold whether some deferred processing is needed,
726
; 1. ebx will hold whether some deferred processing is needed,
734
; that cannot be done from the interrupt handler. Initialize to zero.
727
; that cannot be done from the interrupt handler. Initialize to zero.
735
        xor     ebx, ebx
728
        xor     ebx, ebx
736
; 2. Get the mask of events which should be processed.
729
; 2. Get the mask of events which should be processed.
737
        mov     esi, [.controller]
730
        mov     esi, [.controller]
738
        mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
731
        mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
739
        spin_lock_irqsave [esi+usb_controller.WaitSpinlock]
732
        spin_lock_irqsave [esi+usb_controller.WaitSpinlock]
740
        mov     eax, [edi+EhciStatusReg]
733
        mov     eax, [edi+EhciStatusReg]
741
;       DEBUGF 1,'K : [%d] EHCI status %x\n',[timer_ticks],eax
734
;       DEBUGF 1,'K : [%d] EHCI status %x\n',[timer_ticks],eax
742
; 3. Check whether that interrupt has been generated by our controller.
735
; 3. Check whether that interrupt has been generated by our controller.
743
; (One IRQ can be shared by several devices.)
736
; (One IRQ can be shared by several devices.)
744
        and     eax, [edi+EhciInterruptReg]
737
        and     eax, [edi+EhciInterruptReg]
745
        jz      .noint
738
        jz      .noint
746
; 4. Clear the events we know of.
739
; 4. Clear the events we know of.
747
; Note that this should be done before processing of events:
740
; Note that this should be done before processing of events:
748
; new events could arise while we are processing those, this way we won't lose
741
; new events could arise while we are processing those, this way we won't lose
749
; them (the controller would generate another interrupt after completion
742
; them (the controller would generate another interrupt after completion
750
; of this one).
743
; of this one).
751
;       DEBUGF 1,'K : EHCI interrupt: status = %x\n',eax
744
;       DEBUGF 1,'K : EHCI interrupt: status = %x\n',eax
752
        mov     [edi+EhciStatusReg], eax
745
        mov     [edi+EhciStatusReg], eax
753
; 5. Sanity check.
746
; 5. Sanity check.
754
        test    al, 10h
747
        test    al, 10h
755
        jz      @f
748
        jz      @f
756
        DEBUGF 1,'K : something terrible happened with EHCI %x (%x)\n',esi,al
749
        DEBUGF 1,'K : something terrible happened with EHCI %x (%x)\n',esi,al
757
@@:
750
@@:
758
; We can't do too much from an interrupt handler. Inform the processing thread
751
; We can't do too much from an interrupt handler. Inform the processing thread
759
; that it should perform appropriate actions.
752
; that it should perform appropriate actions.
760
        or      [esi+ehci_controller.DeferredActions-sizeof.ehci_controller], eax
753
        or      [esi+ehci_controller.DeferredActions-sizeof.ehci_controller], eax
761
        spin_unlock_irqrestore [esi+usb_controller.WaitSpinlock]
754
        spin_unlock_irqrestore [esi+usb_controller.WaitSpinlock]
762
        inc     ebx
755
        inc     ebx
763
        call    usb_wakeup_if_needed
756
        call    usb_wakeup_if_needed
764
; 6. Interrupt processed; return non-zero.
757
; 6. Interrupt processed; return non-zero.
765
        mov     al, 1
758
        mov     al, 1
766
        pop     edi esi ebx     ; restore used registers to be cdecl
759
        pop     edi esi ebx     ; restore used registers to be cdecl
767
        ret
760
        ret
768
endp
761
endp
769
 
762
 
770
; This procedure is called from usb_set_address_callback
763
; This procedure is called from usb_set_address_callback
771
; and stores USB device address in the ehci_pipe structure.
764
; and stores USB device address in the ehci_pipe structure.
772
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
765
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
773
proc ehci_set_device_address
766
proc ehci_set_device_address
774
        mov     byte [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart], cl
767
        mov     byte [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart], cl
775
        call    usb_subscribe_control
768
        call    usb_subscribe_control
776
        ret
769
        ret
777
endp
770
endp
778
 
771
 
779
; This procedure returns USB device address from the ehci_pipe structure.
772
; This procedure returns USB device address from the ehci_pipe structure.
780
; in: esi -> usb_controller, ebx -> usb_pipe
773
; in: esi -> usb_controller, ebx -> usb_pipe
781
; out: eax = endpoint address
774
; out: eax = endpoint address
782
proc ehci_get_device_address
775
proc ehci_get_device_address
783
        mov     eax, [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
776
        mov     eax, [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
784
        and     eax, 7Fh
777
        and     eax, 7Fh
785
        ret
778
        ret
786
endp
779
endp
787
 
780
 
788
; This procedure is called from usb_set_address_callback
781
; This procedure is called from usb_set_address_callback
789
; if the device does not accept SET_ADDRESS command and needs
782
; if the device does not accept SET_ADDRESS command and needs
790
; to be disabled at the port level.
783
; to be disabled at the port level.
791
; in: esi -> usb_controller, ecx = port (zero-based)
784
; in: esi -> usb_controller, ecx = port (zero-based)
792
proc ehci_port_disable
785
proc ehci_port_disable
793
        mov     eax, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
786
        mov     eax, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
794
        and     dword [eax+EhciPortsReg+ecx*4], not (4 or 2Ah)
787
        and     dword [eax+EhciPortsReg+ecx*4], not (4 or 2Ah)
795
        ret
788
        ret
796
endp
789
endp
797
 
790
 
798
; This procedure is called from usb_get_descr8_callback when
791
; This procedure is called from usb_get_descr8_callback when
799
; the packet size for zero endpoint becomes known and
792
; the packet size for zero endpoint becomes known and
800
; stores the packet size in ehci_pipe structure.
793
; stores the packet size in ehci_pipe structure.
801
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size
794
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size
802
proc ehci_set_endpoint_packet_size
795
proc ehci_set_endpoint_packet_size
803
        mov     eax, [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
796
        mov     eax, [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
804
        and     eax, not (0x7FF shl 16)
797
        and     eax, not (0x7FF shl 16)
805
        shl     ecx, 16
798
        shl     ecx, 16
806
        or      eax, ecx
799
        or      eax, ecx
807
        mov     [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart], eax
800
        mov     [ebx+ehci_pipe.Token-ehci_pipe.SoftwarePart], eax
808
; Wait until hardware cache is evicted.
801
; Wait until hardware cache is evicted.
809
        call    usb_subscribe_control
802
        call    usb_subscribe_control
810
        ret
803
        ret
811
endp
804
endp
812
 
805
 
813
uglobal
806
uglobal
814
align 4
807
align 4
815
; Data for memory allocator, see memory.inc.
808
; Data for memory allocator, see memory.inc.
816
ehci_ep_first_page      dd      ?
809
ehci_ep_first_page      dd      ?
817
ehci_ep_mutex           MUTEX
810
ehci_ep_mutex           MUTEX
818
ehci_gtd_first_page     dd      ?
811
ehci_gtd_first_page     dd      ?
819
ehci_gtd_mutex          MUTEX
812
ehci_gtd_mutex          MUTEX
820
endg
813
endg
821
 
814
 
822
; This procedure allocates memory for pipe.
815
; This procedure allocates memory for pipe.
823
; Both hardware+software parts must be allocated, returns pointer to usb_pipe
816
; Both hardware+software parts must be allocated, returns pointer to usb_pipe
824
; (software part).
817
; (software part).
825
proc ehci_alloc_pipe
818
proc ehci_alloc_pipe
826
        push    ebx
819
        push    ebx
827
        mov     ebx, ehci_ep_mutex
820
        mov     ebx, ehci_ep_mutex
828
        stdcall usb_allocate_common, sizeof.ehci_pipe
821
        stdcall usb_allocate_common, sizeof.ehci_pipe
829
        test    eax, eax
822
        test    eax, eax
830
        jz      @f
823
        jz      @f
831
        add     eax, ehci_pipe.SoftwarePart
824
        add     eax, ehci_pipe.SoftwarePart
832
@@:
825
@@:
833
        pop     ebx
826
        pop     ebx
834
        ret
827
        ret
835
endp
828
endp
836
 
829
 
837
; This procedure frees memory for pipe allocated by ehci_alloc_pipe.
830
; This procedure frees memory for pipe allocated by ehci_alloc_pipe.
838
; void stdcall with one argument = pointer to usb_pipe.
831
; void stdcall with one argument = pointer to usb_pipe.
839
proc ehci_free_pipe
832
proc ehci_free_pipe
840
virtual at esp
833
virtual at esp
841
        dd      ?       ; return address
834
        dd      ?       ; return address
842
.ptr    dd      ?
835
.ptr    dd      ?
843
end virtual
836
end virtual
844
        sub     [.ptr], ehci_pipe.SoftwarePart
837
        sub     [.ptr], ehci_pipe.SoftwarePart
845
        jmp     usb_free_common
838
        jmp     usb_free_common
846
endp
839
endp
847
 
840
 
848
; This procedure is called from API usb_open_pipe and processes
841
; This procedure is called from API usb_open_pipe and processes
849
; the controller-specific part of this API. See docs.
842
; the controller-specific part of this API. See docs.
850
; in: edi -> usb_pipe for target, ecx -> usb_pipe for config pipe,
843
; in: edi -> usb_pipe for target, ecx -> usb_pipe for config pipe,
851
; esi -> usb_controller, eax -> usb_gtd for the first TD,
844
; esi -> usb_controller, eax -> usb_gtd for the first TD,
852
; [ebp+12] = endpoint, [ebp+16] = maxpacket, [ebp+20] = type
845
; [ebp+12] = endpoint, [ebp+16] = maxpacket, [ebp+20] = type
853
proc ehci_init_pipe
846
proc ehci_init_pipe
854
virtual at ebp+8
847
virtual at ebp+8
855
.config_pipe    dd      ?
848
.config_pipe    dd      ?
856
.endpoint       dd      ?
849
.endpoint       dd      ?
857
.maxpacket      dd      ?
850
.maxpacket      dd      ?
858
.type           dd      ?
851
.type           dd      ?
859
.interval       dd      ?
852
.interval       dd      ?
860
end virtual
853
end virtual
861
; 1. Zero all fields in the hardware part.
854
; 1. Zero all fields in the hardware part.
862
        push    eax ecx
855
        push    eax ecx
863
        sub     edi, ehci_pipe.SoftwarePart
856
        sub     edi, ehci_pipe.SoftwarePart
864
        xor     eax, eax
857
        xor     eax, eax
865
        push    ehci_pipe.SoftwarePart/4
858
        movi    ecx, ehci_pipe.SoftwarePart/4
866
        pop     ecx
-
 
867
        rep stosd
859
        rep stosd
868
        pop     ecx eax
860
        pop     ecx eax
869
; 2. Setup PID in the first TD and make sure that the it is not active.
861
; 2. Setup PID in the first TD and make sure that the it is not active.
870
        xor     edx, edx
862
        xor     edx, edx
871
        test    byte [.endpoint], 80h
863
        test    byte [.endpoint], 80h
872
        setnz   dh
864
        setnz   dh
873
        mov     [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], edx
865
        mov     [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], edx
874
        mov     [eax+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], 1
866
        mov     [eax+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], 1
875
        mov     [eax+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], 1
867
        mov     [eax+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], 1
876
; 3. Store physical address of the first TD.
868
; 3. Store physical address of the first TD.
877
        sub     eax, ehci_gtd.SoftwarePart
869
        sub     eax, ehci_gtd.SoftwarePart
878
        call    get_phys_addr
870
        call    get_phys_addr
879
        mov     [edi+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart], eax
871
        mov     [edi+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart], eax
880
; 4. Fill ehci_pipe.Flags except for S- and C-masks.
872
; 4. Fill ehci_pipe.Flags except for S- and C-masks.
881
; Copy location from the config pipe.
873
; Copy location from the config pipe.
882
        mov     eax, [ecx+ehci_pipe.Flags-ehci_pipe.SoftwarePart]
874
        mov     eax, [ecx+ehci_pipe.Flags-ehci_pipe.SoftwarePart]
883
        and     eax, 3FFF0000h
875
        and     eax, 3FFF0000h
884
; Use 1 requests per microframe for control/bulk endpoints,
876
; Use 1 requests per microframe for control/bulk endpoints,
885
; use value from the endpoint descriptor for periodic endpoints
877
; use value from the endpoint descriptor for periodic endpoints
886
        push    1
-
 
887
        pop     edx
878
        movi    edx, 1
888
        test    [.type], 1
879
        test    [.type], 1
889
        jz      @f
880
        jz      @f
890
        mov     edx, [.maxpacket]
881
        mov     edx, [.maxpacket]
891
        shr     edx, 11
882
        shr     edx, 11
892
        inc     edx
883
        inc     edx
893
@@:
884
@@:
894
        shl     edx, 30
885
        shl     edx, 30
895
        or      eax, edx
886
        or      eax, edx
896
        mov     [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart], eax
887
        mov     [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart], eax
897
; 5. Fill ehci_pipe.Token.
888
; 5. Fill ehci_pipe.Token.
898
        mov     eax, [ecx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
889
        mov     eax, [ecx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
899
; copy following fields from the config pipe:
890
; copy following fields from the config pipe:
900
; DeviceAddress, EndpointSpeed, ControlEndpoint if new type is control
891
; DeviceAddress, EndpointSpeed, ControlEndpoint if new type is control
901
        mov     ecx, eax
892
        mov     ecx, eax
902
        and     eax, 307Fh
893
        and     eax, 307Fh
903
        and     ecx, 8000000h
894
        and     ecx, 8000000h
904
        or      ecx, 4000h
895
        or      ecx, 4000h
905
        mov     edx, [.endpoint]
896
        mov     edx, [.endpoint]
906
        and     edx, 15
897
        and     edx, 15
907
        shl     edx, 8
898
        shl     edx, 8
908
        or      eax, edx
899
        or      eax, edx
909
        mov     edx, [.maxpacket]
900
        mov     edx, [.maxpacket]
910
        shl     edx, 16
901
        shl     edx, 16
911
        or      eax, edx
902
        or      eax, edx
912
; for control endpoints, use DataToggle from TD, otherwise use DataToggle from QH
903
; for control endpoints, use DataToggle from TD, otherwise use DataToggle from QH
913
        cmp     [.type], CONTROL_PIPE
904
        cmp     [.type], CONTROL_PIPE
914
        jnz     @f
905
        jnz     @f
915
        or      eax, ecx
906
        or      eax, ecx
916
@@:
907
@@:
917
; for control/bulk USB2 endpoints, set NakCountReload to 4
908
; for control/bulk USB2 endpoints, set NakCountReload to 4
918
        test    eax, USB_SPEED_HS shl 12
909
        test    eax, USB_SPEED_HS shl 12
919
        jz      .nonak
910
        jz      .nonak
920
        cmp     [.type], CONTROL_PIPE
911
        cmp     [.type], CONTROL_PIPE
921
        jz      @f
912
        jz      @f
922
        cmp     [.type], BULK_PIPE
913
        cmp     [.type], BULK_PIPE
923
        jnz     .nonak
914
        jnz     .nonak
924
@@:
915
@@:
925
        or      eax, 40000000h
916
        or      eax, 40000000h
926
.nonak:
917
.nonak:
927
        mov     [edi+ehci_pipe.Token-ehci_pipe.SoftwarePart], eax
918
        mov     [edi+ehci_pipe.Token-ehci_pipe.SoftwarePart], eax
928
; 5. Select the corresponding list and insert to the list.
919
; 5. Select the corresponding list and insert to the list.
929
; 5a. Use Control list for control pipes, Bulk list for bulk pipes.
920
; 5a. Use Control list for control pipes, Bulk list for bulk pipes.
930
        lea     edx, [esi+ehci_controller.ControlED.SoftwarePart-sizeof.ehci_controller]
921
        lea     edx, [esi+ehci_controller.ControlED.SoftwarePart-sizeof.ehci_controller]
931
        cmp     [.type], BULK_PIPE
922
        cmp     [.type], BULK_PIPE
932
        jb      .insert ; control pipe
923
        jb      .insert ; control pipe
933
        lea     edx, [esi+ehci_controller.BulkED.SoftwarePart-sizeof.ehci_controller]
924
        lea     edx, [esi+ehci_controller.BulkED.SoftwarePart-sizeof.ehci_controller]
934
        jz      .insert ; bulk pipe
925
        jz      .insert ; bulk pipe
935
.interrupt_pipe:
926
.interrupt_pipe:
936
; 5b. For interrupt pipes, let the scheduler select the appropriate list
927
; 5b. For interrupt pipes, let the scheduler select the appropriate list
937
; and the appropriate microframe(s) (which goes to S-mask and C-mask)
928
; and the appropriate microframe(s) (which goes to S-mask and C-mask)
938
; based on the current bandwidth distribution and the requested bandwidth.
929
; based on the current bandwidth distribution and the requested bandwidth.
939
; There are two schedulers, one for high-speed devices,
930
; There are two schedulers, one for high-speed devices,
940
; another for split transactions.
931
; another for split transactions.
941
; This could fail if the requested bandwidth is not available;
932
; This could fail if the requested bandwidth is not available;
942
; if so, return an error.
933
; if so, return an error.
943
        test    word [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart+2], 3FFFh
934
        test    word [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart+2], 3FFFh
944
        jnz     .interrupt_fs
935
        jnz     .interrupt_fs
945
        call    ehci_select_hs_interrupt_list
936
        call    ehci_select_hs_interrupt_list
946
        jmp     .interrupt_common
937
        jmp     .interrupt_common
947
.interrupt_fs:
938
.interrupt_fs:
948
        call    ehci_select_fs_interrupt_list
939
        call    ehci_select_fs_interrupt_list
949
.interrupt_common:
940
.interrupt_common:
950
        test    edx, edx
941
        test    edx, edx
951
        jz      .return0
942
        jz      .return0
952
        mov     word [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart], ax
943
        mov     word [edi+ehci_pipe.Flags-ehci_pipe.SoftwarePart], ax
953
.insert:
944
.insert:
954
        mov     [edi+ehci_pipe.BaseList-ehci_pipe.SoftwarePart], edx
945
        mov     [edi+ehci_pipe.BaseList-ehci_pipe.SoftwarePart], edx
955
; Insert to the head of the corresponding list.
946
; Insert to the head of the corresponding list.
956
; Note: inserting to the head guarantees that the list traverse in
947
; Note: inserting to the head guarantees that the list traverse in
957
; ehci_process_updated_schedule, once started, will not interact with new pipes.
948
; ehci_process_updated_schedule, once started, will not interact with new pipes.
958
; However, we still need to ensure that links in the new pipe (edi.NextVirt)
949
; However, we still need to ensure that links in the new pipe (edi.NextVirt)
959
; are initialized before links to the new pipe (edx.NextVirt).
950
; are initialized before links to the new pipe (edx.NextVirt).
960
; 5c. Insert in the list of virtual addresses.
951
; 5c. Insert in the list of virtual addresses.
961
        mov     ecx, [edx+usb_pipe.NextVirt]
952
        mov     ecx, [edx+usb_pipe.NextVirt]
962
        mov     [edi+usb_pipe.NextVirt], ecx
953
        mov     [edi+usb_pipe.NextVirt], ecx
963
        mov     [edi+usb_pipe.PrevVirt], edx
954
        mov     [edi+usb_pipe.PrevVirt], edx
964
        mov     [ecx+usb_pipe.PrevVirt], edi
955
        mov     [ecx+usb_pipe.PrevVirt], edi
965
        mov     [edx+usb_pipe.NextVirt], edi
956
        mov     [edx+usb_pipe.NextVirt], edi
966
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
957
; 5d. Insert in the hardware list: copy previous NextQH to the new pipe,
967
; store the physical address of the new pipe to previous NextQH.
958
; store the physical address of the new pipe to previous NextQH.
968
        mov     ecx, [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart]
959
        mov     ecx, [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart]
969
        mov     [edi+ehci_pipe.NextQH-ehci_pipe.SoftwarePart], ecx
960
        mov     [edi+ehci_pipe.NextQH-ehci_pipe.SoftwarePart], ecx
970
        lea     eax, [edi-ehci_pipe.SoftwarePart]
961
        lea     eax, [edi-ehci_pipe.SoftwarePart]
971
        call    get_phys_addr
962
        call    get_phys_addr
972
        inc     eax
963
        inc     eax
973
        inc     eax
964
        inc     eax
974
        mov     [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], eax
965
        mov     [edx+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], eax
975
; 6. Return with nonzero eax.
966
; 6. Return with nonzero eax.
976
        ret
967
        ret
977
.return0:
968
.return0:
978
        xor     eax, eax
969
        xor     eax, eax
979
        ret
970
        ret
980
endp
971
endp
981
 
972
 
982
; This function is called from ehci_process_deferred when
973
; This function is called from ehci_process_deferred when
983
; a new device was connected at least USB_CONNECT_DELAY ticks
974
; a new device was connected at least USB_CONNECT_DELAY ticks
984
; and therefore is ready to be configured.
975
; and therefore is ready to be configured.
985
; ecx = port, esi -> ehci_controller, edi -> EHCI MMIO
976
; ecx = port, esi -> ehci_controller, edi -> EHCI MMIO
986
proc ehci_new_port
977
proc ehci_new_port
987
; 1. If the device operates at low-speed, just release it to a companion.
978
; 1. If the device operates at low-speed, just release it to a companion.
988
        mov     eax, [edi+EhciPortsReg+ecx*4]
979
        mov     eax, [edi+EhciPortsReg+ecx*4]
989
        DEBUGF 1,'K : [%d] EHCI %x port %d state is %x\n',[timer_ticks],esi,ecx,eax
980
        DEBUGF 1,'K : [%d] EHCI %x port %d state is %x\n',[timer_ticks],esi,ecx,eax
990
        mov     edx, eax
981
        mov     edx, eax
991
        and     ah, 0Ch
982
        and     ah, 0Ch
992
        cmp     ah, 4
983
        cmp     ah, 4
993
        jz      .low_speed
984
        jz      .low_speed
994
; 2. Devices operating at full-speed and high-speed must now have ah == 8.
985
; 2. Devices operating at full-speed and high-speed must now have ah == 8.
995
; Some broken hardware asserts both D+ and D- even after initial decoupling;
986
; Some broken hardware asserts both D+ and D- even after initial decoupling;
996
; if so, stop initialization here, no sense in further actions.
987
; if so, stop initialization here, no sense in further actions.
997
        cmp     ah, 0Ch
988
        cmp     ah, 0Ch
998
        jz      .se1
989
        jz      .se1
999
; 3. If another port is resetting right now, mark this port as 'reset pending'
990
; 3. If another port is resetting right now, mark this port as 'reset pending'
1000
; and return.
991
; and return.
1001
        bts     [esi+usb_controller.PendingPorts], ecx
992
        bts     [esi+usb_controller.PendingPorts], ecx
1002
        cmp     [esi+usb_controller.ResettingPort], -1
993
        cmp     [esi+usb_controller.ResettingPort], -1
1003
        jnz     .nothing
994
        jnz     .nothing
1004
        btr     [esi+usb_controller.PendingPorts], ecx
995
        btr     [esi+usb_controller.PendingPorts], ecx
1005
; Otherwise, fall through to ohci_new_port.reset.
996
; Otherwise, fall through to ohci_new_port.reset.
1006
 
997
 
1007
; This function is called from ehci_new_port and usb_test_pending_port.
998
; This function is called from ehci_new_port and usb_test_pending_port.
1008
; It starts reset signalling for the port. Note that in USB first stages
999
; It starts reset signalling for the port. Note that in USB first stages
1009
; of configuration can not be done for several ports in parallel.
1000
; of configuration can not be done for several ports in parallel.
1010
.reset:
1001
.reset:
1011
        push    edi
1002
        push    edi
1012
        mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
1003
        mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
1013
        mov     eax, [edi+EhciPortsReg+ecx*4]
1004
        mov     eax, [edi+EhciPortsReg+ecx*4]
1014
; 1. Store information about resetting hub (roothub) and port.
1005
; 1. Store information about resetting hub (roothub) and port.
1015
        and     [esi+usb_controller.ResettingHub], 0
1006
        and     [esi+usb_controller.ResettingHub], 0
1016
        mov     [esi+usb_controller.ResettingPort], cl
1007
        mov     [esi+usb_controller.ResettingPort], cl
1017
; 2. Initiate reset signalling.
1008
; 2. Initiate reset signalling.
1018
        or      ah, 1
1009
        or      ah, 1
1019
        and     al, not (4 or 2Ah)
1010
        and     al, not (4 or 2Ah)
1020
        mov     [edi+EhciPortsReg+ecx*4], eax
1011
        mov     [edi+EhciPortsReg+ecx*4], eax
1021
; 3. Store the current time and set status to 1 = reset signalling active.
1012
; 3. Store the current time and set status to 1 = reset signalling active.
1022
        mov     eax, [timer_ticks]
1013
        mov     eax, [timer_ticks]
1023
        mov     [esi+usb_controller.ResetTime], eax
1014
        mov     [esi+usb_controller.ResetTime], eax
1024
        mov     [esi+usb_controller.ResettingStatus], 1
1015
        mov     [esi+usb_controller.ResettingStatus], 1
1025
;       dbgstr 'high-speed or full-speed device, resetting'
1016
;       dbgstr 'high-speed or full-speed device, resetting'
1026
        DEBUGF 1,'K : [%d] EHCI %x: port %d has HS or FS device, resetting\n',[timer_ticks],esi,ecx
1017
        DEBUGF 1,'K : [%d] EHCI %x: port %d has HS or FS device, resetting\n',[timer_ticks],esi,ecx
1027
        pop     edi
1018
        pop     edi
1028
.nothing:
1019
.nothing:
1029
        ret
1020
        ret
1030
.low_speed:
1021
.low_speed:
1031
;       dbgstr 'low-speed device, releasing'
1022
;       dbgstr 'low-speed device, releasing'
1032
        DEBUGF 1,'K : [%d] EHCI %x: port %d has LS device, releasing\n',[timer_ticks],esi,ecx
1023
        DEBUGF 1,'K : [%d] EHCI %x: port %d has LS device, releasing\n',[timer_ticks],esi,ecx
1033
        or      dh, 20h
1024
        or      dh, 20h
1034
        and     dl, not 2Ah
1025
        and     dl, not 2Ah
1035
        mov     [edi+EhciPortsReg+ecx*4], edx
1026
        mov     [edi+EhciPortsReg+ecx*4], edx
1036
        ret
1027
        ret
1037
.se1:
1028
.se1:
1038
        dbgstr 'SE1 after connect debounce. Broken hardware?'
1029
        dbgstr 'SE1 after connect debounce. Broken hardware?'
1039
        ret
1030
        ret
1040
endp
1031
endp
1041
 
1032
 
1042
; This procedure is called from several places in main USB code
1033
; This procedure is called from several places in main USB code
1043
; and allocates required packets for the given transfer.
1034
; and allocates required packets for the given transfer.
1044
; ebx = pipe, other parameters are passed through the stack:
1035
; ebx = pipe, other parameters are passed through the stack:
1045
; buffer,size = data to transfer
1036
; buffer,size = data to transfer
1046
; flags = same as in usb_open_pipe: bit 0 = allow short transfer, other bits reserved
1037
; flags = same as in usb_open_pipe: bit 0 = allow short transfer, other bits reserved
1047
; td = pointer to the current end-of-queue descriptor
1038
; td = pointer to the current end-of-queue descriptor
1048
; direction =
1039
; direction =
1049
;   0000b for normal transfers,
1040
;   0000b for normal transfers,
1050
;   1000b for control SETUP transfer,
1041
;   1000b for control SETUP transfer,
1051
;   1101b for control OUT transfer,
1042
;   1101b for control OUT transfer,
1052
;   1110b for control IN transfer
1043
;   1110b for control IN transfer
1053
; returns eax = pointer to the new end-of-queue descriptor
1044
; returns eax = pointer to the new end-of-queue descriptor
1054
; (not included in the queue itself) or 0 on error
1045
; (not included in the queue itself) or 0 on error
1055
proc ehci_alloc_transfer stdcall uses edi, \
1046
proc ehci_alloc_transfer stdcall uses edi, \
1056
        buffer:dword, size:dword, flags:dword, td:dword, direction:dword
1047
        buffer:dword, size:dword, flags:dword, td:dword, direction:dword
1057
locals
1048
locals
1058
origTD          dd      ?
1049
origTD          dd      ?
1059
packetSize      dd      ?       ; must be last variable, see usb_init_transfer
1050
packetSize      dd      ?       ; must be last variable, see usb_init_transfer
1060
endl
1051
endl
1061
; 1. Save original value of td:
1052
; 1. Save original value of td:
1062
; it will be useful for rollback if something would fail.
1053
; it will be useful for rollback if something would fail.
1063
        mov     eax, [td]
1054
        mov     eax, [td]
1064
        mov     [origTD], eax
1055
        mov     [origTD], eax
1065
; One transfer descriptor can describe up to 5 pages.
1056
; One transfer descriptor can describe up to 5 pages.
1066
; In the worst case (when the buffer is something*1000h+0FFFh)
1057
; In the worst case (when the buffer is something*1000h+0FFFh)
1067
; this corresponds to 4001h bytes. If the requested size is
1058
; this corresponds to 4001h bytes. If the requested size is
1068
; greater, we should split the transfer into several descriptors.
1059
; greater, we should split the transfer into several descriptors.
1069
; Boundaries to split must be multiples of endpoint transfer size
1060
; Boundaries to split must be multiples of endpoint transfer size
1070
; to avoid short packets except in the end of the transfer,
1061
; to avoid short packets except in the end of the transfer,
1071
; 4000h is always a good value.
1062
; 4000h is always a good value.
1072
; 2. While the remaining data cannot fit in one descriptor,
1063
; 2. While the remaining data cannot fit in one descriptor,
1073
; allocate full descriptors (of maximal possible size).
1064
; allocate full descriptors (of maximal possible size).
1074
        mov     edi, 4000h
1065
        mov     edi, 4000h
1075
        mov     [packetSize], edi
1066
        mov     [packetSize], edi
1076
.fullpackets:
1067
.fullpackets:
1077
        cmp     [size], edi
1068
        cmp     [size], edi
1078
        jbe     .lastpacket
1069
        jbe     .lastpacket
1079
        call    ehci_alloc_packet
1070
        call    ehci_alloc_packet
1080
        test    eax, eax
1071
        test    eax, eax
1081
        jz      .fail
1072
        jz      .fail
1082
        mov     [td], eax
1073
        mov     [td], eax
1083
        add     [buffer], edi
1074
        add     [buffer], edi
1084
        sub     [size], edi
1075
        sub     [size], edi
1085
        jmp     .fullpackets
1076
        jmp     .fullpackets
1086
; 3. The remaining data can fit in one packet;
1077
; 3. The remaining data can fit in one packet;
1087
; allocate the last descriptor with size = size of remaining data.
1078
; allocate the last descriptor with size = size of remaining data.
1088
.lastpacket:
1079
.lastpacket:
1089
        mov     eax, [size]
1080
        mov     eax, [size]
1090
        mov     [packetSize], eax
1081
        mov     [packetSize], eax
1091
        call    ehci_alloc_packet
1082
        call    ehci_alloc_packet
1092
        test    eax, eax
1083
        test    eax, eax
1093
        jz      .fail
1084
        jz      .fail
1094
; 9. Update flags in the last packet.
1085
; 9. Update flags in the last packet.
1095
        mov     edx, [flags]
1086
        mov     edx, [flags]
1096
        mov     [ecx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], edx
1087
        mov     [ecx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], edx
1097
; 10. Fill AlternateNextTD field in all allocated TDs.
1088
; 10. Fill AlternateNextTD field in all allocated TDs.
1098
; If the caller says that short transfer is ok, the queue must advance to
1089
; If the caller says that short transfer is ok, the queue must advance to
1099
; the next descriptor, which is in eax.
1090
; the next descriptor, which is in eax.
1100
; Otherwise, the queue should stop, so make AlternateNextTD point to
1091
; Otherwise, the queue should stop, so make AlternateNextTD point to
1101
; always-inactive descriptor StopQueueTD.
1092
; always-inactive descriptor StopQueueTD.
1102
        push    eax
1093
        push    eax
1103
        test    dl, 1
1094
        test    dl, 1
1104
        jz      .disable_short
1095
        jz      .disable_short
1105
        sub     eax, ehci_gtd.SoftwarePart
1096
        sub     eax, ehci_gtd.SoftwarePart
1106
        jmp     @f
1097
        jmp     @f
1107
.disable_short:
1098
.disable_short:
1108
        mov     eax, [ebx+usb_pipe.Controller]
1099
        mov     eax, [ebx+usb_pipe.Controller]
1109
        add     eax, ehci_controller.StopQueueTD - sizeof.ehci_controller
1100
        add     eax, ehci_controller.StopQueueTD - sizeof.ehci_controller
1110
@@:
1101
@@:
1111
        call    get_phys_addr
1102
        call    get_phys_addr
1112
        mov     edx, [origTD]
1103
        mov     edx, [origTD]
1113
@@:
1104
@@:
1114
        cmp     edx, [esp]
1105
        cmp     edx, [esp]
1115
        jz      @f
1106
        jz      @f
1116
        mov     [edx+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], eax
1107
        mov     [edx+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], eax
1117
        mov     edx, [edx+usb_gtd.NextVirt]
1108
        mov     edx, [edx+usb_gtd.NextVirt]
1118
        jmp     @b
1109
        jmp     @b
1119
@@:
1110
@@:
1120
        pop     eax
1111
        pop     eax
1121
        ret
1112
        ret
1122
.fail:
1113
.fail:
1123
        mov     edi, ehci_hardware_func
1114
        mov     edi, ehci_hardware_func
1124
        mov     eax, [td]
1115
        mov     eax, [td]
1125
        stdcall usb_undo_tds, [origTD]
1116
        stdcall usb_undo_tds, [origTD]
1126
        xor     eax, eax
1117
        xor     eax, eax
1127
        ret
1118
        ret
1128
endp
1119
endp
1129
 
1120
 
1130
; Helper procedure for ehci_alloc_transfer.
1121
; Helper procedure for ehci_alloc_transfer.
1131
; Allocates and initializes one transfer descriptor.
1122
; Allocates and initializes one transfer descriptor.
1132
; ebx = pipe, other parameters are passed through the stack;
1123
; ebx = pipe, other parameters are passed through the stack;
1133
; fills the current last descriptor and
1124
; fills the current last descriptor and
1134
; returns eax = next descriptor (not filled).
1125
; returns eax = next descriptor (not filled).
1135
proc ehci_alloc_packet
1126
proc ehci_alloc_packet
1136
; inherit some variables from the parent ehci_alloc_transfer
1127
; inherit some variables from the parent ehci_alloc_transfer
1137
virtual at ebp-8
1128
virtual at ebp-8
1138
.origTD         dd      ?
1129
.origTD         dd      ?
1139
.packetSize     dd      ?
1130
.packetSize     dd      ?
1140
                rd      2
1131
                rd      2
1141
.buffer         dd      ?
1132
.buffer         dd      ?
1142
.transferSize   dd      ?
1133
.transferSize   dd      ?
1143
.Flags          dd      ?
1134
.Flags          dd      ?
1144
.td             dd      ?
1135
.td             dd      ?
1145
.direction      dd      ?
1136
.direction      dd      ?
1146
end virtual
1137
end virtual
1147
; 1. Allocate the next TD.
1138
; 1. Allocate the next TD.
1148
        call    ehci_alloc_td
1139
        call    ehci_alloc_td
1149
        test    eax, eax
1140
        test    eax, eax
1150
        jz      .nothing
1141
        jz      .nothing
1151
; 2. Initialize controller-independent parts of both TDs.
1142
; 2. Initialize controller-independent parts of both TDs.
1152
        push    eax
1143
        push    eax
1153
        call    usb_init_transfer
1144
        call    usb_init_transfer
1154
        pop     eax
1145
        pop     eax
1155
; 3. Copy PID to the new descriptor.
1146
; 3. Copy PID to the new descriptor.
1156
        mov     edx, [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart]
1147
        mov     edx, [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart]
1157
        mov     [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], edx
1148
        mov     [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], edx
1158
        mov     [eax+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], 1
1149
        mov     [eax+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], 1
1159
        mov     [eax+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], 1
1150
        mov     [eax+ehci_gtd.AlternateNextTD-ehci_gtd.SoftwarePart], 1
1160
; 4. Save the returned value (next descriptor).
1151
; 4. Save the returned value (next descriptor).
1161
        push    eax
1152
        push    eax
1162
; 5. Store the physical address of the next descriptor.
1153
; 5. Store the physical address of the next descriptor.
1163
        sub     eax, ehci_gtd.SoftwarePart
1154
        sub     eax, ehci_gtd.SoftwarePart
1164
        call    get_phys_addr
1155
        call    get_phys_addr
1165
        mov     [ecx+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], eax
1156
        mov     [ecx+ehci_gtd.NextTD-ehci_gtd.SoftwarePart], eax
1166
; 6. For zero-length transfers, store zero in all fields for buffer addresses.
1157
; 6. For zero-length transfers, store zero in all fields for buffer addresses.
1167
; Otherwise, fill them with real values.
1158
; Otherwise, fill them with real values.
1168
        xor     eax, eax
1159
        xor     eax, eax
1169
        mov     [ecx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], eax
1160
        mov     [ecx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], eax
1170
repeat 10
1161
repeat 10
1171
        mov     [ecx+ehci_gtd.BufferPointers-ehci_gtd.SoftwarePart+(%-1)*4], eax
1162
        mov     [ecx+ehci_gtd.BufferPointers-ehci_gtd.SoftwarePart+(%-1)*4], eax
1172
end repeat
1163
end repeat
1173
        cmp     [.packetSize], eax
1164
        cmp     [.packetSize], eax
1174
        jz      @f
1165
        jz      @f
1175
        mov     eax, [.buffer]
1166
        mov     eax, [.buffer]
1176
        call    get_phys_addr
1167
        call    get_phys_addr
1177
        mov     [ecx+ehci_gtd.BufferPointers-ehci_gtd.SoftwarePart], eax
1168
        mov     [ecx+ehci_gtd.BufferPointers-ehci_gtd.SoftwarePart], eax
1178
        and     eax, 0xFFF
1169
        and     eax, 0xFFF
1179
        mov     edx, [.packetSize]
1170
        mov     edx, [.packetSize]
1180
        add     edx, eax
1171
        add     edx, eax
1181
        sub     edx, 0x1000
1172
        sub     edx, 0x1000
1182
        jbe     @f
1173
        jbe     @f
1183
        mov     eax, [.buffer]
1174
        mov     eax, [.buffer]
1184
        add     eax, 0x1000
1175
        add     eax, 0x1000
1185
        call    get_pg_addr
1176
        call    get_pg_addr
1186
        mov     [ecx+ehci_gtd.BufferPointers+4-ehci_gtd.SoftwarePart], eax
1177
        mov     [ecx+ehci_gtd.BufferPointers+4-ehci_gtd.SoftwarePart], eax
1187
        sub     edx, 0x1000
1178
        sub     edx, 0x1000
1188
        jbe     @f
1179
        jbe     @f
1189
        mov     eax, [.buffer]
1180
        mov     eax, [.buffer]
1190
        add     eax, 0x2000
1181
        add     eax, 0x2000
1191
        call    get_pg_addr
1182
        call    get_pg_addr
1192
        mov     [ecx+ehci_gtd.BufferPointers+8-ehci_gtd.SoftwarePart], eax
1183
        mov     [ecx+ehci_gtd.BufferPointers+8-ehci_gtd.SoftwarePart], eax
1193
        sub     edx, 0x1000
1184
        sub     edx, 0x1000
1194
        jbe     @f
1185
        jbe     @f
1195
        mov     eax, [.buffer]
1186
        mov     eax, [.buffer]
1196
        add     eax, 0x3000
1187
        add     eax, 0x3000
1197
        call    get_pg_addr
1188
        call    get_pg_addr
1198
        mov     [ecx+ehci_gtd.BufferPointers+12-ehci_gtd.SoftwarePart], eax
1189
        mov     [ecx+ehci_gtd.BufferPointers+12-ehci_gtd.SoftwarePart], eax
1199
        sub     edx, 0x1000
1190
        sub     edx, 0x1000
1200
        jbe     @f
1191
        jbe     @f
1201
        mov     eax, [.buffer]
1192
        mov     eax, [.buffer]
1202
        add     eax, 0x4000
1193
        add     eax, 0x4000
1203
        call    get_pg_addr
1194
        call    get_pg_addr
1204
        mov     [ecx+ehci_gtd.BufferPointers+16-ehci_gtd.SoftwarePart], eax
1195
        mov     [ecx+ehci_gtd.BufferPointers+16-ehci_gtd.SoftwarePart], eax
1205
@@:
1196
@@:
1206
; 7. Fill Token field:
1197
; 7. Fill Token field:
1207
; set Status = 0 (inactive, ehci_insert_transfer would mark everything active);
1198
; set Status = 0 (inactive, ehci_insert_transfer would mark everything active);
1208
; keep current PID if [.direction] is zero, use two lower bits of [.direction]
1199
; keep current PID if [.direction] is zero, use two lower bits of [.direction]
1209
; otherwise shifted as (0|1|2) -> (2|0|1);
1200
; otherwise shifted as (0|1|2) -> (2|0|1);
1210
; set error counter to 3;
1201
; set error counter to 3;
1211
; set current page to 0;
1202
; set current page to 0;
1212
; do not interrupt on complete (ehci_insert_transfer sets this bit where needed);
1203
; do not interrupt on complete (ehci_insert_transfer sets this bit where needed);
1213
; set DataToggle to bit 2 of [.direction].
1204
; set DataToggle to bit 2 of [.direction].
1214
        mov     eax, [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart]
1205
        mov     eax, [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart]
1215
        and     eax, 300h       ; keep PID code
1206
        and     eax, 300h       ; keep PID code
1216
        mov     edx, [.direction]
1207
        mov     edx, [.direction]
1217
        test    edx, edx
1208
        test    edx, edx
1218
        jz      .haspid
1209
        jz      .haspid
1219
        and     edx, 3
1210
        and     edx, 3
1220
        dec     edx
1211
        dec     edx
1221
        jns     @f
1212
        jns     @f
1222
        add     edx, 3
1213
        add     edx, 3
1223
@@:
1214
@@:
1224
        mov     ah, dl
1215
        mov     ah, dl
1225
        mov     edx, [.direction]
1216
        mov     edx, [.direction]
1226
        and     edx, not 3
1217
        and     edx, not 3
1227
        shl     edx, 29
1218
        shl     edx, 29
1228
        or      eax, edx
1219
        or      eax, edx
1229
.haspid:
1220
.haspid:
1230
        or      eax, 0C00h
1221
        or      eax, 0C00h
1231
        mov     edx, [.packetSize]
1222
        mov     edx, [.packetSize]
1232
        shl     edx, 16
1223
        shl     edx, 16
1233
        or      eax, edx
1224
        or      eax, edx
1234
        mov     [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart], eax
1225
        mov     [ecx+ehci_gtd.Token-ehci_gtd.SoftwarePart], eax
1235
; 4. Restore the returned value saved in step 2.
1226
; 4. Restore the returned value saved in step 2.
1236
        pop     eax
1227
        pop     eax
1237
.nothing:
1228
.nothing:
1238
        ret
1229
        ret
1239
endp
1230
endp
1240
 
1231
 
1241
; This procedure is called from several places in main USB code
1232
; This procedure is called from several places in main USB code
1242
; and activates the transfer which was previously allocated by
1233
; and activates the transfer which was previously allocated by
1243
; ehci_alloc_transfer.
1234
; ehci_alloc_transfer.
1244
; ecx -> last descriptor for the transfer, ebx -> usb_pipe
1235
; ecx -> last descriptor for the transfer, ebx -> usb_pipe
1245
proc ehci_insert_transfer
1236
proc ehci_insert_transfer
1246
        or      byte [ecx+ehci_gtd.Token+1-ehci_gtd.SoftwarePart], 80h  ; set IOC bit
1237
        or      byte [ecx+ehci_gtd.Token+1-ehci_gtd.SoftwarePart], 80h  ; set IOC bit
1247
        mov     eax, [esp+4]
1238
        mov     eax, [esp+4]
1248
.activate:
1239
.activate:
1249
        or      byte [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], 80h    ; set Active bit
1240
        or      byte [eax+ehci_gtd.Token-ehci_gtd.SoftwarePart], 80h    ; set Active bit
1250
        cmp     eax, ecx
1241
        cmp     eax, ecx
1251
        mov     eax, [eax+usb_gtd.NextVirt]
1242
        mov     eax, [eax+usb_gtd.NextVirt]
1252
        jnz     .activate
1243
        jnz     .activate
1253
        ret
1244
        ret
1254
endp
1245
endp
1255
 
1246
 
1256
; This function is called from ehci_process_deferred when
1247
; This function is called from ehci_process_deferred when
1257
; reset signalling for a new device needs to be finished.
1248
; reset signalling for a new device needs to be finished.
1258
proc ehci_port_reset_done
1249
proc ehci_port_reset_done
1259
        movzx   ecx, [esi+usb_controller.ResettingPort]
1250
        movzx   ecx, [esi+usb_controller.ResettingPort]
1260
        and     dword [edi+EhciPortsReg+ecx*4], not 12Ah
1251
        and     dword [edi+EhciPortsReg+ecx*4], not 12Ah
1261
        mov     eax, [timer_ticks]
1252
        mov     eax, [timer_ticks]
1262
        mov     [esi+usb_controller.ResetTime], eax
1253
        mov     [esi+usb_controller.ResetTime], eax
1263
        mov     [esi+usb_controller.ResettingStatus], 2
1254
        mov     [esi+usb_controller.ResettingStatus], 2
1264
        DEBUGF 1,'K : [%d] EHCI %x: reset port %d done\n',[timer_ticks],esi,ecx
1255
        DEBUGF 1,'K : [%d] EHCI %x: reset port %d done\n',[timer_ticks],esi,ecx
1265
        ret
1256
        ret
1266
endp
1257
endp
1267
 
1258
 
1268
; This function is called from ehci_process_deferred when
1259
; This function is called from ehci_process_deferred when
1269
; a new device has been reset, recovered after reset and needs to be configured.
1260
; a new device has been reset, recovered after reset and needs to be configured.
1270
proc ehci_port_init
1261
proc ehci_port_init
1271
; 1. Get the status and set it to zero.
1262
; 1. Get the status and set it to zero.
1272
; If reset has been failed (device disconnected during reset),
1263
; If reset has been failed (device disconnected during reset),
1273
; continue to next device (if there is one).
1264
; continue to next device (if there is one).
1274
        xor     eax, eax
1265
        xor     eax, eax
1275
        xchg    al, [esi+usb_controller.ResettingStatus]
1266
        xchg    al, [esi+usb_controller.ResettingStatus]
1276
        test    al, al
1267
        test    al, al
1277
        js      usb_test_pending_port
1268
        js      usb_test_pending_port
1278
; 2. Get the port status. High-speed devices should be now enabled,
1269
; 2. Get the port status. High-speed devices should be now enabled,
1279
; full-speed devices are left disabled;
1270
; full-speed devices are left disabled;
1280
; if the port is disabled, release it to a companion and continue to
1271
; if the port is disabled, release it to a companion and continue to
1281
; next device (if there is one).
1272
; next device (if there is one).
1282
        movzx   ecx, [esi+usb_controller.ResettingPort]
1273
        movzx   ecx, [esi+usb_controller.ResettingPort]
1283
        mov     eax, [edi+EhciPortsReg+ecx*4]
1274
        mov     eax, [edi+EhciPortsReg+ecx*4]
1284
        DEBUGF 1,'K : [%d] EHCI %x status of port %d is %x\n',[timer_ticks],esi,ecx,eax
1275
        DEBUGF 1,'K : [%d] EHCI %x status of port %d is %x\n',[timer_ticks],esi,ecx,eax
1285
        test    al, 4
1276
        test    al, 4
1286
        jnz     @f
1277
        jnz     @f
1287
;       DEBUGF 1,'K : USB port disabled after reset, status = %x\n',eax
1278
;       DEBUGF 1,'K : USB port disabled after reset, status = %x\n',eax
1288
        dbgstr 'releasing to companion'
1279
        dbgstr 'releasing to companion'
1289
        or      ah, 20h
1280
        or      ah, 20h
1290
        mov     [edi+EhciPortsReg+ecx*4], eax
1281
        mov     [edi+EhciPortsReg+ecx*4], eax
1291
        jmp     usb_test_pending_port
1282
        jmp     usb_test_pending_port
1292
@@:
1283
@@:
1293
; 3. Call the worker procedure to notify the protocol layer
1284
; 3. Call the worker procedure to notify the protocol layer
1294
; about new EHCI device. It is high-speed.
1285
; about new EHCI device. It is high-speed.
1295
        push    USB_SPEED_HS
1286
        movi    eax, USB_SPEED_HS
1296
        pop     eax
-
 
1297
        call    ehci_new_device
1287
        call    ehci_new_device
1298
        test    eax, eax
1288
        test    eax, eax
1299
        jnz     .nothing
1289
        jnz     .nothing
1300
; 4. If something at the protocol layer has failed
1290
; 4. If something at the protocol layer has failed
1301
; (no memory, no bus address), disable the port and stop the initialization.
1291
; (no memory, no bus address), disable the port and stop the initialization.
1302
.disable_exit:
1292
.disable_exit:
1303
        and     dword [edi+EhciPortsReg+ecx*4], not (4 or 2Ah)
1293
        and     dword [edi+EhciPortsReg+ecx*4], not (4 or 2Ah)
1304
        jmp     usb_test_pending_port
1294
        jmp     usb_test_pending_port
1305
.nothing:
1295
.nothing:
1306
        ret
1296
        ret
1307
endp
1297
endp
1308
 
1298
 
1309
; This procedure is called from ehci_port_init and from hub support code
1299
; This procedure is called from ehci_port_init and from hub support code
1310
; when a new device is connected and has been reset.
1300
; when a new device is connected and has been reset.
1311
; It calls usb_new_device at the protocol layer with correct parameters.
1301
; It calls usb_new_device at the protocol layer with correct parameters.
1312
; in: esi -> usb_controller, eax = speed.
1302
; in: esi -> usb_controller, eax = speed.
1313
proc ehci_new_device
1303
proc ehci_new_device
1314
        push    ebx ecx ; save used registers (ecx is important for ehci_port_init)
1304
        push    ebx ecx ; save used registers (ecx is important for ehci_port_init)
1315
; 1. Store the speed for the protocol layer.
1305
; 1. Store the speed for the protocol layer.
1316
        mov     [esi+usb_controller.ResettingSpeed], al
1306
        mov     [esi+usb_controller.ResettingSpeed], al
1317
; 2. Shift speed bits to the proper place in ehci_pipe.Token.
1307
; 2. Shift speed bits to the proper place in ehci_pipe.Token.
1318
        shl     eax, 12
1308
        shl     eax, 12
1319
; 3. For high-speed devices, go to step 5 with edx = 0.
1309
; 3. For high-speed devices, go to step 5 with edx = 0.
1320
        xor     edx, edx
1310
        xor     edx, edx
1321
        cmp     ah, USB_SPEED_HS shl (12-8)
1311
        cmp     ah, USB_SPEED_HS shl (12-8)
1322
        jz      .common
1312
        jz      .common
1323
; 4. For low-speed and full-speed devices, fill address:port
1313
; 4. For low-speed and full-speed devices, fill address:port
1324
; of the last high-speed hub (the closest to the device hub)
1314
; of the last high-speed hub (the closest to the device hub)
1325
; for split transactions, and set ControlEndpoint bit in eax;
1315
; for split transactions, and set ControlEndpoint bit in eax;
1326
; ehci_init_pipe assumes that the parent pipe is a control pipe.
1316
; ehci_init_pipe assumes that the parent pipe is a control pipe.
1327
        movzx   ecx, [esi+usb_controller.ResettingPort]
1317
        movzx   ecx, [esi+usb_controller.ResettingPort]
1328
        mov     edx, [esi+usb_controller.ResettingHub]
1318
        mov     edx, [esi+usb_controller.ResettingHub]
1329
        push    eax
1319
        push    eax
1330
.find_hs_hub:
1320
.find_hs_hub:
1331
        mov     eax, [edx+usb_hub.ConfigPipe]
1321
        mov     eax, [edx+usb_hub.ConfigPipe]
1332
        mov     eax, [eax+usb_pipe.DeviceData]
1322
        mov     eax, [eax+usb_pipe.DeviceData]
1333
        cmp     [eax+usb_device_data.Speed], USB_SPEED_HS
1323
        cmp     [eax+usb_device_data.Speed], USB_SPEED_HS
1334
        jz      .found_hs_hub
1324
        jz      .found_hs_hub
1335
        movzx   ecx, [eax+usb_device_data.Port]
1325
        movzx   ecx, [eax+usb_device_data.Port]
1336
        mov     edx, [eax+usb_device_data.Hub]
1326
        mov     edx, [eax+usb_device_data.Hub]
1337
        jmp     .find_hs_hub
1327
        jmp     .find_hs_hub
1338
.found_hs_hub:
1328
.found_hs_hub:
1339
        mov     edx, [edx+usb_hub.ConfigPipe]
1329
        mov     edx, [edx+usb_hub.ConfigPipe]
1340
        inc     ecx
1330
        inc     ecx
1341
        mov     edx, [edx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
1331
        mov     edx, [edx+ehci_pipe.Token-ehci_pipe.SoftwarePart]
1342
        shl     ecx, 23
1332
        shl     ecx, 23
1343
        and     edx, 7Fh
1333
        and     edx, 7Fh
1344
        shl     edx, 16
1334
        shl     edx, 16
1345
        or      edx, ecx        ; ehci_pipe.Flags
1335
        or      edx, ecx        ; ehci_pipe.Flags
1346
        pop     eax
1336
        pop     eax
1347
        or      eax, 1 shl 27   ; ehci_pipe.Token
1337
        or      eax, 1 shl 27   ; ehci_pipe.Token
1348
.common:
1338
.common:
1349
; 5. Create pseudo-pipe in the stack.
1339
; 5. Create pseudo-pipe in the stack.
1350
; See ehci_init_pipe: only .Controller, .Token, .Flags fields are used.
1340
; See ehci_init_pipe: only .Controller, .Token, .Flags fields are used.
1351
        push    esi     ; ehci_pipe.SoftwarePart.Controller
1341
        push    esi     ; ehci_pipe.SoftwarePart.Controller
1352
        mov     ecx, esp
1342
        mov     ecx, esp
1353
        sub     esp, ehci_pipe.SoftwarePart - ehci_pipe.Flags - 4
1343
        sub     esp, ehci_pipe.SoftwarePart - ehci_pipe.Flags - 4
1354
        push    edx     ; ehci_pipe.Flags
1344
        push    edx     ; ehci_pipe.Flags
1355
        push    eax     ; ehci_pipe.Token
1345
        push    eax     ; ehci_pipe.Token
1356
; 6. Notify the protocol layer.
1346
; 6. Notify the protocol layer.
1357
        call    usb_new_device
1347
        call    usb_new_device
1358
; 7. Cleanup the stack after step 5 and return.
1348
; 7. Cleanup the stack after step 5 and return.
1359
        add     esp, ehci_pipe.SoftwarePart - ehci_pipe.Flags + 8
1349
        add     esp, ehci_pipe.SoftwarePart - ehci_pipe.Flags + 8
1360
        pop     ecx ebx ; restore used registers
1350
        pop     ecx ebx ; restore used registers
1361
        ret
1351
        ret
1362
endp
1352
endp
1363
 
1353
 
1364
; This procedure is called in the USB thread from usb_thread_proc,
1354
; This procedure is called in the USB thread from usb_thread_proc,
1365
; processes regular actions and those actions which can't be safely done
1355
; processes regular actions and those actions which can't be safely done
1366
; from interrupt handler.
1356
; from interrupt handler.
1367
; Returns maximal time delta before the next call.
1357
; Returns maximal time delta before the next call.
1368
proc ehci_process_deferred
1358
proc ehci_process_deferred
1369
        push    ebx edi         ; save used registers to be stdcall
1359
        push    ebx edi         ; save used registers to be stdcall
1370
        mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
1360
        mov     edi, [esi+ehci_controller.MMIOBase2-sizeof.ehci_controller]
1371
; 1. Get the mask of events to process.
1361
; 1. Get the mask of events to process.
1372
        xor     eax, eax
1362
        xor     eax, eax
1373
        xchg    eax, [esi+ehci_controller.DeferredActions-sizeof.ehci_controller]
1363
        xchg    eax, [esi+ehci_controller.DeferredActions-sizeof.ehci_controller]
1374
        push    eax
1364
        push    eax
1375
; 2. Initialize the return value.
1365
; 2. Initialize the return value.
1376
        push    -1
1366
        push    -1
1377
; Handle roothub events.
1367
; Handle roothub events.
1378
; 3a. Test whether there are such events.
1368
; 3a. Test whether there are such events.
1379
        test    al, 4
1369
        test    al, 4
1380
        jz      .skip_roothub
1370
        jz      .skip_roothub
1381
; Status of some port has changed. Loop over all ports.
1371
; Status of some port has changed. Loop over all ports.
1382
; 3b. Prepare for the loop: start from port 0.
1372
; 3b. Prepare for the loop: start from port 0.
1383
        xor     ecx, ecx
1373
        xor     ecx, ecx
1384
.portloop:
1374
.portloop:
1385
; 3c. Get the port status and changes of it.
1375
; 3c. Get the port status and changes of it.
1386
; If there are no changes, just continue to the next port.
1376
; If there are no changes, just continue to the next port.
1387
        mov     eax, [edi+EhciPortsReg+ecx*4]
1377
        mov     eax, [edi+EhciPortsReg+ecx*4]
1388
        test    al, 2Ah
1378
        test    al, 2Ah
1389
        jz      .nextport
1379
        jz      .nextport
1390
; 3d. Clear change bits and read the status again.
1380
; 3d. Clear change bits and read the status again.
1391
; (It is possible, although quite unlikely, that some event occurs between
1381
; (It is possible, although quite unlikely, that some event occurs between
1392
; the first read and the clearing, invalidating the old status. If an event
1382
; the first read and the clearing, invalidating the old status. If an event
1393
; occurs after the clearing, we will not miss it, looking in the next scan.
1383
; occurs after the clearing, we will not miss it, looking in the next scan.
1394
        mov     [edi+EhciPortsReg+ecx*4], eax
1384
        mov     [edi+EhciPortsReg+ecx*4], eax
1395
        mov     ebx, eax
1385
        mov     ebx, eax
1396
        mov     eax, [edi+EhciPortsReg+ecx*4]
1386
        mov     eax, [edi+EhciPortsReg+ecx*4]
1397
        DEBUGF 1,'K : [%d] EHCI %x: status of port %d changed to %x\n',[timer_ticks],esi,ecx,ebx
1387
        DEBUGF 1,'K : [%d] EHCI %x: status of port %d changed to %x\n',[timer_ticks],esi,ecx,ebx
1398
; 3e. Handle overcurrent.
1388
; 3e. Handle overcurrent.
1399
; Note: that needs work.
1389
; Note: that needs work.
1400
        test    bl, 20h ; overcurrent change
1390
        test    bl, 20h ; overcurrent change
1401
        jz      .noovercurrent
1391
        jz      .noovercurrent
1402
        test    al, 10h ; overcurrent active
1392
        test    al, 10h ; overcurrent active
1403
        jz      .noovercurrent
1393
        jz      .noovercurrent
1404
        DEBUGF 1,'K : overcurrent at port %d\n',ecx
1394
        DEBUGF 1,'K : overcurrent at port %d\n',ecx
1405
.noovercurrent:
1395
.noovercurrent:
1406
; 3f. Handle changing of connection status.
1396
; 3f. Handle changing of connection status.
1407
        test    bl, 2
1397
        test    bl, 2
1408
        jz      .nocsc
1398
        jz      .nocsc
1409
; There was a connect or disconnect event at this port.
1399
; There was a connect or disconnect event at this port.
1410
; 3g. Disconnect the old device on this port, if any.
1400
; 3g. Disconnect the old device on this port, if any.
1411
; If the port was resetting, indicate fail; later stages will process it.
1401
; If the port was resetting, indicate fail; later stages will process it.
1412
        cmp     [esi+usb_controller.ResettingHub], 0
1402
        cmp     [esi+usb_controller.ResettingHub], 0
1413
        jnz     @f
1403
        jnz     @f
1414
        cmp     cl, [esi+usb_controller.ResettingPort]
1404
        cmp     cl, [esi+usb_controller.ResettingPort]
1415
        jnz     @f
1405
        jnz     @f
1416
        mov     [esi+usb_controller.ResettingStatus], -1
1406
        mov     [esi+usb_controller.ResettingStatus], -1
1417
@@:
1407
@@:
1418
        bts     [esi+usb_controller.NewDisconnected], ecx
1408
        bts     [esi+usb_controller.NewDisconnected], ecx
1419
; 3h. Change connected status. For the connection event, also store
1409
; 3h. Change connected status. For the connection event, also store
1420
; the connection time; any further processing is permitted only after
1410
; the connection time; any further processing is permitted only after
1421
; USB_CONNECT_DELAY ticks.
1411
; USB_CONNECT_DELAY ticks.
1422
        test    al, 1
1412
        test    al, 1
1423
        jz      .disconnect
1413
        jz      .disconnect
1424
        mov     eax, [timer_ticks]
1414
        mov     eax, [timer_ticks]
1425
        mov     [esi+usb_controller.ConnectedTime+ecx*4], eax
1415
        mov     [esi+usb_controller.ConnectedTime+ecx*4], eax
1426
        bts     [esi+usb_controller.NewConnected], ecx
1416
        bts     [esi+usb_controller.NewConnected], ecx
1427
        jmp     .nextport
1417
        jmp     .nextport
1428
.disconnect:
1418
.disconnect:
1429
        btr     [esi+usb_controller.NewConnected], ecx
1419
        btr     [esi+usb_controller.NewConnected], ecx
1430
        jmp     .nextport
1420
        jmp     .nextport
1431
.nocsc:
1421
.nocsc:
1432
; 3i. Handle port disabling.
1422
; 3i. Handle port disabling.
1433
; Note: that needs work.
1423
; Note: that needs work.
1434
        test    al, 8
1424
        test    al, 8
1435
        jz      @f
1425
        jz      @f
1436
        test    al, 4
1426
        test    al, 4
1437
        jz      @f
1427
        jz      @f
1438
        DEBUGF 1,'K : port %d disabled\n',ecx
1428
        DEBUGF 1,'K : port %d disabled\n',ecx
1439
@@:
1429
@@:
1440
; 3j. Continue the loop for the next port.
1430
; 3j. Continue the loop for the next port.
1441
.nextport:
1431
.nextport:
1442
        inc     ecx
1432
        inc     ecx
1443
        cmp     ecx, [esi+usb_controller.NumPorts]
1433
        cmp     ecx, [esi+usb_controller.NumPorts]
1444
        jb      .portloop
1434
        jb      .portloop
1445
.skip_roothub:
1435
.skip_roothub:
1446
; 4. Process disconnect events. This should be done after step 3
1436
; 4. Process disconnect events. This should be done after step 3
1447
; (which includes the first stage of disconnect processing).
1437
; (which includes the first stage of disconnect processing).
1448
        call    usb_disconnect_stage2
1438
        call    usb_disconnect_stage2
1449
; 5. Check for previously connected devices.
1439
; 5. Check for previously connected devices.
1450
; If there is a connected device which was connected less than
1440
; If there is a connected device which was connected less than
1451
; USB_CONNECT_DELAY ticks ago, plan to wake up when the delay will be over.
1441
; USB_CONNECT_DELAY ticks ago, plan to wake up when the delay will be over.
1452
; Otherwise, call ehci_new_port.
1442
; Otherwise, call ehci_new_port.
1453
; This should be done after step 3.
1443
; This should be done after step 3.
1454
        xor     ecx, ecx
1444
        xor     ecx, ecx
1455
        cmp     [esi+usb_controller.NewConnected], ecx
1445
        cmp     [esi+usb_controller.NewConnected], ecx
1456
        jz      .skip_newconnected
1446
        jz      .skip_newconnected
1457
.portloop2:
1447
.portloop2:
1458
        bt      [esi+usb_controller.NewConnected], ecx
1448
        bt      [esi+usb_controller.NewConnected], ecx
1459
        jnc     .noconnect
1449
        jnc     .noconnect
1460
        mov     eax, [timer_ticks]
1450
        mov     eax, [timer_ticks]
1461
        sub     eax, [esi+usb_controller.ConnectedTime+ecx*4]
1451
        sub     eax, [esi+usb_controller.ConnectedTime+ecx*4]
1462
        sub     eax, USB_CONNECT_DELAY
1452
        sub     eax, USB_CONNECT_DELAY
1463
        jge     .connected
1453
        jge     .connected
1464
        neg     eax
1454
        neg     eax
1465
        cmp     [esp], eax
1455
        cmp     [esp], eax
1466
        jb      .nextport2
1456
        jb      .nextport2
1467
        mov     [esp], eax
1457
        mov     [esp], eax
1468
        jmp     .nextport2
1458
        jmp     .nextport2
1469
.connected:
1459
.connected:
1470
        btr     [esi+usb_controller.NewConnected], ecx
1460
        btr     [esi+usb_controller.NewConnected], ecx
1471
        call    ehci_new_port
1461
        call    ehci_new_port
1472
        jmp     .portloop2
1462
        jmp     .portloop2
1473
.noconnect:
1463
.noconnect:
1474
.nextport2:
1464
.nextport2:
1475
        inc     ecx
1465
        inc     ecx
1476
        cmp     ecx, [esi+usb_controller.NumPorts]
1466
        cmp     ecx, [esi+usb_controller.NumPorts]
1477
        jb      .portloop2
1467
        jb      .portloop2
1478
.skip_newconnected:
1468
.skip_newconnected:
1479
; 6. Process wait lists.
1469
; 6. Process wait lists.
1480
; 6a. Periodic endpoints.
1470
; 6a. Periodic endpoints.
1481
; If a request is pending >8 microframes, satisfy it.
1471
; If a request is pending >8 microframes, satisfy it.
1482
; If a request is pending <=8 microframes, schedule next wakeup in 0.01s.
1472
; If a request is pending <=8 microframes, schedule next wakeup in 0.01s.
1483
        mov     eax, [esi+usb_controller.WaitPipeRequestPeriodic]
1473
        mov     eax, [esi+usb_controller.WaitPipeRequestPeriodic]
1484
        cmp     eax, [esi+usb_controller.ReadyPipeHeadPeriodic]
1474
        cmp     eax, [esi+usb_controller.ReadyPipeHeadPeriodic]
1485
        jz      .noperiodic
1475
        jz      .noperiodic
1486
        mov     edx, [edi+EhciFrameIndexReg]
1476
        mov     edx, [edi+EhciFrameIndexReg]
1487
        sub     edx, [esi+usb_controller.StartWaitFrame]
1477
        sub     edx, [esi+usb_controller.StartWaitFrame]
1488
        and     edx, 0x3FFF
1478
        and     edx, 0x3FFF
1489
        cmp     edx, 8
1479
        cmp     edx, 8
1490
        jbe     @f
1480
        jbe     @f
1491
        mov     [esi+usb_controller.ReadyPipeHeadPeriodic], eax
1481
        mov     [esi+usb_controller.ReadyPipeHeadPeriodic], eax
1492
        jmp     .noperiodic
1482
        jmp     .noperiodic
1493
@@:
1483
@@:
1494
        pop     eax
1484
        pop     eax
1495
        push    1               ; wakeup in 0.01 sec for next test
1485
        push    1               ; wakeup in 0.01 sec for next test
1496
.noperiodic:
1486
.noperiodic:
1497
; 6b. Asynchronous endpoints.
1487
; 6b. Asynchronous endpoints.
1498
; Satisfy a request when InterruptOnAsyncAdvance fired.
1488
; Satisfy a request when InterruptOnAsyncAdvance fired.
1499
        test    byte [esp+4], 20h
1489
        test    byte [esp+4], 20h
1500
        jz      @f
1490
        jz      @f
1501
        dbgstr 'async advance int'
1491
        dbgstr 'async advance int'
1502
        mov     eax, [esi+usb_controller.WaitPipeRequestAsync]
1492
        mov     eax, [esi+usb_controller.WaitPipeRequestAsync]
1503
        mov     [esi+usb_controller.ReadyPipeHeadAsync], eax
1493
        mov     [esi+usb_controller.ReadyPipeHeadAsync], eax
1504
@@:
1494
@@:
1505
; Some hardware in some (rarely) conditions set the status bit,
1495
; Some hardware in some (rarely) conditions set the status bit,
1506
; but just does not generate the corresponding interrupt.
1496
; but just does not generate the corresponding interrupt.
1507
; Force checking the status here.
1497
; Force checking the status here.
1508
        mov     eax, [esi+usb_controller.WaitPipeRequestAsync]
1498
        mov     eax, [esi+usb_controller.WaitPipeRequestAsync]
1509
        cmp     [esi+usb_controller.ReadyPipeHeadAsync], eax
1499
        cmp     [esi+usb_controller.ReadyPipeHeadAsync], eax
1510
        jz      .noasync
1500
        jz      .noasync
1511
        spin_lock_irq [esi+usb_controller.WaitSpinlock]
1501
        spin_lock_irq [esi+usb_controller.WaitSpinlock]
1512
        mov     edx, [edi+EhciStatusReg]
1502
        mov     edx, [edi+EhciStatusReg]
1513
        test    dl, 20h
1503
        test    dl, 20h
1514
        jz      @f
1504
        jz      @f
1515
        mov     dword [edi+EhciStatusReg], 20h
1505
        mov     dword [edi+EhciStatusReg], 20h
1516
        and     dword [esi+ehci_controller.DeferredActions-sizeof.ehci_controller], not 20h
1506
        and     dword [esi+ehci_controller.DeferredActions-sizeof.ehci_controller], not 20h
1517
        dbgstr 'warning: async advance int missed'
1507
        dbgstr 'warning: async advance int missed'
1518
        mov     [esi+usb_controller.ReadyPipeHeadAsync], eax
1508
        mov     [esi+usb_controller.ReadyPipeHeadAsync], eax
1519
        jmp     .async_unlock
1509
        jmp     .async_unlock
1520
@@:
1510
@@:
1521
        cmp     dword [esp], 100
1511
        cmp     dword [esp], 100
1522
        jb      .async_unlock
1512
        jb      .async_unlock
1523
        mov     dword [esp], 100
1513
        mov     dword [esp], 100
1524
.async_unlock:
1514
.async_unlock:
1525
        spin_unlock_irq [esi+usb_controller.WaitSpinlock]
1515
        spin_unlock_irq [esi+usb_controller.WaitSpinlock]
1526
.noasync:
1516
.noasync:
1527
; 7. Finalize transfers processed by hardware.
1517
; 7. Finalize transfers processed by hardware.
1528
; It is better to perform this step after step 4 (disconnect events),
1518
; It is better to perform this step after step 4 (disconnect events),
1529
; although not strictly obligatory. This way, an active transfer aborted
1519
; although not strictly obligatory. This way, an active transfer aborted
1530
; due to disconnect would be handled with more specific USB_STATUS_CLOSED,
1520
; due to disconnect would be handled with more specific USB_STATUS_CLOSED,
1531
; not USB_STATUS_NORESPONSE.
1521
; not USB_STATUS_NORESPONSE.
1532
        test    byte [esp+4], 3
1522
        test    byte [esp+4], 3
1533
        jz      @f
1523
        jz      @f
1534
        call    ehci_process_updated_schedule
1524
        call    ehci_process_updated_schedule
1535
@@:
1525
@@:
1536
; 8. Test whether reset signalling has been started and should be stopped now.
1526
; 8. Test whether reset signalling has been started and should be stopped now.
1537
; This must be done after step 7, because completion of some transfer could
1527
; This must be done after step 7, because completion of some transfer could
1538
; result in resetting a new port.
1528
; result in resetting a new port.
1539
.test_reset:
1529
.test_reset:
1540
; 8a. Test whether reset signalling is active.
1530
; 8a. Test whether reset signalling is active.
1541
        cmp     [esi+usb_controller.ResettingStatus], 1
1531
        cmp     [esi+usb_controller.ResettingStatus], 1
1542
        jnz     .no_reset_in_progress
1532
        jnz     .no_reset_in_progress
1543
; 8b. Yep. Test whether it should be stopped.
1533
; 8b. Yep. Test whether it should be stopped.
1544
        mov     eax, [timer_ticks]
1534
        mov     eax, [timer_ticks]
1545
        sub     eax, [esi+usb_controller.ResetTime]
1535
        sub     eax, [esi+usb_controller.ResetTime]
1546
        sub     eax, USB_RESET_TIME
1536
        sub     eax, USB_RESET_TIME
1547
        jge     .reset_done
1537
        jge     .reset_done
1548
; 8c. Not yet, but initiate wakeup in -eax ticks and exit this step.
1538
; 8c. Not yet, but initiate wakeup in -eax ticks and exit this step.
1549
        neg     eax
1539
        neg     eax
1550
        cmp     [esp], eax
1540
        cmp     [esp], eax
1551
        jb      .skip_reset
1541
        jb      .skip_reset
1552
        mov     [esp], eax
1542
        mov     [esp], eax
1553
        jmp     .skip_reset
1543
        jmp     .skip_reset
1554
.reset_done:
1544
.reset_done:
1555
; 8d. Yep, call the worker function and proceed to 8e.
1545
; 8d. Yep, call the worker function and proceed to 8e.
1556
        call    ehci_port_reset_done
1546
        call    ehci_port_reset_done
1557
.no_reset_in_progress:
1547
.no_reset_in_progress:
1558
; 8e. Test whether reset process is done, either successful or failed.
1548
; 8e. Test whether reset process is done, either successful or failed.
1559
        cmp     [esi+usb_controller.ResettingStatus], 0
1549
        cmp     [esi+usb_controller.ResettingStatus], 0
1560
        jz      .skip_reset
1550
        jz      .skip_reset
1561
; 8f. Yep. Test whether it should be stopped.
1551
; 8f. Yep. Test whether it should be stopped.
1562
        mov     eax, [timer_ticks]
1552
        mov     eax, [timer_ticks]
1563
        sub     eax, [esi+usb_controller.ResetTime]
1553
        sub     eax, [esi+usb_controller.ResetTime]
1564
        sub     eax, USB_RESET_RECOVERY_TIME
1554
        sub     eax, USB_RESET_RECOVERY_TIME
1565
        jge     .reset_recovery_done
1555
        jge     .reset_recovery_done
1566
; 8g. Not yet, but initiate wakeup in -eax ticks and exit this step.
1556
; 8g. Not yet, but initiate wakeup in -eax ticks and exit this step.
1567
        neg     eax
1557
        neg     eax
1568
        cmp     [esp], eax
1558
        cmp     [esp], eax
1569
        jb      .skip_reset
1559
        jb      .skip_reset
1570
        mov     [esp], eax
1560
        mov     [esp], eax
1571
        jmp     .skip_reset
1561
        jmp     .skip_reset
1572
.reset_recovery_done:
1562
.reset_recovery_done:
1573
; 8h. Yep, call the worker function. This could initiate another reset,
1563
; 8h. Yep, call the worker function. This could initiate another reset,
1574
; so return to the beginning of this step.
1564
; so return to the beginning of this step.
1575
        call    ehci_port_init
1565
        call    ehci_port_init
1576
        jmp     .test_reset
1566
        jmp     .test_reset
1577
.skip_reset:
1567
.skip_reset:
1578
; 9. Process wait-done notifications, test for new wait requests.
1568
; 9. Process wait-done notifications, test for new wait requests.
1579
; Note: that must be done after steps 4 and 7 which could create new requests.
1569
; Note: that must be done after steps 4 and 7 which could create new requests.
1580
; 9a. Call the worker function.
1570
; 9a. Call the worker function.
1581
        call    usb_process_wait_lists
1571
        call    usb_process_wait_lists
1582
; 9b. If it reports that an asynchronous endpoint should be removed,
1572
; 9b. If it reports that an asynchronous endpoint should be removed,
1583
; doorbell InterruptOnAsyncAdvance and schedule wakeup in 1s
1573
; doorbell InterruptOnAsyncAdvance and schedule wakeup in 1s
1584
; (sometimes it just does not fire).
1574
; (sometimes it just does not fire).
1585
        test    al, 1 shl CONTROL_PIPE
1575
        test    al, 1 shl CONTROL_PIPE
1586
        jz      @f
1576
        jz      @f
1587
        mov     edx, [esi+usb_controller.WaitPipeListAsync]
1577
        mov     edx, [esi+usb_controller.WaitPipeListAsync]
1588
        mov     [esi+usb_controller.WaitPipeRequestAsync], edx
1578
        mov     [esi+usb_controller.WaitPipeRequestAsync], edx
1589
        or      dword [edi+EhciCommandReg], 1 shl 6
1579
        or      dword [edi+EhciCommandReg], 1 shl 6
1590
        dbgstr 'async advance doorbell'
1580
        dbgstr 'async advance doorbell'
1591
        cmp     dword [esp], 100
1581
        cmp     dword [esp], 100
1592
        jb      @f
1582
        jb      @f
1593
        mov     dword [esp], 100
1583
        mov     dword [esp], 100
1594
@@:
1584
@@:
1595
; 9c. If it reports that a periodic endpoint should be removed,
1585
; 9c. If it reports that a periodic endpoint should be removed,
1596
; save the current frame and schedule wakeup in 0.01 sec.
1586
; save the current frame and schedule wakeup in 0.01 sec.
1597
        test    al, 1 shl INTERRUPT_PIPE
1587
        test    al, 1 shl INTERRUPT_PIPE
1598
        jz      @f
1588
        jz      @f
1599
        mov     eax, [esi+usb_controller.WaitPipeListPeriodic]
1589
        mov     eax, [esi+usb_controller.WaitPipeListPeriodic]
1600
        mov     [esi+usb_controller.WaitPipeRequestPeriodic], eax
1590
        mov     [esi+usb_controller.WaitPipeRequestPeriodic], eax
1601
        mov     edx, [edi+EhciFrameIndexReg]
1591
        mov     edx, [edi+EhciFrameIndexReg]
1602
        mov     [esi+usb_controller.StartWaitFrame], edx
1592
        mov     [esi+usb_controller.StartWaitFrame], edx
1603
        mov     dword [esp], 1  ; wakeup in 0.01 sec for next test
1593
        mov     dword [esp], 1  ; wakeup in 0.01 sec for next test
1604
@@:
1594
@@:
1605
; 10. Pop the return value, restore the stack after step 1 and return.
1595
; 10. Pop the return value, restore the stack after step 1 and return.
1606
        pop     eax
1596
        pop     eax
1607
        pop     ecx
1597
        pop     ecx
1608
        pop     edi ebx ; restore used registers to be stdcall
1598
        pop     edi ebx ; restore used registers to be stdcall
1609
        ret
1599
        ret
1610
endp
1600
endp
1611
 
1601
 
1612
; This procedure is called in the USB thread from ehci_process_deferred
1602
; This procedure is called in the USB thread from ehci_process_deferred
1613
; when EHCI IRQ handler has signalled that new IOC-packet was processed.
1603
; when EHCI IRQ handler has signalled that new IOC-packet was processed.
1614
; It scans all lists for completed packets and calls ehci_process_finalized_td
1604
; It scans all lists for completed packets and calls ehci_process_finalized_td
1615
; for those packets.
1605
; for those packets.
1616
proc ehci_process_updated_schedule
1606
proc ehci_process_updated_schedule
1617
; Important note: we cannot hold the list lock during callbacks,
1607
; Important note: we cannot hold the list lock during callbacks,
1618
; because callbacks sometimes open and/or close pipes and thus acquire/release
1608
; because callbacks sometimes open and/or close pipes and thus acquire/release
1619
; the corresponding lock itself.
1609
; the corresponding lock itself.
1620
; Fortunately, pipes can be finally freed only by another step of
1610
; Fortunately, pipes can be finally freed only by another step of
1621
; ehci_process_deferred, so all pipes existing at the start of this function
1611
; ehci_process_deferred, so all pipes existing at the start of this function
1622
; will be valid while this function is running. Some pipes can be removed
1612
; will be valid while this function is running. Some pipes can be removed
1623
; from the corresponding list, some pipes can be inserted; insert/remove
1613
; from the corresponding list, some pipes can be inserted; insert/remove
1624
; functions guarantee that traversing one list yields all pipes that were in
1614
; functions guarantee that traversing one list yields all pipes that were in
1625
; that list at the beginning of the traversing (possibly with some new pipes,
1615
; that list at the beginning of the traversing (possibly with some new pipes,
1626
; possibly without some new pipes, that doesn't matter).
1616
; possibly without some new pipes, that doesn't matter).
1627
        push    edi
1617
        push    edi
1628
; 1. Process all Periodic lists.
1618
; 1. Process all Periodic lists.
1629
        lea     edi, [esi+ehci_controller.IntEDs-sizeof.ehci_controller+ehci_static_ep.SoftwarePart]
1619
        lea     edi, [esi+ehci_controller.IntEDs-sizeof.ehci_controller+ehci_static_ep.SoftwarePart]
1630
        lea     ebx, [esi+ehci_controller.IntEDs+63*sizeof.ehci_static_ep-sizeof.ehci_controller+ehci_static_ep.SoftwarePart]
1620
        lea     ebx, [esi+ehci_controller.IntEDs+63*sizeof.ehci_static_ep-sizeof.ehci_controller+ehci_static_ep.SoftwarePart]
1631
@@:
1621
@@:
1632
        call    ehci_process_updated_list
1622
        call    ehci_process_updated_list
1633
        cmp     edi, ebx
1623
        cmp     edi, ebx
1634
        jnz     @b
1624
        jnz     @b
1635
; 2. Process the Control list.
1625
; 2. Process the Control list.
1636
        add     edi, ehci_controller.ControlDelta
1626
        add     edi, ehci_controller.ControlDelta
1637
        call    ehci_process_updated_list
1627
        call    ehci_process_updated_list
1638
; 3. Process the Bulk list.
1628
; 3. Process the Bulk list.
1639
        call    ehci_process_updated_list
1629
        call    ehci_process_updated_list
1640
; 4. Return.
1630
; 4. Return.
1641
        pop     edi
1631
        pop     edi
1642
        ret
1632
        ret
1643
endp
1633
endp
1644
 
1634
 
1645
; This procedure is called from ehci_process_updated_schedule, see comments there.
1635
; This procedure is called from ehci_process_updated_schedule, see comments there.
1646
; It processes one list, esi -> usb_controller, edi -> usb_static_ep,
1636
; It processes one list, esi -> usb_controller, edi -> usb_static_ep,
1647
; and advances edi to next head.
1637
; and advances edi to next head.
1648
proc ehci_process_updated_list
1638
proc ehci_process_updated_list
1649
        push    ebx
1639
        push    ebx
1650
; 1. Perform the external loop over all pipes.
1640
; 1. Perform the external loop over all pipes.
1651
        mov     ebx, [edi+usb_static_ep.NextVirt]
1641
        mov     ebx, [edi+usb_static_ep.NextVirt]
1652
.loop:
1642
.loop:
1653
        cmp     ebx, edi
1643
        cmp     ebx, edi
1654
        jz      .done
1644
        jz      .done
1655
; store pointer to the next pipe in the stack
1645
; store pointer to the next pipe in the stack
1656
        push    [ebx+usb_static_ep.NextVirt]
1646
        push    [ebx+usb_static_ep.NextVirt]
1657
; 2. For every pipe, perform the internal loop over all descriptors.
1647
; 2. For every pipe, perform the internal loop over all descriptors.
1658
; All descriptors are organized in the queue; we process items from the start
1648
; All descriptors are organized in the queue; we process items from the start
1659
; of the queue until a) the last descriptor (not the part of the queue itself)
1649
; of the queue until a) the last descriptor (not the part of the queue itself)
1660
; or b) an active (not yet processed by the hardware) descriptor is reached.
1650
; or b) an active (not yet processed by the hardware) descriptor is reached.
1661
        lea     ecx, [ebx+usb_pipe.Lock]
1651
        lea     ecx, [ebx+usb_pipe.Lock]
1662
        call    mutex_lock
1652
        call    mutex_lock
1663
        mov     ebx, [ebx+usb_pipe.LastTD]
1653
        mov     ebx, [ebx+usb_pipe.LastTD]
1664
        push    ebx
1654
        push    ebx
1665
        mov     ebx, [ebx+usb_gtd.NextVirt]
1655
        mov     ebx, [ebx+usb_gtd.NextVirt]
1666
.tdloop:
1656
.tdloop:
1667
; 3. For every descriptor, test active flag and check for end-of-queue;
1657
; 3. For every descriptor, test active flag and check for end-of-queue;
1668
; if either of conditions holds, exit from the internal loop.
1658
; if either of conditions holds, exit from the internal loop.
1669
        cmp     ebx, [esp]
1659
        cmp     ebx, [esp]
1670
        jz      .tddone
1660
        jz      .tddone
1671
        cmp     byte [ebx+ehci_gtd.Token-ehci_gtd.SoftwarePart], 0
1661
        cmp     byte [ebx+ehci_gtd.Token-ehci_gtd.SoftwarePart], 0
1672
        js      .tddone
1662
        js      .tddone
1673
; Release the queue lock while processing one descriptor:
1663
; Release the queue lock while processing one descriptor:
1674
; callback function could (and often would) schedule another transfer.
1664
; callback function could (and often would) schedule another transfer.
1675
        push    ecx
1665
        push    ecx
1676
        call    mutex_unlock
1666
        call    mutex_unlock
1677
        call    ehci_process_updated_td
1667
        call    ehci_process_updated_td
1678
        pop     ecx
1668
        pop     ecx
1679
        call    mutex_lock
1669
        call    mutex_lock
1680
        jmp     .tdloop
1670
        jmp     .tdloop
1681
.tddone:
1671
.tddone:
1682
        call    mutex_unlock
1672
        call    mutex_unlock
1683
        pop     ebx
1673
        pop     ebx
1684
; End of internal loop, restore pointer to the next pipe
1674
; End of internal loop, restore pointer to the next pipe
1685
; and continue the external loop.
1675
; and continue the external loop.
1686
        pop     ebx
1676
        pop     ebx
1687
        jmp     .loop
1677
        jmp     .loop
1688
.done:
1678
.done:
1689
        pop     ebx
1679
        pop     ebx
1690
        add     edi, sizeof.ehci_static_ep
1680
        add     edi, sizeof.ehci_static_ep
1691
        ret
1681
        ret
1692
endp
1682
endp
1693
 
1683
 
1694
; This procedure is called from ehci_process_updated_list, which is itself
1684
; This procedure is called from ehci_process_updated_list, which is itself
1695
; called from ehci_process_updated_schedule, see comments there.
1685
; called from ehci_process_updated_schedule, see comments there.
1696
; It processes one completed descriptor.
1686
; It processes one completed descriptor.
1697
; in: ebx -> usb_gtd, out: ebx -> next usb_gtd.
1687
; in: ebx -> usb_gtd, out: ebx -> next usb_gtd.
1698
proc ehci_process_updated_td
1688
proc ehci_process_updated_td
1699
;       mov     eax, [ebx+usb_gtd.Pipe]
1689
;       mov     eax, [ebx+usb_gtd.Pipe]
1700
;       cmp     [eax+usb_pipe.Type], INTERRUPT_PIPE
1690
;       cmp     [eax+usb_pipe.Type], INTERRUPT_PIPE
1701
;       jnz     @f
1691
;       jnz     @f
1702
;       DEBUGF 1,'K : finalized TD for pipe %x:\n',eax
1692
;       DEBUGF 1,'K : finalized TD for pipe %x:\n',eax
1703
;       lea     eax, [ebx-ehci_gtd.SoftwarePart]
1693
;       lea     eax, [ebx-ehci_gtd.SoftwarePart]
1704
;       DEBUGF 1,'K : %x %x %x %x\n',[eax],[eax+4],[eax+8],[eax+12]
1694
;       DEBUGF 1,'K : %x %x %x %x\n',[eax],[eax+4],[eax+8],[eax+12]
1705
;       DEBUGF 1,'K : %x %x %x %x\n',[eax+16],[eax+20],[eax+24],[eax+28]
1695
;       DEBUGF 1,'K : %x %x %x %x\n',[eax+16],[eax+20],[eax+24],[eax+28]
1706
;@@:
1696
;@@:
1707
; 1. Remove this descriptor from the list of descriptors for this pipe.
1697
; 1. Remove this descriptor from the list of descriptors for this pipe.
1708
        call    usb_unlink_td
1698
        call    usb_unlink_td
1709
; 2. Calculate actual number of bytes transferred.
1699
; 2. Calculate actual number of bytes transferred.
1710
        mov     eax, [ebx+ehci_gtd.Token-ehci_gtd.SoftwarePart]
1700
        mov     eax, [ebx+ehci_gtd.Token-ehci_gtd.SoftwarePart]
1711
        lea     edx, [eax+eax]
1701
        lea     edx, [eax+eax]
1712
        shr     edx, 17
1702
        shr     edx, 17
1713
        sub     edx, [ebx+usb_gtd.Length]
1703
        sub     edx, [ebx+usb_gtd.Length]
1714
        neg     edx
1704
        neg     edx
1715
; 3. Check whether we need some special processing beyond notifying the driver.
1705
; 3. Check whether we need some special processing beyond notifying the driver.
1716
; Transfer errors require special processing.
1706
; Transfer errors require special processing.
1717
; Short packets require special processing if
1707
; Short packets require special processing if
1718
; a) this is not the last descriptor for transfer stage
1708
; a) this is not the last descriptor for transfer stage
1719
; (in this case we need to process subsequent descriptors for the stage too)
1709
; (in this case we need to process subsequent descriptors for the stage too)
1720
; or b) the caller considers short transfers to be an error.
1710
; or b) the caller considers short transfers to be an error.
1721
; ehci_alloc_transfer sets bit 0 of ehci_gtd.Flags to 0 if short packet
1711
; ehci_alloc_transfer sets bit 0 of ehci_gtd.Flags to 0 if short packet
1722
; in this descriptor requires special processing and to 1 otherwise.
1712
; in this descriptor requires special processing and to 1 otherwise.
1723
; If special processing is not needed, advance to 4 with ecx = 0.
1713
; If special processing is not needed, advance to 4 with ecx = 0.
1724
; Otherwise, go to 6.
1714
; Otherwise, go to 6.
1725
        xor     ecx, ecx
1715
        xor     ecx, ecx
1726
        test    al, 40h
1716
        test    al, 40h
1727
        jnz     .error
1717
        jnz     .error
1728
        test    byte [ebx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], 1
1718
        test    byte [ebx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], 1
1729
        jnz     .notify
1719
        jnz     .notify
1730
        cmp     edx, [ebx+usb_gtd.Length]
1720
        cmp     edx, [ebx+usb_gtd.Length]
1731
        jnz     .special
1721
        jnz     .special
1732
.notify:
1722
.notify:
1733
; 4. Either the descriptor in ebx was processed without errors,
1723
; 4. Either the descriptor in ebx was processed without errors,
1734
; or all necessary error actions were taken and ebx points to the last
1724
; or all necessary error actions were taken and ebx points to the last
1735
; related descriptor.
1725
; related descriptor.
1736
; 4a. Test whether it is the last descriptor in the transfer
1726
; 4a. Test whether it is the last descriptor in the transfer
1737
; <=> it has an associated callback.
1727
; <=> it has an associated callback.
1738
        mov     eax, [ebx+usb_gtd.Callback]
1728
        mov     eax, [ebx+usb_gtd.Callback]
1739
        test    eax, eax
1729
        test    eax, eax
1740
        jz      .nocallback
1730
        jz      .nocallback
1741
; 4b. It has an associated callback; call it with corresponding parameters.
1731
; 4b. It has an associated callback; call it with corresponding parameters.
1742
        stdcall_verify eax, [ebx+usb_gtd.Pipe], ecx, \
1732
        stdcall_verify eax, [ebx+usb_gtd.Pipe], ecx, \
1743
                [ebx+usb_gtd.Buffer], edx, [ebx+usb_gtd.UserData]
1733
                [ebx+usb_gtd.Buffer], edx, [ebx+usb_gtd.UserData]
1744
        jmp     .callback
1734
        jmp     .callback
1745
.nocallback:
1735
.nocallback:
1746
; 4c. It is an intermediate descriptor. Add its length to the length
1736
; 4c. It is an intermediate descriptor. Add its length to the length
1747
; in the following descriptor.
1737
; in the following descriptor.
1748
        mov     eax, [ebx+usb_gtd.NextVirt]
1738
        mov     eax, [ebx+usb_gtd.NextVirt]
1749
        add     [eax+usb_gtd.Length], edx
1739
        add     [eax+usb_gtd.Length], edx
1750
.callback:
1740
.callback:
1751
; 5. Free the current descriptor and return the next one.
1741
; 5. Free the current descriptor and return the next one.
1752
        push    [ebx+usb_gtd.NextVirt]
1742
        push    [ebx+usb_gtd.NextVirt]
1753
        stdcall ehci_free_td, ebx
1743
        stdcall ehci_free_td, ebx
1754
        pop     ebx
1744
        pop     ebx
1755
        ret
1745
        ret
1756
.error:
1746
.error:
1757
        push    ebx
1747
        push    ebx
1758
        sub     ebx, ehci_gtd.SoftwarePart
1748
        sub     ebx, ehci_gtd.SoftwarePart
1759
        DEBUGF 1,'K : TD failed:\n'
1749
        DEBUGF 1,'K : TD failed:\n'
1760
        DEBUGF 1,'K : %x %x %x %x\n',[ebx],[ebx+4],[ebx+8],[ebx+12]
1750
        DEBUGF 1,'K : %x %x %x %x\n',[ebx],[ebx+4],[ebx+8],[ebx+12]
1761
        DEBUGF 1,'K : %x %x %x %x\n',[ebx+16],[ebx+20],[ebx+24],[ebx+28]
1751
        DEBUGF 1,'K : %x %x %x %x\n',[ebx+16],[ebx+20],[ebx+24],[ebx+28]
1762
        pop     ebx
1752
        pop     ebx
1763
        DEBUGF 1,'K : pipe now:\n'
1753
        DEBUGF 1,'K : pipe now:\n'
1764
        mov     ecx, [ebx+usb_gtd.Pipe]
1754
        mov     ecx, [ebx+usb_gtd.Pipe]
1765
        sub     ecx, ehci_pipe.SoftwarePart
1755
        sub     ecx, ehci_pipe.SoftwarePart
1766
        DEBUGF 1,'K : %x %x %x %x\n',[ecx],[ecx+4],[ecx+8],[ecx+12]
1756
        DEBUGF 1,'K : %x %x %x %x\n',[ecx],[ecx+4],[ecx+8],[ecx+12]
1767
        DEBUGF 1,'K : %x %x %x %x\n',[ecx+16],[ecx+20],[ecx+24],[ecx+28]
1757
        DEBUGF 1,'K : %x %x %x %x\n',[ecx+16],[ecx+20],[ecx+24],[ecx+28]
1768
        DEBUGF 1,'K : %x %x %x %x\n',[ecx+32],[ecx+36],[ecx+40],[ecx+44]
1758
        DEBUGF 1,'K : %x %x %x %x\n',[ecx+32],[ecx+36],[ecx+40],[ecx+44]
1769
.special:
1759
.special:
1770
; 6. Special processing is needed.
1760
; 6. Special processing is needed.
1771
; 6a. Save the status and length.
1761
; 6a. Save the status and length.
1772
        push    edx
1762
        push    edx
1773
        push    eax
1763
        push    eax
1774
; 6b. Traverse the list of descriptors looking for the final descriptor
1764
; 6b. Traverse the list of descriptors looking for the final descriptor
1775
; for this transfer. Free and unlink non-final descriptors.
1765
; for this transfer. Free and unlink non-final descriptors.
1776
; Final descriptor will be freed in step 5.
1766
; Final descriptor will be freed in step 5.
1777
.look_final:
1767
.look_final:
1778
        call    usb_is_final_packet
1768
        call    usb_is_final_packet
1779
        jnc     .found_final
1769
        jnc     .found_final
1780
        push    [ebx+usb_gtd.NextVirt]
1770
        push    [ebx+usb_gtd.NextVirt]
1781
        stdcall ehci_free_td, ebx
1771
        stdcall ehci_free_td, ebx
1782
        pop     ebx
1772
        pop     ebx
1783
        call    usb_unlink_td
1773
        call    usb_unlink_td
1784
        jmp     .look_final
1774
        jmp     .look_final
1785
.found_final:
1775
.found_final:
1786
; 6c. Restore the status saved in 6a and transform it to the error code.
1776
; 6c. Restore the status saved in 6a and transform it to the error code.
1787
; Notes:
1777
; Notes:
1788
; * any USB transaction error results in Halted bit; if it is not set,
1778
; * any USB transaction error results in Halted bit; if it is not set,
1789
;   but we are here, it must be due to short packet;
1779
;   but we are here, it must be due to short packet;
1790
; * babble is considered a fatal USB transaction error,
1780
; * babble is considered a fatal USB transaction error,
1791
;   other errors just lead to retrying the transaction;
1781
;   other errors just lead to retrying the transaction;
1792
;   if babble is detected, return the corresponding error;
1782
;   if babble is detected, return the corresponding error;
1793
; * if several non-fatal errors have occured during transaction retries,
1783
; * if several non-fatal errors have occured during transaction retries,
1794
;   all corresponding bits are set. In this case, return some error code,
1784
;   all corresponding bits are set. In this case, return some error code,
1795
;   the order is quite arbitrary.
1785
;   the order is quite arbitrary.
1796
        pop     eax     ; status
1786
        pop     eax     ; status
1797
        push    USB_STATUS_UNDERRUN
1787
        movi    ecx, USB_STATUS_UNDERRUN
1798
        pop     ecx
-
 
1799
        test    al, 40h         ; not Halted?
1788
        test    al, 40h         ; not Halted?
1800
        jz      .know_error
1789
        jz      .know_error
1801
        mov     cl, USB_STATUS_OVERRUN
1790
        mov     cl, USB_STATUS_OVERRUN
1802
        test    al, 10h         ; Babble detected?
1791
        test    al, 10h         ; Babble detected?
1803
        jnz     .know_error
1792
        jnz     .know_error
1804
        mov     cl, USB_STATUS_BUFOVERRUN
1793
        mov     cl, USB_STATUS_BUFOVERRUN
1805
        test    al, 20h         ; Data Buffer error?
1794
        test    al, 20h         ; Data Buffer error?
1806
        jnz     .know_error
1795
        jnz     .know_error
1807
        mov     cl, USB_STATUS_NORESPONSE
1796
        mov     cl, USB_STATUS_NORESPONSE
1808
        test    al, 8           ; Transaction Error?
1797
        test    al, 8           ; Transaction Error?
1809
        jnz     .know_error
1798
        jnz     .know_error
1810
        mov     cl, USB_STATUS_STALL
1799
        mov     cl, USB_STATUS_STALL
1811
.know_error:
1800
.know_error:
1812
; 6d. If error code is USB_STATUS_UNDERRUN and the last TD allows short packets,
1801
; 6d. If error code is USB_STATUS_UNDERRUN and the last TD allows short packets,
1813
; it is not an error; in this case, go to 4 with ecx = 0.
1802
; it is not an error; in this case, go to 4 with ecx = 0.
1814
        cmp     ecx, USB_STATUS_UNDERRUN
1803
        cmp     ecx, USB_STATUS_UNDERRUN
1815
        jnz     @f
1804
        jnz     @f
1816
        test    byte [ebx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], 1
1805
        test    byte [ebx+ehci_gtd.Flags-ehci_gtd.SoftwarePart], 1
1817
        jz      @f
1806
        jz      @f
1818
        xor     ecx, ecx
1807
        xor     ecx, ecx
1819
        pop     edx     ; length
1808
        pop     edx     ; length
1820
        jmp     .notify
1809
        jmp     .notify
1821
@@:
1810
@@:
1822
; 6e. Abort the entire transfer.
1811
; 6e. Abort the entire transfer.
1823
; There are two cases: either there is only one transfer stage
1812
; There are two cases: either there is only one transfer stage
1824
; (everything except control transfers), then ebx points to the last TD and
1813
; (everything except control transfers), then ebx points to the last TD and
1825
; all previous TD were unlinked and dismissed (if possible),
1814
; all previous TD were unlinked and dismissed (if possible),
1826
; or there are several stages (a control transfer) and ebx points to the last
1815
; or there are several stages (a control transfer) and ebx points to the last
1827
; TD of Data or Status stage (usb_is_final_packet does not stop in Setup stage,
1816
; TD of Data or Status stage (usb_is_final_packet does not stop in Setup stage,
1828
; because Setup stage can not produce short packets); for Data stage, we need
1817
; because Setup stage can not produce short packets); for Data stage, we need
1829
; to unlink and free (if possible) one more TD and advance ebx to the next one.
1818
; to unlink and free (if possible) one more TD and advance ebx to the next one.
1830
        cmp     [ebx+usb_gtd.Callback], 0
1819
        cmp     [ebx+usb_gtd.Callback], 0
1831
        jnz     .normal
1820
        jnz     .normal
1832
        push    ecx
1821
        push    ecx
1833
        push    [ebx+usb_gtd.NextVirt]
1822
        push    [ebx+usb_gtd.NextVirt]
1834
        stdcall ehci_free_td, ebx
1823
        stdcall ehci_free_td, ebx
1835
        pop     ebx
1824
        pop     ebx
1836
        call    usb_unlink_td
1825
        call    usb_unlink_td
1837
        pop     ecx
1826
        pop     ecx
1838
.normal:
1827
.normal:
1839
; 6f. For bulk/interrupt transfers we have no choice but halt the queue,
1828
; 6f. For bulk/interrupt transfers we have no choice but halt the queue,
1840
; the driver should intercede (through some API which is not written yet).
1829
; the driver should intercede (through some API which is not written yet).
1841
; Control pipes normally recover at the next SETUP transaction (first stage
1830
; Control pipes normally recover at the next SETUP transaction (first stage
1842
; of any control transfer), so we hope on the best and just advance the queue
1831
; of any control transfer), so we hope on the best and just advance the queue
1843
; to the next transfer. (According to the standard, "A control pipe may also
1832
; to the next transfer. (According to the standard, "A control pipe may also
1844
; support functional stall as well, but this is not recommended.").
1833
; support functional stall as well, but this is not recommended.").
1845
        mov     edx, [ebx+usb_gtd.Pipe]
1834
        mov     edx, [ebx+usb_gtd.Pipe]
1846
        mov     eax, [ebx+ehci_gtd.NextTD-ehci_gtd.SoftwarePart]
1835
        mov     eax, [ebx+ehci_gtd.NextTD-ehci_gtd.SoftwarePart]
1847
        or      al, 1
1836
        or      al, 1
1848
        mov     [edx+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart], eax
1837
        mov     [edx+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart], eax
1849
        mov     [edx+ehci_pipe.Overlay.AlternateNextTD-ehci_pipe.SoftwarePart], eax
1838
        mov     [edx+ehci_pipe.Overlay.AlternateNextTD-ehci_pipe.SoftwarePart], eax
1850
        cmp     [edx+usb_pipe.Type], CONTROL_PIPE
1839
        cmp     [edx+usb_pipe.Type], CONTROL_PIPE
1851
        jz      .control
1840
        jz      .control
1852
; Bulk/interrupt transfer; halt the queue.
1841
; Bulk/interrupt transfer; halt the queue.
1853
        mov     [edx+ehci_pipe.Overlay.Token-ehci_pipe.SoftwarePart], 40h
1842
        mov     [edx+ehci_pipe.Overlay.Token-ehci_pipe.SoftwarePart], 40h
1854
        pop     edx
1843
        pop     edx
1855
        jmp     .notify
1844
        jmp     .notify
1856
; Control transfer.
1845
; Control transfer.
1857
.control:
1846
.control:
1858
        and     [edx+ehci_pipe.Overlay.Token-ehci_pipe.SoftwarePart], 0
1847
        and     [edx+ehci_pipe.Overlay.Token-ehci_pipe.SoftwarePart], 0
1859
        dec     [edx+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart]
1848
        dec     [edx+ehci_pipe.Overlay.NextTD-ehci_pipe.SoftwarePart]
1860
        pop     edx
1849
        pop     edx
1861
        jmp     .notify
1850
        jmp     .notify
1862
endp
1851
endp
1863
 
1852
 
1864
; This procedure unlinks the pipe from the corresponding pipe list.
1853
; This procedure unlinks the pipe from the corresponding pipe list.
1865
; esi -> usb_controller, ebx -> usb_pipe
1854
; esi -> usb_controller, ebx -> usb_pipe
1866
proc ehci_unlink_pipe
1855
proc ehci_unlink_pipe
1867
        cmp     [ebx+usb_pipe.Type], INTERRUPT_PIPE
1856
        cmp     [ebx+usb_pipe.Type], INTERRUPT_PIPE
1868
        jnz     @f
1857
        jnz     @f
1869
        test    word [ebx+ehci_pipe.Flags-ehci_pipe.SoftwarePart+2], 3FFFh
1858
        test    word [ebx+ehci_pipe.Flags-ehci_pipe.SoftwarePart+2], 3FFFh
1870
        jnz     .interrupt_fs
1859
        jnz     .interrupt_fs
1871
        call    ehci_hs_interrupt_list_unlink
1860
        call    ehci_hs_interrupt_list_unlink
1872
        jmp     .interrupt_common
1861
        jmp     .interrupt_common
1873
.interrupt_fs:
1862
.interrupt_fs:
1874
        call    ehci_fs_interrupt_list_unlink
1863
        call    ehci_fs_interrupt_list_unlink
1875
.interrupt_common:
1864
.interrupt_common:
1876
@@:
1865
@@:
1877
        mov     edx, [ebx+usb_pipe.NextVirt]
1866
        mov     edx, [ebx+usb_pipe.NextVirt]
1878
        mov     eax, [ebx+usb_pipe.PrevVirt]
1867
        mov     eax, [ebx+usb_pipe.PrevVirt]
1879
        mov     [edx+usb_pipe.PrevVirt], eax
1868
        mov     [edx+usb_pipe.PrevVirt], eax
1880
        mov     [eax+usb_pipe.NextVirt], edx
1869
        mov     [eax+usb_pipe.NextVirt], edx
1881
        mov     edx, esi
1870
        mov     edx, esi
1882
        sub     edx, eax
1871
        sub     edx, eax
1883
        cmp     edx, sizeof.ehci_controller
1872
        cmp     edx, sizeof.ehci_controller
1884
        mov     edx, [ebx+ehci_pipe.NextQH-ehci_pipe.SoftwarePart]
1873
        mov     edx, [ebx+ehci_pipe.NextQH-ehci_pipe.SoftwarePart]
1885
        jb      .prev_is_static
1874
        jb      .prev_is_static
1886
        mov     [eax+ehci_pipe.NextQH-ehci_pipe.SoftwarePart], edx
1875
        mov     [eax+ehci_pipe.NextQH-ehci_pipe.SoftwarePart], edx
1887
        ret
1876
        ret
1888
.prev_is_static:
1877
.prev_is_static:
1889
        mov     [eax+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], edx
1878
        mov     [eax+ehci_static_ep.NextQH-ehci_static_ep.SoftwarePart], edx
1890
        ret
1879
        ret
1891
endp
1880
endp
1892
 
1881
 
1893
proc ehci_alloc_td
1882
proc ehci_alloc_td
1894
        push    ebx
1883
        push    ebx
1895
        mov     ebx, ehci_gtd_mutex
1884
        mov     ebx, ehci_gtd_mutex
1896
        stdcall usb_allocate_common, sizeof.ehci_gtd
1885
        stdcall usb_allocate_common, sizeof.ehci_gtd
1897
        test    eax, eax
1886
        test    eax, eax
1898
        jz      @f
1887
        jz      @f
1899
        add     eax, ehci_gtd.SoftwarePart
1888
        add     eax, ehci_gtd.SoftwarePart
1900
@@:
1889
@@:
1901
        pop     ebx
1890
        pop     ebx
1902
        ret
1891
        ret
1903
endp
1892
endp
1904
 
1893
 
1905
; This procedure is called from several places from main USB code and
1894
; This procedure is called from several places from main USB code and
1906
; frees all additional data associated with the transfer descriptor.
1895
; frees all additional data associated with the transfer descriptor.
1907
; EHCI has no additional data, so just free ehci_gtd structure.
1896
; EHCI has no additional data, so just free ehci_gtd structure.
1908
proc ehci_free_td
1897
proc ehci_free_td
1909
        sub     dword [esp+4], ehci_gtd.SoftwarePart
1898
        sub     dword [esp+4], ehci_gtd.SoftwarePart
1910
        jmp     usb_free_common
1899
        jmp     usb_free_common
1911
endp
1900
endp