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

📄 pnp.c

📁 PCI驱动编程实例
💻 C
📖 第 1 页 / 共 4 页
字号:

                //
                // The bus driver has declined to start the device.
                // Oh well...
                //
#if DBG
                DbgPrint("OsrPnp: IoCallDriver() for START fails! 0x%0x \n", code);
#endif

            }

            //
            // We must now complete the IRP, since we stopped it in the
            // completetion routine with MORE_PROCESSING_REQUIRED.
            //
            Irp->IoStatus.Status = code;

            Irp->IoStatus.Information = 0;

            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            
            break;



        //
        // STATE:   STARTED
        // IRP_MN:  _QUERY_REMOVE
        //
        // We're here because we're running, and the PnP Manager wants
        // to "nicely" remove our device.  This is the orderly way
        // PnP Manager handles device disconnections (as opposed to
        // doing a SURPRISE_REMOVAL).
        //
        // What we do here is (a) change the state of the device such
        // that newly arriving requests will be rejected, (b) wait for
        // all requests to complete on the device, and (c) pass the
        // request on down.
        //
        case STATE_STARTED + IRP_MN_QUERY_REMOVE_DEVICE:

#if DBG
            DbgPrint("OsrPnp: PROCESSING QUERY_REMOVE_DEVICE\n");
#endif
            //
            // WE process this request FIRST
            //
 
            //
            // See if we're OK with removing the device at this point.
            // We do NOT actually RETURN the resources here... we
            // just affirm or deny that we're OK with returning them.
            //
            code = OsrCanRemoveDevice(devExt, Irp);
            
            //
            // Replace status code that's in the IRP to indicate our
            // opinion about stopping the device.  If we're
            // OK with returning the resources, this will be
            // STATUS_SUCCESS.
            //
            Irp->IoStatus.Status = code;

            if(!NT_SUCCESS(code)) {

                //
                // NOPE.  Can't remove the device because, for some
                // reason (perhaps because we can't return our
                // resources).  Too bad. Tell the PnP Manager that
                // stopping right now is not an option for us.
                //
                // NOTE: NO NEED to pass IRP down if WE can't stop
                // it doesn't matter if the Bus Driver can.
                //
                IoCompleteRequest(Irp, IO_NO_INCREMENT);
                        
                
            } else {                    

#if DBG
                DbgPrint("OsrPnp: Waiting for pending requests to complete. (%d. remain)\n", devExt->OutstandingIO);
#endif

                //
                // Set new state -- This state results in any new
                // requests received at our dispatch entry points
                // being REJECTED... any request still on the queues
                // are allowed to complete, however.
                //
                devExt->State = STATE_REMOVE_PENDING;

                //
                // Decrement our reference on the device here, and then
                // wait until there are no requests active or on the
                // device's queues.
                //
                OsrRequestDecrement(devExt);

                OsrWaitForRemove(devExt);
                
                //
                // OK.  No further requests remain.  Let the bus driver
                // know.

                //
                // DECREMENTED REQUEST COUNT above.  Return immediately
                // below.
                //
#if DBG
                DbgPrint("OsrPnp: Leaving With state: ");
                OsrPrintState(devExt);
#endif
                //
                // Pass this request on down to the bus driver
                //
                IoSkipCurrentIrpStackLocation(Irp);

                return(IoCallDriver(devExt->DeviceToSendIrpsTo, Irp));

            }
            break;

        //
        // STATE:   REMOVE_PENDING
        // IRP_MN:  _REMOVE_DEVICE
        //
        // We're here because we've previously received notification
        // of the intention to remove the device in an orderly way.
        // We return our resources here, and then tear down our device
        // object.  Note that there can be no requests pending at this
        // point, because we finished them all during QUERY_REMOVE
        // processing (before entering RemovePending state)
        //
        case STATE_REMOVE_PENDING + IRP_MN_REMOVE_DEVICE:

            //
            // All queued and active IRPs are complete at this point.
            //

            //
            // Return any resources we're using.
            //
            OsrReturnResources(devExt);

            //
            // Fall through...
            //

        //
        // STATE:   SURPRISE_REMOVED
        // IRP_MN:  _REMOVE_DEVICE
        //
        // We're here because we've previously received notification
        // of a "surprise" removal.  At this point, we just tear down
        // our device object
        //
        case STATE_SURPRISE_REMOVED + IRP_MN_REMOVE_DEVICE:

            //
            // Removing the device at this point is NOT optional.
            //
            #if DBG
            DbgPrint("OsrPnp: REMOVE_DEVICE\n");
            #endif

            //
            // Device has been removed
            //
            devExt->State = STATE_REMOVED;

            //
            // Decrement our reference on the device here, and then
            // wait until we can remove the device.  Because we would
            // have gotten a prior warning of this removal (via an
            // IRP_MN_SUPRISE_REMOVAL or an IRP_MN_QUERY_REMOVE) and
            // at that time transitioned state appropriately, there
            // should be no requests outstanding here.
            //
            OsrRequestDecrement(devExt);
        
