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

📄 usbfx2lk_io.cpp

📁 基于vc++6.0环境的cypress USB 驱动源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
///////////////////////////////////////////////////////////////////////////////
//
//    (C) Copyright 2005 OSR Open Systems Resources, Inc.
//    All Rights Reserved
//
//    This sofware is supplied for instructional purposes only.
//
//    OSR Open Systems Resources, Inc. (OSR) expressly disclaims any warranty
//    for this software.  THIS SOFTWARE IS PROVIDED  "AS IS" WITHOUT WARRANTY
//    OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
//    THE IMPLIED WARRANTIES OF MECHANTABILITY OR FITNESS FOR A PARTICULAR
//    PURPOSE.  THE ENTIRE RISK ARISING FROM THE USE OF THIS SOFTWARE REMAINS
//    WITH YOU.  OSR's entire liability and your exclusive remedy shall not
//    exceed the price paid for this material.  In no event shall OSR or its
//    suppliers be liable for any damages whatsoever (including, without
//    limitation, damages for loss of business profit, business interruption,
//    loss of business information, or any other pecuniary loss) arising out
//    of the use or inability to use this software, even if OSR has been
//    advised of the possibility of such damages.  Because some states/
//    jurisdictions do not allow the exclusion or limitation of liability for
//    consequential or incidental damages, the above limitation may not apply
//    to you.
//
//    OSR Open Systems Resources, Inc.
//    105 Route 101A Suite 19
//    Amherst, NH 03031  (603) 595-6500 FAX: (603) 595-6503
//    email bugs to: bugs@osr.com
//
//
//    MODULE:
//
//      USBFx2LK_io.cpp
//
//    ABSTRACT:
//
//      This file contains the routines that handle IRP_MJ_READ and
//      IRP_MJ_WRITE processing for the OSR USB FX2 Learning Kit Device
//
//    AUTHOR(S):
//
//      OSR Open Systems Resources, Inc.
// 
///////////////////////////////////////////////////////////////////////////////
#include "usbfx2lk.h"

#ifdef WPP_TRACING
//
// Include the necessary tmh file - this is 
//  just a matter of course if you're using WPP tracing.
//
extern "C" {
#include "usbfx2lk_io.tmh"
}
#endif

//
// Forward Definitions
//
NTSTATUS UsbFx2LkReadCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID  Context);
NTSTATUS UsbFx2LkWriteCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID  Context);
VOID IssueUsbReadRequest(IN PDEVICE_OBJECT DeviceObject,IN PVOID Context);
VOID IssueUsbWriteRequest(IN PDEVICE_OBJECT DeviceObject,IN PVOID Context);


///////////////////////////////////////////////////////////////////////////////
//
// ProcessNextIrpInQueue
//
//  This routine processes the Next Irp in the Io Queue, if we are in a state
//  to process Irps.   If not, the Irps will remain in the queue until the state
//  of the device changes to either a state where the Irps can be processed or where
//  the Irps will be removed from the queue.
//
//  INPUTS:
//
//      DevExt  -  Address of our Device Extension.
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      User Context
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID ProcessNextIrpInQueue(PUSBFX2LK_EXT DevExt)
{
    KIRQL       oldIrql;
    PIRP        irp;

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_READWRITE, ("ProcessNextIrpInQueue Entered...\n"));

    //
    // Check the state of the device.   If we not processing irps
    // we will just return.
    //
    KeAcquireSpinLock(&DevExt->IoStateLock,&oldIrql);
    if(DevExt->DevicePnPState >= STATE_ALL_ABOVE_QUEUE) {
        KeReleaseSpinLock(&DevExt->IoStateLock,oldIrql);
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_READWRITE,
            ("ProcessNextIrpInQueue: Exit Queuing Irps, Not Processing\n"));
        return;
    }
    KeReleaseSpinLock(&DevExt->IoStateLock,oldIrql);

    //
    // See if the device is currently suspended. If it 
    //  is, this routine will attempt to asynchronously power 
    //  the device back up and will return TRUE. In that
    //  case, the power up code will restart our queues and
    //  we can simply exit here. However, if this routine
    //  returns FALSE the device is already powered up
    //  and we can attempt to start the next IRP in
    //  the queue.
    //
    if (!SSPowerDeviceIfSuspendedAsync(DevExt)) {
    
        //
        // Attempt to remove an IRP from the Queue.  
        //
        irp = IoCsqRemoveNextIrp(&DevExt->CancelSafeIoQueue,NULL);

        //
        // See if we got an IRP.   If not, then we exit.
        //
        if(!irp) {

            OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_READWRITE, 
                ("ProcessNextIrpInQueue Exit No Irps in Queue\n"));
            return;
        }

        //
        // Got an IRP, submit it to the Device Below us.
        //
        (VOID)IoCallDriver(DevExt->DeviceToSendIrpsTo,irp);

    }

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_READWRITE, ("ProcessNextIrpInQueue Exit...\n"));

    return;
}

