Author: janderwald
Date: Fri May 27 13:04:55 2011
New Revision: 51957

URL: http://svn.reactos.org/svn/reactos?rev=51957&view=rev
Log:
[USBOHCI]
- Implement function to retrieve isochronous head endpoint descriptor
- Implement function to retrieve current frame number
- Set isochronous descriptor flag for head endpoint
- Implement retrieve device status for devices
- Implement retrieve class status from device
- Partly implement isochronous descriptor handling in usb queue
- Start implementing isochronous transfers in ISUBRequest
- Code currently not tested as the Virtual Machine with XP + ReactOS usbohci 
driver brings down the host system when starting the iso transfers. Ironically 
it crashes in MS usbohci driver


Modified:
    branches/usb-bringup/drivers/usb/usbohci/hardware.cpp
    branches/usb-bringup/drivers/usb/usbohci/hardware.h
    branches/usb-bringup/drivers/usb/usbohci/hub_controller.cpp
    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=51957&r1=51956&r2=51957&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] Fri May 
27 13:04:55 2011
@@ -62,7 +62,9 @@
     NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** 
OutDescriptor);
     NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR 
** OutDescriptor);
     NTSTATUS GetInterruptEndpointDescriptors(struct _OHCI_ENDPOINT_DESCRIPTOR 
*** OutDescriptor);
+    NTSTATUS GetIsochronousHeadEndpointDescriptor(struct 
_OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
     VOID HeadEndpointDescriptorModified(ULONG HeadType);
+
 
     NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager);
     NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue);
@@ -80,6 +82,7 @@
 
     KIRQL AcquireDeviceLock(void);
     VOID ReleaseDeviceLock(KIRQL OldLevel);
+    virtual VOID GetCurrentFrameNumber(PULONG FrameNumber);
     // local
     BOOLEAN InterruptService();
     NTSTATUS InitializeController();
@@ -698,6 +701,17 @@
     return STATUS_SUCCESS;
 }
 
+NTSTATUS
+CUSBHardwareDevice::GetIsochronousHeadEndpointDescriptor(
+    struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
+{
+    //
+    // get descriptor
+    //
+    *OutDescriptor = m_IsoEndpointDescriptor;
+    return STATUS_SUCCESS;
+}
+
 VOID
 CUSBHardwareDevice::HeadEndpointDescriptorModified(
     ULONG Type)
@@ -847,6 +861,11 @@
     // Now link the first endpoint to the isochronous endpoint
     //
     m_InterruptEndpoints[0]->NextPhysicalEndpoint = 
m_IsoEndpointDescriptor->PhysicalAddress.LowPart;
+
+    //
+    // set iso endpoint type
+    //
+    m_IsoEndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
 
     //
     // done
@@ -1183,6 +1202,15 @@
     return OldLevel;
 }
 
+VOID
+CUSBHardwareDevice::GetCurrentFrameNumber(
+    PULONG FrameNumber)
+{
+    //
+    // store frame number
+    //
+    *FrameNumber = m_HCCA->CurrentFrameNumber;
+}
 
 VOID
 CUSBHardwareDevice::ReleaseDeviceLock(

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=51957&r1=51956&r2=51957&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] Fri May 27 
13:04:55 2011
@@ -231,6 +231,8 @@
 #define OHCI_ENDPOINT_FULL_SPEED                0x00000000
 #define OHCI_ENDPOINT_DIRECTION_OUT             0x00000800
 #define OHCI_ENDPOINT_DIRECTION_IN              0x00001000
+#define OHCI_ENDPOINT_GENERAL_FORMAT            0x00000000
+#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT        0x00008000
 
 //
 // Maximum port count set by OHCI
@@ -293,3 +295,35 @@
 #define OHCI_TD_CONDITION_BUFFER_OVERRUN    0x0c
 #define OHCI_TD_CONDITION_BUFFER_UNDERRUN   0x0d
 #define OHCI_TD_CONDITION_NOT_ACCESSED      0x0f
