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.
7 * Michael Martin (mjmartin@reactos.org)
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
;
86 (*CtrlTD2
)->BufferPointer
[0] = 0;
88 (*CtrlTD2
)->BufferPointer
[0] = (ULONG
)MmGetPhysicalAddress((PVOID
) (*CtrlData
)).LowPart
;
89 (*CtrlTD2
)->Token
.Bits
.DataToggle
= TRUE
;
90 (*CtrlTD2
)->Token
.Bits
.InterruptOnComplete
= TRUE
;
91 (*CtrlTD2
)->Token
.Bits
.TotalBytesToTransfer
= Size
;
92 (*CtrlTD2
)->Token
.Bits
.ErrorCounter
= 0x03;
93 (*CtrlTD2
)->Token
.Bits
.PIDCode
= PID_CODE_IN_TOKEN
;
94 (*CtrlTD2
)->Token
.Bits
.Active
= TRUE
;
96 (*CtrlTD1
)->NextPointer
= (ULONG
)MmGetPhysicalAddress((PVOID
)(*CtrlTD2
)).LowPart
;
98 (*CtrlTD3
)->NextPointer
= TERMINATE_POINTER
;
99 (*CtrlTD3
)->AlternateNextPointer
= TERMINATE_POINTER
;
100 (*CtrlTD3
)->BufferPointer
[0] = 0;
101 (*CtrlTD3
)->Token
.Bits
.Active
= TRUE
;
102 (*CtrlTD3
)->Token
.Bits
.PIDCode
= PID_CODE_OUT_TOKEN
;
103 (*CtrlTD3
)->Token
.Bits
.InterruptOnComplete
= TRUE
;
104 (*CtrlTD3
)->Token
.Bits
.TotalBytesToTransfer
= 0;
105 (*CtrlTD3
)->Token
.Bits
.DataToggle
= TRUE
;
106 (*CtrlTD3
)->Token
.Bits
.ErrorCounter
= 0x03;
107 (*CtrlTD2
)->NextPointer
= (ULONG
) MmGetPhysicalAddress((PVOID
)(*CtrlTD3
)).LowPart
;
112 ExecuteControlRequest(PFDO_DEVICE_EXTENSION DeviceExtension
, PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
, UCHAR Address
, ULONG Port
, PVOID Buffer
, ULONG BufferLength
)
114 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
= NULL
;
115 PVOID CtrlData
= NULL
;
116 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD1
= NULL
;
117 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD2
= NULL
;
118 PQUEUE_TRANSFER_DESCRIPTOR CtrlTD3
= NULL
;
120 PQUEUE_HEAD QueueHead
;
121 PEHCI_USBCMD_CONTENT UsbCmd
;
122 PEHCI_USBSTS_CONTEXT UsbSts
;
126 DPRINT1("ExecuteControlRequest: Buffer %x, Length %x\n", Buffer
, BufferLength
);
128 Base
= (ULONG
) DeviceExtension
->ResourceMemory
;
130 /* Set up the QUEUE HEAD in memory */
131 QueueHead
= (PQUEUE_HEAD
) ((ULONG
)DeviceExtension
->AsyncListQueueHeadPtr
);
133 /* Initialize the memory pointers */
134 IntializeHeadQueueForStandardRequest(QueueHead
,
142 QueueHead
->EndPointCapabilities2
.PortNumber
= Port
;
143 QueueHead
->EndPointCapabilities1
.DeviceAddress
= Address
;
145 CtrlSetup
->bmRequestType
._BM
.Recipient
= SetupPacket
->bmRequestType
._BM
.Recipient
;
146 CtrlSetup
->bmRequestType
._BM
.Type
= SetupPacket
->bmRequestType
._BM
.Type
;
147 CtrlSetup
->bmRequestType
._BM
.Dir
= SetupPacket
->bmRequestType
._BM
.Dir
;
148 CtrlSetup
->bRequest
= SetupPacket
->bRequest
;
149 CtrlSetup
->wValue
.LowByte
= SetupPacket
->wValue
.LowByte
;
150 CtrlSetup
->wValue
.HiByte
= SetupPacket
->wValue
.HiByte
;
151 CtrlSetup
->wIndex
.W
= SetupPacket
->wIndex
.W
;
152 CtrlSetup
->wLength
= SetupPacket
->wLength
;
154 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
155 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
157 WRITE_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
), tmp
);
159 /* Wait for the controller to halt */
162 KeStallExecutionProcessor(10);
163 tmp
= READ_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBSTS
));
164 UsbSts
= (PEHCI_USBSTS_CONTEXT
)&tmp
;
165 DPRINT("Waiting for Halt, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG
)(Base
+ EHCI_USBSTS
)));
166 if (UsbSts
->HCHalted
)
172 /* Set to TRUE on interrupt for async completion */
173 DeviceExtension
->AsyncComplete
= FALSE
;
174 QueueHead
->QETDPointer
= (ULONG
) MmGetPhysicalAddress((PVOID
)(CtrlTD1
)).LowPart
;
176 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
177 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
178 UsbCmd
->AsyncEnable
= TRUE
;
180 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
182 tmp
= READ_REGISTER_ULONG((PULONG
) (Base
+ EHCI_USBCMD
));
183 UsbCmd
= (PEHCI_USBCMD_CONTENT
) &tmp
;
185 /* Interrupt on Async completion */
186 UsbCmd
->DoorBell
= TRUE
;
188 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
192 KeStallExecutionProcessor(100);
193 DPRINT("Waiting for completion!\n");
194 if (DeviceExtension
->AsyncComplete
== TRUE
)
199 WRITE_REGISTER_ULONG((PULONG
)(Base
+ EHCI_USBCMD
), tmp
);
201 if (CtrlSetup
->bmRequestType
._BM
.Dir
== BMREQUEST_DEVICE_TO_HOST
)
203 if ((Buffer
) && (BufferLength
))
205 RtlCopyMemory(Buffer
, CtrlData
, BufferLength
);
208 DPRINT1("Unable to copy data to buffer\n");