Cómo obtener la información de configuración y ubicación de un dispositivo PCI

Seleccione idioma Seleccione idioma
Id. de artículo: 253232 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

Resumen

En este artículo se describe cómo puede obtener la configuración y información de ubicación (como BusNumber, DeviceNumber y número de función) de un dispositivo de interconexión de componentes periféricos (PCI) en un controlador que forma parte del controlador del dispositivo de destino como una función de la pila o controlador de filtro.

Más información

En Windows NT 4.0, controladores obtener esta información mediante la exploración del bus y llamar a la HalGetBusData y HalGetBusDataByOffset API. En Windows 2000 y sistemas operativos de Windows posteriores, los buses de hardware están controlados por sus controladores respectivos bus y no por HAL. Por lo tanto, todas las API de HAL que utiliza para proporcionar información relacionada con el bus están obsoletas en Windows 2000 y posterior del sistema operativo Windows.

En Windows 2000 y posteriores sistemas operativos de Windows, no es necesario un controlador consultar el dispositivo para buscar recursos. El controlador obtiene los recursos desde el Administrador de Plug and Play (PnP) en su solicitud puede iniciar (IRP_MN_START_DEVICE) correctamente. Normalmente, un controlador bien escrito no necesitaría esta información para funcionar correctamente. Si por alguna razón el controlador requiere esta información, siga el ejemplo de código muestra cómo obtener los recursos. El controlador debe ser parte de la pila del controlador del dispositivo porque requiere los objetos de dispositivo físico (PDO) subyacentes del dispositivo para enviar la solicitud PnP.

En el siguiente ejemplo de código muestra cómo obtener la información de configuración:
NTSTATUS
ReadWriteConfigSpace(
    IN PDEVICE_OBJECT DeviceObject,
    IN ULONG	      ReadOrWrite, // 0 for read 1 for write
    IN PVOID	      Buffer,
    IN ULONG	      Offset,
    IN ULONG	      Length
    )
{
    KEVENT event;
    NTSTATUS status;
    PIRP irp;
    IO_STATUS_BLOCK ioStatusBlock;
    PIO_STACK_LOCATION irpStack;
    PDEVICE_OBJECT targetObject;

    PAGED_CODE();

    KeInitializeEvent( &event, NotificationEvent, FALSE );

    targetObject = IoGetAttachedDeviceReference( DeviceObject );

    irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,
                                        targetObject,
                                        NULL,
                                        0,
                                        NULL,
                                        &event,
                                        &ioStatusBlock );

    if (irp == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto End;
    }

    irpStack = IoGetNextIrpStackLocation( irp );

    if (ReadOrWrite == 0) {
        irpStack->MinorFunction = IRP_MN_READ_CONFIG;
    }else {
        irpStack->MinorFunction = IRP_MN_WRITE_CONFIG;
    }

    irpStack->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG;
    irpStack->Parameters.ReadWriteConfig.Buffer = Buffer;
    irpStack->Parameters.ReadWriteConfig.Offset = Offset;
    irpStack->Parameters.ReadWriteConfig.Length = Length;

    // 
    // Initialize the status to error in case the bus driver does not 
    // set it correctly.
    // 

    irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;

    status = IoCallDriver( targetObject, irp );

    if (status == STATUS_PENDING) {

        KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
        status = ioStatusBlock.Status;
    }

End:
    // 
    // Done with reference
    // 
    ObDereferenceObject( targetObject );

    return status;

}
				
porque sólo puede enviar los paquetes de solicitud E/s PnP (IRP) en PASSIVE_LEVEL, no puede utilizar la función anterior para obtener la información de configuración en DISPATCH_LEVEL.

