[USBOHCI]

- Fix OHCI_ISO_TD structure. Fixes host system crashes in Windows XP
- Fix multiple bugs in isochronous transfer implementation
- Still not yet working, as the interrupt completion is not fired yet

svn path=/branches/usb-bringup/; revision=51998
This commit is contained in:
Johannes Anderwald 2011-05-29 19:54:55 +00:00
parent 2231c8333a
commit d2accc6c3e
3 changed files with 240 additions and 59 deletions

View file

@ -310,13 +310,22 @@ typedef struct _OHCI_ISO_TD_
ULONG BufferPhysical; // Physical page number of byte 0 ULONG BufferPhysical; // Physical page number of byte 0
ULONG NextPhysicalDescriptor; // Next isochronous transfer descriptor ULONG NextPhysicalDescriptor; // Next isochronous transfer descriptor
ULONG LastPhysicalByteAddress; // Physical buffer end ULONG LastPhysicalByteAddress; // Physical buffer end
ULONG Offset[OHCI_ITD_NOFFSET]; // Buffer offsets USHORT Offset[OHCI_ITD_NOFFSET]; // Buffer offsets
// Software part // Software part
PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this descriptor PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this descriptor
struct _OHCI_ISO_TD_ * NextLogicalDescriptor; // Logical pointer next descriptor struct _OHCI_ISO_TD_ * NextLogicalDescriptor; // Logical pointer next descriptor
}OHCI_ISO_TD, *POHCI_ISO_TD; }OHCI_ISO_TD, *POHCI_ISO_TD;
C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, Flags) == 0);
C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, BufferPhysical) == 4);
C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, NextPhysicalDescriptor) == 8);
C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, LastPhysicalByteAddress) == 12);
C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, Offset) == 16);
C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, PhysicalAddress) == 32);
C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, NextLogicalDescriptor) == 40);
C_ASSERT(sizeof(OHCI_ISO_TD) == 48);
#define OHCI_ITD_GET_STARTING_FRAME(x) ((x) & 0x0000ffff) #define OHCI_ITD_GET_STARTING_FRAME(x) ((x) & 0x0000ffff)
#define OHCI_ITD_SET_STARTING_FRAME(x) ((x) & 0xffff) #define OHCI_ITD_SET_STARTING_FRAME(x) ((x) & 0xffff)
#define OHCI_ITD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7) #define OHCI_ITD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7)

View file

