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 PUSB_DEFAULT_PIPE_SETUP_PACKET
*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
= (PUSB_DEFAULT_PIPE_SETUP_PACKET
) (( (ULONG
)(*CtrlTD3
) + sizeof(QUEUE_TRANSFER_DESCRIPTOR
) + 0xFFF) & ~0xFFF);
71 *CtrlData
= (PVOID
) (( (ULONG
)(*CtrlSetup
) + sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
) + 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(USB_DEFAULT_PIPE_SETUP_PACKET
);
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 ExecuteControlRequest(PFDO_DEVICE_EXTENSION DeviceExtension
, PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
, UCHAR Address
, ULONG Port
, PVOID Buffer
, ULONG BufferLength
)
110 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
= NULL
;
111 PVOID CtrlData
= NULL
;
112 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD1
= NULL
;
113 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD2
= NULL
;
114 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD3
= NULL
;
116 PQUEUE_HEAD QueueHead
;
117 PEHCI_USBCMD_CONTENT UsbCmd
;
118 PEHCI_USBSTS_CONTEXT UsbSts
;
122 DPRINT1("ExecuteControlRequest: Buffer %x, Length %x\n", Buffer
, BufferLength
);
124 Base
= (ULONG
) DeviceExtension
->ResourceMemory
;
126 /* Set up the QUEUE HEAD in memory */
127 QueueHead
= (PQUEUE_HEAD
) ((ULONG
)DeviceExtension
->AsyncListQueueHeadPtr
);
129 /* Initialize the memory pointers */
130 IntializeHeadQueueForStandardRequest(QueueHead
,
138 CtrlSetup
->bmRequestType
._BM
.Recipient
= SetupPacket
->bmRequestType
._BM
.Recipient
;
139 CtrlSetup
->bmRequestType
._BM
.Type
= SetupPacket
->bmRequestType
._BM
.Type
;
140 CtrlSetup
->bmRequestType
._BM
.Dir
= SetupPacket
->bmRequestType
._BM
.Dir
;
141 CtrlSetup
->bRequest
= SetupPacket
->bRequest
;
142 CtrlSetup
->wValue
.LowByte
= SetupPacket
->wValue
.LowByte
;
143 CtrlSetup
->wValue
.HiByte
= SetupPacket
->wValue
.HiByte
;
144 CtrlSetup
->wIndex
.W
= SetupPacket
->wIndex
.W
;
145 CtrlSetup
->wLength
= SetupPacket
->wLength
;
148 QueueHead
->EndPointCapabilities1
.DeviceAddress
= Address
;
149 //QueueHead->EndPointCapabilities2.PortNumber = Port;
151 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
152 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
154 WRITE_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
), tmp
);
156 /* Wait for the controller to halt */
159 KeStallExecutionProcessor(10);
160 tmp
= READ_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBSTS
));
161 UsbSts
= (PEHCI_USBSTS_CONTEXT
)&tmp
;
162 DPRINT("Waiting for Halt, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG
)(Base
+ EHCI_USBSTS
)));
163 if (UsbSts
->HCHalted
)
169 /* Set to TRUE on interrupt for async completion */
170 DeviceExtension
->AsyncComplete
= FALSE
;
171 QueueHead
->QETDPointer
= (ULONG
) MmGetPhysicalAddress((PVOID
)(CtrlTD1
)).LowPart
;
173 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
174 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
175 UsbCmd
->AsyncEnable
= TRUE
;
177 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
179 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
180 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
182 /* Interrupt on Async completion */
183 UsbCmd
->DoorBell
= TRUE
;
185 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
189 KeStallExecutionProcessor(10);
190 DPRINT("Waiting for completion!\n");
191 if (DeviceExtension
->AsyncComplete
== TRUE
)
195 if (CtrlSetup
->bmRequestType
._BM
.Dir
== BMREQUEST_DEVICE_TO_HOST
)
197 if ((Buffer
) && (BufferLength
))
199 RtlCopyMemory(Buffer
, CtrlData
, BufferLength
);
202 DPRINT1("Unable to copy data to buffer\n");