Como obter as informações de configuração e a localização de um dispositivo PCI

Traduções de Artigos Traduções de Artigos
Artigo: 253232 - Ver produtos para os quais este artigo se aplica.
Expandir tudo | Reduzir tudo

Sumário

Este artigo descreve como pode obter a configuração e informações de localização (como BusNumber DeviceNumber e número de função) de um dispositivo PCI (Peripheral Component Interconnect) num controlador que faz parte do controlador do dispositivo de destino como uma função na pilha ou controlador de filtro.

Mais Informação

No Windows NT 4.0, controladores de obter estas informações ao pesquisar o barramento e chamar as APIs HalGetBusDataByOffset e HalGetBusData. No Windows 2000 e sistemas operativos posteriores, os barramentos de hardware são controlados pelos respectivos controladores respectivos bus e não por HAL. Deste modo, todas as APIs de HAL utilizado para fornecer informações relacionadas com bus estão obsoletas no Windows 2000 e sistemas operativos posteriores.

No Windows 2000 e sistemas operativos posteriores, um controlador não é necessário consultar o dispositivo para localizar recursos. O controlador obtém os recursos do Gestor de Plug and Play (PnP) no respectivo pedido IRP_MN_START_DEVICE. Normalmente, um controlador consultar não requer nenhuma destas informações para funcionar correctamente. Se por alguma razão o controlador necessitar desta informação, o código de exemplo a seguir mostra como obter os recursos. O controlador deve fazer parte de pilha do controlador do dispositivo, porque requer os objectos de dispositivo físico subjacente (PDO) do dispositivo para enviar o pedido PnP.

O código de exemplo seguinte demonstra como obter as informações de configuração:
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;

}
				
uma vez que só pode enviar o PnP E/s pedido pacotes (IRPs) em PASSIVE_LEVEL, não é possível utilizar a função acima para obter as informações de configuração ao DISPATCH_LEVEL.

Pode efectuar os seguintes passos para aceder a no espaço de configuração na DISPATCH_LEVEL:
  1. Envie um IRP_MN_QUERY_INTERFACE cada PASSIVE_LEVEL para obter a estrutura de interface de chamada directo (BUS_INTERFACE_STANDARD) do controlador de barramento PCI. Armazene este numa memória paginável (normalmente em DevcieExtension).
  2. Chamar os SetBusData e GetBusData para aceder a no espaço de configuração na DISPATCH_LEVEL.
  3. O controlador de barramento PCI tem uma contagem de referência na interface antes de devolver, pelo que deve anular a referência a interface quando já não for necessário.
  4. Utilize a função seguinte para obter o BUS_INTERFACE_STANDARD ao 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;
    
    }
    					
O código seguinte mostra como pode utilizar a função de chamada directa de interface para obter os dados de barramento.
    bytes = busInterfaceStandard.GetBusData(<BR/>
                    busInterfaceStandard.Context,
                    PCI_WHICHSPACE_CONFIG,
                    Buffer
                    Offset,
                    Length);
				
quando já não necessitar da interface, utilize o seguinte código para anular a referência de interface com o código a seguir. Não chame rotinas qualquer interface depois de anular a referência da interface.
    (busInterfaceStandard.InterfaceDereference)(
                (PVOID)busInterfaceStandard.Context);
				
utilizar a função IoGetDeviceProperty no PDO do dispositivo de destino para obter os bus, função e dispositivos números da seguinte forma:
    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);

				
importante do bus PCI números podem ser dinâmicos e pode alterar qualquer momento. Por conseguinte, não é aconselhável dependem o número de barramento ou utilizar essas informações para aceder directamente as portas PCI. Isso pode provocar a falha do sistema.

Propriedades

Artigo: 253232 - Última revisão: 8 de setembro de 2005 - Revisão: 2.1
A informação contida neste artigo aplica-se a:
  • Microsoft Win32 Device Driver Kit para 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 Edition
  • Microsoft Windows Server 2003 Service Pack 1
Palavras-chave: 
kbmt kbhowto kbwdm KB253232 KbMtpt
Tradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine translation ou MT), não tendo sido portanto revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 253232

Submeter comentários

 

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