Author: janderwald
Date: Tue May 24 17:57:00 2011
New Revision: 51888
URL:
http://svn.reactos.org/svn/reactos?rev=51888&view=rev
Log:
[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)
Modified:
branches/usb-bringup/drivers/usb/usbohci/hardware.cpp
branches/usb-bringup/drivers/usb/usbohci/hardware.h
branches/usb-bringup/drivers/usb/usbohci/interfaces.h
branches/usb-bringup/drivers/usb/usbohci/usb_device.cpp
branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp
branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp
Modified: branches/usb-bringup/drivers/usb/usbohci/hardware.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/hardware.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/hardware.cpp [iso-8859-1] Tue May 24 17:57:00
2011
@@ -540,6 +540,7 @@
// 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 @@
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 @@
//
// 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)
@@ -1231,11 +1244,6 @@
{
//
// head completed
- //
- DPRINT1("InterruptServiceRoutine> Done Head completion\n");
- ASSERT(FALSE);
- //
- // FIXME: handle event
//
Acknowledge |= OHCI_WRITEBACK_DONE_HEAD;
}
@@ -1307,6 +1315,8 @@
{
CUSBHardwareDevice *This;
ULONG CStatus, Index, PortStatus;
+ POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+ ULONG DoneHead;
//
// get parameters
@@ -1314,6 +1324,25 @@
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)
{
//
Modified: branches/usb-bringup/drivers/usb/usbohci/hardware.h
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/hardware.h [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/hardware.h [iso-8859-1] Tue May 24 17:57:00
2011
@@ -202,8 +202,9 @@
// Software part
PHYSICAL_ADDRESS PhysicalAddress;
+ PVOID HeadLogicalDescriptor;
+ PVOID NextDescriptor;
PVOID Request;
- PVOID NextDescriptor;
}OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR;
@@ -238,9 +239,9 @@
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;
Modified: branches/usb-bringup/drivers/usb/usbohci/interfaces.h
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/interfaces.h [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/interfaces.h [iso-8859-1] Tue May 24 17:57:00
2011
@@ -436,6 +436,13 @@
virtual BOOLEAN IsRequestInitialized() = 0;
+//-----------------------------------------------------------------------------------------
+//
+// CompletionCallback
+//
+// Description: notifies request that the endpoint descriptor is complete
+
+ virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) =
0;
};
@@ -495,6 +502,14 @@
// Description: creates an usb request
virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// TransferDescriptorCompletionCallback
+//
+// Description: notifies the queue that a transfer was completed
+
+ virtual VOID TransferDescriptorCompletionCallback(ULONG
TransferDescriptorLogicalAddress) = 0;
};
Modified: branches/usb-bringup/drivers/usb/usbohci/usb_device.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/usb_device.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/usb_device.cpp [iso-8859-1] Tue May 24
17:57:00 2011
@@ -707,6 +707,11 @@
}
//
+ // zero buffer
+ //
+ RtlZeroMemory(Buffer, PAGE_SIZE);
+
+ //
// build setup packet
//
CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
Modified: branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp [iso-8859-1] Tue May 24
17:57:00 2011
@@ -33,11 +33,17 @@
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 @@
// 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 @@
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(
Modified: branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp [iso-8859-1] Tue May 24
17:57:00 2011
@@ -44,7 +44,7 @@
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 @@
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 @@
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 @@
//
// now create the data descriptor
//
- Status = CreateGeneralTransferDescriptor(&DataDescriptor, 0);
+ Status = CreateGeneralTransferDescriptor(&DataDescriptor,
m_TransferBufferLength);
if (!NT_SUCCESS(Status))
{
//
@@ -699,6 +715,7 @@
m_DmaManager->Release(EndpointDescriptor,
sizeof(OHCI_ENDPOINT_DESCRIPTOR));
FreeDescriptor(SetupDescriptor);
FreeDescriptor(StatusDescriptor);
+ FreeDescriptor(LastDescriptor);
return Status;
}
@@ -762,11 +779,20 @@
// link setup descriptor to data descriptor
//
SetupDescriptor->NextPhysicalDescriptor =
DataDescriptor->PhysicalAddress.LowPart;
-
- //
- // FIXME: should link to last data descriptor to status descriptor
+ SetupDescriptor->NextLogicalDescriptor = DataDescriptor;
+
+ //
+ // 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 @@
// 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 @@
}
+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()