https://git.reactos.org/?p=reactos.git;a=commitdiff;h=83c07f4e4c2a74e00c30db...
commit 83c07f4e4c2a74e00c30db18deee7ba092f44408 Author: Oleg Dubinskiy oleg.dubinskij2013@yandex.ua AuthorDate: Thu Jan 2 15:01:32 2020 +0200 Commit: Victor Perevertkin victor@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@reactos.org) - * Johannes Anderwald (johannes.anderwald@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@reactos.org) - * Johannes Anderwald (johannes.anderwald@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@reactos.org) - * Johannes Anderwald (johannes.anderwald@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 ...