#if DBG
            DbgPrint("OsrPnp: Waiting for pending requests to complete. %d. remain\n", devExt->OutstandingIO);
#endif
            OsrWaitForRemove(devExt);
            
            //
            // WE process this request first
            //

            //
            // Detach from the PDO 
            //
            IoDetachDevice(devExt->DeviceToSendIrpsTo);

            targetDevice = devExt->DeviceToSendIrpsTo;

#if DBG
            devExt->DeviceToSendIrpsTo = NULL;

            devExt = NULL;
#endif
            //
            // Return our device object
            //
            IoDeleteDevice(devExt->FunctionalDeviceObject);

            //
            // Indidcate that we've successfully processed the IRP
            //
            Irp->IoStatus.Status = STATUS_SUCCESS;

            //
            // Pass this request on down to the bus driver
            //
            IoSkipCurrentIrpStackLocation(Irp);

            code = IoCallDriver(targetDevice, Irp);
            
            ASSERT(code != STATUS_PENDING);

            //
            // IMPORTANT: We decremented our I/O In Progress count
            // above... We don't want to decrement it again, so we
            // return right here.
            //
#if DBG
            DbgPrint("OsrPnp: Leaving with state: STATE_REMOVE");
#endif
            return(code);

            break;

        //
        // STATE:   STARTED
        // IRP_MN:  _SURPRISE_REMOVAL
        //
        // We're here when the device is running, and a device is
        // forcibly removed.  PnP Manager will send us a remove device
        // IRP when we're supposed to actually return our resources
        // and the like.
        //
        // Note that this is a "best effort" activity.  It is quite
        // possible, due to timing issues etc, that we'll crash the
        // system because the device is gone.  While we'll TRY not
        // to do this, it is within the rules.
        //
        // THIS IRP IS NOT SENT ON Win9x.
        //
        case STATE_STARTED + IRP_MN_SURPRISE_REMOVAL:

            devExt->State = STATE_SURPRISE_REMOVED;

            //
            // We handle this request before the bus driver
            //

            //
            // Cancel any pending requests... make sure
            // the active requests get stopped within a second (with
            // no hardware access, as a result of setting the state
            // above).
            //
            OsrClearQueues(devExt);

            //
            // We're happy... sort of.  Note that it's not "legal"
            // to fail this request.  Afterall, what woudl that MEAN?
            //
            Irp->IoStatus.Status = STATUS_SUCCESS;

            //
            // Pass this request on down to the bus driver
            //
            IoSkipCurrentIrpStackLocation(Irp);

            code = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp);

            break;

        //
        // STATE:   STARTED
        // IRP_MN:  _REMOVE_DEVICE
        //
        // We're here when the device is running, and a device is
        // forcibly removed.
        //
        // Note that like getting a SUPRISE_REMOVAL IRP on NT trying
        // to handle a removal directly from started state is a "best
        // effort" type of activity.  We'll do what we can but it's
        // possible, due to timing issues etc, that we'll crash the
        // system because the device is gone.  While we'll TRY not
        // to do this, it could be unavoidable.  Oh well.
        //
        // ON NT, we'd get an IRP_MN_SURPRISE_REMOVAL instead of this
        // IRP in this state.  We get this only on Win9x systems.
        //
        case STATE_STARTED + IRP_MN_REMOVE_DEVICE:

#if DBG
            DbgPrint("OsrPnp: REMOVE_DEVICE\n");
#endif
            devExt->State = STATE_REMOVED;

            //
            // We handle this request before the bus driver
            // Note that this is another one of those requests we're
            // not "allowed" to fail.
            //

            //
            // Cancel any pending requests... make sure
            // the active requests get stopped within a second (with
            // no hardware access, as a result of setting the state
            // above).
            //
            OsrClearQueues(devExt);

            //
            // Removing the device at this point is NOT optional.
            //

            //
            // Detach from the PDO 
            //
            IoDetachDevice(devExt->DeviceToSendIrpsTo);

            targetDevice = devExt->DeviceToSendIrpsTo;

#if DBG
            devExt->DeviceToSendIrpsTo = NULL;

            devExt = NULL;
#endif

            //
            // Decrement our reference on the device here, and then
            // wait until we can remove the device.
            //
            OsrRequestDecrement(devExt);
        
#if DBG
            DbgPrint("OsrPnp: Waiting for pending requests to complete. %d. remain\n", devExt->OutstandingIO);
