diff --git a/drivers/usb/usbehci_new/hardware.cpp b/drivers/usb/usbehci_new/hardware.cpp index 1b3fe8cf4df..37449102af0 100644 --- a/drivers/usb/usbehci_new/hardware.cpp +++ b/drivers/usb/usbehci_new/hardware.cpp @@ -52,7 +52,7 @@ public: NTSTATUS PnpStop(void); NTSTATUS HandlePower(PIRP Irp); NTSTATUS GetDeviceDetails(PUSHORT VendorId, PUSHORT DeviceId, PULONG NumberOfPorts, PULONG Speed); - NTSTATUS GetDmaAdapter(OUT PDMA_ADAPTER AdapterObject); + NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager); NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue); NTSTATUS StartController(); @@ -60,6 +60,10 @@ public: NTSTATUS ResetController(); NTSTATUS ResetPort(ULONG PortIndex); + NTSTATUS GetPortStatus(ULONG PortId, OUT USHORT *PortStatus, OUT USHORT *PortChange); + NTSTATUS ClearPortStatus(ULONG PortId, ULONG Status); + NTSTATUS SetPortFeature(ULONG PortId, ULONG Feature); + VOID SetAsyncListRegister(ULONG PhysicalAddress); VOID SetPeriodicListRegister(ULONG PhysicalAddress); @@ -85,6 +89,8 @@ protected: KSPIN_LOCK m_Lock; PKINTERRUPT m_Interrupt; KDPC m_IntDpcObject; + PVOID VirtualBase; + PHYSICAL_ADDRESS PhysicalAddress; PULONG m_Base; PDMA_ADAPTER m_Adapter; ULONG m_MapRegisters; @@ -92,7 +98,7 @@ protected: USHORT m_VendorID; USHORT m_DeviceID; PUSBQUEUE m_UsbQueue; - + PDMAMEMORYMANAGER m_MemoryManager; VOID SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd); VOID GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd); ULONG EHCI_READ_REGISTER_ULONG(ULONG Offset); @@ -132,6 +138,16 @@ CUSBHardwareDevice::Initialize( DPRINT1("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 // @@ -142,6 +158,16 @@ CUSBHardwareDevice::Initialize( return Status; } + // + // 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; + } + // // store device objects // @@ -336,6 +362,19 @@ CUSBHardwareDevice::PnpStart( 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; + } + // // Stop the controller before modifying schedules // @@ -395,14 +434,26 @@ CUSBHardwareDevice::GetDeviceDetails( return STATUS_SUCCESS; } +NTSTATUS CUSBHardwareDevice::GetDMA( + OUT struct IDMAMemoryManager **OutDMAMemoryManager) +{ + if (!m_MemoryManager) + return STATUS_UNSUCCESSFUL; + *OutDMAMemoryManager = m_MemoryManager; + return STATUS_SUCCESS; +} + NTSTATUS CUSBHardwareDevice::GetUSBQueue( OUT struct IUSBQueue **OutUsbQueue) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + if (!m_UsbQueue) + return STATUS_UNSUCCESSFUL; + *OutUsbQueue = m_UsbQueue; + return STATUS_SUCCESS; } + NTSTATUS CUSBHardwareDevice::StartController(void) { @@ -589,6 +640,140 @@ CUSBHardwareDevice::ResetPort( return STATUS_SUCCESS; } +NTSTATUS CUSBHardwareDevice::GetPortStatus( + ULONG PortId, + OUT USHORT *PortStatus, + OUT USHORT *PortChange) +{ + ULONG Value; + USHORT Status = 0, Change = 0; + + // + // 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 Speed. If SlowSpeedLine flag is there then its a slow speed device + if (Value & EHCI_PRT_SLOWSPEEDLINE) + Status |= USB_PORT_STATUS_LOW_SPEED; + else + Status |= USB_PORT_STATUS_HIGH_SPEED; + + // Get Connected Status + if (Value & EHCI_PRT_CONNECTED) + Status |= USB_PORT_STATUS_CONNECT; + + // 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) + Status |= USB_PORT_STATUS_RESET; + + // + // FIXME: Is the Change here correct? + // + if (Value & EHCI_PRT_CONNECTSTATUSCHANGE) + Change |= USB_PORT_STATUS_CONNECT; + + if (Value & EHCI_PRT_ENABLEDSTATUSCHANGE) + Change |= USB_PORT_STATUS_ENABLE; + + + return STATUS_SUCCESS; +} + +NTSTATUS CUSBHardwareDevice::ClearPortStatus( + ULONG PortId, + ULONG Status) +{ + ULONG Value; + + Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); + + if (Status == C_PORT_RESET) + { + if (Value & EHCI_PRT_RESET) + { + Value &= ~EHCI_PRT_RESET; + EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value); + KeStallExecutionProcessor(100); + } + } + + if (Status == C_PORT_CONNECTION) + { + // FIXME: Make sure its the Connection and Enable Change status. + Value |= EHCI_PRT_CONNECTSTATUSCHANGE; + Value |= EHCI_PRT_ENABLEDSTATUSCHANGE; + EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value); + } + + return STATUS_SUCCESS; +} + + +NTSTATUS CUSBHardwareDevice::SetPortFeature( + ULONG PortId, + ULONG Feature) +{ + ULONG Value; + + Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); + if (Feature == PORT_ENABLE) + { + // + // FIXME: EHCI Ports can only be disabled via reset + // + } + + if (Feature == PORT_RESET) + { + if (Value & EHCI_PRT_SLOWSPEEDLINE) + { + DPRINT1("Non HighSpeed device. Releasing Ownership\n"); + } + + // + // Reset and clean enable + // + Value |= EHCI_PRT_RESET; + Value &= ~EHCI_PRT_ENABLED; + EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value); + + KeStallExecutionProcessor(100); + } + + if (Feature == PORT_POWER) + DPRINT1("Not implemented\n"); + + return STATUS_SUCCESS; +} + VOID CUSBHardwareDevice::SetAsyncListRegister(ULONG PhysicalAddress) { EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, PhysicalAddress); @@ -693,12 +878,12 @@ EhciDefferedRoutine( // // Device connected or removed // - if (PortStatus & EHCI_PRT_CONNECTSTATUSCHAGE) + if (PortStatus & EHCI_PRT_CONNECTSTATUSCHANGE) { // // Clear the port change status // - This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), PortStatus & EHCI_PRT_CONNECTSTATUSCHAGE); + This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), PortStatus | EHCI_PRT_CONNECTSTATUSCHANGE); if (PortStatus & EHCI_PRT_CONNECTED) { diff --git a/drivers/usb/usbehci_new/hardware.h b/drivers/usb/usbehci_new/hardware.h index d2b83feea48..a6047caa5be 100644 --- a/drivers/usb/usbehci_new/hardware.h +++ b/drivers/usb/usbehci_new/hardware.h @@ -46,7 +46,7 @@ // Port Register Flags // #define EHCI_PRT_CONNECTED 0x01 -#define EHCI_PRT_CONNECTSTATUSCHAGE 0x02 +#define EHCI_PRT_CONNECTSTATUSCHANGE 0x02 #define EHCI_PRT_ENABLED 0x04 #define EHCI_PRT_ENABLEDSTATUSCHANGE 0x08 #define EHCI_PRT_OVERCURRENTACTIVE 0x10 @@ -192,7 +192,7 @@ typedef struct _QUEUE_HEAD LIST_ENTRY LinkedQueueHeads; PQUEUE_TRANSFER_DESCRIPTOR TransferDescriptor; PIRP IrpToComplete; - PMDL MdlToFree; + PMDL Mdl; PKEVENT Event; } QUEUE_HEAD, *PQUEUE_HEAD; diff --git a/drivers/usb/usbehci_new/hub_controller.cpp b/drivers/usb/usbehci_new/hub_controller.cpp index c1c3df128ff..05ca3abf971 100644 --- a/drivers/usb/usbehci_new/hub_controller.cpp +++ b/drivers/usb/usbehci_new/hub_controller.cpp @@ -157,20 +157,6 @@ const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] = 0xFF /* bInterval; (255ms -- usb 2.0 spec) */ }; -// -// flags for handling USB_REQUEST_SET_FEATURE / USB_REQUEST_GET_FEATURE -// -#define PORT_ENABLE 1 -#define PORT_SUSPEND 2 -#define PORT_OVER_CURRENT 3 -#define PORT_RESET 4 -#define PORT_POWER 8 -#define C_PORT_CONNECTION 16 -#define C_PORT_ENABLE 17 -#define C_PORT_SUSPEND 18 -#define C_PORT_OVER_CURRENT 19 -#define C_PORT_RESET 20 - //---------------------------------------------------------------------------------------- NTSTATUS STDMETHODCALLTYPE diff --git a/drivers/usb/usbehci_new/usb_queue.cpp b/drivers/usb/usbehci_new/usb_queue.cpp index 0ab6333c2df..5cc3eb599d0 100644 --- a/drivers/usb/usbehci_new/usb_queue.cpp +++ b/drivers/usb/usbehci_new/usb_queue.cpp @@ -48,14 +48,9 @@ protected: LONG m_Ref; KSPIN_LOCK m_Lock; PDMA_ADAPTER m_Adapter; - PVOID VirtualBase; - PHYSICAL_ADDRESS PhysicalAddress; PQUEUE_HEAD AsyncQueueHead; PQUEUE_HEAD PendingQueueHead; - IDMAMemoryManager *m_MemoryManager; - PQUEUE_HEAD CreateQueueHead(); - PQUEUE_TRANSFER_DESCRIPTOR CreateDescriptor(UCHAR PIDCode, ULONG TotalBytesToTransfer); VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead); VOID UnlinkQueueHead(PQUEUE_HEAD QueueHead); VOID LinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead); @@ -87,35 +82,11 @@ CUSBQueue::Initialize( PDMA_ADAPTER AdapterObject, IN OPTIONAL PKSPIN_LOCK Lock) { - NTSTATUS Status; + NTSTATUS Status = STATUS_SUCCESS; DPRINT1("CUSBQueue::Initialize()\n"); ASSERT(Hardware); - ASSERT(AdapterObject); - - // - // Create Common Buffer - // - VirtualBase = AdapterObject->DmaOperations->AllocateCommonBuffer(AdapterObject, - PAGE_SIZE * 4, - &PhysicalAddress, - FALSE); - if (!VirtualBase) - { - DPRINT1("Failed to allocate a common buffer\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // 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; - } // // initialize device lock @@ -123,46 +94,20 @@ CUSBQueue::Initialize( KeInitializeSpinLock(&m_Lock); // - // Initialize the DMAMemoryManager + // FIXME: Need to set AsyncRegister with a QUEUEHEAD // - Status = m_MemoryManager->Initialize(Hardware, &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 use in Async Register - // - AsyncQueueHead = CreateQueueHead(); - AsyncQueueHead->HorizontalLinkPointer = AsyncQueueHead->PhysicalAddr | QH_TYPE_QH; - AsyncQueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE; - AsyncQueueHead->Token.Bits.InterruptOnComplete = FALSE; - AsyncQueueHead->EndPointCharacteristics.HeadOfReclamation = TRUE; - AsyncQueueHead->Token.Bits.Halted = TRUE; - - Hardware->SetAsyncListRegister(AsyncQueueHead->PhysicalAddr); - - // - // Create a Unused QueueHead to hold pending QueueHeads - // - PendingQueueHead = CreateQueueHead(); - PendingQueueHead->Token.Bits.Halted = TRUE; - - // - // Initialize ListHead in QueueHeads - // - InitializeListHead(&AsyncQueueHead->LinkedQueueHeads); - InitializeListHead(&PendingQueueHead->LinkedQueueHeads); - - return STATUS_SUCCESS; + return Status; } ULONG CUSBQueue::GetPendingRequestCount() { - UNIMPLEMENTED + // + // Loop through the pending list and iterrate one for each QueueHead that + // has a IRP to complete. + // + + return 0; } @@ -197,84 +142,6 @@ CUSBQueue::CreateUSBRequest( return STATUS_NOT_IMPLEMENTED; } -PQUEUE_HEAD -CUSBQueue::CreateQueueHead() -{ - PQUEUE_HEAD QueueHead; - PHYSICAL_ADDRESS PhysicalAddress; - NTSTATUS Status; - // - // Create the QueueHead from Common Buffer - // - Status = m_MemoryManager->Allocate(sizeof(QUEUE_HEAD), - (PVOID*)&QueueHead, - &PhysicalAddress); - if (!NT_SUCCESS(Status)) - return NULL; - - // - // Initialize default values - // - - QueueHead->PhysicalAddr = PhysicalAddress.LowPart; - QueueHead->HorizontalLinkPointer = TERMINATE_POINTER; - QueueHead->AlternateNextPointer = TERMINATE_POINTER; - QueueHead->NextPointer = TERMINATE_POINTER; - - // 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 = 0xF; - - // Get the Initial Data Toggle from the Queue Element Desriptor - QueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE; - - QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED; - - QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x03; - - // Interrupt when QueueHead is processed - QueueHead->Token.Bits.InterruptOnComplete = FALSE; - - return QueueHead; -} - -PQUEUE_TRANSFER_DESCRIPTOR -CUSBQueue::CreateDescriptor( - UCHAR PIDCode, - ULONG TotalBytesToTransfer) -{ - PQUEUE_TRANSFER_DESCRIPTOR Descriptor; - PHYSICAL_ADDRESS PhysicalAddress; - NTSTATUS Status; - - // - // Create the Descriptor from Common Buffer - // - Status = m_MemoryManager->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR), - (PVOID*)&Descriptor, - &PhysicalAddress); - if (!NT_SUCCESS(Status)) - return NULL; - - // - // Set default values - // - Descriptor->NextPointer = TERMINATE_POINTER; - Descriptor->AlternateNextPointer = TERMINATE_POINTER; - Descriptor->Token.Bits.DataToggle = TRUE; - Descriptor->Token.Bits.ErrorCounter = 0x03; - Descriptor->Token.Bits.Active = TRUE; - Descriptor->Token.Bits.PIDCode = PIDCode; - Descriptor->Token.Bits.TotalBytesToTransfer = TotalBytesToTransfer; - Descriptor->PhysicalAddr = PhysicalAddress.LowPart; - - return Descriptor; -} - // // LinkQueueHead - Links one QueueHead to the end of HeadQueueHead list, updating HorizontalLinkPointer. // diff --git a/drivers/usb/usbehci_new/usbehci.h b/drivers/usb/usbehci_new/usbehci.h index 83fe7374e53..02e71cec51d 100644 --- a/drivers/usb/usbehci_new/usbehci.h +++ b/drivers/usb/usbehci_new/usbehci.h @@ -7,6 +7,10 @@ #include #include #include +// +// FIXME: +// #include +// #include #include #include @@ -21,6 +25,20 @@ #include "interfaces.h" +// +// flags for handling USB_REQUEST_SET_FEATURE / USB_REQUEST_GET_FEATURE +// +#define PORT_ENABLE 1 +#define PORT_SUSPEND 2 +#define PORT_OVER_CURRENT 3 +#define PORT_RESET 4 +#define PORT_POWER 8 +#define C_PORT_CONNECTION 16 +#define C_PORT_ENABLE 17 +#define C_PORT_SUSPEND 18 +#define C_PORT_OVER_CURRENT 19 +#define C_PORT_RESET 20 + typedef struct { BOOLEAN IsFDO; // is device a FDO or PDO