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
= (PSTANDARD_DEVICE_DESC
) (( (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
)
110 PEHCI_SETUP_FORMAT CtrlSetup
= NULL
;
111 PSTANDARD_DEVICE_DESC 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(STANDARD_DEVICE_DESC
));
134 /* FIXME: Use defines and handle other than Device Desciptors */
135 CtrlSetup
->bmRequestType
= 0x80;
136 CtrlSetup
->bRequest
= 0x06;
137 CtrlSetup
->wValue
= 0x0100;
138 CtrlSetup
->wIndex
= 0;
139 CtrlSetup
->wLength
= sizeof(STANDARD_DEVICE_DESC
);
141 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
142 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
144 WRITE_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
), tmp
);
146 /* Wait for the controller to halt */
149 KeStallExecutionProcessor(10);
150 tmp
= READ_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBSTS
));
151 UsbSts
= (PEHCI_USBSTS_CONTEXT
)&tmp
;
152 DPRINT("Waiting for Halt, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG
)(Base
+ EHCI_USBSTS
)));
153 if (UsbSts
->HCHalted
)
159 /* Set to TRUE on interrupt for async completion */
160 DeviceExtension
->AsyncComplete
= FALSE
;
161 QueueHead
->QETDPointer
= (ULONG
) MmGetPhysicalAddress((PVOID
)(CtrlTD1
)).LowPart
;
163 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
164 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
165 UsbCmd
->AsyncEnable
= TRUE
;
167 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
169 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
170 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
172 /* Interrupt on Async completion */
173 UsbCmd
->DoorBell
= TRUE
;
175 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
179 KeStallExecutionProcessor(10);
180 DPRINT("Waiting for completion!\n");
181 if (DeviceExtension
->AsyncComplete
== TRUE
)
185 DPRINT1("bLength %d\n", CtrlData
->bLength
);
186 DPRINT1("bDescriptorType %x\n", CtrlData
->bDescriptorType
);
187 DPRINT1("bcdUSB %x\n", CtrlData
->bcdUSB
);
188 DPRINT1("CtrlData->bDeviceClass %x\n", CtrlData
->bDeviceClass
);
189 DPRINT1("CtrlData->bDeviceSubClass %x\n", CtrlData
->bDeviceSubClass
);
190 DPRINT1("CtrlData->bDeviceProtocal %x\n", CtrlData
->bDeviceProtocal
);
191 DPRINT1("CtrlData->bMaxPacketSize %x\n", CtrlData
->bMaxPacketSize
);
192 DPRINT1("CtrlData->idVendor %x\n", CtrlData
->idVendor
);
193 DPRINT1("CtrlData->idProduct %x\n", CtrlData
->idProduct
);
194 DPRINT1("CtrlData->bcdDevice %x\n", CtrlData
->bcdDevice
);
195 DPRINT1("CtrlData->iManufacturer %x\n", CtrlData
->iManufacturer
);
196 DPRINT1("CtrlData->iProduct %x\n", CtrlData
->iProduct
);
197 DPRINT1("CtrlData->iSerialNumber %x\n", CtrlData
->iSerialNumber
);
198 DPRINT1("CtrlData->bNumConfigurations %x\n", CtrlData
->bNumConfigurations
);
200 /* Temporary: Remove */
201 if (CtrlData
->bLength
> 0)
203 /* We got valid data, try for strings */
204 UCHAR Manufacturer
= CtrlData
->iManufacturer
;
205 UCHAR Product
= CtrlData
->iManufacturer
;
206 UCHAR SerialNumber
= CtrlData
->iSerialNumber
;
208 GetDeviceStringDescriptor(DeviceExtension
, Manufacturer
);
209 GetDeviceStringDescriptor(DeviceExtension
, Product
);
210 GetDeviceStringDescriptor(DeviceExtension
, SerialNumber
);
217 GetDeviceStringDescriptor(PFDO_DEVICE_EXTENSION DeviceExtension
, UCHAR Index
)
219 PEHCI_SETUP_FORMAT CtrlSetup
= NULL
;
220 PSTRING_DESCRIPTOR CtrlData
= NULL
;
221 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD1
= NULL
;
222 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD2
= NULL
;
223 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD3
= NULL
;
224 PQUEUE_HEAD QueueHead
;
225 PEHCI_USBCMD_CONTENT UsbCmd
;
226 PEHCI_USBSTS_CONTEXT UsbSts
;
230 Base
= (ULONG
) DeviceExtension
->ResourceMemory
;
231 DPRINT1("Index: %d\n", Index
);
232 /* Set up the QUEUE HEAD in memory */
233 QueueHead
= (PQUEUE_HEAD
) ((ULONG
)DeviceExtension
->AsyncListQueueHeadPtr
);
235 IntializeHeadQueueForStandardRequest(QueueHead
,
241 sizeof(STRING_DESCRIPTOR
) + 256);
243 /* FIXME: Use defines and handle other than Device Desciptors */
244 CtrlSetup
->bmRequestType
= 0x80;
245 CtrlSetup
->bRequest
= 0x06;
246 CtrlSetup
->wValue
= 0x0300 | Index
;
247 CtrlSetup
->wIndex
= 0;
248 /* 256 pulled from thin air */
249 CtrlSetup
->wLength
= sizeof(STRING_DESCRIPTOR
) + 256;
251 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
252 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
254 WRITE_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
), tmp
);
256 /* Wait for the controller to halt */
259 KeStallExecutionProcessor(10);
260 tmp
= READ_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBSTS
));
261 UsbSts
= (PEHCI_USBSTS_CONTEXT
)&tmp
;
262 DPRINT("Waiting for Halt, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG
)(Base
+ EHCI_USBSTS
)));
263 if (UsbSts
->HCHalted
)
269 /* Set to TRUE on interrupt for async completion */
270 DeviceExtension
->AsyncComplete
= FALSE
;
271 QueueHead
->QETDPointer
= (ULONG
) MmGetPhysicalAddress((PVOID
)(CtrlTD1
)).LowPart
;
273 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
274 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
275 UsbCmd
->AsyncEnable
= TRUE
;
277 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
279 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
280 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
282 /* Interrupt on Async completion */
283 UsbCmd
->DoorBell
= TRUE
;
285 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
289 KeStallExecutionProcessor(10);
290 DPRINT("Waiting for completion!\n");
291 if (DeviceExtension
->AsyncComplete
== TRUE
)
295 DPRINT1("String %S\n", &CtrlData
->bString
);