#endif

            OsrWaitForRemove(devExt);
            
            //
            // OK!  Now we can return our device object
            //
            IoDeleteDevice(devExt->FunctionalDeviceObject);

            //
            // Tell the underlying driver we're cool
            //
            Irp->IoStatus.Status = STATUS_SUCCESS;

            //
            // Pass this request on down to the bus driver
            //
            IoSkipCurrentIrpStackLocation(Irp);

            code = IoCallDriver(targetDevice, Irp);
            
            ASSERT(code != STATUS_PENDING);

            //
            // IMPORTANT: We decremented our I/O In Progress count
            // above... We don't want to decrement it again, so we
            // return right here.
            //
#if DBG
            DbgPrint("OsrPnp: Leaving with state: STATE_REMOVED");
#endif
            return(code);

            break;

        //
        // STATE:   STARTED
        // IRP_MN:  _QUERY_STOP_DEVICE
        //
        // We're here if we're running and the PnP Manager sends us
        // a QUERY_STOP_DEVICE request.  He'll do this if he wants to
        // rebalance resources, to see if we're willing to give up the
        // hardware resources that were allocated for us when we got
        // our IRP_MN_START_DEVICE.
        //
        // To proess this QUERY_STOP, we check to see if the stop is
        // acceptable to us (in this driver it always is), and then
        // we just transition the device to STOP_PENDING state.  In
        // this state, new requests that arrive are queued.  When a
        // currently in-progress request is completed, a new request
        // is NOT started.  Thus, ON OUR DEVICE, we sort of hope that
        // between the QUERY_STOP IRP arrive and actual STOP IRP arriving
        // that any in-progress I/O will complete of its own accord.
        // We like this scheme, particularly because at least on NT
        // during startup the device seems to get lots of QUERY_STOP
        // IRPs, that are just followed by CANCEL_STOP.  Thus, we think
        // it would be unfortunate to do anything radical with the
        // outstanding requests (like cancel them) when we receive a
        // QUERY_STOP.
        //
        case STATE_STARTED + IRP_MN_QUERY_STOP_DEVICE:

#if DBG
            DbgPrint("OsrPnp: PROCESSING QUERY_STOP_DEVICE\n");
#endif
            //
            // WE process this request before the BUS DRIVER
            //

            //
            // See if we're OK with stopping the device at this point.
            // We do NOT actually RETURN the resources here... we
            // just affirm or deny that we're OK with returning them.
            //
            code = OsrCanStopDevice(devExt, Irp);
            
            //
            // Replace status code that's in the IRP to indicate our
            // opinion about stopping the device.  If we're
            // OK with returning the resources, this will be
            // STATUS_SUCCESS.
            //
            Irp->IoStatus.Status = code;

            if(!NT_SUCCESS(code)) {

                //
                // NOPE.  Can't stop the device because, for some
                // reason (perhaps because we can't return our
                // resources).  Too bad. Tell the PnP Manager that
                // stopping right now is not an option for us.
                //
                // NOTE: NO NEED to pass IRP down if WE can't stop
                // it doesn't matter if the Bus Driver can.
                //
                IoCompleteRequest(Irp, IO_NO_INCREMENT);
                        
                
            } else {                    

                //
                // We CAN stop our device and return the resources.
                // Pass the IRP down to see if the bus driver is
                // equally ammenable to the request.
                //
#if DBG
                DbgPrint("OsrPnp: Agreeing to stop device.\n");
#endif

                //
                // Set new state. This state results in no new
                // requests being started on the device, but incoming
                // requests are still allowed and queued.
                //
                devExt->State = STATE_STOP_PENDING;

                //
                // Pass this request on down to the bus driver
                //
                IoSkipCurrentIrpStackLocation(Irp);

                code = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp);

            }
            break;

        //
        // STATE:   STOP_PENDING
        // IRP_MN:  _STOP_DEVICE
        //
        // We're in this state because we previously received a 
        // QUERY_STOP_DEVICE, that we agreed that we could grant.
        // Thus, we're waiting to receive a STOP_DEVICE request.
        // To process this request, we first wait for any in-progress
        // requests to complete (note that no NEW requests have been
        // started since the transition to STOP_PENDING state as a
        // result of receiving the QUERY_STOP IRP).  After all in-
        // progress requests are complete, we return our resources
        // and wait for further instructions from the PnP Manager (
        // which better include a START_DEVICE someplace down the line!).
        // 
        // While in this state, any IRPs we receive will be queued
        // for processing after we get the START_DEVICE.
        //
        case STATE_STOP_PENDING + IRP_MN_STOP_DEVICE:

#if DBG
            DbgPrint("OsrPnp: PROCESSING STOP_DEVICE\n");
#endif
            //
            // Assume success
            //
            devExt->State = STATE_STOPPED;
        
#if DBG
            DbgPrint("OsrPnp: Waiting for in-progress requests to complete\n");
#endif

            //
            // We process this request before passing it to the bus

⌨️ 快捷键说明

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