Author: janderwald
Date: Mon May 23 17:42:52 2011
New Revision: 51864

URL: http://svn.reactos.org/svn/reactos?rev=51864&view=rev
Log:
[USBOHCI]
- Start implementing control transfers
- Move initialization of usb queue after the bulk / control head endpoints have 
been created
- Add interface functions to retrieve bulk / control head endpoint descriptors
- Add macros for setting transfer descriptors field (taken from Haiku)
- Partly implement IUSBQueue::AddUSBRequest for control / bulk transfers
- Create endpoint descriptor for control request and link setup descriptor to 
it 
- Link setup descriptors to data descriptor / status descriptor
- WIP (needs fixes)

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=51864&r1=51863&r2=51864&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] Mon May 
23 17:42:52 2011
@@ -59,6 +59,10 @@
     NTSTATUS PnpStop(void);
     NTSTATUS HandlePower(PIRP Irp);
     NTSTATUS GetDeviceDetails(PUSHORT VendorId, PUSHORT DeviceId, PULONG 
NumberOfPorts, PULONG Speed);
+    NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** 
OutDescriptor);
+    NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR 
** OutDescriptor);
+    VOID HeadEndpointDescriptorModified(ULONG HeadType);
+
     NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager);
     NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue);
 
@@ -360,23 +364,23 @@
     }
 
     //
+    // initializes the controller
+    //
+    Status = InitializeController();
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to Initialize the controller \n");
+        ASSERT(FALSE);
+        return Status;
+    }
+
+    //
     // Initialize the UsbQueue now that we have an AdapterObject.
     //
     Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, 
m_MemoryManager, NULL);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Failed to Initialize the UsbQueue\n");
-        return Status;
-    }
-
-    //
-    // initializes the controller
-    //
-    Status = InitializeController();
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("Failed to Initialize the controller \n");
-        ASSERT(FALSE);
         return Status;
     }
 
@@ -628,6 +632,42 @@
     //
     // done
     //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBHardwareDevice::GetBulkHeadEndpointDescriptor(
+    struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
+{
+    *OutDescriptor = m_BulkEndpointDescriptor;
+    return STATUS_SUCCESS;
+}
+
+VOID
+CUSBHardwareDevice::HeadEndpointDescriptorModified(
+    ULONG Type)
+{
+    if (Type == USB_ENDPOINT_TYPE_CONTROL)
+    {
+        //
+        // notify controller
+        //
+        WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 
OHCI_COMMAND_STATUS_OFFSET), OHCI_CONTROL_LIST_FILLED);
+    }
+    else if (Type == USB_ENDPOINT_TYPE_BULK)
+    {
+        //
+        // notify controller
+        //
+        WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 
OHCI_COMMAND_STATUS_OFFSET), OHCI_BULK_LIST_FILLED);
+    }
+}
+
+NTSTATUS
+CUSBHardwareDevice::GetControlHeadEndpointDescriptor(
+    struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
+{
+    *OutDescriptor = m_ControlEndpointDescriptor;
     return STATUS_SUCCESS;
 }
 
@@ -1128,7 +1168,7 @@
          // head completed
          //
          DPRINT1("InterruptServiceRoutine> Done Head completion\n");
-
+         ASSERT(FALSE);
          //
          // FIXME: handle event
          //
@@ -1148,9 +1188,11 @@
     if (Status & OHCI_UNRECOVERABLE_ERROR)
     {
         DPRINT1("InterruptServiceRoutine> Controller error\n");
+
         //
         // halt controller
         //
+        ASSERT(FALSE);
         WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + 
OHCI_CONTROL_OFFSET), OHCI_HC_FUNCTIONAL_STATE_RESET);
     }
 

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=51864&r1=51863&r2=51864&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] Mon May 23 
17:42:52 2011
@@ -192,7 +192,7 @@
 #define OHCI_PAGE_OFFSET(x)         ((x) & 0xfff)
 
 
-typedef struct 
+typedef struct _OHCI_ENDPOINT_DESCRIPTOR
 {
     // Hardware part
     ULONG  Flags;
@@ -202,10 +202,19 @@
 
     // Software part
     PHYSICAL_ADDRESS  PhysicalAddress;
+    PVOID Request;
+    PVOID NextDescriptor;
 }OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR;
 
 
 #define OHCI_ENDPOINT_SKIP                      0x00004000
+#define OHCI_ENDPOINT_SET_DEVICE_ADDRESS(s)     (s)
+#define OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(s)    (((s) >> 7) & 0xf)
+#define OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(s)    ((s) << 7)
+#define OHCI_ENDPOINT_GET_MAX_PACKET_SIZE(s)    (((s) >> 16) & 0x07ff)
+#define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s)    ((s) << 16)
+#define OHCI_ENDPOINT_LOW_SPEED                 0x00002000
+#define OHCI_ENDPOINT_FULL_SPEED                0x00000000
 
 //
 // Maximum port count set by OHCI
@@ -220,15 +229,51 @@
 }OHCI_PORT_STATUS;
 
 
-typedef struct {
+typedef struct
+{
     // Hardware part 16 bytes
-    uint32  flags;                      // Flags field
-    uint32  buffer_physical;            // Physical buffer pointer
-    uint32  next_physical_descriptor;   // Physical pointer next descriptor
-    uint32  last_physical_byte_address; // Physical pointer to buffer end
+    ULONG Flags;                      // Flags field
+    ULONG  BufferPhysical;            // Physical buffer pointer
+    ULONG  NextPhysicalDescriptor;   // Physical pointer next descriptor
+    ULONG LastPhysicalByteAddress; // Physical pointer to buffer end
     // Software part
-    addr_t  physical_address;           // Physical address of this descriptor
-    size_t  buffer_size;                // Size of the buffer
-    void    *buffer_logical;            // Logical pointer to the buffer
-    void    *next_logical_descriptor;   // Logical pointer next descriptor
-} ohci_general_td;
+    PHYSICAL_ADDRESS  PhysicalAddress;           // Physical address of this 
descriptor
+    ULONG  BufferSize;                // Size of the buffer
+    PVOID    BufferLogical;            // Logical pointer to the buffer
+    PVOID  Request;                   // pointer to IUSBRequest
+}OHCI_GENERAL_TD, *POHCI_GENERAL_TD;
+
+
+#define OHCI_TD_BUFFER_ROUNDING         0x00040000
+#define OHCI_TD_DIRECTION_PID_MASK      0x00180000
+#define OHCI_TD_DIRECTION_PID_SETUP     0x00000000
+#define OHCI_TD_DIRECTION_PID_OUT       0x00080000
+#define OHCI_TD_DIRECTION_PID_IN        0x00100000
+#define OHCI_TD_GET_DELAY_INTERRUPT(x)  (((x) >> 21) & 7)
+#define OHCI_TD_SET_DELAY_INTERRUPT(x)  ((x) << 21)
+#define OHCI_TD_INTERRUPT_MASK          0x00e00000
+#define OHCI_TD_TOGGLE_CARRY            0x00000000
+#define OHCI_TD_TOGGLE_0                0x02000000
+#define OHCI_TD_TOGGLE_1                0x03000000
+#define OHCI_TD_TOGGLE_MASK             0x03000000
+#define OHCI_TD_GET_ERROR_COUNT(x)      (((x) >> 26) & 3)
+#define OHCI_TD_GET_CONDITION_CODE(x)   ((x) >> 28)
+#define OHCI_TD_SET_CONDITION_CODE(x)   ((x) << 28)
+#define OHCI_TD_CONDITION_CODE_MASK     0xf0000000
+
+#define OHCI_TD_INTERRUPT_IMMEDIATE         0x00
+#define OHCI_TD_INTERRUPT_NONE              0x07
+
+#define OHCI_TD_CONDITION_NO_ERROR          0x00
+#define OHCI_TD_CONDITION_CRC_ERROR         0x01
+#define OHCI_TD_CONDITION_BIT_STUFFING      0x02
+#define OHCI_TD_CONDITION_TOGGLE_MISMATCH   0x03
+#define OHCI_TD_CONDITION_STALL             0x04
+#define OHCI_TD_CONDITION_NO_RESPONSE       0x05
+#define OHCI_TD_CONDITION_PID_CHECK_FAILURE 0x06
+#define OHCI_TD_CONDITION_UNEXPECTED_PID    0x07
+#define OHCI_TD_CONDITION_DATA_OVERRUN      0x08
+#define OHCI_TD_CONDITION_DATA_UNDERRUN     0x09
+#define OHCI_TD_CONDITION_BUFFER_OVERRUN    0x0c
+#define OHCI_TD_CONDITION_BUFFER_UNDERRUN   0x0d
+#define OHCI_TD_CONDITION_NOT_ACCESSED      0x0f

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=51864&r1=51863&r2=51864&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] Mon May 
23 17:42:52 2011
@@ -107,7 +107,7 @@
 
 typedef IHCDController *PHCDCONTROLLER;
 
-
+struct _OHCI_ENDPOINT_DESCRIPTOR;
 
//=========================================================================================
 //
 // class IUSBHardwareDevice
@@ -171,6 +171,33 @@
 // Do not call Initialize on IUSBQueue, the object is already initialized
 
     virtual NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetBulkHeadEndpointDescriptor
+//
+// Description: returns the bulk head endpoint descriptor
+
+    virtual NTSTATUS GetBulkHeadEndpointDescriptor(struct 
_OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetControlHeadEndpointDescriptor
+//
+// Description: returns the control head endpoint descriptor
+
+    virtual NTSTATUS GetControlHeadEndpointDescriptor(struct 
_OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// HeadEndpointDescriptorModified
+//
+// Description: notifies the hardware that an endpoint descriptor was added to 
head endpoint descriptor
+
+    virtual VOID HeadEndpointDescriptorModified(ULONG HeadType) = 0;
+
+
+
 
 
//-----------------------------------------------------------------------------------------
 //
@@ -334,8 +361,6 @@
 // CancelCallback routine is invoked.
 // 
 
-struct _QUEUE_HEAD;
-
 DECLARE_INTERFACE_(IUSBRequest, IUnknown)
 {
     DEFINE_ABSTRACT_UNKNOWN()
@@ -387,6 +412,14 @@
 
 
//-----------------------------------------------------------------------------------------
 //
+// GetEndpointDescriptor
+//
+// Description: returns the general transfer descriptor
+
+    virtual NTSTATUS GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** 
OutDescriptor) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
 // GetResultStatus
 //
 // Description: returns the status code of the result

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=51864&r1=51863&r2=51864&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] Mon May 
23 17:42:52 2011
@@ -46,6 +46,9 @@
 protected:
     LONG m_Ref;                                                                
         // reference count
     KSPIN_LOCK m_Lock;                                                         
         // list lock
+    PUSBHARDWAREDEVICE m_Hardware;                                             
         // hardware
+    POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor;                    
         // bulk head descriptor
+    POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor;                 
         // control head descriptor
 };
 
 
//=================================================================================================
@@ -74,7 +77,26 @@
     IN PDMAMEMORYMANAGER MemManager,
     IN OPTIONAL PKSPIN_LOCK Lock)
 {
-    UNIMPLEMENTED
+    //
+    // get bulk endpoint descriptor
+    //
+    Hardware->GetBulkHeadEndpointDescriptor(&m_BulkHeadEndpointDescriptor);
+
+    //
+    // get control endpoint descriptor
+    //
+    
Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor);
+
+    //
+    // initialize spinlock
+    //
+    KeInitializeSpinLock(&m_Lock);
+
+    //
+    // store hardware
+    //
+    m_Hardware = Hardware;
+
     return STATUS_SUCCESS;
 }
 
@@ -96,6 +118,10 @@
     NTSTATUS Status;
     ULONG Type;
     KIRQL OldLevel;
+    POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
+    POHCI_ENDPOINT_DESCRIPTOR Descriptor;
+
+    DPRINT1("CUSBQueue::AddUSBRequest\n");
 
     //
     // sanity check
@@ -143,6 +169,63 @@
     //
     Request->AddRef();
 