+
+// --------------------------------
+//  Isochronous transfer descriptor structure (section 4.3.2)
+// --------------------------------
+
+#define OHCI_ITD_NOFFSET 8
+
+typedef struct _OHCI_ISO_TD_
+{
+
+    // Hardware part 32 byte
+    ULONG Flags;
+    ULONG BufferPhysical;                       // Physical page number of 
byte 0
+    ULONG NextPhysicalDescriptor;               // Next isochronous transfer 
descriptor
+    ULONG LastPhysicalByteAddress;              // Physical buffer end
+    ULONG Offset[OHCI_ITD_NOFFSET];             // Buffer offsets
+
+    // Software part
+    PHYSICAL_ADDRESS PhysicalAddress;             // Physical address of this 
descriptor
+    struct _OHCI_ISO_TD_ * NextLogicalDescriptor; // Logical pointer next 
descriptor
+}OHCI_ISO_TD, *POHCI_ISO_TD;
+
+#define OHCI_ITD_GET_STARTING_FRAME(x)          ((x) & 0x0000ffff)
+#define OHCI_ITD_SET_STARTING_FRAME(x)          ((x) & 0xffff)
+#define OHCI_ITD_GET_DELAY_INTERRUPT(x)         (((x) >> 21) & 7)
+#define OHCI_ITD_SET_DELAY_INTERRUPT(x)         ((x) << 21)
+#define OHCI_ITD_NO_INTERRUPT                   0x00e00000
+#define OHCI_ITD_GET_FRAME_COUNT(x)             ((((x) >> 24) & 7) + 1)
+#define OHCI_ITD_SET_FRAME_COUNT(x)             (((x) - 1) << 24)
+#define OHCI_ITD_GET_CONDITION_CODE(x)          ((x) >> 28)
+#define OHCI_ITD_NO_CONDITION_CODE              0xf0000000
+

Modified: branches/usb-bringup/drivers/usb/usbohci/hub_controller.cpp
URL: 
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci/hub_controller.cpp?rev=51957&r1=51956&r2=51957&view=diff
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/hub_controller.cpp [iso-8859-1] 
(original)
+++ branches/usb-bringup/drivers/usb/usbohci/hub_controller.cpp [iso-8859-1] 
Fri May 27 13:04:55 2011
@@ -1119,7 +1119,10 @@
     IN OUT PIRP Irp, 
     PURB Urb)
 {
-    PUSHORT Status;
+    PUSHORT DeviceStatus;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+    PUSBDEVICE UsbDevice;
 
     //
     // sanity checks
@@ -1127,22 +1130,54 @@
     PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
     PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= 
sizeof(USHORT));
     PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
-    PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL); 
 
     //
     // get status buffer
     //
-    Status = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
-
-    //
-    // FIXME need more flags ?
-    //
-    *Status = USB_PORT_STATUS_CONNECT;
+    DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
+
+
+    if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
+    {
+        //
+        // FIXME need more flags ?
+        //
+        *DeviceStatus = USB_PORT_STATUS_CONNECT;
+        return STATUS_SUCCESS;
+    }
+
+    //
+    // check if this is a valid usb device handle
+    //
+    ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+
+    //
+    // get device
+    //
+    UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+
+     //
+     // generate setup packet
+     //
+     CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
+     CtrlSetup.wValue.LowByte = 0;
+     CtrlSetup.wValue.HiByte = 0;
+     CtrlSetup.wIndex.W = Urb->UrbControlGetStatusRequest.Index; 
+     CtrlSetup.wLength = 
(USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
+     CtrlSetup.bmRequestType.B = 0x80;
+
+    //
+    // submit setup packet
+    //
+    Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 
Urb->UrbControlDescriptorRequest.TransferBufferLength, 
Urb->UrbControlDescriptorRequest.TransferBuffer);
+    ASSERT(Status == STATUS_SUCCESS);
+    DPRINT1("CHubController::HandleGetStatusFromDevice Status %x Length %lu 
DeviceStatus %x\n", Status, 
Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus);
 
     //
     // done
     //
