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/usbohci/usb_queue.cpp
5 * PURPOSE: USB OHCI device driver.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
14 class CUSBQueue
: public IUSBQueue
17 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
19 STDMETHODIMP_(ULONG
) AddRef()
21 InterlockedIncrement(&m_Ref
);
24 STDMETHODIMP_(ULONG
) Release()
26 InterlockedDecrement(&m_Ref
);
41 BOOLEAN
IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, IN ULONG TransferDescriptorLogicalAddress
);
42 BOOLEAN
IsTransferDescriptorInIsoEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, IN ULONG TransferDescriptorLogicalAddress
);
43 NTSTATUS
FindTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, IN ULONG TransferDescriptorLogicalAddress
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
);
44 NTSTATUS
FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
);
45 NTSTATUS
FindTransferDescriptorInIsochronousHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
);
47 VOID
CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor
);
48 POHCI_ENDPOINT_DESCRIPTOR
FindInterruptEndpointDescriptor(UCHAR InterruptInterval
);
49 VOID
PrintEndpointList(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
);
50 VOID
LinkEndpoint(POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor
, POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
);
51 VOID
AddEndpointDescriptor(IN POHCI_ENDPOINT_DESCRIPTOR Descriptor
);
54 // constructor / destructor
55 CUSBQueue(IUnknown
*OuterUnknown
){}
56 virtual ~CUSBQueue(){}
59 LONG m_Ref
; // reference count
60 KSPIN_LOCK m_Lock
; // list lock
61 POHCIHARDWAREDEVICE m_Hardware
; // hardware
62 POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor
; // bulk head descriptor
63 POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor
; // control head descriptor
64 POHCI_ENDPOINT_DESCRIPTOR m_IsoHeadEndpointDescriptor
; // isochronous head descriptor
65 POHCI_ENDPOINT_DESCRIPTOR
* m_InterruptEndpoints
;
66 LIST_ENTRY m_PendingRequestList
; // pending request list
69 //=================================================================================================
74 CUSBQueue::QueryInterface(
78 if (IsEqualGUIDAligned(refiid
, IID_IUnknown
))
80 *Output
= PVOID(PUNKNOWN(this));
81 PUNKNOWN(*Output
)->AddRef();
82 return STATUS_SUCCESS
;
85 return STATUS_UNSUCCESSFUL
;
89 CUSBQueue::Initialize(
90 IN PUSBHARDWAREDEVICE Hardware
,
91 IN PDMA_ADAPTER AdapterObject
,
92 IN PDMAMEMORYMANAGER MemManager
,
93 IN OPTIONAL PKSPIN_LOCK Lock
)
98 m_Hardware
= POHCIHARDWAREDEVICE(Hardware
);
102 // get bulk endpoint descriptor
104 m_Hardware
->GetBulkHeadEndpointDescriptor(&m_BulkHeadEndpointDescriptor
);
107 // get control endpoint descriptor
109 m_Hardware
->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor
);
112 // get isochronous endpoint
114 m_Hardware
->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor
);
117 // get interrupt endpoints
119 m_Hardware
->GetInterruptEndpointDescriptors(&m_InterruptEndpoints
);
122 // initialize spinlock
124 KeInitializeSpinLock(&m_Lock
);
129 InitializeListHead(&m_PendingRequestList
);
131 return STATUS_SUCCESS
;
135 CUSBQueue::LinkEndpoint(
136 POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor
,
137 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
139 POHCI_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
= HeadEndpointDescriptor
;
142 // get last descriptor in queue
144 while(CurrentEndpointDescriptor
->NextDescriptor
)
147 // move to last descriptor
149 CurrentEndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentEndpointDescriptor
->NextDescriptor
;
155 CurrentEndpointDescriptor
->NextPhysicalEndpoint
= EndpointDescriptor
->PhysicalAddress
.LowPart
;
156 CurrentEndpointDescriptor
->NextDescriptor
= EndpointDescriptor
;
161 CUSBQueue::AddEndpointDescriptor(
162 IN POHCI_ENDPOINT_DESCRIPTOR Descriptor
)
164 IOHCIRequest
*Request
;
166 POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor
;
167 POHCI_ISO_TD CurrentDescriptor
;
175 ASSERT(Descriptor
->Request
);
176 Request
= (IOHCIRequest
*)Descriptor
->Request
;
181 Type
= Request
->GetTransferType();
186 if (Type
== USB_ENDPOINT_TYPE_BULK
)
189 // get head descriptor
191 HeadDescriptor
= m_BulkHeadEndpointDescriptor
;
193 else if (Type
== USB_ENDPOINT_TYPE_CONTROL
)
196 // get head descriptor
198 HeadDescriptor
= m_ControlHeadEndpointDescriptor
;
200 else if (Type
== USB_ENDPOINT_TYPE_INTERRUPT
)
203 // get head descriptor
205 HeadDescriptor
= FindInterruptEndpointDescriptor(Request
->GetInterval());
206 ASSERT(HeadDescriptor
);
208 else if (Type
== USB_ENDPOINT_TYPE_ISOCHRONOUS
)
211 // get head descriptor
213 HeadDescriptor
= m_IsoHeadEndpointDescriptor
;
216 // get current frame number
218 m_Hardware
->GetCurrentFrameNumber(&FrameNumber
);
221 // FIXME: increment frame number
226 // apply frame number to iso transfer descriptors
228 CurrentDescriptor
= (POHCI_ISO_TD
)Descriptor
->HeadLogicalDescriptor
;
230 DPRINT("ISO: NextFrameNumber %x\n", FrameNumber
);
231 Frame
= (FrameNumber
& 0xFFFF);
233 while(CurrentDescriptor
)
236 // set current frame number
238 CurrentDescriptor
->Flags
|= OHCI_ITD_SET_STARTING_FRAME(Frame
);
241 // move to next frame number
243 Frame
+= OHCI_ITD_GET_FRAME_COUNT(CurrentDescriptor
->Flags
);
246 // move to next descriptor
248 CurrentDescriptor
= CurrentDescriptor
->NextLogicalDescriptor
;
252 // get current frame number
254 m_Hardware
->GetCurrentFrameNumber(&FrameNumber
);
256 DPRINT("Hardware 1ms %p Iso %p\n",m_InterruptEndpoints
[0], m_IsoHeadEndpointDescriptor
);
257 ASSERT(m_InterruptEndpoints
[0]->NextPhysicalEndpoint
== m_IsoHeadEndpointDescriptor
->PhysicalAddress
.LowPart
);
259 PrintEndpointList(m_IsoHeadEndpointDescriptor
);
271 // set descriptor active
273 Descriptor
->Flags
&= ~OHCI_ENDPOINT_SKIP
;
276 // insert endpoint at end
278 LinkEndpoint(HeadDescriptor
, Descriptor
);
280 if (Type
== USB_ENDPOINT_TYPE_CONTROL
|| Type
== USB_ENDPOINT_TYPE_BULK
)
283 // notify hardware of our request
285 m_Hardware
->HeadEndpointDescriptorModified(Type
);
291 CUSBQueue::AddUSBRequest(
295 IN POHCI_ENDPOINT_DESCRIPTOR Descriptor
;
296 POHCIREQUEST Request
;
298 DPRINT("CUSBQueue::AddUSBRequest\n");
301 Request
= POHCIREQUEST(Req
);
307 ASSERT(Request
!= NULL
);
310 // add extra reference which is released when the request is completed
315 // get transfer descriptors
317 Status
= Request
->GetEndpointDescriptor(&Descriptor
);
318 if (!NT_SUCCESS(Status
))
321 // failed to get transfer descriptor
323 DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with %x\n", Status
);
335 AddEndpointDescriptor(Descriptor
);
336 return STATUS_SUCCESS
;
340 CUSBQueue::CreateUSBRequest(
341 IUSBRequest
**OutRequest
)
343 PUSBREQUEST UsbRequest
;
347 Status
= InternalCreateUSBRequest(&UsbRequest
);
349 if (NT_SUCCESS(Status
))
351 *OutRequest
= UsbRequest
;
358 CUSBQueue::FindTransferDescriptorInEndpoint(
359 IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
360 IN ULONG TransferDescriptorLogicalAddress
,
361 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
,
362 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
)
364 POHCI_ENDPOINT_DESCRIPTOR LastDescriptor
= EndpointDescriptor
;
368 // skip first endpoint head
370 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
372 while(EndpointDescriptor
)
375 // check if the transfer descriptor is inside the list
377 if ((EndpointDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HEAD_MASK
) == EndpointDescriptor
->TailPhysicalDescriptor
|| (EndpointDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HALTED
))
382 *OutEndpointDescriptor
= EndpointDescriptor
;
383 *OutPreviousEndpointDescriptor
= LastDescriptor
;
388 return STATUS_SUCCESS
;
392 // store last endpoint
394 LastDescriptor
= EndpointDescriptor
;
399 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
403 // failed to endpoint
405 return STATUS_NOT_FOUND
;
409 CUSBQueue::FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
)
415 // search descriptor in endpoint list
417 for(Index
= 0; Index
< OHCI_STATIC_ENDPOINT_COUNT
; Index
++)
420 // is it in current endpoint
422 Status
= FindTransferDescriptorInEndpoint(m_InterruptEndpoints
[Index
], TransferDescriptorLogicalAddress
, OutEndpointDescriptor
, OutPreviousEndpointDescriptor
);
423 if (NT_SUCCESS(Status
))
426 // found transfer descriptor
428 return STATUS_SUCCESS
;
435 return STATUS_NOT_FOUND
;
439 CUSBQueue::FindTransferDescriptorInIsochronousHeadEndpoints(
440 IN ULONG TransferDescriptorLogicalAddress
,
441 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
,
442 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
)
444 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
445 POHCI_ENDPOINT_DESCRIPTOR LastDescriptor
= m_IsoHeadEndpointDescriptor
;
449 // skip first endpoint head
451 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)m_IsoHeadEndpointDescriptor
->NextDescriptor
;
453 while(EndpointDescriptor
)
456 // check if the transfer descriptor is inside the list
458 if (IsTransferDescriptorInIsoEndpoint(EndpointDescriptor
, TransferDescriptorLogicalAddress
))
463 *OutEndpointDescriptor
= EndpointDescriptor
;
464 *OutPreviousEndpointDescriptor
= LastDescriptor
;
469 return STATUS_SUCCESS
;
473 // store last endpoint
475 LastDescriptor
= EndpointDescriptor
;
480 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
484 // failed to endpoint
486 return STATUS_NOT_FOUND
;
490 CUSBQueue::IsTransferDescriptorInIsoEndpoint(
491 IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
492 IN ULONG TransferDescriptorLogicalAddress
)
494 POHCI_ISO_TD Descriptor
;
497 // get first general transfer descriptor
499 Descriptor
= (POHCI_ISO_TD
)EndpointDescriptor
->HeadLogicalDescriptor
;
508 if (Descriptor
->PhysicalAddress
.LowPart
== TransferDescriptorLogicalAddress
)
519 Descriptor
= (POHCI_ISO_TD
)Descriptor
->NextLogicalDescriptor
;
523 // no descriptor found
530 CUSBQueue::IsTransferDescriptorInEndpoint(
531 IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
532 IN ULONG TransferDescriptorLogicalAddress
)
534 POHCI_GENERAL_TD Descriptor
;
537 // get first general transfer descriptor
539 Descriptor
= (POHCI_GENERAL_TD
)EndpointDescriptor
->HeadLogicalDescriptor
;
548 if (Descriptor
->PhysicalAddress
.LowPart
== TransferDescriptorLogicalAddress
)
559 Descriptor
= (POHCI_GENERAL_TD
)Descriptor
->NextLogicalDescriptor
;
564 // no descriptor found
570 CUSBQueue::CleanupEndpointDescriptor(
571 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
572 POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor
)
574 POHCIREQUEST Request
;
575 POHCI_ENDPOINT_DESCRIPTOR NewEndpointDescriptor
;
576 USBD_STATUS UrbStatus
;
580 // FIXME: verify unlinking process
582 PreviousEndpointDescriptor
->NextDescriptor
= EndpointDescriptor
->NextDescriptor
;
583 PreviousEndpointDescriptor
->NextPhysicalEndpoint
= EndpointDescriptor
->NextPhysicalEndpoint
;
586 // get corresponding request
588 Request
= POHCIREQUEST(EndpointDescriptor
->Request
);
594 if (EndpointDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HALTED
)
597 // the real error will processed by IUSBRequest
599 UrbStatus
= USBD_STATUS_STALL_PID
;
606 UrbStatus
= USBD_STATUS_SUCCESS
;
610 // Check if the transfer was completed and if UrbStatus is ok
612 if ((Request
->IsRequestComplete() == FALSE
) && (UrbStatus
== USBD_STATUS_SUCCESS
))
615 // request is incomplete, get new queue head
617 if (Request
->GetEndpointDescriptor(&NewEndpointDescriptor
) == STATUS_SUCCESS
)
620 // notify of completion
622 Request
->FreeEndpointDescriptor(EndpointDescriptor
);
625 // first acquire request lock
627 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
630 // add to pending list
632 InsertTailList(&m_PendingRequestList
, &NewEndpointDescriptor
->DescriptorListEntry
);
635 // release queue head
637 KeReleaseSpinLock(&m_Lock
, OldLevel
);
644 DPRINT1("Unable to create a new QueueHead\n");
648 // Else there was a problem
649 // FIXME: Find better return
650 UrbStatus
= USBD_STATUS_INSUFFICIENT_RESOURCES
;
653 if (UrbStatus
!= USBD_STATUS_SUCCESS
)
655 DPRINT1("URB failed with status 0x%x\n", UrbStatus
);
660 // free endpoint descriptor
662 Request
->FreeEndpointDescriptor(EndpointDescriptor
);
665 // notify of completion
667 Request
->CompletionCallback();
677 CUSBQueue::PrintEndpointList(
678 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
680 DPRINT1("CUSBQueue::PrintEndpointList HeadEndpoint %p Logical %x\n", EndpointDescriptor
, EndpointDescriptor
->PhysicalAddress
.LowPart
);
683 // get first general transfer descriptor
685 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
687 while(EndpointDescriptor
)
689 DPRINT1(" CUSBQueue::PrintEndpointList Endpoint %p Logical %x\n", EndpointDescriptor
, EndpointDescriptor
->PhysicalAddress
.LowPart
);
694 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
699 CUSBQueue::TransferDescriptorCompletionCallback(
700 ULONG TransferDescriptorLogicalAddress
)
702 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, PreviousEndpointDescriptor
;
706 DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress
);
711 // find transfer descriptor in control list
713 Status
= FindTransferDescriptorInEndpoint(m_ControlHeadEndpointDescriptor
, TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
714 if (NT_SUCCESS(Status
))
719 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
728 // find transfer descriptor in bulk list
730 Status
= FindTransferDescriptorInEndpoint(m_BulkHeadEndpointDescriptor
, TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
731 if (NT_SUCCESS(Status
))
736 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
745 // find transfer descriptor in interrupt list
747 Status
= FindTransferDescriptorInInterruptHeadEndpoints(TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
748 if (NT_SUCCESS(Status
))
753 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
762 // last try: find the descriptor in isochronous list
764 Status
= FindTransferDescriptorInIsochronousHeadEndpoints(TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
765 if (NT_SUCCESS(Status
))
770 DPRINT("ISO endpoint complete\n");
772 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
781 // no more completed descriptors found
791 KeAcquireSpinLockAtDpcLevel(&m_Lock
);
794 // is there a pending list item
796 if (!IsListEmpty(&m_PendingRequestList
))
801 Entry
= RemoveHeadList(&m_PendingRequestList
);
806 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CONTAINING_RECORD(Entry
, OHCI_ENDPOINT_DESCRIPTOR
, DescriptorListEntry
);
811 AddEndpointDescriptor(EndpointDescriptor
);
817 KeReleaseSpinLockFromDpcLevel(&m_Lock
);
820 POHCI_ENDPOINT_DESCRIPTOR
821 CUSBQueue::FindInterruptEndpointDescriptor(
822 UCHAR InterruptInterval
)
830 ASSERT(InterruptInterval
<= OHCI_BIGGEST_INTERVAL
);
833 // find interrupt index
835 while (Power
<= OHCI_BIGGEST_INTERVAL
/ 2)
838 // is current interval greater
840 if (Power
* 2 > InterruptInterval
)
849 // move to next interrupt
854 DPRINT("InterruptInterval %lu Selected InterruptIndex %lu Choosen Interval %lu\n", InterruptInterval
, Index
, Power
);
859 return m_InterruptEndpoints
[Index
];
863 CUSBQueue::AbortDevicePipe(
864 IN UCHAR DeviceAddress
,
865 IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
867 POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor
, CurrentDescriptor
, PreviousDescriptor
, TempDescriptor
;
869 POHCI_GENERAL_TD TransferDescriptor
;
874 Type
= (EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
879 if (Type
== USB_ENDPOINT_TYPE_BULK
)
882 // get head descriptor
884 HeadDescriptor
= m_BulkHeadEndpointDescriptor
;
886 else if (Type
== USB_ENDPOINT_TYPE_CONTROL
)
889 // get head descriptor
891 HeadDescriptor
= m_ControlHeadEndpointDescriptor
;
893 else if (Type
== USB_ENDPOINT_TYPE_INTERRUPT
)
896 // get head descriptor
898 HeadDescriptor
= FindInterruptEndpointDescriptor(EndpointDescriptor
->bInterval
);
899 ASSERT(HeadDescriptor
);
906 ASSERT(Type
== USB_ENDPOINT_TYPE_ISOCHRONOUS
);
908 return STATUS_NOT_IMPLEMENTED
;
912 // FIXME should disable list processing
916 // now remove all endpoints
918 ASSERT(HeadDescriptor
);
919 CurrentDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)HeadDescriptor
->NextDescriptor
;
920 PreviousDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)HeadDescriptor
;
922 while(CurrentDescriptor
)
924 if ((CurrentDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HEAD_MASK
) == CurrentDescriptor
->TailPhysicalDescriptor
|| (CurrentDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HALTED
))
929 TempDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
->NextDescriptor
;
930 CleanupEndpointDescriptor(CurrentDescriptor
, PreviousDescriptor
);
933 // use next descriptor
935 CurrentDescriptor
= TempDescriptor
;
938 if (!CurrentDescriptor
)
941 if (CurrentDescriptor
->HeadPhysicalDescriptor
)
943 TransferDescriptor
= (POHCI_GENERAL_TD
)CurrentDescriptor
->HeadLogicalDescriptor
;
944 ASSERT(TransferDescriptor
);
946 if ((OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(TransferDescriptor
->Flags
) == (EndpointDescriptor
->bEndpointAddress
& 0xF)) &&
947 (OHCI_ENDPOINT_GET_DEVICE_ADDRESS(TransferDescriptor
->Flags
) == DeviceAddress
))
952 TempDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
->NextDescriptor
;
953 CleanupEndpointDescriptor(CurrentDescriptor
, PreviousDescriptor
);
955 // use next descriptor
957 CurrentDescriptor
= TempDescriptor
;
961 if (!CurrentDescriptor
)
964 PreviousDescriptor
= CurrentDescriptor
;
965 CurrentDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
->NextDescriptor
;
971 return STATUS_SUCCESS
;
977 PUSBQUEUE
*OutUsbQueue
)
982 // allocate controller
984 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBQueue(0);
988 // failed to allocate
990 return STATUS_INSUFFICIENT_RESOURCES
;
994 // add reference count
1001 *OutUsbQueue
= (PUSBQUEUE
)This
;
1006 return STATUS_SUCCESS
;