+    //
+    // get transfer descriptors
+    //
+    Status = Request->GetEndpointDescriptor(&Descriptor);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to get transfer descriptor
+        //
+        DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with 
%x\n", Status);
+
+        //
+        // release reference
+        //
+        Request->Release();
+        return Status;
+    }
+
+    //
+    // check type
+    //
+    if (Type == USB_ENDPOINT_TYPE_BULK)
+    {
+        //
+        // get head descriptor
+        //
+        HeadDescriptor = m_BulkHeadEndpointDescriptor;
+    }
+    else if (Type == USB_ENDPOINT_TYPE_CONTROL)
+    {
+        //
+        // get head descriptor
+        //
+        HeadDescriptor = m_ControlHeadEndpointDescriptor;
+    }
+
+    //
+    // link endpoints
+    //
+    Descriptor->NextPhysicalEndpoint = HeadDescriptor->NextPhysicalEndpoint;
+    Descriptor->NextDescriptor = HeadDescriptor->NextDescriptor;
+
+    HeadDescriptor->NextPhysicalEndpoint = Descriptor->PhysicalAddress.LowPart;
+    HeadDescriptor->NextDescriptor = Descriptor;
+
+    //
+    // set descriptor active
+    //
+    Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
+
+    //
+    // notify hardware of our request
+    //
+    m_Hardware->HeadEndpointDescriptorModified(Type);
+
+    DPRINT1("Request added to queue\n");
+
 
     return STATUS_SUCCESS;
 }

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=51864&r1=51863&r2=51864&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] Mon 
May 23 17:42:52 2011
@@ -40,6 +40,7 @@
     virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT 
PIRP Irp);
     virtual BOOLEAN IsRequestComplete();
     virtual ULONG GetTransferType();
+    virtual NTSTATUS GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** 
OutEndpointDescriptor);
     virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT 
OPTIONAL PULONG UrbStatusCode);
     virtual BOOLEAN IsRequestInitialized();
     virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
@@ -51,6 +52,12 @@
     UCHAR GetDeviceAddress();
     NTSTATUS BuildSetupPacket();
     NTSTATUS BuildSetupPacketFromURB();
+    NTSTATUS BuildControlTransferDescriptor(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);
+    UCHAR GetEndpointAddress();
+    USHORT GetMaxPacketSize();
 
     // constructor / destructor
     CUSBRequest(IUnknown *OuterUnknown){}
@@ -348,6 +355,46 @@
     return InternalGetTransferType();
 }
 
+USHORT
+CUSBRequest::GetMaxPacketSize()
+{
+    if (!m_EndpointDescriptor)
+    {
+        //
+        // control request
+        //
+        return 0;
+    }
+
+    ASSERT(m_Irp);
+    ASSERT(m_EndpointDescriptor);
+
+    //
+    // return max packet size
+    //
+    return m_EndpointDescriptor->wMaxPacketSize;
+}
+
+UCHAR
+CUSBRequest::GetEndpointAddress()
+{
+    if (!m_EndpointDescriptor)
+    {
+        //
+        // control request
+        //
+        return 0;
+    }
+
+    ASSERT(m_Irp);
+    ASSERT(m_EndpointDescriptor);
+
+    //
+    // endpoint number is between 1-15
+    //
+    return (m_EndpointDescriptor->bEndpointAddress & 0xF);
+}
+
 
//----------------------------------------------------------------------------------------
 ULONG
 CUSBRequest::InternalGetTransferType()
@@ -444,9 +491,366 @@
     return 0;
 }
 
-
-
-
+VOID
+CUSBRequest::FreeDescriptor(
+    POHCI_GENERAL_TD Descriptor)
+{
+    if (Descriptor->BufferSize)
+    {
+        //
+        // free buffer
+        //
+        m_DmaManager->Release(Descriptor->BufferLogical, 
Descriptor->BufferSize);
+    }
+
+    //
+    // release descriptor
+    //
+    m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
+
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::CreateGeneralTransferDescriptor(
+    POHCI_GENERAL_TD* OutDescriptor, 
+    ULONG BufferSize)
+{
+    POHCI_GENERAL_TD Descriptor;
+    PHYSICAL_ADDRESS DescriptorAddress;
+    NTSTATUS Status;
+
+    //
+    // allocate transfer descriptor
+    //
+    Status = m_DmaManager->Allocate(sizeof(OHCI_GENERAL_TD), 
(PVOID*)&Descriptor, &DescriptorAddress);
+    if (!NT_SUCCESS(Status))
+    {
+         //
+         // no memory
+         //
+         return Status;
+    }
+
+    //
+    // initialize descriptor, hardware part
+    //
+    Descriptor->Flags = 0;
+    Descriptor->BufferPhysical = 0;
+    Descriptor->NextPhysicalDescriptor = 0;
+    Descriptor->LastPhysicalByteAddress = 0;
+
+    //
+    // software part
+    //
+    Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
+    Descriptor->BufferSize = BufferSize;
+
+    if (BufferSize > 0)
+    {
+        //
+        // allocate buffer from dma
+        //
+        Status = m_DmaManager->Allocate(BufferSize, 
&Descriptor->BufferLogical, &DescriptorAddress);
+        if (!NT_SUCCESS(Status))
+        {
+             //
+             // no memory
+             //
+             m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
+             return Status;
+        }
+
+        //
+        // set physical address of buffer 
+        //
+        Descriptor->BufferPhysical = DescriptorAddress.LowPart;
+        Descriptor->LastPhysicalByteAddress = Descriptor->BufferPhysical + 
BufferSize - 1;
+    }
+
+    //
+    // store result
+    //
+    *OutDescriptor = Descriptor;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBRequest::AllocateEndpointDescriptor(
+    OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor)
+{
+    POHCI_ENDPOINT_DESCRIPTOR Descriptor;
+    PHYSICAL_ADDRESS DescriptorAddress;
+    NTSTATUS Status;
+
+    //
+    // allocate descriptor
+    //
+    Status = m_DmaManager->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR), 
(PVOID*)&Descriptor, &DescriptorAddress);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to allocate descriptor
+        //
+        return Status;
+    }
+
+    //
+    // intialize descriptor
+    //
+    Descriptor->Flags = OHCI_ENDPOINT_SKIP;
+
+    //
+    // append device address and endpoint number
+    //
+    Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(m_DeviceAddress);
+    Descriptor->Flags |= 
OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
+    Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
+
+    //
+    // FIXME: detect type
+    //
+    Descriptor->Flags |= OHCI_ENDPOINT_FULL_SPEED;
+
+    Descriptor->HeadPhysicalDescriptor = 0;
+    Descriptor->NextPhysicalEndpoint = 0;
+    Descriptor->TailPhysicalDescriptor = 0;
+    Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
+
+    //
+    // store result
+    //
+    *OutDescriptor = Descriptor;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBRequest::BuildControlTransferDescriptor(
+    POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
+{
+    POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL;
+    POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+    NTSTATUS Status;
+
+    DPRINT1("CUSBRequest::BuildControlTransferDescriptor\n");
+
+    //
+    // allocate endpoint descriptor
+    //
+    Status = AllocateEndpointDescriptor(&EndpointDescriptor);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to create setup descriptor
+        //
+        return Status;
+    }
+
+    //
+    // first allocate setup descriptor
+    //
+    Status = CreateGeneralTransferDescriptor(&SetupDescriptor, 
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to create setup descriptor
+        //
+        m_DmaManager->Release(EndpointDescriptor, 
sizeof(OHCI_ENDPOINT_DESCRIPTOR));
+        return Status;
+    }
+
+    //
+    // now create the status descriptor
+    //
+    Status = CreateGeneralTransferDescriptor(&StatusDescriptor, 0);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to create status descriptor
+        //
+        FreeDescriptor(SetupDescriptor);
+        m_DmaManager->Release(EndpointDescriptor, 
sizeof(OHCI_ENDPOINT_DESCRIPTOR));
+        return Status;
+    }
+
+    if (m_TransferBufferLength)
+    {
+        //
+        // FIXME: support more than one data descriptor
+        //
+        ASSERT(m_TransferBufferLength < 8192);
+
+        //
+        // now create the data descriptor
+        //
+        Status = CreateGeneralTransferDescriptor(&DataDescriptor, 0);
+        if (!NT_SUCCESS(Status))
+        {
+            //
+            // failed to create status descriptor
+            //
+            m_DmaManager->Release(EndpointDescriptor, 
sizeof(OHCI_ENDPOINT_DESCRIPTOR));
+            FreeDescriptor(SetupDescriptor);
+            FreeDescriptor(StatusDescriptor);
+            return Status;
+        }
+
+        //
+        // initialize data descriptor
+        //
+        DataDescriptor->Flags = 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 | 
OHCI_TD_DIRECTION_PID_IN;
+
+        //
+        // store physical address of buffer
+        //
+        DataDescriptor->BufferPhysical = 
MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
+        DataDescriptor->LastPhysicalByteAddress = 
DataDescriptor->BufferPhysical + m_TransferBufferLength - 1; 
+    }
+
+    //
+    // initialize setup descriptor
+    //
+    SetupDescriptor->Flags = OHCI_TD_DIRECTION_PID_SETUP | 
OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_0 | 
OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
+
+    if (m_SetupPacket)
+    {
+        //
+        // copy setup packet
+        //
+        RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket, 
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+    }
+    else
+    {
+        //
+        // generate setup packet from urb
+        //
+        ASSERT(FALSE);
+    }
+
+    //
+    // initialize status descriptor
+    //
+    StatusDescriptor->Flags = 
OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_1 | 
OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
+    if (m_TransferBufferLength == 0)
+    {
+        //
+        // input direction is flipped for the status descriptor
+        //
+        StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
+    }
+    else
+    {
+        //
+        // output direction is flipped for the status descriptor
+        //
+        StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_OUT;
+    }
+
+    //
+    // now link the descriptors
+    //
+    if (m_TransferBufferLength)
+    {
+         //
+         // link setup descriptor to data descriptor
+         //
+         SetupDescriptor->NextPhysicalDescriptor = 
DataDescriptor->PhysicalAddress.LowPart;
+
+         //
+         // FIXME: should link to last data descriptor to status descriptor
+         //
+         DataDescriptor->NextPhysicalDescriptor = 
StatusDescriptor->PhysicalAddress.LowPart;
+    }
+    else
+    {
+         //
+         // link setup descriptor to status descriptor
+         //
+         SetupDescriptor->NextPhysicalDescriptor = 
StatusDescriptor->PhysicalAddress.LowPart;
+    }
+
+    //
+    // now link descriptor to endpoint
+    //
+    EndpointDescriptor->HeadPhysicalDescriptor = 
SetupDescriptor->PhysicalAddress.LowPart;
+    EndpointDescriptor->TailPhysicalDescriptor = 
SetupDescriptor->PhysicalAddress.LowPart;
+    DPRINT1("CUSBRequest::BuildControlTransferDescriptor done\n");
+
+    //
+    // store result
+    //
+    *OutEndpointDescriptor = EndpointDescriptor;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::GetEndpointDescriptor(
+    struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
+{
+    ULONG TransferType;
+    NTSTATUS Status;
+
+    //
+    // get transfer type
+    //
+    TransferType = InternalGetTransferType();
+
+    //
+    // build request depending on type
+    //
+    switch(TransferType)
+    {
+        case USB_ENDPOINT_TYPE_CONTROL:
+            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;
+            break;
+        case USB_ENDPOINT_TYPE_ISOCHRONOUS:
+            DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+        default:
+            PC_ASSERT(FALSE);
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+    }
+
+    if (NT_SUCCESS(Status))
+    {
+        //
+        // store queue head
+        //
+        //m_QueueHead = *OutDescriptor;
+
+        //
+        // store request object
+        //
+        (*OutDescriptor)->Request = PVOID(this);
+    }
+
+    //
+    // done
+    //
+    return Status;
+}
 
 
//----------------------------------------------------------------------------------------
 VOID


Reply via email to