///////////////////////////////////////////////////////////////////////////////
//
// UsbFx2LkRead
//
//  This routine is called by the IO Manager to process a IRP_MJ_READ
//  Irp.
//
//
//  INPUTS:
//
//      DeviceObject  -  One of our Device Objects.
//      Irp  -  The Irp to process.
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      STATUS_PENDING, or an ERROR.  
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      User Context
//
//  NOTES:
//
//      READ requests are always serviced by the bulk input pipe
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS UsbFx2LkRead(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
    PUSBFX2LK_EXT           devExt = (PUSBFX2LK_EXT)DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION      ioStack = IoGetCurrentIrpStackLocation(Irp);
    KIRQL                   oldIrql;
    PUSBFX2LK_IO_CONTEXT    pFx2Context = NULL;
    NTSTATUS                status;
    PMDL                    pMdl = NULL;
    ULONG                   totalLength = 0;
    ULONG                   urbFlags = 0;
    PUCHAR                  virtualAddress = 0;
    ULONG                   stageLength = 0;
    PURB                    urb = NULL;
    PIO_STACK_LOCATION      nextStack = IoGetNextIrpStackLocation(Irp);

    //
    // We should never be here and not at PASSIVE_LEVEL
    //
    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

    //
    // Major issue is we haven't setup our bulk input pipe yet
    //
    ASSERT(devExt->BulkInPipe);

    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_READWRITE, ("UsbFx2LkRead Entered...\n"));

    //
    // Increment the number of outstanding IOs queued to the device.
    //
    OsrIncrementOutstandingIoCount(devExt,__FILE__,__LINE__);


    //
    // See what sort of state we're in. 
    //
    KeAcquireSpinLock(&devExt->IoStateLock,&oldIrql);
    if (devExt->DevicePnPState < STATE_ALL_BELOW_FAIL) {

        KeReleaseSpinLock(&devExt->IoStateLock,oldIrql);
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_READWRITE, 
                ("UsbFx2LkRead: Failing  request due to Pnp State! Current PnP state - %s\n",
                  OsrPrintState(devExt)));

        status = STATUS_INVALID_DEVICE_STATE;
        goto UsbFx2LkRead_Exit;
    }
    KeReleaseSpinLock(&devExt->IoStateLock,oldIrql);

    //
    // We do not support zero length operations in this driver
    //
    if(!ioStack->Parameters.Read.Length || !Irp->MdlAddress) {

        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_READWRITE, 
                ("UsbFx2LkRead: Invalid Parameters to READ \n"));

        status = STATUS_INVALID_PARAMETER;
        goto UsbFx2LkRead_Exit;
    }


    //
    // Get the total length of the transfer we are asked to perform.
    //
    totalLength = ioStack->Parameters.Read.Length;

    //
    // See if the transfer length is greater than the maximum packet
    //  size of the pipe * the amount of buffering that the firmware
    //  provides. If the transfer is too large, we will reject it here
    //  without further processing
    //
    if(totalLength > 
            (ULONG)(devExt->BulkInPipe->PipeInformation.MaximumPacketSize * \
                                        USBFX2LK_BULK_TRANSFER_FW_BUFFERING)) {

        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_READWRITE,
            ("UsbFx2LkRead: Length exceeds %d\n", 
            devExt->BulkInPipe->PipeInformation.MaximumPacketSize * USBFX2LK_BULK_TRANSFER_FW_BUFFERING));

        status = STATUS_INVALID_PARAMETER;
        goto UsbFx2LkRead_Exit;
    }

    //
    // Allocate a USBFX2 I/O context. This is a driver specific
    //  structure that we'll use to contain all the necessary
    //  information about this particular request while we
    //  own that request
    //
    pFx2Context = (PUSBFX2LK_IO_CONTEXT) ExAllocatePoolWithTag(NonPagedPool,sizeof(USBFX2LK_IO_CONTEXT),'ciuO');

    if(pFx2Context == NULL) {
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_READWRITE,
            ("UsbFx2LkRead: Failed to allocate IO Context\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto UsbFx2LkRead_Exit;
    }

    //
    // Get the user's base virtual address from the MDL. This
    //  will be used as a cookie to indicate what area of the 
    //  user's data buffer we are currently copying data into
    //
    virtualAddress = (PUCHAR) MmGetMdlVirtualAddress(Irp->MdlAddress);

    //
    // the transfer request is for totalLength. We can perform a maximum of
    // the bulk input pipe's PipeInformation.MaximumPacketSize in each stage.
    //
    pFx2Context->MaxmimumStageSize = devExt->BulkInPipe->PipeInformation.MaximumPacketSize;

    if(totalLength > devExt->BulkInPipe->PipeInformation.MaximumPacketSize) {
        //
        // Total length is bigger that we can send, so we will break up
        // the transfer into smaller pieces.
        //
        stageLength = pFx2Context->MaxmimumStageSize;
    } else {
        //
        // We can send this packet in one transfer.
        //
        stageLength = totalLength;
    }

    //
    // We asked the I/O manager to supply reads and writes from user
    //  mode components in the form of MDLs by setting the DO_DIRECT_IO
    //  bit in our device object during AddDevice. This will result in
    //  the I/O manager sending our driver MDLs that describe the entire
    //  length of the user's buffer for the entire operation.
    //
    // However, we may need to split this single user transfer up
    //  into multiple "stages" so that we don't send our device
    //  I/O operations that exceed the maximum supported single 
    //  transfer size. To do this, we will build what are called
    //  "partial MDLs" that describe only the portion of the user's
    //  data buffer that we will be transferring at each individual
    //  stage. 
    //
    // The first step in building partial MDLs will be allocating 
    //  a new MDL that is large enough to describe the passed in MDL.
    //  
    pMdl = IoAllocateMdl((PVOID)virtualAddress,
                         totalLength,
                         FALSE,
                         FALSE,
                         NULL);

    if(pMdl == NULL) {
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_READWRITE,("UsbFx2LkRead: Failed to Allocate Mdl\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        ExFreePool(pFx2Context);
        goto UsbFx2LkRead_Exit;
    }

    //
    // Now, build a partial MDL out of the newly allocated 
    //  MDL. This will map the first stageLength bytes of
    //  the MDL in the IRP into the newly allocated MDL
    //
    IoBuildPartialMdl(Irp->MdlAddress,
                      pMdl,
                      (PVOID)virtualAddress,
                      stageLength);

    //
    // Allocate an URB to be used for the transfer.
    //
    urb = (PURB) ExAllocatePoolWithTag(NonPagedPool,sizeof(URB),'bruO');

    if(urb == NULL) {
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_READWRITE,("UsbFx2LkRead: Failed to allocate URB\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        ExFreePool(pFx2Context);
        IoFreeMdl(pMdl);
        goto UsbFx2LkRead_Exit;
    }

    //
    // Build the Transfer URB.
    //

    //
    // Indicate that this is a read function and that we will allow short
    // transfers of data.
    //
    urbFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN;

    UsbBuildInterruptOrBulkTransferRequest(
                            urb,
                            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                            devExt->BulkInPipe->PipeInformation.PipeHandle,
                            NULL,
                            pMdl,
                            stageLength,

⌨️ 快捷键说明

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