วิธีการรับข้อมูลเกี่ยวกับการตั้งค่าคอนฟิกและตำแหน่งที่ตั้งของอุปกรณ์ PCI

การแปลบทความ การแปลบทความ
หมายเลขบทความ (Article ID): 253232 - ผลิตภัณฑ์ที่เกี่ยวข้องในบทความนี้
ขยายทั้งหมด | ยุบทั้งหมด

สรุป

บทความนี้อธิบายวิธีที่คุณสามารถรับการกำหนดค่า และสถานที่เก็บข้อมูล (เช่น BusNumber, DeviceNumber และหมาย เลขฟังก์ชัน) ของอุปกรณ์ต่อพ่วงคอมโพเนนต์ Interconnect (PCI) ในโปรแกรมควบคุมที่เป็นส่วนหนึ่งของโปรแกรมควบคุมของอุปกรณ์เป้าหมายการกองซ้อนใดเป็นฟังก์ชัน หรือกรองโปรแกรมควบคุม

ข้อมูลเพิ่มเติม

ใน Windows NT 4.0 ไดรเวอร์เรียกข้อมูลนี้ โดยการสแกนบัส และเรียก HalGetBusData และ APIs HalGetBusDataByOffset ใน Windows 2000 และระบบปฏิบัติการ Windows รุ่นที่ใหม่กว่า buses ฮาร์ดแวร์ถูกควบคุม โดยโปรแกรมควบคุมของบัสที่เกี่ยวข้อง และไม่ใช่ โดย HAL ดังนั้น APIs Hal ที่ใช้เพื่อให้ข้อมูลที่เกี่ยวข้องกับบัสทั้งหมดจะล้าสมัยใน Windows 2000 และระบบปฏิบัติการ Windows รุ่นที่ใหม่กว่า

ใน Windows 2000 และระบบปฏิบัติการ Windows รุ่นที่ใหม่กว่า ไดรเวอร์ไม่จำเป็นต้องสอบถามอุปกรณ์เพื่อค้นหาทรัพยากร โปรแกรมควบคุมที่ได้รับทรัพยากรจากตัวจัดการ Plug and Play (PnP) ในคำขอของ IRP_MN_START_DEVICE โดยทั่วไป ไดรเวอร์ well-written จะไม่ต้องการข้อมูลนี้ในการทำงานอย่างถูกต้อง ถ้ามีเหตุผลบางประการ โปรแกรมควบคุมที่ต้องใช้ข้อมูลนี้ ตัวอย่างของรหัสการทำตามแสดงวิธีการรับทรัพยากร โปรแกรมควบคุมควรเป็นส่วนหนึ่งของกองซ้อนของไดรเวอร์ของอุปกรณ์ได้เนื่องจากต้องวัตถุอุปกรณ์ทางกายภาพขีดเส้นใต้ (PDO) ของอุปกรณ์เพื่อส่งการร้องขอ PnP

ตัวอย่างรหัสต่อไปนี้อธิบายวิธีการขอรับข้อมูลการกำหนดค่า:
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;

}
				
เนื่องจากเฉพาะคุณสามารถส่งการ PnP I/O Request เก็ต (IRPs) ที่ PASSIVE_LEVEL คุณไม่สามารถใช้ฟังก์ชันที่ด้านบนเพื่อรับข้อมูลการกำหนดค่าที่ DISPATCH_LEVEL

คุณสามารถดำเนินการขั้นตอนต่อไปนี้ในการเข้าถึงพื้นที่การตั้งค่าคอนฟิกที่ DISPATCH_LEVEL:
  1. ส่งการ IRP_MN_QUERY_INTERFACE ที่ PASSIVE_LEVEL เพื่อเรียกดูโครงสร้างอินเทอร์เฟซการเรียกลโดยตรง (BUS_INTERFACE_STANDARD) จากโปรแกรมควบคุมของบัส PCI เก็บนี้ในหน่วยความจำของพูลโปรแกรม nonpaged (โดยทั่วไปใน DevcieExtension)
  2. เรียก SetBusData และ GetBusData เพื่อเข้าถึงพื้นที่การตั้งค่าคอนฟิกที่ DISPATCH_LEVEL
  3. โปรแกรมควบคุมของบัส PCI ใช้จำนวนการอ้างอิงบนอินเทอร์เฟซก่อนที่จะส่งกลับ เพื่อที่คุณต้อง dereference อินเทอร์เฟซได้เมื่อคุณไม่ต้องการ
  4. ใช้ฟังก์ชันต่อไปนี้เพื่อเรียกดูแบบ 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;
    
    }
    					
