liuzhu800613
驱动牛犊
驱动牛犊
  • 注册日期2005-08-06
  • 最后登录2016-01-09
  • 粉丝2
  • 关注0
  • 积分1分
  • 威望39点
  • 贡献值0点
  • 好评度30点
  • 原创分0分
  • 专家分0分
阅读:4141回复:2

显卡I2C端口再讨论!

楼主#
更多 发布于:2008-04-16 15:30
以前有个帖子:如何利用显卡的VGA口上的I2C总线来传送数据。给了我很大的帮助,在此感谢那些提供宝贵意见的人们!我根据那个帖子给出的提示作了很长时间的研究,但是成效甚微。现在我能够找到显卡驱动中的I2C接口函数的指针:i2cOpen和i2cAccess。但是,这两个函数却不能使用,总是返回0xc00000c2这个硬件错误。我用的显卡是ATI RADEON 9200,操作系统是windows xp。下面是我的例子代码:
NTSTATUS
FindI2CInterfaceProvider(I2CINTERFACE * pI2CInterface)
{
    PWSTR pInterfaceList;
    PWSTR pInterfaceListWalk;
//    I2CINTERFACE * pI2CInterface;
    NTSTATUS status;
//
// Enumerate buses
    DbgPrint("FindI2CInterfaceOnDisplayDevice ....\n");
//
  

//    DbgPrint("IoGetDeviceInterfaces success!pInterfaceList=%d \n",0xffff & *pInterfaceList);
    
    pInterfaceListWalk = pInterfaceList;
//    pI2CInterface = ExAllocatePool(PagedPool, sizeof(I2CINTERFACE));
//    if (!pI2CInterface) {
//        DbgPrint("pI2CInterface can not be ExAllocatePool! \n");
//        return STATUS_INSUFFICIENT_RESOURCES;
//    }

    DbgPrint("pI2CInterface can  be ExAllocatePool success!\n");

    if(*pInterfaceListWalk != UNICODE_NULL) {
        PDEVICE_OBJECT pTargetDevice;
        UNICODE_STRING TargetDeviceName;
        PIRP pIrp;
        KEVENT Event;
        IO_STATUS_BLOCK Iosb;
        PIO_STACK_LOCATION pIrpSp;
        PFILE_OBJECT pFileObject;
//
// Create counted string version of
// target device name.
//
        RtlInitUnicodeString(&TargetDeviceName, pInterfaceList);
        KeInitializeEvent(&Event, NotificationEvent, FALSE);
//
// Get a pointer to its Device object
//
        status = IoGetDeviceObjectPointer(
                     &TargetDeviceName,
                     FILE_ALL_ACCESS,
                     &pFileObject,
                     &pTargetDevice);
        if (!NT_SUCCESS(status)) {
            DbgPrint("IoGetDeviceObjectPointer() failed!\n");
            return status;
        }
        DbgPrint("IoGetDeviceObjectPointer() success!\n ");
//
// Decrement reference count on unused
// File object
//
        ObDereferenceObject(pFileObject);
//        RtlZeroMemory(pI2CInterface, sizeof(I2CINTERFACE) );
        pIrp = IoAllocateIrp(pTargetDevice->StackSize, FALSE);

        if(pIrp == NULL)
        {
            DbgPrint("IoAllocateIrp can not allocate IRP!\n");
            return status;
        }

        pIrpSp = IoGetNextIrpStackLocation(pIrp);

        if(pIrpSp == NULL)
        {
            DbgPrint("IoGetNextIrpStackLocation can not allocate NextStack!\n");
            return status;
        }

        pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
        pIrpSp->MajorFunction = IRP_MJ_PNP;
        pIrpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;

        pIrpSp->Parameters.QueryInterface.InterfaceType = (struct _GUID *)&GUID_I2C_INTERFACE;
        pIrpSp->Parameters.QueryInterface.Size = sizeof(I2CINTERFACE);
        pIrpSp->Parameters.QueryInterface.Version = 1;
        pIrpSp->Parameters.QueryInterface.Interface = (PINTERFACE)pI2CInterface;
        pIrpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;


        IoSetCompletionRoutine(pIrp, SynchFunction, &Event, TRUE, TRUE, TRUE);
//
// Call SMB CMI driver to get segment/device information
//
        status = IoCallDriver(pTargetDevice, pIrp);
        if (status == STATUS_PENDING) {
// Wait for the IRP to be completed, then grab the real status code
            KeWaitForSingleObject(
                &Event,
                Executive,
                KernelMode,
                FALSE,
                NULL);
            status = pIrp->IoStatus.Status;
        }

        DbgPrint("IRP_MN_QUERY_INTERFACE has been send\n");

        if (NT_SUCCESS(status)) {

// we've got a device, so create a device object and save
// the slave address and lower device object pointer
// to the device extension

            DbgPrint("We have find one I2C Interface!\n");

            if((pI2CInterface->i2cOpen ==NULL) || (pI2CInterface->i2cAccess == NULL))
            {
               DbgPrint("I2c Interface can not be opened!\n");
            }
            else{
                DbgPrint("I2c Interface can  be opened!\n");

                g_pi2creference->m_pdoDriver = pTargetDevice;              //HERN :get device object of display adapter.
//                g_pi2creference->m_i2cProviderInterface = * pI2CInterface;
//                RtlCopyMemory(g_pi2creference->m_i2cProviderInterface,pI2CInterface,sizeof(I2CINTERFACE));


                g_pi2creference->m_ulI2CAccessClockRate = I2C_FIXED_CLOCK_RATE;

                DbgPrint("I2c Interface can  be copyed to g_pi2creference!\n");
            //    DbgPrint("I2c Interface g_pi2creference->m_ulI2CAccessClockRate = %d\n",g_pi2creference->m_ulI2CAccessClockRate);

            }
        } //
            
//        DbgPrint("status is %x\n",status);
        IoFreeIrp(pIrp);
//
        
// Advance to next interface string
//

//        pInterfaceListWalk += wcslen(pInterfaceListWalk) + 1;   //HERN we get first device only,and not mention the others.

    }
//    ExFreePool(pI2CInterface);
    ExFreePool(pInterfaceList);
    return status;
}

