Пример #1
0
VOID
LspCloseWorkItem(
	__in PDEVICE_OBJECT DeviceObject, 
	__in PVOID Context)
{
	NTSTATUS status;
	PIRP irp;
	KIRQL oldIrql;

	irp = (PIRP) Context;

	status = LspCleanupConnection(DeviceObject);
	LSP_KDPRINT(("LspClenaupConnection returned status %x\n", status));

	irp->IoStatus.Information = 0;
	irp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(irp, IO_NO_INCREMENT);	

	//
	// IoStartNextPacket should be called at DISPATCH_LEVEL
	//
	KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
	IoStartNextPacket(DeviceObject, TRUE);
	KeLowerIrql(oldIrql);
}
Пример #2
0
VOID
NTAPI
BeepCancel(IN PDEVICE_OBJECT DeviceObject,
           IN PIRP Irp)
{
    /* Check if this is the current request */
    if (Irp == DeviceObject->CurrentIrp)
    {
        /* Clear it */
        DeviceObject->CurrentIrp = NULL;

        /* Release the cancel lock and start the next packet */
        IoReleaseCancelSpinLock(Irp->CancelIrql);
        IoStartNextPacket(DeviceObject, TRUE);
    }
    else
    {
        /* Otherwise, remove the packet from the queue and relelase the lock */
        KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue,
                                 &Irp->Tail.Overlay.DeviceQueueEntry);
        IoReleaseCancelSpinLock(Irp->CancelIrql);
    }

    /* Complete the request */
    Irp->IoStatus.Status = STATUS_CANCELLED;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
}
Пример #3
0
VOID
disp_noio_urb_completion(PURB purb, PVOID context)
{
    PUSB_CTRL_SETUP_PACKET psetup;
    PURB purb2;
    PUSB_DEV_MANAGER dev_mgr;
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION irp_stack;
    PDEVEXT_HEADER dev_hdr;

    if (purb == NULL)
        return;

    psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;

    if ((psetup->bmRequestType == 0x2) &&
        (psetup->bRequest == USB_REQ_CLEAR_FEATURE) &&
        (psetup->wIndex == 0))       //reset pipe
    {
        purb2 = (PURB) context;
    }
    else
    {
        purb2 = purb;
    }

    if (purb2->pirp == NULL)
        return;

    dev_mgr = (PUSB_DEV_MANAGER) purb2->context;

    dev_mgr_remove_irp(dev_mgr, purb2->pirp);

    if (purb->status != STATUS_SUCCESS)
        status = STATUS_IO_DEVICE_ERROR;

    purb2->pirp->IoStatus.Information = 0;
    purb2->pirp->IoStatus.Status = status;
    irp_stack = IoGetCurrentIrpStackLocation(purb->pirp);
    if (irp_stack)
    {
        dev_hdr = irp_stack->DeviceObject->DeviceExtension;
        if (dev_hdr->start_io)
        {
            IoStartNextPacket(irp_stack->DeviceObject, TRUE);
        }
    }
    IoCompleteRequest(purb2->pirp, IO_NO_INCREMENT);
    return;
}
Пример #4
0
static VOID
i8042PacketDpc(
	IN PPORT_DEVICE_EXTENSION DeviceExtension)
{
	BOOLEAN FinishIrp = FALSE;
	KIRQL Irql;
	NTSTATUS Result = STATUS_INTERNAL_ERROR; /* Shouldn't happen */

	/* If the interrupt happens before this is setup, the key
	 * was already in the buffer. Too bad! */
	if (!DeviceExtension->HighestDIRQLInterrupt)
		return;

	Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt);

	if (DeviceExtension->Packet.State == Idle
	 && DeviceExtension->PacketComplete)
	{
		FinishIrp = TRUE;
		Result = DeviceExtension->PacketResult;
		DeviceExtension->PacketComplete = FALSE;
	}

	KeReleaseInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt, Irql);

	if (!FinishIrp)
		return;

	if (DeviceExtension->CurrentIrp)
	{
		DeviceExtension->CurrentIrp->IoStatus.Status = Result;
		IoCompleteRequest(DeviceExtension->CurrentIrp, IO_NO_INCREMENT);
		IoStartNextPacket(DeviceExtension->CurrentIrpDevice, FALSE);
		DeviceExtension->CurrentIrp = NULL;
		DeviceExtension->CurrentIrpDevice = NULL;
	}
}
Пример #5
0
NTSTATUS TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context)
{
    PTRANSFER_PACKET pkt = (PTRANSFER_PACKET)Context;
    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = pkt->Fdo->DeviceExtension;
    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
    PIO_STACK_LOCATION origCurrentSp = IoGetCurrentIrpStackLocation(pkt->OriginalIrp);
    BOOLEAN packetDone = FALSE;

    /*
     *  Put all the assertions and spew in here so we don't have to look at them.
     */
    DBGCHECKRETURNEDPKT(pkt);    
    
    if (SRB_STATUS(pkt->Srb.SrbStatus) == SRB_STATUS_SUCCESS){
        
        fdoData->LoggedTURFailureSinceLastIO = FALSE;
        
        /*
         *  The port driver should not have allocated a sense buffer
         *  if the SRB succeeded.
         */
        ASSERT(!PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb));

        /*
         *  Add this packet's transferred length to the original IRP's.
         */
        InterlockedExchangeAdd((PLONG)&pkt->OriginalIrp->IoStatus.Information, 
                              (LONG)pkt->Srb.DataTransferLength);

        if (pkt->InLowMemRetry){
            packetDone = StepLowMemRetry(pkt);
        }
        else {
            packetDone = TRUE;
        }
        
    }
    else {
        /*
         *  The packet failed.  We may retry it if possible.
         */
        BOOLEAN shouldRetry;
        
        /*
         *  Make sure IRP status matches SRB error status (since we propagate it).
         */
        if (NT_SUCCESS(Irp->IoStatus.Status)){
            Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
        }

        /*
         *  Interpret the SRB error (to a meaningful IRP status)
         *  and determine if we should retry this packet.
         *  This call looks at the returned SENSE info to figure out what to do.
         */
        shouldRetry = InterpretTransferPacketError(pkt);

        /*
         *  Sometimes the port driver can allocates a new 'sense' buffer
         *  to report transfer errors, e.g. when the default sense buffer
         *  is too small.  If so, it is up to us to free it.
         *  Now that we're done interpreting the sense info, free it if appropriate.
         */
        if (PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb)) {
            DBGTRACE(ClassDebugSenseInfo, ("Freeing port-allocated sense buffer for pkt %ph.", pkt));
            FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExt, &pkt->Srb);
            pkt->Srb.SenseInfoBuffer = &pkt->SrbErrorSenseData;
            pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
        }

        /*
         *  If the SRB queue is locked-up, release it.
         *  Do this after calling the error handler.
         */
        if (pkt->Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN){
            ClassReleaseQueue(pkt->Fdo);
        }
        
        if (shouldRetry && (pkt->NumRetries > 0)){           
            packetDone = RetryTransferPacket(pkt);
        }
        else {
            packetDone = TRUE;
        }
        
    }

    /*
     *  If the packet is completed, put it back in the free list.
     *  If it is the last packet servicing the original request, complete the original irp.
     */
    if (packetDone){
        LONG numPacketsRemaining;
        PIRP deferredIrp;
        PDEVICE_OBJECT Fdo = pkt->Fdo;
        UCHAR uniqueAddr;
        
        /*
         *  In case a remove is pending, bump the lock count so we don't get freed
         *  right after we complete the original irp.
         */
        ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddr);        

        /*
         *  The original IRP should get an error code
         *  if any one of the packets failed.
         */
        if (!NT_SUCCESS(Irp->IoStatus.Status)){
            pkt->OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;

            /*
             *  If the original I/O originated in user space (i.e. it is thread-queued), 
             *  and the error is user-correctable (e.g. media is missing, for removable media),
             *  alert the user.
             *  Since this is only one of possibly several packets completing for the original IRP,
             *  we may do this more than once for a single request.  That's ok; this allows
             *  us to test each returned status with IoIsErrorUserInduced().
             */
            if (IoIsErrorUserInduced(Irp->IoStatus.Status) &&
                pkt->CompleteOriginalIrpWhenLastPacketCompletes &&
                pkt->OriginalIrp->Tail.Overlay.Thread){

                IoSetHardErrorOrVerifyDevice(pkt->OriginalIrp, pkt->Fdo);
            }
        }

        /*
         *  We use a field in the original IRP to count
         *  down the transfer pieces as they complete.
         */
        numPacketsRemaining = InterlockedDecrement(
            (PLONG)&pkt->OriginalIrp->Tail.Overlay.DriverContext[0]);
            
        if (numPacketsRemaining > 0){
            /*
             *  More transfer pieces remain for the original request.
             *  Wait for them to complete before completing the original irp.
             */
        }
        else {

            /*
             *  All the transfer pieces are done.
             *  Complete the original irp if appropriate.
             */
            ASSERT(numPacketsRemaining == 0);
            if (pkt->CompleteOriginalIrpWhenLastPacketCompletes){  
                if (NT_SUCCESS(pkt->OriginalIrp->IoStatus.Status)){
                    ASSERT((ULONG)pkt->OriginalIrp->IoStatus.Information == origCurrentSp->Parameters.Read.Length);
                    ClasspPerfIncrementSuccessfulIo(fdoExt);
                }
                ClassReleaseRemoveLock(pkt->Fdo, pkt->OriginalIrp);

                ClassCompleteRequest(pkt->Fdo, pkt->OriginalIrp, IO_DISK_INCREMENT);

                /*
                 *  We may have been called by one of the class drivers (e.g. cdrom)
                 *  via the legacy API ClassSplitRequest.  
                 *  This is the only case for which the packet engine is called for an FDO
                 *  with a StartIo routine; in that case, we have to call IoStartNextPacket
                 *  now that the original irp has been completed.
                 */
                if (fdoExt->CommonExtension.DriverExtension->InitData.ClassStartIo) {
                    if (TEST_FLAG(pkt->Srb.SrbFlags, SRB_FLAGS_DONT_START_NEXT_PACKET)){
                        DBGTRAP(("SRB_FLAGS_DONT_START_NEXT_PACKET should never be set here (?)"));
                    }
                    else {
                        KIRQL oldIrql;
                        KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
                        IoStartNextPacket(pkt->Fdo, FALSE);
                        KeLowerIrql(oldIrql);
                    }
                }              
            }            
        }

        /*
         *  If the packet was synchronous, write the final
         *  result back to the issuer's status buffer and
         *  signal his event.
         */
        if (pkt->SyncEventPtr){
            KeSetEvent(pkt->SyncEventPtr, 0, FALSE);
            pkt->SyncEventPtr = NULL;
        }

        /*
         *  Free the completed packet.
         */
        pkt->OriginalIrp = NULL;
        pkt->InLowMemRetry = FALSE;
        EnqueueFreeTransferPacket(pkt->Fdo, pkt);

        /*
         *  Now that we have freed some resources,
         *  try again to send one of the previously deferred irps.
         */
        deferredIrp = DequeueDeferredClientIrp(fdoData);
        if (deferredIrp){
            DBGWARN(("... retrying deferred irp %xh.", deferredIrp)); 
            ServiceTransferRequest(pkt->Fdo, deferredIrp);
        }

        ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddr);        
    }

    return STATUS_MORE_PROCESSING_REQUIRED;
}
Пример #6
0
/*++////////////////////////////////////////////////////////////////////////////

ClassIoCompleteAssociated()

Routine Description:

    This routine executes when the port driver has completed a request.
    It looks at the SRB status in the completing SRB and if not success
    it checks for valid request sense buffer information. If valid, the
    info is used to update status with more precise message of type of
    error. This routine deallocates the SRB.  This routine is used for
    requests which were build by split request.  After it has processed
    the request it decrements the Irp count in the master Irp.  If the
    count goes to zero then the master Irp is completed.

Arguments:

    Fdo - Supplies the functional device object which represents the target.

    Irp - Supplies the Irp which has completed.

    Context - Supplies a pointer to the SRB.

Return Value:

    NT status

--*/
NTSTATUS
NTAPI
ClassIoCompleteAssociated(
    IN PDEVICE_OBJECT Fdo,
    IN PIRP Irp,
    IN PVOID Context
    )
{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;

    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    PSCSI_REQUEST_BLOCK srb = Context;

    PIRP originalIrp = Irp->AssociatedIrp.MasterIrp;
    LONG irpCount;

    NTSTATUS status;
    BOOLEAN retry;

    DBGWARN(("ClassIoCompleteAssociated is OBSOLETE !"));

    //
    // Check SRB status for success of completing request.
    //

    if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {

        ULONG retryInterval;

        DebugPrint((2,"ClassIoCompleteAssociated: IRP %p, SRB %p", Irp, srb));

        //
        // Release the queue if it is frozen.
        //

        if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
            ClassReleaseQueue(Fdo);
        }

        retry = ClassInterpretSenseInfo(
                    Fdo,
                    srb,
                    irpStack->MajorFunction,
                    irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ?
                        irpStack->Parameters.DeviceIoControl.IoControlCode :
                        0,
                    MAXIMUM_RETRIES -
                        ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4),
                    &status,
                    &retryInterval);

        //
        // If the status is verified required and the this request
        // should bypass verify required then retry the request.
        //

        if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
            status == STATUS_VERIFY_REQUIRED) {

            status = STATUS_IO_DEVICE_ERROR;
            retry = TRUE;
        }

        if (retry && ((*(PCHAR*)&irpStack->Parameters.Others.Argument4)--)) {

            //
            // Retry request. If the class driver has supplied a StartIo,
            // call it directly for retries.
            //

            DebugPrint((1, "Retry request %p\n", Irp));

            if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
                FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
            }

            RetryRequest(Fdo, Irp, srb, TRUE, retryInterval);

            return STATUS_MORE_PROCESSING_REQUIRED;
        }

    } else {

        //
        // Set status for successful request.
        //

        status = STATUS_SUCCESS;

    } // end if (SRB_STATUS(srb->SrbStatus) ...

    //
    // Return SRB to list.
    //

    if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
        FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
    }

    ClassFreeOrReuseSrb(fdoExtension, srb);

    //
    // Set status in completing IRP.
    //

    Irp->IoStatus.Status = status;

    DebugPrint((2, "ClassIoCompleteAssociated: Partial xfer IRP %p\n", Irp));

    //
    // Get next stack location. This original request is unused
    // except to keep track of the completing partial IRPs so the
    // stack location is valid.
    //

    irpStack = IoGetNextIrpStackLocation(originalIrp);

    //
    // Update status only if error so that if any partial transfer
    // completes with error, then the original IRP will return with
    // error. If any of the asynchronous partial transfer IRPs fail,
    // with an error then the original IRP will return 0 bytes transfered.
    // This is an optimization for successful transfers.
    //

    if (!NT_SUCCESS(status)) {

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

        //
        // Set the hard error if necessary.
        //

        if (IoIsErrorUserInduced(status)) {

            //
            // Store DeviceObject for filesystem.
            //

            IoSetHardErrorOrVerifyDevice(originalIrp, Fdo);
        }
    }

    //
    // Decrement and get the count of remaining IRPs.
    //

    irpCount = InterlockedDecrement(
                    (PLONG)&irpStack->Parameters.Others.Argument1);

    DebugPrint((2, "ClassIoCompleteAssociated: Partial IRPs left %d\n",
                irpCount));

    //
    // Ensure that the irpCount doesn't go negative.  This was happening once
    // because classpnp would get confused if it ran out of resources when
    // splitting the request.
    //

    ASSERT(irpCount >= 0);

    if (irpCount == 0) {

        //
        // All partial IRPs have completed.
        //

        DebugPrint((2,
                 "ClassIoCompleteAssociated: All partial IRPs complete %p\n",
                 originalIrp));

        if (fdoExtension->CommonExtension.DriverExtension->InitData.ClassStartIo) {

            //
            // Acquire a separate copy of the remove lock so the debugging code
            // works okay and we don't have to hold up the completion of this
            // irp until after we start the next packet(s).
            //

            KIRQL oldIrql;
            UCHAR uniqueAddress;
            ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddress);
            ClassReleaseRemoveLock(Fdo, originalIrp);
            ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT);

            KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
            IoStartNextPacket(Fdo, FALSE);
            KeLowerIrql(oldIrql);

            ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddress);

        } else {

            //
            // just complete this request
            //

            ClassReleaseRemoveLock(Fdo, originalIrp);
            ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT);

        }

    }

    //
    // Deallocate IRP and indicate the I/O system should not attempt any more
    // processing.
    //

    IoFreeIrp(Irp);
    return STATUS_MORE_PROCESSING_REQUIRED;

} // end ClassIoCompleteAssociated()
Пример #7
0
VOID
USBSTOR_QueueNextRequest(
    IN PDEVICE_OBJECT DeviceObject)
{
    PFDO_DEVICE_EXTENSION FDODeviceExtension;
    PIRP Irp;
    PIO_STACK_LOCATION IoStack;
    PSCSI_REQUEST_BLOCK Request;

    //
    // get pdo device extension
    //
    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    //
    // sanity check
    //
    ASSERT(FDODeviceExtension->Common.IsFDO);

    //
    // check first if there's already a request pending or the queue is frozen
    //
    if (FDODeviceExtension->ActiveSrb != NULL ||
        FDODeviceExtension->IrpListFreeze)
    {
        //
        // no work to do yet
        //
        return;
    }

    //
    // remove first irp from list
    //
    Irp = USBSTOR_RemoveIrp(DeviceObject);

    //
    // is there an irp pending
    //
    if (!Irp)
    {
        //
        // no work to do
        //
        IoStartNextPacket(DeviceObject, TRUE);
        return;
    }

    //
    // get current stack location
    //
    IoStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // get srb
    //
    Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;

    //
    // sanity check
    //
    ASSERT(Request);

    //
    // set the active SRB
    //
    FDODeviceExtension->ActiveSrb = Request;

    //
    // start next packet
    //
    IoStartPacket(DeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);

    //
    // start next request
    //
    IoStartNextPacket(DeviceObject, TRUE);
}
Пример #8
0
VOID
DBusStartIo(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine starts an I/O operation for the device.

Arguments:

    DeviceObject - Pointer to the device object.

    Irp - Pointer to the request packet.

Return Value:

    None.

--*/

{
    PDEVICE_EXTENSION deviceExtension;
    PIO_STACK_LOCATION irpSp;

    BusPrint((2, "DBusStartIo: enter\n"));

    deviceExtension = DeviceObject->DeviceExtension;

    //
    // Bump the error log sequence number.
    //

    deviceExtension->SequenceNumber += 1;

    //
    // Get a pointer to the current parameters for this request.  The
    // information is contained in the current stack location.
    //

    irpSp = IoGetCurrentIrpStackLocation(Irp);

    //
    // We know we got here with an internal device control request.  Switch
    // on IoControlCode.
    //

    switch(irpSp->Parameters.DeviceIoControl.IoControlCode) {

        //
        // Enable mouse interrupts, by calling BusEnableInterrupts
        // synchronously.
        //

        case IOCTL_INTERNAL_MOUSE_ENABLE:

            KeSynchronizeExecution(
                deviceExtension->InterruptObject,
                (PKSYNCHRONIZE_ROUTINE) BusEnableInterrupts,
                (PVOID) deviceExtension
                );

            BusPrint((
                2, 
                "DBusStartIo: mouse enable (count %d)\n",
                deviceExtension->MouseEnableCount
                ));

            Irp->IoStatus.Status = STATUS_SUCCESS;

            //
            // Complete the request.
            //

            IoStartNextPacket(DeviceObject, FALSE);
            IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);

            break;

        //
        // Disable mouse interrupts, by calling BusDisableInterrupts
        // synchronously.
        //

        case IOCTL_INTERNAL_MOUSE_DISABLE:

            BusPrint((2, "DBusStartIo: mouse disable"));

            if (deviceExtension->MouseEnableCount == 0) {

                //
                // Mouse already disabled.
                //

                BusPrint((2, " - error\n"));

                Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;

            } else {

                //
                // Disable mouse by calling BusDisableInterrupts.
                //

                KeSynchronizeExecution(
                    deviceExtension->InterruptObject,
                    (PKSYNCHRONIZE_ROUTINE) BusDisableInterrupts,
                    (PVOID) deviceExtension
                    );

                BusPrint((
                    2, 
                    " (count %d)\n",
                    deviceExtension->MouseEnableCount
                    ));

                Irp->IoStatus.Status = STATUS_SUCCESS;
            }

            //
            // Complete the request.
            //

            IoStartNextPacket(DeviceObject, FALSE);
            IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);

            break;

        default:

            BusPrint((2, "DBusStartIo: INVALID REQUEST\n"));

            //
            // Log an internal error.  Note that we're calling the
            // error log DPC routine directly, rather than duplicating
            // code.
            //

            BusErrorLogDpc(
                (PKDPC) NULL,
                DeviceObject,
                Irp,
                (PVOID) (ULONG) BUSMOUSE_INVALID_STARTIO_REQUEST
                );

            ASSERT(FALSE);
            break;
    }

    BusPrint((2, "DBusStartIo: exit\n"));

    return;
}
Пример #9
0
VOID
LspTransferCompletion(
	__in PIRP TransferIrp,
	__in PXTDI_OVERLAPPED Overlapped)
{
	NTSTATUS status;
	PDEVICE_OBJECT deviceObject;
	PDEVICE_EXTENSION deviceExtension;

	LONG outstandingLspTransfer;
	KIRQL oldIrql;
	IO_STATUS_BLOCK txIoStatus;

	UNREFERENCED_PARAMETER(TransferIrp);

	deviceObject = (PDEVICE_OBJECT) Overlapped->UserContext;
	deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;

	outstandingLspTransfer = InterlockedDecrement(&deviceExtension->LspTransferCount);
	ASSERT(outstandingLspTransfer >= 0);

	LSP_KDPRINT(("LspTransferCompletion: TransferIrp=%p, Overlapped=%p, TxCount=%d\n", 
		TransferIrp, Overlapped, outstandingLspTransfer));

	if (0 == outstandingLspTransfer)
	{
		txIoStatus = Overlapped->IoStatus;
		deviceExtension->LspStatus = lsp_process_next(deviceExtension->LspHandle);

		LspDataResetAll(deviceObject);

		status = LspProcessNext(deviceObject, &deviceExtension->LspStatus);

		if (STATUS_PENDING == status)
		{
			return;
		}

		if (NULL != deviceExtension->CurrentIrp)
		{
			//
			// Asynchronous Transfer in progress
			//
			PIRP irp = deviceExtension->CurrentIrp;
			
			LSP_KDPRINT(("LspTransferCompletion: Completing Irp=%p.\n", irp));
			
			deviceExtension->CurrentIrp = NULL;
			irp->IoStatus.Status = 
				NT_SUCCESS(txIoStatus.Status) ? status : txIoStatus.Status;
			if (!NT_SUCCESS(irp->IoStatus.Status))
			{
				irp->IoStatus.Information = 0;
			}

			IoCompleteRequest(
				irp, 
				IO_NO_INCREMENT);
			//
			// IoStartNextPacket should be running at DISPATCH_LEVEL
			//
			ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
			oldIrql = KeRaiseIrqlToDpcLevel();
			IoStartNextPacket(deviceObject, TRUE);
			KeLowerIrql(oldIrql);
			return;
		}
		else
		{
			//
			// Synchronous Transfer in progress
			//
			LSP_KDPRINT(("LspTransferCompletion: Synchronous transfer event=%p.\n", &deviceExtension->LspCompletionEvent));
			KeSetEvent(
				&deviceExtension->LspCompletionEvent, 
				IO_NO_INCREMENT, 
				FALSE);
		}
	}
}
Пример #10
0
VOID
disp_urb_completion(PURB purb, PVOID context)
{
    PUSB_DEV_MANAGER dev_mgr;
    ULONG ctrl_code;
    NTSTATUS status;
    PDEVEXT_HEADER dev_hdr;

    UNREFERENCED_PARAMETER(context);

    if (purb == NULL)
        return;

    ctrl_code = (ULONG) purb->reference;
    dev_mgr = (PUSB_DEV_MANAGER) purb->context;

    // at this stage, the irp can not be canceled since the urb
    // won't be found in any queue and the irp is not in any queue.
    // see line 4685 in hub.c
    // Sometimes, it may be very fast to enter this routine before
    // the dev_mgr_register_irp to be called in dispatch routine in
    // usb2.0 environment as
    // we did in usb1.1 driver. We can not simply add a loop to wait
    // for the dispatch thread to add the irp to the list, because
    // here we are at DPC level higher than the dispatch thread
    // running level. And the solution is to register the irp
    // before the urb is scheduled instead of registering it after
    // urb is scheduled.
    if (purb->pirp)
    {
        PIO_STACK_LOCATION irp_stack;
        dev_mgr_remove_irp(dev_mgr, purb->pirp);

        status = purb->status;
        irp_stack = IoGetCurrentIrpStackLocation(purb->pirp);

        if (purb->status != STATUS_SUCCESS)
        {
            purb->pirp->IoStatus.Information = 0;
        }
        else
        {
            // currently only IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL
            // are allowed. And we do not need to set information
            // for IRP_MJ_INTERNAL_DEVICE_CONTROL
            if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
                purb->pirp->IoStatus.Information = purb->data_length;
        }
        purb->pirp->IoStatus.Status = status;
        if (irp_stack)
        {
            dev_hdr = irp_stack->DeviceObject->DeviceExtension;
            if (dev_hdr->start_io)
            {
                IoStartNextPacket(irp_stack->DeviceObject, TRUE);
            }
        }
        IoCompleteRequest(purb->pirp, IO_NO_INCREMENT);
    }
    return;
}
Пример #11
0
VOID
LspStartIo(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp)
{
	NTSTATUS status;
	lsp_status_t lspStatus;
	PIO_STACK_LOCATION irpStack;
	PDEVICE_EXTENSION deviceExtension;

	LSP_KDPRINT(("LspStartIo: Irp=%p\n", Irp));

	irpStack = IoGetCurrentIrpStackLocation(Irp);
	deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

	switch (irpStack->MajorFunction)
	{
	case IRP_MJ_CREATE:
		{
			deviceExtension->LspTransferCount = 0;
			deviceExtension->CurrentIrp = NULL;

			IoQueueWorkItem(
				deviceExtension->CloseWorkItem,
				LspCreateWorkItem,
				DelayedWorkQueue,
				Irp);
		}
		break;
	case IRP_MJ_CLOSE:
		{
			deviceExtension->LspTransferCount = 0;
			deviceExtension->CurrentIrp = NULL;

			IoQueueWorkItem(
				deviceExtension->CloseWorkItem, 
				LspCloseWorkItem, 
				DelayedWorkQueue, 
				Irp);
		}
		break;
	case IRP_MJ_READ:
		{
			LARGE_INTEGER location;
			PVOID dataBuffer;
			ULONG dataLength;
			KIRQL oldIrql;

			static ULONG random = 0;

			location.QuadPart = random++;

			dataLength = irpStack->Parameters.Read.Length;
			dataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

			if (NULL == dataBuffer)
			{
				Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
				Irp->IoStatus.Information = 0;
				IoCompleteRequest(Irp, IO_NO_INCREMENT);
				return;
			}

			if (0 != (dataLength % 512))
			{
				Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
				Irp->IoStatus.Information = 0;
				IoCompleteRequest(Irp, IO_NO_INCREMENT);
				return;
			}

			// KeAcquireSpinLock(&deviceExtension->LspLock, &oldIrql);

			deviceExtension->LspTransferCount = 0;
			deviceExtension->CurrentIrp = Irp;

			deviceExtension->LspStatus = lsp_ide_read(
				deviceExtension->LspHandle,
				(lsp_large_integer_t*)&location,
				(lsp_int16_t)(dataLength >> 9),
				dataBuffer,
				dataLength);

			Irp->IoStatus.Information = dataLength;
			// KeReleaseSpinLock(&deviceExtension->LspLock, oldIrql);

			status = LspProcessNext(DeviceObject, &deviceExtension->LspStatus);
			if (STATUS_PENDING != status)
			{
				deviceExtension->CurrentIrp = NULL;
				Irp->IoStatus.Status = status;
				IoCompleteRequest(Irp, IO_NO_INCREMENT);
				IoStartNextPacket(DeviceObject, TRUE);
				return;
			}
		}
		break;
	default:
		ASSERT(FALSE);
	}
}
Пример #12
0
NTSTATUS TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context)
{
    PTRANSFER_PACKET pkt = (PTRANSFER_PACKET)Context;
    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = pkt->Fdo->DeviceExtension;
    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
    BOOLEAN packetDone = FALSE;
    BOOLEAN idleRequest = FALSE;

    /*
     *  Put all the assertions and spew in here so we don't have to look at them.
     */
    DBGLOGRETURNPACKET(pkt);
    DBGCHECKRETURNEDPKT(pkt);
    HISTORYLOGRETURNEDPACKET(pkt);

    if (fdoData->IdlePrioritySupported == TRUE) {
        idleRequest = ClasspIsIdleRequest(pkt->OriginalIrp);
        if (idleRequest) {
            InterlockedDecrement(&fdoData->ActiveIdleIoCount);
            ASSERT(fdoData->ActiveIdleIoCount >= 0);
        } else {
            InterlockedDecrement(&fdoData->ActiveIoCount);
            ASSERT(fdoData->ActiveIoCount >= 0);
            KeQuerySystemTime(&fdoData->LastIoTime);
            fdoData->IdleTicks = 0;
        }
    }

    //
    // If partial MDL was used, unmap the pages.  When the packet is retried, the
    // MDL will be recreated.  If the packet is done, the MDL will be ready to be reused.
    //
    if (pkt->UsePartialMdl) {
        MmPrepareMdlForReuse(pkt->PartialMdl);
    }

    if (SRB_STATUS(pkt->Srb.SrbStatus) == SRB_STATUS_SUCCESS) {

        fdoData->LoggedTURFailureSinceLastIO = FALSE;

        /*
         *  The port driver should not have allocated a sense buffer
         *  if the SRB succeeded.
         */
        ASSERT(!PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb));

        /*
         *  Add this packet's transferred length to the original IRP's.
         */
        InterlockedExchangeAdd((PLONG)&pkt->OriginalIrp->IoStatus.Information,
                              (LONG)pkt->Srb.DataTransferLength);

        if ((pkt->InLowMemRetry) ||
            (pkt->DriverUsesStartIO && pkt->LowMemRetry_remainingBufLen > 0)) {
            packetDone = StepLowMemRetry(pkt);
        }
        else {
            packetDone = TRUE;
        }

    }
    else {
        /*
         *  The packet failed.  We may retry it if possible.
         */
        BOOLEAN shouldRetry;

        /*
         *  Make sure IRP status matches SRB error status (since we propagate it).
         */
        if (NT_SUCCESS(Irp->IoStatus.Status)){
            Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
        }

        /*
         *  The packet failed.
         *  So when sending the packet down we either saw either an error or STATUS_PENDING,
         *  and so we returned STATUS_PENDING for the original IRP.
         *  So now we must mark the original irp pending to match that, _regardless_ of
         *  whether we actually switch threads here by retrying.
         *  (We also have to mark the irp pending if the lower driver marked the irp pending;
         *   that is dealt with farther down).
         */
        if (pkt->CompleteOriginalIrpWhenLastPacketCompletes){
            IoMarkIrpPending(pkt->OriginalIrp);
        }

        /*
         *  Interpret the SRB error (to a meaningful IRP status)
         *  and determine if we should retry this packet.
         *  This call looks at the returned SENSE info to figure out what to do.
         */
        shouldRetry = InterpretTransferPacketError(pkt);

        /*
         *  Sometimes the port driver can allocates a new 'sense' buffer
         *  to report transfer errors, e.g. when the default sense buffer
         *  is too small.  If so, it is up to us to free it.
         *  Now that we're done interpreting the sense info, free it if appropriate.
         *  Then clear the sense buffer so it doesn't pollute future errors returned in this packet.
         */
        if (PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb)) {
            TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "Freeing port-allocated sense buffer for pkt %ph.", pkt));
            FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExt, &pkt->Srb);
            pkt->Srb.SenseInfoBuffer = &pkt->SrbErrorSenseData;
            pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
        }
        else {
            ASSERT(pkt->Srb.SenseInfoBuffer == &pkt->SrbErrorSenseData);
            ASSERT(pkt->Srb.SenseInfoBufferLength <= sizeof(SENSE_DATA));
        }
        RtlZeroMemory(&pkt->SrbErrorSenseData, sizeof(SENSE_DATA));

        /*
         *  If the SRB queue is locked-up, release it.
         *  Do this after calling the error handler.
         */
        if (pkt->Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN){
            ClassReleaseQueue(pkt->Fdo);
        }

        if (NT_SUCCESS(Irp->IoStatus.Status)){
            /*
             *  The error was recovered above in the InterpretTransferPacketError() call.
             */

            ASSERT(!shouldRetry);

            /*
             *  In the case of a recovered error,
             *  add the transfer length to the original Irp as we would in the success case.
             */
            InterlockedExchangeAdd((PLONG)&pkt->OriginalIrp->IoStatus.Information,
                                  (LONG)pkt->Srb.DataTransferLength);

            if ((pkt->InLowMemRetry) ||
                (pkt->DriverUsesStartIO && pkt->LowMemRetry_remainingBufLen > 0)) {
                packetDone = StepLowMemRetry(pkt);
            }
            else {
                packetDone = TRUE;
            }
        }
        else {
            if (shouldRetry && (pkt->NumRetries > 0)){
                packetDone = RetryTransferPacket(pkt);
            }
            else if (shouldRetry && (pkt->RetryHistory != NULL)){
                // don't limit retries if class driver has custom interpretation routines
                packetDone = RetryTransferPacket(pkt);
            }
            else {
                packetDone = TRUE;
            }
        }
    }

    /*
     *  If the packet is completed, put it back in the free list.
     *  If it is the last packet servicing the original request, complete the original irp.
     */
    if (packetDone){
        LONG numPacketsRemaining;
        PIRP deferredIrp;
        PDEVICE_OBJECT Fdo = pkt->Fdo;
        UCHAR uniqueAddr;

        /*
         *  In case a remove is pending, bump the lock count so we don't get freed
         *  right after we complete the original irp.
         */
        ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddr);


        /*
         *  The original IRP should get an error code
         *  if any one of the packets failed.
         */
        if (!NT_SUCCESS(Irp->IoStatus.Status)){
            pkt->OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;

            /*
             *  If the original I/O originated in user space (i.e. it is thread-queued),
             *  and the error is user-correctable (e.g. media is missing, for removable media),
             *  alert the user.
             *  Since this is only one of possibly several packets completing for the original IRP,
             *  we may do this more than once for a single request.  That's ok; this allows
             *  us to test each returned status with IoIsErrorUserInduced().
             */
            if (IoIsErrorUserInduced(Irp->IoStatus.Status) &&
                pkt->CompleteOriginalIrpWhenLastPacketCompletes &&
                pkt->OriginalIrp->Tail.Overlay.Thread){

                IoSetHardErrorOrVerifyDevice(pkt->OriginalIrp, Fdo);
            }
        }

        /*
         *  We use a field in the original IRP to count
         *  down the transfer pieces as they complete.
         */
        numPacketsRemaining = InterlockedDecrement(
            (PLONG)&pkt->OriginalIrp->Tail.Overlay.DriverContext[0]);

        if (numPacketsRemaining > 0){
            /*
             *  More transfer pieces remain for the original request.
             *  Wait for them to complete before completing the original irp.
             */
        }
        else {

            /*
             *  All the transfer pieces are done.
             *  Complete the original irp if appropriate.
             */
            ASSERT(numPacketsRemaining == 0);
            if (pkt->CompleteOriginalIrpWhenLastPacketCompletes){

                IO_PAGING_PRIORITY priority = (TEST_FLAG(pkt->OriginalIrp->Flags, IRP_PAGING_IO)) ? IoGetPagingIoPriority(pkt->OriginalIrp) : IoPagingPriorityInvalid;
                KIRQL oldIrql;

                if (NT_SUCCESS(pkt->OriginalIrp->IoStatus.Status)){
                    ASSERT((ULONG)pkt->OriginalIrp->IoStatus.Information ==  IoGetCurrentIrpStackLocation(pkt->OriginalIrp)->Parameters.Read.Length);
                    ClasspPerfIncrementSuccessfulIo(fdoExt);
                }
                ClassReleaseRemoveLock(Fdo, pkt->OriginalIrp);

                /*
                 *  We submitted all the downward irps, including this last one, on the thread
                 *  that the OriginalIrp came in on.  So the OriginalIrp is completing on a
                 *  different thread iff this last downward irp is completing on a different thread.
                 *  If BlkCache is loaded, for example, it will often complete
                 *  requests out of the cache on the same thread, therefore not marking the downward
                 *  irp pending and not requiring us to do so here.  If the downward request is completing
                 *  on the same thread, then by not marking the OriginalIrp pending we can save an APC
                 *  and get extra perf benefit out of BlkCache.
                 *  Note that if the packet ever cycled due to retry or LowMemRetry,
                 *  we set the pending bit in those codepaths.
                 */
                if (pkt->Irp->PendingReturned){
                    IoMarkIrpPending(pkt->OriginalIrp);
                }


                ClassCompleteRequest(Fdo, pkt->OriginalIrp, IO_DISK_INCREMENT);

                //
                // Drop the count only after completing the request, to give
                // Mm some amount of time to issue its next critical request
                //

                if (priority == IoPagingPriorityHigh)
                {
                    KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);

                    if (fdoData->MaxInterleavedNormalIo < ClassMaxInterleavePerCriticalIo)
                    {
                        fdoData->MaxInterleavedNormalIo = 0;
                    }
                    else
                    {
                        fdoData->MaxInterleavedNormalIo -= ClassMaxInterleavePerCriticalIo;
                    }

                    fdoData->NumHighPriorityPagingIo--;

                    if (fdoData->NumHighPriorityPagingIo == 0)
                    {
                        LARGE_INTEGER period;

                        //
                        // Exiting throttle mode
                        //

                        KeQuerySystemTime(&fdoData->ThrottleStopTime);

                        period.QuadPart = fdoData->ThrottleStopTime.QuadPart - fdoData->ThrottleStartTime.QuadPart;
                        fdoData->LongestThrottlePeriod.QuadPart = max(fdoData->LongestThrottlePeriod.QuadPart, period.QuadPart);
                    }

                    KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
                }

                if (idleRequest) {
                    ClasspCompleteIdleRequest(fdoExt);
                }

                /*
                 *  We may have been called by one of the class drivers (e.g. cdrom)
                 *  via the legacy API ClassSplitRequest.
                 *  This is the only case for which the packet engine is called for an FDO
                 *  with a StartIo routine; in that case, we have to call IoStartNextPacket
                 *  now that the original irp has been completed.
                 */
                if (fdoExt->CommonExtension.DriverExtension->InitData.ClassStartIo) {
                    if (TEST_FLAG(pkt->Srb.SrbFlags, SRB_FLAGS_DONT_START_NEXT_PACKET)){
                        TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "SRB_FLAGS_DONT_START_NEXT_PACKET should never be set here (??)"));
                    }
                    else {
                        KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
                        IoStartNextPacket(Fdo, TRUE); // yes, some IO is now cancellable
                        KeLowerIrql(oldIrql);
                    }
                }
            }
        }

        /*
         *  If the packet was synchronous, write the final result back to the issuer's status buffer
         *  and signal his event.
         */
        if (pkt->SyncEventPtr){
            KeSetEvent(pkt->SyncEventPtr, 0, FALSE);
            pkt->SyncEventPtr = NULL;
        }

        /*
         *  Free the completed packet.
         */
        pkt->UsePartialMdl = FALSE;
//        pkt->OriginalIrp = NULL;
        pkt->InLowMemRetry = FALSE;
        EnqueueFreeTransferPacket(Fdo, pkt);

        /*
         *  Now that we have freed some resources,
         *  try again to send one of the previously deferred irps.
         */
        deferredIrp = DequeueDeferredClientIrp(fdoData);
        if (deferredIrp){
            ServiceTransferRequest(Fdo, deferredIrp);
        }

        ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddr);
    }

    return STATUS_MORE_PROCESSING_REQUIRED;
}
Пример #13
0
VOID
NTAPI
BeepStartIo(IN PDEVICE_OBJECT DeviceObject,
            IN PIRP Irp)
{
    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
    KIRQL CancelIrql;
    PIO_STACK_LOCATION IoStack;
    PBEEP_SET_PARAMETERS BeepParam;
    LARGE_INTEGER DueTime;
    NTSTATUS Status;

    /* Acquire the cancel lock and make sure the IRP is valid */
    IoAcquireCancelSpinLock(&CancelIrql);
    if (!Irp)
    {
        /* It's not, release the lock and quit */
        IoReleaseCancelSpinLock(CancelIrql);
        return;
    }

    /* Remove the cancel routine and release the lock */
    (VOID)IoSetCancelRoutine(Irp, NULL);
    IoReleaseCancelSpinLock(CancelIrql);

    /* Get the I/O Stack and make sure the request is valid */
    BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
    IoStack = IoGetCurrentIrpStackLocation(Irp);
    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_BEEP_SET)
    {
        /* Check if we have an active timer */
        if (DeviceExtension->TimerActive)
        {
            /* Cancel it */
            if (KeCancelTimer(&DeviceExtension->Timer))
            {
                /* Set the state */
                InterlockedDecrement(&DeviceExtension->TimerActive);
            }
        }

        /* Make the beep */
        if (HalMakeBeep(BeepParam->Frequency))
        {
            /* Beep successful, queue a DPC to stop it */
            Status = STATUS_SUCCESS;
            DueTime.QuadPart = Int32x32To64(BeepParam->Duration, -10000);
            InterlockedIncrement(&DeviceExtension->TimerActive);
            KeSetTimer(&DeviceExtension->Timer, DueTime, &DeviceObject->Dpc);
        }
        else
        {
            /* Beep has failed */
            Status = STATUS_INVALID_PARAMETER;
        }
    }
    else
    {
        /* Invalid request */
        Status = STATUS_INVALID_PARAMETER;
    }

    /* Complete the request and start the next packet */
    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = 0;
    IoStartNextPacket(DeviceObject, TRUE);
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
}