📄 usbios.c
字号:
// 16 times slower than normal. To deal with this we schedule a DPC
// callback that will submit the bulk transfers when bandwidth
// reclamation is enabled.
USBLS120_KdPrint( DBGLVL_HIGH,("Queuing Data Xfer DPC\n"));
// Queue the DPC
KeInsertQueueDpc(DeviceExtension->TransferDataDpc, Reference, 0 );
} else {
USBLS120_KdPrint( DBGLVL_HIGH,("Request completed successfully\n"));
IoFreeIrp(Irp);
ExFreePool(Urb);
// Command phase completed successfully, with no data phase needed.
// Notify port driver and return.
IoPacket->Status = IO_STATUS_SUCCESS;
DeviceExtension->CompleteRequest(IoPacket);
}
// All driver-orignated IRPs must return
// STATUS_MORE_PROCESSING_REQUIRED.
return STATUS_MORE_PROCESSING_REQUIRED;
}
VOID
USBLS120_TransferDataWorker(
IN PVOID DeviceObject
)
/*++
Routine Description:
Worker function for resetting bulk pipe after stall.
Arguments:
DeviceObject - Previous device object.
Return Value:
None.
--*/
{
PDEVICE_EXTENSION DeviceExtension;
USBLS120_KdPrint( DBGLVL_MEDIUM,("enter USBLS120_TransferDataError\n"));
DeviceExtension = ((PDEVICE_OBJECT)(DeviceObject))->DeviceExtension;
USBLS120_ResetPipe(
(PDEVICE_OBJECT)(DeviceObject),
(DeviceExtension->IoPacket->Flags & IO_FLAGS_DATA_IN) ?
&(DeviceExtension->UsbInterface->Pipes[DeviceExtension->DataInPipe]) :
&(DeviceExtension->UsbInterface->Pipes[DeviceExtension->DataOutPipe])
);
DeviceExtension->IoPacket->Status = IO_STATUS_DEVICE_ERROR;
DeviceExtension->CompleteRequest(DeviceExtension->IoPacket);
ExFreePool(DeviceExtension->WorkItem);
}
VOID
USBLS120_TransferDataDPC(
PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2
)
/*++
Routine Description:
DPC handler used to schedule bulk data transfer to/from the device
after command phase.
Arguments:
Dpc - DPC object.
DeferredContext - N/A
SystemArgument1 - Points to our Device Object
SystemArgument2 - N/A
Return Value:
None.
--*/
{
PDEVICE_OBJECT DeviceObject;
USBLS120_KdPrint( DBGLVL_HIGH,("enter USBLS120_TransferDataDPC\n"));
DeviceObject = (PDEVICE_OBJECT)SystemArgument1;
USBLS120_TransferData(DeviceObject);
USBLS120_KdPrint( DBGLVL_HIGH,("exit USBLS120_TransferDataDPC\n"));
}
VOID
USBLS120_TransferData(
PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Schedules bulk data transfer to/from the device.
Arguments:
DeviceObject - FDO for USB storage device.
Return Value:
None.
--*/
{
PURB Urb;
PIRP Irp;
USBD_PIPE_HANDLE PipeHandle;
PDEVICE_EXTENSION DeviceExtension;
NTSTATUS ntStatus;
BOOLEAN DataIn;
PVOID DataBuffer;
ULONG XferLength;
PIO_STACK_LOCATION NextStack;
BlockDev_Scatter_Gather * Sgd;
USBLS120_KdPrint( DBGLVL_HIGH,("enter USBLS120_TransferData\n"));
DeviceExtension = DeviceObject->DeviceExtension;
Urb = DeviceExtension->Urb;
Irp = DeviceExtension->Irp;
// Figure out which direction we're going
if ((DeviceExtension->IoPacket->Flags) & IO_FLAGS_DATA_IN)
DataIn = TRUE;
else
DataIn = FALSE;
// Use appropriate bulk pipe
if (DataIn)
PipeHandle = DeviceExtension->UsbInterface->Pipes[DeviceExtension->DataInPipe].PipeHandle;
else
PipeHandle = DeviceExtension->UsbInterface->Pipes[DeviceExtension->DataOutPipe].PipeHandle;
// If we are doing scatter gather, we will need to find the current
// SGD element and use its data buffer
if (DeviceExtension->IoPacket->Flags & IO_FLAGS_SCATTER_GATHER) {
// Retrieve the SGD list stored in the IoPacket
Sgd = (BlockDev_Scatter_Gather *)(DeviceExtension->IoPacket->DataBuffer);
// Extract SGD's data buffer pointer
DataBuffer = (PVOID)Sgd[DeviceExtension->CurrentSGD].BD_SG_Buffer_Ptr;
// SGD length is block count, need to convert to byte count
// and increment the current SGD counter
XferLength = Sgd[DeviceExtension->CurrentSGD++].BD_SG_Count *
DeviceExtension->IoPacket->BlockSize;
USBLS120_KdPrint( DBGLVL_HIGH,("SGDBuffer=%x, BuffSize=%x\n", DataBuffer, XferLength));
} else {
// No SGD, just a flat linear data buffer
DataBuffer = (PVOID)DeviceExtension->IoPacket->DataBuffer;
XferLength = DeviceExtension->DataLeft;
}
// Keep track of how much data we have left to transfer
DeviceExtension->DataLeft -= XferLength;
// Build a URB for our bulk data transfer
UsbBuildInterruptOrBulkTransferRequest(
Urb,
sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER),
PipeHandle,
DataBuffer,
NULL,
XferLength,
DataIn ? USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK :
USBD_TRANSFER_DIRECTION_OUT,
NULL
);
NextStack = IoGetNextIrpStackLocation(Irp);
USBLS120_ASSERT(NextStack != NULL);
USBLS120_ASSERT(DeviceObject->StackSize>1);
NextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextStack->Parameters.Others.Argument1 = Urb;
NextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(
Irp,
USBLS120_TransferDataComplete,
(PVOID)DeviceObject,
TRUE, // invoke on success
TRUE, // invoke on error
TRUE // invoke on cancellation of the Irp
);
USBLS120_IncrementIoCount(DeviceObject);
// Pass Irp to the USB driver stack without checking status.
// We don't look at the return status since we will
// always complete the IOS request in our
// completion handler, regardless of status.
// Call USB driver stack
IoCallDriver(DeviceExtension->TopOfStackDeviceObject, Irp);
}
NTSTATUS
USBLS120_TransferDataComplete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Reference
)
/*++
Routine Description:
Completion handler for bulk data transfer
Arguments:
DeviceObject - Previous device object in the stack.
Irp - Irp being completed.
Reference - Our device object.
Return Value:
NTSTATUS value.
--*/
{
NTSTATUS NtStatus;
PURB Urb;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION DeviceExtension;
USBLS120_KdPrint( DBGLVL_HIGH,("enter USBLS120_TransferDataComplete\n"));
DeviceExtension = ((PDEVICE_OBJECT)(Reference))->DeviceExtension;
Urb = DeviceExtension->Urb;
USBLS120_DecrementIoCount((PDEVICE_OBJECT)(Reference));
USBLS120_KdPrint(
DBGLVL_HIGH,
("TransferLength=%x, Urb Status=%x, Irp Status = %x\n",
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
Urb->UrbHeader.Status,
Irp->IoStatus.Status));
NtStatus = Irp->IoStatus.Status;
if (!NT_SUCCESS(NtStatus)) {
//Device failed Data Transfer
IoFreeIrp(Irp);
ExFreePool(Urb);
// Check if we need to clear stalled pipe
if (USBD_HALTED(Urb->UrbHeader.Status)) {
// Reset pipe can only be done at passive level, so we need
// to schedule a work item to do it.
DeviceExtension->WorkItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
if (DeviceExtension->WorkItem) {
USBLS120_KdPrint( DBGLVL_HIGH,("Scheduling DPC to reset endpoint\n"));
// Schedule a work-item to reset the pipe
ExInitializeWorkItem(
DeviceExtension->WorkItem,
USBLS120_TransferDataWorker,
Reference
);
ExQueueWorkItem(
DeviceExtension->WorkItem,
DelayedWorkQueue
);
return STATUS_MORE_PROCESSING_REQUIRED;
} else {
// Can't reset pipe because we can't allocate work-item
USBLS120_KdPrint( DBGLVL_MINIMUM,("Failed to allocate work-item to reset pipe!!\n"));
TRAP();
}
}
USBLS120_KdPrint( DBGLVL_MINIMUM,("Completing IOPACKET with error\n"));
// Complete request with error
DeviceExtension->IoPacket->Status = IO_STATUS_DEVICE_ERROR;
DeviceExtension->CompleteRequest(DeviceExtension->IoPacket);
return STATUS_MORE_PROCESSING_REQUIRED;
}
//
// Transfer succeeded
//
// Do we have more data to transfer?
if (DeviceExtension->DataLeft) {
// Transfer the next SGD
USBLS120_TransferData((PDEVICE_OBJECT)(Reference));
} else {
USBLS120_KdPrint( DBGLVL_HIGH,("Completing IOP successfully\n"));
IoFreeIrp(Irp);
ExFreePool(Urb);
DeviceExtension->IoPacket->Status = IO_STATUS_SUCCESS;
DeviceExtension->CompleteRequest(DeviceExtension->IoPacket);
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -