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

Traduções deste artigo Traduções deste artigo
ID do artigo: 253232 - Exibir os produtos aos quais esse artigo se aplica.
Expandir tudo | Recolher tudo

Sumário

Este artigo descreve como você pode obter a configuração e informações de local (como BusNumber, DeviceNumber e número de função) de um dispositivo de interconexão de componentes periféricos (PCI) em um driver que faz parte do driver do dispositivo de destino como uma função de pilha ou driver de filtro.

Mais Informações

No Windows NT 4.0, drivers de obtém essa informação verificação o barramento e chamando as APIs HalGetBusDataByOffset e HalGetBusData. No Windows 2000 e posteriores sistemas operacionais do Windows, os barramentos de hardware são controlados por seus drivers respectivos barramento e não por HAL. Portanto, todas as APIs de HAL que usado para fornecer informações relacionadas ao barramento são obsoletas no Windows 2000 e posteriores sistemas operacionais do Windows.

No Windows 2000 e posteriores sistemas operacionais do Windows, um driver não é necessário para o dispositivo para localizar recursos de consulta. O driver obtém os recursos do Gerenciador de Plug and Play (PnP) na solicitação de IRP_MN_START_DEVICE. Normalmente, um driver bem escrito não requer qualquer um dessas informações para funcionar corretamente. Se por algum motivo o driver requer essas informações, o exemplo de código a seguir mostra como obter os recursos. O driver deve ser parte da pilha de driver do dispositivo porque ele requer os objetos de dispositivo físico subjacente (PDO) do dispositivo para enviar a solicitação PnP.

O exemplo de código a seguir 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;

}
				
porque você só pode enviar o PnP pacotes solicitação de E/s (IRPs) em PASSIVE_LEVEL, você não pode usar a função acima para obter as informações de configuração em DISPATCH_LEVEL.

Você pode executar as seguintes etapas para acessar o espaço de configuração em DISPATCH_LEVEL:
  1. Envie um IRP_MN_QUERY_INTERFACE PASSIVE_LEVEL para aproveitar a estrutura de interface de chamada direta (BUS_INTERFACE_STANDARD) o driver de barramento PCI. Armazene isso em uma memória de pool não-paginável (normalmente em DevcieExtension).
  2. Chamar o SetBusData e GetBusData para acessar o espaço de configuração em DISPATCH_LEVEL.
  3. O driver de barramento PCI leva uma contagem de referência na interface antes de retornar, portanto, você deve eliminar referência a interface quando não for necessário.
  4. Use a função seguinte para chegar a 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;
    
    }
    					
O código a seguir mostra como você pode usar a função de chamada direta de interface para obter os dados de barramento.
    bytes = busInterfaceStandard.GetBusData(<BR/>
                    busInterfaceStandard.Context,
                    PCI_WHICHSPACE_CONFIG,
                    Buffer
                    Offset,
                    Length);
				
quando você não precisa da interface, use o código a seguir para eliminar referência a interface com o código a seguir. Não chame quaisquer rotinas de interface depois de eliminar referência da interface.
    (busInterfaceStandard.InterfaceDereference)(
                (PVOID)busInterfaceStandard.Context);
				
use a função IoGetDeviceProperty PDO do dispositivo de destino para obter os números de barramento, função e dispositivos da seguinte maneira:
    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 PCI Bus números podem ser dinâmicos e pode alterar a qualquer momento. Portanto, não é bom dependem o número do barramento ou usar essas informações para acessar as portas PCI diretamente. Isso pode levar à falha do sistema.

Propriedades

ID do artigo: 253232 - Última revisão: quinta-feira, 8 de setembro de 2005 - Revisão: 2.1
A informação contida neste artigo aplica-se 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
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 traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes 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