这部分代码可以成功找到显卡驱动导出的I2C函数借口指针,但是,I2C 函数却无法使用,总是返回错误代码0xc00000c2。我已经仔细研究过ddk中给出的这部分帮助文档。但是却找不到解决方法。我在网上看到有人遇到相同的问题。在此,恳请各位给与宝贵意见。
liuzhu800613
驱动牛犊
驱动牛犊
  • 注册日期2005-08-06
  • 最后登录2016-01-09
  • 粉丝2
  • 关注0
  • 积分1分
  • 威望39点
  • 贡献值0点
  • 好评度30点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-04-16 15:45
我知道我现在使用的显卡肯定支持 IRP_MN_QUERY_INTERFACE  GUID_I2C_INTERFACE。我不知道是不是xp 操作系统修改了这部分的要求,还是其他的原因。我也研究过现在网上的WinI2C-DDC,我发现,那个东东的编程思想是按照WinIo的思路作的。结合linux版本的I2C通信程序,可以实现windows 版本的I2C 通信程序。但是,我不明白为什么明确给出的接口为什么不能用。

我的联系方式:37279691(qq)
                   (msn): liuzhu800613@hotmail.com
                  email:liuzhu800613@126.com
                          
AllenZh
驱动老牛
驱动老牛
  • 注册日期2001-08-19
  • 最后登录2015-11-27
  • 粉丝19
  • 关注10
  • 积分1316分
  • 威望2387点
  • 贡献值7点
  • 好评度321点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-04-27 02:42
是的,你的思路是对的,可能是你没有处理好
WINI2C-DDC确实也是通过IO方式来实现的。
1,承接Windows下驱动/应用开发 2,本人原创虚拟鼠标/键盘,触摸屏,虚拟显卡,Mirror驱动,XP无盘的SCSI虚拟磁盘驱动等 3,windows下有尝技术服务(包括BUG调试,员工培训等) 欢迎深圳和海外企业联系.msn:mfczmh@sina.com
游客

返回顶部