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

📄 ios.c

📁 usb海量存储的驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1999-2001 Microsoft Corporation

Module Name:

    Usbios.c 

Abstract:

    Sample USB device driver for USB Mass Storage devices
    Interface for IOS I/O requests

Environment:

    kernel mode only

Notes:

  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  PURPOSE.

  Copyright (c) 1999-2001 Microsoft Corporation.  All Rights Reserved.


Revision History:

    01/13/99: MRB  Adapted from BULKUSB DDK sample.

--*/
#define GLOBAL_VARS

#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "umss.h"




PDEVICE_OBJECT _stdcall
UMSS_GetNextPDO(
    IN PDEVICE_OBJECT *Fdo
    )
/*++
Routine Description:

    Called by the IOS port driver. Walks list of FDOs 
    associated with this driver, returning the PDO the FDO
    is attached to.  Allows IOS port driver to distinguish
    between multiple instances of the USB device.

 Arguments:

    DeviceObject -- ptr to previous FDO, or NULL if returning 1st PDO

Return Value:

    Next PDO, or
    NULL if no more FDOs associated with this driver.

--*/

{
    PDEVICE_EXTENSION DeviceExtension;

    ENTER(UMSS_GetNextPDO);

    // First Fdo?
    if (NULL == *Fdo)
    {

        // Get first Device Object associated with this driver
        *Fdo = UMSSDriverObject->DeviceObject;

    }
    else
    {
        // Get next device object for this driver
        *Fdo = (*Fdo)->NextDevice;
    }

    // No more device obects?
    if (NULL == *Fdo)
        return NULL;

    //Filter out our own child PDOs
    DeviceExtension = (*Fdo)->DeviceExtension;

    while (DO_FDO != DeviceExtension->DeviceObjectType)
    {
        *Fdo = (*Fdo)->NextDevice;
        if (NULL == *Fdo)
            return NULL;
        DeviceExtension = (*Fdo)->DeviceExtension;
    }

    RETURN(DeviceExtension->PhysicalDeviceObject, UMSS_GetNextPDO);
}
	


VOID _stdcall
UMSS_RegisterCompletionHandler(
    PDEVICE_OBJECT DeviceObject,
    COMPLETION_HANDLER CompletionHandler
    )
/*++
Routine Description:

    Called by the IOS port driver. Registers a completion
    handler in the port driver that is called whenever
    we complete an I/O request.

 Arguments:

    DeviceObject -- FDO we are registering the completion handler for.
    CompletionHandler - Address of completion handler.

Return Value:

    NONE

--*/

{
    PDEVICE_EXTENSION DeviceExtension;

    ENTER(UMSS_RegisterCompletionHandler);

    DeviceExtension = DeviceObject->DeviceExtension;
    DeviceExtension->CompleteRequest = CompletionHandler;

    EXIT(UMSS_RegisterCompletionHandler);

}


CHAR _stdcall
UMSS_GetMaxLun(
    IN PDEVICE_OBJECT Fdo
    )
/*++
Routine Description:

    Called by the IOS port driver. returns maximum LUN number for device.

 Arguments:

    DeviceObject -- FDO of device

Return Value:

    Maximum LUN number of device.

--*/

{
    PDEVICE_EXTENSION DeviceExtension;

    DeviceExtension = Fdo->DeviceExtension;

    return (DeviceExtension->MaxLun);
}



VOID _stdcall
UMSS_StartRequest(
    IN PIOPACKET IoPacket
    )
/*++
Routine Description:

    Called by the IOS port driver to start an I/O request

    Please Note!! - All USB transfers that occur in response
    to this request must be done asynchronously.  IOS and IFSMGR
    implements their own thread blocking mechanisms, and it
    is possible to create a race condition if we also block
    waiting for a USB transfer to complete.

 Arguments:

    IoPacket -- Structure containing pertient information about the
                I/O request.

Return Value:

    NONE

--*/

