Author: mjmartin
Date: Fri Dec 31 12:01:21 2010
New Revision: 50230
URL: 
http://svn.reactos.org/svn/reactos?rev=50230&view=rev
Log:
[usb/usbehci]:
- Implement creating and deleting Queue Heads and Transfer Descriptors from common buffer.
- Implement linking/unlinking QueueHeads to create a linked list for Asynchronous Schedule
traversal.
- Implement BuildSetupPacketFromURB for creating a setup packet from a URB.
- Implement SubmitControlTransfer.
Added:
    trunk/reactos/drivers/usb/usbehci/hwiface.c   (with props)
    trunk/reactos/drivers/usb/usbehci/hwiface.h   (with props)
    trunk/reactos/drivers/usb/usbehci/transfer.c   (with props)
    trunk/reactos/drivers/usb/usbehci/transfer.h   (with props)
Added: trunk/reactos/drivers/usb/usbehci/hwiface.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/hwifac…
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/hwiface.c (added)
+++ trunk/reactos/drivers/usb/usbehci/hwiface.c [iso-8859-1] Fri Dec 31 12:01:21 2010
@@ -1,0 +1,175 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci/hwiface.c
+ * PURPOSE:     EHCI Interface routines: Queue Heads and Queue Element
+                Transfer Descriptors.
+ * TODO:        Periodic Frame List, Isochronous Transaction Descriptors
+                and Split-transaction ITD.
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin(a)reactos.org)
+ */
+
+#include "hwiface.h"
+#include "physmem.h"
+#define NDEBUG
+#include <debug.h>
+
+/* Queue Element Transfer Descriptors */
+
+PQUEUE_TRANSFER_DESCRIPTOR
+CreateDescriptor(PEHCI_HOST_CONTROLLER hcd, UCHAR PIDCode, ULONG TotalBytesToTransfer)
+{
+    PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
+    ULONG PhysicalAddress;
+    UCHAR i;
+    KIRQL OldIrql;
+
+    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
+
+    Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)AllocateMemory(hcd,
sizeof(QUEUE_TRANSFER_DESCRIPTOR), &PhysicalAddress);
+    RtlZeroMemory(Descriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
+    Descriptor->NextPointer = TERMINATE_POINTER;
+    Descriptor->AlternateNextPointer = TERMINATE_POINTER;
+    Descriptor->Token.Bits.DataToggle = TRUE;
+    Descriptor->Token.Bits.InterruptOnComplete = TRUE;
+    Descriptor->Token.Bits.ErrorCounter = 0x03;
+    Descriptor->Token.Bits.Active = TRUE;
+    Descriptor->Token.Bits.PIDCode = PIDCode;
+    Descriptor->Token.Bits.TotalBytesToTransfer = TotalBytesToTransfer;
+    Descriptor->PhysicalAddr = PhysicalAddress;
+    for (i=0;i<5;i++)
+        Descriptor->BufferPointer[i] = 0;
+
+    KeReleaseSpinLock(&hcd->Lock, OldIrql);
+
+    return Descriptor;
+}
+
+VOID
+FreeDescriptor(PQUEUE_TRANSFER_DESCRIPTOR Descriptor)
+{
+    ReleaseMemory((ULONG)Descriptor);
+}
+
+/* Queue Head */
+
+VOID
+DumpQueueHeadList(PEHCI_HOST_CONTROLLER hcd)
+{
+    KIRQL OldIrql;
+
+    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
+
+    PQUEUE_HEAD QueueHead = (PQUEUE_HEAD)hcd->CommonBufferVA;
+    PQUEUE_HEAD FirstQueueHead = QueueHead;
+    DPRINT1("Dumping QueueHead List!!!!!!!!!!!!!\n");
+    while (1)
+    {
+        DPRINT1("QueueHead Address %x\n", QueueHead);
+        DPRINT1("QueueHead->PreviousQueueHead = %x\n",
QueueHead->PreviousQueueHead);
+        DPRINT1("QueueHead->NextQueueHead = %x\n",
QueueHead->NextQueueHead);
+        DPRINT1(" ---> PhysicalAddress %x\n",
(ULONG)MmGetPhysicalAddress(QueueHead).LowPart);
+        DPRINT1("QueueHead->HorizontalLinkPointer %x\n",
QueueHead->HorizontalLinkPointer);
+        QueueHead = QueueHead->NextQueueHead;
+        DPRINT1("Next QueueHead %x\n", QueueHead);
+        if (QueueHead == FirstQueueHead) break;
+    }
+    DPRINT1("-----------------------------------\n");
+    KeReleaseSpinLock(&hcd->Lock, OldIrql);
+}
+
+PQUEUE_HEAD
+CreateQueueHead(PEHCI_HOST_CONTROLLER hcd)
+{
+    PQUEUE_HEAD CurrentQH;
+    ULONG PhysicalAddress , i;
+    KIRQL OldIrql;
+
+    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
+
+    CurrentQH = (PQUEUE_HEAD)AllocateMemory(hcd, sizeof(QUEUE_HEAD),
&PhysicalAddress);
+    RtlZeroMemory(CurrentQH, sizeof(QUEUE_HEAD));
+
+    ASSERT(CurrentQH);
+    CurrentQH->PhysicalAddr = PhysicalAddress;
+    CurrentQH->HorizontalLinkPointer = TERMINATE_POINTER;
+    CurrentQH->CurrentLinkPointer = TERMINATE_POINTER;
+    CurrentQH->AlternateNextPointer = TERMINATE_POINTER;
+    CurrentQH->NextPointer = TERMINATE_POINTER;
+
+    /* 1 for non high speed, 0 for high speed device */
+    CurrentQH->EndPointCharacteristics.ControlEndPointFlag = 0;
+    CurrentQH->EndPointCharacteristics.HeadOfReclamation = FALSE;
+    CurrentQH->EndPointCharacteristics.MaximumPacketLength = 64;
+
+    /* Set NakCountReload to max value possible */
+    CurrentQH->EndPointCharacteristics.NakCountReload = 0xF;
+
+    /* Get the Initial Data Toggle from the QEDT */
+    CurrentQH->EndPointCharacteristics.QEDTDataToggleControl = TRUE;
+
+    /* High Speed Device */
+    CurrentQH->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
+
+    CurrentQH->EndPointCapabilities.NumberOfTransactionPerFrame = 0x03;
+
+    CurrentQH->Token.DWord = 0;
+    CurrentQH->NextQueueHead = NULL;
+    CurrentQH->PreviousQueueHead = NULL;
+    for (i=0; i<5; i++)
+        CurrentQH->BufferPointer[i] = 0;
+
+    CurrentQH->Token.Bits.InterruptOnComplete = TRUE;
+
+    KeReleaseSpinLock(&hcd->Lock, OldIrql);
+    return CurrentQH;
+}
+
+VOID
+LinkQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead)
+{
+    KIRQL OldIrql;
+    PQUEUE_HEAD CurrentHead  = (PQUEUE_HEAD)hcd->AsyncListQueue;
+    PQUEUE_HEAD PreviousHead = CurrentHead->PreviousQueueHead;
+
+    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
+
+    QueueHead->HorizontalLinkPointer = (CurrentHead->HorizontalLinkPointer |
QH_TYPE_QH) & ~TERMINATE_POINTER;
+    QueueHead->NextQueueHead = CurrentHead;
+    QueueHead->PreviousQueueHead = PreviousHead;
+
+    CurrentHead->PreviousQueueHead = QueueHead;
+    if (PreviousHead)
+        PreviousHead->NextQueueHead = QueueHead;
+
+    CurrentHead->HorizontalLinkPointer = QueueHead->PhysicalAddr | QH_TYPE_QH;
+
+    KeReleaseSpinLock(&hcd->Lock, OldIrql);
+}
+
+VOID
+UnlinkQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead)
+{
+    KIRQL OldIrql;
+    PQUEUE_HEAD PreviousHead = QueueHead->PreviousQueueHead;
+    PQUEUE_HEAD NextHead = QueueHead->NextQueueHead;
+    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
+
+    if (PreviousHead)
+    {
+        PreviousHead->NextQueueHead = NextHead;
+        PreviousHead->HorizontalLinkPointer = QueueHead->HorizontalLinkPointer;
+    }
+    if (NextHead)
+        NextHead->PreviousQueueHead = PreviousHead;
+
+    KeReleaseSpinLock(&hcd->Lock, OldIrql);
+}
+
+VOID
+DeleteQueueHead(PQUEUE_HEAD QueueHead)
+{
+    ReleaseMemory((ULONG)QueueHead);
+}
+
Propchange: trunk/reactos/drivers/usb/usbehci/hwiface.c
------------------------------------------------------------------------------
    svn:eol-style = native
