Author: janderwald
Date: Thu May 26 02:15:11 2011
New Revision: 51917

URL: http://svn.reactos.org/svn/reactos?rev=51917&view=rev
Log:
[USBOHCI]
- Remove dead code
- Silence traces
- Pass status & DoneHead as parameters to dpc routine
- Move IUSBRequest cleanup code into new function and use it for bulk / control 
transfer cleanup
- Fix bugs in AllocateEndpointDescriptor. It did not take the device address 
into account. It also did not respect the direction of the descriptor
- Implement support for bulk transfer requests
- Handle irp completion in CompletionCallback
- Tested in Windows XP SP3 + Vbox 4.04 + USB2.0 disabled + ReactOS usbstor + 
USB mass storage device
- OHCI Mass storage support is now also ready
- Next interrupt transfers

Modified:
    branches/usb-bringup/drivers/usb/usbohci/hardware.cpp
    branches/usb-bringup/drivers/usb/usbohci/hardware.h
    branches/usb-bringup/drivers/usb/usbohci/interfaces.h
    branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp
    branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp

Modified: branches/usb-bringup/drivers/usb/usbohci/hardware.cpp
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci/hardware.cpp?rev=51917&r1=51916&r2=51917&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/hardware.cpp [iso-8859-1] 
(original)
+++ branches/usb-bringup/drivers/usb/usbohci/hardware.cpp [iso-8859-1] Thu May 
26 02:15:11 2011
@@ -697,8 +697,6 @@
         //
         // notify controller
         //
-        //WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 
OHCI_CONTROL_HEAD_ED_OFFSET), 
m_ControlEndpointDescriptor->NextPhysicalEndpoint);
-        //WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 
OHCI_CONTROL_CURRENT_ED_OFFSET), 
m_ControlEndpointDescriptor->NextPhysicalEndpoint);
         WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 
OHCI_COMMAND_STATUS_OFFSET), Value | OHCI_CONTROL_LIST_FILLED);
     }
     else if (Type == USB_ENDPOINT_TYPE_BULK)
@@ -708,12 +706,6 @@
         //
         WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 
OHCI_COMMAND_STATUS_OFFSET), Value | OHCI_BULK_LIST_FILLED);
     }
-
-    Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 
OHCI_COMMAND_STATUS_OFFSET));
-
-
-    DPRINT1("HeadEndpointDescriptorModified Value %x Type %x\n", Value, Type);
-
 }
 
 NTSTATUS
@@ -1191,7 +1183,7 @@
     //
     This = (CUSBHardwareDevice*) ServiceContext;
 
-    DPRINT1("InterruptServiceRoutine\n");
+    DPRINT("InterruptServiceRoutine\n");
 
     //
     // get done head
@@ -1246,6 +1238,7 @@
          // head completed
          //
          Acknowledge |= OHCI_WRITEBACK_DONE_HEAD;
+         This->m_HCCA->DoneHead = 0;
     }
 
     if (Status & OHCI_RESUME_DETECTED)
@@ -1296,8 +1289,8 @@
     //
     // defer processing
     //
-    DPRINT1("Status %x\n", Status);
-    KeInsertQueueDpc(&This->m_IntDpcObject, This, (PVOID)Status);
+    DPRINT("Status %x Acknowledge %x\n", Status, Acknowledge);
+    KeInsertQueueDpc(&This->m_IntDpcObject, (PVOID)Status, (PVOID)(DoneHead & 
~1));
 
     //
     // interrupt handled
@@ -1321,23 +1314,14 @@
     //
     // get parameters
     //
