mirror of
https://github.com/reactos/reactos.git
synced 2024-07-31 00:28:56 +00:00
[USBOHCI]
- Remove dead code - Silence traces - Pass status & DoneHead as parameters to dpc routine - Move IUSBRequest cleanup code into new function and use it for bulk / control transfer cleanup - Fix bugs in AllocateEndpointDescriptor. It did not take the device address into account. It also did not respect the direction of the descriptor - Implement support for bulk transfer requests - Handle irp completion in CompletionCallback - Tested in Windows XP SP3 + Vbox 4.04 + USB2.0 disabled + ReactOS usbstor + USB mass storage device - OHCI Mass storage support is now also ready - Next interrupt transfers svn path=/branches/usb-bringup/; revision=51917
This commit is contained in:
parent
2c6077dc50
commit
667b425b6c
|
@ -697,8 +697,6 @@ CUSBHardwareDevice::HeadEndpointDescriptorModified(
|
||||||
//
|
//
|
||||||
// notify controller
|
// notify controller
|
||||||
//
|
//
|
||||||
//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);
|
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), Value | OHCI_CONTROL_LIST_FILLED);
|
||||||
}
|
}
|
||||||
else if (Type == USB_ENDPOINT_TYPE_BULK)
|
else if (Type == USB_ENDPOINT_TYPE_BULK)
|
||||||
|
@ -708,12 +706,6 @@ CUSBHardwareDevice::HeadEndpointDescriptorModified(
|
||||||
//
|
//
|
||||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), Value | 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
|
NTSTATUS
|
||||||
|
@ -1191,7 +1183,7 @@ InterruptServiceRoutine(
|
||||||
//
|
//
|
||||||
This = (CUSBHardwareDevice*) ServiceContext;
|
This = (CUSBHardwareDevice*) ServiceContext;
|
||||||
|
|
||||||
DPRINT1("InterruptServiceRoutine\n");
|
DPRINT("InterruptServiceRoutine\n");
|
||||||
|
|
||||||
//
|
//
|
||||||
// get done head
|
// get done head
|
||||||
|
@ -1246,6 +1238,7 @@ InterruptServiceRoutine(
|
||||||
// head completed
|
// head completed
|
||||||
//
|
//
|
||||||
Acknowledge |= OHCI_WRITEBACK_DONE_HEAD;
|
Acknowledge |= OHCI_WRITEBACK_DONE_HEAD;
|
||||||
|
This->m_HCCA->DoneHead = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Status & OHCI_RESUME_DETECTED)
|
if (Status & OHCI_RESUME_DETECTED)
|
||||||
|
@ -1296,8 +1289,8 @@ InterruptServiceRoutine(
|
||||||
//
|
//
|
||||||
// defer processing
|
// defer processing
|
||||||
//
|
//
|
||||||
DPRINT1("Status %x\n", Status);
|
DPRINT("Status %x Acknowledge %x\n", Status, Acknowledge);
|
||||||
KeInsertQueueDpc(&This->m_IntDpcObject, This, (PVOID)Status);
|
KeInsertQueueDpc(&This->m_IntDpcObject, (PVOID)Status, (PVOID)(DoneHead & ~1));
|
||||||
|
|
||||||
//
|
//
|
||||||
// interrupt handled
|
// interrupt handled
|
||||||
|
@ -1321,23 +1314,14 @@ OhciDefferedRoutine(
|
||||||
//
|
//
|
||||||
// get parameters
|
// get parameters
|
||||||
//
|
//
|
||||||
This = (CUSBHardwareDevice*) SystemArgument1;
|
This = (CUSBHardwareDevice*)DeferredContext;
|
||||||
CStatus = (ULONG) SystemArgument2;
|
CStatus = (ULONG) SystemArgument1;
|
||||||
|
DoneHead = (ULONG)SystemArgument2;
|
||||||
|
|
||||||
DPRINT1("OhciDefferedRoutine Status %x\n", CStatus);
|
DPRINT("OhciDefferedRoutine Status %x\n", CStatus);
|
||||||
|
|
||||||
if (CStatus & OHCI_WRITEBACK_DONE_HEAD)
|
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
|
// notify queue of event
|
||||||
//
|
//
|
||||||
|
|
|
@ -216,6 +216,8 @@ typedef struct _OHCI_ENDPOINT_DESCRIPTOR
|
||||||
#define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s) ((s) << 16)
|
#define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s) ((s) << 16)
|
||||||
#define OHCI_ENDPOINT_LOW_SPEED 0x00002000
|
#define OHCI_ENDPOINT_LOW_SPEED 0x00002000
|
||||||
#define OHCI_ENDPOINT_FULL_SPEED 0x00000000
|
#define OHCI_ENDPOINT_FULL_SPEED 0x00000000
|
||||||
|
#define OHCI_ENDPOINT_DIRECTION_OUT 0x00000800
|
||||||
|
#define OHCI_ENDPOINT_DIRECTION_IN 0x00001000
|
||||||
|
|
||||||
//
|
//
|
||||||
// Maximum port count set by OHCI
|
// Maximum port count set by OHCI
|
||||||
|
|
|
@ -443,6 +443,14 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
||||||
// Description: notifies request that the endpoint descriptor is complete
|
// Description: notifies request that the endpoint descriptor is complete
|
||||||
|
|
||||||
virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) = 0;
|
virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) = 0;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// FreeEndpointDescriptor
|
||||||
|
//
|
||||||
|
// Description: frees the associated endpoint descriptor and its general descriptors
|
||||||
|
|
||||||
|
virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ public:
|
||||||
// local functions
|
// local functions
|
||||||
BOOLEAN IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress);
|
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);
|
NTSTATUS FindTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor);
|
||||||
|
VOID CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor);
|
||||||
|
|
||||||
// constructor / destructor
|
// constructor / destructor
|
||||||
CUSBQueue(IUnknown *OuterUnknown){}
|
CUSBQueue(IUnknown *OuterUnknown){}
|
||||||
|
@ -127,7 +128,7 @@ CUSBQueue::AddUSBRequest(
|
||||||
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
|
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
|
||||||
POHCI_ENDPOINT_DESCRIPTOR Descriptor;
|
POHCI_ENDPOINT_DESCRIPTOR Descriptor;
|
||||||
|
|
||||||
DPRINT1("CUSBQueue::AddUSBRequest\n");
|
DPRINT("CUSBQueue::AddUSBRequest\n");
|
||||||
|
|
||||||
//
|
//
|
||||||
// sanity check
|
// sanity check
|
||||||
|
@ -146,11 +147,11 @@ CUSBQueue::AddUSBRequest(
|
||||||
{
|
{
|
||||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||||
case USB_ENDPOINT_TYPE_INTERRUPT:
|
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||||
case USB_ENDPOINT_TYPE_BULK:
|
|
||||||
/* NOT IMPLEMENTED IN QUEUE */
|
/* NOT IMPLEMENTED IN QUEUE */
|
||||||
Status = STATUS_NOT_SUPPORTED;
|
Status = STATUS_NOT_SUPPORTED;
|
||||||
break;
|
break;
|
||||||
case USB_ENDPOINT_TYPE_CONTROL:
|
case USB_ENDPOINT_TYPE_CONTROL:
|
||||||
|
case USB_ENDPOINT_TYPE_BULK:
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -228,12 +229,14 @@ CUSBQueue::AddUSBRequest(
|
||||||
Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
|
Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
|
||||||
//HeadDescriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
|
//HeadDescriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
|
||||||
|
|
||||||
|
DPRINT("Request %x Logical %x added to queue Queue %p Logical %x\n", Descriptor, Descriptor->PhysicalAddress.LowPart, HeadDescriptor, HeadDescriptor->PhysicalAddress.LowPart);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// notify hardware of our request
|
// notify hardware of our request
|
||||||
//
|
//
|
||||||
m_Hardware->HeadEndpointDescriptorModified(Type);
|
m_Hardware->HeadEndpointDescriptorModified(Type);
|
||||||
|
|
||||||
DPRINT1("Request %x %x added to queue\n", Descriptor, Descriptor->PhysicalAddress);
|
|
||||||
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -356,6 +359,47 @@ CUSBQueue::IsTransferDescriptorInEndpoint(
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CUSBQueue::CleanupEndpointDescriptor(
|
||||||
|
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor,
|
||||||
|
POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor)
|
||||||
|
{
|
||||||
|
PUSBREQUEST Request;
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: verify unlinking process
|
||||||
|
//
|
||||||
|
PreviousEndpointDescriptor->NextDescriptor = EndpointDescriptor->NextDescriptor;
|
||||||
|
PreviousEndpointDescriptor->NextPhysicalEndpoint = EndpointDescriptor->NextPhysicalEndpoint;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get corresponding request
|
||||||
|
//
|
||||||
|
Request = PUSBREQUEST(EndpointDescriptor->Request);
|
||||||
|
ASSERT(Request);
|
||||||
|
|
||||||
|
//
|
||||||
|
// notify of completion
|
||||||
|
//
|
||||||
|
Request->CompletionCallback(EndpointDescriptor);
|
||||||
|
|
||||||
|
//
|
||||||
|
// free endpoint descriptor
|
||||||
|
//
|
||||||
|
Request->FreeEndpointDescriptor(EndpointDescriptor);
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: check if complete
|
||||||
|
//
|
||||||
|
//ASSERT(Request->IsRequestComplete());
|
||||||
|
|
||||||
|
//
|
||||||
|
// release request
|
||||||
|
//
|
||||||
|
Request->Release();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CUSBQueue::TransferDescriptorCompletionCallback(
|
CUSBQueue::TransferDescriptorCompletionCallback(
|
||||||
|
@ -363,7 +407,8 @@ CUSBQueue::TransferDescriptorCompletionCallback(
|
||||||
{
|
{
|
||||||
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
|
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PUSBREQUEST Request;
|
|
||||||
|
DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress);
|
||||||
|
|
||||||
//
|
//
|
||||||
// find transfer descriptor in control list
|
// find transfer descriptor in control list
|
||||||
|
@ -372,32 +417,39 @@ CUSBQueue::TransferDescriptorCompletionCallback(
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// FIXME: make sure this is ok
|
// cleanup endpoint
|
||||||
// unlink descriptor
|
|
||||||
//
|
//
|
||||||
PreviousEndpointDescriptor->NextDescriptor = EndpointDescriptor->NextDescriptor;
|
CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor);
|
||||||
PreviousEndpointDescriptor->NextPhysicalEndpoint = EndpointDescriptor->NextPhysicalEndpoint;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// get corresponding request
|
// done
|
||||||
//
|
//
|
||||||
Request = PUSBREQUEST(EndpointDescriptor->Request);
|
return;
|
||||||
|
|
||||||
//
|
|
||||||
// notify of completion
|
|
||||||
//
|
|
||||||
Request->CompletionCallback(EndpointDescriptor);
|
|
||||||
|
|
||||||
//
|
|
||||||
// FIXME: check if complete
|
|
||||||
//
|
|
||||||
ASSERT(Request->IsRequestComplete());
|
|
||||||
//
|
|
||||||
// release request
|
|
||||||
//
|
|
||||||
Request->Release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// find transfer descriptor in bulk list
|
||||||
|
//
|
||||||
|
Status = FindTransferDescriptorInEndpoint(m_BulkHeadEndpointDescriptor, TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// cleanup endpoint
|
||||||
|
//
|
||||||
|
CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor);
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// hardware reported dead endpoint completed
|
||||||
|
//
|
||||||
|
DPRINT1("CUSBQueue::TransferDescriptorCompletionCallback invalid transfer descriptor %x\n", TransferDescriptorLogicalAddress);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ public:
|
||||||
virtual BOOLEAN IsRequestInitialized();
|
virtual BOOLEAN IsRequestInitialized();
|
||||||
virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
|
virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
|
||||||
virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
|
virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
|
||||||
|
virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
|
||||||
|
|
||||||
// local functions
|
// local functions
|
||||||
ULONG InternalGetTransferType();
|
ULONG InternalGetTransferType();
|
||||||
|
@ -53,6 +54,7 @@ public:
|
||||||
NTSTATUS BuildSetupPacket();
|
NTSTATUS BuildSetupPacket();
|
||||||
NTSTATUS BuildSetupPacketFromURB();
|
NTSTATUS BuildSetupPacketFromURB();
|
||||||
NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
|
NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
|
||||||
|
NTSTATUS BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
|
||||||
NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, ULONG BufferSize);
|
NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, ULONG BufferSize);
|
||||||
VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor);
|
VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor);
|
||||||
NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor);
|
NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor);
|
||||||
|
@ -606,10 +608,36 @@ CUSBRequest::AllocateEndpointDescriptor(
|
||||||
//
|
//
|
||||||
// append device address and endpoint number
|
// append device address and endpoint number
|
||||||
//
|
//
|
||||||
Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(m_DeviceAddress);
|
Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(GetDeviceAddress());
|
||||||
Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
|
Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
|
||||||
Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
|
Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
|
||||||
|
|
||||||
|
//
|
||||||
|
// is there an endpoint descriptor
|
||||||
|
//
|
||||||
|
if (m_EndpointDescriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// check direction
|
||||||
|
//
|
||||||
|
if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor->bEndpointAddress))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// direction out
|
||||||
|
//
|
||||||
|
Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_OUT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// direction in
|
||||||
|
//
|
||||||
|
Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_IN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME: detect type
|
// FIXME: detect type
|
||||||
//
|
//
|
||||||
|
@ -631,6 +659,198 @@ CUSBRequest::AllocateEndpointDescriptor(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::BuildBulkInterruptEndpoint(
|
||||||
|
POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
|
||||||
|
{
|
||||||
|
POHCI_GENERAL_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor, LastDescriptor;
|
||||||
|
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||||
|
ULONG BufferSize, CurrentSize, Direction, MaxLengthInPage;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PVOID Buffer;
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate endpoint descriptor
|
||||||
|
//
|
||||||
|
Status = AllocateEndpointDescriptor(&EndpointDescriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to create setup descriptor
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate transfer descriptor for last descriptor
|
||||||
|
//
|
||||||
|
Status = CreateGeneralTransferDescriptor(&LastDescriptor, 0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to create transfer descriptor
|
||||||
|
//
|
||||||
|
m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get buffer size
|
||||||
|
//
|
||||||
|
BufferSize = m_TransferBufferLength;
|
||||||
|
ASSERT(BufferSize);
|
||||||
|
ASSERT(m_TransferBufferMDL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get buffer
|
||||||
|
//
|
||||||
|
Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
|
||||||
|
ASSERT(Buffer);
|
||||||
|
|
||||||
|
if (InternalGetPidDirection())
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// input direction
|
||||||
|
//
|
||||||
|
Direction = OHCI_TD_DIRECTION_PID_IN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// output direction
|
||||||
|
//
|
||||||
|
Direction = OHCI_TD_DIRECTION_PID_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get current buffersize
|
||||||
|
//
|
||||||
|
CurrentSize = min(8192, BufferSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get page offset
|
||||||
|
//
|
||||||
|
MaxLengthInPage = PAGE_SIZE - BYTE_OFFSET(Buffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get minimum from current page size
|
||||||
|
//
|
||||||
|
CurrentSize = min(CurrentSize, MaxLengthInPage);
|
||||||
|
ASSERT(CurrentSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate transfer descriptor
|
||||||
|
//
|
||||||
|
Status = CreateGeneralTransferDescriptor(&CurrentDescriptor, 0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to create transfer descriptor
|
||||||
|
// TODO: cleanup
|
||||||
|
//
|
||||||
|
ASSERT(FALSE);
|
||||||
|
m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
|
||||||
|
FreeDescriptor(LastDescriptor);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize descriptor
|
||||||
|
//
|
||||||
|
CurrentDescriptor->Flags = Direction | 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;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store physical address of buffer
|
||||||
|
//
|
||||||
|
CurrentDescriptor->BufferPhysical = MmGetPhysicalAddress(Buffer).LowPart;
|
||||||
|
CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + CurrentSize - 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// is there a previous descriptor
|
||||||
|
//
|
||||||
|
if (PreviousDescriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// link descriptors
|
||||||
|
//
|
||||||
|
PreviousDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor;
|
||||||
|
PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// it is the first descriptor
|
||||||
|
//
|
||||||
|
FirstDescriptor = CurrentDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("PreviousDescriptor %p CurrentDescriptor %p Buffer Logical %p Physical %x Last Physical %x CurrentSize %lu\n", PreviousDescriptor, CurrentDescriptor, CurrentDescriptor->BufferLogical, CurrentDescriptor->BufferPhysical, CurrentDescriptor->LastPhysicalByteAddress, CurrentSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// set previous descriptor
|
||||||
|
//
|
||||||
|
PreviousDescriptor = CurrentDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// subtract buffer size
|
||||||
|
//
|
||||||
|
BufferSize -= CurrentSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// increment buffer offset
|
||||||
|
//
|
||||||
|
Buffer = (PVOID)((ULONG_PTR)Buffer + CurrentSize);
|
||||||
|
|
||||||
|
}while(BufferSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// first descriptor has no carry bit
|
||||||
|
//
|
||||||
|
FirstDescriptor->Flags &= ~OHCI_TD_TOGGLE_CARRY;
|
||||||
|
|
||||||
|
//
|
||||||
|
// fixme: toggle
|
||||||
|
//
|
||||||
|
FirstDescriptor->Flags |= OHCI_TD_TOGGLE_0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// clear interrupt mask for last transfer descriptor
|
||||||
|
//
|
||||||
|
CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
|
||||||
|
|
||||||
|
//
|
||||||
|
// fire interrupt as soon transfer is finished
|
||||||
|
//
|
||||||
|
CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// link last data descriptor to last descriptor
|
||||||
|
//
|
||||||
|
CurrentDescriptor->NextLogicalDescriptor = LastDescriptor;
|
||||||
|
CurrentDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
|
||||||
|
|
||||||
|
//
|
||||||
|
// now link descriptor to endpoint
|
||||||
|
//
|
||||||
|
EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
|
||||||
|
EndpointDescriptor->TailPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
|
||||||
|
EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
*OutEndpointDescriptor = EndpointDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CUSBRequest::BuildControlTransferDescriptor(
|
CUSBRequest::BuildControlTransferDescriptor(
|
||||||
POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
|
POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
|
||||||
|
@ -639,8 +859,6 @@ CUSBRequest::BuildControlTransferDescriptor(
|
||||||
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT1("CUSBRequest::BuildControlTransferDescriptor\n");
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// allocate endpoint descriptor
|
// allocate endpoint descriptor
|
||||||
//
|
//
|
||||||
|
@ -695,7 +913,6 @@ CUSBRequest::BuildControlTransferDescriptor(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (m_TransferBufferLength)
|
if (m_TransferBufferLength)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -729,6 +946,7 @@ CUSBRequest::BuildControlTransferDescriptor(
|
||||||
//
|
//
|
||||||
DataDescriptor->BufferPhysical = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
|
DataDescriptor->BufferPhysical = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
|
||||||
DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1;
|
DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -849,12 +1067,8 @@ CUSBRequest::GetEndpointDescriptor(
|
||||||
Status = BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
|
Status = BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
|
||||||
break;
|
break;
|
||||||
case USB_ENDPOINT_TYPE_BULK:
|
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:
|
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||||
DPRINT1("USB_ENDPOINT_TYPE_INTERRUPT not implemented\n");
|
Status = BuildBulkInterruptEndpoint(OutDescriptor);
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
break;
|
break;
|
||||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||||
DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
|
DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
|
||||||
|
@ -919,32 +1133,24 @@ CUSBRequest::GetResultStatus(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CUSBRequest::CompletionCallback(
|
CUSBRequest::FreeEndpointDescriptor(
|
||||||
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
|
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
|
||||||
{
|
{
|
||||||
POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
|
POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
|
||||||
|
|
||||||
DPRINT1("CUSBRequest::CompletionCallback\n");
|
DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
|
||||||
|
|
||||||
//
|
|
||||||
// set status code
|
|
||||||
//
|
|
||||||
m_NtStatusCode = STATUS_SUCCESS;
|
|
||||||
m_UrbStatusCode = USBD_STATUS_SUCCESS;
|
|
||||||
|
|
||||||
ASSERT(!m_Irp);
|
|
||||||
|
|
||||||
//
|
|
||||||
// FIXME: cleanup descriptors
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// get first general transfer descriptor
|
// get first general transfer descriptor
|
||||||
//
|
//
|
||||||
TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
|
TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// release endpoint descriptor
|
||||||
|
//
|
||||||
|
m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
|
||||||
|
|
||||||
while(TransferDescriptor)
|
while(TransferDescriptor)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -963,6 +1169,8 @@ CUSBRequest::CompletionCallback(
|
||||||
m_DmaManager->Release(TransferDescriptor->BufferLogical, TransferDescriptor->BufferSize);
|
m_DmaManager->Release(TransferDescriptor->BufferLogical, TransferDescriptor->BufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor, TransferDescriptor->PhysicalAddress.LowPart, TransferDescriptor->BufferPhysical, TransferDescriptor->LastPhysicalByteAddress);
|
||||||
|
|
||||||
//
|
//
|
||||||
// release descriptor
|
// release descriptor
|
||||||
//
|
//
|
||||||
|
@ -974,16 +1182,75 @@ CUSBRequest::CompletionCallback(
|
||||||
TransferDescriptor = NextTransferDescriptor;
|
TransferDescriptor = NextTransferDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
}
|
||||||
// release endpoint descriptor
|
|
||||||
//
|
VOID
|
||||||
m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
|
CUSBRequest::CompletionCallback(
|
||||||
|
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
|
||||||
|
{
|
||||||
|
POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PURB Urb;
|
||||||
|
|
||||||
|
DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
|
||||||
|
|
||||||
//
|
//
|
||||||
// signal completion event
|
// set status code
|
||||||
//
|
//
|
||||||
PC_ASSERT(m_CompletionEvent);
|
m_NtStatusCode = STATUS_SUCCESS;
|
||||||
KeSetEvent(m_CompletionEvent, 0, FALSE);
|
m_UrbStatusCode = USBD_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (m_Irp)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// set irp completion status
|
||||||
|
//
|
||||||
|
m_Irp->IoStatus.Status = STATUS_SUCCESS; //FIXME
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current irp stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store urb status
|
||||||
|
//
|
||||||
|
Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; //FIXME
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check if the MDL was created
|
||||||
|
//
|
||||||
|
if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Free Mdl
|
||||||
|
//
|
||||||
|
IoFreeMdl(m_TransferBufferMDL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: support status and calculate length
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: check if the transfer was split
|
||||||
|
// if yes dont complete irp yet
|
||||||
|
//
|
||||||
|
IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// signal completion event
|
||||||
|
//
|
||||||
|
PC_ASSERT(m_CompletionEvent);
|
||||||
|
KeSetEvent(m_CompletionEvent, 0, FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue