[USB\USBEHCI]

- Implement ExecuteTransfer to replace SubmitTransfer.
- Start implentation for BulkTransfers and needed DMA. This needs much more work to be done correctly. We will get to it.
- Implement URB_FUNCTION_CLASS_INTERFACE.
- Add comments.
Change 3 of 3.

svn path=/trunk/; revision=51327
This commit is contained in:
Michael Martin 2011-04-13 04:48:50 +00:00
parent fe97558adf
commit 35e6c5fe82
4 changed files with 592 additions and 161 deletions

View file

@ -70,13 +70,17 @@ QueueURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp)
NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
ULONG_PTR Information = 0;
PIO_STACK_LOCATION Stack;
PUSB_DEVICE UsbDevice = NULL;
PEHCI_HOST_CONTROLLER hcd;
URB *Urb;
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) PdoDeviceExtension->ControllerFdo->DeviceExtension;
hcd = &FdoDeviceExtension->hcd;
Stack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(Stack);
@ -105,16 +109,62 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
{
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
{
DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER UsbDevice %x\n", UsbDevice);
PUSB_ENDPOINT_DESCRIPTOR EndPointDesc;
int i;
for (i = 0; i < UsbDevice->ActiveInterface->InterfaceDescriptor.bNumEndpoints; i++)
{
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)&UsbDevice->ActiveInterface->EndPoints[i]->EndPointDescriptor;
DPRINT("EndPoint %d Handle %x\n", i, &UsbDevice->ActiveInterface->EndPoints[i]->EndPointDescriptor);
DPRINT("bmAttributes %x\n", EndPointDesc->bmAttributes);
DPRINT("EndPoint is transfer type %x\n", EndPointDesc->bmAttributes & 0x0F);
}
DPRINT("UsbDevice %x, Handle %x\n", UsbDevice, Urb->UrbBulkOrInterruptTransfer.PipeHandle);
if (&UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor != Urb->UrbBulkOrInterruptTransfer.PipeHandle)
{
DPRINT1("Invalid Parameter, Expected EndPointDescriptor of %x, but got %x\n", &UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor, Urb->UrbBulkOrInterruptTransfer.PipeHandle);
Status = STATUS_INVALID_PARAMETER;
DPRINT("HubDevice %x, UsbDevice %x\n", PdoDeviceExtension->UsbDevices[0], UsbDevice);
if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
DPRINT1("USBD_TRANSFER_DIRECTION_IN\n");
if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_OUT)
DPRINT1("USBD_TRANSFER_DIRECTION_OUT\n");
if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_SHORT_TRANSFER_OK)
DPRINT1("USBD_SHORT_TRANSFER_OK\n");
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
DPRINT("EndPoint is transfer type %x\n", EndPointDesc->bmAttributes & 0x0F);
DPRINT("Endpoint Address %x\n", EndPointDesc->bEndpointAddress & 0x0F);
if ((EndPointDesc->bmAttributes & 0x0F) == USB_ENDPOINT_TYPE_BULK)
{
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
UsbDevice,
Urb->UrbBulkOrInterruptTransfer.PipeHandle,
NULL,
Urb->UrbBulkOrInterruptTransfer.TransferFlags,
Urb->UrbBulkOrInterruptTransfer.TransferBuffer ?
Urb->UrbBulkOrInterruptTransfer.TransferBuffer :
(PVOID)Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL,
Urb->UrbBulkOrInterruptTransfer.TransferBuffer ?
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength : 0,
Irp);
}
else
{
DPRINT1("Transfer Type not implemented yet!\n");
/* FAKE IT */
Status = STATUS_SUCCESS;
}
break;
}
if (!Urb->UrbBulkOrInterruptTransfer.TransferBuffer)
{
DPRINT1("TransferBuffer is NULL!\n");
ASSERT(FALSE);
break;
}
ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer != NULL);
RtlZeroMemory(Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
if (UsbDevice == PdoDeviceExtension->UsbDevices[0])
@ -122,9 +172,9 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK))
{
LONG i;
for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
for (i = 0; i < hcd->ECHICaps.HCSParams.PortCount; i++)
{
if (PdoDeviceExtension->Ports[i].PortChange)
if (hcd->Ports[i].PortChange)
{
DPRINT1("Inform hub driver that port %d has changed\n", i+1);
((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((i + 1) & 7);
@ -177,11 +227,8 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
if (UsbDevice == PdoDeviceExtension->UsbDevices[0])
{
DPRINT1("ROOTHUB!\n");
BufPtr = (PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer;
DPRINT1("Length %x\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
/* Copy the Device Descriptor */
RtlCopyMemory(BufPtr, &UsbDevice->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
DumpDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer);
@ -193,11 +240,17 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
Urb->UrbControlDescriptorRequest.TransferBuffer,
Urb->UrbControlDescriptorRequest.TransferBufferLength,
Irp);
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
UsbDevice,
0,
&CtrlSetup,
0,
Urb->UrbControlDescriptorRequest.TransferBuffer ?
Urb->UrbControlDescriptorRequest.TransferBuffer :
(PVOID)Urb->UrbControlDescriptorRequest.TransferBufferMDL,
Urb->UrbControlDescriptorRequest.TransferBuffer ?
Urb->UrbControlDescriptorRequest.TransferBufferLength : 0,
Irp);
break;
}
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
@ -270,12 +323,17 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
Urb->UrbControlDescriptorRequest.TransferBuffer,
Urb->UrbControlDescriptorRequest.TransferBufferLength,
Irp);
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
UsbDevice,
0,
&CtrlSetup,
0,
Urb->UrbControlDescriptorRequest.TransferBuffer ?
Urb->UrbControlDescriptorRequest.TransferBuffer :
(PVOID)Urb->UrbControlDescriptorRequest.TransferBufferMDL,
Urb->UrbControlDescriptorRequest.TransferBuffer ?
Urb->UrbControlDescriptorRequest.TransferBufferLength : 0,
Irp);
break;
}
default:
@ -290,17 +348,17 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
LONG iCount, pCount;
DPRINT1("Selecting Configuration\n");
DPRINT1("ConfigurationHandle %x\n",Urb->UrbSelectConfiguration.ConfigurationHandle);
DPRINT("Selecting Configuration\n");
DPRINT("ConfigurationHandle %x\n",Urb->UrbSelectConfiguration.ConfigurationHandle);
if (Urb->UrbSelectConfiguration.ConfigurationDescriptor)
{
Urb->UrbSelectConfiguration.ConfigurationHandle = &UsbDevice->ActiveConfig->ConfigurationDescriptor;
DPRINT1("ConfigHandle %x\n", Urb->UrbSelectConfiguration.ConfigurationHandle);
ASSERT(FALSE);
DPRINT("ConfigHandle %x\n", Urb->UrbSelectConfiguration.ConfigurationHandle);
InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
DPRINT1("Length %x\n", InterfaceInfo->Length);
DPRINT1("NumberOfPipes %x\n", InterfaceInfo->NumberOfPipes);
DPRINT("Length %x\n", InterfaceInfo->Length);
DPRINT("NumberOfPipes %x\n", InterfaceInfo->NumberOfPipes);
for (iCount = 0; iCount < Urb->UrbSelectConfiguration.ConfigurationDescriptor->bNumInterfaces; iCount++)
{
@ -324,6 +382,29 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length);
if (InterfaceInfo->Length == 0) break;
}
if (UsbDevice != PdoDeviceExtension->UsbDevices[0])
{
DPRINT("Setting Configuration!\n");
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
DPRINT1("Input Buffer %x, MDL %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, (PVOID)Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
UsbDevice,
0,
&CtrlSetup,
0,
NULL,
0,
Irp);
break;
}
else
{
DPRINT1("Hub only has one configuration.\n");
}
}
else
{
@ -334,7 +415,6 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
case URB_FUNCTION_SELECT_INTERFACE:
{
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
int i;
@ -353,12 +433,14 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
NULL,
0,
Irp);
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
UsbDevice,
0,
&CtrlSetup,
0,
NULL,
0,
Irp);
break;
}
case URB_FUNCTION_CLASS_DEVICE:
@ -425,7 +507,6 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
else
{
/* FIXME: Handle this correctly */
UsbHubDescr->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
UsbHubDescr->bDescriptorType = 0x29;
break;
@ -433,7 +514,7 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
DPRINT1("USB_DEVICE_CLASS_HUB request\n");
UsbHubDescr->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
UsbHubDescr->bDescriptorType = 0x29;
UsbHubDescr->bNumberOfPorts = PdoDeviceExtension->NumberOfPorts;
UsbHubDescr->bNumberOfPorts = hcd->ECHICaps.HCSParams.PortCount;
UsbHubDescr->wHubCharacteristics = 0x0012;
UsbHubDescr->bPowerOnToPowerGood = 0x01;
UsbHubDescr->bHubControlCurrent = 0x00;
@ -480,10 +561,10 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
DPRINT("USB_REQUEST_GET_STATUS Port %d\n", Urb->UrbControlVendorClassRequest.Index);
ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer != 0);
DPRINT("PortStatus %x\n", PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus);
DPRINT("PortChange %x\n", PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange);
((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus;
((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[1] = PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange;
DPRINT("PortStatus %x\n", hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus);
DPRINT("PortChange %x\n", hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange);
((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus;
((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[1] = hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange;
break;
}
case USB_REQUEST_CLEAR_FEATURE:
@ -492,12 +573,12 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
{
case C_PORT_CONNECTION:
DPRINT("C_PORT_CONNECTION\n");
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_CONNECT;
hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_CONNECT;
break;
case C_PORT_RESET:
DPRINT("C_PORT_RESET\n");
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_RESET;
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus |= USB_PORT_STATUS_ENABLE;
hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_RESET;
hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus |= USB_PORT_STATUS_ENABLE;
break;
default:
DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
@ -507,46 +588,49 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
case USB_REQUEST_SET_FEATURE:
{
DPRINT("USB_REQUEST_SET_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
DPRINT1("USB_REQUEST_SET_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
Urb->UrbControlVendorClassRequest.Value);
switch(Urb->UrbControlVendorClassRequest.Value)
{
case PORT_RESET:
{
DPRINT("Port Reset %d\n", Urb->UrbControlVendorClassRequest.Index-1);
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange |= USB_PORT_STATUS_RESET;
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus &= ~USB_PORT_STATUS_ENABLE;
ResetPort(&FdoDeviceExtension->hcd, Urb->UrbControlVendorClassRequest.Index-1);
DPRINT1("Port Reset %d\n", Urb->UrbControlVendorClassRequest.Index-1);
hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange |= USB_PORT_STATUS_RESET;
hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus &= ~USB_PORT_STATUS_ENABLE;
ResetPort(hcd, Urb->UrbControlVendorClassRequest.Index-1);
break;
}
case PORT_ENABLE:
{
DPRINT("PORT_ENABLE not implemented\n");
DPRINT1("PORT_ENABLE not implemented\n");
break;
}
case PORT_POWER:
{
DPRINT("PORT_POWER not implemented\n");
DPRINT1("PORT_POWER not implemented\n");
break;
}
default:
{
DPRINT("Unknown Set Feature!\n");
DPRINT1("Unknown Set Feature!\n");
break;
}
}
if (!(PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus & 0x8000))
if (!(hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus & 0x8000))
{
DPRINT1("------ PortStatus %x\n", hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus);
DPRINT1("Calling CompletePendingURBRequest\n");
CompletePendingURBRequest(PdoDeviceExtension);
}
break;
}
case USB_REQUEST_SET_ADDRESS:
{
DPRINT1("USB_REQUEST_SET_ADDRESS\n");
ASSERT(FALSE);
break;
}
case USB_REQUEST_GET_DESCRIPTOR:
@ -606,7 +690,35 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
case URB_FUNCTION_CLASS_INTERFACE:
{
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
CtrlSetup.bmRequestType.B = 0xa1; //FIXME: Const.
CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
UsbDevice,
0,
&CtrlSetup,
0,
Urb->UrbControlVendorClassRequest.TransferBuffer ?
Urb->UrbControlVendorClassRequest.TransferBuffer :
(PVOID)Urb->UrbControlVendorClassRequest.TransferBufferMDL,
Urb->UrbControlVendorClassRequest.TransferBuffer ?
Urb->UrbControlVendorClassRequest.TransferBufferLength : 0,
Irp);
break;
}
default:
@ -632,8 +744,9 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
if (IsListEmpty(&DeviceExtension->IrpQueue))
{
DPRINT1("There should have been one SCE request pending\n");
DPRINT1("There should have been one SCE request pending. Did the usbhub driver load?\n");
KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
ASSERT(FALSE);
return;
}
NextIrp = RemoveHeadList(&DeviceExtension->IrpQueue);

View file

@ -47,12 +47,8 @@ const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR [] =
0x01, /* bNumInterfaces; (1) */
0x23, /* bConfigurationValue; */
0x00, /* iConfiguration; */
0x40, /* bmAttributes;
Bit 7: must be set,
6: Self-powered,
5: Remote wakeup,
4..0: reserved */
0x00 /* MaxPower; */
0x40, /* bmAttributes; */
0x00 /* MaxPower; */
};
const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
@ -66,7 +62,7 @@ const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
0x09, /* bInterfaceClass; HUB_CLASSCODE */
0x01, /* bInterfaceSubClass; */
0x00, /* bInterfaceProtocol: */
0x00 /* iInterface; */
0x00 /* iInterface; */
};
const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] =
@ -88,12 +84,14 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
PIO_STACK_LOCATION Stack = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ULONG_PTR Information = 0;
PEHCI_HOST_CONTROLLER hcd;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) PdoDeviceExtension->ControllerFdo->DeviceExtension;
ASSERT(PdoDeviceExtension->Common.IsFdo == FALSE);
hcd = &FdoDeviceExtension->hcd;
Stack = IoGetCurrentIrpStackLocation(Irp);
switch(Stack->Parameters.DeviceIoControl.IoControlCode)
@ -108,13 +106,18 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
UsbDevice = Urb->UrbHeader.UsbdDeviceHandle;
/* If there was no device passed then this URB is for the RootHub */
if (UsbDevice == NULL)
UsbDevice = PdoDeviceExtension->UsbDevices[0];
/* Check if it is a Status Change Endpoint (SCE). The Hub Driver sends this request and miniports mark the IRP pending
if there is no changes on any of the ports. When the DPC of miniport routine detects changes this IRP will be completed.
Based on XEN PV Usb Drivers */
if ((Urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) &&
(UsbDevice == PdoDeviceExtension->UsbDevices[0]))
{
DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER on SCE\n");
DPRINT("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER on SCE\n");
if (Urb->UrbBulkOrInterruptTransfer.PipeHandle != &UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor)
{
DPRINT1("PipeHandle doesnt match SCE PipeHandle\n");
@ -123,12 +126,23 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
/* Queue the Irp first */
QueueURBRequest(PdoDeviceExtension, Irp);
/* Check if there is any connected devices */
for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
/* Check for port changes */
if (EnumControllerPorts(hcd) == FALSE)
{
if (PdoDeviceExtension->Ports[i].PortChange == 0x01)
DPRINT("No port change\n");
Status = STATUS_PENDING;
IoMarkIrpPending(Irp);
break;
}
/* If we reached this point then port status has changed, so check
which port */
for (i = 0; i < hcd->ECHICaps.HCSParams.PortCount; i++)
{
if (hcd->Ports[i].PortChange == 0x01)
{
DPRINT1("Inform hub driver that port %d has changed\n", i+1);
DPRINT1("On SCE request: Inform hub driver that port %d has changed\n", i+1);
ASSERT(FALSE);
((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((i + 1) & 7);
Information = 0;
Status = STATUS_SUCCESS;
@ -143,15 +157,11 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
}
}
if (Status == STATUS_SUCCESS) break;
DPRINT1("Queueing IRP\n");
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
break;
}
else
{
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB send to device %x\n", UsbDevice);
}
Status = HandleUrbRequest(PdoDeviceExtension, Irp);
@ -186,7 +196,7 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
}
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
{
DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", Stack->Parameters.Others.Argument2);
DPRINT1("Ehci: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", Stack->Parameters.Others.Argument2);
if (Stack->Parameters.Others.Argument1)
{
/* Return the root hubs devicehandle */
@ -202,12 +212,12 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
}
case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
{
DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT);
DPRINT1("Ehci: IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT);
ASSERT(Stack->Parameters.Others.Argument1 != NULL);
if (Stack->Parameters.Others.Argument1)
{
/* FIXME: Determine the number of hubs between the usb device and root hub */
DPRINT1("RootHubCount %x\n", *(PULONG)Stack->Parameters.Others.Argument1);
/* FIXME: Determine the number of hubs between the usb device and root hub.
For now we have at least one. */
*(PULONG)Stack->Parameters.Others.Argument1 = 1;
}
Status = STATUS_SUCCESS;
@ -235,15 +245,14 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
}
case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
{
DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO Arg1 %x, Arg2 %x\n", Stack->Parameters.Others.Argument1, Stack->Parameters.Others.Argument2);
DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
/* DDK documents that both the PDO and FDO are returned. However, while writing the UsbHub driver it was determine
that this was not the case. Windows usbehci driver gives the Pdo in both Arguments. Which makes sense as upper level
drivers should not be communicating with FDO. */
if (Stack->Parameters.Others.Argument1)
*(PVOID *)Stack->Parameters.Others.Argument1 = FdoDeviceExtension->Pdo;
/* Windows usbehci driver gives the Pdo in both Arguments. */
if (Stack->Parameters.Others.Argument2)
//*(PVOID *)Stack->Parameters.Others.Argument2 = IoGetAttachedDeviceReference(FdoDeviceExtension->DeviceObject);
*(PVOID *)Stack->Parameters.Others.Argument2 = FdoDeviceExtension->Pdo;
Information = 0;
Status = STATUS_SUCCESS;
break;
@ -254,8 +263,6 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
DPRINT1("Ehci: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
/* FIXME: Set Callback for safe power down */
CallBackInfo = Stack->Parameters.DeviceIoControl.Type3InputBuffer;
DPRINT1("IdleCallback %x\n", CallBackInfo->IdleCallback);
DPRINT1("IdleContext %x\n", CallBackInfo->IdleContext);
PdoDeviceExtension->IdleCallback = CallBackInfo->IdleCallback;
PdoDeviceExtension->IdleContext = CallBackInfo->IdleContext;
@ -300,6 +307,7 @@ PdoQueryId(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG_PTR* Information)
}
case BusQueryHardwareIDs:
{
/* FIXME: Build from Device Vendor and Device ID */
Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID8086&PID265C&REV0000") + 1;
Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID8086&PID265C") + 1;
Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
@ -388,7 +396,6 @@ PdoDispatchPnp(
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
UNICODE_STRING InterfaceSymLinkName;
LONG i;
DPRINT1("Ehci: PDO StartDevice\n");
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
@ -397,15 +404,6 @@ PdoDispatchPnp(
/* Create the root hub */
RootHubDevice = InternalCreateUsbDevice(1, 0, NULL, TRUE);
for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
{
PdoDeviceExtension->Ports[i].PortStatus = 0x8000;
PdoDeviceExtension->Ports[i].PortChange = 0;
if (!FdoDeviceExtension->hcd.ECHICaps.HCSParams.PortPowerControl)
PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_POWER;
}
RtlCopyMemory(&RootHubDevice->DeviceDescriptor,
ROOTHUB2_DEVICE_DESCRIPTOR,
sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
@ -413,7 +411,8 @@ PdoDispatchPnp(
RootHubDevice->DeviceDescriptor.idVendor = FdoDeviceExtension->VendorId;
RootHubDevice->DeviceDescriptor.idProduct = FdoDeviceExtension->DeviceId;
/* FIXME: Do something better below */
/* Here config, interfaces and descriptors are stored. This was duplicated from XEN PV Usb Drivers implementation.
Not sure that it is really needed as the information can be queueried from the device. */
RootHubDevice->Configs = ExAllocatePoolWithTag(NonPagedPool,
sizeof(PVOID) * RootHubDevice->DeviceDescriptor.bNumConfigurations,
@ -483,11 +482,11 @@ PdoDispatchPnp(
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DPRINT1("BusRelations!!!!!\n");
DPRINT("BusRelations!!!!!\n");
/* The hub driver has created the new device object and reported to pnp, as a result the pnp manager
has resent this IRP and type, so leave the next SCE request pending until a new device arrives.
Is there a better way to do this */
has sent this IRP and type, so leave the next SCE request pending until a new device arrives.
Is there a better way to do this? */
ExAcquireFastMutex(&PdoDeviceExtension->ListLock);
PdoDeviceExtension->HaltQueue = TRUE;
ExReleaseFastMutex(&PdoDeviceExtension->ListLock);
@ -531,7 +530,7 @@ PdoDispatchPnp(
DeviceCapabilities->UINumber = 0;
DeviceCapabilities->DeviceD2 = 1;
/* FIXME */
/* FIXME: Verify these settings are correct */
DeviceCapabilities->HardwareDisabled = FALSE;
//DeviceCapabilities->NoDisplayInUI = FALSE;
DeviceCapabilities->DeviceState[0] = PowerDeviceD0;

View file

@ -7,9 +7,20 @@
* Michael Martin (michael.martin@reactos.org)
*/
/* All QueueHeads, Descriptors and pipe setup packets used by control transfers are allocated from common buffer.
The routines in physmem manages this buffer. Each allocation is aligned to 32bits, which is requirement of USB 2.0. */
#include "transfer.h"
#include <debug.h>
typedef struct _MAPREGISTERCALLBACKINFO
{
PVOID MapRegisterBase;
KEVENT Event;
}MAPREGISTERCALLBACKINFO, *PMAPREGISTERCALLBACKINFO;
/* Fills CtrlSetup parameter with values based on Urb */
VOID
BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd, PURB Urb, PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup)
{
@ -76,6 +87,7 @@ BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd, PURB Urb, PUSB_DEFAULT_PIPE_S
/* SET CONFIG */
case URB_FUNCTION_SELECT_CONFIGURATION:
DPRINT1("Bulding data for Select Config\n");
CtrlSetup->bRequest = USB_REQUEST_SET_CONFIGURATION;
CtrlSetup->wValue.W = Urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue;
CtrlSetup->wIndex.W = 0;
@ -131,18 +143,86 @@ BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd, PURB Urb, PUSB_DEFAULT_PIPE_S
}
}
BOOLEAN
SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
PVOID TransferBuffer,
ULONG TransferBufferLength,
PIRP IrpToComplete)
/* Build a Bulk Transfer with a max transfer of 3 descriptors which each has 5 pointers to one page of memory, paged align of course */
PQUEUE_HEAD
BuildBulkTransfer(PEHCI_HOST_CONTROLLER hcd,
ULONG DeviceAddress,
USBD_PIPE_HANDLE PipeHandle,
UCHAR PidDirection,
PMDL pMdl,
BOOLEAN FreeMdl)
{
PQUEUE_HEAD QueueHead;
PQUEUE_TRANSFER_DESCRIPTOR Descriptor[3];
ULONG MdlByteCount = MmGetMdlByteCount(pMdl);
ULONG NeededDescriptorCount = 1;
int i;
QueueHead = CreateQueueHead(hcd);
QueueHead->EndPointCharacteristics.DeviceAddress = DeviceAddress;
if (PipeHandle)
{
QueueHead->EndPointCharacteristics.EndPointNumber = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->bEndpointAddress & 0x0F;
QueueHead->EndPointCharacteristics.MaximumPacketLength = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->wMaxPacketSize;
}
QueueHead->FreeMdl = FreeMdl;
QueueHead->Mdl = pMdl;
/* FIXME: This is totally screwed */
/* Calculate how many descriptors would be needed to transfer this buffer */
if (pMdl)
{
if (MdlByteCount < (PAGE_SIZE * 5))
NeededDescriptorCount = 1;
else if (MdlByteCount < (PAGE_SIZE * 10))
NeededDescriptorCount = 2;
else if (MdlByteCount < (PAGE_SIZE * 15))
NeededDescriptorCount = 3;
else
ASSERT(FALSE);
}
/* Limiter Transfers to PAGE_SIZE * 5 * 3, Three Descriptors */
QueueHead->NumberOfTransferDescriptors = NeededDescriptorCount;
for (i=0; i< NeededDescriptorCount;i++)
{
Descriptor[i] = CreateDescriptor(hcd,
PidDirection,
0);
Descriptor[i]->AlternateNextPointer = QueueHead->DeadDescriptor->PhysicalAddr;
if (i > 0)
{
Descriptor[i-1]->NextDescriptor = Descriptor[i];
Descriptor[i]->PreviousDescriptor = Descriptor[i-1];
Descriptor[i-1]->NextPointer = Descriptor[i]->PhysicalAddr;
}
}
Descriptor[0]->Token.Bits.InterruptOnComplete = TRUE;
/* Save the first descriptor in the QueueHead */
QueueHead->FirstTransferDescriptor = Descriptor[0];
QueueHead->NextPointer = Descriptor[0]->PhysicalAddr;
return QueueHead;
}
/* Builds a QueueHead with 2 to 3 descriptors needed for control transfer
2 descriptors used for and control request that doesnt return data, such as SetAddress */
PQUEUE_HEAD
BuildControlTransfer(PEHCI_HOST_CONTROLLER hcd,
ULONG DeviceAddress,
USBD_PIPE_HANDLE PipeHandle,
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
PMDL pMdl,
BOOLEAN FreeMdl)
{
PQUEUE_HEAD QueueHead;
PQUEUE_TRANSFER_DESCRIPTOR Descriptor[3];
ULONG MdlPhysicalAddr;
PKEVENT Event = NULL;
PMDL pMdl = NULL;
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetupVA, CtrlPhysicalPA;
CtrlSetupVA = (PUSB_DEFAULT_PIPE_SETUP_PACKET)AllocateMemory(hcd,
@ -150,57 +230,45 @@ SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
(ULONG*)&CtrlPhysicalPA);
RtlCopyMemory(CtrlSetupVA, CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
/* If no Irp then wait on completion */
if (IrpToComplete == NULL)
{
Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
KeInitializeEvent(Event, NotificationEvent, FALSE);
}
if (TransferBuffer)
{
/* Allocate Mdl for Buffer */
pMdl = IoAllocateMdl(TransferBuffer,
TransferBufferLength,
FALSE,
FALSE,
NULL);
/* Lock Physical Pages */
MmBuildMdlForNonPagedPool(pMdl);
//MmProbeAndLockPages(pMdl, KernelMode, IoReadAccess);
MdlPhysicalAddr = MmGetPhysicalAddress((PVOID)TransferBuffer).LowPart;
}
QueueHead = CreateQueueHead(hcd);
QueueHead->EndPointCharacteristics.DeviceAddress = DeviceAddress;
if (PipeHandle)
QueueHead->EndPointCharacteristics.EndPointNumber = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->bEndpointAddress & 0x0F;
QueueHead->Token.Bits.DataToggle = TRUE;
QueueHead->FreeMdl = FreeMdl;
QueueHead->Mdl = pMdl;
Descriptor[0] = CreateDescriptor(hcd,
PID_CODE_SETUP_TOKEN,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
Descriptor[0]->Token.Bits.InterruptOnComplete = FALSE;
Descriptor[0]->Token.Bits.DataToggle = FALSE;
/* Save the first descriptor */
QueueHead->TransferDescriptor = Descriptor[0];
QueueHead->FirstTransferDescriptor = Descriptor[0];
if (TransferBuffer)
if (pMdl)
{
Descriptor[1] = CreateDescriptor(hcd,
PID_CODE_IN_TOKEN,
TransferBufferLength);
MmGetMdlByteCount(pMdl));
Descriptor[2] = CreateDescriptor(hcd,
PID_CODE_OUT_TOKEN,
0);
}
else
{
Descriptor[2] = CreateDescriptor(hcd,
PID_CODE_IN_TOKEN,
0);
}
Descriptor[2] = CreateDescriptor(hcd,
PID_CODE_OUT_TOKEN,
0);
Descriptor[1]->Token.Bits.InterruptOnComplete = FALSE;
Descriptor[2]->Token.Bits.InterruptOnComplete = TRUE;
/* Link the descriptors */
if (TransferBuffer)
if (pMdl)
{
Descriptor[0]->NextDescriptor = Descriptor[1];
Descriptor[1]->NextDescriptor = Descriptor[2];
@ -213,35 +281,267 @@ SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
Descriptor[2]->PreviousDescriptor = Descriptor[0];
}
/* Assign the descritors buffers */
/* Assign the descriptor buffers */
Descriptor[0]->BufferPointer[0] = (ULONG)CtrlPhysicalPA;
if (TransferBuffer)
{
Descriptor[1]->BufferPointer[0] = MdlPhysicalAddr;
Descriptor[0]->BufferPointerVA[0] = (ULONG)CtrlSetupVA;
if (pMdl)
{
Descriptor[0]->NextPointer = Descriptor[1]->PhysicalAddr;
Descriptor[1]->NextPointer = Descriptor[2]->PhysicalAddr;
Descriptor[0]->AlternateNextPointer = Descriptor[2]->PhysicalAddr;
Descriptor[1]->NextPointer = Descriptor[2]->PhysicalAddr;
Descriptor[1]->AlternateNextPointer = Descriptor[2]->PhysicalAddr;
}
else
{
Descriptor[0]->NextPointer = Descriptor[2]->PhysicalAddr;
Descriptor[0]->AlternateNextPointer = Descriptor[2]->PhysicalAddr;
}
QueueHead->NextPointer = Descriptor[0]->PhysicalAddr;
if (pMdl)
QueueHead->NumberOfTransferDescriptors = 3;
else
QueueHead->NumberOfTransferDescriptors = 2;
return QueueHead;
}
QueueHead->IrpToComplete = IrpToComplete;
QueueHead->MdlToFree = pMdl;
QueueHead->Event = Event;
/* Link in the QueueHead */
LinkQueueHead(hcd, QueueHead);
IO_ALLOCATION_ACTION NTAPI MapRegisterCallBack(PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID MapRegisterBase,
PVOID Context)
{
PMAPREGISTERCALLBACKINFO CallBackInfo = (PMAPREGISTERCALLBACKINFO)Context;
CallBackInfo->MapRegisterBase = MapRegisterBase;
KeSetEvent(&CallBackInfo->Event, IO_NO_INCREMENT, FALSE);
return KeepObject;
}
NTSTATUS
ExecuteTransfer(PDEVICE_OBJECT DeviceObject,
PUSB_DEVICE UsbDevice,
USBD_PIPE_HANDLE PipeHandle,
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
ULONG TransferFlags,
PVOID TransferBufferOrMdl,
ULONG TransferBufferLength,
PIRP IrpToComplete)
{
PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
PEHCI_HOST_CONTROLLER hcd;
PQUEUE_HEAD QueueHead;
PKEVENT CompleteEvent = NULL;
PMAPREGISTERCALLBACKINFO CallBackInfo;
LARGE_INTEGER TimeOut;
PMDL pMdl = NULL;
BOOLEAN FreeMdl = FALSE;
PVOID VirtualAddressOfMdl;
ULONG NumberOfMapRegisters;
KIRQL OldIrql;
NTSTATUS Status = STATUS_SUCCESS;
UCHAR EndPointType, PidDirection;
BOOLEAN IsReadOp = TRUE;
ULONG TransferBtyesOffset, CurrentTransferBytes;
PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
PHYSICAL_ADDRESS PhysicalAddr;
int i,j;
hcd = &((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->hcd;
/* If no Irp then we will need to wait on completion */
if (IrpToComplete == NULL)
{
DPRINT1("Waiting For Completion %x!\n", Event);
KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL);
ExFreePool(Event);
CompleteEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
KeInitializeEvent(CompleteEvent, NotificationEvent, FALSE);
}
return TRUE;
CallBackInfo = ExAllocatePool(NonPagedPool, sizeof(MAPREGISTERCALLBACKINFO));
CallBackInfo->MapRegisterBase = 0;
KeInitializeEvent(&CallBackInfo->Event, NotificationEvent, FALSE);
/* Determine EndPoint Type */
if (!PipeHandle)
{
EndPointType = USB_ENDPOINT_TYPE_CONTROL;
}
else
{
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)PipeHandle;
EndPointType = EndPointDesc->bmAttributes & 0x0F;
}
if (TransferBufferOrMdl)
{
/* Create MDL for Buffer */
if (TransferBufferLength)
{
pMdl = IoAllocateMdl(TransferBufferOrMdl,
TransferBufferLength,
FALSE,
FALSE,
NULL);
/* UEHCI created the MDL so it needs to free it */
FreeMdl = TRUE;
}
else
{
pMdl = TransferBufferOrMdl;
}
MmBuildMdlForNonPagedPool(pMdl);
}
switch (EndPointType)
{
case USB_ENDPOINT_TYPE_CONTROL:
{
QueueHead = BuildControlTransfer(hcd,
UsbDevice->Address,
PipeHandle,
CtrlSetup,
pMdl,
FreeMdl);
IsReadOp = TRUE;
break;
}
case USB_ENDPOINT_TYPE_BULK:
{
PidDirection = EndPointDesc->bEndpointAddress >> 7;
if (PidDirection)
IsReadOp = FALSE;
QueueHead = BuildBulkTransfer(hcd,
UsbDevice->Address,
PipeHandle,
PidDirection,
pMdl,
FreeMdl);
break;
}
case USB_ENDPOINT_TYPE_INTERRUPT:
{
DPRINT1("Interrupt Endpoints not implemented yet!\n");
break;
}
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
{
DPRINT1("Isochronous Endpoints not implemented yet!\n");
break;
}
default:
{
DPRINT1("Unknown Endpoint type!!\n");
break;
}
}
QueueHead->IrpToComplete = IrpToComplete;
QueueHead->Event = CompleteEvent;
if (!pMdl)
{
ASSERT(QueueHead->NumberOfTransferDescriptors == 2);
LinkQueueHead(hcd, QueueHead);
if (IrpToComplete == NULL)
{
DPRINT1("Waiting For Completion %x!\n", CompleteEvent);
TimeOut.QuadPart = -10000000;
KeWaitForSingleObject(CompleteEvent, Suspended, KernelMode, FALSE, NULL);//&TimeOut);
DPRINT1("Request Completed\n");
ExFreePool(CompleteEvent);
}
return Status;
}
//ASSERT(FALSE);
KeFlushIoBuffers(pMdl, IsReadOp, TRUE);
NumberOfMapRegisters = 15;
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
hcd->pDmaAdapter->DmaOperations->AllocateAdapterChannel(hcd->pDmaAdapter,
((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ControllerFdo,
NumberOfMapRegisters,
MapRegisterCallBack,
(PVOID)CallBackInfo);
KeLowerIrql(OldIrql);
DPRINT1("Waiting for AdapterChannel\n");
KeWaitForSingleObject(&CallBackInfo->Event, Suspended, KernelMode, FALSE, NULL);
DPRINT1("Dma controller ready!\n");
DPRINT1("Getting address for MDL %x\n", pMdl);
VirtualAddressOfMdl = MmGetMdlVirtualAddress(pMdl);
TransferBtyesOffset = 0;
while (TransferBtyesOffset < MmGetMdlByteCount(pMdl))
{
CurrentTransferBytes = MmGetMdlByteCount(pMdl);
Descriptor = QueueHead->FirstTransferDescriptor;
if ((Descriptor->Token.Bits.PIDCode == PID_CODE_SETUP_TOKEN) && (QueueHead->NumberOfTransferDescriptors == 3))
{
DPRINT1("QueueHead is for endpoint 0\n");
DPRINT1("MapRegisterBase %x\n", CallBackInfo->MapRegisterBase);
DPRINT1("VirtualAddressOfMdl %x, TransferBytesOffset %x\n", VirtualAddressOfMdl, TransferBtyesOffset);
Descriptor = Descriptor->NextDescriptor;
PhysicalAddr = hcd->pDmaAdapter->DmaOperations->MapTransfer(hcd->pDmaAdapter,
pMdl,
CallBackInfo->MapRegisterBase,
(PVOID)((ULONG_PTR)VirtualAddressOfMdl + TransferBtyesOffset),
&CurrentTransferBytes,
!IsReadOp);
DPRINT1("BufferPointer[0] = %x\n", PhysicalAddr.LowPart);
Descriptor->BufferPointer[0] = PhysicalAddr.LowPart;
DPRINT1("CurrentTransferBytes %x\n", CurrentTransferBytes);
TransferBtyesOffset += CurrentTransferBytes;
LinkQueueHead(hcd, QueueHead);
break;
}
DPRINT1("PID_CODE_SETUP_TOKEN %x, PidDirection %x, NumDesc %x\n", PID_CODE_SETUP_TOKEN, PidDirection, QueueHead->NumberOfTransferDescriptors);
for (i=0; i<QueueHead->NumberOfTransferDescriptors; i++)
{
if (Descriptor->Token.Bits.PIDCode != PID_CODE_SETUP_TOKEN)
{
for (j=0; j<5; j++)
{
PhysicalAddr = hcd->pDmaAdapter->DmaOperations->MapTransfer(hcd->pDmaAdapter,
pMdl,
CallBackInfo->MapRegisterBase,
(PVOID)((ULONG_PTR)VirtualAddressOfMdl + TransferBtyesOffset),
&CurrentTransferBytes,
!IsReadOp);
DPRINT1("BufferPointer[%d] = %x\n", j, PhysicalAddr.LowPart);
Descriptor->BufferPointer[j] = PhysicalAddr.LowPart;
TransferBtyesOffset += CurrentTransferBytes;
if (TransferBtyesOffset >= MmGetMdlByteCount(pMdl))
break;
}
}
Descriptor = Descriptor->NextDescriptor;
}
LinkQueueHead(hcd, QueueHead);
break;
}
if (TransferBtyesOffset < MmGetMdlByteCount(pMdl)) ASSERT(FALSE);
if (IrpToComplete == NULL)
{
DPRINT1("Waiting For Completion %x!\n", CompleteEvent);
TimeOut.QuadPart = -10000000;
KeWaitForSingleObject(CompleteEvent, Suspended, KernelMode, FALSE, NULL);//&TimeOut);
DPRINT1("Request Completed\n");
ExFreePool(CompleteEvent);
}
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
hcd->pDmaAdapter->DmaOperations->FreeMapRegisters(hcd->pDmaAdapter,
CallBackInfo->MapRegisterBase,
NumberOfMapRegisters);
hcd->pDmaAdapter->DmaOperations->FreeAdapterChannel (hcd->pDmaAdapter);
KeLowerIrql(OldIrql);
return Status;
}

View file

@ -3,18 +3,37 @@
#include "hardware.h"
#include "hwiface.h"
#include "physmem.h"
#include "usbehci.h"
#include <usb.h>
#include <ntddk.h>
BOOLEAN
SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
PVOID TransferBuffer,
ULONG TransferBufferLength,
PIRP IrpToComplete);
PQUEUE_HEAD
BuildControlTransfer(PEHCI_HOST_CONTROLLER hcd,
ULONG DeviceAddress,
USBD_PIPE_HANDLE PipeHandle,
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
PMDL pMdl,
BOOLEAN FreeMdl);
PQUEUE_HEAD
BuildBulkTransfer(PEHCI_HOST_CONTROLLER hcd,
ULONG DeviceAddress,
USBD_PIPE_HANDLE PipeHandle,
UCHAR PidDirection,
PMDL pMdl,
BOOLEAN FreeMdl);
VOID
BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd,
PURB Urb,
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup);
NTSTATUS
ExecuteTransfer(PDEVICE_OBJECT DeviceObject,
PUSB_DEVICE UsbDevice,
USBD_PIPE_HANDLE PipeHandle,
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
ULONG TransferFlags,
PVOID TransferBufferOrMdl,
ULONG TransferBufferLength,
PIRP IrpToComplete);