รหัสต่อไปนี้แสดงวิธีการที่คุณสามารถใช้ฟังก์ชันการเรียกลโดยตรงอินเทอร์เฟซการเรียกข้อมูลบัส
    bytes = busInterfaceStandard.GetBusData(<BR/>
                    busInterfaceStandard.Context,
                    PCI_WHICHSPACE_CONFIG,
                    Buffer
                    Offset,
                    Length);
				
เมื่อคุณไม่ต้องอินเทอร์เฟซ ใช้รหัสดังต่อไปนี้เพื่อ dereference อินเทอร์เฟซการ มีรหัสเป็นไปตาม ไม่เรียกตามปกติอินเทอร์เฟซใด ๆ หลังจากที่คุณ dereference อินเทอร์เฟซ
    (busInterfaceStandard.InterfaceDereference)(
                (PVOID)busInterfaceStandard.Context);
				
ใช้แบบIoGetDevicePropertyฟังก์ชันบน PDO อุปกรณ์เป้าหมายของการเรียกหมายเลขบัส ฟังก์ชัน และอุปกรณ์ต่อไปนี้:
    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);

				
สิ่งสำคัญหมายเลขบัส pci อาจเป็นแบบไดนามิก และสามารถเปลี่ยนแปลงในใด ๆ ดังนั้น มันไม่ได้ดีขึ้นอยู่กับหมายเลขบัส หรือใช้ข้อมูลนั้นในการเข้าถึงพอร์ตที่ PCI โดยตรง ซึ่งอาจนำล้มเหลวของระบบ

คุณสมบัติ

หมายเลขบทความ (Article ID): 253232 - รีวิวครั้งสุดท้าย: 8 มกราคม 2554 - Revision: 2.0
ใช้กับ
  • Microsoft Windows XP Driver Development Kit
  • Microsoft Windows 2000 Professional Edition
  • Microsoft Windows XP Home Edition
  • Microsoft Windows XP Professional Edition
  • Microsoft Windows Server 2003 Service Pack 1
Keywords: 
kbhowto kbwdm kbmt KB253232 KbMtth
แปลโดยคอมพิวเตอร์
ข้อมูลสำคัญ: บทความนี้แปลโดยซอฟต์แวร์การแปลด้วยคอมพิวเตอร์ของ Microsoft แทนที่จะเป็นนักแปลที่เป็นบุคคล Microsoft มีบทความที่แปลโดยนักแปลและบทความที่แปลด้วยคอมพิวเตอร์ เพื่อให้คุณสามารถเข้าถึงบทความทั้งหมดในฐานความรู้ของเรา ในภาษาของคุณเอง อย่างไรก็ตาม บทความที่แปลด้วยคอมพิวเตอร์นั้นอาจมีข้อบกพร่อง โดยอาจมีข้อผิดพลาดในคำศัพท์ รูปแบบการใช้ภาษาและไวยากรณ์ เช่นเดียวกับกรณีที่ชาวต่างชาติพูดผิดเมื่อพูดภาษาของคุณ Microsoft ไม่มีส่วนรับผิดชอบต่อความคลาดเคลื่อน ความผิดพลาดหรือความเสียหายที่เกิดจากการแปลเนื้อหาผิดพลาด หรือการใช้บทแปลของลูกค้า และ Microsoft มีการปรับปรุงซอฟต์แวร์การแปลด้วยคอมพิวเตอร์อยู่เป็นประจำ
ต่อไปนี้เป็นฉบับภาษาอังกฤษของบทความนี้:253232

ให้ข้อเสนอแนะ

 

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