⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ios.c

📁 微软提供的USB Mass Storage驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
VOID _stdcall
UMSS_IosTimeout(
    PDEVICE_OBJECT DeviceObject,
    )
/*++
Routine Description:

    Called by the IOS port driver when an IOS timeout occurs.
    Cancel any pending I/O and reset the device.

 Arguments:

    DeviceObject -- FDO for our device.

Return Value:

    None.        
--/
{
//mrbmrb - to be implemented
    // See if we have a pending I/O request
    if (NULL != DeviceExtension-IoPacket)
    {
        
*/


PVOID
UMSS_GetBuffer(
    PDEVICE_EXTENSION DeviceExtension,
    ULONG* BufferSize
    )
/*++
Routine Description:

    Parses IOS scatter-gather descriptors and returns next data buffer
    fragment to be used in transferring data from/to device.

 Arguments:

    DeviceExtension - Our device extension.
    BufferSize - ULONG to recieve transfer length.

Return Value:
    Extracted data buffer, or NULL if no more data to transfer.

--*/

{
    BlockDev_Scatter_Gather * Sgd;
    PVOID Buffer;

    ENTER(UMSS_GetBuffer);

    if (0 == DeviceExtension->BytesToTransfer)
    {
        RETURN(NULL, UMSS_GetBuffer);
    }

    // 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
        Buffer = (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
        *BufferSize = Sgd[DeviceExtension->CurrentSGD++].BD_SG_Count *
                         DeviceExtension->IoPacket->BlockSize;

        UMSS_KdPrint( DBGLVL_HIGH,("SGDBuffer=%x, BuffSize=%x\n", Buffer, *BufferSize));
    } else
    {
        // No SGD, just a flat linear data buffer
        Buffer = (PVOID)DeviceExtension->IoPacket->DataBuffer;
        *BufferSize = DeviceExtension->BytesToTransfer;
    }

    DeviceExtension->BytesToTransfer -= *BufferSize;

    RETURN(Buffer, UMSS_GetBuffer);
}


VOID
UMSS_ClassSpecificRequest(
    IN PDEVICE_EXTENSION DeviceExtension,
    IN UCHAR Request,
    IN UCHAR TransferDirection,
    IN PVOID Buffer,
    IN ULONG BufferLength,
    IN PIO_COMPLETION_ROUTINE CompletionRoutine
    )
/*++
Routine Description:

    Sends a class-specific request to the device

    NOTE: Assumes device extension has valid IRP and URB.

 Arguments:

    DeviceExtension - Our device extension.
    Request - Class specific request value.
    TransferDirection - Direction of data transfer.
    Buffer - Address of data buffer to use for data transfer.
    BufferLength - Number of bytes to transfer.
    CompletionRoutine - Function to call when request completes.

Return Value:

    NONE.

--*/

