[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:
Michael Martin 2011-04-29 13:16:03 +00:00
parent 07dbb71da0
commit bdfaf318b8
3 changed files with 243 additions and 15 deletions

View file

@ -761,6 +761,8 @@ CHubController::HandleBulkOrInterruptTransfer(
IN OUT PIRP Irp,
PURB Urb)
{
PUSBDEVICE UsbDevice;
PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
//
// 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.
//
DPRINT1("Pending SCE Irp\n");;
m_PendingSCEIrp = Irp;
IoMarkIrpPending(Irp);
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);
DPRINT1("SCE Notification!\n");
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);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}

View file

@ -456,7 +456,7 @@ CUSBDevice::CommitIrp(
NTSTATUS Status;
PUSBREQUEST Request;
if (!m_Queue || m_DmaManager)
if (!m_Queue || !m_DmaManager)
{
//
// no queue, wtf?

View file

@ -53,6 +53,7 @@ public:
// local functions
ULONG InternalGetTransferType();
UCHAR InternalGetPidDirection();
NTSTATUS BuildControlTransferQueueHead(PQUEUE_HEAD * OutHead);
NTSTATUS BuildBulkTransferQueueHead(PQUEUE_HEAD * OutHead);
NTSTATUS CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor);
@ -205,6 +206,8 @@ CUSBRequest::InitializeWithIrp(
PC_ASSERT(DmaManager);
PC_ASSERT(Irp);
m_DmaManager = DmaManager;
//
// get current irp stack location
//
@ -245,20 +248,49 @@ CUSBRequest::InitializeWithIrp(
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
//
m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
//
// get mdl buffer
//
m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
}
break;
}
@ -316,6 +348,18 @@ CUSBRequest::CompletionCallback(
//
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
//
@ -536,6 +580,35 @@ CUSBRequest::InternalGetTransferType()
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
CUSBRequest::BuildControlTransferQueueHead(
@ -705,8 +778,123 @@ NTSTATUS
CUSBRequest::BuildBulkTransferQueueHead(
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;
//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
//
Status = m_DmaManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysicalAddress);
if (!NT_SUCCESS(Status))
{
//
@ -1225,12 +1414,12 @@ CUSBRequest::IsQueueHeadComplete(
//
// 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
//
PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Active == 0);
//PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Active == 0);
}
}