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 IOHCIQueue
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
;
90 CUSBQueue::Initialize(
91 IN PUSBHARDWAREDEVICE Hardware
,
92 IN PDMA_ADAPTER AdapterObject
,
93 IN PDMAMEMORYMANAGER MemManager
,
94 IN OPTIONAL PKSPIN_LOCK Lock
)
99 DPRINT1("[USBOHCI] Failed to initialize queue\n");
100 return STATUS_UNSUCCESSFUL
;
106 m_Hardware
= POHCIHARDWAREDEVICE(Hardware
);
110 // get bulk endpoint descriptor
112 m_Hardware
->GetBulkHeadEndpointDescriptor(&m_BulkHeadEndpointDescriptor
);
115 // get control endpoint descriptor
117 m_Hardware
->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor
);
120 // get isochronous endpoint
122 m_Hardware
->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor
);
125 // get interrupt endpoints
127 m_Hardware
->GetInterruptEndpointDescriptors(&m_InterruptEndpoints
);
130 // initialize spinlock
132 KeInitializeSpinLock(&m_Lock
);
137 InitializeListHead(&m_PendingRequestList
);
139 return STATUS_SUCCESS
;
143 CUSBQueue::LinkEndpoint(
144 POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor
,
145 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
147 POHCI_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
= HeadEndpointDescriptor
;
150 // get last descriptor in queue
152 while(CurrentEndpointDescriptor
->NextDescriptor
)
155 // move to last descriptor
157 CurrentEndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentEndpointDescriptor
->NextDescriptor
;
163 CurrentEndpointDescriptor
->NextPhysicalEndpoint
= EndpointDescriptor
->PhysicalAddress
.LowPart
;
164 CurrentEndpointDescriptor
->NextDescriptor
= EndpointDescriptor
;
169 CUSBQueue::AddEndpointDescriptor(
170 IN POHCI_ENDPOINT_DESCRIPTOR Descriptor
)
172 IOHCIRequest
*Request
;
174 POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor
;
175 POHCI_ISO_TD CurrentDescriptor
;
183 ASSERT(Descriptor
->Request
);
184 Request
= (IOHCIRequest
*)Descriptor
->Request
;
189 Type
= Request
->GetTransferType();
194 if (Type
== USB_ENDPOINT_TYPE_BULK
)
197 // get head descriptor
199 HeadDescriptor
= m_BulkHeadEndpointDescriptor
;
201 else if (Type
== USB_ENDPOINT_TYPE_CONTROL
)
204 // get head descriptor
206 HeadDescriptor
= m_ControlHeadEndpointDescriptor
;
208 else if (Type
== USB_ENDPOINT_TYPE_INTERRUPT
)
211 // get head descriptor
213 HeadDescriptor
= FindInterruptEndpointDescriptor(Request
->GetInterval());
214 ASSERT(HeadDescriptor
);
216 else if (Type
== USB_ENDPOINT_TYPE_ISOCHRONOUS
)
219 // get head descriptor
221 HeadDescriptor
= m_IsoHeadEndpointDescriptor
;
224 // get current frame number
226 m_Hardware
->GetCurrentFrameNumber(&FrameNumber
);
229 // FIXME: increment frame number
234 // apply frame number to iso transfer descriptors
236 CurrentDescriptor
= (POHCI_ISO_TD
)Descriptor
->HeadLogicalDescriptor
;
238 DPRINT("ISO: NextFrameNumber %x\n", FrameNumber
);
239 Frame
= (FrameNumber
& 0xFFFF);
241 while(CurrentDescriptor
)
244 // set current frame number
246 CurrentDescriptor
->Flags
|= OHCI_ITD_SET_STARTING_FRAME(Frame
);
249 // move to next frame number
251 Frame
+= OHCI_ITD_GET_FRAME_COUNT(CurrentDescriptor
->Flags
);
254 // move to next descriptor
256 CurrentDescriptor
= CurrentDescriptor
->NextLogicalDescriptor
;
260 // get current frame number
262 m_Hardware
->GetCurrentFrameNumber(&FrameNumber
);
264 DPRINT("Hardware 1ms %p Iso %p\n",m_InterruptEndpoints
[0], m_IsoHeadEndpointDescriptor
);
265 ASSERT(m_InterruptEndpoints
[0]->NextPhysicalEndpoint
== m_IsoHeadEndpointDescriptor
->PhysicalAddress
.LowPart
);
267 PrintEndpointList(m_IsoHeadEndpointDescriptor
);
279 // set descriptor active
281 Descriptor
->Flags
&= ~OHCI_ENDPOINT_SKIP
;
284 // insert endpoint at end
286 LinkEndpoint(HeadDescriptor
, Descriptor
);
288 if (Type
== USB_ENDPOINT_TYPE_CONTROL
|| Type
== USB_ENDPOINT_TYPE_BULK
)
291 // notify hardware of our request
293 m_Hardware
->HeadEndpointDescriptorModified(Type
);
300 CUSBQueue::AddUSBRequest(
304 IN POHCI_ENDPOINT_DESCRIPTOR Descriptor
;
305 POHCIREQUEST Request
;
307 DPRINT("CUSBQueue::AddUSBRequest\n");
310 Request
= POHCIREQUEST(Req
);
316 ASSERT(Request
!= NULL
);
319 // add extra reference which is released when the request is completed
324 // get transfer descriptors
326 Status
= Request
->GetEndpointDescriptor(&Descriptor
);
327 if (!NT_SUCCESS(Status
))
330 // failed to get transfer descriptor
332 DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with %x\n", Status
);
344 AddEndpointDescriptor(Descriptor
);
345 return STATUS_SUCCESS
;
350 CUSBQueue::CreateUSBRequest(
351 IUSBRequest
**OutRequest
)
353 PUSBREQUEST UsbRequest
;
357 Status
= InternalCreateUSBRequest(&UsbRequest
);
359 if (NT_SUCCESS(Status
))
361 *OutRequest
= UsbRequest
;
368 CUSBQueue::FindTransferDescriptorInEndpoint(
369 IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
370 IN ULONG TransferDescriptorLogicalAddress
,
371 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
,
372 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
)
374 POHCI_ENDPOINT_DESCRIPTOR LastDescriptor
= EndpointDescriptor
;
378 // skip first endpoint head
380 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
382 while(EndpointDescriptor
)
385 // check if the transfer descriptor is inside the list
387 if ((EndpointDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HEAD_MASK
) == EndpointDescriptor
->TailPhysicalDescriptor
|| (EndpointDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HALTED
))
392 *OutEndpointDescriptor
= EndpointDescriptor
;
393 *OutPreviousEndpointDescriptor
= LastDescriptor
;
398 return STATUS_SUCCESS
;
402 // store last endpoint
404 LastDescriptor
= EndpointDescriptor
;
409 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
413 // failed to endpoint
415 return STATUS_NOT_FOUND
;
419 CUSBQueue::FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
, OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
)
425 // search descriptor in endpoint list
427 for(Index
= 0; Index
< OHCI_STATIC_ENDPOINT_COUNT
; Index
++)
430 // is it in current endpoint
432 Status
= FindTransferDescriptorInEndpoint(m_InterruptEndpoints
[Index
], TransferDescriptorLogicalAddress
, OutEndpointDescriptor
, OutPreviousEndpointDescriptor
);
433 if (NT_SUCCESS(Status
))
436 // found transfer descriptor
438 return STATUS_SUCCESS
;
445 return STATUS_NOT_FOUND
;
449 CUSBQueue::FindTransferDescriptorInIsochronousHeadEndpoints(
450 IN ULONG TransferDescriptorLogicalAddress
,
451 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutEndpointDescriptor
,
452 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutPreviousEndpointDescriptor
)
454 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
455 POHCI_ENDPOINT_DESCRIPTOR LastDescriptor
= m_IsoHeadEndpointDescriptor
;
459 // skip first endpoint head
461 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)m_IsoHeadEndpointDescriptor
->NextDescriptor
;
463 while(EndpointDescriptor
)
466 // check if the transfer descriptor is inside the list
468 if (IsTransferDescriptorInIsoEndpoint(EndpointDescriptor
, TransferDescriptorLogicalAddress
))
473 *OutEndpointDescriptor
= EndpointDescriptor
;
474 *OutPreviousEndpointDescriptor
= LastDescriptor
;
479 return STATUS_SUCCESS
;
483 // store last endpoint
485 LastDescriptor
= EndpointDescriptor
;
490 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
494 // failed to endpoint
496 return STATUS_NOT_FOUND
;
500 CUSBQueue::IsTransferDescriptorInIsoEndpoint(
501 IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
502 IN ULONG TransferDescriptorLogicalAddress
)
504 POHCI_ISO_TD Descriptor
;
507 // get first general transfer descriptor
509 Descriptor
= (POHCI_ISO_TD
)EndpointDescriptor
->HeadLogicalDescriptor
;
518 if (Descriptor
->PhysicalAddress
.LowPart
== TransferDescriptorLogicalAddress
)
529 Descriptor
= (POHCI_ISO_TD
)Descriptor
->NextLogicalDescriptor
;
533 // no descriptor found
540 CUSBQueue::IsTransferDescriptorInEndpoint(
541 IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
542 IN ULONG TransferDescriptorLogicalAddress
)
544 POHCI_GENERAL_TD Descriptor
;
547 // get first general transfer descriptor
549 Descriptor
= (POHCI_GENERAL_TD
)EndpointDescriptor
->HeadLogicalDescriptor
;
558 if (Descriptor
->PhysicalAddress
.LowPart
== TransferDescriptorLogicalAddress
)
569 Descriptor
= (POHCI_GENERAL_TD
)Descriptor
->NextLogicalDescriptor
;
574 // no descriptor found
580 CUSBQueue::CleanupEndpointDescriptor(
581 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
582 POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor
)
584 POHCIREQUEST Request
;
585 POHCI_ENDPOINT_DESCRIPTOR NewEndpointDescriptor
;
586 USBD_STATUS UrbStatus
;
590 // FIXME: verify unlinking process
592 PreviousEndpointDescriptor
->NextDescriptor
= EndpointDescriptor
->NextDescriptor
;
593 PreviousEndpointDescriptor
->NextPhysicalEndpoint
= EndpointDescriptor
->NextPhysicalEndpoint
;
596 // get corresponding request
598 Request
= POHCIREQUEST(EndpointDescriptor
->Request
);
604 if (EndpointDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HALTED
)
607 // the real error will processed by IUSBRequest
609 UrbStatus
= USBD_STATUS_STALL_PID
;
616 UrbStatus
= USBD_STATUS_SUCCESS
;
620 // Check if the transfer was completed and if UrbStatus is ok
622 if ((Request
->IsRequestComplete() == FALSE
) && (UrbStatus
== USBD_STATUS_SUCCESS
))
625 // request is incomplete, get new queue head
627 if (Request
->GetEndpointDescriptor(&NewEndpointDescriptor
) == STATUS_SUCCESS
)
630 // notify of completion
632 Request
->FreeEndpointDescriptor(EndpointDescriptor
);
635 // first acquire request lock
637 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
640 // add to pending list
642 InsertTailList(&m_PendingRequestList
, &NewEndpointDescriptor
->DescriptorListEntry
);
645 // release queue head
647 KeReleaseSpinLock(&m_Lock
, OldLevel
);
654 DPRINT1("Unable to create a new QueueHead\n");
658 // Else there was a problem
659 // FIXME: Find better return
660 UrbStatus
= USBD_STATUS_INSUFFICIENT_RESOURCES
;
663 if (UrbStatus
!= USBD_STATUS_SUCCESS
)
665 DPRINT1("URB failed with status 0x%x\n", UrbStatus
);
670 // free endpoint descriptor
672 Request
->FreeEndpointDescriptor(EndpointDescriptor
);
675 // notify of completion
677 Request
->CompletionCallback();
687 CUSBQueue::PrintEndpointList(
688 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
690 DPRINT1("CUSBQueue::PrintEndpointList HeadEndpoint %p Logical %x\n", EndpointDescriptor
, EndpointDescriptor
->PhysicalAddress
.LowPart
);
693 // get first general transfer descriptor
695 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
697 while(EndpointDescriptor
)
699 DPRINT1(" CUSBQueue::PrintEndpointList Endpoint %p Logical %x\n", EndpointDescriptor
, EndpointDescriptor
->PhysicalAddress
.LowPart
);
704 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)EndpointDescriptor
->NextDescriptor
;
710 CUSBQueue::TransferDescriptorCompletionCallback(
711 ULONG TransferDescriptorLogicalAddress
)
713 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor
, PreviousEndpointDescriptor
;
717 DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress
);
722 // find transfer descriptor in control list
724 Status
= FindTransferDescriptorInEndpoint(m_ControlHeadEndpointDescriptor
, TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
725 if (NT_SUCCESS(Status
))
730 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
739 // find transfer descriptor in bulk list
741 Status
= FindTransferDescriptorInEndpoint(m_BulkHeadEndpointDescriptor
, TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
742 if (NT_SUCCESS(Status
))
747 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
756 // find transfer descriptor in interrupt list
758 Status
= FindTransferDescriptorInInterruptHeadEndpoints(TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
759 if (NT_SUCCESS(Status
))
764 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
773 // last try: find the descriptor in isochronous list
775 Status
= FindTransferDescriptorInIsochronousHeadEndpoints(TransferDescriptorLogicalAddress
, &EndpointDescriptor
, &PreviousEndpointDescriptor
);
776 if (NT_SUCCESS(Status
))
781 DPRINT("ISO endpoint complete\n");
783 CleanupEndpointDescriptor(EndpointDescriptor
, PreviousEndpointDescriptor
);
792 // no more completed descriptors found
802 KeAcquireSpinLockAtDpcLevel(&m_Lock
);
805 // is there a pending list item
807 if (!IsListEmpty(&m_PendingRequestList
))
812 Entry
= RemoveHeadList(&m_PendingRequestList
);
817 EndpointDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CONTAINING_RECORD(Entry
, OHCI_ENDPOINT_DESCRIPTOR
, DescriptorListEntry
);
822 AddEndpointDescriptor(EndpointDescriptor
);
828 KeReleaseSpinLockFromDpcLevel(&m_Lock
);
831 POHCI_ENDPOINT_DESCRIPTOR
832 CUSBQueue::FindInterruptEndpointDescriptor(
833 UCHAR InterruptInterval
)
841 ASSERT(InterruptInterval
<= OHCI_BIGGEST_INTERVAL
);
844 // find interrupt index
846 while (Power
<= OHCI_BIGGEST_INTERVAL
/ 2)
849 // is current interval greater
851 if (Power
* 2 > InterruptInterval
)
860 // move to next interrupt
865 DPRINT("InterruptInterval %lu Selected InterruptIndex %lu Choosen Interval %lu\n", InterruptInterval
, Index
, Power
);
870 return m_InterruptEndpoints
[Index
];
875 CUSBQueue::AbortDevicePipe(
876 IN UCHAR DeviceAddress
,
877 IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
879 POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor
, CurrentDescriptor
, PreviousDescriptor
, TempDescriptor
;
881 POHCI_GENERAL_TD TransferDescriptor
;
886 Type
= (EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
);
891 if (Type
== USB_ENDPOINT_TYPE_BULK
)
894 // get head descriptor
896 HeadDescriptor
= m_BulkHeadEndpointDescriptor
;
898 else if (Type
== USB_ENDPOINT_TYPE_CONTROL
)
901 // get head descriptor
903 HeadDescriptor
= m_ControlHeadEndpointDescriptor
;
905 else if (Type
== USB_ENDPOINT_TYPE_INTERRUPT
)
908 // get head descriptor
910 HeadDescriptor
= FindInterruptEndpointDescriptor(EndpointDescriptor
->bInterval
);
911 ASSERT(HeadDescriptor
);
918 ASSERT(Type
== USB_ENDPOINT_TYPE_ISOCHRONOUS
);
920 return STATUS_NOT_IMPLEMENTED
;
924 // FIXME should disable list processing
928 // now remove all endpoints
930 ASSERT(HeadDescriptor
);
931 CurrentDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)HeadDescriptor
->NextDescriptor
;
932 PreviousDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)HeadDescriptor
;
934 while(CurrentDescriptor
)
936 if ((CurrentDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HEAD_MASK
) == CurrentDescriptor
->TailPhysicalDescriptor
|| (CurrentDescriptor
->HeadPhysicalDescriptor
& OHCI_ENDPOINT_HALTED
))
941 TempDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
->NextDescriptor
;
942 CleanupEndpointDescriptor(CurrentDescriptor
, PreviousDescriptor
);
945 // use next descriptor
947 CurrentDescriptor
= TempDescriptor
;
950 if (!CurrentDescriptor
)
953 if (CurrentDescriptor
->HeadPhysicalDescriptor
)
955 TransferDescriptor
= (POHCI_GENERAL_TD
)CurrentDescriptor
->HeadLogicalDescriptor
;
956 ASSERT(TransferDescriptor
);
958 if ((OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(TransferDescriptor
->Flags
) == (EndpointDescriptor
->bEndpointAddress
& 0xF)) &&
959 (OHCI_ENDPOINT_GET_DEVICE_ADDRESS(TransferDescriptor
->Flags
) == DeviceAddress
))
964 TempDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
->NextDescriptor
;
965 CleanupEndpointDescriptor(CurrentDescriptor
, PreviousDescriptor
);
967 // use next descriptor
969 CurrentDescriptor
= TempDescriptor
;
973 if (!CurrentDescriptor
)
976 PreviousDescriptor
= CurrentDescriptor
;
977 CurrentDescriptor
= (POHCI_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
->NextDescriptor
;
983 return STATUS_SUCCESS
;
990 PUSBQUEUE
*OutUsbQueue
)
995 // allocate controller
997 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBQueue(0);
1001 // failed to allocate
1003 return STATUS_INSUFFICIENT_RESOURCES
;
1007 // add reference count
1014 *OutUsbQueue
= (PUSBQUEUE
)This
;
1019 return STATUS_SUCCESS
;