-    This = (CUSBHardwareDevice*) SystemArgument1;
-    CStatus = (ULONG) SystemArgument2;
-
-       DPRINT1("OhciDefferedRoutine Status %x\n", CStatus);
+    This = (CUSBHardwareDevice*)DeferredContext;
+    CStatus = (ULONG) SystemArgument1;
+    DoneHead = (ULONG)SystemArgument2;
+
+    DPRINT("OhciDefferedRoutine Status %x\n", CStatus);
 
     if (CStatus & OHCI_WRITEBACK_DONE_HEAD)
     {
-        //
-        // descriptor completion, get done head
-        //
-        DoneHead = This->m_HCCA->DoneHead;
-
-        //
-        // clear out lower bits, ed are 16 byte aligned
-        //
-        DoneHead &= ~0xF;
-
         //
         // notify queue of event
         //

Modified: branches/usb-bringup/drivers/usb/usbohci/hardware.h
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci/hardware.h?rev=51917&r1=51916&r2=51917&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/hardware.h [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/hardware.h [iso-8859-1] Thu May 26 
02:15:11 2011
@@ -216,6 +216,8 @@
 #define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s)    ((s) << 16)
 #define OHCI_ENDPOINT_LOW_SPEED                 0x00002000
 #define OHCI_ENDPOINT_FULL_SPEED                0x00000000
+#define OHCI_ENDPOINT_DIRECTION_OUT             0x00000800
+#define OHCI_ENDPOINT_DIRECTION_IN              0x00001000
 
 //
 // Maximum port count set by OHCI

Modified: branches/usb-bringup/drivers/usb/usbohci/interfaces.h
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci/interfaces.h?rev=51917&r1=51916&r2=51917&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/interfaces.h [iso-8859-1] 
(original)
+++ branches/usb-bringup/drivers/usb/usbohci/interfaces.h [iso-8859-1] Thu May 
26 02:15:11 2011
@@ -443,6 +443,14 @@
 // Description: notifies request that the endpoint descriptor is complete
 
     virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * 
OutDescriptor) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// FreeEndpointDescriptor
+//
+// Description: frees the associated endpoint descriptor and its general 
descriptors
+
+    virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * 
OutDescriptor) = 0;
 };
 
 

Modified: branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp?rev=51917&r1=51916&r2=51917&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp [iso-8859-1] 
(original)
+++ branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp [iso-8859-1] Thu May 
26 02:15:11 2011
@@ -44,6 +44,7 @@
     // local functions
     BOOLEAN IsTransferDescriptorInEndpoint(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);
+    VOID CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR 
EndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor);
 
     // constructor / destructor
     CUSBQueue(IUnknown *OuterUnknown){}
@@ -127,7 +128,7 @@
     POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
     POHCI_ENDPOINT_DESCRIPTOR Descriptor;
 
-    DPRINT1("CUSBQueue::AddUSBRequest\n");
+    DPRINT("CUSBQueue::AddUSBRequest\n");
 
     //
     // sanity check
@@ -146,11 +147,11 @@
     {
         case USB_ENDPOINT_TYPE_ISOCHRONOUS:
         case USB_ENDPOINT_TYPE_INTERRUPT:
-        case USB_ENDPOINT_TYPE_BULK:
             /* NOT IMPLEMENTED IN QUEUE */
             Status = STATUS_NOT_SUPPORTED;
             break;
         case USB_ENDPOINT_TYPE_CONTROL:
+        case USB_ENDPOINT_TYPE_BULK:
             Status = STATUS_SUCCESS;
             break;
         default:
@@ -228,12 +229,14 @@
     Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
     //HeadDescriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
 
+    DPRINT("Request %x Logical %x added to queue Queue %p Logical %x\n", 
Descriptor, Descriptor->PhysicalAddress.LowPart, HeadDescriptor, 
HeadDescriptor->PhysicalAddress.LowPart);
+
+
     //
     // notify hardware of our request
     //
     m_Hardware->HeadEndpointDescriptorModified(Type);
 
-    DPRINT1("Request %x %x added to queue\n", Descriptor, 
Descriptor->PhysicalAddress);
 
 
     return STATUS_SUCCESS;
@@ -356,6 +359,47 @@
     return FALSE;
 }
 