Added: trunk/reactos/drivers/usb/usbehci/hwiface.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/hwifac…
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/hwiface.h (added)
+++ trunk/reactos/drivers/usb/usbehci/hwiface.h [iso-8859-1] Fri Dec 31 12:01:21 2010
@@ -1,0 +1,24 @@
+#include "hardware.h"
+#include <ntddk.h>
+
+PQUEUE_TRANSFER_DESCRIPTOR
+CreateDescriptor(PEHCI_HOST_CONTROLLER hcd, UCHAR PIDCode, ULONG TotalBytesToTransfer);
+
+VOID
+FreeDescriptor(PQUEUE_TRANSFER_DESCRIPTOR Descriptor);
+
+VOID
+DumpQueueHeadList(PEHCI_HOST_CONTROLLER hcd);
+
+PQUEUE_HEAD
+CreateQueueHead(PEHCI_HOST_CONTROLLER hcd);
+
+VOID
+LinkQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead);
+
+VOID
+UnlinkQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead);
+
+VOID
+DeleteQueueHead(PQUEUE_HEAD QueueHead);
+
Propchange: trunk/reactos/drivers/usb/usbehci/hwiface.h
------------------------------------------------------------------------------
    svn:eol-style = native
Added: trunk/reactos/drivers/usb/usbehci/transfer.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/transf…
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/transfer.c (added)
+++ trunk/reactos/drivers/usb/usbehci/transfer.c [iso-8859-1] Fri Dec 31 12:01:21 2010
@@ -1,0 +1,217 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci/transfer.c
+ * PURPOSE:     Transfers to EHCI.
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin(a)reactos.org)
+ */
+
+#include "transfer.h"
+#include <debug.h>
+
+VOID
+BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd, PURB Urb,
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup)
+{
+    switch (Urb->UrbHeader.Function)
+    {
+    /* CLEAR FEATURE */
+        case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
+        case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
+        case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
+            DPRINT1("Not implemented!\n");
+            break;
+
+    /* GET CONFIG */
+        case URB_FUNCTION_GET_CONFIGURATION:
+            CtrlSetup->bRequest = USB_REQUEST_GET_CONFIGURATION;
+            CtrlSetup->bmRequestType.B = 0x80;
+            CtrlSetup->wLength = 1;
+            break;
+
+    /* GET DESCRIPTOR */
+        case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+            CtrlSetup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+            CtrlSetup->wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
+            CtrlSetup->wValue.HiByte =
Urb->UrbControlDescriptorRequest.DescriptorType;
+            CtrlSetup->wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
+            CtrlSetup->wLength =
Urb->UrbControlDescriptorRequest.TransferBufferLength;
+            CtrlSetup->bmRequestType.B = 0x80;
+            break;
+
+    /* GET INTERFACE */
+        case URB_FUNCTION_GET_INTERFACE:
+            CtrlSetup->bRequest = USB_REQUEST_GET_CONFIGURATION;
+            CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
+            CtrlSetup->bmRequestType.B = 0x80;
+            CtrlSetup->wLength = 1;
+            break;
+
+    /* GET STATUS */
+        case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
+            CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
+            ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
+            CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
+            CtrlSetup->bmRequestType.B = 0x80;
+            CtrlSetup->wLength = 2;
+            break;
+
+    case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
+            CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
+            ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
+            CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
+            CtrlSetup->bmRequestType.B = 0x81;
+            CtrlSetup->wLength = 2;
+            break;
+
+    case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
+            CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
+            ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
+            CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
+            CtrlSetup->bmRequestType.B = 0x82;
+            CtrlSetup->wLength = 2;
+            break;
+
+    /* SET ADDRESS */
+
+    /* SET CONFIG */
+        case URB_FUNCTION_SELECT_CONFIGURATION:
+            CtrlSetup->bRequest = USB_REQUEST_SET_CONFIGURATION;
+            CtrlSetup->bmRequestType.B = 0x00;
+            break;
+
+    /* SET DESCRIPTOR */
+        case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:
+        case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
+        case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:
+            DPRINT1("Not implemented\n");
+            break;
+
+    /* SET FEATURE */
+        case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
+            CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
+            ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
+            CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
+            CtrlSetup->bmRequestType.B = 0x80;
+            break;
+
+        case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
+            CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
+            ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
+            CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
+            CtrlSetup->bmRequestType.B = 0x81;
+            break;
+
+        case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
+            CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
+            ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
+            CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
+            CtrlSetup->bmRequestType.B = 0x82;
+            break;
+
+    /* SET INTERFACE*/
+        case URB_FUNCTION_SELECT_INTERFACE:
+            DPRINT1("Not implemented\n");
+            break;
+
+    /* SYNC FRAME */
+        case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
+            DPRINT1("Not implemented\n");
+            break;
+        default:
+            DPRINT1("Unknown USB Request!\n");
+            break;
+    }
+}
+
+BOOLEAN
+SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
+                      PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
+                      PVOID TransferBuffer,
+                      ULONG TransferBufferLength,
+                      PIRP IrpToComplete)
+{
+    PQUEUE_HEAD QueueHead;
+    PQUEUE_TRANSFER_DESCRIPTOR Descriptor[3];
+    ULONG MdlPhysicalAddr;
+    PKEVENT Event = NULL;
+    PMDL pMdl = NULL;
+    PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetupVA, CtrlPhysicalPA;
+
+    CtrlSetupVA = (PUSB_DEFAULT_PIPE_SETUP_PACKET)AllocateMemory(hcd,
+
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET),
+
(ULONG*)&CtrlPhysicalPA);
+
+    RtlCopyMemory(CtrlSetupVA, CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+    /* If no Irp then wait on completion */
+    if (IrpToComplete == NULL)
+    {
+        Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
+        KeInitializeEvent(Event, NotificationEvent, FALSE);
+    }
+
+    /* Allocate Mdl for Buffer */
+    pMdl = IoAllocateMdl(TransferBuffer,
+                         TransferBufferLength,
+                         FALSE,
+                         FALSE,
+                         NULL);
+
+    /* Lock Physical Pages */
+    MmBuildMdlForNonPagedPool(pMdl);
+    //MmProbeAndLockPages(pMdl, KernelMode, IoReadAccess);
+
+    MdlPhysicalAddr = MmGetPhysicalAddress((PVOID)TransferBuffer).LowPart;
+
+    QueueHead = CreateQueueHead(hcd);
+
+    Descriptor[0] = CreateDescriptor(hcd,
+                                     PID_CODE_SETUP_TOKEN,
+                                     sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+    Descriptor[0]->Token.Bits.InterruptOnComplete = FALSE;
+    Descriptor[0]->Token.Bits.DataToggle = FALSE;
+
+    /* Save the first descriptor */
+    QueueHead->TransferDescriptor = Descriptor[0];
+
+    Descriptor[1] = CreateDescriptor(hcd,
+                                     PID_CODE_IN_TOKEN,
+                                     TransferBufferLength);
+
+    Descriptor[2] = CreateDescriptor(hcd,
+                                     PID_CODE_OUT_TOKEN,
+                                     0);
+
+    Descriptor[1]->Token.Bits.InterruptOnComplete = FALSE;
+
+    /* Link the descriptors */
+    Descriptor[0]->NextDescriptor = Descriptor[1];
+    Descriptor[1]->NextDescriptor = Descriptor[2];
+    Descriptor[1]->PreviousDescriptor = Descriptor[0];
+    Descriptor[2]->PreviousDescriptor = Descriptor[1];
+
+    /* Assign the descritors buffers */
+    Descriptor[0]->BufferPointer[0] = (ULONG)CtrlPhysicalPA;
+    Descriptor[1]->BufferPointer[0] = MdlPhysicalAddr;
+
+    Descriptor[0]->NextPointer = Descriptor[1]->PhysicalAddr;
+    Descriptor[1]->NextPointer = Descriptor[2]->PhysicalAddr;
+    QueueHead->NextPointer = Descriptor[0]->PhysicalAddr;
+
+    QueueHead->IrpToComplete = IrpToComplete;
+    QueueHead->MdlToFree = pMdl;
+    QueueHead->Event = Event;
+
+    /* Link in the QueueHead */
+    LinkQueueHead(hcd, QueueHead);
+
+    if (IrpToComplete == NULL)
+    {
+        DPRINT1("Waiting For Completion %x!\n", Event);
+        KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL);
+        ExFreePool(Event);
+    }
+
+    return TRUE;
+}
Propchange: trunk/reactos/drivers/usb/usbehci/transfer.c
------------------------------------------------------------------------------
    svn:eol-style = native
Added: trunk/reactos/drivers/usb/usbehci/transfer.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/transf…
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/transfer.h (added)
+++ trunk/reactos/drivers/usb/usbehci/transfer.h [iso-8859-1] Fri Dec 31 12:01:21 2010
@@ -1,0 +1,20 @@
+#pragma once
+
+#include "hardware.h"
+#include "hwiface.h"
+#include "physmem.h"
+#include <usb.h>
+#include <ntddk.h>
+
+BOOLEAN
+SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
+                      PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
+                      PVOID TransferBuffer,
+                      ULONG TransferBufferLength,
+                      PIRP IrpToComplete);
+
+VOID
+BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd,
+                        PURB Urb,
+                        PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup);
+
Propchange: trunk/reactos/drivers/usb/usbehci/transfer.h
------------------------------------------------------------------------------
    svn:eol-style = native