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/usb_request.cpp
5 * PURPOSE: USB EHCI device driver.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
16 class CUSBRequest
: public IEHCIRequest
19 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
21 STDMETHODIMP_(ULONG
) AddRef()
23 InterlockedIncrement(&m_Ref
);
26 STDMETHODIMP_(ULONG
) Release()
28 InterlockedDecrement(&m_Ref
);
38 // IUSBRequest interface functions
40 // IEHCI Request interface functions
44 ULONG
InternalGetTransferType();
45 UCHAR
InternalGetPidDirection();
46 NTSTATUS
BuildControlTransferQueueHead(PQUEUE_HEAD
* OutHead
);
47 NTSTATUS
BuildBulkInterruptTransferQueueHead(PQUEUE_HEAD
* OutHead
);
48 NTSTATUS STDMETHODCALLTYPE
CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR
*OutDescriptor
);
49 NTSTATUS
CreateQueueHead(PQUEUE_HEAD
*OutQueueHead
);
50 UCHAR STDMETHODCALLTYPE
GetDeviceAddress();
51 NTSTATUS
BuildSetupPacket();
52 NTSTATUS
BuildSetupPacketFromURB();
53 ULONG
InternalCalculateTransferLength();
54 NTSTATUS STDMETHODCALLTYPE
BuildTransferDescriptorChain(IN PQUEUE_HEAD QueueHead
, IN PVOID TransferBuffer
, IN ULONG TransferBufferLength
, IN UCHAR PidCode
, IN UCHAR InitialDataToggle
, OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutFirstDescriptor
, OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutLastDescriptor
, OUT PUCHAR OutDataToggle
, OUT PULONG OutTransferBufferOffset
);
55 VOID STDMETHODCALLTYPE
InitDescriptor(IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor
, IN PVOID TransferBuffer
, IN ULONG TransferBufferLength
, IN UCHAR PidCode
, IN UCHAR DataToggle
, OUT PULONG OutDescriptorLength
);
56 VOID
DumpQueueHead(IN PQUEUE_HEAD QueueHead
);
58 // constructor / destructor
59 CUSBRequest(IUnknown
*OuterUnknown
);
60 virtual ~CUSBRequest();
66 // memory manager for allocating setup packet / queue head / transfer descriptors
68 PDMAMEMORYMANAGER m_DmaManager
;
71 // caller provided irp packet containing URB request
76 // transfer buffer length
78 ULONG m_TransferBufferLength
;
81 // current transfer length
83 ULONG m_TransferBufferLengthCompleted
;
86 // Total Transfer Length
88 ULONG m_TotalBytesTransferred
;
91 // transfer buffer MDL
93 PMDL m_TransferBufferMDL
;
96 // caller provided setup packet
98 PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket
;
101 // completion event for callers who initialized request with setup packet
103 PKEVENT m_CompletionEvent
;
106 // device address for callers who initialized it with device address
108 UCHAR m_DeviceAddress
;
111 // store end point address
113 PUSB_ENDPOINT m_EndpointDescriptor
;
118 PQUEUE_HEAD m_QueueHead
;
121 // allocated setup packet from the DMA pool
123 PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket
;
124 PHYSICAL_ADDRESS m_DescriptorSetupPacket
;
127 // stores the result of the operation
129 NTSTATUS m_NtStatusCode
;
130 ULONG m_UrbStatusCode
;
132 // buffer base address
136 USB_DEVICE_SPEED m_Speed
;
140 //----------------------------------------------------------------------------------------
141 CUSBRequest::CUSBRequest(IUnknown
*OuterUnknown
) :
142 m_CompletionEvent(NULL
)
144 UNREFERENCED_PARAMETER(OuterUnknown
);
147 //----------------------------------------------------------------------------------------
148 CUSBRequest::~CUSBRequest()
150 if (m_CompletionEvent
!= NULL
)
152 ExFreePoolWithTag(m_CompletionEvent
, TAG_USBEHCI
);
156 //----------------------------------------------------------------------------------------
159 CUSBRequest::QueryInterface(
163 return STATUS_UNSUCCESSFUL
;
166 //----------------------------------------------------------------------------------------
169 CUSBRequest::InitializeWithSetupPacket(
170 IN PDMAMEMORYMANAGER DmaManager
,
171 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
172 IN PUSBDEVICE Device
,
173 IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor
,
174 IN OUT ULONG TransferBufferLength
,
175 IN OUT PMDL TransferBuffer
)
180 PC_ASSERT(DmaManager
);
181 PC_ASSERT(SetupPacket
);
186 m_DmaManager
= DmaManager
;
187 m_SetupPacket
= SetupPacket
;
188 m_TransferBufferLength
= TransferBufferLength
;
189 m_TransferBufferMDL
= TransferBuffer
;
190 m_DeviceAddress
= Device
->GetDeviceAddress();
191 m_Speed
= Device
->GetSpeed();
192 m_EndpointDescriptor
= EndpointDescriptor
;
193 m_TotalBytesTransferred
= 0;
196 // Set Length Completed to 0
198 m_TransferBufferLengthCompleted
= 0;
201 // allocate completion event
203 m_CompletionEvent
= (PKEVENT
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_USBEHCI
);
204 if (!m_CompletionEvent
)
207 // failed to allocate completion event
209 return STATUS_INSUFFICIENT_RESOURCES
;
213 // initialize completion event
215 KeInitializeEvent(m_CompletionEvent
, NotificationEvent
, FALSE
);
220 return STATUS_SUCCESS
;
222 //----------------------------------------------------------------------------------------
225 CUSBRequest::InitializeWithIrp(
226 IN PDMAMEMORYMANAGER DmaManager
,
227 IN PUSBDEVICE Device
,
230 PIO_STACK_LOCATION IoStack
;
236 PC_ASSERT(DmaManager
);
239 m_DmaManager
= DmaManager
;
240 m_TotalBytesTransferred
= 0;
241 m_Speed
= Device
->GetSpeed();
244 // get current irp stack location
246 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
251 PC_ASSERT(IoStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
);
252 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_SUBMIT_URB
);
253 PC_ASSERT(IoStack
->Parameters
.Others
.Argument1
!= 0);
258 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
266 // check function type
268 switch (Urb
->UrbHeader
.Function
)
271 // luckily those request have the same structure layout
273 case URB_FUNCTION_CLASS_INTERFACE
:
274 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
275 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
278 // bulk interrupt transfer
280 if (Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
)
283 // Check if there is a MDL
285 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
290 PC_ASSERT(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
);
293 // Create one using TransferBuffer
295 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
296 m_TransferBufferMDL
= IoAllocateMdl(Urb
->UrbBulkOrInterruptTransfer
.TransferBuffer
,
297 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
,
302 if (!m_TransferBufferMDL
)
305 // failed to allocate mdl
307 return STATUS_INSUFFICIENT_RESOURCES
;
311 // build mdl for non paged pool
312 // FIXME: Does hub driver already do this when passing MDL?
314 MmBuildMdlForNonPagedPool(m_TransferBufferMDL
);
317 // Keep that ehci created the MDL and needs to free it.
322 m_TransferBufferMDL
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
;
326 // save buffer length
328 m_TransferBufferLength
= Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
;
331 // Set Length Completed to 0
333 m_TransferBufferLengthCompleted
= 0;
336 // get endpoint descriptor
338 m_EndpointDescriptor
= (PUSB_ENDPOINT
)Urb
->UrbBulkOrInterruptTransfer
.PipeHandle
;
344 DPRINT1("URB Function: not supported %x\n", Urb
->UrbHeader
.Function
);
351 return STATUS_SUCCESS
;
355 //----------------------------------------------------------------------------------------
358 CUSBRequest::CompletionCallback(
359 IN NTSTATUS NtStatusCode
,
360 IN ULONG UrbStatusCode
,
361 IN
struct _QUEUE_HEAD
*QueueHead
)
363 PIO_STACK_LOCATION IoStack
;
367 // FIXME: support linked queue heads
371 // store completion code
373 m_NtStatusCode
= NtStatusCode
;
374 m_UrbStatusCode
= UrbStatusCode
;
379 // set irp completion status
381 m_Irp
->IoStatus
.Status
= NtStatusCode
;
384 // get current irp stack location
386 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
391 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
396 Urb
->UrbHeader
.Status
= UrbStatusCode
;
399 // Check if the MDL was created
401 if (!Urb
->UrbBulkOrInterruptTransfer
.TransferBufferMDL
)
406 IoFreeMdl(m_TransferBufferMDL
);
410 // check if the request was successful
412 if (!NT_SUCCESS(NtStatusCode
))
415 // set returned length to zero in case of error
417 Urb
->UrbHeader
.Length
= 0;
422 // calculate transfer length
424 Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
= InternalCalculateTransferLength();
427 DPRINT("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x Transferred Length %lu\n", this, m_Irp
, NtStatusCode
, UrbStatusCode
, Urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
);
430 // FIXME: check if the transfer was split
431 // if yes dont complete irp yet
433 IoCompleteRequest(m_Irp
, IO_NO_INCREMENT
);
438 // signal completion event
440 PC_ASSERT(m_CompletionEvent
);
441 KeSetEvent(m_CompletionEvent
, 0, FALSE
);
445 //----------------------------------------------------------------------------------------
448 CUSBRequest::GetQueueHead(
449 struct _QUEUE_HEAD
** OutHead
)
455 // first get transfer type
457 TransferType
= InternalGetTransferType();
460 // build request depending on type
464 case USB_ENDPOINT_TYPE_CONTROL
:
465 Status
= BuildControlTransferQueueHead(OutHead
);
467 case USB_ENDPOINT_TYPE_INTERRUPT
:
468 case USB_ENDPOINT_TYPE_BULK
:
469 Status
= BuildBulkInterruptTransferQueueHead(OutHead
);
471 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
472 DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
473 Status
= STATUS_NOT_IMPLEMENTED
;
477 Status
= STATUS_NOT_IMPLEMENTED
;
481 if (NT_SUCCESS(Status
))
486 m_QueueHead
= *OutHead
;
489 // store request object
491 (*OutHead
)->Request
= PVOID(this);
500 //----------------------------------------------------------------------------------------
503 CUSBRequest::IsRequestComplete()
506 // FIXME: check if request was split
510 // Check if the transfer was completed, only valid for Bulk Transfers
512 if ((m_TransferBufferLengthCompleted
< m_TransferBufferLength
)
513 && (GetTransferType() == USB_ENDPOINT_TYPE_BULK
))
516 // Transfer not completed
522 //----------------------------------------------------------------------------------------
525 CUSBRequest::GetTransferType()
528 // call internal implementation
530 return InternalGetTransferType();
533 //----------------------------------------------------------------------------------------
535 CUSBRequest::InternalGetTransferType()
540 // check if an irp is provided
544 ASSERT(m_EndpointDescriptor
);
547 // end point is defined in the low byte of bmAttributes
549 TransferType
= (m_EndpointDescriptor
->EndPointDescriptor
.bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
554 // initialized with setup packet, must be a control transfer
556 TransferType
= USB_ENDPOINT_TYPE_CONTROL
;
557 ASSERT(m_EndpointDescriptor
== NULL
);
567 CUSBRequest::InternalGetPidDirection()
569 if (m_EndpointDescriptor
)
572 // end point direction is highest bit in bEndpointAddress
574 return (m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& USB_ENDPOINT_DIRECTION_MASK
) >> 7;
579 // request arrives on the control pipe, extract direction from setup packet
581 ASSERT(m_DescriptorPacket
);
582 return (m_DescriptorPacket
->bmRequestType
.B
>> 7);
588 CUSBRequest::InitDescriptor(
589 IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor
,
590 IN PVOID TransferBuffer
,
591 IN ULONG TransferBufferLength
,
594 OUT PULONG OutDescriptorLength
)
596 ULONG Index
, Length
= 0, PageOffset
, BufferLength
;
597 PHYSICAL_ADDRESS Address
;
600 // init transfer descriptor
602 CurrentDescriptor
->Token
.Bits
.PIDCode
= PidCode
;
603 CurrentDescriptor
->Token
.Bits
.TotalBytesToTransfer
= 0;
604 CurrentDescriptor
->Token
.Bits
.DataToggle
= DataToggle
;
609 ASSERT(TransferBufferLength
);
618 // get address (HACK)
620 *(volatile char *)TransferBuffer
;
621 Address
= MmGetPhysicalAddress(TransferBuffer
);
624 // use physical address
626 CurrentDescriptor
->BufferPointer
[Index
] = Address
.LowPart
;
627 CurrentDescriptor
->ExtendedBufferPointer
[Index
] = Address
.HighPart
;
630 // Get the offset from page size
632 PageOffset
= BYTE_OFFSET(CurrentDescriptor
->BufferPointer
[Index
]);
638 TransferBuffer
= (PVOID
)ROUND_TO_PAGES(TransferBuffer
);
645 TransferBuffer
= (PVOID
)((ULONG_PTR
)TransferBuffer
+ PAGE_SIZE
);
649 // calculate buffer length
651 BufferLength
= min(TransferBufferLength
, PAGE_SIZE
- PageOffset
);
654 // increment transfer bytes
656 CurrentDescriptor
->Token
.Bits
.TotalBytesToTransfer
+= BufferLength
;
657 CurrentDescriptor
->TotalBytesToTransfer
+= BufferLength
;
658 Length
+= BufferLength
;
659 DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu Buffer Phy %p TransferBuffer %p\n", Index
, TransferBufferLength
, PageOffset
, BufferLength
, CurrentDescriptor
->BufferPointer
[Index
], TransferBuffer
);
662 // decrement available byte count
664 TransferBufferLength
-= BufferLength
;
665 if (TransferBufferLength
== 0)
681 ASSERT(CurrentDescriptor
->BufferPointer
[Index
] != CurrentDescriptor
->BufferPointer
[Index
-1]);
685 // next descriptor index
693 *OutDescriptorLength
= Length
;
698 CUSBRequest::BuildTransferDescriptorChain(
699 IN PQUEUE_HEAD QueueHead
,
700 IN PVOID TransferBuffer
,
701 IN ULONG TransferBufferLength
,
703 IN UCHAR InitialDataToggle
,
704 OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutFirstDescriptor
,
705 OUT PQUEUE_TRANSFER_DESCRIPTOR
* OutLastDescriptor
,
706 OUT PUCHAR OutDataToggle
,
707 OUT PULONG OutTransferBufferOffset
)
709 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor
= NULL
, CurrentDescriptor
, LastDescriptor
= NULL
;
711 ULONG DescriptorLength
, TransferBufferOffset
= 0;
712 ULONG MaxPacketSize
= 0, TransferSize
;
715 // is there an endpoint descriptor
717 if (m_EndpointDescriptor
)
720 // use endpoint packet size
722 MaxPacketSize
= m_EndpointDescriptor
->EndPointDescriptor
.wMaxPacketSize
;
728 // allocate transfer descriptor
730 Status
= CreateDescriptor(&CurrentDescriptor
);
731 if (!NT_SUCCESS(Status
))
734 // failed to allocate transfer descriptor
736 return STATUS_INSUFFICIENT_RESOURCES
;
742 // transfer size is minimum available buffer or endpoint size
744 TransferSize
= min(TransferBufferLength
- TransferBufferOffset
, MaxPacketSize
);
749 // use available buffer
751 TransferSize
= TransferBufferLength
- TransferBufferOffset
;
755 // now init the descriptor
757 InitDescriptor(CurrentDescriptor
,
758 (PVOID
)((ULONG_PTR
)TransferBuffer
+ TransferBufferOffset
),
765 // insert into queue head
767 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &CurrentDescriptor
->DescriptorEntry
);
772 TransferBufferOffset
+= DescriptorLength
;
777 // link to current descriptor
779 LastDescriptor
->NextPointer
= CurrentDescriptor
->PhysicalAddr
;
780 LastDescriptor
= CurrentDescriptor
;
785 // first descriptor in chain
787 LastDescriptor
= FirstDescriptor
= CurrentDescriptor
;
793 InitialDataToggle
= !InitialDataToggle
;
795 if(TransferBufferLength
== TransferBufferOffset
)
805 if (OutFirstDescriptor
)
808 // store first descriptor
810 *OutFirstDescriptor
= FirstDescriptor
;
813 if (OutLastDescriptor
)
816 // store last descriptor
818 *OutLastDescriptor
= CurrentDescriptor
;
824 // store result data toggle
826 *OutDataToggle
= InitialDataToggle
;
829 if (OutTransferBufferOffset
)
834 *OutTransferBufferOffset
= TransferBufferOffset
;
840 return STATUS_SUCCESS
;
843 //----------------------------------------------------------------------------------------
845 CUSBRequest::BuildControlTransferQueueHead(
846 PQUEUE_HEAD
* OutHead
)
849 ULONG DescriptorChainLength
;
850 PQUEUE_HEAD QueueHead
;
851 PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor
, StatusDescriptor
, FirstDescriptor
, LastDescriptor
;
854 // first allocate the queue head
856 Status
= CreateQueueHead(&QueueHead
);
857 if (!NT_SUCCESS(Status
))
860 // failed to allocate queue head
862 DPRINT1("[EHCI] Failed to create queue head\n");
869 PC_ASSERT(QueueHead
);
872 // create setup packet
874 Status
= BuildSetupPacket();
875 if (!NT_SUCCESS(Status
))
877 // failed to create setup packet
878 DPRINT1("[EHCI] Failed to create setup packet\n");
880 // release queue head
881 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
886 // create setup descriptor
888 Status
= CreateDescriptor(&SetupDescriptor
);
889 if (!NT_SUCCESS(Status
))
891 // failed to create setup transfer descriptor
892 DPRINT1("[EHCI] Failed to create setup descriptor\n");
894 if (m_DescriptorPacket
)
896 // release packet descriptor
897 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
900 // release queue head
901 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
906 // create status descriptor
908 Status
= CreateDescriptor(&StatusDescriptor
);
909 if (!NT_SUCCESS(Status
))
911 // failed to create status transfer descriptor
912 DPRINT1("[EHCI] Failed to create status descriptor\n");
914 // release setup transfer descriptor
915 m_DmaManager
->Release(SetupDescriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
917 if (m_DescriptorPacket
)
919 // release packet descriptor
920 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
923 // release queue head
924 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
929 // now initialize the queue head
931 QueueHead
->EndPointCharacteristics
.DeviceAddress
= GetDeviceAddress();
933 ASSERT(m_EndpointDescriptor
== NULL
);
936 // init setup descriptor
938 SetupDescriptor
->Token
.Bits
.PIDCode
= PID_CODE_SETUP_TOKEN
;
939 SetupDescriptor
->Token
.Bits
.TotalBytesToTransfer
= sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
);
940 SetupDescriptor
->Token
.Bits
.DataToggle
= FALSE
;
941 SetupDescriptor
->BufferPointer
[0] = m_DescriptorSetupPacket
.LowPart
;
942 SetupDescriptor
->ExtendedBufferPointer
[0] = m_DescriptorSetupPacket
.HighPart
;
943 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &SetupDescriptor
->DescriptorEntry
);
947 // init status descriptor
949 StatusDescriptor
->Token
.Bits
.TotalBytesToTransfer
= 0;
950 StatusDescriptor
->Token
.Bits
.DataToggle
= TRUE
;
951 StatusDescriptor
->Token
.Bits
.InterruptOnComplete
= TRUE
;
956 if (m_TransferBufferLength
)
958 Status
= BuildTransferDescriptorChain(QueueHead
,
959 MmGetMdlVirtualAddress(m_TransferBufferMDL
),
960 m_TransferBufferLength
,
961 InternalGetPidDirection(),
966 &DescriptorChainLength
);
967 if (!NT_SUCCESS(Status
))
969 // failed to create descriptor chain
970 DPRINT1("[EHCI] Failed to create descriptor chain\n");
972 // release status transfer descriptor
973 m_DmaManager
->Release(StatusDescriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
975 // release setup transfer descriptor
976 m_DmaManager
->Release(SetupDescriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
978 if (m_DescriptorPacket
)
980 // release packet descriptor
981 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
984 // release queue head
985 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
989 if (m_TransferBufferLength
!= DescriptorChainLength
)
991 DPRINT1("DescriptorChainLength %x\n", DescriptorChainLength
);
992 DPRINT1("m_TransferBufferLength %x\n", m_TransferBufferLength
);
997 // now link the descriptors
999 SetupDescriptor
->NextPointer
= FirstDescriptor
->PhysicalAddr
;
1000 SetupDescriptor
->AlternateNextPointer
= FirstDescriptor
->PhysicalAddr
;
1001 LastDescriptor
->NextPointer
= StatusDescriptor
->PhysicalAddr
;
1002 LastDescriptor
->AlternateNextPointer
= StatusDescriptor
->PhysicalAddr
;
1006 // pid code is flipped for ops with data stage
1008 StatusDescriptor
->Token
.Bits
.PIDCode
= !InternalGetPidDirection();
1015 SetupDescriptor
->NextPointer
= StatusDescriptor
->PhysicalAddr
;
1016 SetupDescriptor
->AlternateNextPointer
= StatusDescriptor
->PhysicalAddr
;
1019 // retrieve result of operation
1021 StatusDescriptor
->Token
.Bits
.PIDCode
= PID_CODE_IN_TOKEN
;
1025 // insert status descriptor
1027 InsertTailList(&QueueHead
->TransferDescriptorListHead
, &StatusDescriptor
->DescriptorEntry
);
1031 // link transfer descriptors to queue head
1033 QueueHead
->NextPointer
= SetupDescriptor
->PhysicalAddr
;
1038 *OutHead
= QueueHead
;
1041 // displays the current request
1043 //DumpQueueHead(QueueHead);
1045 DPRINT("BuildControlTransferQueueHead done\n");
1049 return STATUS_SUCCESS
;
1053 CUSBRequest::DumpQueueHead(
1054 IN PQUEUE_HEAD QueueHead
)
1057 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1060 DPRINT1("QueueHead %p Addr %x\n", QueueHead
, QueueHead
->PhysicalAddr
);
1061 DPRINT1("QueueHead AlternateNextPointer %x\n", QueueHead
->AlternateNextPointer
);
1062 DPRINT1("QueueHead NextPointer %x\n", QueueHead
->NextPointer
);
1064 DPRINT1("QueueHead HubAddr %x\n", QueueHead
->EndPointCharacteristics
.ControlEndPointFlag
);
1065 DPRINT1("QueueHead DeviceAddress %x\n", QueueHead
->EndPointCharacteristics
.DeviceAddress
);
1066 DPRINT1("QueueHead EndPointNumber %x\n", QueueHead
->EndPointCharacteristics
.EndPointNumber
);
1067 DPRINT1("QueueHead EndPointSpeed %x\n", QueueHead
->EndPointCharacteristics
.EndPointSpeed
);
1068 DPRINT1("QueueHead HeadOfReclamation %x\n", QueueHead
->EndPointCharacteristics
.HeadOfReclamation
);
1069 DPRINT1("QueueHead InactiveOnNextTransaction %x\n", QueueHead
->EndPointCharacteristics
.InactiveOnNextTransaction
);
1070 DPRINT1("QueueHead MaximumPacketLength %x\n", QueueHead
->EndPointCharacteristics
.MaximumPacketLength
);
1071 DPRINT1("QueueHead NakCountReload %x\n", QueueHead
->EndPointCharacteristics
.NakCountReload
);
1072 DPRINT1("QueueHead QEDTDataToggleControl %x\n", QueueHead
->EndPointCharacteristics
.QEDTDataToggleControl
);
1073 DPRINT1("QueueHead HubAddr %x\n", QueueHead
->EndPointCapabilities
.HubAddr
);
1074 DPRINT1("QueueHead InterruptScheduleMask %x\n", QueueHead
->EndPointCapabilities
.InterruptScheduleMask
);
1075 DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n", QueueHead
->EndPointCapabilities
.NumberOfTransactionPerFrame
);
1076 DPRINT1("QueueHead PortNumber %x\n", QueueHead
->EndPointCapabilities
.PortNumber
);
1077 DPRINT1("QueueHead SplitCompletionMask %x\n", QueueHead
->EndPointCapabilities
.SplitCompletionMask
);
1079 Entry
= QueueHead
->TransferDescriptorListHead
.Flink
;
1080 while(Entry
!= &QueueHead
->TransferDescriptorListHead
)
1083 // get transfer descriptor
1085 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1087 DPRINT1("TransferDescriptor %lu Addr %x\n", Index
, Descriptor
->PhysicalAddr
);
1088 DPRINT1("TransferDescriptor %lu Next %x\n", Index
, Descriptor
->NextPointer
);
1089 DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index
, Descriptor
->AlternateNextPointer
);
1090 DPRINT1("TransferDescriptor %lu Active %lu\n", Index
, Descriptor
->Token
.Bits
.Active
);
1091 DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index
, Descriptor
->Token
.Bits
.BabbleDetected
);
1092 DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index
, Descriptor
->Token
.Bits
.CurrentPage
);
1093 DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index
, Descriptor
->Token
.Bits
.DataBufferError
);
1094 DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index
, Descriptor
->Token
.Bits
.DataToggle
);
1095 DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index
, Descriptor
->Token
.Bits
.ErrorCounter
);
1096 DPRINT1("TransferDescriptor %lu Halted %lu\n", Index
, Descriptor
->Token
.Bits
.Halted
);
1097 DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index
, Descriptor
->Token
.Bits
.InterruptOnComplete
);
1098 DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index
, Descriptor
->Token
.Bits
.MissedMicroFrame
);
1099 DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index
, Descriptor
->Token
.Bits
.PIDCode
);
1100 DPRINT1("TransferDescriptor %lu PingState %lu\n", Index
, Descriptor
->Token
.Bits
.PingState
);
1101 DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index
, Descriptor
->Token
.Bits
.SplitTransactionState
);
1102 DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index
, Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1103 DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index
, Descriptor
->Token
.Bits
.TransactionError
);
1105 DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index
, Descriptor
->BufferPointer
[0]);
1106 DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index
, Descriptor
->BufferPointer
[1]);
1107 DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index
, Descriptor
->BufferPointer
[2]);
1108 DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index
, Descriptor
->BufferPointer
[3]);
1109 DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index
, Descriptor
->BufferPointer
[4]);
1110 Entry
= Entry
->Flink
;
1116 //----------------------------------------------------------------------------------------
1118 CUSBRequest::BuildBulkInterruptTransferQueueHead(
1119 PQUEUE_HEAD
* OutHead
)
1122 PQUEUE_HEAD QueueHead
;
1124 ULONG ChainDescriptorLength
;
1125 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor
, LastDescriptor
;
1128 // Allocate the queue head
1130 Status
= CreateQueueHead(&QueueHead
);
1131 if (!NT_SUCCESS(Status
))
1134 // failed to allocate queue head
1136 DPRINT1("[EHCI] Failed to create queue head\n");
1143 PC_ASSERT(QueueHead
);
1144 PC_ASSERT(m_TransferBufferLength
);
1149 // get virtual base of mdl
1151 m_Base
= MmGetSystemAddressForMdlSafe(m_TransferBufferMDL
, NormalPagePriority
);
1155 // Increase the size of last transfer, 0 in case this is the first
1157 Base
= (PVOID
)((ULONG_PTR
)m_Base
+ m_TransferBufferLengthCompleted
);
1159 PC_ASSERT(m_EndpointDescriptor
);
1165 ASSERT(m_EndpointDescriptor
);
1168 // use 4 * PAGE_SIZE at max for each new request
1170 ULONG MaxTransferLength
= min(4 * PAGE_SIZE
, m_TransferBufferLength
- m_TransferBufferLengthCompleted
);
1173 // build bulk transfer descriptor chain
1175 Status
= BuildTransferDescriptorChain(QueueHead
,
1178 InternalGetPidDirection(),
1179 m_EndpointDescriptor
->DataToggle
,
1182 &m_EndpointDescriptor
->DataToggle
,
1183 &ChainDescriptorLength
);
1184 if (!NT_SUCCESS(Status
))
1187 // failed to build transfer descriptor chain
1189 DPRINT1("[EHCI] Failed to create descriptor chain\n");
1190 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
1195 // move to next offset
1197 m_TransferBufferLengthCompleted
+= ChainDescriptorLength
;
1202 QueueHead
->EndPointCharacteristics
.DeviceAddress
= GetDeviceAddress();
1203 QueueHead
->EndPointCharacteristics
.EndPointNumber
= m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
& 0x0F;
1204 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= m_EndpointDescriptor
->EndPointDescriptor
.wMaxPacketSize
;
1205 QueueHead
->NextPointer
= FirstDescriptor
->PhysicalAddr
;
1206 QueueHead
->CurrentLinkPointer
= FirstDescriptor
->PhysicalAddr
;
1207 QueueHead
->AlternateNextPointer
= TERMINATE_POINTER
;
1209 ASSERT(QueueHead
->EndPointCharacteristics
.DeviceAddress
);
1210 ASSERT(QueueHead
->EndPointCharacteristics
.EndPointNumber
);
1211 ASSERT(QueueHead
->EndPointCharacteristics
.MaximumPacketLength
);
1212 ASSERT(QueueHead
->NextPointer
);
1215 // interrupt on last descriptor
1217 LastDescriptor
->Token
.Bits
.InterruptOnComplete
= TRUE
;
1222 *OutHead
= QueueHead
;
1227 //DumpQueueHead(QueueHead);
1232 return STATUS_SUCCESS
;
1235 //----------------------------------------------------------------------------------------
1238 CUSBRequest::CreateDescriptor(
1239 PQUEUE_TRANSFER_DESCRIPTOR
*OutDescriptor
)
1241 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1243 PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress
;
1246 // allocate descriptor
1248 Status
= m_DmaManager
->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR
), (PVOID
*)&Descriptor
, &TransferDescriptorPhysicalAddress
);
1249 if (!NT_SUCCESS(Status
))
1252 // failed to allocate transfer descriptor
1254 return STATUS_INSUFFICIENT_RESOURCES
;
1258 // initialize transfer descriptor
1260 Descriptor
->NextPointer
= TERMINATE_POINTER
;
1261 Descriptor
->AlternateNextPointer
= TERMINATE_POINTER
;
1262 Descriptor
->Token
.Bits
.DataToggle
= TRUE
;
1263 Descriptor
->Token
.Bits
.ErrorCounter
= 0x03;
1264 Descriptor
->Token
.Bits
.Active
= TRUE
;
1265 Descriptor
->PhysicalAddr
= TransferDescriptorPhysicalAddress
.LowPart
;
1270 *OutDescriptor
= Descriptor
;
1278 //----------------------------------------------------------------------------------------
1280 CUSBRequest::CreateQueueHead(
1281 PQUEUE_HEAD
*OutQueueHead
)
1283 PQUEUE_HEAD QueueHead
;
1284 PHYSICAL_ADDRESS QueueHeadPhysicalAddress
;
1288 // allocate queue head
1290 Status
= m_DmaManager
->Allocate(sizeof(QUEUE_HEAD
), (PVOID
*)&QueueHead
, &QueueHeadPhysicalAddress
);
1291 if (!NT_SUCCESS(Status
))
1294 // failed to allocate queue head
1296 return STATUS_INSUFFICIENT_RESOURCES
;
1300 // initialize queue head
1302 QueueHead
->HorizontalLinkPointer
= TERMINATE_POINTER
;
1303 QueueHead
->AlternateNextPointer
= TERMINATE_POINTER
;
1304 QueueHead
->NextPointer
= TERMINATE_POINTER
;
1305 InitializeListHead(&QueueHead
->TransferDescriptorListHead
);
1308 // 1 for non high speed, 0 for high speed device
1310 QueueHead
->EndPointCharacteristics
.ControlEndPointFlag
= 0;
1311 QueueHead
->EndPointCharacteristics
.HeadOfReclamation
= FALSE
;
1312 QueueHead
->EndPointCharacteristics
.MaximumPacketLength
= 64;
1315 // Set NakCountReload to max value possible
1317 QueueHead
->EndPointCharacteristics
.NakCountReload
= 0x3;
1320 // Get the Initial Data Toggle from the QEDT
1322 QueueHead
->EndPointCharacteristics
.QEDTDataToggleControl
= TRUE
;
1325 // FIXME: check if High Speed Device
1327 QueueHead
->EndPointCharacteristics
.EndPointSpeed
= QH_ENDPOINT_HIGHSPEED
;
1328 QueueHead
->EndPointCapabilities
.NumberOfTransactionPerFrame
= 0x01;
1329 QueueHead
->Token
.DWord
= 0;
1330 QueueHead
->Token
.Bits
.InterruptOnComplete
= FALSE
;
1335 QueueHead
->PhysicalAddr
= QueueHeadPhysicalAddress
.LowPart
;
1338 // output queue head
1340 *OutQueueHead
= QueueHead
;
1345 return STATUS_SUCCESS
;
1348 //----------------------------------------------------------------------------------------
1351 CUSBRequest::GetDeviceAddress()
1353 PIO_STACK_LOCATION IoStack
;
1355 PUSBDEVICE UsbDevice
;
1358 // check if there is an irp provided
1363 // used provided address
1365 return m_DeviceAddress
;
1369 // get current stack location
1371 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1374 // get contained urb
1376 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1379 // check if there is a pipe handle provided
1381 if (Urb
->UrbHeader
.UsbdDeviceHandle
)
1384 // there is a device handle provided
1386 UsbDevice
= (PUSBDEVICE
)Urb
->UrbHeader
.UsbdDeviceHandle
;
1389 // return device address
1391 return UsbDevice
->GetDeviceAddress();
1395 // no device handle provided, it is the host root bus
1400 //----------------------------------------------------------------------------------------
1402 CUSBRequest::BuildSetupPacket()
1407 // allocate common buffer setup packet
1409 Status
= m_DmaManager
->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
), (PVOID
*)&m_DescriptorPacket
, &m_DescriptorSetupPacket
);
1410 if (!NT_SUCCESS(Status
))
1421 // copy setup packet
1423 RtlCopyMemory(m_DescriptorPacket
, m_SetupPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1428 // build setup packet from urb
1430 Status
= BuildSetupPacketFromURB();
1441 CUSBRequest::BuildSetupPacketFromURB()
1443 PIO_STACK_LOCATION IoStack
;
1445 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
1451 PC_ASSERT(m_DescriptorPacket
);
1454 // get stack location
1456 IoStack
= IoGetCurrentIrpStackLocation(m_Irp
);
1461 Urb
= (PURB
)IoStack
->Parameters
.Others
.Argument1
;
1464 // zero descriptor packet
1466 RtlZeroMemory(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1469 switch (Urb
->UrbHeader
.Function
)
1472 case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE
:
1473 case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE
:
1474 case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT
:
1479 case URB_FUNCTION_GET_CONFIGURATION
:
1480 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
1481 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1482 m_DescriptorPacket
->wLength
= 1;
1485 /* GET DESCRIPTOR */
1486 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
1487 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1488 m_DescriptorPacket
->wValue
.LowByte
= Urb
->UrbControlDescriptorRequest
.Index
;
1489 m_DescriptorPacket
->wValue
.HiByte
= Urb
->UrbControlDescriptorRequest
.DescriptorType
;
1490 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlDescriptorRequest
.LanguageId
;
1491 m_DescriptorPacket
->wLength
= (USHORT
)Urb
->UrbControlDescriptorRequest
.TransferBufferLength
;
1492 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1496 case URB_FUNCTION_GET_INTERFACE
:
1497 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_CONFIGURATION
;
1498 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1499 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1500 m_DescriptorPacket
->wLength
= 1;
1504 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
1505 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1506 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1507 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1508 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1509 m_DescriptorPacket
->wLength
= 2;
1512 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
:
1513 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1514 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
1515 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1516 m_DescriptorPacket
->bmRequestType
.B
= 0x81;
1517 m_DescriptorPacket
->wLength
= 2;
1520 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
:
1521 m_DescriptorPacket
->bRequest
= USB_REQUEST_GET_STATUS
;
1522 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
!= 0);
1523 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1524 m_DescriptorPacket
->bmRequestType
.B
= 0x82;
1525 m_DescriptorPacket
->wLength
= 2;
1531 case URB_FUNCTION_SELECT_CONFIGURATION
:
1532 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_CONFIGURATION
;
1533 m_DescriptorPacket
->wValue
.W
= Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
->bConfigurationValue
;
1534 m_DescriptorPacket
->wIndex
.W
= 0;
1535 m_DescriptorPacket
->wLength
= 0;
1536 m_DescriptorPacket
->bmRequestType
.B
= 0x00;
1539 /* SET DESCRIPTOR */
1540 case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE
:
1541 case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE
:
1542 case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT
:
1547 case URB_FUNCTION_SET_FEATURE_TO_DEVICE
:
1548 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1549 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1550 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1551 m_DescriptorPacket
->bmRequestType
.B
= 0x80;
1554 case URB_FUNCTION_SET_FEATURE_TO_INTERFACE
:
1555 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1556 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1557 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1558 m_DescriptorPacket
->bmRequestType
.B
= 0x81;
1561 case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT
:
1562 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_FEATURE
;
1563 ASSERT(Urb
->UrbControlGetStatusRequest
.Index
== 0);
1564 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbControlGetStatusRequest
.Index
;
1565 m_DescriptorPacket
->bmRequestType
.B
= 0x82;
1569 case URB_FUNCTION_SELECT_INTERFACE
:
1570 m_DescriptorPacket
->bRequest
= USB_REQUEST_SET_INTERFACE
;
1571 m_DescriptorPacket
->wValue
.W
= Urb
->UrbSelectInterface
.Interface
.AlternateSetting
;
1572 m_DescriptorPacket
->wIndex
.W
= Urb
->UrbSelectInterface
.Interface
.InterfaceNumber
;
1573 m_DescriptorPacket
->wLength
= 0;
1574 m_DescriptorPacket
->bmRequestType
.B
= 0x01;
1578 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
1589 //----------------------------------------------------------------------------------------
1592 CUSBRequest::GetResultStatus(
1593 OUT OPTIONAL NTSTATUS
* NtStatusCode
,
1594 OUT OPTIONAL PULONG UrbStatusCode
)
1599 PC_ASSERT(m_CompletionEvent
);
1602 // wait for the operation to complete
1604 KeWaitForSingleObject(m_CompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1611 *NtStatusCode
= m_NtStatusCode
;
1619 *UrbStatusCode
= m_UrbStatusCode
;
1624 //-----------------------------------------------------------------------------------------
1627 CUSBRequest::ShouldReleaseRequestAfterCompletion()
1632 // the request is completed, release it
1639 // created with an setup packet, don't release
1645 //-----------------------------------------------------------------------------------------
1648 CUSBRequest::FreeQueueHead(
1649 IN
struct _QUEUE_HEAD
* QueueHead
)
1652 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1657 ASSERT(m_DmaManager
);
1659 ASSERT(!IsListEmpty(&QueueHead
->TransferDescriptorListHead
));
1664 // get transfer descriptors
1666 Entry
= RemoveHeadList(&QueueHead
->TransferDescriptorListHead
);
1670 // obtain descriptor from entry
1672 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1676 // add transfer count
1678 m_TotalBytesTransferred
+= (Descriptor
->TotalBytesToTransfer
- Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1679 DPRINT("TotalBytes Transferred in Descriptor %p Phys Addr %x TotalBytesSoftware %lu Length %lu\n", Descriptor
, Descriptor
->PhysicalAddr
, Descriptor
->TotalBytesToTransfer
, Descriptor
->TotalBytesToTransfer
- Descriptor
->Token
.Bits
.TotalBytesToTransfer
);
1682 // release transfer descriptors
1684 m_DmaManager
->Release(Descriptor
, sizeof(QUEUE_TRANSFER_DESCRIPTOR
));
1686 }while(!IsListEmpty(&QueueHead
->TransferDescriptorListHead
));
1688 if (m_DescriptorPacket
)
1691 // release packet descriptor
1693 m_DmaManager
->Release(m_DescriptorPacket
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1697 // release queue head
1699 m_DmaManager
->Release(QueueHead
, sizeof(QUEUE_HEAD
));
1705 m_DescriptorPacket
= 0;
1708 //-----------------------------------------------------------------------------------------
1711 CUSBRequest::IsQueueHeadComplete(
1712 struct _QUEUE_HEAD
* QueueHead
)
1715 PQUEUE_TRANSFER_DESCRIPTOR Descriptor
;
1718 // first check - is the queue head currently active
1720 if (QueueHead
->Token
.Bits
.Active
)
1723 // queue head is active (currently processed)
1728 if (QueueHead
->Token
.Bits
.Halted
)
1733 DPRINT1("Found halted queue head %p\n", QueueHead
);
1734 DumpQueueHead(QueueHead
);
1740 // loop list and see if there are any active descriptors
1742 Entry
= QueueHead
->TransferDescriptorListHead
.Flink
;
1743 while(Entry
!= &QueueHead
->TransferDescriptorListHead
)
1746 // obtain descriptor from entry
1748 Descriptor
= (PQUEUE_TRANSFER_DESCRIPTOR
)CONTAINING_RECORD(Entry
, QUEUE_TRANSFER_DESCRIPTOR
, DescriptorEntry
);
1750 if (Descriptor
->Token
.Bits
.Active
)
1753 // descriptor is still active
1759 // move to next entry
1761 Entry
= Entry
->Flink
;
1764 DPRINT("QueueHead %p Addr %x is complete\n", QueueHead
, QueueHead
->PhysicalAddr
);
1767 // no active descriptors found, queue head is finished
1772 //-----------------------------------------------------------------------------------------
1774 CUSBRequest::InternalCalculateTransferLength()
1779 // FIXME: get length for control request
1781 return m_TransferBufferLength
;
1787 ASSERT(m_EndpointDescriptor
);
1788 if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor
->EndPointDescriptor
.bEndpointAddress
))
1792 // HACK: Properly determine transfer length
1794 return m_TransferBufferLength
;//m_TotalBytesTransferred;
1798 // bulk out transfer
1800 return m_TransferBufferLength
;
1804 CUSBRequest::GetSpeed()
1810 CUSBRequest::GetInterval()
1812 if (!m_EndpointDescriptor
)
1815 return m_EndpointDescriptor
->EndPointDescriptor
.bInterval
;
1818 //-----------------------------------------------------------------------------------------
1821 InternalCreateUSBRequest(
1822 PUSBREQUEST
*OutRequest
)
1827 // allocate requests
1829 This
= new(NonPagedPool
, TAG_USBEHCI
) CUSBRequest(0);
1833 // failed to allocate
1835 return STATUS_INSUFFICIENT_RESOURCES
;
1839 // add reference count
1846 *OutRequest
= (PUSBREQUEST
)This
;
1851 return STATUS_SUCCESS
;