mirror of
https://github.com/reactos/reactos.git
synced 2024-10-05 00:43:21 +00:00
[USBOHCI]
- Add sanity checks - Preserve command status value when notifying the hc that a control / bulk endpoint was added - Re-enable root hub notification interrupt when reset port has been completed - Dispatch processing to USBQeueu when DoneHead event arrives - Scan endpoints to find the logical endpoint which was completed by the hardware - Signal completion to IUSBRequest by calling CompletionCallback - Create a final transfer descriptor which is linked to the endpoint descriptor - Control transfers now appear to be working (Device retrieves device descriptor / configuration descriptor and succeeds in setting device address) - Configuration parsing code needs more work now (currently fails there due to invalid / unexpected configuration descriptor from device) svn path=/branches/usb-bringup/; revision=51888
This commit is contained in:
parent
b275073474
commit
e24bfbfa91
|
@ -540,6 +540,7 @@ CUSBHardwareDevice::StartController(void)
|
|||
// assert that the controller has been started
|
||||
//
|
||||
ASSERT((Control & OHCI_HC_FUNCTIONAL_STATE_MASK) == OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL);
|
||||
ASSERT((Control & OHCI_ENABLE_LIST) == OHCI_ENABLE_LIST);
|
||||
|
||||
//
|
||||
// get frame interval
|
||||
|
@ -689,20 +690,30 @@ VOID
|
|||
CUSBHardwareDevice::HeadEndpointDescriptorModified(
|
||||
ULONG Type)
|
||||
{
|
||||
ULONG Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET));
|
||||
|
||||
if (Type == USB_ENDPOINT_TYPE_CONTROL)
|
||||
{
|
||||
//
|
||||
// notify controller
|
||||
//
|
||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), OHCI_CONTROL_LIST_FILLED);
|
||||
//WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_HEAD_ED_OFFSET), m_ControlEndpointDescriptor->NextPhysicalEndpoint);
|
||||
//WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_CURRENT_ED_OFFSET), m_ControlEndpointDescriptor->NextPhysicalEndpoint);
|
||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), Value | OHCI_CONTROL_LIST_FILLED);
|
||||
}
|
||||
else if (Type == USB_ENDPOINT_TYPE_BULK)
|
||||
{
|
||||
//
|
||||
// notify controller
|
||||
//
|
||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), OHCI_BULK_LIST_FILLED);
|
||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), Value | OHCI_BULK_LIST_FILLED);
|
||||
}
|
||||
|
||||
Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET));
|
||||
|
||||
|
||||
DPRINT1("HeadEndpointDescriptorModified Value %x Type %x\n", Value, Type);
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -1035,7 +1046,9 @@ CUSBHardwareDevice::ClearPortStatus(
|
|||
//
|
||||
// re-enable root hub change
|
||||
//
|
||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET), OHCI_ROOT_HUB_STATUS_CHANGE);
|
||||
Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET));
|
||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET), Value | OHCI_ROOT_HUB_STATUS_CHANGE);
|
||||
|
||||
}
|
||||
|
||||
if (Status == C_PORT_CONNECTION)
|
||||
|
@ -1232,11 +1245,6 @@ InterruptServiceRoutine(
|
|||
//
|
||||
// head completed
|
||||
//
|
||||
DPRINT1("InterruptServiceRoutine> Done Head completion\n");
|
||||
ASSERT(FALSE);
|
||||
//
|
||||
// FIXME: handle event
|
||||
//
|
||||
Acknowledge |= OHCI_WRITEBACK_DONE_HEAD;
|
||||
}
|
||||
|
||||
|
@ -1307,6 +1315,8 @@ OhciDefferedRoutine(
|
|||
{
|
||||
CUSBHardwareDevice *This;
|
||||
ULONG CStatus, Index, PortStatus;
|
||||
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||
ULONG DoneHead;
|
||||
|
||||
//
|
||||
// get parameters
|
||||
|
@ -1314,6 +1324,25 @@ OhciDefferedRoutine(
|
|||
This = (CUSBHardwareDevice*) SystemArgument1;
|
||||
CStatus = (ULONG) SystemArgument2;
|
||||
|
||||
DPRINT1("OhciDefferedRoutine Status %x\n", CStatus);
|
||||
|
||||
if (CStatus & OHCI_WRITEBACK_DONE_HEAD)
|
||||
{
|
||||
//
|
||||
// descriptor completion, get done head
|
||||
//
|
||||
DoneHead = This->m_HCCA->DoneHead;
|
||||
|
||||
//
|
||||
// clear out lower bits, ed are 16 byte aligned
|
||||
//
|
||||
DoneHead &= ~0xF;
|
||||
|
||||
//
|
||||
// notify queue of event
|
||||
//
|
||||
This->m_UsbQueue->TransferDescriptorCompletionCallback(DoneHead);
|
||||
}
|
||||
if (CStatus & OHCI_ROOT_HUB_STATUS_CHANGE)
|
||||
{
|
||||
//
|
||||
|
|
|
@ -202,8 +202,9 @@ typedef struct _OHCI_ENDPOINT_DESCRIPTOR
|
|||
|
||||
// Software part
|
||||
PHYSICAL_ADDRESS PhysicalAddress;
|
||||
PVOID Request;
|
||||
PVOID HeadLogicalDescriptor;
|
||||
PVOID NextDescriptor;
|
||||
PVOID Request;
|
||||
}OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR;
|
||||
|
||||
|
||||
|
@ -238,9 +239,9 @@ typedef struct
|
|||
ULONG LastPhysicalByteAddress; // Physical pointer to buffer end
|
||||
// Software part
|
||||
PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this descriptor
|
||||
PVOID NextLogicalDescriptor;
|
||||
ULONG BufferSize; // Size of the buffer
|
||||
PVOID BufferLogical; // Logical pointer to the buffer
|
||||
PVOID Request; // pointer to IUSBRequest
|
||||
}OHCI_GENERAL_TD, *POHCI_GENERAL_TD;
|
||||
|
||||
|
||||
|
|
|
@ -436,6 +436,13 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
|||
|
||||
virtual BOOLEAN IsRequestInitialized() = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
// CompletionCallback
|
||||
//
|
||||
// Description: notifies request that the endpoint descriptor is complete
|
||||
|
||||
virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -496,6 +503,14 @@ DECLARE_INTERFACE_(IUSBQueue, IUnknown)
|
|||
|
||||
virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest) = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
// TransferDescriptorCompletionCallback
|
||||
//
|
||||
// Description: notifies the queue that a transfer was completed
|
||||
|
||||
virtual VOID TransferDescriptorCompletionCallback(ULONG TransferDescriptorLogicalAddress) = 0;
|
||||
|
||||
};
|
||||
|
||||
typedef IUSBQueue *PUSBQUEUE;
|
||||
|
|
|
@ -706,6 +706,11 @@ CUSBDevice::CreateConfigurationDescriptor(
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// zero buffer
|
||||
//
|
||||
RtlZeroMemory(Buffer, PAGE_SIZE);
|
||||
|
||||
//
|
||||
// build setup packet
|
||||
//
|
||||
|
|
|
@ -33,11 +33,17 @@ public:
|
|||
return m_Ref;
|
||||
}
|
||||
|
||||
// com
|
||||
virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, PDMA_ADAPTER AdapterObject, IN PDMAMEMORYMANAGER MemManager, IN OPTIONAL PKSPIN_LOCK Lock);
|
||||
virtual ULONG GetPendingRequestCount();
|
||||
virtual NTSTATUS AddUSBRequest(IUSBRequest * Request);
|
||||
virtual NTSTATUS CancelRequests();
|
||||
virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest);
|
||||
virtual VOID TransferDescriptorCompletionCallback(ULONG TransferDescriptorLogicalAddress);
|
||||
|
||||
// local functions
|
||||
BOOLEAN IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress);
|
||||
NTSTATUS FindTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor);
|
||||
|
||||
// constructor / destructor
|
||||
CUSBQueue(IUnknown *OuterUnknown){}
|
||||
|
@ -218,13 +224,14 @@ CUSBQueue::AddUSBRequest(
|
|||
// set descriptor active
|
||||
//
|
||||
Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
|
||||
//HeadDescriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
|
||||
|
||||
//
|
||||
// notify hardware of our request
|
||||
//
|
||||
m_Hardware->HeadEndpointDescriptorModified(Type);
|
||||
|
||||
DPRINT1("Request added to queue\n");
|
||||
DPRINT1("Request %x %x added to queue\n", Descriptor, Descriptor->PhysicalAddress);
|
||||
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -255,6 +262,142 @@ CUSBQueue::CreateUSBRequest(
|
|||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CUSBQueue::FindTransferDescriptorInEndpoint(
|
||||
IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor,
|
||||
IN ULONG TransferDescriptorLogicalAddress,
|
||||
OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor,
|
||||
OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor)
|
||||
{
|
||||
POHCI_ENDPOINT_DESCRIPTOR LastDescriptor = EndpointDescriptor;
|
||||
|
||||
|
||||
//
|
||||
// skip first endpoint head
|
||||
//
|
||||
EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor;
|
||||
|
||||
while(EndpointDescriptor)
|
||||
{
|
||||
//
|
||||
// check if the transfer descriptor is inside the list
|
||||
//
|
||||
if (IsTransferDescriptorInEndpoint(EndpointDescriptor, TransferDescriptorLogicalAddress))
|
||||
{
|
||||
//
|
||||
// found endpoint
|
||||
//
|
||||
*OutEndpointDescriptor = EndpointDescriptor;
|
||||
*OutPreviousEndpointDescriptor = LastDescriptor;
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// store last endpoint
|
||||
//
|
||||
LastDescriptor = EndpointDescriptor;
|
||||
|
||||
//
|
||||
// move to next
|
||||
//
|
||||
EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor;
|
||||
}
|
||||
|
||||
//
|
||||
// failed to endpoint
|
||||
//
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
CUSBQueue::IsTransferDescriptorInEndpoint(
|
||||
IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor,
|
||||
IN ULONG TransferDescriptorLogicalAddress)
|
||||
{
|
||||
POHCI_GENERAL_TD Descriptor;
|
||||
|
||||
//
|
||||
// get first general transfer descriptor
|
||||
//
|
||||
Descriptor = (POHCI_GENERAL_TD)EndpointDescriptor->HeadLogicalDescriptor;
|
||||
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(Descriptor);
|
||||
|
||||
do
|
||||
{
|
||||
if (Descriptor->PhysicalAddress.LowPart == TransferDescriptorLogicalAddress)
|
||||
{
|
||||
//
|
||||
// found descriptor
|
||||
//
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// move to next
|
||||
//
|
||||
Descriptor = (POHCI_GENERAL_TD)Descriptor->NextLogicalDescriptor;
|
||||
}while(Descriptor);
|
||||
|
||||
|
||||
//
|
||||
// no descriptor found
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CUSBQueue::TransferDescriptorCompletionCallback(
|
||||
ULONG TransferDescriptorLogicalAddress)
|
||||
{
|
||||
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
|
||||
NTSTATUS Status;
|
||||
PUSBREQUEST Request;
|
||||
|
||||
//
|
||||
// find transfer descriptor in control list
|
||||
//
|
||||
Status = FindTransferDescriptorInEndpoint(m_ControlHeadEndpointDescriptor, TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// FIXME: make sure this is ok
|
||||
// unlink descriptor
|
||||
//
|
||||
PreviousEndpointDescriptor->NextDescriptor = EndpointDescriptor->NextDescriptor;
|
||||
PreviousEndpointDescriptor->NextPhysicalEndpoint = EndpointDescriptor->NextPhysicalEndpoint;
|
||||
|
||||
//
|
||||
// get corresponding request
|
||||
//
|
||||
Request = PUSBREQUEST(EndpointDescriptor->Request);
|
||||
|
||||
//
|
||||
// notify of completion
|
||||
//
|
||||
Request->CompletionCallback(EndpointDescriptor);
|
||||
|
||||
//
|
||||
// FIXME: check if complete
|
||||
//
|
||||
|
||||
//
|
||||
// release request
|
||||
//
|
||||
Request->Release();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CreateUSBQueue(
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode);
|
||||
virtual BOOLEAN IsRequestInitialized();
|
||||
virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
|
||||
|
||||
virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
|
||||
|
||||
// local functions
|
||||
ULONG InternalGetTransferType();
|
||||
|
@ -635,7 +635,7 @@ NTSTATUS
|
|||
CUSBRequest::BuildControlTransferDescriptor(
|
||||
POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
|
||||
{
|
||||
POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL;
|
||||
POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL, LastDescriptor;
|
||||
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||
NTSTATUS Status;
|
||||
|
||||
|
@ -680,6 +680,22 @@ CUSBRequest::BuildControlTransferDescriptor(
|
|||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// finally create the last descriptor
|
||||
//
|
||||
Status = CreateGeneralTransferDescriptor(&LastDescriptor, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to create status descriptor
|
||||
//
|
||||
FreeDescriptor(SetupDescriptor);
|
||||
FreeDescriptor(StatusDescriptor);
|
||||
m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
if (m_TransferBufferLength)
|
||||
{
|
||||
//
|
||||
|
@ -690,7 +706,7 @@ CUSBRequest::BuildControlTransferDescriptor(
|
|||
//
|
||||
// now create the data descriptor
|
||||
//
|
||||
Status = CreateGeneralTransferDescriptor(&DataDescriptor, 0);
|
||||
Status = CreateGeneralTransferDescriptor(&DataDescriptor, m_TransferBufferLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
|
@ -699,6 +715,7 @@ CUSBRequest::BuildControlTransferDescriptor(
|
|||
m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
|
||||
FreeDescriptor(SetupDescriptor);
|
||||
FreeDescriptor(StatusDescriptor);
|
||||
FreeDescriptor(LastDescriptor);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -762,11 +779,20 @@ CUSBRequest::BuildControlTransferDescriptor(
|
|||
// link setup descriptor to data descriptor
|
||||
//
|
||||
SetupDescriptor->NextPhysicalDescriptor = DataDescriptor->PhysicalAddress.LowPart;
|
||||
SetupDescriptor->NextLogicalDescriptor = DataDescriptor;
|
||||
|
||||
//
|
||||
// FIXME: should link to last data descriptor to status descriptor
|
||||
// link data descriptor to status descriptor
|
||||
// FIXME: check if there are more data descriptors
|
||||
//
|
||||
DataDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
|
||||
DataDescriptor->NextLogicalDescriptor = StatusDescriptor;
|
||||
|
||||
//
|
||||
// link status descriptor to last descriptor
|
||||
//
|
||||
StatusDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
|
||||
StatusDescriptor->NextLogicalDescriptor = LastDescriptor;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -774,14 +800,21 @@ CUSBRequest::BuildControlTransferDescriptor(
|
|||
// link setup descriptor to status descriptor
|
||||
//
|
||||
SetupDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
|
||||
SetupDescriptor->NextLogicalDescriptor = StatusDescriptor;
|
||||
|
||||
//
|
||||
// link status descriptor to last descriptor
|
||||
//
|
||||
StatusDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
|
||||
StatusDescriptor->NextLogicalDescriptor = LastDescriptor;
|
||||
}
|
||||
|
||||
//
|
||||
// now link descriptor to endpoint
|
||||
//
|
||||
EndpointDescriptor->HeadPhysicalDescriptor = SetupDescriptor->PhysicalAddress.LowPart;
|
||||
EndpointDescriptor->TailPhysicalDescriptor = SetupDescriptor->PhysicalAddress.LowPart;
|
||||
DPRINT1("CUSBRequest::BuildControlTransferDescriptor done\n");
|
||||
EndpointDescriptor->TailPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
|
||||
EndpointDescriptor->HeadLogicalDescriptor = SetupDescriptor;
|
||||
|
||||
//
|
||||
// store result
|
||||
|
@ -887,6 +920,32 @@ CUSBRequest::GetResultStatus(
|
|||
}
|
||||
|
||||
|
||||
VOID
|
||||
CUSBRequest::CompletionCallback(
|
||||
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
|
||||
{
|
||||
DPRINT1("CUSBRequest::CompletionCallback\n");
|
||||
|
||||
//
|
||||
// set status code
|
||||
//
|
||||
m_NtStatusCode = STATUS_SUCCESS;
|
||||
m_UrbStatusCode = USBD_STATUS_SUCCESS;
|
||||
|
||||
ASSERT(!m_Irp);
|
||||
|
||||
//
|
||||
// FIXME: cleanup descriptors
|
||||
//
|
||||
|
||||
//
|
||||
// signal completion event
|
||||
//
|
||||
PC_ASSERT(m_CompletionEvent);
|
||||
KeSetEvent(m_CompletionEvent, 0, FALSE);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
BOOLEAN
|
||||
CUSBRequest::IsRequestInitialized()
|
||||
|
|
Loading…
Reference in a new issue