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)
16 class CUSBQueue
: public IOHCIQueue
19 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
21 STDMETHODIMP_(ULONG
) AddRef()
23 InterlockedIncrement(&m_Ref
);
26 STDMETHODIMP_(ULONG
) Release()
28 InterlockedDecrement(&m_Ref
);
43 BOOLEAN
IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, IN ULONG TransferDescriptorLogicalAddress
);
44 BOOLEAN
IsTransferDescriptorInIsoEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, IN ULONG TransferDescriptorLogicalAddress
);
45 NTSTATUS
FindTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, IN ULONG TransferDescriptorLogicalAddress
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
);
46 NTSTATUS
FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
);
47 NTSTATUS
FindTransferDescriptorInIsochronousHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
);
49 VOID
CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor
);
50 POHCI_ENDPOINT_DESCRIPTOR
FindInterruptEndpointDescriptor(UCHAR InterruptInterval
);
51 VOID
PrintEndpointList(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
);
52 VOID
LinkEndpoint(POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor
, POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
);
53 VOID
AddEndpointDescriptor(IN POHCI_ENDPOINT_DESCRIPTOR Descriptor
);
56 // constructor / destructor
57 CUSBQueue(IUnknown
*OuterUnknown
){}
58 virtual ~CUSBQueue(){}
61 LONG m_Ref
; // reference count
62 KSPIN_LOCK m_Lock
; // list lock
63 POHCIHARDWAREDEVICE m_Hardware
; // hardware
64 POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor
; // bulk head descriptor
65 POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor
; // control head descriptor
66 POHCI_ENDPOINT_DESCRIPTOR m_IsoHeadEndpointDescriptor
; // isochronous head descriptor
67 POHCI_ENDPOINT_DESCRIPTOR
* m_InterruptEndpoints
;
68 LIST_ENTRY m_PendingRequestList
; // pending request list
71 //=================================================================================================
76 CUSBQueue::QueryInterface(
80 if (IsEqualGUIDAligned(refiid
, IID_IUnknown
))
82 *Output
= PVOID(PUNKNOWN(this));
83 PUNKNOWN(*Output
)->AddRef();
84 return STATUS_SUCCESS
;
87 return STATUS_UNSUCCESSFUL
;
92 CUSBQueue::Initialize(
93 IN PUSBHARDWAREDEVICE Hardware
,
94 IN PDMA_ADAPTER AdapterObject
,
95 IN PDMAMEMORYMANAGER MemManager
,
96 IN OPTIONAL PKSPIN_LOCK Lock
)
101 DPRINT1("[USBOHCI] Failed to initialize queue\n");
102 return STATUS_UNSUCCESSFUL
;
108 m_Hardware
= POHCIHARDWAREDEVICE(Hardware
);
112 // get bulk endpoint descriptor
114 m_Hardware
->GetBulkHeadEndpointDescriptor(&m_BulkHeadEndpointDescriptor
);
117 // get control endpoint descriptor
119 m_Hardware
->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor
);
122 // get isochronous endpoint
124 m_Hardware
->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor
);
127 // get interrupt endpoints
129 m_Hardware
->GetInterruptEndpointDescriptors(&m_InterruptEndpoints
);
132 // initialize spinlock
134 KeInitializeSpinLock(&m_Lock
);
139 InitializeListHead(&m_PendingRequestList
);
141 return STATUS_SUCCESS
;
145 CUSBQueue::LinkEndpoint(
146 POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor
,
147 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
149 POHCI_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
= HeadEndpointDescriptor
;
152 // get last descriptor in queue
154 while(CurrentEndpointDescriptor
->NextDescriptor
)
157 // move to last descriptor
159 CurrentEndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentEndpointDescriptor
->NextDescriptor
;
165 CurrentEndpointDescriptor
->NextPhysicalEndpoint
= EndpointDescriptor
->PhysicalAddress
.LowPart
;
166 CurrentEndpointDescriptor
->NextDescriptor
= EndpointDescriptor
;
171 CUSBQueue::AddEndpointDescriptor(
172 IN POHCI_ENDPOINT_DESCRIPTOR Descriptor
)
174 IOHCIRequest
*Request
;
176 POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor
;
177 POHCI_ISO_TD CurrentDescriptor
;
185 ASSERT(Descriptor
->Request
);
186 Request
= (IOHCIRequest
*)Descriptor
->Request
;
191 Type
= Request
->GetTransferType();
196 if (Type
== USB_ENDPOINT_TYPE_BULK
)
199 // get head descriptor
201 HeadDescriptor
= m_BulkHeadEndpointDescriptor
;
203 else if (Type
== USB_ENDPOINT_TYPE_CONTROL
)
206 // get head descriptor
208 HeadDescriptor
= m_ControlHeadEndpointDescriptor
;
210 else if (Type
== USB_ENDPOINT_TYPE_INTERRUPT
)
213 // get head descriptor
215 HeadDescriptor
= FindInterruptEndpointDescriptor(Request
->GetInterval());
216 ASSERT(HeadDescriptor
);
218 else if (Type
== USB_ENDPOINT_TYPE_ISOCHRONOUS
)
221 // get head descriptor
223 HeadDescriptor
= m_IsoHeadEndpointDescriptor
;
226 // get current frame number
228 m_Hardware
->GetCurrentFrameNumber(&FrameNumber
);
231 // FIXME: increment frame number
236 // apply frame number to iso transfer descriptors
238 CurrentDescriptor
= (POHCI_ISO_TD
)Descriptor
->HeadLogicalDescriptor
;
240 DPRINT("ISO: NextFrameNumber %x\n", FrameNumber
);
241 Frame
= (FrameNumber
& 0xFFFF);
243 while(CurrentDescriptor
)
246 // set current frame number
248 CurrentDescriptor
->Flags
|= OHCI_ITD_SET_STARTING_FRAME(Frame
);
251 // move to next frame number
253 Frame
+= OHCI_ITD_GET_FRAME_COUNT(CurrentDescriptor
->Flags
);
256 // move to next descriptor
258 CurrentDescriptor
= CurrentDescriptor
->NextLogicalDescriptor
;
262 // get current frame number
264 m_Hardware
->GetCurrentFrameNumber(&FrameNumber
);
266 DPRINT("Hardware 1ms %p Iso %p\n",m_InterruptEndpoints
[0], m_IsoHeadEndpointDescriptor
);
267 ASSERT(m_InterruptEndpoints
[0]->NextPhysicalEndpoint
== m_IsoHeadEndpointDescriptor
->PhysicalAddress
.LowPart
);
269 PrintEndpointList(m_IsoHeadEndpointDescriptor
);
281 // set descriptor active
283 Descriptor
->Flags
&= ~OHCI_ENDPOINT_SKIP
;
286 // insert endpoint at end
288 LinkEndpoint(HeadDescriptor
, Descriptor
);
290 if (Type
== USB_ENDPOINT_TYPE_CONTROL
|| Type
== USB_ENDPOINT_TYPE_BULK
)
293 // notify hardware of our request
295 m_Hardware
->HeadEndpointDescriptorModified(Type
);
302 CUSBQueue::AddUSBRequest(
306 IN POHCI_ENDPOINT_DESCRIPTOR Descriptor
;
307 POHCIREQUEST Request
;
309 DPRINT("CUSBQueue::AddUSBRequest\n");
312 Request
= POHCIREQUEST(Req
);
318 ASSERT(Request
!= NULL
);
321 // add extra reference which is released when the request is completed
326 // get transfer descriptors
328 Status
= Request
->GetEndpointDescriptor(&Descriptor
);
329 if (!NT_SUCCESS(Status
))
332 // failed to get transfer descriptor
334 DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with %x\n", Status
);
346 AddEndpointDescriptor(Descriptor
);
347 return STATUS_SUCCESS
;
352 CUSBQueue::CreateUSBRequest(
353 IUSBRequest
**OutRequest
)
355 PUSBREQUEST UsbRequest
;
359 Status
= InternalCreateUSBRequest(&UsbRequest
);
361 if (NT_SUCCESS(Status
))
363 *OutRequest
= UsbRequest
;
370 CUSBQueue::FindTransferDescriptorInEndpoint(
371 IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
372 IN ULONG TransferDescriptorLogicalAddress
,
373 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
,
374 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
)
376 POHCI_ENDPOINT_DESCRIPTOR LastDescriptor
= EndpointDescriptor
;
380 // skip first endpoint head
382 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
384 while(EndpointDescriptor
)
387 // check if the transfer descriptor is inside the list
389 if ((EndpointDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HEAD_MASK
) == EndpointDescriptor
->TailPhysicalDescriptor
|| (EndpointDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HALTED
))
394 *OutEndpointDescriptor
= EndpointDescriptor
;
395 *OutPreviousEndpointDescriptor
= LastDescriptor
;
400 return STATUS_SUCCESS
;
404 // store last endpoint
406 LastDescriptor
= EndpointDescriptor
;
411 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
415 // failed to endpoint
417 return STATUS_NOT_FOUND
;
421 CUSBQueue::FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
)
427 // search descriptor in endpoint list
429 for(Index
= 0; Index
< OHCI_STATIC_ENDPOINT_COUNT
; Index
++)
432 // is it in current endpoint
434 Status
= FindTransferDescriptorInEndpoint(m_InterruptEndpoints
[Index
], TransferDescriptorLogicalAddress
, OutEndpointDescriptor
, OutPreviousEndpointDescriptor
);
435 if (NT_SUCCESS(Status
))
438 // found transfer descriptor
440 return STATUS_SUCCESS
;
447 return STATUS_NOT_FOUND
;
451 CUSBQueue::FindTransferDescriptorInIsochronousHeadEndpoints(
452 IN ULONG TransferDescriptorLogicalAddress
,
453 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
,
454 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
)
456 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
457 POHCI_ENDPOINT_DESCRIPTOR LastDescriptor
= m_IsoHeadEndpointDescriptor
;
461 // skip first endpoint head
463 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)m_IsoHeadEndpointDescriptor
->NextDescriptor
;
465 while(EndpointDescriptor
)
468 // check if the transfer descriptor is inside the list
470 if (IsTransferDescriptorInIsoEndpoint(EndpointDescriptor
, TransferDescriptorLogicalAddress
))
475 *OutEndpointDescriptor
= EndpointDescriptor
;
476 *OutPreviousEndpointDescriptor
= LastDescriptor
;
481 return STATUS_SUCCESS
;
485 // store last endpoint
487 LastDescriptor
= EndpointDescriptor
;
492 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
496 // failed to endpoint
498 return STATUS_NOT_FOUND
;
502 CUSBQueue::IsTransferDescriptorInIsoEndpoint(
503 IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
504 IN ULONG TransferDescriptorLogicalAddress
)
506 POHCI_ISO_TD Descriptor
;
509 // get first general transfer descriptor
511 Descriptor
= (POHCI_ISO_TD
)EndpointDescriptor
->HeadLogicalDescriptor
;
520 if (Descriptor
->PhysicalAddress
.LowPart
== TransferDescriptorLogicalAddress
)
531 Descriptor
= (POHCI_ISO_TD
)Descriptor
->NextLogicalDescriptor
;
535 // no descriptor found
542 CUSBQueue::IsTransferDescriptorInEndpoint(
543 IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
544 IN ULONG TransferDescriptorLogicalAddress
)
546 POHCI_GENERAL_TD Descriptor
;
549 // get first general transfer descriptor
551 Descriptor
= (POHCI_GENERAL_TD
)EndpointDescriptor
->HeadLogicalDescriptor
;
560 if (Descriptor
->PhysicalAddress
.LowPart
== TransferDescriptorLogicalAddress
)
571 Descriptor
= (POHCI_GENERAL_TD
)Descriptor
->NextLogicalDescriptor
;
576 // no descriptor found
582 CUSBQueue::CleanupEndpointDescriptor(
583 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
584 POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor
)
586 POHCIREQUEST Request
;
587 POHCI_ENDPOINT_DESCRIPTOR NewEndpointDescriptor
;
588 USBD_STATUS UrbStatus
;
592 // FIXME: verify unlinking process
594 PreviousEndpointDescriptor
->NextDescriptor
= EndpointDescriptor
->NextDescriptor
;
595 PreviousEndpointDescriptor
->NextPhysicalEndpoint
= EndpointDescriptor
->NextPhysicalEndpoint
;
598 // get corresponding request
600 Request
= POHCIREQUEST(EndpointDescriptor
->Request
);
606 if (EndpointDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HALTED
)
609 // the real error will processed by IUSBRequest
611 UrbStatus
= USBD_STATUS_STALL_PID
;
618 UrbStatus
= USBD_STATUS_SUCCESS
;
622 // Check if the transfer was completed and if UrbStatus is ok
624 if ((Request
->IsRequestComplete() == FALSE
) && (UrbStatus
== USBD_STATUS_SUCCESS
))
627 // request is incomplete, get new queue head
629 if (Request
->GetEndpointDescriptor(&NewEndpointDescriptor
) == STATUS_SUCCESS
)
632 // notify of completion
634 Request
->FreeEndpointDescriptor(EndpointDescriptor
);
637 // first acquire request lock
639 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
642 // add to pending list
644 InsertTailList(&m_PendingRequestList
, &NewEndpointDescriptor
->DescriptorListEntry
);
647 // release queue head
649 KeReleaseSpinLock(&m_Lock
, OldLevel
);
656 DPRINT1("Unable to create a new QueueHead\n");
660 // Else there was a problem
661 // FIXME: Find better return
662 UrbStatus
= USBD_STATUS_INSUFFICIENT_RESOURCES
;
665 if (UrbStatus
!= USBD_STATUS_SUCCESS
)
667 DPRINT1("URB failed with status 0x%x\n", UrbStatus
);
672 // free endpoint descriptor
674 Request
->FreeEndpointDescriptor(EndpointDescriptor
);
677 // notify of completion
679 Request
->CompletionCallback();
689 CUSBQueue::PrintEndpointList(
690 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
692 DPRINT1("CUSBQueue::PrintEndpointList HeadEndpoint %p Logical %x\n", EndpointDescriptor
, EndpointDescriptor
->PhysicalAddress
.LowPart
);
695 // get first general transfer descriptor
697 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
699 while(EndpointDescriptor
)
701 DPRINT1(" CUSBQueue::PrintEndpointList Endpoint %p Logical %x\n", EndpointDescriptor
, EndpointDescriptor
->PhysicalAddress
.LowPart
);
706 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
712 CUSBQueue::TransferDescriptorCompletionCallback(
713 ULONG TransferDescriptorLogicalAddress
)
715 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, PreviousEndpointDescriptor
;
719 DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress
);
724 // find transfer descriptor in control list
726 Status
= FindTransferDescriptorInEndpoint(m_ControlHeadEndpointDescriptor
, TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
727 if (NT_SUCCESS(Status
))
732 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
741 // find transfer descriptor in bulk list
743 Status
= FindTransferDescriptorInEndpoint(m_BulkHeadEndpointDescriptor
, TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
744 if (NT_SUCCESS(Status
))
749 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
758 // find transfer descriptor in interrupt list
760 Status
= FindTransferDescriptorInInterruptHeadEndpoints(TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
761 if (NT_SUCCESS(Status
))
766 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
775 // last try: find the descriptor in isochronous list
777 Status
= FindTransferDescriptorInIsochronousHeadEndpoints(TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
778 if (NT_SUCCESS(Status
))
783 DPRINT("ISO endpoint complete\n");
785 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
794 // no more completed descriptors found
804 KeAcquireSpinLockAtDpcLevel(&m_Lock
);
807 // is there a pending list item
809 if (!IsListEmpty(&m_PendingRequestList
))
814 Entry
= RemoveHeadList(&m_PendingRequestList
);
819 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CONTAINING_RECORD(Entry
, OHCI_ENDPOINT_DESCRIPTOR
, DescriptorListEntry
);
824 AddEndpointDescriptor(EndpointDescriptor
);
830 KeReleaseSpinLockFromDpcLevel(&m_Lock
);
833 POHCI_ENDPOINT_DESCRIPTOR
834 CUSBQueue::FindInterruptEndpointDescriptor(
835 UCHAR InterruptInterval
)
843 ASSERT(InterruptInterval
<= OHCI_BIGGEST_INTERVAL
);
846 // find interrupt index
848 while (Power
<= OHCI_BIGGEST_INTERVAL
/ 2)
851 // is current interval greater
853 if (Power
* 2 > InterruptInterval
)
862 // move to next interrupt
867 DPRINT("InterruptInterval %lu Selected InterruptIndex %lu Chosen Interval %lu\n", InterruptInterval
, Index
, Power
);
872 return m_InterruptEndpoints
[Index
];
877 CUSBQueue::AbortDevicePipe(
878 IN UCHAR DeviceAddress
,
879 IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
881 POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor
, CurrentDescriptor
, PreviousDescriptor
, TempDescriptor
;
883 POHCI_GENERAL_TD TransferDescriptor
;
888 Type
= (EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
893 if (Type
== USB_ENDPOINT_TYPE_BULK
)
896 // get head descriptor
898 HeadDescriptor
= m_BulkHeadEndpointDescriptor
;
900 else if (Type
== USB_ENDPOINT_TYPE_CONTROL
)
903 // get head descriptor
905 HeadDescriptor
= m_ControlHeadEndpointDescriptor
;
907 else if (Type
== USB_ENDPOINT_TYPE_INTERRUPT
)
910 // get head descriptor
912 HeadDescriptor
= FindInterruptEndpointDescriptor(EndpointDescriptor
->bInterval
);
913 ASSERT(HeadDescriptor
);
920 ASSERT(Type
== USB_ENDPOINT_TYPE_ISOCHRONOUS
);
922 return STATUS_NOT_IMPLEMENTED
;
926 // FIXME should disable list processing
930 // now remove all endpoints
932 ASSERT(HeadDescriptor
);
933 CurrentDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)HeadDescriptor
->NextDescriptor
;
934 PreviousDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)HeadDescriptor
;
936 while(CurrentDescriptor
)
938 if ((CurrentDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HEAD_MASK
) == CurrentDescriptor
->TailPhysicalDescriptor
|| (CurrentDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HALTED
))
943 TempDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
->NextDescriptor
;
944 CleanupEndpointDescriptor(CurrentDescriptor
, PreviousDescriptor
);
947 // use next descriptor
949 CurrentDescriptor
= TempDescriptor
;
952 if (!CurrentDescriptor
)
955 if (CurrentDescriptor
->HeadPhysicalDescriptor
)
957 TransferDescriptor
= (POHCI_GENERAL_TD
)CurrentDescriptor
->HeadLogicalDescriptor
;
958 ASSERT(TransferDescriptor
);
960 if ((OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(TransferDescriptor
->Flags
) == (EndpointDescriptor
->bEndpointAddress
& 0xF)) &&
961 (OHCI_ENDPOINT_GET_DEVICE_ADDRESS(TransferDescriptor
->Flags
) == DeviceAddress
))
966 TempDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
->NextDescriptor
;
967 CleanupEndpointDescriptor(CurrentDescriptor
, PreviousDescriptor
);
969 // use next descriptor
971 CurrentDescriptor
= TempDescriptor
;
975 if (!CurrentDescriptor
)
978 PreviousDescriptor
= CurrentDescriptor
;
979 CurrentDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
->NextDescriptor
;
985 return STATUS_SUCCESS
;
992 PUSBQUEUE
*OutUsbQueue
)
997 // allocate controller
999 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBQueue(0);
1003 // failed to allocate
1005 return STATUS_INSUFFICIENT_RESOURCES
;
1009 // add reference count
1016 *OutUsbQueue
= (PUSBQUEUE
)This
;
1021 return STATUS_SUCCESS
;