Rev 3908 | Rev 5201 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3908 | Rev 4423 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | ; Functions for USB pipe manipulation: opening/closing, sending data etc. |
1 | ; Functions for USB pipe manipulation: opening/closing, sending data etc. |
2 | ; |
2 | ; |
3 | ; ============================================================================= |
- | |
4 | ; ================================= Constants ================================= |
- | |
5 | ; ============================================================================= |
- | |
6 | ; USB pipe types |
- | |
7 | CONTROL_PIPE = 0 |
- | |
8 | ISOCHRONOUS_PIPE = 1 |
- | |
9 | BULK_PIPE = 2 |
- | |
10 | INTERRUPT_PIPE = 3 |
- | |
11 | - | ||
12 | ; Status codes for transfer callbacks. |
- | |
13 | ; Taken from OHCI as most verbose controller in this sense. |
- | |
14 | USB_STATUS_OK = 0 ; no error |
- | |
15 | USB_STATUS_CRC = 1 ; CRC error |
- | |
16 | USB_STATUS_BITSTUFF = 2 ; bit stuffing violation |
- | |
17 | USB_STATUS_TOGGLE = 3 ; data toggle mismatch |
- | |
18 | USB_STATUS_STALL = 4 ; device returned STALL |
- | |
19 | USB_STATUS_NORESPONSE = 5 ; device not responding |
- | |
20 | USB_STATUS_PIDCHECK = 6 ; invalid PID check bits |
- | |
21 | USB_STATUS_WRONGPID = 7 ; unexpected PID value |
- | |
22 | USB_STATUS_OVERRUN = 8 ; too many data from endpoint |
- | |
23 | USB_STATUS_UNDERRUN = 9 ; too few data from endpoint |
- | |
24 | USB_STATUS_BUFOVERRUN = 12 ; overflow of internal controller buffer |
- | |
25 | USB_STATUS_BUFUNDERRUN = 13 ; underflow of internal controller buffer |
- | |
26 | USB_STATUS_CLOSED = 16 ; pipe closed |
- | |
27 | ; either explicitly with USBClosePipe |
- | |
28 | ; or implicitly due to device disconnect |
- | |
29 | - | ||
30 | ; flags for usb_pipe.Flags |
- | |
31 | USB_FLAG_CLOSED = 1 ; pipe is closed, no new transfers |
- | |
32 | ; pipe is closed, return error instead of submitting any new transfer |
- | |
33 | USB_FLAG_CAN_FREE = 2 |
- | |
34 | ; pipe is closed via explicit call to USBClosePipe, so it can be freed without |
- | |
35 | ; any driver notification; if this flag is not set, then the pipe is closed due |
- | |
36 | ; to device disconnect, so it must remain valid until return from disconnect |
- | |
37 | ; callback provided by the driver |
- | |
38 | USB_FLAG_EXTRA_WAIT = 4 |
- | |
39 | ; The pipe was in wait list, while another event occured; |
- | |
40 | ; when the first wait will be done, reinsert the pipe to wait list |
- | |
41 | USB_FLAG_CLOSED_BIT = 0 ; USB_FLAG_CLOSED = 1 shl USB_FLAG_CLOSED_BIT |
- | |
42 | - | ||
43 | ; ============================================================================= |
- | |
44 | ; ================================ Structures ================================= |
- | |
45 | ; ============================================================================= |
- | |
46 | - | ||
47 | ; Pipe descriptor. |
- | |
48 | ; * An USB pipe is described by two structures, for hardware and for software. |
- | |
49 | ; * This is the software part. The hardware part is defined in a driver |
- | |
50 | ; of the corresponding controller. |
- | |
51 | ; * The hardware part is located immediately before usb_pipe, |
- | |
52 | ; both are allocated at once by controller-specific code |
- | |
53 | ; (it knows the total length, which depends on the hardware part). |
- | |
54 | struct usb_pipe |
- | |
55 | Controller dd ? |
- | |
56 | ; Pointer to usb_controller structure corresponding to this pipe. |
- | |
57 | ; Must be the first dword after hardware part, see *hci_new_device. |
- | |
58 | ; |
- | |
59 | ; Every endpoint is included into one of processing lists: |
- | |
60 | ; * Bulk list contains all Bulk endpoints. |
- | |
61 | ; * Control list contains all Control endpoints. |
- | |
62 | ; * Several Periodic lists serve Interrupt endpoints with different interval. |
- | |
63 | ; - There are N=2^n "leaf" periodic lists for N ms interval, one is processed |
- | |
64 | ; in the frames 0,N,2N,..., another is processed in the frames |
- | |
65 | ; 1,1+N,1+2N,... and so on. The hardware starts processing of periodic |
- | |
66 | ; endpoints in every frame from the list identified by lower n bits of the |
- | |
67 | ; frame number; the addresses of these N lists are written to the |
- | |
68 | ; controller data area during the initialization. |
- | |
69 | ; - We assume that n=5, N=32 to simplify the code and compact the data. |
- | |
70 | ; OHCI works in this way. UHCI and EHCI actually have n=10, N=1024, |
- | |
71 | ; but this is an overkill for interrupt endpoints; the large value of N is |
- | |
72 | ; useful only for isochronous transfers in UHCI and EHCI. UHCI/EHCI code |
- | |
73 | ; initializes "leaf" lists k,k+32,k+64,...,k+(1024-32) to the same value, |
- | |
74 | ; giving essentially N=32. |
- | |
75 | ; This restriction means that the actual maximum interval of polling any |
- | |
76 | ; interrupt endpoint is 32ms, which seems to be a reasonable value. |
- | |
77 | ; - Similarly, there are 16 lists for 16-ms interval, 8 lists for 8-ms |
- | |
78 | ; interval and so on. Finally, there is one list for 1ms interval. Their |
- | |
79 | ; addresses are not directly known to the controller. |
- | |
80 | ; - The hardware serves endpoints following a physical link from the hardware |
- | |
81 | ; part. |
- | |
82 | ; - The hardware links are organized as follows. If the list item is not the |
- | |
83 | ; last, it's hardware link points to the next item. The hardware link of |
- | |
84 | ; the last item points to the first item of the "next" list. |
- | |
85 | ; - The "next" list for k-th and (k+M)-th periodic lists for interval 2M ms |
- | |
86 | ; is the k-th periodic list for interval M ms, M >= 1. In this scheme, |
- | |
87 | ; if two "previous" lists are served in the frames k,k+2M,k+4M,... |
- | |
88 | ; and k+M,k+3M,k+5M,... correspondingly, the "next" list is served in |
- | |
89 | ; the frames k,k+M,k+2M,k+3M,k+4M,k+5M,..., which is exactly what we want. |
- | |
90 | ; - The links between Periodic, Control, Bulk lists and the processing of |
- | |
91 | ; Isochronous endpoints are controller-specific. |
- | |
92 | ; * The head of every processing list is a static entry which does not |
- | |
93 | ; correspond to any real pipe. It is described by usb_static_ep |
- | |
94 | ; structure, not usb_pipe. For OHCI and UHCI, sizeof.usb_static_ep plus |
- | |
95 | ; sizeof hardware part is 20h, the total number of lists is |
- | |
96 | ; 32+16+8+4+2+1+1+1 = 65, so all these structures fit in one page, |
- | |
97 | ; leaving space for other data. This is another reason for 32ms limit. |
- | |
98 | ; * Static endpoint descriptors are kept in *hci_controller structure. |
- | |
99 | ; * All items in every processing list, including the static head, are |
- | |
100 | ; organized in a double-linked list using .NextVirt and .PrevVirt fields. |
- | |
101 | ; * [[item.NextVirt].PrevVirt] = [[item.PrevVirt].NextVirt] for all items. |
- | |
102 | NextVirt dd ? |
- | |
103 | ; Next endpoint in the processing list. |
- | |
104 | ; See also PrevVirt field and the description before NextVirt field. |
- | |
105 | PrevVirt dd ? |
- | |
106 | ; Previous endpoint in the processing list. |
- | |
107 | ; See also NextVirt field and the description before NextVirt field. |
- | |
108 | ; |
- | |
109 | ; Every pipe has the associated transfer queue, that is, the double-linked |
- | |
110 | ; list of Transfer Descriptors aka TD. For Control, Bulk and Interrupt |
- | |
111 | ; endpoints this list consists of usb_gtd structures |
- | |
112 | ; (GTD = General Transfer Descriptors), for Isochronous endpoints |
- | |
113 | ; this list consists of usb_itd structures, which are not developed yet. |
- | |
114 | ; The pipe needs to know only the last TD; the first TD can be |
- | |
115 | ; obtained as [[pipe.LastTD].NextVirt]. |
- | |
116 | LastTD dd ? |
- | |
117 | ; Last TD in the transfer queue. |
- | |
118 | ; |
- | |
119 | ; All opened pipes corresponding to the same physical device are organized in |
- | |
120 | ; the double-linked list using .NextSibling and .PrevSibling fields. |
- | |
121 | ; The head of this list is kept in usb_device_data structure (OpenedPipeList). |
- | |
122 | ; This list is used when the device is disconnected and all pipes for the |
- | |
123 | ; device should be closed. |
- | |
124 | ; Also, all pipes closed due to disconnect must remain valid at least until |
- | |
125 | ; driver-provided disconnect function returns; all should-be-freed-but-not-now |
- | |
126 | ; pipes for one device are organized in another double-linked list with |
- | |
127 | ; the head in usb_device_data.ClosedPipeList; this list uses the same link |
- | |
128 | ; fields, one pipe can never be in both lists. |
- | |
129 | NextSibling dd ? |
- | |
130 | ; Next pipe for the physical device. |
- | |
131 | PrevSibling dd ? |
- | |
132 | ; Previous pipe for the physical device. |
- | |
133 | ; |
- | |
134 | ; When hardware part of pipe is changed, some time is needed before further |
- | |
135 | ; actions so that hardware reacts on this change. During that time, |
- | |
136 | ; all changed pipes are organized in single-linked list with the head |
- | |
137 | ; usb_controller.WaitPipeList* and link field NextWait. |
- | |
138 | ; Currently there are two possible reasons to change: |
- | |
139 | ; change of address/packet size in initial configuration, |
- | |
140 | ; close of the pipe. They are distinguished by USB_FLAG_CLOSED. |
- | |
141 | NextWait dd ? |
- | |
142 | Lock MUTEX |
- | |
143 | ; Mutex that guards operations with transfer queue for this pipe. |
- | |
144 | Type db ? |
- | |
145 | ; Type of pipe, one of {CONTROL,ISOCHRONOUS,BULK,INTERRUPT}_PIPE. |
- | |
146 | Flags db ? |
- | |
147 | ; Combination of flags, USB_FLAG_*. |
- | |
148 | rb 2 ; dword alignment |
- | |
149 | DeviceData dd ? |
- | |
150 | ; Pointer to usb_device_data, common for all pipes for one device. |
- | |
151 | ends |
- | |
152 | - | ||
153 | ; This structure describes the static head of every list of pipes. |
- | |
154 | struct usb_static_ep |
- | |
155 | ; software fields |
- | |
156 | Bandwidth dd ? |
- | |
157 | ; valid only for interrupt/isochronous USB1 lists |
- | |
158 | ; The offsets of the following two fields must be the same in this structure |
- | |
159 | ; and in usb_pipe. |
- | |
160 | NextVirt dd ? |
- | |
161 | PrevVirt dd ? |
- | |
162 | ends |
- | |
163 | - | ||
164 | ; This structure represents one transfer descriptor |
- | |
165 | ; ('g' stands for "general" as opposed to isochronous usb_itd). |
- | |
166 | ; Note that one transfer can have several descriptors: |
- | |
167 | ; a control transfer has three stages. |
- | |
168 | ; Additionally, every controller has a limit on transfer length with |
- | |
169 | ; one descriptor (packet size for UHCI, 1K for OHCI, 4K for EHCI), |
- | |
170 | ; large transfers must be split into individual packets according to that limit. |
- | |
171 | struct usb_gtd |
- | |
172 | Callback dd ? |
- | |
173 | ; Zero for intermediate descriptors, pointer to callback function |
- | |
174 | ; for final descriptor. See the docs for description of the callback. |
- | |
175 | UserData dd ? |
- | |
176 | ; Dword which is passed to Callback as is, not used by USB code itself. |
- | |
177 | ; Two following fields organize all descriptors for one pipe in |
- | |
178 | ; the linked list. |
- | |
179 | NextVirt dd ? |
- | |
180 | PrevVirt dd ? |
- | |
181 | Pipe dd ? |
- | |
182 | ; Pointer to the parent usb_pipe. |
- | |
183 | Buffer dd ? |
- | |
184 | ; Pointer to data for this descriptor. |
- | |
185 | Length dd ? |
- | |
186 | ; Length of data for this descriptor. |
- | |
187 | ends |
- | |
188 | - | ||
189 | ; ============================================================================= |
- | |
190 | ; =================================== Code ==================================== |
- | |
191 | ; ============================================================================= |
- | |
192 | - | ||
193 | USB_STDCALL_VERIFY = 1 |
3 | USB_STDCALL_VERIFY = 1 |
194 | macro stdcall_verify [arg] |
4 | macro stdcall_verify [arg] |
195 | { |
5 | { |
196 | common |
6 | common |
197 | if USB_STDCALL_VERIFY |
7 | if USB_STDCALL_VERIFY |
Line 214... | Line 24... | ||
214 | 24 | ||
215 | ; Part of API for drivers, see documentation for USBOpenPipe. |
25 | ; Part of API for drivers, see documentation for USBOpenPipe. |
216 | proc usb_open_pipe stdcall uses ebx esi edi,\ |
26 | proc usb_open_pipe stdcall uses ebx esi edi,\ |
217 | config_pipe:dword, endpoint:dword, maxpacket:dword, type:dword, interval:dword |
27 | config_pipe:dword, endpoint:dword, maxpacket:dword, type:dword, interval:dword |
218 | locals |
28 | locals |
219 | tt_vars rd (ehci_select_tt_interrupt_list.local_vars_size + 3) / 4 |
29 | tt_vars rd 24 ; should be enough for ehci_select_tt_interrupt_list |
220 | targetsmask dd ? ; S-Mask for USB2 |
30 | targetsmask dd ? ; S-Mask for USB2 |
221 | bandwidth dd ? |
31 | bandwidth dd ? |
222 | target dd ? |
32 | target dd ? |
223 | endl |
33 | endl |
Line 808... | Line 618... | ||
808 | mov [eax+usb_gtd.NextVirt], edx |
618 | mov [eax+usb_gtd.NextVirt], edx |
809 | call mutex_unlock |
619 | call mutex_unlock |
810 | ret |
620 | ret |
811 | endp |
621 | endp |
Line -... | Line 622... | ||
- | 622 | ||
- | 623 | ; One part of transfer is completed, run the associated callback |
|
- | 624 | ; or update total length in the next part of transfer. |
|
- | 625 | ; in: ebx -> usb_gtd, ecx = status, edx = length |
|
- | 626 | proc usb_process_gtd |
|
- | 627 | ; 1. Test whether it is the last descriptor in the transfer |
|
- | 628 | ; <=> it has an associated callback. |
|
- | 629 | mov eax, [ebx+usb_gtd.Callback] |
|
- | 630 | test eax, eax |
|
- | 631 | jz .nocallback |
|
- | 632 | ; 2. It has an associated callback; call it with corresponding parameters. |
|
- | 633 | stdcall_verify eax, [ebx+usb_gtd.Pipe], ecx, \ |
|
- | 634 | [ebx+usb_gtd.Buffer], edx, [ebx+usb_gtd.UserData] |
|
- | 635 | ret |
|
- | 636 | .nocallback: |
|
- | 637 | ; 3. It is an intermediate descriptor. Add its length to the length |
|
- | 638 | ; in the following descriptor. |
|
- | 639 | mov eax, [ebx+usb_gtd.NextVirt] |
|
- | 640 | add [eax+usb_gtd.Length], edx |
|
- | 641 | ret |
|
- | 642 | endp |
|
812 | 643 | ||
813 | if USB_STDCALL_VERIFY |
644 | if USB_STDCALL_VERIFY |
814 | proc verify_regs |
645 | proc verify_regs |
815 | virtual at esp |
646 | virtual at esp |
816 | dd ? ; return address |
647 | dd ? ; return address |