+VOID
+CUSBQueue::CleanupEndpointDescriptor(
+    POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor,
+    POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor)
+{
+    PUSBREQUEST Request;
+
+    //
+    // FIXME: verify unlinking process
+    //
+    PreviousEndpointDescriptor->NextDescriptor = 
EndpointDescriptor->NextDescriptor;
+    PreviousEndpointDescriptor->NextPhysicalEndpoint = 
EndpointDescriptor->NextPhysicalEndpoint;
+
+    //
+    // get corresponding request
+    //
+    Request = PUSBREQUEST(EndpointDescriptor->Request);
+    ASSERT(Request);
+
+    //
+    // notify of completion
+    //
+    Request->CompletionCallback(EndpointDescriptor);
+
+    //
+    // free endpoint descriptor
+    //
+    Request->FreeEndpointDescriptor(EndpointDescriptor);
+
+    //
+    // FIXME: check if complete
+    //
+    //ASSERT(Request->IsRequestComplete());
+
+    //
+    // release request
+    //
+    Request->Release();
+
+}
+
 
 VOID
 CUSBQueue::TransferDescriptorCompletionCallback(
@@ -363,7 +407,8 @@
 {
     POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
     NTSTATUS Status;
-    PUSBREQUEST Request;
+
+    DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer 
descriptor %x\n", TransferDescriptorLogicalAddress);
 
     //
     // find transfer descriptor in control list
@@ -372,31 +417,38 @@
     if (NT_SUCCESS(Status))
     {
         //
-        // FIXME: make sure this is ok
-        // unlink descriptor
-        //
-        PreviousEndpointDescriptor->NextDescriptor = 
EndpointDescriptor->NextDescriptor;
-        PreviousEndpointDescriptor->NextPhysicalEndpoint = 
EndpointDescriptor->NextPhysicalEndpoint;
-
-        //
-        // get corresponding request
-        //
-        Request = PUSBREQUEST(EndpointDescriptor->Request);
-
-        //
-        // notify of completion
-        //
-        Request->CompletionCallback(EndpointDescriptor);
-
-        //
-        // FIXME: check if complete
-        //
-        ASSERT(Request->IsRequestComplete());
-        //
-        // release request
-        //
-        Request->Release();
-    }
+        // cleanup endpoint
+        //
+        CleanupEndpointDescriptor(EndpointDescriptor, 
PreviousEndpointDescriptor);
+
+        //
+        // done
+        //
+        return;
+    }
+
+    //
+    // find transfer descriptor in bulk list
+    //
+    Status = FindTransferDescriptorInEndpoint(m_BulkHeadEndpointDescriptor, 
TransferDescriptorLogicalAddress, &EndpointDescriptor, 
&PreviousEndpointDescriptor);
+    if (NT_SUCCESS(Status))
+    {
+        //
+        // cleanup endpoint
+        //
+        CleanupEndpointDescriptor(EndpointDescriptor, 
PreviousEndpointDescriptor);
+
+        //
+        // done
+        //
+        return;
+    }
+
+    //
+    // hardware reported dead endpoint completed
+    //
+    DPRINT1("CUSBQueue::TransferDescriptorCompletionCallback invalid transfer 
descriptor %x\n", TransferDescriptorLogicalAddress);
+    ASSERT(FALSE);
 
 }
 

Modified: branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp?rev=51917&r1=51916&r2=51917&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp [iso-8859-1] 
(original)
+++ branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp [iso-8859-1] Thu 
May 26 02:15:11 2011
@@ -45,6 +45,7 @@
     virtual BOOLEAN IsRequestInitialized();
     virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
     virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * 
OutDescriptor);
+    virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * 
OutDescriptor);
 
     // local functions
     ULONG InternalGetTransferType();
@@ -53,6 +54,7 @@
     NTSTATUS BuildSetupPacket();
     NTSTATUS BuildSetupPacketFromURB();
     NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * 
OutEndpointDescriptor);
+    NTSTATUS BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR * 
OutEndpointDescriptor);
     NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, 
ULONG BufferSize);
     VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor);
     NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR 
*OutDescriptor);
@@ -606,9 +608,35 @@
     //
     // append device address and endpoint number
     //
-    Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(m_DeviceAddress);
+    Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(GetDeviceAddress());
     Descriptor->Flags |= 
OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
     Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
+
+    //
+    // is there an endpoint descriptor
+    //
+    if (m_EndpointDescriptor)
+    {
+        //
+        // check direction
+        //
+        if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor->bEndpointAddress))
+        {
+            //
+            // direction out
+            //
+            Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_OUT;
+        }
+        else
+        {
+            //
+            // direction in
+            //
+            Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_IN;
+        }
+
+    }
+
 
     //
     // FIXME: detect type
@@ -632,14 +660,204 @@
 }
 
 NTSTATUS
+CUSBRequest::BuildBulkInterruptEndpoint(
+    POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
+{
+    POHCI_GENERAL_TD FirstDescriptor, PreviousDescriptor = NULL, 
CurrentDescriptor, LastDescriptor;
+    POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+    ULONG BufferSize, CurrentSize, Direction, MaxLengthInPage;
+    NTSTATUS Status;
+    PVOID Buffer;
+
+    //
+    // allocate endpoint descriptor
+    //
+    Status = AllocateEndpointDescriptor(&EndpointDescriptor);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to create setup descriptor
+        //
+        return Status;
+    }
+
+    //
+    // allocate transfer descriptor for last descriptor
+    //
+    Status = CreateGeneralTransferDescriptor(&LastDescriptor, 0);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to create transfer descriptor
+        //
+        m_DmaManager->Release(EndpointDescriptor, 
sizeof(OHCI_ENDPOINT_DESCRIPTOR));
+        return Status;
+    }
+
+    //
+    // get buffer size
+    //
+    BufferSize = m_TransferBufferLength;
+    ASSERT(BufferSize);
+    ASSERT(m_TransferBufferMDL);
+
+    //
+    // get buffer
+    //
+    Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, 
NormalPagePriority);
+    ASSERT(Buffer);
+
+    if (InternalGetPidDirection())
+    {
+        //
+        // input direction
+        //
+        Direction = OHCI_TD_DIRECTION_PID_IN;
+    }
+    else
+    {
+        //
+        // output direction
+        //
+        Direction = OHCI_TD_DIRECTION_PID_OUT;
+    }
+
+    do
+    {
+        //
+        // get current buffersize
+        //
+        CurrentSize = min(8192, BufferSize);
+
+        //
+        // get page offset
+        //
+        MaxLengthInPage = PAGE_SIZE - BYTE_OFFSET(Buffer);
+
+        //
+        // get minimum from current page size
+        //
+        CurrentSize = min(CurrentSize, MaxLengthInPage);
+        ASSERT(CurrentSize);
+
+        //
+        // allocate transfer descriptor
+        //
+        Status = CreateGeneralTransferDescriptor(&CurrentDescriptor, 0);
+        if (!NT_SUCCESS(Status))
+        {
+            //
+            // failed to create transfer descriptor
+            // TODO: cleanup
+            //
+            ASSERT(FALSE);
+            m_DmaManager->Release(EndpointDescriptor, 
sizeof(OHCI_ENDPOINT_DESCRIPTOR));
+            FreeDescriptor(LastDescriptor);
+            return Status;
+        }
+
+        //
+        // initialize descriptor
+        //
+        CurrentDescriptor->Flags = Direction | OHCI_TD_BUFFER_ROUNDING | 
OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | 
OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_TOGGLE_CARRY;
+
+        //
+        // store physical address of buffer
+        //
+        CurrentDescriptor->BufferPhysical = 
MmGetPhysicalAddress(Buffer).LowPart;
+        CurrentDescriptor->LastPhysicalByteAddress = 
CurrentDescriptor->BufferPhysical + CurrentSize - 1; 
+
+        //
+        // is there a previous descriptor
+        //
+        if (PreviousDescriptor)
+        {
+            //
+            // link descriptors
+            //
+            PreviousDescriptor->NextLogicalDescriptor = 
(PVOID)CurrentDescriptor;
+            PreviousDescriptor->NextPhysicalDescriptor = 
CurrentDescriptor->PhysicalAddress.LowPart;
+        }
+        else
+        {
+            //
+            // it is the first descriptor
+            //
+            FirstDescriptor = CurrentDescriptor;
+        }
+
+        DPRINT("PreviousDescriptor %p CurrentDescriptor %p  Buffer Logical %p 
Physical %x Last Physical %x CurrentSize %lu\n", PreviousDescriptor, 
CurrentDescriptor, CurrentDescriptor->BufferLogical, 
CurrentDescriptor->BufferPhysical, CurrentDescriptor->LastPhysicalByteAddress, 
CurrentSize);
+
+        //
+        //  set previous descriptor
+        //
+        PreviousDescriptor = CurrentDescriptor;
+
+        //
+        // subtract buffer size
+        //
+        BufferSize -= CurrentSize;
+
+        //
+        // increment buffer offset
+        //
+        Buffer = (PVOID)((ULONG_PTR)Buffer + CurrentSize);
+
+    }while(BufferSize);
+
+    //
+    // first descriptor has no carry bit
+    //
+    FirstDescriptor->Flags &= ~OHCI_TD_TOGGLE_CARRY;
+
+    //
+    // fixme: toggle
+    //
+    FirstDescriptor->Flags |= OHCI_TD_TOGGLE_0;
+
+    //
+    // clear interrupt mask for last transfer descriptor
+    //
+    CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
+
+    //
+    // fire interrupt as soon transfer is finished
+    //
+    CurrentDescriptor->Flags |= 
OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
+
+    //
+    // link last data descriptor to last descriptor
+    //
+    CurrentDescriptor->NextLogicalDescriptor = LastDescriptor;
+    CurrentDescriptor->NextPhysicalDescriptor = 
LastDescriptor->PhysicalAddress.LowPart;
+
+    //
+    // now link descriptor to endpoint
+    //
+    EndpointDescriptor->HeadPhysicalDescriptor = 
FirstDescriptor->PhysicalAddress.LowPart;
+    EndpointDescriptor->TailPhysicalDescriptor = 
LastDescriptor->PhysicalAddress.LowPart;
+    EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
+
+    //
+    // store result
+    //
+    *OutEndpointDescriptor = EndpointDescriptor;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+
+}
+
+
+NTSTATUS
 CUSBRequest::BuildControlTransferDescriptor(
     POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
 {
     POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL, 
LastDescriptor;
     POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
     NTSTATUS Status;
-
-    DPRINT1("CUSBRequest::BuildControlTransferDescriptor\n");
 
     //
     // allocate endpoint descriptor
@@ -694,7 +912,6 @@
         m_DmaManager->Release(EndpointDescriptor, 
sizeof(OHCI_ENDPOINT_DESCRIPTOR));
         return Status;
     }
-
 
     if (m_TransferBufferLength)
     {
@@ -729,6 +946,7 @@
         //
         DataDescriptor->BufferPhysical = 
MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
         DataDescriptor->LastPhysicalByteAddress = 
DataDescriptor->BufferPhysical + m_TransferBufferLength - 1; 
+
     }
 
     //
@@ -849,12 +1067,8 @@
             Status = 
BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
             break;
         case USB_ENDPOINT_TYPE_BULK:
-            DPRINT1("USB_ENDPOINT_TYPE_BULK not implemented\n");
-            Status = STATUS_NOT_IMPLEMENTED; 
//BuildBulkTransferQueueHead(OutDescriptor);
-            break;
         case USB_ENDPOINT_TYPE_INTERRUPT:
-            DPRINT1("USB_ENDPOINT_TYPE_INTERRUPT not implemented\n");
-            Status = STATUS_NOT_IMPLEMENTED;
+            Status = BuildBulkInterruptEndpoint(OutDescriptor);
             break;
         case USB_ENDPOINT_TYPE_ISOCHRONOUS:
             DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
@@ -919,14 +1133,66 @@
 
 }
 
