mirror of
https://github.com/reactos/reactos.git
synced 2024-09-08 11:50:08 +00:00
[USBEHCI_NEW]
- Fix a type causing CommitIrp to fail. - Add a sanity check in StatusChangeEndpointCallBack to check that a pending SCE irp is queued. - Start Implementing Bulk Transfers. Needs more work. svn path=/branches/usb-bringup/; revision=51493
This commit is contained in:
parent
07dbb71da0
commit
bdfaf318b8
|
@ -761,6 +761,8 @@ CHubController::HandleBulkOrInterruptTransfer(
|
||||||
IN OUT PIRP Irp,
|
IN OUT PIRP Irp,
|
||||||
PURB Urb)
|
PURB Urb)
|
||||||
{
|
{
|
||||||
|
PUSBDEVICE UsbDevice;
|
||||||
|
PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
|
||||||
//
|
//
|
||||||
// First check if the request is for the Status Change Endpoint
|
// First check if the request is for the Status Change Endpoint
|
||||||
//
|
//
|
||||||
|
@ -779,13 +781,45 @@ CHubController::HandleBulkOrInterruptTransfer(
|
||||||
//
|
//
|
||||||
// Else pend the IRP, to be completed when a device connects or disconnects.
|
// Else pend the IRP, to be completed when a device connects or disconnects.
|
||||||
//
|
//
|
||||||
|
DPRINT1("Pending SCE Irp\n");;
|
||||||
m_PendingSCEIrp = Irp;
|
m_PendingSCEIrp = Irp;
|
||||||
IoMarkIrpPending(Irp);
|
IoMarkIrpPending(Irp);
|
||||||
return STATUS_PENDING;
|
return STATUS_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIMPLEMENTED
|
//
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
// Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
|
||||||
|
//
|
||||||
|
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
||||||
|
|
||||||
|
switch(EndPointDesc->bmAttributes & 0x0F)
|
||||||
|
{
|
||||||
|
case USB_ENDPOINT_TYPE_CONTROL:
|
||||||
|
DPRINT1("Control Transfer is not expected!!!\n");
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
case USB_ENDPOINT_TYPE_BULK:
|
||||||
|
DPRINT1("Initiating Bulk Transfer\n");
|
||||||
|
break;
|
||||||
|
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||||
|
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||||
|
DPRINT1("Not Supported\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DPRINT1("Unknown EndPoint Type!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if this is a valid usb device handle
|
||||||
|
//
|
||||||
|
PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device
|
||||||
|
//
|
||||||
|
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
|
||||||
|
|
||||||
|
return UsbDevice->SubmitIrp(Irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
|
@ -3068,13 +3102,18 @@ VOID StatusChangeEndpointCallBack(PVOID Context)
|
||||||
|
|
||||||
ASSERT(This);
|
ASSERT(This);
|
||||||
|
|
||||||
DPRINT1("SCE Notification!\n");
|
|
||||||
Irp = This->m_PendingSCEIrp;
|
Irp = This->m_PendingSCEIrp;
|
||||||
This->m_PendingSCEIrp = NULL;
|
if (!Irp)
|
||||||
|
{
|
||||||
|
DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
This->m_PendingSCEIrp = NULL;
|
||||||
This->QueryStatusChageEndpoint(Irp);
|
This->QueryStatusChageEndpoint(Irp);
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,7 +456,7 @@ CUSBDevice::CommitIrp(
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PUSBREQUEST Request;
|
PUSBREQUEST Request;
|
||||||
|
|
||||||
if (!m_Queue || m_DmaManager)
|
if (!m_Queue || !m_DmaManager)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// no queue, wtf?
|
// no queue, wtf?
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
|
|
||||||
// local functions
|
// local functions
|
||||||
ULONG InternalGetTransferType();
|
ULONG InternalGetTransferType();
|
||||||
|
UCHAR InternalGetPidDirection();
|
||||||
NTSTATUS BuildControlTransferQueueHead(PQUEUE_HEAD * OutHead);
|
NTSTATUS BuildControlTransferQueueHead(PQUEUE_HEAD * OutHead);
|
||||||
NTSTATUS BuildBulkTransferQueueHead(PQUEUE_HEAD * OutHead);
|
NTSTATUS BuildBulkTransferQueueHead(PQUEUE_HEAD * OutHead);
|
||||||
NTSTATUS CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor);
|
NTSTATUS CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor);
|
||||||
|
@ -205,6 +206,8 @@ CUSBRequest::InitializeWithIrp(
|
||||||
PC_ASSERT(DmaManager);
|
PC_ASSERT(DmaManager);
|
||||||
PC_ASSERT(Irp);
|
PC_ASSERT(Irp);
|
||||||
|
|
||||||
|
m_DmaManager = DmaManager;
|
||||||
|
|
||||||
//
|
//
|
||||||
// get current irp stack location
|
// get current irp stack location
|
||||||
//
|
//
|
||||||
|
@ -245,20 +248,49 @@ CUSBRequest::InitializeWithIrp(
|
||||||
if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
|
if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// FIXME: it must have an MDL
|
// Check if there is a MDL
|
||||||
//
|
//
|
||||||
PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
|
if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Create one using TransferBuffer
|
||||||
|
//
|
||||||
|
DPRINT1("Creating Mdl from Urb Buffer\n");
|
||||||
|
m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
|
||||||
|
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!m_TransferBufferMDL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate mdl
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// build mdl for non paged pool
|
||||||
|
// FIXME: Does hub driver already do this when passing MDL?
|
||||||
|
//
|
||||||
|
MmBuildMdlForNonPagedPool(m_TransferBufferMDL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// save buffer length
|
||||||
|
//
|
||||||
|
m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
|
||||||
|
|
||||||
//
|
//
|
||||||
// get endpoint descriptor
|
// get endpoint descriptor
|
||||||
//
|
//
|
||||||
m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
||||||
|
|
||||||
//
|
|
||||||
// get mdl buffer
|
|
||||||
//
|
|
||||||
m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
|
|
||||||
m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -316,6 +348,18 @@ CUSBRequest::CompletionCallback(
|
||||||
//
|
//
|
||||||
Urb->UrbHeader.Status = UrbStatusCode;
|
Urb->UrbHeader.Status = UrbStatusCode;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check if the MDL was created
|
||||||
|
//
|
||||||
|
|
||||||
|
if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Free Mdl
|
||||||
|
//
|
||||||
|
IoFreeMdl(m_TransferBufferMDL);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// check if the request was successfull
|
// check if the request was successfull
|
||||||
//
|
//
|
||||||
|
@ -536,6 +580,35 @@ CUSBRequest::InternalGetTransferType()
|
||||||
return TransferType;
|
return TransferType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UCHAR
|
||||||
|
CUSBRequest::InternalGetPidDirection()
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PURB Urb;
|
||||||
|
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||||
|
|
||||||
|
ASSERT(m_Irp);
|
||||||
|
//
|
||||||
|
// get stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// cast to end point
|
||||||
|
//
|
||||||
|
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
||||||
|
|
||||||
|
//
|
||||||
|
// end point is defined in the low byte of bmAttributes
|
||||||
|
//
|
||||||
|
return (EndpointDescriptor->bmAttributes & USB_ENDPOINT_DIRECTION_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CUSBRequest::BuildControlTransferQueueHead(
|
CUSBRequest::BuildControlTransferQueueHead(
|
||||||
|
@ -705,8 +778,123 @@ NTSTATUS
|
||||||
CUSBRequest::BuildBulkTransferQueueHead(
|
CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
PQUEUE_HEAD * OutHead)
|
PQUEUE_HEAD * OutHead)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
NTSTATUS Status;
|
||||||
|
ULONG NumTransferDescriptors, TransferBufferRounded, NumPages, Index, FailIndex;
|
||||||
|
PQUEUE_HEAD QueueHead;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate the queue head
|
||||||
|
//
|
||||||
|
Status = CreateQueueHead(&QueueHead);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate queue heads
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
PC_ASSERT(QueueHead);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Determine number of transfer descriptors needed. Max size is 3 * 5 Pages
|
||||||
|
// FIXME: Do we need anything bigger?
|
||||||
|
//
|
||||||
|
TransferBufferRounded = ROUND_TO_PAGES(m_TransferBufferLength);
|
||||||
|
NumPages = Index = 0;
|
||||||
|
NumTransferDescriptors = 1;
|
||||||
|
while (TransferBufferRounded > 0)
|
||||||
|
{
|
||||||
|
TransferBufferRounded -= PAGE_SIZE;
|
||||||
|
NumPages++;
|
||||||
|
Index++;
|
||||||
|
if (Index == 5)
|
||||||
|
{
|
||||||
|
NumTransferDescriptors++;
|
||||||
|
Index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1("Need TransferDescriptors %x, Pages %x\n", NumTransferDescriptors, NumPages);
|
||||||
|
DPRINT1("This is the end of the line!!!!!!!!\n");
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
//FIXME: Below needs work.
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: Handle transfers greater than 5 * PAGE_SIZE * 3
|
||||||
|
//
|
||||||
|
if (NumTransferDescriptors > 3) NumTransferDescriptors = 3;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocated transfer descriptors
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < NumTransferDescriptors; Index++)
|
||||||
|
{
|
||||||
|
Status = CreateDescriptor(&m_TransferDescriptors[Index]);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Failed to allocate transfer descriptors
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free QueueHead
|
||||||
|
//
|
||||||
|
FreeQueueHead(QueueHead);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free Descriptors
|
||||||
|
// FIXME: Implement FreeDescriptors
|
||||||
|
//
|
||||||
|
//for (FailIndex = 0; FailIndex < Index; FailIndex++)
|
||||||
|
//FreeDescriptor(m_TransferDescriptors[FailIndex]);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Go ahead and link descriptors
|
||||||
|
//
|
||||||
|
if (Index > 0)
|
||||||
|
{
|
||||||
|
m_TransferDescriptors[Index - 1]->NextPointer = m_TransferDescriptors[Index]->PhysicalAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the QueueHead
|
||||||
|
//
|
||||||
|
QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
|
||||||
|
|
||||||
|
if (m_EndpointDescriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Set endpoint address and max packet length
|
||||||
|
//
|
||||||
|
QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->bEndpointAddress & 0x0F;
|
||||||
|
QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->wMaxPacketSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueHead->Token.Bits.DataToggle = TRUE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Setup descriptors
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[0]->Token.Bits.PIDCode = InternalGetPidDirection();
|
||||||
|
//m_TransferDescriptors[0]->Token.Bits.TotalBytesToTransfer = ???
|
||||||
|
//m_TransferDescriptors[0]->Token.Bits.DataToggle = FALSE;
|
||||||
|
|
||||||
|
m_TransferDescriptors[Index]->Token.Bits.InterruptOnComplete = TRUE;
|
||||||
|
|
||||||
|
ASSERT(m_TransferBufferMDL);
|
||||||
|
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
|
@ -764,6 +952,7 @@ CUSBRequest::CreateQueueHead(
|
||||||
// allocate queue head
|
// allocate queue head
|
||||||
//
|
//
|
||||||
Status = m_DmaManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysicalAddress);
|
Status = m_DmaManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysicalAddress);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -1225,12 +1414,12 @@ CUSBRequest::IsQueueHeadComplete(
|
||||||
//
|
//
|
||||||
// check for serious error
|
// check for serious error
|
||||||
//
|
//
|
||||||
PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Halted == 0);
|
//PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Halted == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// the transfer descriptor should be in the same state as the queue head
|
// the transfer descriptor should be in the same state as the queue head
|
||||||
//
|
//
|
||||||
PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Active == 0);
|
//PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Active == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue