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/transfer.c
5 * PURPOSE: Transfers to EHCI.
7 * Michael Martin (michael.martin@reactos.org)
10 /* All QueueHeads, Descriptors and pipe setup packets used by control transfers are allocated from common buffer.
11 The routines in physmem manages this buffer. Each allocation is aligned to 32bits, which is requirement of USB 2.0. */
17 typedef struct _MAPREGISTERCALLBACKINFO
19 PVOID MapRegisterBase
;
21 }MAPREGISTERCALLBACKINFO
, *PMAPREGISTERCALLBACKINFO
;
23 /* Fills CtrlSetup parameter with values based on Urb */
25 BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd
, PURB Urb
, PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
)
27 switch (Urb
->UrbHeader
.Function
)
30 case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE
:
31 case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE
:
32 case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT
:
33 DPRINT1("Not implemented!\n");
37 case URB_FUNCTION_GET_CONFIGURATION
:
38 CtrlSetup
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
39 CtrlSetup
->bmRequestType
.B
= 0x80;
40 CtrlSetup
->wLength
= 1;
44 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
45 CtrlSetup
->bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
46 CtrlSetup
->wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
47 CtrlSetup
->wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
48 CtrlSetup
->wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
49 CtrlSetup
->wLength
= Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
50 CtrlSetup
->bmRequestType
.B
= 0x80;
54 case URB_FUNCTION_GET_INTERFACE
:
55 CtrlSetup
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
56 CtrlSetup
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
57 CtrlSetup
->bmRequestType
.B
= 0x80;
58 CtrlSetup
->wLength
= 1;
62 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
63 CtrlSetup
->bRequest
= USB_REQUEST_GET_STATUS
;
64 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
65 CtrlSetup
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
66 CtrlSetup
->bmRequestType
.B
= 0x80;
67 CtrlSetup
->wLength
= 2;
70 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
71 CtrlSetup
->bRequest
= USB_REQUEST_GET_STATUS
;
72 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
73 CtrlSetup
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
74 CtrlSetup
->bmRequestType
.B
= 0x81;
75 CtrlSetup
->wLength
= 2;
78 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
79 CtrlSetup
->bRequest
= USB_REQUEST_GET_STATUS
;
80 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
81 CtrlSetup
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
82 CtrlSetup
->bmRequestType
.B
= 0x82;
83 CtrlSetup
->wLength
= 2;
89 case URB_FUNCTION_SELECT_CONFIGURATION
:
90 DPRINT1("Bulding data for Select Config\n");
91 CtrlSetup
->bRequest
= USB_REQUEST_SET_CONFIGURATION
;
92 CtrlSetup
->wValue
.W
= Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
->bConfigurationValue
;
93 CtrlSetup
->wIndex
.W
= 0;
94 CtrlSetup
->wLength
= 0;
95 CtrlSetup
->bmRequestType
.B
= 0x00;
99 case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE
:
100 case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE
:
101 case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT
:
102 DPRINT1("Not implemented\n");
106 case URB_FUNCTION_SET_FEATURE_TO_DEVICE
:
107 CtrlSetup
->bRequest
= USB_REQUEST_SET_FEATURE
;
108 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
109 CtrlSetup
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
110 CtrlSetup
->bmRequestType
.B
= 0x80;
113 case URB_FUNCTION_SET_FEATURE_TO_INTERFACE
:
114 CtrlSetup
->bRequest
= USB_REQUEST_SET_FEATURE
;
115 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
116 CtrlSetup
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
117 CtrlSetup
->bmRequestType
.B
= 0x81;
120 case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT
:
121 CtrlSetup
->bRequest
= USB_REQUEST_SET_FEATURE
;
122 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
123 CtrlSetup
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
124 CtrlSetup
->bmRequestType
.B
= 0x82;
128 case URB_FUNCTION_SELECT_INTERFACE
:
129 CtrlSetup
->bRequest
= USB_REQUEST_SET_INTERFACE
;
130 CtrlSetup
->wValue
.W
= Urb
->UrbSelectInterface
.Interface
.AlternateSetting
;
131 CtrlSetup
->wIndex
.W
= Urb
->UrbSelectInterface
.Interface
.InterfaceNumber
;
132 CtrlSetup
->wLength
= 0;
133 CtrlSetup
->bmRequestType
.B
= 0x01;
137 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
138 DPRINT1("Not implemented\n");
141 DPRINT1("Unknown USB Request!\n");
146 /* Build a Bulk Transfer with a max transfer of 3 descriptors which each has 5 pointers to one page of memory, paged align of course */
148 BuildBulkTransfer(PEHCI_HOST_CONTROLLER hcd
,
150 USBD_PIPE_HANDLE PipeHandle
,
155 PQUEUE_HEAD QueueHead
;
156 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
[3];
157 ULONG MdlByteCount
= MmGetMdlByteCount(pMdl
);
158 ULONG NeededDescriptorCount
= 1;
161 QueueHead
= CreateQueueHead(hcd
);
162 QueueHead
->EndPointCharacteristics
.DeviceAddress
= DeviceAddress
;
166 QueueHead
->EndPointCharacteristics
.EndPointNumber
= ((PUSB_ENDPOINT_DESCRIPTOR
)PipeHandle
)->bEndpointAddress
& 0x0F;
167 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= ((PUSB_ENDPOINT_DESCRIPTOR
)PipeHandle
)->wMaxPacketSize
;
170 QueueHead
->FreeMdl
= FreeMdl
;
171 QueueHead
->Mdl
= pMdl
;
173 /* FIXME: This is totally screwed */
174 /* Calculate how many descriptors would be needed to transfer this buffer */
177 if (MdlByteCount
< (PAGE_SIZE
* 5))
178 NeededDescriptorCount
= 1;
179 else if (MdlByteCount
< (PAGE_SIZE
* 10))
180 NeededDescriptorCount
= 2;
181 else if (MdlByteCount
< (PAGE_SIZE
* 15))
182 NeededDescriptorCount
= 3;
186 /* Limiter Transfers to PAGE_SIZE * 5 * 3, Three Descriptors */
188 QueueHead
->NumberOfTransferDescriptors
= NeededDescriptorCount
;
189 for (i
=0; i
< NeededDescriptorCount
;i
++)
191 Descriptor
[i
] = CreateDescriptor(hcd
,
194 Descriptor
[i
]->AlternateNextPointer
= QueueHead
->DeadDescriptor
->PhysicalAddr
;
198 Descriptor
[i
-1]->NextDescriptor
= Descriptor
[i
];
199 Descriptor
[i
]->PreviousDescriptor
= Descriptor
[i
-1];
200 Descriptor
[i
-1]->NextPointer
= Descriptor
[i
]->PhysicalAddr
;
204 Descriptor
[0]->Token
.Bits
.InterruptOnComplete
= TRUE
;
206 /* Save the first descriptor in the QueueHead */
207 QueueHead
->FirstTransferDescriptor
= Descriptor
[0];
208 QueueHead
->NextPointer
= Descriptor
[0]->PhysicalAddr
;
214 /* Builds a QueueHead with 2 to 3 descriptors needed for control transfer
215 2 descriptors used for and control request that doesnt return data, such as SetAddress */
217 BuildControlTransfer(PEHCI_HOST_CONTROLLER hcd
,
219 USBD_PIPE_HANDLE PipeHandle
,
220 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
,
224 PQUEUE_HEAD QueueHead
;
225 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
[3];
226 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetupVA
, CtrlPhysicalPA
;
228 CtrlSetupVA
= (PUSB_DEFAULT_PIPE_SETUP_PACKET
)AllocateMemory(hcd
,
229 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
),
230 (ULONG
*)&CtrlPhysicalPA
);
232 RtlCopyMemory(CtrlSetupVA
, CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
234 QueueHead
= CreateQueueHead(hcd
);
235 QueueHead
->EndPointCharacteristics
.DeviceAddress
= DeviceAddress
;
237 QueueHead
->EndPointCharacteristics
.EndPointNumber
= ((PUSB_ENDPOINT_DESCRIPTOR
)PipeHandle
)->bEndpointAddress
& 0x0F;
239 QueueHead
->Token
.Bits
.DataToggle
= TRUE
;
240 QueueHead
->FreeMdl
= FreeMdl
;
241 QueueHead
->Mdl
= pMdl
;
243 Descriptor
[0] = CreateDescriptor(hcd
,
244 PID_CODE_SETUP_TOKEN
,
245 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
247 Descriptor
[0]->Token
.Bits
.DataToggle
= FALSE
;
248 /* Save the first descriptor */
249 QueueHead
->FirstTransferDescriptor
= Descriptor
[0];
253 Descriptor
[1] = CreateDescriptor(hcd
,
255 MmGetMdlByteCount(pMdl
));
257 Descriptor
[2] = CreateDescriptor(hcd
,
263 Descriptor
[2] = CreateDescriptor(hcd
,
268 Descriptor
[2]->Token
.Bits
.InterruptOnComplete
= TRUE
;
270 /* Link the descriptors */
273 Descriptor
[0]->NextDescriptor
= Descriptor
[1];
274 Descriptor
[1]->NextDescriptor
= Descriptor
[2];
275 Descriptor
[1]->PreviousDescriptor
= Descriptor
[0];
276 Descriptor
[2]->PreviousDescriptor
= Descriptor
[1];
280 Descriptor
[0]->NextDescriptor
= Descriptor
[2];
281 Descriptor
[2]->PreviousDescriptor
= Descriptor
[0];
284 /* Assign the descriptor buffers */
285 Descriptor
[0]->BufferPointer
[0] = (ULONG
)CtrlPhysicalPA
;
286 Descriptor
[0]->BufferPointerVA
[0] = (ULONG
)CtrlSetupVA
;
290 Descriptor
[0]->NextPointer
= Descriptor
[1]->PhysicalAddr
;
291 Descriptor
[0]->AlternateNextPointer
= Descriptor
[2]->PhysicalAddr
;
292 Descriptor
[1]->NextPointer
= Descriptor
[2]->PhysicalAddr
;
293 Descriptor
[1]->AlternateNextPointer
= Descriptor
[2]->PhysicalAddr
;
297 Descriptor
[0]->NextPointer
= Descriptor
[2]->PhysicalAddr
;
298 Descriptor
[0]->AlternateNextPointer
= Descriptor
[2]->PhysicalAddr
;
301 QueueHead
->NextPointer
= Descriptor
[0]->PhysicalAddr
;
303 QueueHead
->NumberOfTransferDescriptors
= 3;
305 QueueHead
->NumberOfTransferDescriptors
= 2;
310 IO_ALLOCATION_ACTION NTAPI
MapRegisterCallBack(PDEVICE_OBJECT DeviceObject
,
312 PVOID MapRegisterBase
,
315 PMAPREGISTERCALLBACKINFO CallBackInfo
= (PMAPREGISTERCALLBACKINFO
)Context
;
317 CallBackInfo
->MapRegisterBase
= MapRegisterBase
;
319 KeSetEvent(&CallBackInfo
->Event
, IO_NO_INCREMENT
, FALSE
);
325 ExecuteTransfer(PDEVICE_OBJECT DeviceObject
,
326 PUSB_DEVICE UsbDevice
,
327 USBD_PIPE_HANDLE PipeHandle
,
328 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
,
330 PVOID TransferBufferOrMdl
,
331 ULONG TransferBufferLength
,
334 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc
= NULL
;
335 PEHCI_HOST_CONTROLLER hcd
;
336 PQUEUE_HEAD QueueHead
;
337 PKEVENT CompleteEvent
= NULL
;
338 PMAPREGISTERCALLBACKINFO CallBackInfo
;
339 LARGE_INTEGER TimeOut
;
341 BOOLEAN FreeMdl
= FALSE
;
342 PVOID VirtualAddressOfMdl
;
343 ULONG NumberOfMapRegisters
;
345 NTSTATUS Status
= STATUS_SUCCESS
;
346 UCHAR EndPointType
, PidDirection
;
347 BOOLEAN IsReadOp
= TRUE
;
348 ULONG TransferBtyesOffset
, CurrentTransferBytes
;
349 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
350 PHYSICAL_ADDRESS PhysicalAddr
;
353 hcd
= &((PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->hcd
;
355 /* If no Irp then we will need to wait on completion */
356 if (IrpToComplete
== NULL
)
358 CompleteEvent
= ExAllocatePool(NonPagedPool
, sizeof(KEVENT
));
359 KeInitializeEvent(CompleteEvent
, NotificationEvent
, FALSE
);
362 CallBackInfo
= ExAllocatePool(NonPagedPool
, sizeof(MAPREGISTERCALLBACKINFO
));
363 CallBackInfo
->MapRegisterBase
= 0;
365 KeInitializeEvent(&CallBackInfo
->Event
, NotificationEvent
, FALSE
);
367 /* Determine EndPoint Type */
370 EndPointType
= USB_ENDPOINT_TYPE_CONTROL
;
374 EndPointDesc
= (PUSB_ENDPOINT_DESCRIPTOR
)PipeHandle
;
375 EndPointType
= EndPointDesc
->bmAttributes
& 0x0F;
378 if (TransferBufferOrMdl
)
380 /* Create MDL for Buffer */
381 if (TransferBufferLength
)
383 pMdl
= IoAllocateMdl(TransferBufferOrMdl
,
384 TransferBufferLength
,
388 /* UEHCI created the MDL so it needs to free it */
393 pMdl
= TransferBufferOrMdl
;
395 MmBuildMdlForNonPagedPool(pMdl
);
398 switch (EndPointType
)
400 case USB_ENDPOINT_TYPE_CONTROL
:
402 QueueHead
= BuildControlTransfer(hcd
,
411 case USB_ENDPOINT_TYPE_BULK
:
413 PidDirection
= EndPointDesc
->bEndpointAddress
>> 7;
417 QueueHead
= BuildBulkTransfer(hcd
,
426 case USB_ENDPOINT_TYPE_INTERRUPT
:
428 DPRINT1("Interrupt Endpoints not implemented yet!\n");
431 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
433 DPRINT1("Isochronous Endpoints not implemented yet!\n");
438 DPRINT1("Unknown Endpoint type!!\n");
443 QueueHead
->IrpToComplete
= IrpToComplete
;
444 QueueHead
->Event
= CompleteEvent
;
448 ASSERT(QueueHead
->NumberOfTransferDescriptors
== 2);
449 LinkQueueHead(hcd
, QueueHead
);
450 if (IrpToComplete
== NULL
)
452 DPRINT1("Waiting For Completion %x!\n", CompleteEvent
);
453 TimeOut
.QuadPart
= -10000000;
454 KeWaitForSingleObject(CompleteEvent
, Suspended
, KernelMode
, FALSE
, NULL
);//&TimeOut);
455 DPRINT1("Request Completed\n");
456 ExFreePool(CompleteEvent
);
462 KeFlushIoBuffers(pMdl
, IsReadOp
, TRUE
);
463 NumberOfMapRegisters
= 15;
465 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
466 hcd
->pDmaAdapter
->DmaOperations
->AllocateAdapterChannel(hcd
->pDmaAdapter
,
467 ((PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->ControllerFdo
,
468 NumberOfMapRegisters
,
470 (PVOID
)CallBackInfo
);
471 KeLowerIrql(OldIrql
);
472 DPRINT1("Waiting for AdapterChannel\n");
473 KeWaitForSingleObject(&CallBackInfo
->Event
, Suspended
, KernelMode
, FALSE
, NULL
);
474 DPRINT1("Dma controller ready!\n");
475 DPRINT1("Getting address for MDL %x\n", pMdl
);
477 VirtualAddressOfMdl
= MmGetMdlVirtualAddress(pMdl
);
479 TransferBtyesOffset
= 0;
480 while (TransferBtyesOffset
< MmGetMdlByteCount(pMdl
))
482 CurrentTransferBytes
= MmGetMdlByteCount(pMdl
);
483 Descriptor
= QueueHead
->FirstTransferDescriptor
;
484 if ((Descriptor
->Token
.Bits
.PIDCode
== PID_CODE_SETUP_TOKEN
) && (QueueHead
->NumberOfTransferDescriptors
== 3))
486 DPRINT1("QueueHead is for endpoint 0\n");
487 DPRINT1("MapRegisterBase %x\n", CallBackInfo
->MapRegisterBase
);
488 DPRINT1("VirtualAddressOfMdl %x, TransferBytesOffset %x\n", VirtualAddressOfMdl
, TransferBtyesOffset
);
489 Descriptor
= Descriptor
->NextDescriptor
;
490 PhysicalAddr
= hcd
->pDmaAdapter
->DmaOperations
->MapTransfer(hcd
->pDmaAdapter
,
492 CallBackInfo
->MapRegisterBase
,
493 (PVOID
)((ULONG_PTR
)VirtualAddressOfMdl
+ TransferBtyesOffset
),
494 &CurrentTransferBytes
,
496 DPRINT1("BufferPointer[0] = %x\n", PhysicalAddr
.LowPart
);
497 Descriptor
->BufferPointer
[0] = PhysicalAddr
.LowPart
;
498 DPRINT1("CurrentTransferBytes %x\n", CurrentTransferBytes
);
499 TransferBtyesOffset
+= CurrentTransferBytes
;
500 LinkQueueHead(hcd
, QueueHead
);
503 DPRINT1("PID_CODE_SETUP_TOKEN %x, PidDirection %x, NumDesc %x\n", PID_CODE_SETUP_TOKEN
, PidDirection
, QueueHead
->NumberOfTransferDescriptors
);
504 for (i
=0; i
<QueueHead
->NumberOfTransferDescriptors
; i
++)
506 if (Descriptor
->Token
.Bits
.PIDCode
!= PID_CODE_SETUP_TOKEN
)
510 PhysicalAddr
= hcd
->pDmaAdapter
->DmaOperations
->MapTransfer(hcd
->pDmaAdapter
,
512 CallBackInfo
->MapRegisterBase
,
513 (PVOID
)((ULONG_PTR
)VirtualAddressOfMdl
+ TransferBtyesOffset
),
514 &CurrentTransferBytes
,
516 DPRINT1("BufferPointer[%d] = %x\n", j
, PhysicalAddr
.LowPart
);
517 Descriptor
->BufferPointer
[j
] = PhysicalAddr
.LowPart
;
518 TransferBtyesOffset
+= CurrentTransferBytes
;
519 if (TransferBtyesOffset
>= MmGetMdlByteCount(pMdl
))
523 Descriptor
= Descriptor
->NextDescriptor
;
525 LinkQueueHead(hcd
, QueueHead
);
529 if (TransferBtyesOffset
< MmGetMdlByteCount(pMdl
)) ASSERT(FALSE
);
530 if (IrpToComplete
== NULL
)
532 DPRINT1("Waiting For Completion %x!\n", CompleteEvent
);
533 TimeOut
.QuadPart
= -10000000;
534 KeWaitForSingleObject(CompleteEvent
, Suspended
, KernelMode
, FALSE
, NULL
);//&TimeOut);
535 DPRINT1("Request Completed\n");
536 ExFreePool(CompleteEvent
);
539 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
540 hcd
->pDmaAdapter
->DmaOperations
->FreeMapRegisters(hcd
->pDmaAdapter
,
541 CallBackInfo
->MapRegisterBase
,
542 NumberOfMapRegisters
);
544 hcd
->pDmaAdapter
->DmaOperations
->FreeAdapterChannel (hcd
->pDmaAdapter
);
545 KeLowerIrql(OldIrql
);