https://git.reactos.org/?p=reactos.git;a=commitdiff;h=83c07f4e4c2a74e00c30d…
commit 83c07f4e4c2a74e00c30db18deee7ba092f44408
Author: Oleg Dubinskiy <oleg.dubinskij2013(a)yandex.ua>
AuthorDate: Thu Jan 2 15:01:32 2020 +0200
Commit: Victor Perevertkin <victor(a)perevertkin.ru>
CommitDate: Mon Jan 6 21:16:08 2020 +0200
[SDK][USB] Delete old USB drivers and libusb
---
CODEOWNERS | 1 -
drivers/usb/CMakeLists.txt | 4 -
drivers/usb/usbehci/CMakeLists.txt | 25 -
drivers/usb/usbehci/guid.cpp | 9 -
drivers/usb/usbehci/hardware.cpp | 1490 -----------
drivers/usb/usbehci/hardware.h | 325 ---
drivers/usb/usbehci/interfaces.h | 151 --
drivers/usb/usbehci/usb_queue.cpp | 1236 ---------
drivers/usb/usbehci/usb_request.cpp | 1852 -------------
drivers/usb/usbehci/usbehci.cpp | 57 -
drivers/usb/usbehci/usbehci.h | 36 -
drivers/usb/usbehci/usbehci.rc | 5 -
drivers/usb/usbhub/CMakeLists.txt | 23 -
drivers/usb/usbhub/fdo.c | 2487 -----------------
drivers/usb/usbhub/guid.c | 9 -
drivers/usb/usbhub/hub_fdo.c | 216 --
drivers/usb/usbhub/misc.c | 213 --
drivers/usb/usbhub/pdo.c | 863 ------
drivers/usb/usbhub/usbhub.c | 297 --
drivers/usb/usbhub/usbhub.h | 225 --
drivers/usb/usbhub/usbhub.rc | 5 -
drivers/usb/usbohci/CMakeLists.txt | 25 -
drivers/usb/usbohci/guid.cpp | 9 -
drivers/usb/usbohci/hardware.cpp | 1584 -----------
drivers/usb/usbohci/hardware.h | 347 ---
drivers/usb/usbohci/interfaces.h | 134 -
drivers/usb/usbohci/usb_queue.cpp | 1022 -------
drivers/usb/usbohci/usb_request.cpp | 2014 --------------
drivers/usb/usbohci/usbohci.cpp | 45 -
drivers/usb/usbohci/usbohci.h | 54 -
drivers/usb/usbohci/usbohci.rc | 5 -
drivers/usb/usbuhci/CMakeLists.txt | 25 -
drivers/usb/usbuhci/guid.cpp | 9 -
drivers/usb/usbuhci/hardware.cpp | 1516 -----------
drivers/usb/usbuhci/hardware.h | 191 --
drivers/usb/usbuhci/interfaces.h | 138 -
drivers/usb/usbuhci/usb_queue.cpp | 548 ----
drivers/usb/usbuhci/usb_request.cpp | 1446 ----------
drivers/usb/usbuhci/usbuhci.cpp | 44 -
drivers/usb/usbuhci/usbuhci.h | 50 -
drivers/usb/usbuhci/usbuhci.rc | 5 -
sdk/lib/drivers/CMakeLists.txt | 1 -
sdk/lib/drivers/libusb/CMakeLists.txt | 21 -
sdk/lib/drivers/libusb/common_interfaces.h | 691 -----
sdk/lib/drivers/libusb/hcd_controller.cpp | 791 ------
sdk/lib/drivers/libusb/hub_controller.cpp | 4014 ----------------------------
sdk/lib/drivers/libusb/libusb.cpp | 170 --
sdk/lib/drivers/libusb/libusb.h | 105 -
sdk/lib/drivers/libusb/memory_manager.cpp | 372 ---
sdk/lib/drivers/libusb/misc.cpp | 137 -
sdk/lib/drivers/libusb/purecall.cpp | 25 -
sdk/lib/drivers/libusb/usb_device.cpp | 1329 ---------
52 files changed, 26396 deletions(-)
diff --git a/CODEOWNERS b/CODEOWNERS
index 571825b6a90..04a24a76bc2 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -275,7 +275,6 @@
# R: Extravert-ir, extravert34, Victor Perevertkin
# S: Maintained
/drivers/usb/ @ThFabba @Extravert-ir
-/sdk/lib/drivers/libusb/ @ThFabba @Extravert-ir
/sdk/include/reactos/drivers/usbport/ @ThFabba @Extravert-ir
# Virtual CD-ROM
diff --git a/drivers/usb/CMakeLists.txt b/drivers/usb/CMakeLists.txt
index 1315f1a571e..3f33c2b2c4f 100644
--- a/drivers/usb/CMakeLists.txt
+++ b/drivers/usb/CMakeLists.txt
@@ -1,13 +1,9 @@
add_subdirectory(usbccgp)
add_subdirectory(usbd)
-#add_subdirectory(usbehci)
add_subdirectory(usbehci_new)
-#add_subdirectory(usbhub)
add_subdirectory(usbhub_new)
-#add_subdirectory(usbohci)
add_subdirectory(usbohci_new)
add_subdirectory(usbport)
add_subdirectory(usbstor)
#add_subdirectory(usbstor_new)
-#add_subdirectory(usbuhci)
add_subdirectory(usbuhci_new)
diff --git a/drivers/usb/usbehci/CMakeLists.txt b/drivers/usb/usbehci/CMakeLists.txt
deleted file mode 100644
index f515915899e..00000000000
--- a/drivers/usb/usbehci/CMakeLists.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-
-set_cpp()
-
-remove_definitions(-D_WIN32_WINNT=0x502)
-add_definitions(-D_WIN32_WINNT=0x600)
-
-include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/drivers/libusb)
-
-list(APPEND SOURCE
- usbehci.cpp
- usb_request.cpp
- usb_queue.cpp
- hardware.cpp
- usbehci.h)
-
-add_library(usbehci MODULE
- ${SOURCE}
- guid.cpp
- usbehci.rc)
-
-target_link_libraries(usbehci uuid libusb libcntpr ${PSEH_LIB})
-set_module_type(usbehci kernelmodedriver)
-add_importlibs(usbehci ntoskrnl hal usbd)
-add_pch(usbehci usbehci.h SOURCE)
-add_cd_file(TARGET usbehci DESTINATION reactos/system32/drivers NO_CAB FOR all)
diff --git a/drivers/usb/usbehci/guid.cpp b/drivers/usb/usbehci/guid.cpp
deleted file mode 100644
index 50a60369ff3..00000000000
--- a/drivers/usb/usbehci/guid.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
-
-#include <wdm.h>
-#include <initguid.h>
-#include <wdmguid.h>
-#include <hubbusif.h>
-#include <usbbusif.h>
-
-/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
diff --git a/drivers/usb/usbehci/hardware.cpp b/drivers/usb/usbehci/hardware.cpp
deleted file mode 100644
index 8562eaa4b3c..00000000000
--- a/drivers/usb/usbehci/hardware.cpp
+++ /dev/null
@@ -1,1490 +0,0 @@
-/*
- * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: drivers/usb/usbehci/hcd_controller.cpp
- * PURPOSE: USB EHCI device driver.
- * PROGRAMMERS:
- * Michael Martin (michael.martin(a)reactos.org)
- * Johannes Anderwald (johannes.anderwald(a)reactos.org)
- */
-
-#include "usbehci.h"
-
-#define NDEBUG
-#include <debug.h>
-
-typedef VOID __stdcall HD_INIT_CALLBACK(IN PVOID CallBackContext);
-
-BOOLEAN
-NTAPI
-InterruptServiceRoutine(
- IN PKINTERRUPT Interrupt,
- IN PVOID ServiceContext);
-
-VOID
-NTAPI
-EhciDeferredRoutine(
- IN PKDPC Dpc,
- IN PVOID DeferredContext,
- IN PVOID SystemArgument1,
- IN PVOID SystemArgument2);
-
-VOID
-NTAPI
-StatusChangeWorkItemRoutine(PVOID Context);
-
-class CUSBHardwareDevice : public IEHCIHardwareDevice
-{
-public:
- STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
-
- STDMETHODIMP_(ULONG) AddRef()
- {
- InterlockedIncrement(&m_Ref);
- return m_Ref;
- }
- STDMETHODIMP_(ULONG) Release()
- {
- InterlockedDecrement(&m_Ref);
-
- if (!m_Ref)
- {
- delete this;
- return 0;
- }
- return m_Ref;
- }
- // com
- IMP_IUSBHARDWAREDEVICE
- IMP_IUSBEHCIHARDWARE
-
- // local
- BOOLEAN InterruptService();
- VOID PrintCapabilities();
- NTSTATUS StartController();
- NTSTATUS StopController();
- NTSTATUS ResetController();
-
- // friend function
- friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID
ServiceContext);
- friend VOID NTAPI EhciDeferredRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN
PVOID SystemArgument1, IN PVOID SystemArgument2);
- friend VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context);
- // constructor / destructor
- CUSBHardwareDevice(IUnknown *OuterUnknown){}
- virtual ~CUSBHardwareDevice(){}
-
-protected:
- LONG m_Ref; //
reference count
- PDRIVER_OBJECT m_DriverObject; //
driver object
- PDEVICE_OBJECT m_PhysicalDeviceObject; //
pdo
- PDEVICE_OBJECT m_FunctionalDeviceObject; //
fdo (hcd controller)
- PDEVICE_OBJECT m_NextDeviceObject; //
lower device object
- KSPIN_LOCK m_Lock; //
hardware lock
- PKINTERRUPT m_Interrupt; //
interrupt object
- KDPC m_IntDpcObject; //
dpc object for deferred isr processing
- PVOID VirtualBase; //
virtual base for memory manager
- PHYSICAL_ADDRESS PhysicalAddress; //
physical base for memory manager
- PULONG m_Base; //
EHCI operational port base registers
- PDMA_ADAPTER m_Adapter; //
dma adapter object
- ULONG m_MapRegisters; //
map registers count
- EHCI_CAPS m_Capabilities; //
EHCI caps
- USHORT m_VendorID; //
vendor id
- USHORT m_DeviceID; //
device id
- PQUEUE_HEAD AsyncQueueHead; //
async queue head terminator
- PEHCIQUEUE m_UsbQueue;
// usb request queue
- PDMAMEMORYMANAGER m_MemoryManager; //
memory manager
- HD_INIT_CALLBACK* m_SCECallBack; //
status change callback routine
- PVOID m_SCEContext; //
status change callback routine context
- BOOLEAN m_DoorBellRingInProgress; //
door bell ring in progress
- WORK_QUEUE_ITEM m_StatusChangeWorkItem; //
work item for status change callback
- volatile LONG m_StatusChangeWorkItemStatus; //
work item status
- ULONG m_SyncFramePhysAddr; //
periodic frame list physical address
- BUS_INTERFACE_STANDARD m_BusInterface; //
pci bus interface
- BOOLEAN m_PortResetInProgress[0xF]; //
stores reset in progress (vbox hack)
-
- // read register
- ULONG EHCI_READ_REGISTER_ULONG(ULONG Offset);
-
- // write register
- VOID EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value);
-};
-
-//=================================================================================================
-// COM
-//
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::QueryInterface(
- IN REFIID refiid,
- OUT PVOID* Output)
-{
- if (IsEqualGUIDAligned(refiid, IID_IUnknown))
- {
- *Output = PVOID(PUNKNOWN(this));
- PUNKNOWN(*Output)->AddRef();
- return STATUS_SUCCESS;
- }
-
- return STATUS_UNSUCCESSFUL;
-}
-
-LPCSTR
-STDMETHODCALLTYPE
-CUSBHardwareDevice::GetUSBType()
-{
- return "USBEHCI";
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::Initialize(
- PDRIVER_OBJECT DriverObject,
- PDEVICE_OBJECT FunctionalDeviceObject,
- PDEVICE_OBJECT PhysicalDeviceObject,
- PDEVICE_OBJECT LowerDeviceObject)
-{
- PCI_COMMON_CONFIG PciConfig;
- NTSTATUS Status;
- ULONG BytesRead;
-
- DPRINT("CUSBHardwareDevice::Initialize\n");
-
- //
- // Create DMAMemoryManager for use with QueueHeads and Transfer Descriptors.
- //
- Status = CreateDMAMemoryManager(&m_MemoryManager);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create DMAMemoryManager Object\n");
- return Status;
- }
-
- //
- // Create the UsbQueue class that will handle the Asynchronous and Periodic
Schedules
- //
- Status = CreateUSBQueue((PUSBQUEUE*)&m_UsbQueue);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create UsbQueue!\n");
- return Status;
- }
-
- //
- // store device objects
- //
- m_DriverObject = DriverObject;
- m_FunctionalDeviceObject = FunctionalDeviceObject;
- m_PhysicalDeviceObject = PhysicalDeviceObject;
- m_NextDeviceObject = LowerDeviceObject;
-
- //
- // initialize device lock
- //
- KeInitializeSpinLock(&m_Lock);
-
- //
- // initialize status change work item
- //
- ExInitializeWorkItem(&m_StatusChangeWorkItem, StatusChangeWorkItemRoutine,
PVOID(this));
-
- m_VendorID = 0;
- m_DeviceID = 0;
-
- Status = GetBusInterface(PhysicalDeviceObject, &m_BusInterface);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to get BusInterface!\n");
- return Status;
- }
-
- BytesRead = (*m_BusInterface.GetBusData)(m_BusInterface.Context,
- PCI_WHICHSPACE_CONFIG,
- &PciConfig,
- 0,
- PCI_COMMON_HDR_LENGTH);
-
- if (BytesRead != PCI_COMMON_HDR_LENGTH)
- {
- DPRINT1("Failed to get pci config information!\n");
- return STATUS_SUCCESS;
- }
-
- m_VendorID = PciConfig.VendorID;
- m_DeviceID = PciConfig.DeviceID;
-
- return STATUS_SUCCESS;
-}
-
-VOID
-STDMETHODCALLTYPE
-CUSBHardwareDevice::SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd)
-{
- PULONG Register;
- Register = (PULONG)UsbCmd;
- WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + EHCI_USBCMD), *Register);
-}
-
-VOID
-STDMETHODCALLTYPE
-CUSBHardwareDevice::GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd)
-{
- PULONG Register;
- Register = (PULONG)UsbCmd;
- *Register = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + EHCI_USBCMD));
-}
-
-ULONG
-CUSBHardwareDevice::EHCI_READ_REGISTER_ULONG(ULONG Offset)
-{
- return READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + Offset));
-}
-
-VOID
-CUSBHardwareDevice::EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value)
-{
- WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + Offset), Value);
-}
-
-VOID
-CUSBHardwareDevice::PrintCapabilities()
-{
- if (m_Capabilities.HCSParams.PortPowerControl)
- {
- DPRINT1("Controller EHCI has Port Power Control\n");
- }
-
- DPRINT1("Controller Port Routing Rules %lu\n",
m_Capabilities.HCSParams.PortRouteRules);
- DPRINT1("Number of Ports per Companion Controller %lu\n",
m_Capabilities.HCSParams.PortPerCHC);
- DPRINT1("Number of Companion Controller %lu\n",
m_Capabilities.HCSParams.CHCCount);
-
- if (m_Capabilities.HCSParams.PortIndicator)
- {
- DPRINT1("Controller has Port Indicators Support\n");
- }
-
- if (m_Capabilities.HCSParams.DbgPortNum)
- {
- DPRINT1("Controller has Debug Port Support At Port %x\n",
m_Capabilities.HCSParams.DbgPortNum);
- }
-
- if (m_Capabilities.HCCParams.EECPCapable)
- {
- DPRINT1("Controller has Extended Capabilities Support\n");
- }
-
- if (m_Capabilities.HCCParams.ParkMode)
- {
- DPRINT1("Controller supports Asynchronous Schedule Park\n");
- }
-
- if (m_Capabilities.HCCParams.VarFrameList)
- {
- DPRINT1("Controller supports Programmable Frame List Size\n");
- }
-
- if (m_Capabilities.HCCParams.CurAddrBits)
- {
- DPRINT1("Controller uses 64-Bit Addressing\n");
- }
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::PnpStart(
- PCM_RESOURCE_LIST RawResources,
- PCM_RESOURCE_LIST TranslatedResources)
-{
- ULONG Index, Count;
- PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
- DEVICE_DESCRIPTION DeviceDescription;
- PHYSICAL_ADDRESS AsyncPhysicalAddress;
- PVOID ResourceBase;
- NTSTATUS Status;
- UCHAR Value;
- UCHAR PortCount;
-
- DPRINT("CUSBHardwareDevice::PnpStart\n");
- for(Index = 0; Index < TranslatedResources->List[0].PartialResourceList.Count;
Index++)
- {
- //
- // get resource descriptor
- //
- ResourceDescriptor =
&TranslatedResources->List[0].PartialResourceList.PartialDescriptors[Index];
-
- switch(ResourceDescriptor->Type)
- {
- case CmResourceTypeInterrupt:
- {
- KeInitializeDpc(&m_IntDpcObject,
- EhciDeferredRoutine,
- this);
-
- Status = IoConnectInterrupt(&m_Interrupt,
- InterruptServiceRoutine,
- (PVOID)this,
- NULL,
- ResourceDescriptor->u.Interrupt.Vector,
-
(KIRQL)ResourceDescriptor->u.Interrupt.Level,
-
(KIRQL)ResourceDescriptor->u.Interrupt.Level,
-
(KINTERRUPT_MODE)(ResourceDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED),
- (ResourceDescriptor->ShareDisposition !=
CmResourceShareDeviceExclusive),
- ResourceDescriptor->u.Interrupt.Affinity,
- FALSE);
-
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to register interrupt
- //
- DPRINT1("IoConnect Interrupt failed with %x\n", Status);
- return Status;
- }
- break;
- }
- case CmResourceTypeMemory:
- {
- //
- // get resource base
- //
- ResourceBase = MmMapIoSpace(ResourceDescriptor->u.Memory.Start,
ResourceDescriptor->u.Memory.Length, MmNonCached);
- if (!ResourceBase)
- {
- //
- // failed to map registers
- //
- DPRINT1("MmMapIoSpace failed\n");
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // Get controllers capabilities
- //
- m_Capabilities.Length = READ_REGISTER_UCHAR((PUCHAR)ResourceBase +
EHCI_CAPLENGTH);
- m_Capabilities.HCIVersion =
READ_REGISTER_USHORT((PUSHORT)((ULONG_PTR)ResourceBase + EHCI_HCIVERSION));
- m_Capabilities.HCSParamsLong =
READ_REGISTER_ULONG((PULONG)((ULONG_PTR)ResourceBase + EHCI_HCSPARAMS));
- m_Capabilities.HCCParamsLong =
READ_REGISTER_ULONG((PULONG)((ULONG_PTR)ResourceBase + EHCI_HCCPARAMS));
-
- DPRINT1("Controller Capabilities Length 0x%x\n",
m_Capabilities.Length);
- DPRINT1("Controller EHCI Version 0x%x\n",
m_Capabilities.HCIVersion);
- DPRINT1("Controller EHCI Caps HCSParamsLong 0x%lx\n",
m_Capabilities.HCSParamsLong);
- DPRINT1("Controller EHCI Caps HCCParamsLong 0x%lx\n",
m_Capabilities.HCCParamsLong);
- DPRINT1("Controller has %lu Ports\n",
m_Capabilities.HCSParams.PortCount);
-
- //
- // print capabilities
- //
- PrintCapabilities();
-
- if (m_Capabilities.HCSParams.PortRouteRules)
- {
- Count = 0;
- PortCount = max(m_Capabilities.HCSParams.PortCount/2,
(m_Capabilities.HCSParams.PortCount+1)/2);
- do
- {
- //
- // each entry is a 4 bit field EHCI 2.2.5
- //
- Value = READ_REGISTER_UCHAR((PUCHAR)(ULONG_PTR)ResourceBase +
EHCI_HCSP_PORTROUTE + Count);
- m_Capabilities.PortRoute[Count*2] = (Value & 0xF0);
-
- if ((Count*2) + 1 < m_Capabilities.HCSParams.PortCount)
- m_Capabilities.PortRoute[(Count*2)+1] = (Value & 0x0F);
-
- Count++;
- } while(Count < PortCount);
- }
-
- //
- // Set m_Base to the address of Operational Register Space
- //
- m_Base = (PULONG)((ULONG_PTR)ResourceBase + m_Capabilities.Length);
- break;
- }
- }
- }
-
-
- //
- // zero device description
- //
- RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
-
- //
- // initialize device description
- //
- DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
- DeviceDescription.Master = TRUE;
- DeviceDescription.ScatterGather = TRUE;
- DeviceDescription.Dma32BitAddresses = TRUE;
- DeviceDescription.DmaWidth = Width32Bits;
- DeviceDescription.InterfaceType = PCIBus;
- DeviceDescription.MaximumLength = MAXULONG;
-
- //
- // get dma adapter
- //
- m_Adapter = IoGetDmaAdapter(m_PhysicalDeviceObject, &DeviceDescription,
&m_MapRegisters);
- if (!m_Adapter)
- {
- //
- // failed to get dma adapter
- //
- DPRINT1("Failed to acquire dma adapter\n");
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // Create Common Buffer
- //
- VirtualBase = m_Adapter->DmaOperations->AllocateCommonBuffer(m_Adapter,
- PAGE_SIZE * 4,
- &PhysicalAddress,
- FALSE);
- if (!VirtualBase)
- {
- DPRINT1("Failed to allocate a common buffer\n");
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // Initialize the DMAMemoryManager
- //
- Status = m_MemoryManager->Initialize(this, &m_Lock, PAGE_SIZE * 4,
VirtualBase, PhysicalAddress, 32);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to initialize the DMAMemoryManager\n");
- return Status;
- }
-
- //
- // Create a queuehead for the Async Register
- //
- m_MemoryManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&AsyncQueueHead,
&AsyncPhysicalAddress);
-
- AsyncQueueHead->PhysicalAddr = AsyncPhysicalAddress.LowPart;
- AsyncQueueHead->HorizontalLinkPointer = AsyncQueueHead->PhysicalAddr |
QH_TYPE_QH;
- AsyncQueueHead->EndPointCharacteristics.HeadOfReclamation = TRUE;
- AsyncQueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
- AsyncQueueHead->Token.Bits.Halted = TRUE;
-
- AsyncQueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x01;
- AsyncQueueHead->NextPointer = TERMINATE_POINTER;
- AsyncQueueHead->CurrentLinkPointer = TERMINATE_POINTER;
-
- InitializeListHead(&AsyncQueueHead->LinkedQueueHeads);
-
- //
- // Initialize the UsbQueue now that we have an AdapterObject.
- //
- Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter,
m_MemoryManager, &m_Lock);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to Initialize the UsbQueue\n");
- return Status;
- }
-
- //
- // Start the controller
- //
- DPRINT1("Starting Controller\n");
- Status = StartController();
-
- //
- // done
- //
- return Status;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::PnpStop(void)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::GetDeviceDetails(
- OUT OPTIONAL PUSHORT VendorId,
- OUT OPTIONAL PUSHORT DeviceId,
- OUT OPTIONAL PULONG NumberOfPorts,
- OUT OPTIONAL PULONG Speed)
-{
- if (VendorId)
- *VendorId = m_VendorID;
- if (DeviceId)
- *DeviceId = m_DeviceID;
- if (NumberOfPorts)
- *NumberOfPorts = m_Capabilities.HCSParams.PortCount;
- //FIXME: What to returned here?
- if (Speed)
- *Speed = 0x200;
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::GetDMA(
- OUT struct IDMAMemoryManager **OutDMAMemoryManager)
-{
- if (!m_MemoryManager)
- return STATUS_UNSUCCESSFUL;
- *OutDMAMemoryManager = m_MemoryManager;
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::GetUSBQueue(
- OUT struct IUSBQueue **OutUsbQueue)
-{
- if (!m_UsbQueue)
- return STATUS_UNSUCCESSFUL;
- *OutUsbQueue = m_UsbQueue;
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-CUSBHardwareDevice::StartController(void)
-{
- EHCI_USBCMD_CONTENT UsbCmd;
- ULONG UsbSts, FailSafe, ExtendedCapsSupport, Caps, Index;
- UCHAR Value;
- LARGE_INTEGER Timeout;
-
- //
- // are extended caps supported
- //
- ExtendedCapsSupport = (m_Capabilities.HCCParamsLong >> EHCI_ECP_SHIFT) &
EHCI_ECP_MASK;
- if (ExtendedCapsSupport)
- {
- DPRINT1("[EHCI] Extended Caps Support detected!\n");
-
- //
- // sanity check
- //
- ASSERT(ExtendedCapsSupport >= PCI_COMMON_HDR_LENGTH);
- m_BusInterface.GetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG,
&Caps, ExtendedCapsSupport, sizeof(ULONG));
-
- //
- // OS Handoff Synchronization support capability. EHCI 5.1
- //
- if ((Caps & EHCI_LEGSUP_CAPID_MASK) == EHCI_LEGSUP_CAPID)
- {
- //
- // is it bios owned
- //
- if ((Caps & EHCI_LEGSUP_BIOSOWNED))
- {
- DPRINT1("[EHCI] Controller is BIOS owned, acquiring
control\n");
-
- //
- // acquire ownership
- //
- Value = 1;
- m_BusInterface.SetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG,
&Value, ExtendedCapsSupport+3, sizeof(UCHAR));
-
- for(Index = 0; Index < 20; Index++)
- {
- //
- // get status
- //
- m_BusInterface.GetBusData(m_BusInterface.Context,
PCI_WHICHSPACE_CONFIG, &Caps, ExtendedCapsSupport, sizeof(ULONG));
- if ((Caps & EHCI_LEGSUP_BIOSOWNED))
- {
- //
- // lets wait a bit
- //
- Timeout.QuadPart = 50;
- DPRINT1("Waiting %lu milliseconds for port reset\n",
Timeout.LowPart);
-
- //
- // convert to 100 ns units (absolute)
- //
- Timeout.QuadPart *= -10000;
-
- //
- // perform the wait
- //
- KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
- }
- }
- if ((Caps & EHCI_LEGSUP_BIOSOWNED))
- {
- //
- // failed to acquire ownership
- //
- DPRINT1("[EHCI] failed to acquire ownership\n");
- }
- else if ((Caps & EHCI_LEGSUP_OSOWNED))
- {
- //
- // HC OS Owned Semaphore EHCI 2.1.7
- //
- DPRINT1("[EHCI] acquired ownership\n");
- }
-#if 0
- //
- // explicitly clear the bios owned flag 2.1.7
- //
- Value = 0;
- m_BusInterface.SetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG,
&Value, ExtendedCapsSupport+2, sizeof(UCHAR));
-
- //
- // clear SMI interrupt EHCI 2.1.8
- //
- Caps = 4;
- m_BusInterface.SetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG,
&Caps, ExtendedCapsSupport+4, sizeof(ULONG));
-#endif
- }
- }
- }
-
- //
- // get command register
- //
- GetCommandRegister(&UsbCmd);
-
- //
- // disable running schedules
- //
- UsbCmd.PeriodicEnable = FALSE;
- UsbCmd.AsyncEnable = FALSE;
- SetCommandRegister(&UsbCmd);
-
- //
- // Wait for execution to start
- //
- for (FailSafe = 100; FailSafe > 1; FailSafe--)
- {
- KeStallExecutionProcessor(100);
- UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
-
- if (!(UsbSts & EHCI_STS_PSS) && (UsbSts & EHCI_STS_ASS))
- {
- break;
- }
- }
-
- if ((UsbSts & (EHCI_STS_PSS | EHCI_STS_ASS)))
- {
- DPRINT1("Failed to stop running schedules %x\n", UsbSts);
- //ASSERT(FALSE);
- }
-
-
- //
- // Stop the controller if its running
- //
- UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
- if (!(UsbSts & EHCI_STS_HALT))
- {
- DPRINT1("Stopping Controller %x\n", UsbSts);
- StopController();
- }
-
- //
- // Reset the controller
- //
- ResetController();
-
- //
- // check caps
- //
- if (m_Capabilities.HCCParams.CurAddrBits)
- {
- //
- // disable 64-bit addressing
- //
- EHCI_WRITE_REGISTER_ULONG(EHCI_CTRLDSSEGMENT, 0x0);
- }
-
- //
- // Enable Interrupts and start execution
- //
- ULONG Mask = EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC |
EHCI_USBINTR_HSERR | EHCI_USBINTR_PC;
- EHCI_WRITE_REGISTER_ULONG(EHCI_USBINTR, Mask);
-
- KeStallExecutionProcessor(10);
-
- ULONG Status = EHCI_READ_REGISTER_ULONG(EHCI_USBINTR);
-
- DPRINT1("Interrupt Mask %x\n", Status);
- ASSERT((Status & Mask) == Mask);
-
- //
- // Assign the SyncList Register
- //
- EHCI_WRITE_REGISTER_ULONG(EHCI_PERIODICLISTBASE, m_SyncFramePhysAddr);
-
- //
- // Set Schedules to Enable and Interrupt Threshold to 1ms.
- //
- RtlZeroMemory(&UsbCmd, sizeof(EHCI_USBCMD_CONTENT));
-
- UsbCmd.PeriodicEnable = TRUE;
- UsbCmd.IntThreshold = 0x8; //1ms
- UsbCmd.Run = TRUE;
- UsbCmd.FrameListSize = 0x0; //1024
-
- if (m_Capabilities.HCCParams.ParkMode)
- {
- //
- // enable async park mode
- //
- UsbCmd.AsyncParkEnable = TRUE;
- UsbCmd.AsyncParkCount = 3;
- }
-
- SetCommandRegister(&UsbCmd);
-
-
- //
- // Wait for execution to start
- //
- for (FailSafe = 100; FailSafe > 1; FailSafe--)
- {
- KeStallExecutionProcessor(100);
- UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
-
- if (!(UsbSts & EHCI_STS_HALT) && (UsbSts & EHCI_STS_PSS))
- {
- break;
- }
- }
-
- if (UsbSts & EHCI_STS_HALT)
- {
- DPRINT1("Could not start execution on the controller\n");
- //ASSERT(FALSE);
- return STATUS_UNSUCCESSFUL;
- }
-
- if (!(UsbSts & EHCI_STS_PSS))
- {
- DPRINT1("Could not enable periodic scheduling\n");
- //ASSERT(FALSE);
- return STATUS_UNSUCCESSFUL;
- }
-
- //
- // Assign the AsyncList Register
- //
- EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, AsyncQueueHead->PhysicalAddr);
-
- //
- // get command register
- //
- GetCommandRegister(&UsbCmd);
-
- //
- // preserve bits
- //
- UsbCmd.AsyncEnable = TRUE;
-
- //
- // enable async
- //
- SetCommandRegister(&UsbCmd);
-
- //
- // Wait for execution to start
- //
- for (FailSafe = 100; FailSafe > 1; FailSafe--)
- {
- KeStallExecutionProcessor(100);
- UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
-
- if ((UsbSts & EHCI_STS_ASS))
- {
- break;
- }
- }
-
- if (!(UsbSts & EHCI_STS_ASS))
- {
- DPRINT1("Failed to enable async schedule UsbSts %x\n", UsbSts);
- //ASSERT(FALSE);
- return STATUS_UNSUCCESSFUL;
- }
-
- DPRINT1("UsbSts %x\n", UsbSts);
- GetCommandRegister(&UsbCmd);
-
- DPRINT1("UsbCmd.PeriodicEnable %x\n", UsbCmd.PeriodicEnable);
- DPRINT1("UsbCmd.AsyncEnable %x\n", UsbCmd.AsyncEnable);
- DPRINT1("UsbCmd.IntThreshold %x\n", UsbCmd.IntThreshold);
- DPRINT1("UsbCmd.Run %x\n", UsbCmd.Run);
- DPRINT1("UsbCmd.FrameListSize %x\n", UsbCmd.FrameListSize);
-
- //
- // Set port routing to EHCI controller
- //
- EHCI_WRITE_REGISTER_ULONG(EHCI_CONFIGFLAG, 1);
-
- DPRINT1("EHCI Started!\n");
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-CUSBHardwareDevice::StopController(void)
-{
- EHCI_USBCMD_CONTENT UsbCmd;
- ULONG UsbSts, FailSafe;
-
- //
- // Disable Interrupts and stop execution
- //
- EHCI_WRITE_REGISTER_ULONG (EHCI_USBINTR, 0);
-
- GetCommandRegister(&UsbCmd);
- UsbCmd.Run = FALSE;
- SetCommandRegister(&UsbCmd);
-
- for (FailSafe = 100; FailSafe > 1; FailSafe--)
- {
- KeStallExecutionProcessor(10);
- UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
- if (UsbSts & EHCI_STS_HALT)
- {
- break;
- }
- }
-
- if (!(UsbSts & EHCI_STS_HALT))
- {
- DPRINT1("EHCI ERROR: Controller is not responding to Stop
request!\n");
- return STATUS_UNSUCCESSFUL;
- }
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-CUSBHardwareDevice::ResetController(void)
-{
- EHCI_USBCMD_CONTENT UsbCmd;
- ULONG FailSafe;
-
- GetCommandRegister(&UsbCmd);
- UsbCmd.HCReset = TRUE;
- SetCommandRegister(&UsbCmd);
-
- for (FailSafe = 100; FailSafe > 1; FailSafe--)
- {
- KeStallExecutionProcessor(100);
- GetCommandRegister(&UsbCmd);
- if (!UsbCmd.HCReset)
- break;
- }
-
- if (UsbCmd.HCReset)
- {
- DPRINT1("EHCI ERROR: Controller is not responding to reset
request!\n");
- return STATUS_UNSUCCESSFUL;
- }
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::ResetPort(
- IN ULONG PortIndex)
-{
- ULONG PortStatus;
- LARGE_INTEGER Timeout;
-
- if (PortIndex > m_Capabilities.HCSParams.PortCount)
- return STATUS_UNSUCCESSFUL;
-
- PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
-
- ASSERT(!EHCI_IS_LOW_SPEED(PortStatus));
- ASSERT(PortStatus & EHCI_PRT_CONNECTED);
-
- //
- // Reset and clean enable
- //
- PortStatus |= EHCI_PRT_RESET;
- PortStatus &= EHCI_PORTSC_DATAMASK;
- EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), PortStatus);
-
- //
- // delay is 50 ms for port reset as per USB 2.0 spec
- //
- Timeout.QuadPart = 50;
- DPRINT1("Waiting %lu milliseconds for port reset\n", Timeout.LowPart);
-
- //
- // convert to 100 ns units (absolute)
- //
- Timeout.QuadPart *= -10000;
-
- //
- // perform the wait
- //
- KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::GetPortStatus(
- ULONG PortId,
- OUT USHORT *PortStatus,
- OUT USHORT *PortChange)
-{
- ULONG Value;
- USHORT Status = 0, Change = 0;
-
- if (PortId > m_Capabilities.HCSParams.PortCount)
- return STATUS_UNSUCCESSFUL;
-
- //
- // Get the value of the Port Status and Control Register
- //
- Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
-
- //
- // If the PowerPortControl is 0 then host controller does not have power control
switches
- if (!m_Capabilities.HCSParams.PortPowerControl)
- {
- Status |= USB_PORT_STATUS_POWER;
- }
- else
- {
- // Check the value of PortPower
- if (Value & EHCI_PRT_POWER)
- {
- Status |= USB_PORT_STATUS_POWER;
- }
- }
-
- // Get Connected Status
- if (Value & EHCI_PRT_CONNECTED)
- {
- Status |= USB_PORT_STATUS_CONNECT;
-
- // EHCI only supports high speed
- Status |= USB_PORT_STATUS_HIGH_SPEED;
- }
-
- // Get Enabled Status
- if (Value & EHCI_PRT_ENABLED)
- Status |= USB_PORT_STATUS_ENABLE;
-
- // Is it suspended?
- if (Value & EHCI_PRT_SUSPEND)
- Status |= USB_PORT_STATUS_SUSPEND;
-
- // a overcurrent is active?
- if (Value & EHCI_PRT_OVERCURRENTACTIVE)
- Status |= USB_PORT_STATUS_OVER_CURRENT;
-
- // In a reset state?
- if ((Value & EHCI_PRT_RESET) || m_PortResetInProgress[PortId])
- {
- Status |= USB_PORT_STATUS_RESET;
- Change |= USB_PORT_STATUS_RESET;
- }
-
- // This indicates a connect or disconnect
- if (Value & EHCI_PRT_CONNECTSTATUSCHANGE)
- Change |= USB_PORT_STATUS_CONNECT;
-
- // This is set to indicate a critical port error
- if (Value & EHCI_PRT_ENABLEDSTATUSCHANGE)
- Change |= USB_PORT_STATUS_ENABLE;
-
- *PortStatus = Status;
- *PortChange = Change;
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::ClearPortStatus(
- ULONG PortId,
- ULONG Status)
-{
- ULONG Value;
- LARGE_INTEGER Timeout;
-
- DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n",
PortId, Status);
-
- if (PortId > m_Capabilities.HCSParams.PortCount)
- return STATUS_UNSUCCESSFUL;
-
- if (Status == C_PORT_RESET)
- {
- // reset done
- m_PortResetInProgress[PortId] = FALSE;
-
- // Clear reset
- Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
- Value &= (EHCI_PORTSC_DATAMASK | EHCI_PRT_ENABLED);
- Value &= ~EHCI_PRT_RESET;
- EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
-
- //
- // wait for reset bit to clear
- //
- do
- {
- Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
-
- if (!(Value & EHCI_PRT_RESET))
- break;
-
- KeStallExecutionProcessor(20);
- } while (TRUE);
-
- //
- // delay is 50 ms
- //
- Timeout.QuadPart = 50;
- DPRINT1("Waiting %lu milliseconds for port to recover after reset\n",
Timeout.LowPart);
-
- //
- // convert to 100 ns units (absolute)
- //
- Timeout.QuadPart *= -10000;
-
- //
- // perform the wait
- //
- KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
-
- //
- // check the port status after reset
- //
- Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
- if (!(Value & EHCI_PRT_CONNECTED))
- {
- DPRINT1("No device is here after reset. Bad
controller/device?\n");
- return STATUS_UNSUCCESSFUL;
- }
- else if (EHCI_IS_LOW_SPEED(Value))
- {
- DPRINT1("Low speed device connected. Releasing ownership\n");
- EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value |
EHCI_PRT_RELEASEOWNERSHIP);
- return STATUS_DEVICE_NOT_CONNECTED;
- }
- else if (!(Value & EHCI_PRT_ENABLED))
- {
- DPRINT1("Full speed device connected. Releasing ownership\n");
- EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value |
EHCI_PRT_RELEASEOWNERSHIP);
- return STATUS_DEVICE_NOT_CONNECTED;
- }
- else
- {
- DPRINT1("High speed device connected\n");
- return STATUS_SUCCESS;
- }
- }
- else if (Status == C_PORT_CONNECTION)
- {
- //
- // reset status change bits
- //
- Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
- EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
-
- if (Value & EHCI_PRT_CONNECTED)
- {
- //
- // delay is 100 ms
- //
- Timeout.QuadPart = 100;
- DPRINT1("Waiting %lu milliseconds for port to stabilize after
connection\n", Timeout.LowPart);
-
- //
- // convert to 100 ns units (absolute)
- //
- Timeout.QuadPart *= -10000;
-
- //
- // perform the wait
- //
- KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBHardwareDevice::SetPortFeature(
- ULONG PortId,
- ULONG Feature)
-{
- DPRINT("CUSBHardwareDevice::SetPortFeature\n");
-
- if (PortId > m_Capabilities.HCSParams.PortCount)
- return STATUS_UNSUCCESSFUL;
-
- if (Feature == PORT_ENABLE)
- {
- //
- // FIXME: EHCI Ports can only be disabled via reset
- //
- DPRINT1("PORT_ENABLE not supported for EHCI\n");
- }
-
- if (Feature == PORT_RESET)
- {
- //
- // call the helper
- //
- ResetPort(PortId);
-
- // reset in progress
- m_PortResetInProgress[PortId] = TRUE;
-
- //
- // is there a status change callback
- //
- if (m_SCECallBack != NULL)
- {
- //
- // issue callback
- //
- m_SCECallBack(m_SCEContext);
- }
- }
-
- if (Feature == PORT_POWER)
- {
- if (m_Capabilities.HCSParams.PortPowerControl)
- {
- ULONG Value;
- LARGE_INTEGER Timeout;
-
- //
- // enable port power
- //
- Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)) |
EHCI_PRT_POWER;
- EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
-
- //
- // delay is 20 ms
- //
- Timeout.QuadPart = 20;
- DPRINT1("Waiting %lu milliseconds for port power up\n",
Timeout.LowPart);
-
- //
- // convert to 100 ns units (absolute)
- //
- Timeout.QuadPart *= -10000;
-
- //
- // perform the wait
- //
- KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
- }
- }
- return STATUS_SUCCESS;
-}
-
-VOID
-STDMETHODCALLTYPE
-CUSBHardwareDevice::SetAsyncListRegister(
- ULONG PhysicalAddress)
-{
- EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, PhysicalAddress);
-}
-
-VOID
-STDMETHODCALLTYPE
-CUSBHardwareDevice::SetPeriodicListRegister(
- ULONG PhysicalAddress)
-{
- //
- // store physical address
- //
- m_SyncFramePhysAddr = PhysicalAddress;
-}
-
-struct _QUEUE_HEAD *
-STDMETHODCALLTYPE
-CUSBHardwareDevice::GetAsyncListQueueHead()
-{
- return AsyncQueueHead;
-}
-
-ULONG
-STDMETHODCALLTYPE
-CUSBHardwareDevice::GetPeriodicListRegister()
-{
- UNIMPLEMENTED;
- return NULL;
-}
-
-VOID
-STDMETHODCALLTYPE
-CUSBHardwareDevice::SetStatusChangeEndpointCallBack(
- PVOID CallBack,
- PVOID Context)
-{
- m_SCECallBack = (HD_INIT_CALLBACK*)CallBack;
- m_SCEContext = Context;
-}
-
-BOOLEAN
-NTAPI
-InterruptServiceRoutine(
- IN PKINTERRUPT Interrupt,
- IN PVOID ServiceContext)
-{
- CUSBHardwareDevice *This;
- ULONG CStatus;
-
- This = (CUSBHardwareDevice*) ServiceContext;
- CStatus = This->EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
-
- CStatus &= (EHCI_ERROR_INT | EHCI_STS_INT | EHCI_STS_IAA | EHCI_STS_PCD |
EHCI_STS_FLR);
- DPRINT("InterruptServiceRoutine CStatus %lx\n", CStatus);
-
- //
- // Check that it belongs to EHCI
- //
- if (!CStatus)
- return FALSE;
-
- //
- // Clear the Status
- //
- This->EHCI_WRITE_REGISTER_ULONG(EHCI_USBSTS, CStatus);
-
- if (CStatus & EHCI_STS_FATAL)
- {
- This->StopController();
- DPRINT1("EHCI: Host System Error!\n");
- return TRUE;
- }
-
- if (CStatus & EHCI_ERROR_INT)
- {
- DPRINT1("EHCI Status = 0x%x\n", CStatus);
- }
-
- if (CStatus & EHCI_STS_HALT)
- {
- DPRINT1("Host Error Unexpected Halt\n");
- // FIXME: Reset controller\n");
- return TRUE;
- }
-
- KeInsertQueueDpc(&This->m_IntDpcObject, This, UlongToPtr(CStatus));
- return TRUE;
-}
-
-VOID NTAPI
-EhciDeferredRoutine(
- IN PKDPC Dpc,
- IN PVOID DeferredContext,
- IN PVOID SystemArgument1,
- IN PVOID SystemArgument2)
-{
- CUSBHardwareDevice *This;
- ULONG CStatus, PortStatus, PortCount, i, ShouldRingDoorBell, QueueSCEWorkItem;
- NTSTATUS Status = STATUS_SUCCESS;
- EHCI_USBCMD_CONTENT UsbCmd;
-
- This = (CUSBHardwareDevice*) SystemArgument1;
- CStatus = PtrToUlong(SystemArgument2);
-
- DPRINT("EhciDeferredRoutine CStatus %lx\n", CStatus);
-
- //
- // check for completion of async schedule
- //
- if (CStatus & (EHCI_STS_RECL| EHCI_STS_INT | EHCI_ERROR_INT))
- {
- //
- // check if there is a door bell ring in progress
- //
- if (This->m_DoorBellRingInProgress == FALSE)
- {
- if (CStatus & EHCI_ERROR_INT)
- {
- //
- // controller reported error
- //
- DPRINT1("CStatus %lx\n", CStatus);
- //ASSERT(FALSE);
- }
-
- //
- // inform IUSBQueue of a completed queue head
- //
- This->m_UsbQueue->InterruptCallback(Status, &ShouldRingDoorBell);
-
- //
- // was a queue head completed?
- //
- if (ShouldRingDoorBell)
- {
- //
- // set door ring bell in progress status flag
- //
- This->m_DoorBellRingInProgress = TRUE;
-
- //
- // get command register
- //
- This->GetCommandRegister(&UsbCmd);
-
- //
- // set door rang bell bit
- //
- UsbCmd.DoorBell = TRUE;
-
- //
- // update command status
- //
- This->SetCommandRegister(&UsbCmd);
- }
- }
- }
-
- //
- // check if the controller has acknowledged the door bell
- //
- if (CStatus & EHCI_STS_IAA)
- {
- //
- // controller has acknowledged, assert we rang the bell
- //
- PC_ASSERT(This->m_DoorBellRingInProgress == TRUE);
-
- //
- // now notify IUSBQueue that it can free completed requests
- //
- This->m_UsbQueue->CompleteAsyncRequests();
-
- //
- // door ring bell completed
- //
- This->m_DoorBellRingInProgress = FALSE;
- }
-
- This->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
- if (CStatus & EHCI_STS_PCD)
- {
- QueueSCEWorkItem = FALSE;
- for (i = 0; i < PortCount; i++)
- {
- PortStatus = This->EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * i));
-
- //
- // Device connected or removed
- //
- if (PortStatus & EHCI_PRT_CONNECTSTATUSCHANGE)
- {
- if (PortStatus & EHCI_PRT_CONNECTED)
- {
- DPRINT1("Device connected on port %lu\n", i);
-
- if (This->m_Capabilities.HCSParams.CHCCount)
- {
- if (PortStatus & EHCI_PRT_ENABLED)
- {
- DPRINT1("Misbehaving controller. Port should be disabled
at this point\n");
- }
-
- if (EHCI_IS_LOW_SPEED(PortStatus))
- {
- DPRINT1("Low speed device connected. Releasing
ownership\n");
- This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i),
PortStatus | EHCI_PRT_RELEASEOWNERSHIP);
- continue;
- }
- }
-
- //
- // work to do
- //
- QueueSCEWorkItem = TRUE;
- }
- else
- {
- DPRINT1("Device disconnected on port %lu\n", i);
-
- //
- // work to do
- //
- QueueSCEWorkItem = TRUE;
- }
- }
- }
-
- //
- // is there a status change callback and a high speed device connected /
disconnected
- //
- if (QueueSCEWorkItem && This->m_SCECallBack != NULL)
- {
- if (InterlockedCompareExchange(&This->m_StatusChangeWorkItemStatus, 1,
0) == 0)
- {
- //
- // queue work item for processing
- //
- ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue);
- }
- }
- }
- return;
-}
-
-VOID
-NTAPI
-StatusChangeWorkItemRoutine(
- PVOID Context)
-{
- //
- // cast to hardware object
- //
- CUSBHardwareDevice * This = (CUSBHardwareDevice*)Context;
-
- //
- // is there a callback
- //
- if (This->m_SCECallBack)
- {
- //
- // issue callback
- //
- This->m_SCECallBack(This->m_SCEContext);
- }
-
- //
- // reset active status
- //
- InterlockedDecrement(&This->m_StatusChangeWorkItemStatus);
-}
-
-NTSTATUS
-NTAPI
-CreateUSBHardware(
- PUSBHARDWAREDEVICE *OutHardware)
-{
- PUSBHARDWAREDEVICE This;
-
- This = new(NonPagedPool, TAG_USBEHCI) CUSBHardwareDevice(0);
-
- if (!This)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- This->AddRef();
-
- // return result
- *OutHardware = (PUSBHARDWAREDEVICE)This;
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/usb/usbehci/hardware.h b/drivers/usb/usbehci/hardware.h
deleted file mode 100644
index b0ea4811be5..00000000000
--- a/drivers/usb/usbehci/hardware.h
+++ /dev/null
@@ -1,325 +0,0 @@
-#pragma once
-
-//
-// Host Controller Capability Registers
-//
-#define EHCI_CAPLENGTH 0x00
-#define EHCI_HCIVERSION 0x02
-#define EHCI_HCSPARAMS 0x04
-#define EHCI_HCCPARAMS 0x08
-#define EHCI_HCSP_PORTROUTE 0x0c
-
-
-//
-// Extended Capabilities
-//
-#define EHCI_ECP_SHIFT 8
-#define EHCI_ECP_MASK 0xff
-#define EHCI_LEGSUP_CAPID_MASK 0xff
-#define EHCI_LEGSUP_CAPID 0x01
-#define EHCI_LEGSUP_OSOWNED (1 << 24)
-#define EHCI_LEGSUP_BIOSOWNED (1 << 16)
-
-
-//
-// EHCI Operational Registers
-//
-#define EHCI_USBCMD 0x00
-#define EHCI_USBSTS 0x04
-#define EHCI_USBINTR 0x08
-#define EHCI_FRINDEX 0x0C
-#define EHCI_CTRLDSSEGMENT 0x10
-#define EHCI_PERIODICLISTBASE 0x14
-#define EHCI_ASYNCLISTBASE 0x18
-#define EHCI_CONFIGFLAG 0x40
-#define EHCI_PORTSC 0x44
-
-//
-// Interrupt Register Flags
-//
-#define EHCI_USBINTR_INTE 0x01
-#define EHCI_USBINTR_ERR 0x02
-#define EHCI_USBINTR_PC 0x04
-#define EHCI_USBINTR_FLROVR 0x08
-#define EHCI_USBINTR_HSERR 0x10
-#define EHCI_USBINTR_ASYNC 0x20
-// Bits 6:31 Reserved
-
-//
-// Status Register Flags
-//
-#define EHCI_STS_INT 0x01
-#define EHCI_STS_ERR 0x02
-#define EHCI_STS_PCD 0x04
-#define EHCI_STS_FLR 0x08
-#define EHCI_STS_FATAL 0x10
-#define EHCI_STS_IAA 0x20
-// Bits 11:6 Reserved
-#define EHCI_STS_HALT 0x1000
-#define EHCI_STS_RECL 0x2000
-#define EHCI_STS_PSS 0x4000
-#define EHCI_STS_ASS 0x8000
-#define EHCI_ERROR_INT (EHCI_STS_FATAL | EHCI_STS_ERR)
-
-//
-// Port Register Flags
-//
-#define EHCI_PRT_CONNECTED 0x01
-#define EHCI_PRT_CONNECTSTATUSCHANGE 0x02
-#define EHCI_PRT_ENABLED 0x04
-#define EHCI_PRT_ENABLEDSTATUSCHANGE 0x08
-#define EHCI_PRT_OVERCURRENTACTIVE 0x10
-#define EHCI_PRT_OVERCURRENTCHANGE 0x20
-#define EHCI_PRT_FORCERESUME 0x40
-#define EHCI_PRT_SUSPEND 0x80
-#define EHCI_PRT_RESET 0x100
-#define EHCI_PRT_LINESTATUSA 0x400
-#define EHCI_PRT_LINESTATUSB 0x800
-#define EHCI_PRT_POWER 0x1000
-#define EHCI_PRT_RELEASEOWNERSHIP 0x2000
-
-#define EHCI_PORTSC_DATAMASK 0xffffffd1
-
-#define EHCI_IS_LOW_SPEED(x) (((x) & EHCI_PRT_LINESTATUSA) && !((x) &
EHCI_PRT_LINESTATUSB))
-//
-// Terminate Pointer used for QueueHeads and Element Transfer Descriptors to mark
Pointers as the end
-//
-#define TERMINATE_POINTER 0x01
-
-//
-// QUEUE ELEMENT TRANSFER DESCRIPTOR, defines and structs
-//
-
-//
-// Token Flags
-//
-#define PID_CODE_OUT_TOKEN 0x00
-#define PID_CODE_IN_TOKEN 0x01
-#define PID_CODE_SETUP_TOKEN 0x02
-
-#define DO_START_SPLIT 0x00
-#define DO_COMPLETE_SPLIT 0x01
-
-#define PING_STATE_DO_OUT 0x00
-#define PING_STATE_DO_PING 0x01
-
-typedef struct _PERIODICFRAMELIST
-{
- PULONG VirtualAddr;
- PHYSICAL_ADDRESS PhysicalAddr;
- ULONG Size;
-} PERIODICFRAMELIST, *PPERIODICFRAMELIST;
-
-//
-// QUEUE ELEMENT TRANSFER DESCRIPTOR TOKEN
-//
-typedef struct _QETD_TOKEN_BITS
-{
- ULONG PingState:1;
- ULONG SplitTransactionState:1;
- ULONG MissedMicroFrame:1;
- ULONG TransactionError:1;
- ULONG BabbleDetected:1;
- ULONG DataBufferError:1;
- ULONG Halted:1;
- ULONG Active:1;
- ULONG PIDCode:2;
- ULONG ErrorCounter:2;
- ULONG CurrentPage:3;
- ULONG InterruptOnComplete:1;
- ULONG TotalBytesToTransfer:15;
- ULONG DataToggle:1;
-} QETD_TOKEN_BITS, *PQETD_TOKEN_BITS;
-
-//
-// QUEUE ELEMENT TRANSFER DESCRIPTOR
-//
-typedef struct _QUEUE_TRANSFER_DESCRIPTOR
-{
- //Hardware
- ULONG NextPointer;
- ULONG AlternateNextPointer;
- union
- {
- QETD_TOKEN_BITS Bits;
- ULONG DWord;
- } Token;
- ULONG BufferPointer[5];
- ULONG ExtendedBufferPointer[5];
-
- //Software
- ULONG PhysicalAddr;
- LIST_ENTRY DescriptorEntry;
- ULONG TotalBytesToTransfer;
-} QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
-
-C_ASSERT(FIELD_OFFSET(QUEUE_TRANSFER_DESCRIPTOR, PhysicalAddr) == 0x34);
-
-//
-// EndPointSpeeds Flags and END_POINT_CHARACTERISTICS
-//
-#define QH_ENDPOINT_FULLSPEED 0x00
-#define QH_ENDPOINT_LOWSPEED 0x01
-#define QH_ENDPOINT_HIGHSPEED 0x02
-typedef struct _END_POINT_CHARACTERISTICS
-{
- ULONG DeviceAddress:7;
- ULONG InactiveOnNextTransaction:1;
- ULONG EndPointNumber:4;
- ULONG EndPointSpeed:2;
- ULONG QEDTDataToggleControl:1;
- ULONG HeadOfReclamation:1;
- ULONG MaximumPacketLength:11;
- ULONG ControlEndPointFlag:1;
- ULONG NakCountReload:4;
-} END_POINT_CHARACTERISTICS, *PEND_POINT_CHARACTERISTICS;
-
-//
-// Capabilities
-//
-typedef struct _END_POINT_CAPABILITIES
-{
- ULONG InterruptScheduleMask:8;
- ULONG SplitCompletionMask:8;
- ULONG HubAddr:7;
- ULONG PortNumber:7;
- ULONG NumberOfTransactionPerFrame:2;
-} END_POINT_CAPABILITIES, *PEND_POINT_CAPABILITIES;
-
-//
-// QUEUE HEAD Flags and Struct
-//
-#define QH_TYPE_IDT 0x00
-#define QH_TYPE_QH 0x02
-#define QH_TYPE_SITD 0x04
-#define QH_TYPE_FSTN 0x06
-
-typedef struct _QUEUE_HEAD
-{
- //Hardware
- ULONG HorizontalLinkPointer;
- END_POINT_CHARACTERISTICS EndPointCharacteristics;
- END_POINT_CAPABILITIES EndPointCapabilities;
- // TERMINATE_POINTER not valid for this member
- ULONG CurrentLinkPointer;
- // TERMINATE_POINTER valid
- ULONG NextPointer;
- // TERMINATE_POINTER valid, bits 1:4 is NAK_COUNTERd
- ULONG AlternateNextPointer;
- // Only DataToggle, InterruptOnComplete, ErrorCounter, PingState valid
- union
- {
- QETD_TOKEN_BITS Bits;
- ULONG DWord;
- } Token;
- ULONG BufferPointer[5];
- ULONG ExtendedBufferPointer[5];
-
- //Software
- ULONG PhysicalAddr;
- LIST_ENTRY LinkedQueueHeads;
- LIST_ENTRY TransferDescriptorListHead;
- PVOID NextQueueHead;
- PVOID Request;
-} QUEUE_HEAD, *PQUEUE_HEAD;
-
-C_ASSERT(sizeof(END_POINT_CHARACTERISTICS) == 4);
-C_ASSERT(sizeof(END_POINT_CAPABILITIES) == 4);
-
-C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, HorizontalLinkPointer) == 0x00);
-C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, EndPointCharacteristics) == 0x04);
-C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, EndPointCapabilities) == 0x08);
-C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, CurrentLinkPointer) == 0xC);
-C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, NextPointer) == 0x10);
-C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, AlternateNextPointer) == 0x14);
-C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, Token) == 0x18);
-C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, BufferPointer) == 0x1C);
-C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, PhysicalAddr) == 0x44);
-
-
-//
-// Command register content
-//
-typedef struct _EHCI_USBCMD_CONTENT
-{
- ULONG Run : 1;
- ULONG HCReset : 1;
- ULONG FrameListSize : 2;
- ULONG PeriodicEnable : 1;
- ULONG AsyncEnable : 1;
- ULONG DoorBell : 1;
- ULONG LightReset : 1;
- ULONG AsyncParkCount : 2;
- ULONG Reserved : 1;
- ULONG AsyncParkEnable : 1;
- ULONG Reserved1 : 4;
- ULONG IntThreshold : 8;
- ULONG Reserved2 : 8;
-} EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_CONTENT;
-
-typedef struct _EHCI_HCS_CONTENT
-{
- ULONG PortCount : 4;
- ULONG PortPowerControl: 1;
- ULONG Reserved : 2;
- ULONG PortRouteRules : 1;
- ULONG PortPerCHC : 4;
- ULONG CHCCount : 4;
- ULONG PortIndicator : 1;
- ULONG Reserved2 : 3;
- ULONG DbgPortNum : 4;
- ULONG Reserved3 : 8;
-
-} EHCI_HCS_CONTENT, *PEHCI_HCS_CONTENT;
-
-typedef struct _EHCI_HCC_CONTENT
-{
- ULONG CurAddrBits : 1;
- ULONG VarFrameList : 1;
- ULONG ParkMode : 1;
- ULONG Reserved : 1;
- ULONG IsoSchedThreshold : 4;
- ULONG EECPCapable : 8;
- ULONG Reserved2 : 16;
-
-} EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT;
-
-typedef struct _EHCI_CAPS {
- UCHAR Length;
- UCHAR Reserved;
- USHORT HCIVersion;
- union
- {
- EHCI_HCS_CONTENT HCSParams;
- ULONG HCSParamsLong;
- };
- union
- {
- EHCI_HCC_CONTENT HCCParams;
- ULONG HCCParamsLong;
- };
- UCHAR PortRoute [15];
-} EHCI_CAPS, *PEHCI_CAPS;
-
-typedef struct
-{
- ULONG PortStatus;
- ULONG PortChange;
-}EHCI_PORT_STATUS;
-
-#define EHCI_INTERRUPT_ENTRIES_COUNT (10 + 1)
-#define EHCI_VFRAMELIST_ENTRIES_COUNT 128
-#define EHCI_FRAMELIST_ENTRIES_COUNT 1024
-
-#define MAX_AVAILABLE_BANDWIDTH 125 // Microseconds
-
-#define EHCI_QH_CAPS_MULT_SHIFT 30 // Transactions per Micro-Frame
-#define EHCI_QH_CAPS_MULT_MASK 0x03
-#define EHCI_QH_CAPS_PORT_SHIFT 23 // Hub Port (Split-Transaction)
-#define EHCI_QH_CAPS_PORT_MASK 0x7f
-#define EHCI_QH_CAPS_HUB_SHIFT 16 // Hub Address (Split-Transaction)
-#define EHCI_QH_CAPS_HUB_MASK 0x7f
-#define EHCI_QH_CAPS_SCM_SHIFT 8 // Split Completion Mask
-#define EHCI_QH_CAPS_SCM_MASK 0xff
-#define EHCI_QH_CAPS_ISM_SHIFT 0 // Interrupt Schedule Mask
-#define EHCI_QH_CAPS_ISM_MASK 0xff
diff --git a/drivers/usb/usbehci/interfaces.h b/drivers/usb/usbehci/interfaces.h
deleted file mode 100644
index 58160fa1475..00000000000
--- a/drivers/usb/usbehci/interfaces.h
+++ /dev/null
@@ -1,151 +0,0 @@
-#ifndef INTERFACES_HPP
-#define INTERFACES_HPP
-
-//=========================================================================================
-//
-// class IUSBHardwareDevice
-//
-// Description: This class provides access to the usb hardware controller
-//
-
-#define DEFINE_ABSTRACT_USBEHCIHARDWARE() \
- STDMETHOD_(VOID, SetAsyncListRegister)( THIS_ \
- IN ULONG PhysicalAddress) PURE; \
- \
- STDMETHOD_(VOID, SetPeriodicListRegister)( THIS_ \
- IN ULONG PhysicalAddress) PURE; \
- \
- STDMETHOD_(struct _QUEUE_HEAD *, GetAsyncListQueueHead)( THIS) PURE; \
- \
- STDMETHOD_(ULONG, GetPeriodicListRegister)( THIS) PURE; \
- \
- STDMETHOD_(VOID, SetCommandRegister)( THIS_ \
- IN struct _EHCI_USBCMD_CONTENT *UsbCmd) PURE; \
- \
- STDMETHOD_(VOID, GetCommandRegister)( THIS_ \
- OUT struct _EHCI_USBCMD_CONTENT *UsbCmd) PURE;
-
-#define IMP_IUSBEHCIHARDWARE \
- STDMETHODIMP_(VOID) SetAsyncListRegister( \
- IN ULONG PhysicalAddress); \
- \
- STDMETHODIMP_(VOID) SetPeriodicListRegister( \
- IN ULONG PhysicalAddress); \
- \
- STDMETHODIMP_(struct _QUEUE_HEAD *) GetAsyncListQueueHead(); \
- \
- STDMETHODIMP_(ULONG) GetPeriodicListRegister(); \
- \
- STDMETHODIMP_(VOID) SetCommandRegister( \
- IN struct _EHCI_USBCMD_CONTENT *UsbCmd); \
- STDMETHODIMP_(VOID) GetCommandRegister( \
- OUT struct _EHCI_USBCMD_CONTENT *UsbCmd);
-
-DECLARE_INTERFACE_(IEHCIHardwareDevice, IUSBHardwareDevice)
-{
- DEFINE_ABSTRACT_UNKNOWN()
- DEFINE_ABSTRACT_USBHARDWAREDEVICE()
- DEFINE_ABSTRACT_USBEHCIHARDWARE()
-};
-
-typedef IEHCIHardwareDevice *PEHCIHARDWAREDEVICE;
-
-//=========================================================================================
-//
-// class IUSBRequest
-//
-// Description: This class is used to issue request to usb controller. The class is
-// initialized using InitializeXXX methods. You also need to call SetEndpoint to define
the endpoint
-// In addition you can call SetCompletionDetails if you need to wait for the end of
-// the request or want to complete an irp. You call AddUSBRequest to add the request to
the queue.
-// Once the request is completed the CompletionCallback is invoked. The
CompletionCallback
-// will take care of any completion details which have been set. If the request is
cancelled, the
-// CancelCallback routine is invoked.
-//
-
-struct _QUEUE_HEAD;
-struct _USB_ENDPOINT;
-
-#define DEFINE_ABSTRACT_USBEHCIREQUEST() \
- STDMETHOD_(VOID, CompletionCallback)( THIS_ \
- IN NTSTATUS NtStatusCode, \
- IN ULONG UrbStatusCode, \
- IN struct _QUEUE_HEAD *QueueHead) PURE; \
- \
- STDMETHOD_(NTSTATUS, GetQueueHead)( THIS_ \
- IN struct _QUEUE_HEAD ** OutHead) PURE; \
- \
- STDMETHOD_(BOOLEAN, ShouldReleaseRequestAfterCompletion)( THIS) PURE; \
- \
- \
- STDMETHOD_(VOID, FreeQueueHead)( THIS_ \
- IN struct _QUEUE_HEAD * QueueHead) PURE; \
- \
- STDMETHOD_(BOOLEAN, IsQueueHeadComplete)( THIS_ \
- IN struct _QUEUE_HEAD * QueueHead) PURE; \
- \
- STDMETHOD_(USB_DEVICE_SPEED, GetSpeed)( THIS) PURE; \
- \
- STDMETHOD_(UCHAR, GetInterval)( THIS) PURE;
-
-#define IMP_IEHCIREQUEST \
- STDMETHODIMP_(VOID) CompletionCallback( \
- IN NTSTATUS NtStatusCode, \
- IN ULONG UrbStatusCode, \
- IN struct _QUEUE_HEAD *QueueHead); \
- \
- STDMETHODIMP_(NTSTATUS) GetQueueHead( \
- IN struct _QUEUE_HEAD ** OutHead); \
- \
- STDMETHODIMP_(BOOLEAN) ShouldReleaseRequestAfterCompletion(); \
- \
- STDMETHODIMP_(VOID) FreeQueueHead(struct _QUEUE_HEAD * QueueHead); \
- \
- STDMETHODIMP_(BOOLEAN) IsQueueHeadComplete( \
- IN struct _QUEUE_HEAD * QueueHead); \
- \
- STDMETHODIMP_(USB_DEVICE_SPEED) GetSpeed( THIS); \
- \
- STDMETHODIMP_(UCHAR) GetInterval( THIS);
-
-DECLARE_INTERFACE_(IEHCIRequest, IUSBRequest)
-{
- DEFINE_ABSTRACT_UNKNOWN()
- DEFINE_ABSTRACT_USBREQUEST()
- DEFINE_ABSTRACT_USBEHCIREQUEST()
-};
-
-
-typedef IEHCIRequest *PEHCIREQUEST;
-
-//=========================================================================================
-//
-// class IUSBQueue
-//
-// Description: This class manages pending requests
-//
-
-#define DEFINE_ABSTRACT_USBEHCIQUEUE() \
- STDMETHOD_(VOID, InterruptCallback)( THIS_ \
- IN NTSTATUS Status, \
- OUT PULONG ShouldRingDoorBell) PURE; \
- \
- STDMETHOD_(VOID, CompleteAsyncRequests)( THIS) PURE;
-
-#define IMP_IEHCIQUEUE \
- STDMETHODIMP_(VOID) InterruptCallback( \
- IN NTSTATUS Status, \
- OUT PULONG ShouldRingDoorBell); \
- \
- STDMETHODIMP_(VOID) CompleteAsyncRequests();
-
-DECLARE_INTERFACE_(IEHCIQueue, IUSBQueue)
-{
- DEFINE_ABSTRACT_UNKNOWN()
- DEFINE_ABSTRACT_USBQUEUE()
- DEFINE_ABSTRACT_USBEHCIQUEUE()
-};
-
-typedef IEHCIQueue *PEHCIQUEUE;
-
-#endif /* INTERFACES_HPP */
diff --git a/drivers/usb/usbehci/usb_queue.cpp b/drivers/usb/usbehci/usb_queue.cpp
deleted file mode 100644
index 48a06d62c2d..00000000000
--- a/drivers/usb/usbehci/usb_queue.cpp
+++ /dev/null
@@ -1,1236 +0,0 @@
-/*
- * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: drivers/usb/usbehci/usb_queue.cpp
- * PURPOSE: USB EHCI device driver.
- * PROGRAMMERS:
- * Michael Martin (michael.martin(a)reactos.org)
- * Johannes Anderwald (johannes.anderwald(a)reactos.org)
- */
-
-#include "usbehci.h"
-
-#define NDEBUG
-#include <debug.h>
-
-class CUSBQueue : public IEHCIQueue
-{
-public:
- STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
-
- STDMETHODIMP_(ULONG) AddRef()
- {
- InterlockedIncrement(&m_Ref);
- return m_Ref;
- }
- STDMETHODIMP_(ULONG) Release()
- {
- InterlockedDecrement(&m_Ref);
-
- if (!m_Ref)
- {
- delete this;
- return 0;
- }
- return m_Ref;
- }
-
- // IUSBQueue functions
- IMP_IUSBQUEUE
-
- // IEHCIQueue functions
- IMP_IEHCIQUEUE
-
- // constructor / destructor
- CUSBQueue(IUnknown *OuterUnknown){}
- virtual ~CUSBQueue(){}
-
-protected:
- LONG m_Ref;
// reference count
- PKSPIN_LOCK m_Lock;
// list lock
- PDMA_ADAPTER m_Adapter;
// dma adapter
- PEHCIHARDWAREDEVICE m_Hardware;
// stores hardware object
- PQUEUE_HEAD AsyncListQueueHead;
// async queue head
- LIST_ENTRY m_CompletedRequestAsyncList;
// completed async request list
- LIST_ENTRY m_PendingRequestAsyncList;
// pending async request list
- ULONG m_MaxPeriodicListEntries;
// max periodic list entries
- ULONG m_MaxPollingInterval;
// max polling interval
- PHYSICAL_ADDRESS m_SyncFrameListAddr;
// physical address of sync frame list
- PULONG m_SyncFrameList;
// virtual address of sync frame list
-
- // queue head manipulation functions
- VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
- VOID UnlinkQueueHead(PQUEUE_HEAD QueueHead);
- VOID LinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
- PQUEUE_HEAD UnlinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, ULONG Count);
-
- // processes the async list
- VOID ProcessAsyncList(IN NTSTATUS Status, OUT PULONG ShouldRingDoorBell);
-
- // processes the async list
- VOID ProcessPeriodicSchedule(IN NTSTATUS Status, OUT PULONG ShouldRingDoorBell);
-
- // called for each completed queue head
- VOID QueueHeadCompletion(PQUEUE_HEAD QueueHead, NTSTATUS Status);
-
- // called for each completed queue head
- VOID QueueHeadInterruptCompletion(PQUEUE_HEAD QueueHead, NTSTATUS Status);
-
- // called when the completion queue is cleaned up
- VOID QueueHeadCleanup(PQUEUE_HEAD QueueHead);
-
- // initializes the sync schedule
- NTSTATUS InitializeSyncSchedule(IN PEHCIHARDWAREDEVICE Hardware, IN PDMAMEMORYMANAGER
MemManager);
-
- // links interrupt queue head
- VOID LinkInterruptQueueHead(PQUEUE_HEAD QueueHead);
-
- // interval index
- UCHAR GetIntervalIndex(UCHAR Interval);
-
-
- // interrupt queue heads
- PQUEUE_HEAD m_InterruptQueueHeads[EHCI_INTERRUPT_ENTRIES_COUNT];
-
- // contains the periodic queue heads
- LIST_ENTRY m_PeriodicQueueHeads;
-};
-
-//=================================================================================================
-// COM
-//
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBQueue::QueryInterface(
- IN REFIID refiid,
- OUT PVOID* Output)
-{
- if (IsEqualGUIDAligned(refiid, IID_IUnknown))
- {
- *Output = PVOID(PUNKNOWN(this));
- PUNKNOWN(*Output)->AddRef();
- return STATUS_SUCCESS;
- }
-
- return STATUS_UNSUCCESSFUL;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBQueue::Initialize(
- IN PUSBHARDWAREDEVICE Hardware,
- IN PDMA_ADAPTER AdapterObject,
- IN PDMAMEMORYMANAGER MemManager,
- IN OPTIONAL PKSPIN_LOCK Lock)
-{
- NTSTATUS Status = STATUS_SUCCESS;
-
- DPRINT("CUSBQueue::Initialize()\n");
-
- ASSERT(Hardware);
-
- //
- // store device lock
- //
- m_Lock = Lock;
-
- //
- // store hardware object
- //
- m_Hardware = PEHCIHARDWAREDEVICE(Hardware);
-
-
- //
- // Get the AsyncQueueHead
- //
- AsyncListQueueHead = (PQUEUE_HEAD)m_Hardware->GetAsyncListQueueHead();
-
- //
- // Initialize the List Head
- //
- InitializeListHead(&AsyncListQueueHead->LinkedQueueHeads);
-
- //
- // Initialize completed async list head
- //
- InitializeListHead(&m_CompletedRequestAsyncList);
-
- //
- // Initialize pending async list head
- //
- InitializeListHead(&m_PendingRequestAsyncList);
-
- //
- // initialize periodic queue heads
- //
- InitializeListHead(&m_PeriodicQueueHeads);
-
- //
- // now initialize sync schedule
- //
- Status = InitializeSyncSchedule(m_Hardware, MemManager);
-
-
- return Status;
-}
-
-NTSTATUS
-CUSBQueue::InitializeSyncSchedule(
- IN PEHCIHARDWAREDEVICE Hardware,
- IN PDMAMEMORYMANAGER MemManager)
-{
- PHYSICAL_ADDRESS QueueHeadPhysAddr;
- NTSTATUS Status;
- ULONG Index, Interval, IntervalIndex;
- PQUEUE_HEAD QueueHead;
-
- //
- // FIXME: check if smaller list sizes are supported
- //
- m_MaxPeriodicListEntries = 1024;
-
- //
- // use polling scheme of 512ms
- //
- m_MaxPollingInterval = 512;
-
- //
- // first allocate a page to hold the queue array
- //
- Status = MemManager->Allocate(m_MaxPeriodicListEntries * sizeof(PVOID),
(PVOID*)&m_SyncFrameList, &m_SyncFrameListAddr);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to allocate sync frame list array
- //
- DPRINT1("Failed to allocate sync frame list\n");
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- for(Index = 0; Index < EHCI_INTERRUPT_ENTRIES_COUNT; Index++)
- {
- //
- // allocate queue head
- //
- Status = MemManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead,
&QueueHeadPhysAddr);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to create queue head
- //
- DPRINT1("Failed to create queue head\n");
- return Status;
- }
-
- //
- // initialize queue head
- //
- QueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
- QueueHead->AlternateNextPointer = TERMINATE_POINTER;
- QueueHead->NextPointer = TERMINATE_POINTER;
- QueueHead->EndPointCharacteristics.MaximumPacketLength = 64;
- QueueHead->EndPointCharacteristics.NakCountReload = 0x3;
- QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
- QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x01;
- QueueHead->PhysicalAddr = QueueHeadPhysAddr.LowPart;
- QueueHead->Token.Bits.Halted = TRUE; //FIXME
- m_InterruptQueueHeads[Index]= QueueHead;
-
- if (Index > 0)
- {
- // link all to the first queue head
- QueueHead->HorizontalLinkPointer =
m_InterruptQueueHeads[0]->PhysicalAddr | QH_TYPE_QH;
- QueueHead->NextQueueHead = m_InterruptQueueHeads[0];
- }
- }
-
- //
- // build interrupt tree
- //
- Interval = EHCI_FRAMELIST_ENTRIES_COUNT;
- IntervalIndex = EHCI_INTERRUPT_ENTRIES_COUNT - 1;
- while (Interval > 1)
- {
- for (Index = Interval / 2; Index < EHCI_FRAMELIST_ENTRIES_COUNT; Index +=
Interval)
- {
- DPRINT("Index %lu IntervalIndex %lu\n", Index, IntervalIndex);
- m_SyncFrameList[Index] =
m_InterruptQueueHeads[IntervalIndex]->PhysicalAddr | QH_TYPE_QH;
- }
- IntervalIndex--;
- Interval /= 2;
- }
-
- //
- // now set the sync base
- //
- Hardware->SetPeriodicListRegister(m_SyncFrameListAddr.LowPart);
-
- //
- // sync frame list initialized
- //
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBQueue::AddUSBRequest(
- IUSBRequest * Req)
-{
- PQUEUE_HEAD QueueHead;
- NTSTATUS Status;
- ULONG Type;
- KIRQL OldLevel;
- PEHCIREQUEST Request;
-
- // sanity check
- ASSERT(Req != NULL);
-
- // get internal req
- Request = PEHCIREQUEST(Req);
-
- // 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_BULK:
- case USB_ENDPOINT_TYPE_CONTROL:
- 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
- return Status;
- }
-
- // get queue head
- Status = Request->GetQueueHead(&QueueHead);
-
- // check for success
- if (!NT_SUCCESS(Status))
- {
- // failed to get queue head
- return Status;
- }
-
- // acquire lock
- KeAcquireSpinLock(m_Lock, &OldLevel);
-
- if (Type == USB_ENDPOINT_TYPE_BULK || Type == USB_ENDPOINT_TYPE_CONTROL)
- {
- // Add to list
- LinkQueueHead(AsyncListQueueHead, QueueHead);
- }
- else if (Type == USB_ENDPOINT_TYPE_INTERRUPT)
- {
- // get interval
- LinkInterruptQueueHead(QueueHead);
- }
-
- // release lock
- KeReleaseSpinLock(m_Lock, OldLevel);
-
-
- // add extra reference which is released when the request is completed
- Request->AddRef();
-
- // done
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBQueue::CreateUSBRequest(
- IUSBRequest **OutRequest)
-{
- PUSBREQUEST UsbRequest;
- NTSTATUS Status;
-
- *OutRequest = NULL;
- Status = InternalCreateUSBRequest(&UsbRequest);
-
- if (NT_SUCCESS(Status))
- {
- *OutRequest = UsbRequest;
- }
-
- return Status;
-}
-
-UCHAR
-CUSBQueue::GetIntervalIndex(
- UCHAR Interval)
-{
- UCHAR IntervalIndex;
-
- ASSERT(Interval != 0);
- if (Interval == 1)
- IntervalIndex = 1;
- else if (Interval == 2)
- IntervalIndex = 2;
- else if (Interval <= 4)
- IntervalIndex = 3;
- else if (Interval <= 8)
- IntervalIndex = 4;
- else if (Interval <= 16)
- IntervalIndex = 5;
- else if (Interval <= 32)
- IntervalIndex = 6;
- else if (Interval <= 64)
- IntervalIndex = 7;
- else if (Interval <= 128)
- IntervalIndex = 8;
- else
- IntervalIndex = 9;
-
- ASSERT(IntervalIndex < EHCI_INTERRUPT_ENTRIES_COUNT);
- return IntervalIndex;
-}
-
-VOID
-CUSBQueue::LinkInterruptQueueHead(
- PQUEUE_HEAD QueueHead)
-{
- PEHCIREQUEST Request;
- UCHAR Interval, IntervalIndex;
- USB_DEVICE_SPEED DeviceSpeed;
- PQUEUE_HEAD InterruptQueueHead;
-
- // get internal req
- Request = PEHCIREQUEST(QueueHead->Request);
- ASSERT(Request);
-
- // get interval
- Interval = Request->GetInterval();
-
- // get device speed
- DeviceSpeed = Request->GetSpeed();
- if (DeviceSpeed == UsbHighSpeed)
- {
- // interrupt queue head can be scheduled on each possible micro frame
- QueueHead->EndPointCapabilities.InterruptScheduleMask = 0xFF;
- }
- else
- {
- // As we do not yet support FSTNs to correctly reference low/full
- // speed interrupt transfers, we simply put them into the 1 interval
- // queue. This way we ensure that we reach them on every micro frame
- // and can do the corresponding start/complete split transactions.
- // ToDo: use FSTNs to correctly link non high speed interrupt transfers
- Interval = 1;
-
- // For now we also force start splits to be in micro frame 0 and
- // complete splits to be in micro frame 2, 3 and 4.
- QueueHead->EndPointCapabilities.InterruptScheduleMask = 0x01;
- QueueHead->EndPointCapabilities.SplitCompletionMask = 0x1C;
- }
-
- // sanitize interrupt interval
- Interval = max(1, Interval);
-
- // get interval index
- IntervalIndex = GetIntervalIndex(Interval);
-
-
- // get interrupt queue head
- InterruptQueueHead = m_InterruptQueueHeads[IntervalIndex];
-
- // link queue head
- QueueHead->HorizontalLinkPointer = InterruptQueueHead->HorizontalLinkPointer;
- QueueHead->NextQueueHead = InterruptQueueHead->NextQueueHead;
-
- InterruptQueueHead->HorizontalLinkPointer = QueueHead->PhysicalAddr |
QH_TYPE_QH;
- InterruptQueueHead->NextQueueHead = QueueHead;
-
- // store in periodic list
- InsertTailList(&m_PeriodicQueueHeads, &QueueHead->LinkedQueueHeads);
-}
-
-//
-// LinkQueueHead - Links one QueueHead to the end of HeadQueueHead list, updating
HorizontalLinkPointer.
-//
-VOID
-CUSBQueue::LinkQueueHead(
- PQUEUE_HEAD HeadQueueHead,
- PQUEUE_HEAD NewQueueHead)
-{
- PQUEUE_HEAD LastQueueHead, NextQueueHead;
- PLIST_ENTRY Entry;
- ASSERT(HeadQueueHead);
- ASSERT(NewQueueHead);
-
- //
- // Link the LIST_ENTRYs
- //
- //ASSERT(IsListEmpty(&HeadQueueHead->LinkedQueueHeads));
- InsertTailList(&HeadQueueHead->LinkedQueueHeads,
&NewQueueHead->LinkedQueueHeads);
-
- //
- // Update HLP for NewQueueHead to point to next, which should be the HeadQueueHead
- //
- Entry = NewQueueHead->LinkedQueueHeads.Flink;
- NextQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
- //ASSERT(NextQueueHead == HeadQueueHead);
- NewQueueHead->HorizontalLinkPointer = (NextQueueHead->PhysicalAddr |
QH_TYPE_QH);
-
- _ReadWriteBarrier();
-
- //
- // Update HLP for Previous QueueHead, which should be the last in list.
- //
- Entry = NewQueueHead->LinkedQueueHeads.Blink;
- LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
- //ASSERT(LastQueueHead == HeadQueueHead);
- LastQueueHead->HorizontalLinkPointer = (NewQueueHead->PhysicalAddr |
QH_TYPE_QH);
-
- //
- // head queue head must be halted
- //
- //PC_ASSERT(HeadQueueHead->Token.Bits.Halted == TRUE);
-}
-
-//
-// UnlinkQueueHead - Unlinks one QueueHead, updating HorizontalLinkPointer.
-//
-VOID
-CUSBQueue::UnlinkQueueHead(
- PQUEUE_HEAD QueueHead)
-{
- PQUEUE_HEAD PreviousQH, NextQH;
- PLIST_ENTRY Entry;
-
- //
- // sanity check: there must be at least one queue head with halted bit set
- //
- //PC_ASSERT(QueueHead->Token.Bits.Halted == 0);
-
- //
- // get previous link
- //
- Entry = QueueHead->LinkedQueueHeads.Blink;
-
- //
- // get queue head structure
- //
- PreviousQH = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
-
- //
- // get next link
- //
- Entry = QueueHead->LinkedQueueHeads.Flink;
-
- //
- // get queue head structure
- //
- NextQH = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
-
- //
- // sanity check
- //
- ASSERT(QueueHead->HorizontalLinkPointer == (NextQH->PhysicalAddr |
QH_TYPE_QH));
-
- //
- // remove queue head from linked list
- //
- PreviousQH->HorizontalLinkPointer = NextQH->PhysicalAddr | QH_TYPE_QH;
-
- //
- // remove software link
- //
- RemoveEntryList(&QueueHead->LinkedQueueHeads);
-}
-
-//
-// LinkQueueHeadChain - Links a list of QueueHeads to the HeadQueueHead list, updating
HorizontalLinkPointer.
-//
-VOID
-CUSBQueue::LinkQueueHeadChain(
- PQUEUE_HEAD HeadQueueHead,
- PQUEUE_HEAD NewQueueHead)
-{
- PQUEUE_HEAD LastQueueHead;
- PLIST_ENTRY Entry;
- ASSERT(HeadQueueHead);
- ASSERT(NewQueueHead);
-
- //
- // Find the last QueueHead in NewQueueHead
- //
- Entry = NewQueueHead->LinkedQueueHeads.Blink;
- ASSERT(Entry != NewQueueHead->LinkedQueueHeads.Flink);
- LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
-
- //
- // Set the LinkPointer and Flink
- //
- LastQueueHead->HorizontalLinkPointer = HeadQueueHead->PhysicalAddr |
QH_TYPE_QH;
- LastQueueHead->LinkedQueueHeads.Flink = &HeadQueueHead->LinkedQueueHeads;
-
- //
- // Fine the last QueueHead in HeadQueueHead
- //
- Entry = HeadQueueHead->LinkedQueueHeads.Blink;
- HeadQueueHead->LinkedQueueHeads.Blink = &LastQueueHead->LinkedQueueHeads;
- LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
- LastQueueHead->LinkedQueueHeads.Flink = &NewQueueHead->LinkedQueueHeads;
- LastQueueHead->HorizontalLinkPointer = NewQueueHead->PhysicalAddr |
QH_TYPE_QH;
-}
-
-//
-// UnlinkQueueHeadChain - Unlinks a list number of QueueHeads from HeadQueueHead list,
updating HorizontalLinkPointer.
-// returns the chain of QueueHeads removed from HeadQueueHead.
-//
-PQUEUE_HEAD
-CUSBQueue::UnlinkQueueHeadChain(
- PQUEUE_HEAD HeadQueueHead,
- ULONG Count)
-{
- PQUEUE_HEAD LastQueueHead, FirstQueueHead;
- PLIST_ENTRY Entry;
- ULONG Index;
-
- //
- // Find the last QueueHead in NewQueueHead
- //
- Entry = &HeadQueueHead->LinkedQueueHeads;
- FirstQueueHead = CONTAINING_RECORD(Entry->Flink, QUEUE_HEAD, LinkedQueueHeads);
-
- for (Index = 0; Index < Count; Index++)
- {
- Entry = Entry->Flink;
-
- if (Entry == &HeadQueueHead->LinkedQueueHeads)
- {
- DPRINT1("Warning; Only %lu QueueHeads in HeadQueueHead\n", Index);
- Count = Index + 1;
- break;
- }
- }
-
- LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
- HeadQueueHead->LinkedQueueHeads.Flink = LastQueueHead->LinkedQueueHeads.Flink;
- if (Count + 1 == Index)
- {
- HeadQueueHead->LinkedQueueHeads.Blink =
&HeadQueueHead->LinkedQueueHeads;
- }
- else
- HeadQueueHead->LinkedQueueHeads.Blink =
LastQueueHead->LinkedQueueHeads.Flink;
-
- FirstQueueHead->LinkedQueueHeads.Blink = &LastQueueHead->LinkedQueueHeads;
- LastQueueHead->LinkedQueueHeads.Flink = &FirstQueueHead->LinkedQueueHeads;
- LastQueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
- return FirstQueueHead;
-}
-
-VOID
-CUSBQueue::QueueHeadInterruptCompletion(
- PQUEUE_HEAD QueueHead,
- NTSTATUS Status)
-{
- PEHCIREQUEST Request;
- UCHAR Interval, IntervalIndex;
- PQUEUE_HEAD InterruptQueueHead, LastQueueHead = NULL;
-
-
- //
- // sanity check
- //
- PC_ASSERT(QueueHead->Request);
-
- //
- // get IUSBRequest interface
- //
- Request = (PEHCIREQUEST)QueueHead->Request;
-
- // get interval
- Interval = Request->GetInterval();
-
- // sanitize interval
- Interval = max(1, Interval);
-
- // get interval index
- IntervalIndex = GetIntervalIndex(Interval);
-
- // get interrupt queue head from index
- InterruptQueueHead = m_InterruptQueueHeads[IntervalIndex];
-
- while(InterruptQueueHead != NULL)
- {
- if (InterruptQueueHead == QueueHead)
- break;
-
- // move to next queue head
- LastQueueHead = InterruptQueueHead;
- InterruptQueueHead = (PQUEUE_HEAD)InterruptQueueHead->NextQueueHead;
- }
-
- if (InterruptQueueHead != QueueHead)
- {
- // queue head not in list
- ASSERT(FALSE);
- return;
- }
-
- // now unlink queue head
- LastQueueHead->HorizontalLinkPointer = QueueHead->HorizontalLinkPointer;
- LastQueueHead->NextQueueHead = QueueHead->NextQueueHead;
-
- DPRINT1("Periodic QueueHead %p Addr %x unlinked\n", QueueHead,
QueueHead->PhysicalAddr);
-
- // insert into completed list
- InsertTailList(&m_CompletedRequestAsyncList,
&QueueHead->LinkedQueueHeads);
-}
-
-
-
-VOID
-CUSBQueue::QueueHeadCompletion(
- PQUEUE_HEAD CurrentQH,
- NTSTATUS Status)
-{
- //
- // now unlink the queue head
- // FIXME: implement chained queue heads
- // no need to acquire locks, as it is called with locks held
- //
-
- //
- // unlink queue head
- //
- UnlinkQueueHead(CurrentQH);
-
- //
- // insert into completed list
- //
- InsertTailList(&m_CompletedRequestAsyncList,
&CurrentQH->LinkedQueueHeads);
-}
-
-
-VOID
-CUSBQueue::ProcessPeriodicSchedule(
- IN NTSTATUS Status,
- OUT PULONG ShouldRingDoorBell)
-{
- KIRQL OldLevel;
- PLIST_ENTRY Entry;
- PQUEUE_HEAD QueueHead;
- PEHCIREQUEST Request;
- BOOLEAN IsQueueHeadComplete;
-
- //
- // lock completed async list
- //
- KeAcquireSpinLock(m_Lock, &OldLevel);
-
- //
- // walk async list
- //
- ASSERT(AsyncListQueueHead);
- Entry = m_PeriodicQueueHeads.Flink;
-
- while(Entry != &m_PeriodicQueueHeads)
- {
- //
- // get queue head structure
- //
- QueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
-
- //
- // sanity check
- //
- PC_ASSERT(QueueHead->Request);
-
- //
- // get IUSBRequest interface
- //
- Request = (PEHCIREQUEST)QueueHead->Request;
-
- //
- // move to next entry
- //
- Entry = Entry->Flink;
-
- //
- // check if queue head is complete
- //
- IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead);
-
- DPRINT("Request %p QueueHead %p Complete %c\n", Request, QueueHead,
IsQueueHeadComplete);
-
- //
- // check if queue head is complete
- //
- if (IsQueueHeadComplete)
- {
- //
- // current queue head is complete
- //
- QueueHeadInterruptCompletion(QueueHead, Status);
-
- //
- // ring door bell is going to be necessary
- //
- *ShouldRingDoorBell = TRUE;
- }
- }
-
- //
- // release lock
- //
- KeReleaseSpinLock(m_Lock, OldLevel);
-
-}
-
-VOID
-CUSBQueue::ProcessAsyncList(
- IN NTSTATUS Status,
- OUT PULONG ShouldRingDoorBell)
-{
- KIRQL OldLevel;
- PLIST_ENTRY Entry;
- PQUEUE_HEAD QueueHead;
- PEHCIREQUEST Request;
- BOOLEAN IsQueueHeadComplete;
-
- //
- // lock completed async list
- //
- KeAcquireSpinLock(m_Lock, &OldLevel);
-
- //
- // walk async list
- //
- ASSERT(AsyncListQueueHead);
- Entry = AsyncListQueueHead->LinkedQueueHeads.Flink;
-
- while(Entry != &AsyncListQueueHead->LinkedQueueHeads)
- {
- //
- // get queue head structure
- //
- QueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
-
- //
- // sanity check
- //
- PC_ASSERT(QueueHead->Request);
-
- //
- // get IUSBRequest interface
- //
- Request = (PEHCIREQUEST)QueueHead->Request;
-
- //
- // move to next entry
- //
- Entry = Entry->Flink;
-
- //
- // check if queue head is complete
- //
- IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead);
-
- DPRINT("Request %p QueueHead %p Complete %c\n", Request, QueueHead,
IsQueueHeadComplete);
-
- //
- // check if queue head is complete
- //
- if (IsQueueHeadComplete)
- {
- //
- // current queue head is complete
- //
- QueueHeadCompletion(QueueHead, Status);
-
- //
- // ring door bell is going to be necessary
- //
- *ShouldRingDoorBell = TRUE;
- }
- }
-
- //
- // release lock
- //
- KeReleaseSpinLock(m_Lock, OldLevel);
-}
-
-
-VOID
-STDMETHODCALLTYPE
-CUSBQueue::InterruptCallback(
- IN NTSTATUS Status,
- OUT PULONG ShouldRingDoorBell)
-{
- DPRINT("CUSBQueue::InterruptCallback\n");
-
- //
- // process periodic schedule
- //
- ProcessPeriodicSchedule(Status, ShouldRingDoorBell);
-
- //
- // iterate asynchronous list
- //
- *ShouldRingDoorBell = FALSE;
- ProcessAsyncList(Status, ShouldRingDoorBell);
-}
-
-VOID
-CUSBQueue::QueueHeadCleanup(
- PQUEUE_HEAD CurrentQH)
-{
- PQUEUE_HEAD NewQueueHead;
- PEHCIREQUEST Request;
- BOOLEAN ShouldReleaseWhenDone;
- USBD_STATUS UrbStatus;
- KIRQL OldLevel;
-
- //
- // sanity checks
- //
- PC_ASSERT(CurrentQH->Token.Bits.Active == 0);
- PC_ASSERT(CurrentQH->Request);
-
-
- //
- // get request
- //
- Request = (PEHCIREQUEST)CurrentQH->Request;
-
- //
- // sanity check
- //
- PC_ASSERT(Request);
-
- //
- // check if the queue head was completed with errors
- //
- if (CurrentQH->Token.Bits.Halted)
- {
- if (CurrentQH->Token.Bits.DataBufferError)
- {
- //
- // data buffer error
- //
- UrbStatus = USBD_STATUS_DATA_BUFFER_ERROR;
- }
- else if (CurrentQH->Token.Bits.BabbleDetected)
- {
- //
- // babble detected
- //
- UrbStatus = USBD_STATUS_BABBLE_DETECTED;
- }
- else
- {
- //
- // stall pid
- //
- UrbStatus = USBD_STATUS_STALL_PID;
- }
- }
- else
- {
- //
- // well done ;)
- //
- UrbStatus = USBD_STATUS_SUCCESS;
- }
-
- //
- // Check if the transfer was completed and if UrbStatus is ok
- //
- if ((Request->IsRequestComplete() == FALSE) && (UrbStatus ==
USBD_STATUS_SUCCESS))
- {
- //
- // request is incomplete, get new queue head
- //
- if (Request->GetQueueHead(&NewQueueHead) == STATUS_SUCCESS)
- {
- //
- // let IUSBRequest free the queue head
- //
- Request->FreeQueueHead(CurrentQH);
-
- //
- // first acquire request lock
- //
- KeAcquireSpinLock(m_Lock, &OldLevel);
-
- //
- // add to pending list
- //
- InsertTailList(&m_PendingRequestAsyncList,
&NewQueueHead->LinkedQueueHeads);
-
- //
- // release queue head
- //
- KeReleaseSpinLock(m_Lock, OldLevel);
-
- //
- // Done for now
- //
- return;
- }
- DPRINT1("Unable to create a new QueueHead\n");
- //ASSERT(FALSE);
-
- //
- // Else there was a problem
- // FIXME: Find better return
- UrbStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
- }
-
- if (UrbStatus != USBD_STATUS_SUCCESS)
- {
- DPRINT1("URB failed with status 0x%x\n", UrbStatus);
- //PC_ASSERT(FALSE);
- }
-
- //
- // notify request that a transfer has completed
- //
- Request->CompletionCallback(UrbStatus != USBD_STATUS_SUCCESS ?
STATUS_UNSUCCESSFUL : STATUS_SUCCESS,
- UrbStatus,
- CurrentQH);
-
- //
- // let IUSBRequest free the queue head
- //
- Request->FreeQueueHead(CurrentQH);
-
- //
- // check if we should release request when done
- //
- ShouldReleaseWhenDone = Request->ShouldReleaseRequestAfterCompletion();
-
- //
- // release reference when the request was added
- //
- Request->Release();
-
- //
- // check if the operation was asynchronous
- //
- if (ShouldReleaseWhenDone)
- {
- //
- // release outstanding reference count
- //
- Request->Release();
- }
-
- //
- // request is now released
- //
-}
-
-VOID
-STDMETHODCALLTYPE
-CUSBQueue::CompleteAsyncRequests()
-{
- KIRQL OldLevel;
- PLIST_ENTRY Entry;
- PQUEUE_HEAD CurrentQH;
-
- DPRINT("CUSBQueue::CompleteAsyncRequests\n");
-
- //
- // first acquire request lock
- //
- KeAcquireSpinLock(m_Lock, &OldLevel);
-
- //
- // the list should not be empty
- //
- PC_ASSERT(!IsListEmpty(&m_CompletedRequestAsyncList));
-
- while(!IsListEmpty(&m_CompletedRequestAsyncList))
- {
- //
- // remove first entry
- //
- Entry = RemoveHeadList(&m_CompletedRequestAsyncList);
-
- //
- // get queue head structure
- //
- CurrentQH = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
-
- //
- // release lock
- //
- KeReleaseSpinLock(m_Lock, OldLevel);
-
- //
- // complete request now
- //
- QueueHeadCleanup(CurrentQH);
-
- //
- // first acquire request lock
- //
- KeAcquireSpinLock(m_Lock, &OldLevel);
- }
-
- //
- // is there a pending async entry
- //
- if (!IsListEmpty(&m_PendingRequestAsyncList))
- {
- //
- // remove first entry
- //
- Entry = RemoveHeadList(&m_PendingRequestAsyncList);
-
- //
- // get queue head structure
- //
- CurrentQH = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
-
- //
- // Add it to the AsyncList list
- //
- LinkQueueHead(AsyncListQueueHead, CurrentQH);
- }
-
- //
- // release lock
- //
- KeReleaseSpinLock(m_Lock, OldLevel);
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBQueue::AbortDevicePipe(
- IN UCHAR DeviceAddress,
- IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor)
-{
- KIRQL OldLevel;
- PLIST_ENTRY Entry;
- PQUEUE_HEAD QueueHead;
- LIST_ENTRY ListHead;
-
- //
- // lock completed async list
- //
- KeAcquireSpinLock(m_Lock, &OldLevel);
-
- DPRINT1("AbortDevicePipe DeviceAddress %x EndpointDescriptor %p Addr %x\n",
DeviceAddress, EndpointDescriptor, EndpointDescriptor->bEndpointAddress);
-
- //
- // init list head
- //
- InitializeListHead(&ListHead);
-
-
- //
- // walk async list
- //
- ASSERT(AsyncListQueueHead);
- Entry = AsyncListQueueHead->LinkedQueueHeads.Flink;
-
- while(Entry != &AsyncListQueueHead->LinkedQueueHeads)
- {
- //
- // get queue head structure
- //
- QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
- ASSERT(QueueHead);
-
- //
- // move to next entry
- //
- Entry = Entry->Flink;
-
- if (QueueHead->EndPointCharacteristics.DeviceAddress == DeviceAddress
&&
- QueueHead->EndPointCharacteristics.EndPointNumber ==
(EndpointDescriptor->bEndpointAddress & 0xF) &&
QueueHead->Token.Bits.Halted)
- {
- //
- // unlink queue head
- //
- UnlinkQueueHead(QueueHead);
-
- //
- // add to temp list
- //
- InsertTailList(&ListHead, &QueueHead->LinkedQueueHeads);
- }
- }
-
- //
- // release lock
- //
- KeReleaseSpinLock(m_Lock, OldLevel);
-
- while(!IsListEmpty(&ListHead))
- {
- //
- // remove entry
- //
- Entry = RemoveHeadList(&ListHead);
-
- //
- // get queue head structure
- //
- QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
- ASSERT(QueueHead);
-
- //
- // cleanup queue head
- //
- QueueHeadCleanup(QueueHead);
- }
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-NTAPI
-CreateUSBQueue(
- PUSBQUEUE *OutUsbQueue)
-{
- PUSBQUEUE This;
-
- //
- // allocate controller
- //
- This = new(NonPagedPool, TAG_USBEHCI) CUSBQueue(0);
- if (!This)
- {
- //
- // failed to allocate
- //
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // add reference count
- //
- This->AddRef();
-
- //
- // return result
- //
- *OutUsbQueue = (PUSBQUEUE)This;
-
- //
- // done
- //
- return STATUS_SUCCESS;
-}
-
diff --git a/drivers/usb/usbehci/usb_request.cpp b/drivers/usb/usbehci/usb_request.cpp
deleted file mode 100644
index abffd0dc679..00000000000
--- a/drivers/usb/usbehci/usb_request.cpp
+++ /dev/null
@@ -1,1852 +0,0 @@
-/*
- * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: drivers/usb/usbehci/usb_request.cpp
- * PURPOSE: USB EHCI device driver.
- * PROGRAMMERS:
- * Michael Martin (michael.martin(a)reactos.org)
- * Johannes Anderwald (johannes.anderwald(a)reactos.org)
- */
-
-#include "usbehci.h"
-
-#define NDEBUG
-#include <debug.h>
-
-class CUSBRequest : public IEHCIRequest
-{
-public:
- STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
-
- STDMETHODIMP_(ULONG) AddRef()
- {
- InterlockedIncrement(&m_Ref);
- return m_Ref;
- }
- STDMETHODIMP_(ULONG) Release()
- {
- InterlockedDecrement(&m_Ref);
-
- if (!m_Ref)
- {
- delete this;
- return 0;
- }
- return m_Ref;
- }
-
- // IUSBRequest interface functions
- IMP_IUSBREQUEST
- // IEHCI Request interface functions
- IMP_IEHCIREQUEST
-
- // local functions
- ULONG InternalGetTransferType();
- UCHAR InternalGetPidDirection();
- NTSTATUS BuildControlTransferQueueHead(PQUEUE_HEAD * OutHead);
- NTSTATUS BuildBulkInterruptTransferQueueHead(PQUEUE_HEAD * OutHead);
- NTSTATUS STDMETHODCALLTYPE CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR
*OutDescriptor);
- NTSTATUS CreateQueueHead(PQUEUE_HEAD *OutQueueHead);
- UCHAR STDMETHODCALLTYPE GetDeviceAddress();
- NTSTATUS BuildSetupPacket();
- NTSTATUS BuildSetupPacketFromURB();
- ULONG InternalCalculateTransferLength();
- NTSTATUS STDMETHODCALLTYPE BuildTransferDescriptorChain(IN PQUEUE_HEAD QueueHead, IN
PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR
InitialDataToggle, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor, OUT
PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor, OUT PUCHAR OutDataToggle, OUT PULONG
OutTransferBufferOffset);
- VOID STDMETHODCALLTYPE InitDescriptor(IN PQUEUE_TRANSFER_DESCRIPTOR
CurrentDescriptor, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR
PidCode, IN UCHAR DataToggle, OUT PULONG OutDescriptorLength);
- VOID DumpQueueHead(IN PQUEUE_HEAD QueueHead);
-
- // constructor / destructor
- CUSBRequest(IUnknown *OuterUnknown);
- virtual ~CUSBRequest();
-
-protected:
- LONG m_Ref;
-
- //
- // memory manager for allocating setup packet / queue head / transfer descriptors
- //
- PDMAMEMORYMANAGER m_DmaManager;
-
- //
- // caller provided irp packet containing URB request
- //
- PIRP m_Irp;
-
- //
- // transfer buffer length
- //
- ULONG m_TransferBufferLength;
-
- //
- // current transfer length
- //
- ULONG m_TransferBufferLengthCompleted;
-
- //
- // Total Transfer Length
- //
- ULONG m_TotalBytesTransferred;
-
- //
- // transfer buffer MDL
- //
- PMDL m_TransferBufferMDL;
-
- //
- // caller provided setup packet
- //
- PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket;
-
- //
- // completion event for callers who initialized request with setup packet
- //
- PKEVENT m_CompletionEvent;
-
- //
- // device address for callers who initialized it with device address
- //
- UCHAR m_DeviceAddress;
-
- //
- // store end point address
- //
- PUSB_ENDPOINT m_EndpointDescriptor;
-
- //
- // DMA queue head
- //
- PQUEUE_HEAD m_QueueHead;
-
- //
- // allocated setup packet from the DMA pool
- //
- PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket;
- PHYSICAL_ADDRESS m_DescriptorSetupPacket;
-
- //
- // stores the result of the operation
- //
- NTSTATUS m_NtStatusCode;
- ULONG m_UrbStatusCode;
-
- // buffer base address
- PVOID m_Base;
-
- // device speed
- USB_DEVICE_SPEED m_Speed;
-
-};
-
-//----------------------------------------------------------------------------------------
-CUSBRequest::CUSBRequest(IUnknown *OuterUnknown) :
- m_CompletionEvent(NULL)
-{
- UNREFERENCED_PARAMETER(OuterUnknown);
-}
-
-//----------------------------------------------------------------------------------------
-CUSBRequest::~CUSBRequest()
-{
- if (m_CompletionEvent != NULL)
- {
- ExFreePoolWithTag(m_CompletionEvent, TAG_USBEHCI);
- }
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBRequest::QueryInterface(
- IN REFIID refiid,
- OUT PVOID* Output)
-{
- return STATUS_UNSUCCESSFUL;
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBRequest::InitializeWithSetupPacket(
- IN PDMAMEMORYMANAGER DmaManager,
- IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
- IN PUSBDEVICE Device,
- IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor,
- IN OUT ULONG TransferBufferLength,
- IN OUT PMDL TransferBuffer)
-{
- //
- // sanity checks
- //
- PC_ASSERT(DmaManager);
- PC_ASSERT(SetupPacket);
-
- //
- // initialize packet
- //
- m_DmaManager = DmaManager;
- m_SetupPacket = SetupPacket;
- m_TransferBufferLength = TransferBufferLength;
- m_TransferBufferMDL = TransferBuffer;
- m_DeviceAddress = Device->GetDeviceAddress();
- m_Speed = Device->GetSpeed();
- m_EndpointDescriptor = EndpointDescriptor;
- m_TotalBytesTransferred = 0;
-
- //
- // Set Length Completed to 0
- //
- m_TransferBufferLengthCompleted = 0;
-
- //
- // allocate completion event
- //
- m_CompletionEvent = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT),
TAG_USBEHCI);
- if (!m_CompletionEvent)
- {
- //
- // failed to allocate completion event
- //
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // initialize completion event
- //
- KeInitializeEvent(m_CompletionEvent, NotificationEvent, FALSE);
-
- //
- // done
- //
- return STATUS_SUCCESS;
-}
-//----------------------------------------------------------------------------------------
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBRequest::InitializeWithIrp(
- IN PDMAMEMORYMANAGER DmaManager,
- IN PUSBDEVICE Device,
- IN OUT PIRP Irp)
-{
- PIO_STACK_LOCATION IoStack;
- PURB Urb;
-
- //
- // sanity checks
- //
- PC_ASSERT(DmaManager);
- PC_ASSERT(Irp);
-
- m_DmaManager = DmaManager;
- m_TotalBytesTransferred = 0;
- m_Speed = Device->GetSpeed();
-
- //
- // get current irp stack location
- //
- IoStack = IoGetCurrentIrpStackLocation(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;
-
- //
- // store irp
- //
- m_Irp = Irp;
-
- //
- // check function type
- //
- switch (Urb->UrbHeader.Function)
- {
- //
- // luckily those request have the same structure layout
- //
- case URB_FUNCTION_CLASS_INTERFACE:
- case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
- case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
- {
- //
- // bulk interrupt transfer
- //
- if (Urb->UrbBulkOrInterruptTransfer.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);
-
- //
- // Keep that ehci created the MDL and needs to free it.
- //
- }
- else
- {
- m_TransferBufferMDL =
Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
- }
-
- //
- // save buffer length
- //
- m_TransferBufferLength =
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
-
- //
- // Set Length Completed to 0
- //
- m_TransferBufferLengthCompleted = 0;
-
- //
- // get endpoint descriptor
- //
- m_EndpointDescriptor =
(PUSB_ENDPOINT)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
-
- }
- break;
- }
- default:
- DPRINT1("URB Function: not supported %x\n",
Urb->UrbHeader.Function);
- //ASSERT(FALSE);
- }
-
- //
- // done
- //
- return STATUS_SUCCESS;
-
-}
-
-//----------------------------------------------------------------------------------------
-VOID
-STDMETHODCALLTYPE
-CUSBRequest::CompletionCallback(
- IN NTSTATUS NtStatusCode,
- IN ULONG UrbStatusCode,
- IN struct _QUEUE_HEAD *QueueHead)
-{
- PIO_STACK_LOCATION IoStack;
- PURB Urb;
-
- //
- // FIXME: support linked queue heads
- //
-
- //
- // store completion code
- //
- m_NtStatusCode = NtStatusCode;
- m_UrbStatusCode = UrbStatusCode;
-
- if (m_Irp)
- {
- //
- // set irp completion status
- //
- m_Irp->IoStatus.Status = NtStatusCode;
-
- //
- // get current irp stack location
- //
- IoStack = IoGetCurrentIrpStackLocation(m_Irp);
-
- //
- // get urb
- //
- Urb = (PURB)IoStack->Parameters.Others.Argument1;
-
- //
- // store urb status
- //
- Urb->UrbHeader.Status = UrbStatusCode;
-
- //
- // Check if the MDL was created
- //
- if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
- {
- //
- // Free Mdl
- //
- IoFreeMdl(m_TransferBufferMDL);
- }
-
- //
- // check if the request was successful
- //
- if (!NT_SUCCESS(NtStatusCode))
- {
- //
- // set returned length to zero in case of error
- //
- Urb->UrbHeader.Length = 0;
- }
- else
- {
- //
- // calculate transfer length
- //
- Urb->UrbBulkOrInterruptTransfer.TransferBufferLength =
InternalCalculateTransferLength();
- }
-
- DPRINT("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x
Transferred Length %lu\n", this, m_Irp, NtStatusCode, UrbStatusCode,
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
-
- //
- // 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);
- }
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBRequest::GetQueueHead(
- struct _QUEUE_HEAD ** OutHead)
-{
- ULONG TransferType;
- NTSTATUS Status;
-
- //
- // first get transfer type
- //
- TransferType = InternalGetTransferType();
-
- //
- // build request depending on type
- //
- switch(TransferType)
- {
- case USB_ENDPOINT_TYPE_CONTROL:
- Status = BuildControlTransferQueueHead(OutHead);
- break;
- case USB_ENDPOINT_TYPE_INTERRUPT:
- case USB_ENDPOINT_TYPE_BULK:
- Status = BuildBulkInterruptTransferQueueHead(OutHead);
- 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 = *OutHead;
-
- //
- // store request object
- //
- (*OutHead)->Request = PVOID(this);
- }
-
- //
- // done
- //
- return Status;
-}
-
-//----------------------------------------------------------------------------------------
-BOOLEAN
-STDMETHODCALLTYPE
-CUSBRequest::IsRequestComplete()
-{
- //
- // FIXME: check if request was split
- //
-
- //
- // Check if the transfer was completed, only valid for Bulk Transfers
- //
- if ((m_TransferBufferLengthCompleted < m_TransferBufferLength)
- && (GetTransferType() == USB_ENDPOINT_TYPE_BULK))
- {
- //
- // Transfer not completed
- //
- return FALSE;
- }
- return TRUE;
-}
-//----------------------------------------------------------------------------------------
-ULONG
-STDMETHODCALLTYPE
-CUSBRequest::GetTransferType()
-{
- //
- // call internal implementation
- //
- return InternalGetTransferType();
-}
-
-//----------------------------------------------------------------------------------------
-ULONG
-CUSBRequest::InternalGetTransferType()
-{
- ULONG TransferType;
-
- //
- // check if an irp is provided
- //
- if (m_Irp)
- {
- ASSERT(m_EndpointDescriptor);
-
- //
- // end point is defined in the low byte of bmAttributes
- //
- TransferType = (m_EndpointDescriptor->EndPointDescriptor.bmAttributes &
USB_ENDPOINT_TYPE_MASK);
- }
- else
- {
- //
- // initialized with setup packet, must be a control transfer
- //
- TransferType = USB_ENDPOINT_TYPE_CONTROL;
- ASSERT(m_EndpointDescriptor == NULL);
- }
-
- //
- // done
- //
- return TransferType;
-}
-
-UCHAR
-CUSBRequest::InternalGetPidDirection()
-{
- if (m_EndpointDescriptor)
- {
- //
- // end point direction is highest bit in bEndpointAddress
- //
- return (m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress &
USB_ENDPOINT_DIRECTION_MASK) >> 7;
- }
- else
- {
- //
- // request arrives on the control pipe, extract direction from setup packet
- //
- ASSERT(m_DescriptorPacket);
- return (m_DescriptorPacket->bmRequestType.B >> 7);
- }
-}
-
-VOID
-STDMETHODCALLTYPE
-CUSBRequest::InitDescriptor(
- IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor,
- IN PVOID TransferBuffer,
- IN ULONG TransferBufferLength,
- IN UCHAR PidCode,
- IN UCHAR DataToggle,
- OUT PULONG OutDescriptorLength)
-{
- ULONG Index, Length = 0, PageOffset, BufferLength;
- PHYSICAL_ADDRESS Address;
-
- //
- // init transfer descriptor
- //
- CurrentDescriptor->Token.Bits.PIDCode = PidCode;
- CurrentDescriptor->Token.Bits.TotalBytesToTransfer = 0;
- CurrentDescriptor->Token.Bits.DataToggle = DataToggle;
-
- //
- // sanity check
- //
- ASSERT(TransferBufferLength);
-
- //
- // store buffers
- //
- Index = 0;
- do
- {
- //
- // get address (HACK)
- //
- *(volatile char *)TransferBuffer;
- Address = MmGetPhysicalAddress(TransferBuffer);
-
- //
- // use physical address
- //
- CurrentDescriptor->BufferPointer[Index] = Address.LowPart;
- CurrentDescriptor->ExtendedBufferPointer[Index] = Address.HighPart;
-
- //
- // Get the offset from page size
- //
- PageOffset = BYTE_OFFSET(CurrentDescriptor->BufferPointer[Index]);
- if (PageOffset != 0)
- {
- //
- // move to next page
- //
- TransferBuffer = (PVOID)ROUND_TO_PAGES(TransferBuffer);
- }
- else
- {
- //
- // move to next page
- //
- TransferBuffer = (PVOID)((ULONG_PTR)TransferBuffer + PAGE_SIZE);
- }
-
- //
- // calculate buffer length
- //
- BufferLength = min(TransferBufferLength, PAGE_SIZE - PageOffset);
-
- //
- // increment transfer bytes
- //
- CurrentDescriptor->Token.Bits.TotalBytesToTransfer += BufferLength;
- CurrentDescriptor->TotalBytesToTransfer += BufferLength;
- Length += BufferLength;
- DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu
Buffer Phy %p TransferBuffer %p\n", Index, TransferBufferLength, PageOffset,
BufferLength, CurrentDescriptor->BufferPointer[Index], TransferBuffer);
-
- //
- // decrement available byte count
- //
- TransferBufferLength -= BufferLength;
- if (TransferBufferLength == 0)
- {
- //
- // end reached
- //
- break;
- }
-
- //
- // sanity check
- //
- if (Index > 1)
- {
- //
- // no equal buffers
- //
- ASSERT(CurrentDescriptor->BufferPointer[Index] !=
CurrentDescriptor->BufferPointer[Index-1]);
- }
-
- //
- // next descriptor index
- //
- Index++;
- }while(Index < 5);
-
- //
- // store result
- //
- *OutDescriptorLength = Length;
-}
-
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBRequest::BuildTransferDescriptorChain(
- IN PQUEUE_HEAD QueueHead,
- IN PVOID TransferBuffer,
- IN ULONG TransferBufferLength,
- IN UCHAR PidCode,
- IN UCHAR InitialDataToggle,
- OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor,
- OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor,
- OUT PUCHAR OutDataToggle,
- OUT PULONG OutTransferBufferOffset)
-{
- PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor
= NULL;
- NTSTATUS Status;
- ULONG DescriptorLength, TransferBufferOffset = 0;
- ULONG MaxPacketSize = 0, TransferSize;
-
- //
- // is there an endpoint descriptor
- //
- if (m_EndpointDescriptor)
- {
- //
- // use endpoint packet size
- //
- MaxPacketSize = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
- }
-
- do
- {
- //
- // allocate transfer descriptor
- //
- Status = CreateDescriptor(&CurrentDescriptor);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to allocate transfer descriptor
- //
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- if (MaxPacketSize)
- {
- //
- // transfer size is minimum available buffer or endpoint size
- //
- TransferSize = min(TransferBufferLength - TransferBufferOffset,
MaxPacketSize);
- }
- else
- {
- //
- // use available buffer
- //
- TransferSize = TransferBufferLength - TransferBufferOffset;
- }
-
- //
- // now init the descriptor
- //
- InitDescriptor(CurrentDescriptor,
- (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset),
- TransferSize,
- PidCode,
- InitialDataToggle,
- &DescriptorLength);
-
- //
- // insert into queue head
- //
- InsertTailList(&QueueHead->TransferDescriptorListHead,
&CurrentDescriptor->DescriptorEntry);
-
- //
- // adjust offset
- //
- TransferBufferOffset += DescriptorLength;
-
- if (LastDescriptor)
- {
- //
- // link to current descriptor
- //
- LastDescriptor->NextPointer = CurrentDescriptor->PhysicalAddr;
- LastDescriptor = CurrentDescriptor;
- }
- else
- {
- //
- // first descriptor in chain
- //
- LastDescriptor = FirstDescriptor = CurrentDescriptor;
- }
-
- //
- // flip data toggle
- //
- InitialDataToggle = !InitialDataToggle;
-
- if(TransferBufferLength == TransferBufferOffset)
- {
- //
- // end reached
- //
- break;
- }
-
- }while(TRUE);
-
- if (OutFirstDescriptor)
- {
- //
- // store first descriptor
- //
- *OutFirstDescriptor = FirstDescriptor;
- }
-
- if (OutLastDescriptor)
- {
- //
- // store last descriptor
- //
- *OutLastDescriptor = CurrentDescriptor;
- }
-
- if (OutDataToggle)
- {
- //
- // store result data toggle
- //
- *OutDataToggle = InitialDataToggle;
- }
-
- if (OutTransferBufferOffset)
- {
- //
- // store offset
- //
- *OutTransferBufferOffset = TransferBufferOffset;
- }
-
- //
- // done
- //
- return STATUS_SUCCESS;
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-CUSBRequest::BuildControlTransferQueueHead(
- PQUEUE_HEAD * OutHead)
-{
- NTSTATUS Status;
- ULONG DescriptorChainLength;
- PQUEUE_HEAD QueueHead;
- PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor, StatusDescriptor, FirstDescriptor,
LastDescriptor;
-
- //
- // first allocate the queue head
- //
- Status = CreateQueueHead(&QueueHead);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to allocate queue head
- //
- DPRINT1("[EHCI] Failed to create queue head\n");
- return Status;
- }
-
- //
- // sanity check
- //
- PC_ASSERT(QueueHead);
-
- //
- // create setup packet
- //
- Status = BuildSetupPacket();
- if (!NT_SUCCESS(Status))
- {
- // failed to create setup packet
- DPRINT1("[EHCI] Failed to create setup packet\n");
-
- // release queue head
- m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
- return Status;
- }
-
- //
- // create setup descriptor
- //
- Status = CreateDescriptor(&SetupDescriptor);
- if (!NT_SUCCESS(Status))
- {
- // failed to create setup transfer descriptor
- DPRINT1("[EHCI] Failed to create setup descriptor\n");
-
- if (m_DescriptorPacket)
- {
- // release packet descriptor
- m_DmaManager->Release(m_DescriptorPacket,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
- }
-
- // release queue head
- m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
- return Status;
- }
-
- //
- // create status descriptor
- //
- Status = CreateDescriptor(&StatusDescriptor);
- if (!NT_SUCCESS(Status))
- {
- // failed to create status transfer descriptor
- DPRINT1("[EHCI] Failed to create status descriptor\n");
-
- // release setup transfer descriptor
- m_DmaManager->Release(SetupDescriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
-
- if (m_DescriptorPacket)
- {
- // release packet descriptor
- m_DmaManager->Release(m_DescriptorPacket,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
- }
-
- // release queue head
- m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
- return Status;
- }
-
- //
- // now initialize the queue head
- //
- QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
-
- ASSERT(m_EndpointDescriptor == NULL);
-
- //
- // init setup descriptor
- //
- SetupDescriptor->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN;
- SetupDescriptor->Token.Bits.TotalBytesToTransfer =
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET);
- SetupDescriptor->Token.Bits.DataToggle = FALSE;
- SetupDescriptor->BufferPointer[0] = m_DescriptorSetupPacket.LowPart;
- SetupDescriptor->ExtendedBufferPointer[0] = m_DescriptorSetupPacket.HighPart;
- InsertTailList(&QueueHead->TransferDescriptorListHead,
&SetupDescriptor->DescriptorEntry);
-
-
- //
- // init status descriptor
- //
- StatusDescriptor->Token.Bits.TotalBytesToTransfer = 0;
- StatusDescriptor->Token.Bits.DataToggle = TRUE;
- StatusDescriptor->Token.Bits.InterruptOnComplete = TRUE;
-
- //
- // is there data
- //
- if (m_TransferBufferLength)
- {
- Status = BuildTransferDescriptorChain(QueueHead,
-
MmGetMdlVirtualAddress(m_TransferBufferMDL),
- m_TransferBufferLength,
- InternalGetPidDirection(),
- TRUE,
- &FirstDescriptor,
- &LastDescriptor,
- NULL,
- &DescriptorChainLength);
- if (!NT_SUCCESS(Status))
- {
- // failed to create descriptor chain
- DPRINT1("[EHCI] Failed to create descriptor chain\n");
-
- // release status transfer descriptor
- m_DmaManager->Release(StatusDescriptor,
sizeof(QUEUE_TRANSFER_DESCRIPTOR));
-
- // release setup transfer descriptor
- m_DmaManager->Release(SetupDescriptor,
sizeof(QUEUE_TRANSFER_DESCRIPTOR));
-
- if (m_DescriptorPacket)
- {
- // release packet descriptor
- m_DmaManager->Release(m_DescriptorPacket,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
- }
-
- // release queue head
- m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
- return Status;
- }
-
- if (m_TransferBufferLength != DescriptorChainLength)
- {
- DPRINT1("DescriptorChainLength %x\n", DescriptorChainLength);
- DPRINT1("m_TransferBufferLength %x\n", m_TransferBufferLength);
- ASSERT(FALSE);
- }
-
- //
- // now link the descriptors
- //
- SetupDescriptor->NextPointer = FirstDescriptor->PhysicalAddr;
- SetupDescriptor->AlternateNextPointer = FirstDescriptor->PhysicalAddr;
- LastDescriptor->NextPointer = StatusDescriptor->PhysicalAddr;
- LastDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr;
-
-
- //
- // pid code is flipped for ops with data stage
- //
- StatusDescriptor->Token.Bits.PIDCode = !InternalGetPidDirection();
- }
- else
- {
- //
- // direct link
- //
- SetupDescriptor->NextPointer = StatusDescriptor->PhysicalAddr;
- SetupDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr;
-
- //
- // retrieve result of operation
- //
- StatusDescriptor->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
- }
-
- //
- // insert status descriptor
- //
- InsertTailList(&QueueHead->TransferDescriptorListHead,
&StatusDescriptor->DescriptorEntry);
-
-
- //
- // link transfer descriptors to queue head
- //
- QueueHead->NextPointer = SetupDescriptor->PhysicalAddr;
-
- //
- // store result
- //
- *OutHead = QueueHead;
-
- //
- // displays the current request
- //
- //DumpQueueHead(QueueHead);
-
- DPRINT("BuildControlTransferQueueHead done\n");
- //
- // done
- //
- return STATUS_SUCCESS;
-}
-
-VOID
-CUSBRequest::DumpQueueHead(
- IN PQUEUE_HEAD QueueHead)
-{
- PLIST_ENTRY Entry;
- PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
- ULONG Index = 0;
-
- DPRINT1("QueueHead %p Addr %x\n", QueueHead, QueueHead->PhysicalAddr);
- DPRINT1("QueueHead AlternateNextPointer %x\n",
QueueHead->AlternateNextPointer);
- DPRINT1("QueueHead NextPointer %x\n", QueueHead->NextPointer);
-
- DPRINT1("QueueHead HubAddr %x\n",
QueueHead->EndPointCharacteristics.ControlEndPointFlag);
- DPRINT1("QueueHead DeviceAddress %x\n",
QueueHead->EndPointCharacteristics.DeviceAddress);
- DPRINT1("QueueHead EndPointNumber %x\n",
QueueHead->EndPointCharacteristics.EndPointNumber);
- DPRINT1("QueueHead EndPointSpeed %x\n",
QueueHead->EndPointCharacteristics.EndPointSpeed);
- DPRINT1("QueueHead HeadOfReclamation %x\n",
QueueHead->EndPointCharacteristics.HeadOfReclamation);
- DPRINT1("QueueHead InactiveOnNextTransaction %x\n",
QueueHead->EndPointCharacteristics.InactiveOnNextTransaction);
- DPRINT1("QueueHead MaximumPacketLength %x\n",
QueueHead->EndPointCharacteristics.MaximumPacketLength);
- DPRINT1("QueueHead NakCountReload %x\n",
QueueHead->EndPointCharacteristics.NakCountReload);
- DPRINT1("QueueHead QEDTDataToggleControl %x\n",
QueueHead->EndPointCharacteristics.QEDTDataToggleControl);
- DPRINT1("QueueHead HubAddr %x\n",
QueueHead->EndPointCapabilities.HubAddr);
- DPRINT1("QueueHead InterruptScheduleMask %x\n",
QueueHead->EndPointCapabilities.InterruptScheduleMask);
- DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n",
QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame);
- DPRINT1("QueueHead PortNumber %x\n",
QueueHead->EndPointCapabilities.PortNumber);
- DPRINT1("QueueHead SplitCompletionMask %x\n",
QueueHead->EndPointCapabilities.SplitCompletionMask);
-
- Entry = QueueHead->TransferDescriptorListHead.Flink;
- while(Entry != &QueueHead->TransferDescriptorListHead)
- {
- //
- // get transfer descriptor
- //
- Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry,
QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
-
- DPRINT1("TransferDescriptor %lu Addr %x\n", Index,
Descriptor->PhysicalAddr);
- DPRINT1("TransferDescriptor %lu Next %x\n", Index,
Descriptor->NextPointer);
- DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index,
Descriptor->AlternateNextPointer);
- DPRINT1("TransferDescriptor %lu Active %lu\n", Index,
Descriptor->Token.Bits.Active);
- DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index,
Descriptor->Token.Bits.BabbleDetected);
- DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index,
Descriptor->Token.Bits.CurrentPage);
- DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index,
Descriptor->Token.Bits.DataBufferError);
- DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index,
Descriptor->Token.Bits.DataToggle);
- DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index,
Descriptor->Token.Bits.ErrorCounter);
- DPRINT1("TransferDescriptor %lu Halted %lu\n", Index,
Descriptor->Token.Bits.Halted);
- DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index,
Descriptor->Token.Bits.InterruptOnComplete);
- DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index,
Descriptor->Token.Bits.MissedMicroFrame);
- DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index,
Descriptor->Token.Bits.PIDCode);
- DPRINT1("TransferDescriptor %lu PingState %lu\n", Index,
Descriptor->Token.Bits.PingState);
- DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index,
Descriptor->Token.Bits.SplitTransactionState);
- DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index,
Descriptor->Token.Bits.TotalBytesToTransfer);
- DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index,
Descriptor->Token.Bits.TransactionError);
-
- DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index,
Descriptor->BufferPointer[0]);
- DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index,
Descriptor->BufferPointer[1]);
- DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index,
Descriptor->BufferPointer[2]);
- DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index,
Descriptor->BufferPointer[3]);
- DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index,
Descriptor->BufferPointer[4]);
- Entry = Entry->Flink;
- Index++;
- }
-}
-
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-CUSBRequest::BuildBulkInterruptTransferQueueHead(
- PQUEUE_HEAD * OutHead)
-{
- NTSTATUS Status;
- PQUEUE_HEAD QueueHead;
- PVOID Base;
- ULONG ChainDescriptorLength;
- PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor, LastDescriptor;
-
- //
- // Allocate the queue head
- //
- Status = CreateQueueHead(&QueueHead);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to allocate queue head
- //
- DPRINT1("[EHCI] Failed to create queue head\n");
- return Status;
- }
-
- //
- // sanity checks
- //
- PC_ASSERT(QueueHead);
- PC_ASSERT(m_TransferBufferLength);
-
- if (!m_Base)
- {
- //
- // get virtual base of mdl
- //
- m_Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
- }
-
- //
- // Increase the size of last transfer, 0 in case this is the first
- //
- Base = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted);
-
- PC_ASSERT(m_EndpointDescriptor);
- PC_ASSERT(Base);
-
- //
- // sanity check
- //
- ASSERT(m_EndpointDescriptor);
-
- //
- // use 4 * PAGE_SIZE at max for each new request
- //
- ULONG MaxTransferLength = min(4 * PAGE_SIZE, m_TransferBufferLength -
m_TransferBufferLengthCompleted);
-
- //
- // build bulk transfer descriptor chain
- //
- Status = BuildTransferDescriptorChain(QueueHead,
- Base,
- MaxTransferLength,
- InternalGetPidDirection(),
- m_EndpointDescriptor->DataToggle,
- &FirstDescriptor,
- &LastDescriptor,
- &m_EndpointDescriptor->DataToggle,
- &ChainDescriptorLength);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to build transfer descriptor chain
- //
- DPRINT1("[EHCI] Failed to create descriptor chain\n");
- m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
- return Status;
- }
-
- //
- // move to next offset
- //
- m_TransferBufferLengthCompleted += ChainDescriptorLength;
-
- //
- // init queue head
- //
- QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
- QueueHead->EndPointCharacteristics.EndPointNumber =
m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F;
- QueueHead->EndPointCharacteristics.MaximumPacketLength =
m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
- QueueHead->NextPointer = FirstDescriptor->PhysicalAddr;
- QueueHead->CurrentLinkPointer = FirstDescriptor->PhysicalAddr;
- QueueHead->AlternateNextPointer = TERMINATE_POINTER;
-
- ASSERT(QueueHead->EndPointCharacteristics.DeviceAddress);
- ASSERT(QueueHead->EndPointCharacteristics.EndPointNumber);
- ASSERT(QueueHead->EndPointCharacteristics.MaximumPacketLength);
- ASSERT(QueueHead->NextPointer);
-
- //
- // interrupt on last descriptor
- //
- LastDescriptor->Token.Bits.InterruptOnComplete = TRUE;
-
- //
- // store result
- //
- *OutHead = QueueHead;
-
- //
- // dump status
- //
- //DumpQueueHead(QueueHead);
-
- //
- // done
- //
- return STATUS_SUCCESS;
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-STDMETHODCALLTYPE
-CUSBRequest::CreateDescriptor(
- PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor)
-{
- PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
- NTSTATUS Status;
- PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress;
-
- //
- // allocate descriptor
- //
- Status = m_DmaManager->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR),
(PVOID*)&Descriptor, &TransferDescriptorPhysicalAddress);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to allocate transfer descriptor
- //
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // initialize transfer descriptor
- //
- Descriptor->NextPointer = TERMINATE_POINTER;
- Descriptor->AlternateNextPointer = TERMINATE_POINTER;
- Descriptor->Token.Bits.DataToggle = TRUE;
- Descriptor->Token.Bits.ErrorCounter = 0x03;
- Descriptor->Token.Bits.Active = TRUE;
- Descriptor->PhysicalAddr = TransferDescriptorPhysicalAddress.LowPart;
-
- //
- // store result
- //
- *OutDescriptor = Descriptor;
-
- //
- // done
- //
- return Status;
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-CUSBRequest::CreateQueueHead(
- PQUEUE_HEAD *OutQueueHead)
-{
- PQUEUE_HEAD QueueHead;
- PHYSICAL_ADDRESS QueueHeadPhysicalAddress;
- NTSTATUS Status;
-
- //
- // allocate queue head
- //
- Status = m_DmaManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead,
&QueueHeadPhysicalAddress);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to allocate queue head
- //
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // initialize queue head
- //
- QueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
- QueueHead->AlternateNextPointer = TERMINATE_POINTER;
- QueueHead->NextPointer = TERMINATE_POINTER;
- InitializeListHead(&QueueHead->TransferDescriptorListHead);
-
- //
- // 1 for non high speed, 0 for high speed device
- //
- QueueHead->EndPointCharacteristics.ControlEndPointFlag = 0;
- QueueHead->EndPointCharacteristics.HeadOfReclamation = FALSE;
- QueueHead->EndPointCharacteristics.MaximumPacketLength = 64;
-
- //
- // Set NakCountReload to max value possible
- //
- QueueHead->EndPointCharacteristics.NakCountReload = 0x3;
-
- //
- // Get the Initial Data Toggle from the QEDT
- //
- QueueHead->EndPointCharacteristics.QEDTDataToggleControl = TRUE;
-
- //
- // FIXME: check if High Speed Device
- //
- QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
- QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x01;
- QueueHead->Token.DWord = 0;
- QueueHead->Token.Bits.InterruptOnComplete = FALSE;
-
- //
- // store address
- //
- QueueHead->PhysicalAddr = QueueHeadPhysicalAddress.LowPart;
-
- //
- // output queue head
- //
- *OutQueueHead = QueueHead;
-
- //
- // done
- //
- return STATUS_SUCCESS;
-}
-
-//----------------------------------------------------------------------------------------
-UCHAR
-STDMETHODCALLTYPE
-CUSBRequest::GetDeviceAddress()
-{
- PIO_STACK_LOCATION IoStack;
- PURB Urb;
- PUSBDEVICE UsbDevice;
-
- //
- // check if there is an irp provided
- //
- if (!m_Irp)
- {
- //
- // used provided address
- //
- return m_DeviceAddress;
- }
-
- //
- // get current stack location
- //
- IoStack = IoGetCurrentIrpStackLocation(m_Irp);
-
- //
- // get contained urb
- //
- Urb = (PURB)IoStack->Parameters.Others.Argument1;
-
- //
- // check if there is a pipe handle provided
- //
- if (Urb->UrbHeader.UsbdDeviceHandle)
- {
- //
- // there is a device handle provided
- //
- UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle;
-
- //
- // return device address
- //
- return UsbDevice->GetDeviceAddress();
- }
-
- //
- // no device handle provided, it is the host root bus
- //
- return 0;
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-CUSBRequest::BuildSetupPacket()
-{
- NTSTATUS Status;
-
- //
- // allocate common buffer setup packet
- //
- Status = m_DmaManager->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET),
(PVOID*)&m_DescriptorPacket, &m_DescriptorSetupPacket);
- if (!NT_SUCCESS(Status))
- {
- //
- // no memory
- //
- return Status;
- }
-
- if (m_SetupPacket)
- {
- //
- // copy setup packet
- //
- RtlCopyMemory(m_DescriptorPacket, m_SetupPacket,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
- }
- else
- {
- //
- // build setup packet from urb
- //
- Status = BuildSetupPacketFromURB();
- }
-
- //
- // done
- //
- return Status;
-}
-
-
-NTSTATUS
-CUSBRequest::BuildSetupPacketFromURB()
-{
- PIO_STACK_LOCATION IoStack;
- PURB Urb;
- NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-
- //
- // sanity checks
- //
- PC_ASSERT(m_Irp);
- PC_ASSERT(m_DescriptorPacket);
-
- //
- // get stack location
- //
- IoStack = IoGetCurrentIrpStackLocation(m_Irp);
-
- //
- // get urb
- //
- Urb = (PURB)IoStack->Parameters.Others.Argument1;
-
- //
- // zero descriptor packet
- //
- RtlZeroMemory(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
-
-
- 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:
- UNIMPLEMENTED;
- break;
-
- /* GET CONFIG */
- case URB_FUNCTION_GET_CONFIGURATION:
- m_DescriptorPacket->bRequest = USB_REQUEST_GET_CONFIGURATION;
- m_DescriptorPacket->bmRequestType.B = 0x80;
- m_DescriptorPacket->wLength = 1;
- break;
-
- /* GET DESCRIPTOR */
- case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
- m_DescriptorPacket->bRequest = USB_REQUEST_GET_DESCRIPTOR;
- m_DescriptorPacket->wValue.LowByte =
Urb->UrbControlDescriptorRequest.Index;
- m_DescriptorPacket->wValue.HiByte =
Urb->UrbControlDescriptorRequest.DescriptorType;
- m_DescriptorPacket->wIndex.W =
Urb->UrbControlDescriptorRequest.LanguageId;
- m_DescriptorPacket->wLength =
(USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
- m_DescriptorPacket->bmRequestType.B = 0x80;
- break;
-
- /* GET INTERFACE */
- case URB_FUNCTION_GET_INTERFACE:
- m_DescriptorPacket->bRequest = USB_REQUEST_GET_CONFIGURATION;
- m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
- m_DescriptorPacket->bmRequestType.B = 0x80;
- m_DescriptorPacket->wLength = 1;
- break;
-
- /* GET STATUS */
- case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
- m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS;
- ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
- m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
- m_DescriptorPacket->bmRequestType.B = 0x80;
- m_DescriptorPacket->wLength = 2;
- break;
-
- case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
- m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS;
- ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
- m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
- m_DescriptorPacket->bmRequestType.B = 0x81;
- m_DescriptorPacket->wLength = 2;
- break;
-
- case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
- m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS;
- ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
- m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
- m_DescriptorPacket->bmRequestType.B = 0x82;
- m_DescriptorPacket->wLength = 2;
- break;
-
- /* SET ADDRESS */
-
- /* SET CONFIG */
- case URB_FUNCTION_SELECT_CONFIGURATION:
- m_DescriptorPacket->bRequest = USB_REQUEST_SET_CONFIGURATION;
- m_DescriptorPacket->wValue.W =
Urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue;
- m_DescriptorPacket->wIndex.W = 0;
- m_DescriptorPacket->wLength = 0;
- m_DescriptorPacket->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:
- UNIMPLEMENTED;
- break;
-
- /* SET FEATURE */
- case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
- m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE;
- ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
- m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
- m_DescriptorPacket->bmRequestType.B = 0x80;
- break;
-
- case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
- m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE;
- ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
- m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
- m_DescriptorPacket->bmRequestType.B = 0x81;
- break;
-
- case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
- m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE;
- ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
- m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
- m_DescriptorPacket->bmRequestType.B = 0x82;
- break;
-
- /* SET INTERFACE*/
- case URB_FUNCTION_SELECT_INTERFACE:
- m_DescriptorPacket->bRequest = USB_REQUEST_SET_INTERFACE;
- m_DescriptorPacket->wValue.W =
Urb->UrbSelectInterface.Interface.AlternateSetting;
- m_DescriptorPacket->wIndex.W =
Urb->UrbSelectInterface.Interface.InterfaceNumber;
- m_DescriptorPacket->wLength = 0;
- m_DescriptorPacket->bmRequestType.B = 0x01;
- break;
-
- /* SYNC FRAME */
- case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
- UNIMPLEMENTED;
- break;
- default:
- UNIMPLEMENTED;
- break;
- }
-
- return Status;
-}
-
-//----------------------------------------------------------------------------------------
-VOID
-STDMETHODCALLTYPE
-CUSBRequest::GetResultStatus(
- OUT OPTIONAL NTSTATUS * NtStatusCode,
- OUT OPTIONAL PULONG UrbStatusCode)
-{
- //
- // sanity check
- //
- PC_ASSERT(m_CompletionEvent);
-
- //
- // wait for the operation to complete
- //
- KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL);
-
- //
- // copy status
- //
- if (NtStatusCode)
- {
- *NtStatusCode = m_NtStatusCode;
- }
-
- //
- // copy urb status
- //
- if (UrbStatusCode)
- {
- *UrbStatusCode = m_UrbStatusCode;
- }
-
-}
-
-//-----------------------------------------------------------------------------------------
-BOOLEAN
-STDMETHODCALLTYPE
-CUSBRequest::ShouldReleaseRequestAfterCompletion()
-{
- if (m_Irp)
- {
... 21788 lines suppressed ...