Revert the sync.
[reactos.git] / drivers / usb / usbehci / urbreq.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbehci/urbreq.c
5 * PURPOSE: URB Related Functions.
6 * PROGRAMMERS:
7 * Michael Martin
8 */
9
10 #include "usbehci.h"
11
12 /* QueueHead must point to the base address in common buffer */
13 PVOID
14 IntializeHeadQueueForStandardRequest(PQUEUE_HEAD QueueHead,
15 PQUEUE_TRANSFER_DESCRIPTOR *CtrlTD1,
16 PQUEUE_TRANSFER_DESCRIPTOR *CtrlTD2,
17 PQUEUE_TRANSFER_DESCRIPTOR *CtrlTD3,
18 PEHCI_SETUP_FORMAT *CtrlSetup,
19 PVOID *CtrlData,
20 ULONG Size)
21 {
22 QueueHead->HorizontalLinkPointer = (ULONG)QueueHead | QH_TYPE_QH;
23
24 /* Set NakCountReload to max value possible */
25 QueueHead->EndPointCapabilities1.NakCountReload = 0xF;
26
27 /* 1 for non high speed, 0 for high speed device */
28 QueueHead->EndPointCapabilities1.ControlEndPointFlag = 0;
29
30 QueueHead->EndPointCapabilities1.HeadOfReclamation = TRUE;
31 QueueHead->EndPointCapabilities1.MaximumPacketLength = 64;
32
33 /* Get the Initial Data Toggle from the QEDT */
34 QueueHead->EndPointCapabilities1.QEDTDataToggleControl = TRUE;
35
36 /* HIGH SPEED DEVICE */
37 QueueHead->EndPointCapabilities1.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
38 QueueHead->EndPointCapabilities1.EndPointNumber = 0;
39
40 /* Only used for Periodic Schedule and Not High Speed devices.
41 Setting it to one result in undefined behavior for Async */
42 QueueHead->EndPointCapabilities1.InactiveOnNextTransaction = 0;
43
44 QueueHead->EndPointCapabilities1.DeviceAddress = 0;
45 QueueHead->EndPointCapabilities2.HubAddr = 0;
46 QueueHead->EndPointCapabilities2.NumberOfTransactionPerFrame = 0x01;
47
48 /* 0 For Async, 1 for periodoc schedule */
49 QueueHead->EndPointCapabilities2.InterruptScheduleMask = 0;
50
51 QueueHead->EndPointCapabilities2.PortNumber = 0;
52 QueueHead->EndPointCapabilities2.SplitCompletionMask = 0;
53 QueueHead->CurrentLinkPointer = 0;
54 QueueHead->QETDPointer = TERMINATE_POINTER;
55 QueueHead->AlternateNextPointer = TERMINATE_POINTER;
56 QueueHead->Token.Bits.InterruptOnComplete = TRUE;
57 QueueHead->BufferPointer[0] = 0;
58 QueueHead->BufferPointer[1] = 0;
59 QueueHead->BufferPointer[2] = 0;
60 QueueHead->BufferPointer[3] = 0;
61 QueueHead->BufferPointer[4] = 0;
62 /* Queue Head Initialized */
63
64 /* Queue Transfer Descriptors must be 32 byte aligned and reside in continous physical memory */
65 *CtrlTD1 = (PQUEUE_TRANSFER_DESCRIPTOR) (((ULONG)(QueueHead) + sizeof(QUEUE_HEAD) + 0x1F) & ~0x1F);
66 *CtrlTD2 = (PQUEUE_TRANSFER_DESCRIPTOR) (((ULONG)(*CtrlTD1) + sizeof(QUEUE_TRANSFER_DESCRIPTOR) + 0x1F) & ~0x1F);
67 *CtrlTD3 = (PQUEUE_TRANSFER_DESCRIPTOR) (((ULONG)(*CtrlTD2) + sizeof(QUEUE_TRANSFER_DESCRIPTOR) + 0x1F) & ~0x1F);
68
69 /* Must be Page aligned */
70 *CtrlSetup = (PEHCI_SETUP_FORMAT) (( (ULONG)(*CtrlTD3) + sizeof(QUEUE_TRANSFER_DESCRIPTOR) + 0xFFF) & ~0xFFF);
71 *CtrlData = (PUSB_DEVICE_DESCRIPTOR) (( (ULONG)(*CtrlSetup) + sizeof(EHCI_SETUP_FORMAT) + 0xFFF) & ~0xFFF);
72
73 (*CtrlTD1)->NextPointer = TERMINATE_POINTER;
74 (*CtrlTD1)->AlternateNextPointer = TERMINATE_POINTER;
75 (*CtrlTD1)->BufferPointer[0] = (ULONG)MmGetPhysicalAddress((PVOID) (*CtrlSetup)).LowPart;
76 (*CtrlTD1)->Token.Bits.DataToggle = FALSE;
77 (*CtrlTD1)->Token.Bits.InterruptOnComplete = FALSE;
78 (*CtrlTD1)->Token.Bits.TotalBytesToTransfer = sizeof(EHCI_SETUP_FORMAT);
79 (*CtrlTD1)->Token.Bits.ErrorCounter = 0x03;
80 (*CtrlTD1)->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN;
81 (*CtrlTD1)->Token.Bits.Active = TRUE;
82
83 (*CtrlTD2)->NextPointer = TERMINATE_POINTER;
84 (*CtrlTD2)->AlternateNextPointer = TERMINATE_POINTER;
85 (*CtrlTD2)->BufferPointer[0] = (ULONG)MmGetPhysicalAddress((PVOID) (*CtrlData)).LowPart;
86 (*CtrlTD2)->Token.Bits.DataToggle = TRUE;
87 (*CtrlTD2)->Token.Bits.InterruptOnComplete = TRUE;
88 (*CtrlTD2)->Token.Bits.TotalBytesToTransfer = Size;
89 (*CtrlTD2)->Token.Bits.ErrorCounter = 0x03;
90 (*CtrlTD2)->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
91 (*CtrlTD2)->Token.Bits.Active = TRUE;
92
93 (*CtrlTD1)->NextPointer = (ULONG)MmGetPhysicalAddress((PVOID)(*CtrlTD2)).LowPart;
94
95 (*CtrlTD3)->NextPointer = TERMINATE_POINTER;
96 (*CtrlTD3)->AlternateNextPointer = TERMINATE_POINTER;
97 (*CtrlTD3)->BufferPointer[0] = 0;
98 (*CtrlTD3)->Token.Bits.Active = TRUE;
99 (*CtrlTD3)->Token.Bits.PIDCode = PID_CODE_OUT_TOKEN;
100 (*CtrlTD3)->Token.Bits.InterruptOnComplete = TRUE;
101 (*CtrlTD3)->Token.Bits.DataToggle = TRUE;
102 (*CtrlTD3)->Token.Bits.ErrorCounter = 0x03;
103 (*CtrlTD2)->NextPointer = (ULONG) MmGetPhysicalAddress((PVOID)(*CtrlTD3)).LowPart;
104 return NULL;
105 }
106
107 BOOLEAN
108 GetDeviceDescriptor(PFDO_DEVICE_EXTENSION DeviceExtension, UCHAR Index, PUSB_DEVICE_DESCRIPTOR OutBuffer, BOOLEAN Hub)
109 {
110 PEHCI_SETUP_FORMAT CtrlSetup = NULL;
111 PUSB_DEVICE_DESCRIPTOR CtrlData = NULL;
112 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD1 = NULL;
113 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD2 = NULL;
114 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD3 = NULL;
115 PQUEUE_HEAD QueueHead;
116 PEHCI_USBCMD_CONTENT UsbCmd;
117 PEHCI_USBSTS_CONTEXT UsbSts;
118 LONG Base;
119 LONG tmp;
120
121 Base = (ULONG) DeviceExtension->ResourceMemory;
122
123 /* Set up the QUEUE HEAD in memory */
124 QueueHead = (PQUEUE_HEAD) ((ULONG)DeviceExtension->AsyncListQueueHeadPtr);
125
126 IntializeHeadQueueForStandardRequest(QueueHead,
127 &CtrlTD1,
128 &CtrlTD2,
129 &CtrlTD3,
130 &CtrlSetup,
131 (PVOID)&CtrlData,
132 sizeof(USB_DEVICE_DESCRIPTOR));
133
134 /* FIXME: Use defines and handle other than Device Desciptors */
135 if (Hub)
136 {
137 CtrlSetup->bmRequestType = 0x80;
138 CtrlSetup->wValue = 0x0600;
139 }
140 else
141 {
142 CtrlSetup->bmRequestType = 0x80;
143 CtrlSetup->wValue = 0x0100;
144 }
145 CtrlSetup->bRequest = 0x06;
146 CtrlSetup->wIndex = 0;
147 CtrlSetup->wLength = sizeof(USB_DEVICE_DESCRIPTOR);
148
149 tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
150 UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
151 UsbCmd->Run = FALSE;
152 WRITE_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD), tmp);
153
154 /* Wait for the controller to halt */
155 for (;;)
156 {
157 KeStallExecutionProcessor(10);
158 tmp = READ_REGISTER_ULONG((PULONG)(Base + EHCI_USBSTS));
159 UsbSts = (PEHCI_USBSTS_CONTEXT)&tmp;
160 DPRINT("Waiting for Halt, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG)(Base + EHCI_USBSTS)));
161 if (UsbSts->HCHalted)
162 {
163 break;
164 }
165 }
166
167 /* Set to TRUE on interrupt for async completion */
168 DeviceExtension->AsyncComplete = FALSE;
169 QueueHead->QETDPointer = (ULONG) MmGetPhysicalAddress((PVOID)(CtrlTD1)).LowPart;
170
171 tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
172 UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
173 UsbCmd->AsyncEnable = TRUE;
174
175 WRITE_REGISTER_ULONG((PULONG)(Base + EHCI_USBCMD), tmp);
176
177 tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
178 UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
179
180 /* Interrupt on Async completion */
181 UsbCmd->DoorBell = TRUE;
182 UsbCmd->Run = TRUE;
183 WRITE_REGISTER_ULONG((PULONG)(Base + EHCI_USBCMD), tmp);
184
185 for (;;)
186 {
187 KeStallExecutionProcessor(10);
188 DPRINT("Waiting for completion!\n");
189 if (DeviceExtension->AsyncComplete == TRUE)
190 break;
191 }
192
193 if (OutBuffer != NULL)
194 {
195 OutBuffer->bLength = CtrlData->bLength;
196 OutBuffer->bDescriptorType = CtrlData->bDescriptorType;
197 OutBuffer->bcdUSB = CtrlData->bcdUSB;
198 OutBuffer->bDeviceClass = CtrlData->bDeviceClass;
199 OutBuffer->bDeviceSubClass = CtrlData->bDeviceSubClass;
200 OutBuffer->bDeviceProtocol = CtrlData->bDeviceProtocol;
201 OutBuffer->bMaxPacketSize0 = CtrlData->bMaxPacketSize0;
202 OutBuffer->idVendor = CtrlData->idVendor;
203 OutBuffer->idProduct = CtrlData->idProduct;
204 OutBuffer->bcdDevice = CtrlData->bcdDevice;
205 OutBuffer->iManufacturer = CtrlData->iManufacturer;
206 OutBuffer->iProduct = CtrlData->iProduct;
207 OutBuffer->iSerialNumber = CtrlData->iSerialNumber;
208 OutBuffer->bNumConfigurations = CtrlData->bNumConfigurations;
209 }
210
211 DPRINT1("bLength %d\n", CtrlData->bLength);
212 DPRINT1("bDescriptorType %x\n", CtrlData->bDescriptorType);
213 DPRINT1("bcdUSB %x\n", CtrlData->bcdUSB);
214 DPRINT1("CtrlData->bDeviceClass %x\n", CtrlData->bDeviceClass);
215 DPRINT1("CtrlData->bDeviceSubClass %x\n", CtrlData->bDeviceSubClass);
216 DPRINT1("CtrlData->bDeviceProtocal %x\n", CtrlData->bDeviceProtocol);
217 DPRINT1("CtrlData->bMaxPacketSize %x\n", CtrlData->bMaxPacketSize0);
218 DPRINT1("CtrlData->idVendor %x\n", CtrlData->idVendor);
219 DPRINT1("CtrlData->idProduct %x\n", CtrlData->idProduct);
220 DPRINT1("CtrlData->bcdDevice %x\n", CtrlData->bcdDevice);
221 DPRINT1("CtrlData->iManufacturer %x\n", CtrlData->iManufacturer);
222 DPRINT1("CtrlData->iProduct %x\n", CtrlData->iProduct);
223 DPRINT1("CtrlData->iSerialNumber %x\n", CtrlData->iSerialNumber);
224 DPRINT1("CtrlData->bNumConfigurations %x\n", CtrlData->bNumConfigurations);
225
226 /* Temporary: Remove */
227 if (CtrlData->bLength > 0)
228 {
229 /* We got valid data, try for strings */
230 UCHAR Manufacturer = CtrlData->iManufacturer;
231 UCHAR Product = CtrlData->iProduct;
232 UCHAR SerialNumber = CtrlData->iSerialNumber;
233
234 GetDeviceStringDescriptor(DeviceExtension, Manufacturer);
235 GetDeviceStringDescriptor(DeviceExtension, Product);
236 GetDeviceStringDescriptor(DeviceExtension, SerialNumber);
237 }
238
239 return TRUE;
240 }
241
242 BOOLEAN
243 GetDeviceStringDescriptor(PFDO_DEVICE_EXTENSION DeviceExtension, UCHAR Index)
244 {
245 PEHCI_SETUP_FORMAT CtrlSetup = NULL;
246 PSTRING_DESCRIPTOR CtrlData = NULL;
247 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD1 = NULL;
248 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD2 = NULL;
249 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD3 = NULL;
250 PQUEUE_HEAD QueueHead;
251 PEHCI_USBCMD_CONTENT UsbCmd;
252 PEHCI_USBSTS_CONTEXT UsbSts;
253 LONG Base;
254 LONG tmp;
255
256 Base = (ULONG) DeviceExtension->ResourceMemory;
257
258 /* Set up the QUEUE HEAD in memory */
259 QueueHead = (PQUEUE_HEAD) ((ULONG)DeviceExtension->AsyncListQueueHeadPtr);
260
261 IntializeHeadQueueForStandardRequest(QueueHead,
262 &CtrlTD1,
263 &CtrlTD2,
264 &CtrlTD3,
265 &CtrlSetup,
266 (PVOID)&CtrlData,
267 sizeof(STRING_DESCRIPTOR) + 256);
268
269 /* FIXME: Use defines and handle other than Device Desciptors */
270 CtrlSetup->bmRequestType = 0x80;
271 CtrlSetup->bRequest = 0x06;
272 CtrlSetup->wValue = 0x0300 | Index;
273 CtrlSetup->wIndex = 0;
274 /* 256 pulled from thin air */
275 CtrlSetup->wLength = sizeof(STRING_DESCRIPTOR) + 256;
276
277 tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
278 UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
279 UsbCmd->Run = FALSE;
280 WRITE_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD), tmp);
281
282 /* Wait for the controller to halt */
283 for (;;)
284 {
285 KeStallExecutionProcessor(10);
286 tmp = READ_REGISTER_ULONG((PULONG)(Base + EHCI_USBSTS));
287 UsbSts = (PEHCI_USBSTS_CONTEXT)&tmp;
288 DPRINT("Waiting for Halt, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG)(Base + EHCI_USBSTS)));
289 if (UsbSts->HCHalted)
290 {
291 break;
292 }
293 }
294
295 /* Set to TRUE on interrupt for async completion */
296 DeviceExtension->AsyncComplete = FALSE;
297 QueueHead->QETDPointer = (ULONG) MmGetPhysicalAddress((PVOID)(CtrlTD1)).LowPart;
298
299 tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
300 UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
301 UsbCmd->AsyncEnable = TRUE;
302
303 WRITE_REGISTER_ULONG((PULONG)(Base + EHCI_USBCMD), tmp);
304
305 tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
306 UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
307
308 /* Interrupt on Async completion */
309 UsbCmd->DoorBell = TRUE;
310 UsbCmd->Run = TRUE;
311 WRITE_REGISTER_ULONG((PULONG)(Base + EHCI_USBCMD), tmp);
312
313 for (;;)
314 {
315 KeStallExecutionProcessor(10);
316 DPRINT("Waiting for completion!\n");
317 if (DeviceExtension->AsyncComplete == TRUE)
318 break;
319 }
320
321 DPRINT1("String %S\n", &CtrlData->bString);
322
323 return TRUE;
324 }
325