Puede realizar los pasos siguientes para tener acceso el espacio de configuración en DISPATCH_LEVEL:
  1. Enviar un IRP_MN_QUERY_INTERFACE en PASSIVE_LEVEL para obtener la estructura de interfaz de llamada directa (BUS_INTERFACE_STANDARD) desde el controlador de bus PCI. Almacenar este en una memoria de bloque no paginado (normalmente en DevcieExtension).
  2. Llamar a la SetBusData y GetBusData para tener acceso el espacio de configuración en DISPATCH_LEVEL.
  3. El controlador de bus PCI toma un recuento de referencia en la interfaz antes de devolver, por lo que deberá eliminar referencia la interfaz cuando ya no sea necesario.
  4. Utilice la función siguiente para obtener el BUS_INTERFACE_STANDARD PASSIVE_LEVEL:
    NTSTATUS
    GetPCIBusInterfaceStandard(
        IN  PDEVICE_OBJECT DeviceObject,
        OUT PBUS_INTERFACE_STANDARD	BusInterfaceStandard
        )
    /*++
    
    Routine Description:
    
        This routine gets the bus interface standard information from the PDO.
    
    Arguments:
    
        DeviceObject - Device object to query for this information.
    
        BusInterface - Supplies a pointer to the retrieved information.
    
    Return Value:
    
        NT status.
    
    --*/ 
    {
        KEVENT event;
        NTSTATUS status;
        PIRP irp;
        IO_STATUS_BLOCK ioStatusBlock;
        PIO_STACK_LOCATION irpStack;
        PDEVICE_OBJECT targetObject;
    
        Bus_KdPrint(("GetPciBusInterfaceStandard entered.\n"));
    
        KeInitializeEvent( &event, NotificationEvent, FALSE );
    
        targetObject = IoGetAttachedDeviceReference( DeviceObject );
    
        irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,
                                            targetObject,
                                            NULL,
                                            0,
                                            NULL,
                                            &event,
                                            &ioStatusBlock );
    
        if (irp == NULL) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            goto End;
        }
    
        irpStack = IoGetNextIrpStackLocation( irp );
        irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
        irpStack->Parameters.QueryInterface.InterfaceType = 
                            (LPGUID) &GUID_BUS_INTERFACE_STANDARD ;
        irpStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
        irpStack->Parameters.QueryInterface.Version = 1;
        irpStack->Parameters.QueryInterface.Interface = (PINTERFACE)
    BusInterfaceStandard;
        irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
    
        // 
        // Initialize the status to error in case the bus driver does not 
        // set it correctly.
        // 
    
        irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
    
        status = IoCallDriver( targetObject, irp );
    
        if (status == STATUS_PENDING) {
    
            KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
            status = ioStatusBlock.Status;
        }
    
    End:
        // 
        // Done with reference
        // 
        ObDereferenceObject( targetObject );
    
        return status;
    
    }
    					
El código siguiente muestra cómo puede utilizar la función de llamada directa de interfaz para obtener los datos de bus.
    bytes = busInterfaceStandard.GetBusData(<BR/>
                    busInterfaceStandard.Context,
                    PCI_WHICHSPACE_CONFIG,
                    Buffer
                    Offset,
                    Length);
				
cuando ya no necesite la interfaz, utilice el código siguiente para eliminar la interfaz con el código siguiente. No llame a las rutinas de interfaz después de eliminar la interfaz.
    (busInterfaceStandard.InterfaceDereference)(
                (PVOID)busInterfaceStandard.Context);
				
utilice la función IoGetDeviceProperty en el PDO del dispositivo de destino para obtener los números de bus, función y dispositivos como sigue:
    ULONG   propertyAddress, length;
    USHORT  FunctionNumber; DeviceNumber;
    
    // 
    // Get the BusNumber. Please read the warning to follow.
    // 

    IoGetDeviceProperty(PhysicalDeviceObject,
                        DevicePropertyBusNumber,
                        sizeof(ULONG),
                        (PVOID)&BusNumber,
                        &length);

    // 
    // Get the DevicePropertyAddress
    // 
    IoGetDeviceProperty(PhysicalDeviceObject,
                     DevicePropertyAddress,
                     sizeof(ULONG),
                     (PVOID)&propertyAddress,
                     &length);
    // 
    // For PCI, the DevicePropertyAddress has device number 
    // in the high word and the function number in the low word. 
    // 
    FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
    DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);

				
números de bus PCI importante puede ser dinámicos y puede cambiar en cualquier momento. Por lo tanto, no es conveniente dependen el número de bus o utilizar esa información para tener acceso a los puertos PCI directamente. Esto puede conducir a error del sistema.

Propiedades

Id. de artículo: 253232 - Última revisión: jueves, 8 de septiembre de 2005 - Versión: 2.1
La información de este artículo se refiere a:
  • Microsoft Win32 Device Driver Kit for Windows 2000
  • Microsoft Windows XP Driver Development Kit
  • Microsoft Windows Server 2003 Driver Development Kit (DDK)
  • Microsoft Windows 2000 Professional Edition
  • Microsoft Windows XP Home Edition
  • Microsoft Windows XP Professional
  • Microsoft Windows Server 2003 Service Pack 1
Palabras clave: 
kbmt kbhowto kbwdm KB253232 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 253232

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com