{
    PIRP Irp;
    PURB Urb;
    PIO_STACK_LOCATION NextStack;

    ENTER(UMSS_ClassSpecificRequest);

    Irp = DeviceExtension->Irp;
    Urb = DeviceExtension->Urb;

    // Build URB for the ADSC command
    UsbBuildVendorRequest(
        Urb,
        URB_FUNCTION_CLASS_INTERFACE,
        (USHORT) sizeof (struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
        (DATA_IN == TransferDirection) ? USBD_TRANSFER_DIRECTION_IN : 0,
        0,
        Request,
        0,
        0,
        Buffer,
        NULL,
        BufferLength,
        NULL
        );

    NextStack = IoGetNextIrpStackLocation(Irp);
    UMSS_ASSERT(NextStack != NULL);
    UMSS_ASSERT(DeviceExtension->Fdo->StackSize>1);

    // Initialize our Irp
    NextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    NextStack->Parameters.Others.Argument1 = Urb;
    NextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

    // Register our Irp completion handler
    IoSetCompletionRoutine(
        Irp,
        CompletionRoutine,
        DeviceExtension, 
        TRUE,    // invoke on success
        TRUE,    // invoke on error
        TRUE     // invoke on cancellation of the Irp
        );

    // Pass Irp to the USB driver stack
    IoCallDriver(DeviceExtension->TopOfStackDeviceObject, Irp);

    EXIT(UMSS_ClassSpecificRequest);
}


VOID
UMSS_BulkTransfer(
    IN PDEVICE_EXTENSION DeviceExtension,
    IN UCHAR TransferDirection,
    IN PVOID Buffer,
    IN ULONG BufferLength,
    IN PIO_COMPLETION_ROUTINE CompletionRoutine
    )
/*++
Routine Description:

    Initiates a bulk transfer with the USB device.

 Arguments:

    DeviceExtension - Our device extension.
    TransferDirection - Direction of data transfer.
    Buffer - Address of data buffer to use for data transfer.
    BufferLength - Number of bytes to transfer.
    CompletionRoutine - Function to call when request completes.

Return Value:

    NONE

--*/

{
    PIO_STACK_LOCATION NextStack;
    USBD_PIPE_HANDLE PipeHandle;
    PIRP Irp;
    PURB Urb;

    ENTER(UMSS_DoBulkTransfer);

    if (DATA_IN == TransferDirection)
        PipeHandle = DeviceExtension->UsbInterface->Pipes[DeviceExtension->DataInPipe].PipeHandle;
    else
        PipeHandle = DeviceExtension->UsbInterface->Pipes[DeviceExtension->DataOutPipe].PipeHandle;

    Urb = DeviceExtension->Urb;
    Irp = DeviceExtension->Irp;

    // Build a URB for our bulk transfer
    UsbBuildInterruptOrBulkTransferRequest(
        Urb,
        sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER),
        PipeHandle,
        Buffer,
        NULL,
        BufferLength,
        (DATA_OUT == TransferDirection) ? USBD_TRANSFER_DIRECTION_OUT :
                    USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
        NULL
        );

    NextStack = IoGetNextIrpStackLocation(Irp);

    UMSS_ASSERT(NextStack != NULL);
    UMSS_ASSERT(DeviceExtension->Fdo->StackSize>1);

    // Initialize our Irp
    NextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    NextStack->Parameters.Others.Argument1 = Urb;
    NextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

    // Register our Irp completion handler
    IoSetCompletionRoutine(
        Irp,
        CompletionRoutine,
        DeviceExtension, 
        TRUE,    // invoke on success
        TRUE,    // invoke on error
        TRUE     // invoke on cancellation of the Irp
        );

    // Pass Irp to the USB driver stack
    IoCallDriver(DeviceExtension->TopOfStackDeviceObject, Irp);

    EXIT(UMSS_DoBulkTransfer);
}



BOOLEAN
UMSS_ScheduleWorkItem(
    PVOID Context,
    UMSS_WORKER_ROUTINE Routine
    )
/*++
Routine Description:

    Wrapper for handling worker thread callbacks

 Arguments:

    Routine - Routine to be called when this work-item is processed
    Context - Value to be passed to worker routine

Return Value:
    TRUE if work item queued
    FALSE if work item not queued

--*/

{
    BOOLEAN RetVal = TRUE;
    PWORK_QUEUE_ITEM WorkItem;
    PUMSS_WORKER_PACKET WorkerPacket;

    ENTER(UMSS_ScheduleWorkItem);

    WorkItem = UMSS_ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
    WorkerPacket = UMSS_ExAllocatePool(NonPagedPool, sizeof(UMSS_WORKER_PACKET));     

    if ((WorkItem) && (WorkerPacket))
    {
        WorkerPacket->Routine = Routine;
        WorkerPacket->Context = Context;
        WorkerPacket->WorkItem = WorkItem;

        // Initialize the work-item
        ExInitializeWorkItem(
            WorkItem,
            UMSS_Worker,
            WorkerPacket
            );

        // Schedule the work-item
        ExQueueWorkItem(
            WorkItem,
            DelayedWorkQueue
            );

        UMSS_KdPrint( DBGLVL_MINIMUM,("Work-item queued\n"));
    }
    else
    {
        UMSS_KdPrint( DBGLVL_MINIMUM,("Failed to allocate work-item\n"));

        if (WorkItem)
            UMSS_ExFreePool(WorkItem);

        if (WorkerPacket)
            UMSS_ExFreePool(WorkerPacket);

        RetVal = FALSE;
    }

    RETURN(RetVal, UMSS_ScheduleWorkItem);
}


VOID 
UMSS_Worker(
    IN PVOID Reference
    )
/*++
Routine Description:

    Wrapper for worker thread function.  Handles cleaning up work-item, etc.,
    before calling real worker function.

 Arguments:

    Reference - Context value to be passed to worker function.

Return Value:

    NONE

--*/

{
    PUMSS_WORKER_PACKET WorkerPacket;

    ENTER(UMSS_Worker);

    WorkerPacket = (PUMSS_WORKER_PACKET)Reference;

    WorkerPacket->Routine(WorkerPacket->Context);

    UMSS_ExFreePool(WorkerPacket->WorkItem);
    UMSS_ExFreePool(WorkerPacket);

    EXIT(UMSS_Worker);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -