Subversion Repositories Kolibri OS

Rev

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

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