[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, 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);
} }

View file

@ -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?

View file

@ -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);
} }
} }