Plug and Play Driver Notification

The Configuration Manager (CONFIGMG.VXD) controls the creation, deletion, and resource allocation of the Device Nodes.

When a bus enumerator requests a new device node, the Configuration Manager locates the device ID of the device node in the system registry and loads the driver(s) using the registered device loader, if the necessary entries are present. After loading the device driver, the Configuration Manager sends a PnP_New_DevNode message to the driver's control procedure.

Note  If the new device node is the result of the "first insertion" event, the device node is setup during "appy-time." After successful installation of the device software, the Configuration Manager continues the startup sequence.

On receipt of the PnP_New_DevNode message, the device driver registers a "Config Handler" procedure with the multimedia device loader (MMDEVLDR.VXD), using the MMDEVLDR_Register_Device_Driver service. The Config Handler processes all subsequent CONFIG_ type messages from the Configuration Manager.

The Configuration Manager attempts to satisfy the resource requirements of the new device. If the device is a "floating" configuration, it may filter its logical configurations during the CONFIG_FILTER message processing. When the Configuration Manager can satisfy the resource requirements for the device node, it starts the device by sending a CONFIG_START message to the Config Handler.

A typical Config Handler processes the configuration state messages and applies the configuration by allocating resources such as IRQ virtualization, I/O trapping and memory space from the virtual machine manager (VMM).

The following procedure is a portion of the Config Handler used by MSMPU401.VXD. During the CONFIG_START message processing, the Config Handler queries the Configuration Manager for the allocated resources and then calls MSMPU401_Set_Config (an external private function defined by the specific device) to put the configuration into effect.

//---------------------------------------------------------------------
//  
// MSMPU401_Config_Handler
//  
//---------------------------------------------------------------------

CONFIGRET MSMPU401_Config_Handler
(
    CONFIGFUNC      cfFuncName,
    SUBCONFIGFUNC   scfSubFuncName,
    DEVNODE         dn,
    DWORD           dwRefData,
    ULONG           ulFlags
)
{
   // Switch the function (aka command)

   DPF( "MSMPU401: Config_Handler\r\n" ) ;

   switch (cfFuncName)
   {
      // In this code snippet, we've removed all function processing
      // except CONFIG_START, please see the DDK samples for the 
      // complete example.

      case CONFIG_START:
      {
         // This command is sent to instruct the driver that
         // it can start using the resources that have been
         // allocated to it. This is the meat of this
         // DriverConfigMan.
         //
         // We get our resource allocation by calling the
         // configuration manager (CM) using the devnode that
         // was passed to us.
         //
         // If all has gone well, we should not have been given
         // a resource allocation that we can't use. Ideally
         // this command should always succeed. However, every
         // now and then life throws you a curve ball, so we
         // should still verify that we are happy with the
         // resources we have been given.

         CMCONFIG    ccb ;
         CONFIGRET   cr ;
         WORD        wBaseMPU401 ;
         WORD        wIRQ ;

         // Get our resource allocation from CM. if
         // this fails, we have no choice but to fail
         // the CONFIG_START. We'll return the same
         // error that the CM_Get_Alloc_Config returned.

         if (CR_SUCCESS != 
               (cr = CM_Get_Alloc_Log_Conf( &ccb, dn, 0 )))
            return cr ;

         // Extract the information of interest from the config buffer
         // that we got from CM_Get_Alloc_Config.

         wBaseMPU401 = (WORD) -1 ;

         if (ccb.wNumIOPorts != 1)
         {
            DPF( "MSMPU401: Invalid config.\r\n" ) ;
            return CR_FAILURE ;
         }
                                 
         wBaseMPU401 = ccb.wIOPortBase[ 0 ] ;

         if (ccb.wNumIRQs)
            wIRQ = ccb.bIRQRegisters[ 0 ] ;
         else
            wIRQ = (WORD) -1 ;

         if (-1 == wBaseMPU401)
            return CR_FAILURE ;

         // OK, now do whatever else is necessary to put this
         // configuration into effect.

         cr = MSMPU401_Set_Config( dn, wBaseMPU401, wIRQ ) ;

         return cr ;
      }
   }
} // MSMPU401_Config_Handler()