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.
12 /* QueueHead must point to the base address in common buffer */
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
,
22 QueueHead
->HorizontalLinkPointer
= (ULONG
)QueueHead
| QH_TYPE_QH
;
24 /* Set NakCountReload to max value possible */
25 QueueHead
->EndPointCapabilities1
.NakCountReload
= 0xF;
27 /* 1 for non high speed, 0 for high speed device */
28 QueueHead
->EndPointCapabilities1
.ControlEndPointFlag
= 0;
30 QueueHead
->EndPointCapabilities1
.HeadOfReclamation
= TRUE
;
31 QueueHead
->EndPointCapabilities1
.MaximumPacketLength
= 64;
33 /* Get the Initial Data Toggle from the QEDT */
34 QueueHead
->EndPointCapabilities1
.QEDTDataToggleControl
= TRUE
;
36 /* HIGH SPEED DEVICE */
37 QueueHead
->EndPointCapabilities1
.EndPointSpeed
= QH_ENDPOINT_HIGHSPEED
;
38 QueueHead
->EndPointCapabilities1
.EndPointNumber
= 0;
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;
44 QueueHead
->EndPointCapabilities1
.DeviceAddress
= 0;
45 QueueHead
->EndPointCapabilities2
.HubAddr
= 0;
46 QueueHead
->EndPointCapabilities2
.NumberOfTransactionPerFrame
= 0x01;
48 /* 0 For Async, 1 for periodoc schedule */
49 QueueHead
->EndPointCapabilities2
.InterruptScheduleMask
= 0;
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 */
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);
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);
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
;
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
;
93 (*CtrlTD1
)->NextPointer
= (ULONG
)MmGetPhysicalAddress((PVOID
)(*CtrlTD2
)).LowPart
;
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
;
108 GetDeviceDescriptor(PFDO_DEVICE_EXTENSION DeviceExtension
, UCHAR Index
, PUSB_DEVICE_DESCRIPTOR OutBuffer
, BOOLEAN Hub
)
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
;
121 Base
= (ULONG
) DeviceExtension
->ResourceMemory
;
123 /* Set up the QUEUE HEAD in memory */
124 QueueHead
= (PQUEUE_HEAD
) ((ULONG
)DeviceExtension
->AsyncListQueueHeadPtr
);
126 IntializeHeadQueueForStandardRequest(QueueHead
,
132 sizeof(USB_DEVICE_DESCRIPTOR
));
134 /* FIXME: Use defines and handle other than Device Desciptors */
137 CtrlSetup
->bmRequestType
= 0x80;
138 CtrlSetup
->wValue
= 0x0600;
142 CtrlSetup
->bmRequestType
= 0x80;
143 CtrlSetup
->wValue
= 0x0100;
145 CtrlSetup
->bRequest
= 0x06;
146 CtrlSetup
->wIndex
= 0;
147 CtrlSetup
->wLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
149 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
150 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
152 WRITE_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
), tmp
);
154 /* Wait for the controller to halt */
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
)
167 /* Set to TRUE on interrupt for async completion */
168 DeviceExtension
->AsyncComplete
= FALSE
;
169 QueueHead
->QETDPointer
= (ULONG
) MmGetPhysicalAddress((PVOID
)(CtrlTD1
)).LowPart
;
171 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
172 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
173 UsbCmd
->AsyncEnable
= TRUE
;
175 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
177 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
178 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
180 /* Interrupt on Async completion */
181 UsbCmd
->DoorBell
= TRUE
;
183 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
187 KeStallExecutionProcessor(10);
188 DPRINT("Waiting for completion!\n");
189 if (DeviceExtension
->AsyncComplete
== TRUE
)
193 if (OutBuffer
!= NULL
)
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
;
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
);
226 /* Temporary: Remove */
227 if (CtrlData
->bLength
> 0)
229 /* We got valid data, try for strings */
230 UCHAR Manufacturer
= CtrlData
->iManufacturer
;
231 UCHAR Product
= CtrlData
->iProduct
;
232 UCHAR SerialNumber
= CtrlData
->iSerialNumber
;
234 GetDeviceStringDescriptor(DeviceExtension
, Manufacturer
);
235 GetDeviceStringDescriptor(DeviceExtension
, Product
);
236 GetDeviceStringDescriptor(DeviceExtension
, SerialNumber
);
243 GetDeviceStringDescriptor(PFDO_DEVICE_EXTENSION DeviceExtension
, UCHAR Index
)
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
;
256 Base
= (ULONG
) DeviceExtension
->ResourceMemory
;
258 /* Set up the QUEUE HEAD in memory */
259 QueueHead
= (PQUEUE_HEAD
) ((ULONG
)DeviceExtension
->AsyncListQueueHeadPtr
);
261 IntializeHeadQueueForStandardRequest(QueueHead
,
267 sizeof(STRING_DESCRIPTOR
) + 256);
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;
277 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
278 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
280 WRITE_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
), tmp
);
282 /* Wait for the controller to halt */
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
)
295 /* Set to TRUE on interrupt for async completion */
296 DeviceExtension
->AsyncComplete
= FALSE
;
297 QueueHead
->QETDPointer
= (ULONG
) MmGetPhysicalAddress((PVOID
)(CtrlTD1
)).LowPart
;
299 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
300 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
301 UsbCmd
->AsyncEnable
= TRUE
;
303 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
305 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
306 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
308 /* Interrupt on Async completion */
309 UsbCmd
->DoorBell
= TRUE
;
311 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
315 KeStallExecutionProcessor(10);
316 DPRINT("Waiting for completion!\n");
317 if (DeviceExtension
->AsyncComplete
== TRUE
)
321 DPRINT1("String %S\n", &CtrlData
->bString
);