-    return STATUS_SUCCESS;
+    return Status;
 }
 
 
//-----------------------------------------------------------------------------------------
@@ -1155,6 +1190,8 @@
     PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
     ULONG PortCount, Dummy2;
     USHORT Dummy1;
+    PUSBDEVICE UsbDevice;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
 
     DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", 
Urb->UrbControlVendorClassRequest.Request, 
Urb->UrbControlVendorClassRequest.Value >> 8);
 
@@ -1163,6 +1200,36 @@
     //
     switch(Urb->UrbControlVendorClassRequest.Request)
     {
+        case USB_REQUEST_GET_STATUS:
+        {
+            //
+            // check if this is a valid usb device handle
+            //
+            
ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+
+            //
+            // get device
+            //
+            UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+
+            //
+            // generate setup packet
+            //
+            CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
+            CtrlSetup.wValue.LowByte = Urb->UrbControlVendorClassRequest.Index;
+            CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
+            CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
+            CtrlSetup.wLength = 
(USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
+            CtrlSetup.bmRequestType.B = 0xA0;
+
+            //
+            // submit setup packet
+            //
+            Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 
Urb->UrbControlDescriptorRequest.TransferBufferLength, 
Urb->UrbControlDescriptorRequest.TransferBuffer);
+            ASSERT(Status == STATUS_SUCCESS);
+            break;
+        }
         case USB_REQUEST_GET_DESCRIPTOR:
         {
             switch (Urb->UrbControlVendorClassRequest.Value >> 8)

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=51957&r1=51956&r2=51957&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] Fri May 
27 13:04:55 2011
@@ -190,6 +190,15 @@
 
 
//-----------------------------------------------------------------------------------------
 //
+// GetIsochronousHeadEndpointDescriptor
+//
+// Description: returns the control head endpoint descriptor
+
+    virtual NTSTATUS GetIsochronousHeadEndpointDescriptor(struct 
_OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
+
+
+//-----------------------------------------------------------------------------------------
+//
 // GetInterruptEndpointDescriptors
 //
 // Description: returns interrupt endpoint descriptors
@@ -301,6 +310,14 @@
 // Description: releases the device lock
 
     virtual void ReleaseDeviceLock(KIRQL OldLevel) = 0;
+
+//----------------------------------------------------------------------------------------
+//
+// GetCurrentFrameNumber
+//
+// Description: returns the current frame  number
+
+    virtual VOID GetCurrentFrameNumber(PULONG FrameNumber) = 0;
 };
 
 typedef IUSBHardwareDevice *PUSBHARDWAREDEVICE;

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=51957&r1=51956&r2=51957&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] Fri May 
27 13:04:55 2011
@@ -61,6 +61,7 @@
     PUSBHARDWAREDEVICE m_Hardware;                                             
         // hardware
     POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor;                    
         // bulk head descriptor
     POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor;                 
         // control head descriptor
+    POHCI_ENDPOINT_DESCRIPTOR m_IsoHeadEndpointDescriptor;                     
         // isochronous head descriptor
     POHCI_ENDPOINT_DESCRIPTOR * m_InterruptEndpoints;
 };
 
@@ -101,6 +102,9 @@
     
Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor);
 
     //
+    
Hardware->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor);
+
+    //
     // get interrupt endpoints
     //
     Hardware->GetInterruptEndpointDescriptors(&m_InterruptEndpoints);
@@ -164,6 +168,8 @@
     KIRQL OldLevel;
     POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
     POHCI_ENDPOINT_DESCRIPTOR Descriptor;
+    POHCI_ISO_TD CurrentDescriptor;
+    ULONG FrameNumber;
 
     DPRINT("CUSBQueue::AddUSBRequest\n");
 
@@ -176,39 +182,6 @@
     // get request type
     //
     Type = Request->GetTransferType();
