mirror of
https://github.com/reactos/reactos.git
synced 2024-10-03 07:53:49 +00:00
[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) svn path=/branches/usb-bringup/; revision=51864
This commit is contained in:
parent
c5acda628c
commit
f75cb3d51d
|
@ -59,6 +59,10 @@ public:
|
|||
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);
|
||||
|
||||
|
@ -359,16 +363,6 @@ CUSBHardwareDevice::PnpStart(
|
|||
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
|
||||
//
|
||||
|
@ -380,6 +374,16 @@ CUSBHardwareDevice::PnpStart(
|
|||
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;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Stop the controller before modifying schedules
|
||||
|
@ -631,6 +635,42 @@ CUSBHardwareDevice::AllocateEndpointDescriptor(
|
|||
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;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CUSBHardwareDevice::InitializeController()
|
||||
{
|
||||
|
@ -1128,7 +1168,7 @@ InterruptServiceRoutine(
|
|||
// head completed
|
||||
//
|
||||
DPRINT1("InterruptServiceRoutine> Done Head completion\n");
|
||||
|
||||
ASSERT(FALSE);
|
||||
//
|
||||
// FIXME: handle event
|
||||
//
|
||||
|
@ -1148,9 +1188,11 @@ InterruptServiceRoutine(
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ typedef struct
|
|||
#define OHCI_PAGE_OFFSET(x) ((x) & 0xfff)
|
||||
|
||||
|
||||
typedef struct
|
||||
typedef struct _OHCI_ENDPOINT_DESCRIPTOR
|
||||
{
|
||||
// Hardware part
|
||||
ULONG Flags;
|
||||
|
@ -202,10 +202,19 @@ typedef struct
|
|||
|
||||
// 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 @@ typedef struct
|
|||
}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
|
||||
|
|
|
@ -107,7 +107,7 @@ DECLARE_INTERFACE_(IHCDController, IUnknown)
|
|||
|
||||
typedef IHCDController *PHCDCONTROLLER;
|
||||
|
||||
|
||||
struct _OHCI_ENDPOINT_DESCRIPTOR;
|
||||
//=========================================================================================
|
||||
//
|
||||
// class IUSBHardwareDevice
|
||||
|
@ -172,6 +172,33 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown)
|
|||
|
||||
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;
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
// GetDMA
|
||||
|
@ -334,8 +361,6 @@ typedef IDMAMemoryManager *PDMAMEMORYMANAGER;
|
|||
// CancelCallback routine is invoked.
|
||||
//
|
||||
|
||||
struct _QUEUE_HEAD;
|
||||
|
||||
DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
||||
{
|
||||
DEFINE_ABSTRACT_UNKNOWN()
|
||||
|
@ -385,6 +410,14 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
|||
|
||||
virtual ULONG GetTransferType() = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
// GetEndpointDescriptor
|
||||
//
|
||||
// Description: returns the general transfer descriptor
|
||||
|
||||
virtual NTSTATUS GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
// GetResultStatus
|
||||
|
|
|
@ -46,6 +46,9 @@ public:
|
|||
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 @@ CUSBQueue::Initialize(
|
|||
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 @@ CUSBQueue::AddUSBRequest(
|
|||
NTSTATUS Status;
|
||||
ULONG Type;
|
||||
KIRQL OldLevel;
|
||||
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
|
||||
POHCI_ENDPOINT_DESCRIPTOR Descriptor;
|
||||
|
||||
DPRINT1("CUSBQueue::AddUSBRequest\n");
|
||||
|
||||
//
|
||||
// sanity check
|
||||
|
@ -143,6 +169,63 @@ CUSBQueue::AddUSBRequest(
|
|||
//
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ CUSBRequest::GetTransferType()
|
|||
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 @@ CUSBRequest::GetDeviceAddress()
|
|||
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
|
||||
|
|
Loading…
Reference in a new issue