holimion
驱动牛犊
驱动牛犊
  • 注册日期2008-08-14
  • 最后登录2008-10-13
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2304回复:2

如何访问PCI 配置空间

楼主#
更多 发布于:2008-08-14 14:25
我所知道的访问PCI配置空间的方法有这么几种:

1 DDK的API:HalSetBusDataByOffset 和 HalGetBusDataByOffset。这种方法不能访问4K的扩展空间,而且似乎有时候会失败

2 直接访问CF8、CFC的IO端口,这种方法在多核处理器下,非常容易出错导致蓝屏或死机(请问有没有办法加锁避免?)

3 MMIO的方法,基地址位置和CPU型号相关,而且某些BIOS没有正确映射。

我写的并不是一个正常的驱动程序,只是一个kernel service而已,为上层的应用程序提供访问硬件的权限。

请问有没有人有其他好的方法?
pillarlee
驱动牛犊
驱动牛犊
  • 注册日期2007-04-10
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分12分
  • 威望45点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-09-11 20:54
http://support.microsoft.com/kb/253232

刚好前两天我也遇到这问题,用的是下面的

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;

}
QQ:2091247
seanwan
驱动牛犊
驱动牛犊
  • 注册日期2007-08-20
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望96点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-09-14 14:22
引用楼主holimion于2008-08-14 14:25发表的 如何访问PCI 配置空间 :
3 MMIO的方法,基地址位置和CPU型号相关,而且某些BIOS没有正确映射
.......


BIOS没有正确映射的情况比较少见吧。基地址位置可以从ACPI拿到的。
游客

返回顶部