+VOID
+CUSBRequest::FreeEndpointDescriptor(
+    struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
+{
+    POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
+
+    DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical 
%x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
+
+    //
+    // 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
+        //
+        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;
+    }
+
+}
 
 VOID
 CUSBRequest::CompletionCallback(
     struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
 {
     POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
-
-    DPRINT1("CUSBRequest::CompletionCallback\n");
+    PIO_STACK_LOCATION IoStack;
+    PURB Urb;
+
+    DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress 
%x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
 
     //
     // set status code
@@ -934,56 +1200,57 @@
     m_NtStatusCode = STATUS_SUCCESS;
     m_UrbStatusCode = USBD_STATUS_SUCCESS;
 
-    ASSERT(!m_Irp);
-
-    //
-    // FIXME: cleanup descriptors
-    //
-
-    //
-    // get first general transfer descriptor
-    //
-    TransferDescriptor = 
(POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
-
-    while(TransferDescriptor)
-    {
-        //
-        // get next
-        //
-        NextTransferDescriptor = 
(POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor;
-
-        //
-        // is there a buffer associated
-        //
-        if (TransferDescriptor->BufferSize)
+    if (m_Irp)
+    {
+        //
+        // set irp completion status
+        //
+        m_Irp->IoStatus.Status = STATUS_SUCCESS; //FIXME
+
+        //
+        // get current irp stack location
+        //
+        IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
+        //
+        // get urb
+        //
+        Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+        //
+        // store urb status
+        //
+        Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; //FIXME
+
+        //
+        // Check if the MDL was created
+        //
+        if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
         {
             //
-            // release buffer
-            //
-            m_DmaManager->Release(TransferDescriptor->BufferLogical, 
TransferDescriptor->BufferSize);
+            // Free Mdl
+            //
+            IoFreeMdl(m_TransferBufferMDL);
         }
 
         //
-        // release descriptor
-        //
-        m_DmaManager->Release(TransferDescriptor, sizeof(OHCI_GENERAL_TD));
-
-        //
-        // move to next
-        //
-        TransferDescriptor = NextTransferDescriptor;
-    }
-
-    //
-    // release endpoint descriptor
-    //
-    m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
-
-    //
-    // signal completion event
-    //
-    PC_ASSERT(m_CompletionEvent);
-    KeSetEvent(m_CompletionEvent, 0, FALSE);
+        // FIXME: support status and calculate length
+        //
+
+        //
+        // FIXME: check if the transfer was split
+        // if yes dont complete irp yet
+        //
+        IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
+    }
+    else
+    {
+        //
+        // signal completion event
+        //
+        PC_ASSERT(m_CompletionEvent);
+        KeSetEvent(m_CompletionEvent, 0, FALSE);
+    }
 }
 
 


Reply via email to