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

📄 usbfx2lk_io.cpp

📁 基于vc++6.0环境的cypress USB 驱动源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    return STATUS_PENDING;

UsbFx2LkWrite_Exit:

    //
    // If we're here then we are failing the request.
    //  Decrement our outstanding I/O count
    //
    ASSERT(!NT_SUCCESS(status));

    OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);

    Irp->IoStatus.Status      = status;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest (Irp, IO_NO_INCREMENT);

    return status;
}

///////////////////////////////////////////////////////////////////////////////
//
// UsbFx2LkWriteCompletionRoutine
//
//  This routine is called by the IO Manager when a USB Write Completes
//
//
//  INPUTS:
//
//      DeviceObject  -  One of our Device Objects.
//      Irp  -  The Irp to process.
//      Context - 
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL <= DISPATCH_LEVEL
//
//  CONTEXT:
//
//      User Context
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS UsbFx2LkWriteCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID  Context)
{
    NTSTATUS             status = Irp->IoStatus.Status;
    PUSBFX2LK_IO_CONTEXT pFx2Context = (PUSBFX2LK_IO_CONTEXT) Context;
    ULONG                stageLength = 0;

    UNREFERENCED_PARAMETER(DeviceObject);

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

    //
    // There's no reason why this pointer
    //  shouldn't be valid
    //
    ASSERT(pFx2Context);

    //
    // See if we successfully performed a stageLength of transfer.
    // check if we need to recirculate the irp.
    //
    if(NT_SUCCESS(status)) {

        //
        // The transfer completed successfully, see if we need to continue transfering.
        //
        //
        // Calculate how much data has been recently received.
        //
        pFx2Context->Numxfer += pFx2Context->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;

        //
        // Determine if there is more to transfer.
        //
        if(pFx2Context->RemainingLength) {

            //
            // Set up the next stage of the transfer.
            //
            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_READWRITE,
                ("UsbFx2LkWriteCompletionRoutine: Another stage transfer  %d of %d\n",
                    pFx2Context->Numxfer,pFx2Context->TotalLength));

            //
            // Compare the remaining length to our maximum stage size.
            //  If it is larger, then this transfer will require at 
            //  least two more sub-transfers
            //
            if(pFx2Context->RemainingLength > pFx2Context->MaxmimumStageSize) {

                stageLength = pFx2Context->MaxmimumStageSize;

            } else {

                stageLength = pFx2Context->RemainingLength;

            }

            // 
            // Prepare the MDL to be reused for the next part of the transfer.
            // This function unmaps any pages that may have been previously mapped
            // by this MDL before reusing it.
            //
            MmPrepareMdlForReuse(pFx2Context->Mdl);

            //
            // Setup the partial MDL again, but this time we 
            //  use the updated VirtualAddress pointer from the 
            //  original MDL. This is the cookie that the memory
            //  manager uses to figure out which portion of the 
            //  MDL needs to be mapped into the partial MDL.
            //
            IoBuildPartialMdl(Irp->MdlAddress,
                              pFx2Context->Mdl,
                              (PVOID) pFx2Context->VirtualAddress,
                              stageLength);
            
            //
            // reinitialize the urb
            //
            pFx2Context->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = stageLength;

            //
            // And update the VirtualAddress and remaining transfer length in the 
            //  FX2 I/O context.
            //
            pFx2Context->VirtualAddress += stageLength;
            pFx2Context->RemainingLength -= stageLength;

            //
            // We cannot simply resubmit the IRP here with IoCallDriver for two
            //  reasons:
            //
            //  1) We may be running at IRQL == DISPATCH_LEVEL and the USB stack
            //     is not explicitly documented to be called at its dispatch 
            //     entry points at IRQL DISPATCH_LEVEL
            //
            //  2) If the request is completed in the lower driver's dispatch entry
            //     point, we will be called back here at our completion routine 
            //     recursively. If we then submit the IRP back down inline, we 
            //     can continue doing this recursion until we finally run out 
            //     stack space
            //
            // For those two reasons, we will queue a work item (guaranteeing an 
            //  IRQL of PASSIVE_LEVEL and a fresh stack) and resubmit the IRP 
            //  from the work item.
            //
            IoQueueWorkItem(pFx2Context->PWorkItem,IssueUsbWriteRequest,CriticalWorkQueue,pFx2Context);

            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_READWRITE,("UsbFx2LkWriteCompletionRoutine:  Next Stage.\n"));

            //
            // We are going to be resubmitting this IRP to the host in our 
            //  work item, so we need to indicate to the I/O manager
            //  that we are still processing the IRP by returning the
            //  special STATUS_MORE_PROCESSING_REQUIRED status
            //
            return STATUS_MORE_PROCESSING_REQUIRED;

        } else {

            //
            // this is the last transfer
            //

            //
            // Update Statistics
            //
            pFx2Context->DevExt->WmiStatistics.TotalBulkBytesWritten += pFx2Context->Numxfer ;
            pFx2Context->DevExt->WmiStatistics.TotalBulkWriteIrpCount++;

            //
            // Indicate number of bytes transfered.
            //
            Irp->IoStatus.Information = pFx2Context->Numxfer;

            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_READWRITE,
                ("UsbFx2LkWriteCompletionRoutine:  Write Complete.\n"));
        }
    } else {
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_READWRITE,
            ("UsbFx2LkWriteCompletionRoutine: failed status = %08.8x %s\n", status,OsrNtStatusToString(status)));
    }
    
    //
    // dump Fx2Context
    //
    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_READWRITE,
        ("UsbFx2LkWriteCompletionRoutine: pFx2Context->Urb             = %p\n", 
            pFx2Context->Urb));
    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_READWRITE,
        ("UsbFx2LkWriteCompletionRoutine: pFx2Context->Mdl             = %p\n", 
            pFx2Context->Mdl));
    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_READWRITE,
        ("UsbFx2LkWriteCompletionRoutine: pFx2Context->RemainingLength = %d\n", 
            pFx2Context->RemainingLength));
    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_READWRITE,
        ("UsbFx2LkWriteCompletionRoutine: pFx2Context->Numxfer         = %d\n", 
            pFx2Context->Numxfer));
    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_READWRITE,
        ("UsbFx2LkWriteCompletionRoutine: pFx2Context->VirtualAddress  = %p\n", 
            pFx2Context->VirtualAddress));
    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_READWRITE,
        ("UsbFx2LkWriteCompletionRoutine: pFx2Context->DevExt          = %p\n", 
            pFx2Context->DevExt));

    //
    // Decrement the outstanding IO count
    //
    OsrDecrementOutstandingIoCount(pFx2Context->DevExt,__FILE__,__LINE__);

    //
    // Clean up all of the resources used for this transfer
    //
    IoFreeWorkItem(pFx2Context->PWorkItem);
    ExFreePool(pFx2Context->Urb);
    IoFreeMdl(pFx2Context->Mdl);
    ExFreePool(pFx2Context);

    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_READWRITE,("UsbFx2LkWriteCompletionRoutine:  Exit.\n"));

    return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////
//
// IssueUsbWriteRequest
//
//  This routine is called in response to our UsbFx2LkWriteCompletionRoutine
//  queuing the Work Item to do the next stage of the write request.
//
//
//  INPUTS:
//
//      DeviceObject  -  One of our Device Objects.
//      Context - our pFx2Context
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      System Context
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID IssueUsbWriteRequest(IN PDEVICE_OBJECT DeviceObject,IN PVOID Context)
{
    PUSBFX2LK_IO_CONTEXT pFx2Context = (PUSBFX2LK_IO_CONTEXT) Context;
    PIO_STACK_LOCATION   nextStack;

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

    //
    // Prepare the next stack location so that we can resubmit the irp
    //  to do the next part of the transfer. Note that this step is 
    //  required because the I/O manager zeroes the lower stack
    //  locations as part of completion processing.
    //
    nextStack = IoGetNextIrpStackLocation(pFx2Context->Irp);
    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    nextStack->Parameters.Others.Argument1 = pFx2Context->Urb;
    nextStack->Parameters.DeviceIoControl.IoControlCode = 
                                IOCTL_INTERNAL_USB_SUBMIT_URB;

    //
    // Set our completion routine to be called when this stage of
    //  the read completes.
    //
    IoSetCompletionRoutine(pFx2Context->Irp,
                            UsbFx2LkWriteCompletionRoutine,
                            pFx2Context,
                            TRUE,
                            TRUE,
                            TRUE);

    //
    // Send the write request to the Bus Driver.
    //
    IoCallDriver(pFx2Context->DevExt->DeviceToSendIrpsTo, 
                    pFx2Context->Irp);

    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_READWRITE,("IssueUsbWriteRequest:  Exit.\n"));

}

///////////////////////////////////////////////////////////////////////////////
//
//  OsrProcessQueuedRequests
//
//      This interface checks the current state of the read and write
//      queues, and starts requests on the device if either are not
//      busy.
//
//  INPUTS:
//
//      DevExt - Pointer to device extension of device on which to 
//               start the transfers
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      None.
//
//  IRQL:
//
//      This routine is called at IRQL <= DISPATCH_LEVEL
//
//  CONTEXT:
//
//      Arbitrary 
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID OsrProcessQueuedRequests(PUSBFX2LK_EXT DevExt) 
{
    PIRP        irp = NULL;
    KIRQL       oldIrql;

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

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

    //
    // Try to start up any queued I/O on the 
    //  device.
    //
    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_READWRITE,("OsrProcessQueuedRequests: PnP State = %s\n",
        OsrPrintState(DevExt)));

    //
    // Are we in a proper PnP/Power state?
    //
    KeAcquireSpinLock(&DevExt->IoStateLock,&oldIrql);

    if (DevExt->DevicePnPState < STATE_ALL_BELOW_DRAIN) {
        
        KeReleaseSpinLock(&DevExt->IoStateLock,oldIrql);

        //
        // We're good to go. Attempt to remove an 
        //  IRP off of the queue
        //
        while((irp = IoCsqRemoveNextIrp(&DevExt->CancelSafeIoQueue, NULL))) {

            (VOID)IoCallDriver(DevExt->DeviceToSendIrpsTo,irp);
            
        }
        
        OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_READWRITE,("OsrProcessQueuedRequests: Exit. Irps Queued.\n"));

    } else {
        KeReleaseSpinLock(&DevExt->IoStateLock,oldIrql);
        OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_READWRITE,("OsrProcessQueuedRequests: Exit. Not Processing Queue.\n"));
    }
}

⌨️ 快捷键说明

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