-
-    //
-    // check if supported
-    //
-    switch(Type)
-    {
-        case USB_ENDPOINT_TYPE_ISOCHRONOUS:
-            /* NOT IMPLEMENTED IN QUEUE */
-            Status = STATUS_NOT_SUPPORTED;
-            break;
-        case USB_ENDPOINT_TYPE_INTERRUPT:
-        case USB_ENDPOINT_TYPE_CONTROL:
-        case USB_ENDPOINT_TYPE_BULK:
-            Status = STATUS_SUCCESS;
-            break;
-        default:
-            /* BUG */
-            PC_ASSERT(FALSE);
-            Status = STATUS_NOT_SUPPORTED;
-    }
-
-    //
-    // check for success
-    //
-    if (!NT_SUCCESS(Status))
-    {
-        //
-        // request not supported, please try later
-        //
-        DPRINT1("Request Type %x not supported\n", Type);
-        ASSERT(FALSE);
-        return Status;
-    }
 
     //
     // add extra reference which is released when the request is completed
@@ -258,6 +231,48 @@
         HeadDescriptor = 
FindInterruptEndpointDescriptor(Request->GetInterval());
         ASSERT(HeadDescriptor);
     }
+    else if (Type == USB_ENDPOINT_TYPE_ISOCHRONOUS)
+    {
+        //
+        // get head descriptor
+        //
+        HeadDescriptor = m_IsoHeadEndpointDescriptor;
+
+        //
+        // get current frame number
+        //
+        m_Hardware->GetCurrentFrameNumber(&FrameNumber);
+
+        //
+        // increment frame number
+        //
+        FrameNumber++;
+
+        //
+        // apply frame number to iso transfer descriptors
+        //
+        CurrentDescriptor = (POHCI_ISO_TD)Descriptor->HeadLogicalDescriptor;
+
+        DPRINT1("ISO: NextFrameNumber %x\n", FrameNumber);
+
+        while(CurrentDescriptor)
+        {
+            //
+            // set current frame number
+            //
+            CurrentDescriptor->Flags |= 
OHCI_ITD_SET_STARTING_FRAME(FrameNumber);
+
+            //
+            // move to next frame number
+            //
+            FrameNumber++;
+
+            //
+            // move to next descriptor
+            //
+            CurrentDescriptor = CurrentDescriptor->NextLogicalDescriptor;
+        }
+    }
 
     //
     // insert endpoint at end
@@ -269,9 +284,6 @@
     //
     Descriptor->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);
-
-
     if (Type == USB_ENDPOINT_TYPE_CONTROL || Type == USB_ENDPOINT_TYPE_BULK)
     {
         //
@@ -279,6 +291,7 @@
         //
         m_Hardware->HeadEndpointDescriptorModified(Type);
     }
+
 
     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=51957&r1=51956&r2=51957&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] Fri 
May 27 13:04:55 2011
@@ -57,9 +57,11 @@
     NTSTATUS BuildSetupPacketFromURB();
     NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * 
OutEndpointDescriptor);
     NTSTATUS BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR * 
OutEndpointDescriptor);
+    NTSTATUS BuildIsochronousEndpoint(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);
+    NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD 
*OutDescriptor, ULONG FrameCount);
     UCHAR GetEndpointAddress();
     USHORT GetMaxPacketSize();
 