@ -43,8 +43,10 @@ public:
// local functions // local functions
BOOLEAN IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress); BOOLEAN IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress);
BOOLEAN IsTransferDescriptorInIsoEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress);
NTSTATUS FindTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor); NTSTATUS FindTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor);
NTSTATUS FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor); NTSTATUS FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor);
NTSTATUS FindTransferDescriptorInIsochronousHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor);
VOID CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor); VOID CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor);
POHCI_ENDPOINT_DESCRIPTOR FindInterruptEndpointDescriptor(UCHAR InterruptInterval); POHCI_ENDPOINT_DESCRIPTOR FindInterruptEndpointDescriptor(UCHAR InterruptInterval);
@ -101,6 +103,8 @@ CUSBQueue::Initialize(
// //
Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor); Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor);
//
// get isochronous endpoint
// //
Hardware->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor); Hardware->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor);
@ -170,6 +174,7 @@ CUSBQueue::AddUSBRequest(
POHCI_ENDPOINT_DESCRIPTOR Descriptor; POHCI_ENDPOINT_DESCRIPTOR Descriptor;
POHCI_ISO_TD CurrentDescriptor; POHCI_ISO_TD CurrentDescriptor;
ULONG FrameNumber; ULONG FrameNumber;
USHORT Frame;
DPRINT("CUSBQueue::AddUSBRequest\n"); DPRINT("CUSBQueue::AddUSBRequest\n");
@ -244,9 +249,9 @@ CUSBQueue::AddUSBRequest(
m_Hardware->GetCurrentFrameNumber(&FrameNumber); m_Hardware->GetCurrentFrameNumber(&FrameNumber);
// //
// increment frame number // FIXME: increment frame number
// //
FrameNumber++; FrameNumber += 300;
// //
// apply frame number to iso transfer descriptors // apply frame number to iso transfer descriptors
@ -254,18 +259,19 @@ CUSBQueue::AddUSBRequest(
CurrentDescriptor = (POHCI_ISO_TD)Descriptor->HeadLogicalDescriptor; CurrentDescriptor = (POHCI_ISO_TD)Descriptor->HeadLogicalDescriptor;
DPRINT1("ISO: NextFrameNumber %x\n", FrameNumber); DPRINT1("ISO: NextFrameNumber %x\n", FrameNumber);
Frame = (FrameNumber & 0xFFFF);
while(CurrentDescriptor) while(CurrentDescriptor)
{ {
// //
// set current frame number // set current frame number
// //
CurrentDescriptor->Flags |= OHCI_ITD_SET_STARTING_FRAME(FrameNumber); CurrentDescriptor->Flags |= OHCI_ITD_SET_STARTING_FRAME(Frame);
// //
// move to next frame number // move to next frame number
// //
FrameNumber++; Frame += OHCI_ITD_GET_FRAME_COUNT(CurrentDescriptor->Flags);
// //
// move to next descriptor // move to next descriptor
@ -274,16 +280,16 @@ CUSBQueue::AddUSBRequest(
} }
} }
//
// insert endpoint at end
//
LinkEndpoint(HeadDescriptor, Descriptor);
// //
// set descriptor active // set descriptor active
// //
Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP; Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
//
// insert endpoint at end
//
LinkEndpoint(HeadDescriptor, Descriptor);
if (Type == USB_ENDPOINT_TYPE_CONTROL || Type == USB_ENDPOINT_TYPE_BULK) if (Type == USB_ENDPOINT_TYPE_CONTROL || Type == USB_ENDPOINT_TYPE_BULK)
{ {
// //
@ -402,6 +408,97 @@ CUSBQueue::FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescr
return STATUS_NOT_FOUND; return STATUS_NOT_FOUND;
} }
NTSTATUS
CUSBQueue::FindTransferDescriptorInIsochronousHeadEndpoints(
IN ULONG TransferDescriptorLogicalAddress,
OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor,
OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor)
{
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
POHCI_ENDPOINT_DESCRIPTOR LastDescriptor = m_IsoHeadEndpointDescriptor;
//
// skip first endpoint head
//
EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)m_IsoHeadEndpointDescriptor->NextDescriptor;
while(EndpointDescriptor)
{
//
// check if the transfer descriptor is inside the list
//
if (IsTransferDescriptorInIsoEndpoint(EndpointDescriptor, TransferDescriptorLogicalAddress))
{
//
// found endpoint
//
*OutEndpointDescriptor = EndpointDescriptor;
*OutPreviousEndpointDescriptor = LastDescriptor;
//
// done
//
return STATUS_SUCCESS;
}
//
// store last endpoint
//
LastDescriptor = EndpointDescriptor;
//
// move to next
//
EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor;
}
//
// failed to endpoint
//
return STATUS_NOT_FOUND;
}
BOOLEAN
CUSBQueue::IsTransferDescriptorInIsoEndpoint(
IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor,
IN ULONG TransferDescriptorLogicalAddress)
{
POHCI_ISO_TD Descriptor;
//
// get first general transfer descriptor
//
Descriptor = (POHCI_ISO_TD)EndpointDescriptor->HeadLogicalDescriptor;
//
// sanity check
//
ASSERT(Descriptor);
do
{
if (Descriptor->PhysicalAddress.LowPart == TransferDescriptorLogicalAddress)
{
//
// found descriptor
//
return TRUE;
}
//
// move to next
//
Descriptor = (POHCI_ISO_TD)Descriptor->NextLogicalDescriptor;
}while(Descriptor);
//
// no descriptor found
//
return FALSE;
}
BOOLEAN BOOLEAN
CUSBQueue::IsTransferDescriptorInEndpoint( CUSBQueue::IsTransferDescriptorInEndpoint(
IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor,
@ -476,6 +573,8 @@ CUSBQueue::CleanupEndpointDescriptor(
// //
//ASSERT(Request->IsRequestComplete()); //ASSERT(Request->IsRequestComplete());
Request->FreeEndpointDescriptor(EndpointDescriptor);
// //
// release request // release request
// //
@ -511,7 +610,7 @@ CUSBQueue::TransferDescriptorCompletionCallback(
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor; POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
NTSTATUS Status; NTSTATUS Status;
DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress); DPRINT1("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress);
// //
// find transfer descriptor in control list // find transfer descriptor in control list
@ -564,13 +663,30 @@ CUSBQueue::TransferDescriptorCompletionCallback(
return; return;
} }
//
// last try: find the descriptor in isochronous list
//
Status = FindTransferDescriptorInIsochronousHeadEndpoints(TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor);
if (NT_SUCCESS(Status))
{
//
// cleanup endpoint
//
DPRINT1("ISO endpoint complete\n");
ASSERT(FALSE);
CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor);
//
// done
//
return;
}
// //
// hardware reported dead endpoint completed // hardware reported dead endpoint completed
// //
DPRINT("CUSBQueue::TransferDescriptorCompletionCallback invalid transfer descriptor %x\n", TransferDescriptorLogicalAddress); DPRINT1("CUSBQueue::TransferDescriptorCompletionCallback invalid transfer descriptor %x\n", TransferDescriptorLogicalAddress);
ASSERT(FALSE); ASSERT(FALSE);
} }
POHCI_ENDPOINT_DESCRIPTOR POHCI_ENDPOINT_DESCRIPTOR

View file

@ -299,7 +299,7 @@ CUSBRequest::InitializeWithIrp(
m_TransferBufferMDL = Urb->UrbIsochronousTransfer.TransferBufferMDL; m_TransferBufferMDL = Urb->UrbIsochronousTransfer.TransferBufferMDL;
} }
} }
// //
// save buffer length // save buffer length
// //
@ -656,13 +656,12 @@ CUSBRequest::BuildIsochronousEndpoint(
{ {
POHCI_ISO_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor; POHCI_ISO_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor;
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor; POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
ULONG Index = 0, SubIndex, NumberOfPackets, PageOffset; ULONG Index = 0, SubIndex, NumberOfPackets, PageOffset, Page;
NTSTATUS Status; NTSTATUS Status;
PVOID Buffer; PVOID Buffer;
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
PURB Urb; PURB Urb;
DPRINT1("cp\n");
// //
// get current irp stack location // get current irp stack location
// //
@ -690,23 +689,27 @@ CUSBRequest::BuildIsochronousEndpoint(
// //
// failed to create setup descriptor // failed to create setup descriptor
// //
ASSERT(FALSE);
return Status; return Status;
} }
DPRINT1("cp\n");
// //
// get buffer // get buffer
// //
Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority); Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
ASSERT(Buffer); ASSERT(Buffer);
DPRINT1("cp\n"); //
// FIXME: support requests which spans serveral pages
//
ASSERT(ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(m_TransferBufferMDL), MmGetMdlByteCount(m_TransferBufferMDL)) <= 2);
while(Index < Urb->UrbIsochronousTransfer.NumberOfPackets) while(Index < Urb->UrbIsochronousTransfer.NumberOfPackets)
{ {
// //
// get number of packets remaining // get number of packets remaining
// //
NumberOfPackets = min(Urb->UrbIsochronousTransfer.NumberOfPackets - Index, OHCI_ITD_NOFFSET); NumberOfPackets = min(Urb->UrbIsochronousTransfer.NumberOfPackets - Index, OHCI_ITD_NOFFSET);
DPRINT1("cp Number Packets %lu\n", NumberOfPackets);
// //
// allocate iso descriptor // allocate iso descriptor
// //
@ -720,23 +723,29 @@ CUSBRequest::BuildIsochronousEndpoint(
ASSERT(FALSE); ASSERT(FALSE);
return Status; return Status;
} }
DPRINT1("cp\n");
// //
// initialize descriptor // get physical page
// //
CurrentDescriptor->BufferPhysical = (MmGetPhysicalAddress(Buffer).LowPart & ~ (PAGE_SIZE - 1)); Page = MmGetPhysicalAddress(Buffer).LowPart;
// //
// get page offset // get page offset
// //
PageOffset = BYTE_OFFSET(MmGetPhysicalAddress(Buffer).LowPart); PageOffset = MmGetMdlByteOffset(m_TransferBufferMDL);
DPRINT1("cp\n");
//
// initialize descriptor
//
CurrentDescriptor->BufferPhysical = Page - PageOffset;
for(SubIndex = 0; SubIndex < NumberOfPackets; SubIndex++) for(SubIndex = 0; SubIndex < NumberOfPackets; SubIndex++)
{ {
// //
// store buffer offset // store buffer offset
// //
CurrentDescriptor->Offset[SubIndex] = Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset + PageOffset; CurrentDescriptor->Offset[SubIndex] = Urb->UrbIsochronousTransfer.IsoPacket[Index+SubIndex].Offset + PageOffset;
DPRINT1("Index %lu PacketOffset %lu FinalOffset %lu\n", SubIndex+Index, Urb->UrbIsochronousTransfer.IsoPacket[Index+SubIndex].Offset, CurrentDescriptor->Offset[SubIndex]);
} }
// //
@ -752,19 +761,14 @@ CUSBRequest::BuildIsochronousEndpoint(
// //
// end of transfer // end of transfer
// //
CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + m_TransferBufferLength - 1; CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + m_TransferBufferLength - 1;
} }
else else
{ {
// //
// use start address of next packet - 1 // use start address of next packet - 1
// //
CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + Urb->UrbIsochronousTransfer.IsoPacket[Index + 1].Offset - 1; CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset - 1;
//
// move buffer to next address
//
Buffer = (PVOID)((ULONG_PTR)Buffer + Urb->UrbIsochronousTransfer.IsoPacket[Index + 1].Offset);
} }
// //
@ -790,8 +794,13 @@ CUSBRequest::BuildIsochronousEndpoint(
// store as previous descriptor // store as previous descriptor
// //
PreviousDescriptor = CurrentDescriptor; PreviousDescriptor = CurrentDescriptor;
DPRINT1("Current Descriptor %p Logical %lx StartAddress %x EndAddress %x\n", CurrentDescriptor, CurrentDescriptor->PhysicalAddress.LowPart, CurrentDescriptor->BufferPhysical, CurrentDescriptor->LastPhysicalByteAddress);
//
// fire interrupt as soon transfer is finished
//
CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
} }
DPRINT1("cp\n");
// //
// clear interrupt mask for last transfer descriptor // clear interrupt mask for last transfer descriptor
@ -814,7 +823,7 @@ CUSBRequest::BuildIsochronousEndpoint(
EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart; EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
EndpointDescriptor->TailPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart; EndpointDescriptor->TailPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor; EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
DPRINT1("cp\n");
// //
// store result // store result
// //
@ -1451,48 +1460,95 @@ CUSBRequest::FreeEndpointDescriptor(
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
{ {
POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor; POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
POHCI_ISO_TD IsoTransferDescriptor, IsoNextTransferDescriptor;
ULONG Index, PacketCount;
DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart); DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
// if (OutDescriptor->Flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT)
// get first general transfer descriptor
//
TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
//
// release endpoint descriptor
//
m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
while(TransferDescriptor)
{ {
// //
// get next // get first iso transfer descriptor
// //
NextTransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor; IsoTransferDescriptor = (POHCI_ISO_TD)OutDescriptor->HeadLogicalDescriptor;
// //
// is there a buffer associated // release endpoint descriptor
// //
if (TransferDescriptor->BufferSize) m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
while(IsoTransferDescriptor)
{ {
// //
// release buffer // get next
// //
m_DmaManager->Release(TransferDescriptor->BufferLogical, TransferDescriptor->BufferSize); IsoNextTransferDescriptor = IsoTransferDescriptor->NextLogicalDescriptor;
//
// get packet count
//
PacketCount = OHCI_ITD_GET_FRAME_COUNT(IsoTransferDescriptor->Flags);
DPRINT1("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x PacketCount %lu\n", IsoTransferDescriptor, IsoTransferDescriptor->PhysicalAddress.LowPart, IsoTransferDescriptor->BufferPhysical, IsoTransferDescriptor->LastPhysicalByteAddress, PacketCount);
for(Index = 0; Index < PacketCount; Index++)
{
DPRINT1("PSW Index %lu Value %x\n", Index, IsoTransferDescriptor->Offset[Index]);
}
//
// release descriptor
//
m_DmaManager->Release(IsoTransferDescriptor, sizeof(OHCI_ISO_TD));
//
// move to next
//
IsoTransferDescriptor = IsoNextTransferDescriptor;
} }
}
DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor, TransferDescriptor->PhysicalAddress.LowPart, TransferDescriptor->BufferPhysical, TransferDescriptor->LastPhysicalByteAddress); else
{
//
// get first general transfer descriptor
//
TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
// //
// release descriptor // release endpoint descriptor
// //
m_DmaManager->Release(TransferDescriptor, sizeof(OHCI_GENERAL_TD)); m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
// while(TransferDescriptor)
// move to next {
// //
TransferDescriptor = NextTransferDescriptor; // get next
//
NextTransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor;
//
// is there a buffer associated
//
if (TransferDescriptor->BufferSize)
{
//
// release buffer
//
m_DmaManager->Release(TransferDescriptor->BufferLogical, TransferDescriptor->BufferSize);
}
DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor, TransferDescriptor->PhysicalAddress.LowPart, TransferDescriptor->BufferPhysical, TransferDescriptor->LastPhysicalByteAddress);
//
// release descriptor
//
m_DmaManager->Release(TransferDescriptor, sizeof(OHCI_GENERAL_TD));
//
// move to next
//
TransferDescriptor = NextTransferDescriptor;
}
} }
} }