Author: janderwald
Date: Mon May 23 17:42:52 2011
New Revision: 51864
URL:
http://svn.reactos.org/svn/reactos?rev=51864&view=rev
Log:
[USBOHCI]
- Start implementing control transfers
- Move initialization of usb queue after the bulk / control head endpoints have been
created
- Add interface functions to retrieve bulk / control head endpoint descriptors
- Add macros for setting transfer descriptors field (taken from Haiku)
- Partly implement IUSBQueue::AddUSBRequest for control / bulk transfers
- Create endpoint descriptor for control request and link setup descriptor to it
- Link setup descriptors to data descriptor / status descriptor
- WIP (needs fixes)
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_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] Mon May 23 17:42:52
2011
@@ -59,6 +59,10 @@
NTSTATUS PnpStop(void);
NTSTATUS HandlePower(PIRP Irp);
NTSTATUS GetDeviceDetails(PUSHORT VendorId, PUSHORT DeviceId, PULONG NumberOfPorts,
PULONG Speed);
+ NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR **
OutDescriptor);
+ NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR **
OutDescriptor);
+ VOID HeadEndpointDescriptorModified(ULONG HeadType);
+
NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager);
NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue);
@@ -360,23 +364,23 @@
}
//
+ // initializes the controller
+ //
+ Status = InitializeController();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to Initialize the controller \n");
+ ASSERT(FALSE);
+ return Status;
+ }
+
+ //
// Initialize the UsbQueue now that we have an AdapterObject.
//
Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter,
m_MemoryManager, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to Initialize the UsbQueue\n");
- return Status;
- }
-
- //
- // initializes the controller
- //
- Status = InitializeController();
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to Initialize the controller \n");
- ASSERT(FALSE);
return Status;
}
@@ -628,6 +632,42 @@
//
// done
//
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBHardwareDevice::GetBulkHeadEndpointDescriptor(
+ struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
+{
+ *OutDescriptor = m_BulkEndpointDescriptor;
+ return STATUS_SUCCESS;
+}
+
+VOID
+CUSBHardwareDevice::HeadEndpointDescriptorModified(
+ ULONG Type)
+{
+ if (Type == USB_ENDPOINT_TYPE_CONTROL)
+ {
+ //
+ // notify controller
+ //
+ WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET),
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);
+ }
+}
+
+NTSTATUS
+CUSBHardwareDevice::GetControlHeadEndpointDescriptor(
+ struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
+{
+ *OutDescriptor = m_ControlEndpointDescriptor;
return STATUS_SUCCESS;
}
@@ -1128,7 +1168,7 @@
// head completed
//
DPRINT1("InterruptServiceRoutine> Done Head completion\n");
-
+ ASSERT(FALSE);
//
// FIXME: handle event
//
@@ -1148,9 +1188,11 @@
if (Status & OHCI_UNRECOVERABLE_ERROR)
{
DPRINT1("InterruptServiceRoutine> Controller error\n");
+
//
// halt controller
//
+ ASSERT(FALSE);
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_CONTROL_OFFSET),
OHCI_HC_FUNCTIONAL_STATE_RESET);
}
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] Mon May 23 17:42:52
2011
@@ -192,7 +192,7 @@
#define OHCI_PAGE_OFFSET(x) ((x) & 0xfff)
-typedef struct
+typedef struct _OHCI_ENDPOINT_DESCRIPTOR
{
// Hardware part
ULONG Flags;
@@ -202,10 +202,19 @@
// Software part
PHYSICAL_ADDRESS PhysicalAddress;
+ PVOID Request;
+ PVOID NextDescriptor;
}OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR;
#define OHCI_ENDPOINT_SKIP 0x00004000
+#define OHCI_ENDPOINT_SET_DEVICE_ADDRESS(s) (s)
+#define OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(s) (((s) >> 7) & 0xf)
+#define OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(s) ((s) << 7)
+#define OHCI_ENDPOINT_GET_MAX_PACKET_SIZE(s) (((s) >> 16) & 0x07ff)
+#define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s) ((s) << 16)
+#define OHCI_ENDPOINT_LOW_SPEED 0x00002000
+#define OHCI_ENDPOINT_FULL_SPEED 0x00000000
//
// Maximum port count set by OHCI
@@ -220,15 +229,51 @@
}OHCI_PORT_STATUS;
-typedef struct {
+typedef struct
+{
// Hardware part 16 bytes
- uint32 flags; // Flags field
- uint32 buffer_physical; // Physical buffer pointer
- uint32 next_physical_descriptor; // Physical pointer next descriptor
- uint32 last_physical_byte_address; // Physical pointer to buffer end
+ ULONG Flags; // Flags field
+ ULONG BufferPhysical; // Physical buffer pointer
+ ULONG NextPhysicalDescriptor; // Physical pointer next descriptor
+ ULONG LastPhysicalByteAddress; // Physical pointer to buffer end
// Software part
- addr_t physical_address; // Physical address of this descriptor
- size_t buffer_size; // Size of the buffer
- void *buffer_logical; // Logical pointer to the buffer
- void *next_logical_descriptor; // Logical pointer next descriptor
-} ohci_general_td;
+ PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this descriptor
+ ULONG BufferSize; // Size of the buffer
+ PVOID BufferLogical; // Logical pointer to the buffer
+ PVOID Request; // pointer to IUSBRequest
+}OHCI_GENERAL_TD, *POHCI_GENERAL_TD;
+
+
+#define OHCI_TD_BUFFER_ROUNDING 0x00040000
+#define OHCI_TD_DIRECTION_PID_MASK 0x00180000
+#define OHCI_TD_DIRECTION_PID_SETUP 0x00000000
+#define OHCI_TD_DIRECTION_PID_OUT 0x00080000
+#define OHCI_TD_DIRECTION_PID_IN 0x00100000
+#define OHCI_TD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7)
+#define OHCI_TD_SET_DELAY_INTERRUPT(x) ((x) << 21)
+#define OHCI_TD_INTERRUPT_MASK 0x00e00000
+#define OHCI_TD_TOGGLE_CARRY 0x00000000
+#define OHCI_TD_TOGGLE_0 0x02000000
+#define OHCI_TD_TOGGLE_1 0x03000000
+#define OHCI_TD_TOGGLE_MASK 0x03000000
+#define OHCI_TD_GET_ERROR_COUNT(x) (((x) >> 26) & 3)
+#define OHCI_TD_GET_CONDITION_CODE(x) ((x) >> 28)
+#define OHCI_TD_SET_CONDITION_CODE(x) ((x) << 28)
+#define OHCI_TD_CONDITION_CODE_MASK 0xf0000000
+
+#define OHCI_TD_INTERRUPT_IMMEDIATE 0x00
+#define OHCI_TD_INTERRUPT_NONE 0x07
+
+#define OHCI_TD_CONDITION_NO_ERROR 0x00
+#define OHCI_TD_CONDITION_CRC_ERROR 0x01
+#define OHCI_TD_CONDITION_BIT_STUFFING 0x02
+#define OHCI_TD_CONDITION_TOGGLE_MISMATCH 0x03
+#define OHCI_TD_CONDITION_STALL 0x04
+#define OHCI_TD_CONDITION_NO_RESPONSE 0x05
+#define OHCI_TD_CONDITION_PID_CHECK_FAILURE 0x06
+#define OHCI_TD_CONDITION_UNEXPECTED_PID 0x07
+#define OHCI_TD_CONDITION_DATA_OVERRUN 0x08
+#define OHCI_TD_CONDITION_DATA_UNDERRUN 0x09
+#define OHCI_TD_CONDITION_BUFFER_OVERRUN 0x0c
+#define OHCI_TD_CONDITION_BUFFER_UNDERRUN 0x0d
+#define OHCI_TD_CONDITION_NOT_ACCESSED 0x0f
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] Mon May 23 17:42:52
2011
@@ -107,7 +107,7 @@
typedef IHCDController *PHCDCONTROLLER;
-
+struct _OHCI_ENDPOINT_DESCRIPTOR;
//=========================================================================================
//
// class IUSBHardwareDevice
@@ -171,6 +171,33 @@
// Do not call Initialize on IUSBQueue, the object is already initialized
virtual NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetBulkHeadEndpointDescriptor
+//
+// Description: returns the bulk head endpoint descriptor
+
+ virtual NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR **
OutDescriptor) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetControlHeadEndpointDescriptor
+//
+// Description: returns the control head endpoint descriptor
+
+ virtual NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR **
OutDescriptor) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// HeadEndpointDescriptorModified
+//
+// Description: notifies the hardware that an endpoint descriptor was added to head
endpoint descriptor
+
+ virtual VOID HeadEndpointDescriptorModified(ULONG HeadType) = 0;
+
+
+
//-----------------------------------------------------------------------------------------
//
@@ -334,8 +361,6 @@
// CancelCallback routine is invoked.
//
-struct _QUEUE_HEAD;
-
DECLARE_INTERFACE_(IUSBRequest, IUnknown)
{
DEFINE_ABSTRACT_UNKNOWN()
@@ -387,6 +412,14 @@
//-----------------------------------------------------------------------------------------
//
+// GetEndpointDescriptor
+//
+// Description: returns the general transfer descriptor
+
+ virtual NTSTATUS GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR **
OutDescriptor) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
// GetResultStatus
//
// Description: returns the status code of the result
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] Mon May 23
17:42:52 2011
@@ -46,6 +46,9 @@
protected:
LONG m_Ref;
// reference count
KSPIN_LOCK m_Lock;
// list lock
+ PUSBHARDWAREDEVICE m_Hardware;
// hardware
+ POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor;
// bulk head descriptor
+ POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor;
// control head descriptor
};
//=================================================================================================
@@ -74,7 +77,26 @@
IN PDMAMEMORYMANAGER MemManager,
IN OPTIONAL PKSPIN_LOCK Lock)
{
- UNIMPLEMENTED
+ //
+ // get bulk endpoint descriptor
+ //
+ Hardware->GetBulkHeadEndpointDescriptor(&m_BulkHeadEndpointDescriptor);
+
+ //
+ // get control endpoint descriptor
+ //
+ Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor);
+
+ //
+ // initialize spinlock
+ //
+ KeInitializeSpinLock(&m_Lock);
+
+ //
+ // store hardware
+ //
+ m_Hardware = Hardware;
+
return STATUS_SUCCESS;
}
@@ -96,6 +118,10 @@
NTSTATUS Status;
ULONG Type;
KIRQL OldLevel;
+ POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
+ POHCI_ENDPOINT_DESCRIPTOR Descriptor;
+
+ DPRINT1("CUSBQueue::AddUSBRequest\n");
//
// sanity check
@@ -143,6 +169,63 @@
//
Request->AddRef();
+ //
+ // get transfer descriptors
+ //
+ Status = Request->GetEndpointDescriptor(&Descriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get transfer descriptor
+ //
+ DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with
%x\n", Status);
+
+ //
+ // release reference
+ //
+ Request->Release();
+ return Status;
+ }
+
+ //
+ // check type
+ //
+ if (Type == USB_ENDPOINT_TYPE_BULK)
+ {
+ //
+ // get head descriptor
+ //
+ HeadDescriptor = m_BulkHeadEndpointDescriptor;
+ }
+ else if (Type == USB_ENDPOINT_TYPE_CONTROL)
+ {
+ //
+ // get head descriptor
+ //
+ HeadDescriptor = m_ControlHeadEndpointDescriptor;
+ }
+
+ //
+ // link endpoints
+ //
+ Descriptor->NextPhysicalEndpoint = HeadDescriptor->NextPhysicalEndpoint;
+ Descriptor->NextDescriptor = HeadDescriptor->NextDescriptor;
+
+ HeadDescriptor->NextPhysicalEndpoint = Descriptor->PhysicalAddress.LowPart;
+ HeadDescriptor->NextDescriptor = Descriptor;
+
+ //
+ // set descriptor active
+ //
+ Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
+
+ //
+ // notify hardware of our request
+ //
+ m_Hardware->HeadEndpointDescriptorModified(Type);
+
+ DPRINT1("Request added to queue\n");
+
return STATUS_SUCCESS;
}
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] Mon May 23
17:42:52 2011
@@ -40,6 +40,7 @@
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP
Irp);
virtual BOOLEAN IsRequestComplete();
virtual ULONG GetTransferType();
+ virtual NTSTATUS GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR **
OutEndpointDescriptor);
virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG
UrbStatusCode);
virtual BOOLEAN IsRequestInitialized();
virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
@@ -51,6 +52,12 @@
UCHAR GetDeviceAddress();
NTSTATUS BuildSetupPacket();
NTSTATUS BuildSetupPacketFromURB();
+ NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR *
OutEndpointDescriptor);
+ NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, ULONG
BufferSize);
+ VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor);
+ NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor);
+ UCHAR GetEndpointAddress();
+ USHORT GetMaxPacketSize();
// constructor / destructor
CUSBRequest(IUnknown *OuterUnknown){}
@@ -348,6 +355,46 @@
return InternalGetTransferType();
}
+USHORT
+CUSBRequest::GetMaxPacketSize()
+{
+ if (!m_EndpointDescriptor)
+ {
+ //
+ // control request
+ //
+ return 0;
+ }
+
+ ASSERT(m_Irp);
+ ASSERT(m_EndpointDescriptor);
+
+ //
+ // return max packet size
+ //
+ return m_EndpointDescriptor->wMaxPacketSize;
+}
+
+UCHAR
+CUSBRequest::GetEndpointAddress()
+{
+ if (!m_EndpointDescriptor)
+ {
+ //
+ // control request
+ //
+ return 0;
+ }
+
+ ASSERT(m_Irp);
+ ASSERT(m_EndpointDescriptor);
+
+ //
+ // endpoint number is between 1-15
+ //
+ return (m_EndpointDescriptor->bEndpointAddress & 0xF);
+}
+
//----------------------------------------------------------------------------------------
ULONG
CUSBRequest::InternalGetTransferType()
@@ -444,9 +491,366 @@
return 0;
}
-
-
-
+VOID
+CUSBRequest::FreeDescriptor(
+ POHCI_GENERAL_TD Descriptor)
+{
+ if (Descriptor->BufferSize)
+ {
+ //
+ // free buffer
+ //
+ m_DmaManager->Release(Descriptor->BufferLogical,
Descriptor->BufferSize);
+ }
+
+ //
+ // release descriptor
+ //
+ m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
+
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::CreateGeneralTransferDescriptor(
+ POHCI_GENERAL_TD* OutDescriptor,
+ ULONG BufferSize)
+{
+ POHCI_GENERAL_TD Descriptor;
+ PHYSICAL_ADDRESS DescriptorAddress;
+ NTSTATUS Status;
+
+ //
+ // allocate transfer descriptor
+ //
+ Status = m_DmaManager->Allocate(sizeof(OHCI_GENERAL_TD), (PVOID*)&Descriptor,
&DescriptorAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // no memory
+ //
+ return Status;
+ }
+
+ //
+ // initialize descriptor, hardware part
+ //
+ Descriptor->Flags = 0;
+ Descriptor->BufferPhysical = 0;
+ Descriptor->NextPhysicalDescriptor = 0;
+ Descriptor->LastPhysicalByteAddress = 0;
+
+ //
+ // software part
+ //
+ Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
+ Descriptor->BufferSize = BufferSize;
+
+ if (BufferSize > 0)
+ {
+ //
+ // allocate buffer from dma
+ //
+ Status = m_DmaManager->Allocate(BufferSize, &Descriptor->BufferLogical,
&DescriptorAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // no memory
+ //
+ m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
+ return Status;
+ }
+
+ //
+ // set physical address of buffer
+ //
+ Descriptor->BufferPhysical = DescriptorAddress.LowPart;
+ Descriptor->LastPhysicalByteAddress = Descriptor->BufferPhysical +
BufferSize - 1;
+ }
+
+ //
+ // store result
+ //
+ *OutDescriptor = Descriptor;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBRequest::AllocateEndpointDescriptor(
+ OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor)
+{
+ POHCI_ENDPOINT_DESCRIPTOR Descriptor;
+ PHYSICAL_ADDRESS DescriptorAddress;
+ NTSTATUS Status;
+
+ //
+ // allocate descriptor
+ //
+ Status = m_DmaManager->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR),
(PVOID*)&Descriptor, &DescriptorAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to allocate descriptor
+ //
+ return Status;
+ }
+
+ //
+ // intialize descriptor
+ //
+ Descriptor->Flags = OHCI_ENDPOINT_SKIP;
+
+ //
+ // append device address and endpoint number
+ //
+ Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(m_DeviceAddress);
+ Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
+ Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
+
+ //
+ // FIXME: detect type
+ //
+ Descriptor->Flags |= OHCI_ENDPOINT_FULL_SPEED;
+
+ Descriptor->HeadPhysicalDescriptor = 0;
+ Descriptor->NextPhysicalEndpoint = 0;
+ Descriptor->TailPhysicalDescriptor = 0;
+ Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
+
+ //
+ // store result
+ //
+ *OutDescriptor = Descriptor;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBRequest::BuildControlTransferDescriptor(
+ POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
+{
+ POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL;
+ POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+ NTSTATUS Status;
+
+ DPRINT1("CUSBRequest::BuildControlTransferDescriptor\n");
+
+ //
+ // allocate endpoint descriptor
+ //
+ Status = AllocateEndpointDescriptor(&EndpointDescriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to create setup descriptor
+ //
+ return Status;
+ }
+
+ //
+ // first allocate setup descriptor
+ //
+ Status = CreateGeneralTransferDescriptor(&SetupDescriptor,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to create setup descriptor
+ //
+ m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
+ return Status;
+ }
+
+ //
+ // now create the status descriptor
+ //
+ Status = CreateGeneralTransferDescriptor(&StatusDescriptor, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to create status descriptor
+ //
+ FreeDescriptor(SetupDescriptor);
+ m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
+ return Status;
+ }
+
+ if (m_TransferBufferLength)
+ {
+ //
+ // FIXME: support more than one data descriptor
+ //
+ ASSERT(m_TransferBufferLength < 8192);
+
+ //
+ // now create the data descriptor
+ //
+ Status = CreateGeneralTransferDescriptor(&DataDescriptor, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to create status descriptor
+ //
+ m_DmaManager->Release(EndpointDescriptor,
sizeof(OHCI_ENDPOINT_DESCRIPTOR));
+ FreeDescriptor(SetupDescriptor);
+ FreeDescriptor(StatusDescriptor);
+ return Status;
+ }
+
+ //
+ // initialize data descriptor
+ //
+ DataDescriptor->Flags = OHCI_TD_BUFFER_ROUNDING|
OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) |
OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_TOGGLE_CARRY |
OHCI_TD_DIRECTION_PID_IN;
+
+ //
+ // store physical address of buffer
+ //
+ DataDescriptor->BufferPhysical =
MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
+ DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical +
m_TransferBufferLength - 1;
+ }
+
+ //
+ // initialize setup descriptor
+ //
+ SetupDescriptor->Flags = OHCI_TD_DIRECTION_PID_SETUP |
OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_0 |
OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
+
+ if (m_SetupPacket)
+ {
+ //
+ // copy setup packet
+ //
+ RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+ }
+ else
+ {
+ //
+ // generate setup packet from urb
+ //
+ ASSERT(FALSE);
+ }
+
+ //
+ // initialize status descriptor
+ //
+ StatusDescriptor->Flags =
OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_1 |
OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
+ if (m_TransferBufferLength == 0)
+ {
+ //
+ // input direction is flipped for the status descriptor
+ //
+ StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
+ }
+ else
+ {
+ //
+ // output direction is flipped for the status descriptor
+ //
+ StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_OUT;
+ }
+
+ //
+ // now link the descriptors
+ //
+ if (m_TransferBufferLength)
+ {
+ //
+ // link setup descriptor to data descriptor
+ //
+ SetupDescriptor->NextPhysicalDescriptor =
DataDescriptor->PhysicalAddress.LowPart;
+
+ //
+ // FIXME: should link to last data descriptor to status descriptor
+ //
+ DataDescriptor->NextPhysicalDescriptor =
StatusDescriptor->PhysicalAddress.LowPart;
+ }
+ else
+ {
+ //
+ // link setup descriptor to status descriptor
+ //
+ SetupDescriptor->NextPhysicalDescriptor =
StatusDescriptor->PhysicalAddress.LowPart;
+ }
+
+ //
+ // now link descriptor to endpoint
+ //
+ EndpointDescriptor->HeadPhysicalDescriptor =
SetupDescriptor->PhysicalAddress.LowPart;
+ EndpointDescriptor->TailPhysicalDescriptor =
SetupDescriptor->PhysicalAddress.LowPart;
+ DPRINT1("CUSBRequest::BuildControlTransferDescriptor done\n");
+
+ //
+ // store result
+ //
+ *OutEndpointDescriptor = EndpointDescriptor;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::GetEndpointDescriptor(
+ struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
+{
+ ULONG TransferType;
+ NTSTATUS Status;
+
+ //
+ // get transfer type
+ //
+ TransferType = InternalGetTransferType();
+
+ //
+ // build request depending on type
+ //
+ switch(TransferType)
+ {
+ case USB_ENDPOINT_TYPE_CONTROL:
+ Status =
BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
+ break;
+ case USB_ENDPOINT_TYPE_BULK:
+ DPRINT1("USB_ENDPOINT_TYPE_BULK not implemented\n");
+ Status = STATUS_NOT_IMPLEMENTED;
//BuildBulkTransferQueueHead(OutDescriptor);
+ break;
+ case USB_ENDPOINT_TYPE_INTERRUPT:
+ DPRINT1("USB_ENDPOINT_TYPE_INTERRUPT not implemented\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ 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 = *OutDescriptor;
+
+ //
+ // store request object
+ //
+ (*OutDescriptor)->Request = PVOID(this);
+ }
+
+ //
+ // done
+ //
+ return Status;
+}
//----------------------------------------------------------------------------------------
VOID