mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[USBEHCI_NEW]
- Use LIST_ENTRY in QueueHeads and Descriptors vice Next and Previous Pointers. - Add functions to interface for setting AsyncListRegister and PeriodicListRegister. - USBHardwareDevice: Initialize USBQueue when handling PNPStart. - USBQueue: Allocate Common Buffer and use it to Create and Initialize DmaMemoryManager object. - USBQueue: Implement CreateQueueHead and CreateDescriptor. svn path=/branches/usb-bringup/; revision=51388
This commit is contained in:
parent
a2b99febfa
commit
9067f34e6f
4 changed files with 196 additions and 26 deletions
|
@ -60,7 +60,7 @@ public:
|
|||
NTSTATUS ResetController();
|
||||
NTSTATUS ResetPort(ULONG PortIndex);
|
||||
|
||||
VOID SetAsyncListAddressRegister(ULONG PhysicalAddress);
|
||||
VOID SetAsyncListRegister(ULONG PhysicalAddress);
|
||||
VOID SetPeriodicListRegister(ULONG PhysicalAddress);
|
||||
|
||||
KIRQL AcquireDeviceLock(void);
|
||||
|
@ -132,12 +132,16 @@ CUSBHardwareDevice::Initialize(
|
|||
|
||||
DPRINT1("CUSBHardwareDevice::Initialize\n");
|
||||
|
||||
//
|
||||
// Create the UsbQueue class that will handle the Asynchronous and Periodic Schedules
|
||||
//
|
||||
Status = CreateUSBQueue(&m_UsbQueue);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to create UsbQueue!\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// store device objects
|
||||
//
|
||||
|
@ -332,9 +336,27 @@ CUSBHardwareDevice::PnpStart(
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Stop the controller before modifying schedules
|
||||
//
|
||||
Status = StopController();
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
//
|
||||
// Initialize the UsbQueue now that we have an AdapterObject.
|
||||
//
|
||||
Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to Initialize the UsbQueue\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Start the controller
|
||||
//
|
||||
|
||||
DPRINT1("Starting Controller\n");
|
||||
return StartController();
|
||||
}
|
||||
|
@ -369,7 +391,7 @@ CUSBHardwareDevice::GetDeviceDetails(
|
|||
*NumberOfPorts = m_Capabilities.HCSParams.PortCount;
|
||||
//FIXME: What to returned here?
|
||||
if (Speed)
|
||||
*Speed = 0;
|
||||
*Speed = 0x200;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -477,6 +499,7 @@ CUSBHardwareDevice::StartController(void)
|
|||
// Set port routing to EHCI controller
|
||||
//
|
||||
EHCI_WRITE_REGISTER_ULONG(EHCI_CONFIGFLAG, 1);
|
||||
|
||||
DPRINT1("EHCI Started!\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -489,6 +512,7 @@ CUSBHardwareDevice::StopController(void)
|
|||
|
||||
//
|
||||
// Disable Interrupts and stop execution
|
||||
//
|
||||
EHCI_WRITE_REGISTER_ULONG (EHCI_USBINTR, 0);
|
||||
|
||||
GetCommandRegister(&UsbCmd);
|
||||
|
@ -565,25 +589,11 @@ CUSBHardwareDevice::ResetPort(
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
// SetAsyncListAddressRegister
|
||||
//
|
||||
// Description: this functions sets the register to a address that is the physical address of a QueueHead.
|
||||
// This is the location at which the controller will start executing the Asynchronous Schedule.
|
||||
//
|
||||
VOID CUSBHardwareDevice::SetAsyncListAddressRegister(ULONG PhysicalAddress)
|
||||
VOID CUSBHardwareDevice::SetAsyncListRegister(ULONG PhysicalAddress)
|
||||
{
|
||||
EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, PhysicalAddress);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
// SetPeriodicListRegister
|
||||
//
|
||||
// Description: this functions sets the register to a address that is the physical address of a ???.
|
||||
// This is the location at which the controller will start executing the Periodic Schedule.
|
||||
//
|
||||
VOID CUSBHardwareDevice::SetPeriodicListRegister(ULONG PhysicalAddress)
|
||||
{
|
||||
EHCI_WRITE_REGISTER_ULONG(EHCI_PERIODICLISTBASE, PhysicalAddress);
|
||||
|
|
|
@ -125,8 +125,7 @@ typedef struct _QUEUE_TRANSFER_DESCRIPTOR
|
|||
|
||||
//Software
|
||||
ULONG PhysicalAddr;
|
||||
struct _QUEUE_TRANSFER_DESCRIPTOR *PreviousDescriptor;
|
||||
struct _QUEUE_TRANSFER_DESCRIPTOR *NextDescriptor;
|
||||
LIST_ENTRY LinkedDescriptors;
|
||||
} QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
|
||||
|
||||
//
|
||||
|
@ -190,8 +189,7 @@ typedef struct _QUEUE_HEAD
|
|||
|
||||
//Software
|
||||
ULONG PhysicalAddr;
|
||||
struct _QUEUE_HEAD *PreviousQueueHead;
|
||||
struct _QUEUE_HEAD *NextQueueHead;
|
||||
LIST_ENTRY LinkedQueueHeads;
|
||||
PQUEUE_TRANSFER_DESCRIPTOR TransferDescriptor;
|
||||
PIRP IrpToComplete;
|
||||
PMDL MdlToFree;
|
||||
|
|
|
@ -209,6 +209,25 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown)
|
|||
//
|
||||
|
||||
virtual NTSTATUS ResetPort(ULONG PortNumber) = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
// SetAsyncListRegister
|
||||
//
|
||||
// Description: this functions sets the register to a address that is the physical address of a QueueHead.
|
||||
// This is the location at which the controller will start executing the Asynchronous Schedule.
|
||||
//
|
||||
// FIXME: This is only available for USB 2.0
|
||||
virtual VOID SetAsyncListRegister(ULONG PhysicalAddress) = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
// SetPeriodicListRegister
|
||||
//
|
||||
// Description: this functions sets the register to a address that is the physical address of a ???.
|
||||
// This is the location at which the controller will start executing the Periodic Schedule.
|
||||
//
|
||||
virtual VOID SetPeriodicListRegister(ULONG PhysicalAddress) = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -374,7 +393,7 @@ DECLARE_INTERFACE_(IUSBQueue, IUnknown)
|
|||
// Description: initializes the object
|
||||
|
||||
virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware,
|
||||
PADAPTER_OBJECT AdapterObject,
|
||||
PDMA_ADAPTER AdapterObject,
|
||||
IN OPTIONAL PKSPIN_LOCK Lock) = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
return m_Ref;
|
||||
}
|
||||
|
||||
NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, PADAPTER_OBJECT AdapterObject, IN OPTIONAL PKSPIN_LOCK Lock);
|
||||
NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, PDMA_ADAPTER AdapterObject, IN OPTIONAL PKSPIN_LOCK Lock);
|
||||
ULONG GetPendingRequestCount();
|
||||
NTSTATUS AddUSBRequest(PURB Urb);
|
||||
NTSTATUS AddUSBRequest(IUSBRequest * Request);
|
||||
|
@ -46,10 +46,16 @@ public:
|
|||
|
||||
protected:
|
||||
LONG m_Ref;
|
||||
KSPIN_LOCK m_Lock;
|
||||
PDMA_ADAPTER m_Adapter;
|
||||
PQUEUE_HEAD ExecutingList;
|
||||
PQUEUE_HEAD PendingList;
|
||||
PVOID VirtualBase;
|
||||
PHYSICAL_ADDRESS PhysicalAddress;
|
||||
PLIST_ENTRY ExecutingList;
|
||||
PLIST_ENTRY PendingList;
|
||||
IDMAMemoryManager *m_MemoryManager;
|
||||
|
||||
PQUEUE_HEAD CreateQueueHead();
|
||||
PQUEUE_TRANSFER_DESCRIPTOR CreateDescriptor(UCHAR PIDCode, ULONG TotalBytesToTransfer);
|
||||
};
|
||||
|
||||
//=================================================================================================
|
||||
|
@ -74,14 +80,33 @@ CUSBQueue::QueryInterface(
|
|||
NTSTATUS
|
||||
CUSBQueue::Initialize(
|
||||
IN PUSBHARDWAREDEVICE Hardware,
|
||||
PADAPTER_OBJECT AdapterObject,
|
||||
PDMA_ADAPTER AdapterObject,
|
||||
IN OPTIONAL PKSPIN_LOCK Lock)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PQUEUE_HEAD HeadQueueHead;
|
||||
|
||||
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))
|
||||
{
|
||||
|
@ -89,6 +114,50 @@ CUSBQueue::Initialize(
|
|||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// initialize device lock
|
||||
//
|
||||
KeInitializeSpinLock(&m_Lock);
|
||||
|
||||
//
|
||||
// Initialize the DMAMemoryManager
|
||||
//
|
||||
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 dead QueueHead for use in Async Register
|
||||
//
|
||||
HeadQueueHead = CreateQueueHead();
|
||||
HeadQueueHead->HorizontalLinkPointer = HeadQueueHead->PhysicalAddr | QH_TYPE_QH;
|
||||
HeadQueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
|
||||
HeadQueueHead->Token.Bits.InterruptOnComplete = FALSE;
|
||||
HeadQueueHead->EndPointCharacteristics.HeadOfReclamation = TRUE;
|
||||
HeadQueueHead->Token.Bits.Halted = TRUE;
|
||||
|
||||
Hardware->SetAsyncListRegister(HeadQueueHead->PhysicalAddr);
|
||||
|
||||
//
|
||||
// Set ExecutingList and create PendingList
|
||||
//
|
||||
ExecutingList = &HeadQueueHead->LinkedQueueHeads;
|
||||
PendingList = (PLIST_ENTRY) ExAllocatePool(NonPagedPool, sizeof(LIST_ENTRY));
|
||||
if (!PendingList)
|
||||
{
|
||||
DPRINT1("Pool allocation failed\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize ListHeads
|
||||
//
|
||||
InitializeListHead(ExecutingList);
|
||||
InitializeListHead(PendingList);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -130,6 +199,80 @@ 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CreateUSBQueue(
|
||||
PUSBQUEUE *OutUsbQueue)
|
||||
|
|
Loading…
Reference in a new issue