{
    PURB Urb;
    PIRP Irp;
    CHAR StackSize;
    PDEVICE_EXTENSION DeviceExtension;
    PIO_STACK_LOCATION NextStack;
    ULONG UrbSize;
    ULONG i;
    PDEVICE_OBJECT DeviceObject;

    ENTER(UMSS_StartRequest);

    UMSS_KdPrint( DBGLVL_HIGH,("DataBuffer=%x, DataLength=%x, Flags=%x, Iop=%x\n",
                     IoPacket->DataBuffer,
                     IoPacket->DataLength,
                     IoPacket->Flags,
                     IoPacket->Iop));

#ifdef DBG
    if (IoPacket->CdbLength > 12)
    {
        UMSS_KdPrint( DBGLVL_DEFAULT,("CDB Length = %d, should be <= 12\n", IoPacket->CdbLength));
        TRAP();
    }

    // Dump CDB contents
    for (i=0; i<IoPacket->CdbLength; i++)
                UMSS_KdPrint( DBGLVL_HIGH,("  CDB[%x]=%x\n", i,((char*)(IoPacket->Cdb))[i]));
#endif

    DeviceObject = (PDEVICE_OBJECT)(IoPacket->Fdo);
    DeviceExtension = DeviceObject->DeviceExtension;

    // Increment I/O count.  It will decrement when I/O request completes.
    UMSS_IncrementIoCount(DeviceObject);

    // Allocate IRP for our I/O request
    StackSize = (CCHAR)(DeviceExtension->TopOfStackDeviceObject->StackSize + 1);
    Irp = IoAllocateIrp(StackSize, FALSE);

    if (!Irp) {
        UMSS_KdPrint( DBGLVL_MINIMUM,("Failure due to memory error\n"));

        // Can't allocate IRP - complete request with error and return
        UMSS_CompleteRequest(DeviceExtension, IO_STATUS_OUT_OF_MEMORY);
        EXIT(UMSS_StartRequest);
        return;
    }
	
    // Allocate URB.  It will be used for control, bulk, and interrupt
    // transfers, so insure it is large enough for both types of URBs
    UrbSize = max(sizeof (struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
                  sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER) );

    Urb = UMSS_ExAllocatePool(NonPagedPool, UrbSize);

    if (!Urb) {
        UMSS_KdPrint( DBGLVL_MINIMUM,("Failure due to memory error\n"));

        IoFreeIrp(Irp);

        UMSS_CompleteRequest(DeviceExtension, IO_STATUS_OUT_OF_MEMORY);
        EXIT(UMSS_StartRequest);
        return;
    }



    // Store all the transfer request info in our device extension
    DeviceExtension->Urb = Urb;
    DeviceExtension->Irp = Irp;
    DeviceExtension->CurrentSGD = 0;
    DeviceExtension->IoPacket = IoPacket;

    // Is there a data phase?
    if (IoPacket->Flags & (IO_FLAGS_DATA_IN | IO_FLAGS_DATA_OUT))
        DeviceExtension->BytesToTransfer = IoPacket->DataLength;
    else
        DeviceExtension->BytesToTransfer = 0;


    if (DeviceExtension->DeviceProtocol == PROTOCOL_BULKONLY)
    {
        UMSS_BulkOnlyStartIo(DeviceExtension);
    }
    else if ((DeviceExtension->DeviceProtocol == PROTOCOL_CBI) ||
             (DeviceExtension->DeviceProtocol == PROTOCOL_CB))
    {
        UMSS_CbiStartIo(DeviceExtension);
    }
    else
    {
        UMSS_CompleteRequest(DeviceExtension, IO_STATUS_DEVICE_ERROR);
    }
    EXIT(UMSS_StartRequest);
}


VOID
UMSS_CompleteRequest(
    PDEVICE_EXTENSION DeviceExtension,
    ULONG Status
    )
/*++
Routine Description:

    Completes IOS request by calling back into the IOS port driver.
    
 Arguments:

    DeviceExtension - Our device extension
    Status - Status of I/O request being completed

Return Value:

    NONE

--*/

{
    PIOPACKET IoPacket = DeviceExtension->IoPacket;
    PDEVICE_OBJECT DeviceObject;

    ENTER(UMSS_CompleteRequest);

    DeviceObject = DeviceExtension->Fdo;
    DeviceExtension->IoPacket->Status = Status;
    if (DeviceExtension->Irp)
    {
        IoFreeIrp(DeviceExtension->Irp);
    }

    if (DeviceExtension->Urb)
    {
        UMSS_ExFreePool(DeviceExtension->Urb);
    }

    DeviceExtension->IoPacket = NULL;
    DeviceExtension->Urb = NULL;
    DeviceExtension->Irp = NULL;
    DeviceExtension->CurrentSGD = 0;

    DeviceExtension->CompleteRequest(IoPacket);

    // I/O request completed, so decrement I/O count on FDO.
    UMSS_DecrementIoCount(DeviceObject);

    EXIT(UMSS_CompleteRequest);
}


/*
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);
}

⌨️ 快捷键说明

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