@@ -243,6 +245,81 @@
     //
     switch (Urb->UrbHeader.Function)
     {
+        case URB_FUNCTION_ISOCH_TRANSFER:
+        {
+            //
+            // there must be at least one packet
+            //
+            ASSERT(Urb->UrbIsochronousTransfer.NumberOfPackets);
+
+            //
+            // is there data to be transferred
+            //
+            if (Urb->UrbIsochronousTransfer.TransferBufferLength)
+            {
+                //
+                // Check if there is a MDL
+                //
+                if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
+                {
+                    //
+                    // sanity check
+                    //
+                    PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
+
+                    //
+                    // Create one using TransferBuffer
+                    //
+                    DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", 
Urb->UrbBulkOrInterruptTransfer.TransferBuffer, 
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
+                    m_TransferBufferMDL = 
IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
+                                                        
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
+                                                        FALSE,
+                                                        FALSE,
+                                                        NULL);
+
+                    if (!m_TransferBufferMDL)
+                    {
+                        //
+                        // failed to allocate mdl
+                        //
+                        return STATUS_INSUFFICIENT_RESOURCES;
+                    }
+
+                    //
+                    // build mdl for non paged pool
+                    // FIXME: Does hub driver already do this when passing MDL?
+                    //
+                    MmBuildMdlForNonPagedPool(m_TransferBufferMDL);
+                }
+                else
+                {
+                    //
+                    // use provided mdl
+                    //
+                    m_TransferBufferMDL = 
Urb->UrbIsochronousTransfer.TransferBufferMDL;
+                }
+            }
+
+            //
+            // save buffer length
+            //
+            m_TransferBufferLength = 
Urb->UrbIsochronousTransfer.TransferBufferLength;
+
+            //
+            // Set Length Completed to 0
+            //
+            m_TransferBufferLengthCompleted = 0;
+
+            //
+            // get endpoint descriptor
+            //
+            m_EndpointDescriptor = 
(PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbIsochronousTransfer.PipeHandle;
+
+            //
+            // completed initialization
+            //
+            break;
+        }
         //
         // luckily those request have the same structure layout
         //
@@ -525,6 +602,230 @@
     m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
 
 }
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::CreateIsochronousTransferDescriptor(
+    POHCI_ISO_TD* OutDescriptor, 
+    ULONG FrameCount)
+{
+    POHCI_ISO_TD Descriptor;
+    PHYSICAL_ADDRESS DescriptorAddress;
+    NTSTATUS Status;
+
+    //
+    // allocate transfer descriptor
+    //
+    Status = m_DmaManager->Allocate(sizeof(OHCI_ISO_TD), (PVOID*)&Descriptor, 
&DescriptorAddress);
+    if (!NT_SUCCESS(Status))
+    {
+         //
+         // no memory
+         //
+         return Status;
+    }
+
+    //
+    // initialize descriptor, hardware part
+    //
+    Descriptor->Flags = OHCI_ITD_SET_FRAME_COUNT(FrameCount) | 
OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) |  
OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED);
+    Descriptor->BufferPhysical = 0;
+    Descriptor->NextPhysicalDescriptor = 0;
+    Descriptor->LastPhysicalByteAddress = 0;
+
+    //
+    // software part
+    //
+    Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
+    Descriptor->NextLogicalDescriptor = 0;
+
+    //
+    // store result
+    //
+    *OutDescriptor = Descriptor;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBRequest::BuildIsochronousEndpoint(
+    POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
+{
+    POHCI_ISO_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor;
+    POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+    ULONG Index = 0, SubIndex, NumberOfPackets, PageOffset;
+    NTSTATUS Status;
+    PVOID Buffer;
+    PIO_STACK_LOCATION IoStack;
+    PURB Urb;
+
+    DPRINT1("cp\n");
+    //
+    // get current irp stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
+    PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == 
IOCTL_INTERNAL_USB_SUBMIT_URB);
+    PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
+
+    //
+    // get urb
+    //
+    Urb = (PURB)IoStack->Parameters.Others.Argument1;
+    ASSERT(Urb);
+
+    //
+    // allocate endpoint descriptor
+    //
+    Status = AllocateEndpointDescriptor(&EndpointDescriptor);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to create setup descriptor
+        //
+        return Status;
+    }
+    DPRINT1("cp\n");
+    //
+    // get buffer
+    //
+    Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, 
NormalPagePriority);
+    ASSERT(Buffer);
+
+    DPRINT1("cp\n");
+    while(Index < Urb->UrbIsochronousTransfer.NumberOfPackets)
+    {
+        //
+        // get number of packets remaining
+        //
+        NumberOfPackets = min(Urb->UrbIsochronousTransfer.NumberOfPackets - 
Index, OHCI_ITD_NOFFSET);
+    DPRINT1("cp Number Packets %lu\n", NumberOfPackets);
+        //
+        // allocate iso descriptor
+        //
+        Status = CreateIsochronousTransferDescriptor(&CurrentDescriptor, 
NumberOfPackets);
+        if (!NT_SUCCESS(Status))
+        {
+            //
+            // FIXME: cleanup
+            // failed to allocate descriptor
+            //
+            ASSERT(FALSE);
+            return Status;
+        }
+    DPRINT1("cp\n");
+        //
+        // initialize descriptor
+        //
+        CurrentDescriptor->BufferPhysical = 
(MmGetPhysicalAddress(Buffer).LowPart & ~ (PAGE_SIZE - 1));
+
+        //
+        // get page offset
+        //
+        PageOffset = BYTE_OFFSET(MmGetPhysicalAddress(Buffer).LowPart);
+    DPRINT1("cp\n");
+        for(SubIndex = 0; SubIndex < NumberOfPackets; SubIndex++)
+        {
+            //
+            // store buffer offset
+            //
+            CurrentDescriptor->Offset[SubIndex] = 
Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset + PageOffset;
+        }
+
+        //
+        // increment packet offset
+        //
+        Index += NumberOfPackets;
+
+        //
+        // check if this is the last descriptor
+        //
+        if (Index == Urb->UrbIsochronousTransfer.NumberOfPackets)
+        {
+            //
+            // end of transfer
+            //
+            CurrentDescriptor->LastPhysicalByteAddress = 
CurrentDescriptor->BufferPhysical + m_TransferBufferLength - 1;
+        }
+        else
+        {
+            //
+            // use start address of next packet - 1
+            //
+            CurrentDescriptor->LastPhysicalByteAddress = 
CurrentDescriptor->BufferPhysical + PageOffset + 
Urb->UrbIsochronousTransfer.IsoPacket[Index + 1].Offset - 1;
+
+            //
+            // move buffer to next address
+            //
+            Buffer = (PVOID)((ULONG_PTR)Buffer + 
Urb->UrbIsochronousTransfer.IsoPacket[Index + 1].Offset);
+        }
+
+        //
+        // is there a previous descriptor
+        //
+        if (PreviousDescriptor)
+        {
+            //
+            // link descriptors
+            //
+            PreviousDescriptor->NextLogicalDescriptor = CurrentDescriptor;
+            PreviousDescriptor->NextPhysicalDescriptor = 
CurrentDescriptor->PhysicalAddress.LowPart;
+        }
+        else
+        {
+            //
+            // first descriptor
+            //
+            FirstDescriptor = CurrentDescriptor;
+        }
+
+        //
+        // store as previous descriptor
+        //
+        PreviousDescriptor = CurrentDescriptor;
+    }
+    DPRINT1("cp\n");
+
+    //
+    // 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);
+
+    //
+    // set isochronous type
+    //
+    EndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
+
+    //
+    // now link descriptor to endpoint
+    //
+    EndpointDescriptor->HeadPhysicalDescriptor = 
FirstDescriptor->PhysicalAddress.LowPart;
+    EndpointDescriptor->TailPhysicalDescriptor = 
CurrentDescriptor->PhysicalAddress.LowPart;
+    EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
+    DPRINT1("cp\n");
+    //
+    // store result
+    //
+    *OutEndpointDescriptor = EndpointDescriptor;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
 
//----------------------------------------------------------------------------------------
 NTSTATUS
 CUSBRequest::CreateGeneralTransferDescriptor(
@@ -1084,8 +1385,7 @@
             Status = BuildBulkInterruptEndpoint(OutDescriptor);
             break;
         case USB_ENDPOINT_TYPE_ISOCHRONOUS:
-            DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
-            Status = STATUS_NOT_IMPLEMENTED;
+            Status = 
BuildIsochronousEndpoint((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
             break;
         default:
             PC_ASSERT(FALSE);
@@ -1201,7 +1501,6 @@
 CUSBRequest::CompletionCallback(
     struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
 {
-    POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
     PIO_STACK_LOCATION IoStack;
     PURB Urb;
 


Reply via email to