bohezhou
驱动牛犊
驱动牛犊
  • 注册日期2005-01-08
  • 最后登录2007-06-14
  • 粉丝0
  • 关注0
  • 积分240分
  • 威望27点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
阅读:1656回复:2

紧急求助,wince x86下pci

楼主#
更多 发布于:2007-06-05 20:58

 我在wince x86 下写PCI2040的设备,现在设备可以找到,但按照下面的方法进行地址映射后,
 操作pci2040寄存器,读写结果不对,不知是不是和地址映射有关系,下面是相关的源码,麻烦斑竹看下。

struct PCI9054_INFO{
 INTERFACE_TYPE InterfaceType;
 ULONG BusNumber;
 PVOID pPci9054Address;//驱动可以访问的虚拟地址,对应着pci Memory Base Address0
 PVOID   pCtrlAddress;//驱动可以访问的虚拟地址,对应着pci Control Space Base Address
 DWORD MappedAddress;//ISR可以访问的静态虚拟地址

 HANDLE hIsrHandler;
    WCHAR   RegIsrDll[200];// ISR Dll name.
    WCHAR   RegIsrHandler[200];//ISR Handle Name.
 DWORD dwIrq;// IRQ field
    DWORD   dwSysIntr;// @field System Interrupt number for this peripheral
};//pPci9054Info;

__declspec(dllexport) BOOL FindPci9054(PUCHAR plx9054Address, PUCHAR pIrq)
{
    int                 bus=0, device, function;
    int                 length;
    BOOL                bFoundIt;
    ULONG               inIoSpace = 0;
// PUCHAR    pPci9054Address;
    PHYSICAL_ADDRESS    ioPhysicalBase;
    PCI_SLOT_NUMBER     slotNumber;
    PCI_COMMON_CONFIG   pciConfig;

    bFoundIt = FALSE;
 if(!pPci9054Info)//调试用
  pPci9054Info = (struct PCI9054_INFO *)malloc(sizeof(PCI9054_INFO));

 // Scan for the PCI9054
    for (bus = 0; bus < PCI_MAX_BUS; bus++) {
        for (device = 0; device < PCI_MAX_DEVICES; device++) {
            slotNumber.u.bits.DeviceNumber = device;

            for (function = 0; function < PCI_MAX_FUNCTION; function++) {
                slotNumber.u.bits.FunctionNumber = function;

                length = HalGetBusData(PCIConfiguration, bus, slotNumber.u.AsULONG, &pciConfig,
     sizeof(pciConfig) - sizeof(pciConfig.DeviceSpecific));

                if (length == 0 || pciConfig.VendorID == 0xFFFF)
                    break;

    // If the device is a typical PCI device, see if it is the one we're looking for
    if ((pciConfig.HeaderType == 0))
    {
                    RETAILMSG(1, (TEXT("Found a typical PCI device, VendorId: 0x%X, DeviceId: 0x%X\r\n"),
                                 pciConfig.VendorID, pciConfig.DeviceID));

                    RETAILMSG(1,
                             (TEXT("PCI device config: Irq = 0x%X, Port Base = 0x%X\r\n"),
                              pciConfig.u.type0.InterruptLine,
         pciConfig.u.type0.BaseAddresses[0]));
                
     // If vendor and device IDs match, we have found the PCI bridge we're looking for
     if ((pciConfig.VendorID == PCI9054_VENDOR_ID) &&
      (pciConfig.DeviceID == PCI9054_DEVICE_ID))
     {
      bFoundIt = TRUE;

      // Display all the base addresses
      ULONG index;

      for (index = 0; index < 2; index++)
       RETAILMSG(1, (TEXT("Base address %d = 0x%x\r\n"),
        index, pciConfig.u.type0.BaseAddresses[index]));
      break;
                    }
                }//if ((pciConfig.HeaderType == 0))

                if (function == 0 && !(pciConfig.HeaderType & 0x80))
                    break;
            }//for (function = 0; function < PCI_MAX_FUNCTION; function++)
            if (bFoundIt || length == 0)
                break;
        }//for (bus = 0; bus < PCI_MAX_BUS; bus++)
        if (bFoundIt || (length == 0 && device == 0))
            break;
    }

    if (!bFoundIt)
 {
        RETAILMSG(1, (TEXT("Find9054Hardware: Error, did not find PCI device\r\n")));
        return FALSE;
    }

 // We have found the bridge, now map the memory of the daughtercard and NET2890
// RETAILMSG(1, (TEXT("Find9054Hardware: pciConfig.u.type0.InterruptLine = 0x%x...\r\n"),
//  pciConfig.u.type0.InterruptLine));
    *pIrq = pciConfig.u.type0.InterruptLine;//

 // Now map address to the 9054
    ioPhysicalBase.HighPart = 0;
    ioPhysicalBase.LowPart = pciConfig.u.type0.BaseAddresses[PCI9054_BASE_ADDR_NUM];
 //负责将与总线相关的地址转化为物理地址(即系统地址)
 inIoSpace = 0;//AddressSpace 0x0 indicates memory, 0x1 is I/O space
 bus = 0;
 
 if (HalTranslateBusAddress(PCIBus, bus, ioPhysicalBase, &inIoSpace, &ioPhysicalBase))
 {
  RETAILMSG(1, (TEXT(" After  HalTranslateBusAddress:: Pci9054Address0.high = 0x%x,low=0x%x, inIoSpace=%d\r\n"),
   ioPhysicalBase.HighPart,ioPhysicalBase.LowPart, inIoSpace));
        if (!inIoSpace)
  {
   //负责将物理地址映射到驱动程序能够访问的虚拟地址空间中
            if ((pPci9054Info->pPci9054Address = (PUCHAR)MmMapIoSpace(ioPhysicalBase, PCI9054_REG_SPACE, FALSE)) == NULL)
   {
                RETAILMSG(1, (TEXT("FindPci9054Hardware: Error mapping 9054 I/O Ports.\r\n")));
                return FALSE;
            }
        }
  else
  {
            pPci9054Info->pPci9054Address = (PVOID) ioPhysicalBase.LowPart;
        }
    }
 else
 {
        RETAILMSG(1, (TEXT("FindPci9054Hardware: Error translating 9054 I/O Ports.\r\n")));
        return FALSE;
    }
 RETAILMSG(1, (TEXT(" Pci9054Address0 = 0x%x,\r\n"),pPci9054Info->pPci9054Address));

 // Now map address to the 9054
    ioPhysicalBase.HighPart = 0;
    ioPhysicalBase.LowPart = pciConfig.u.type0.BaseAddresses[PCI9054_BASE_ADDR_NUM+1];
 //负责将与总线相关的地址转化为物理地址(即系统地址)
 inIoSpace = 0;
 if (HalTranslateBusAddress(PCIBus, bus, ioPhysicalBase, &inIoSpace, &ioPhysicalBase))
 {
        if (!inIoSpace)
  {
   //负责将物理地址映射到驱动程序能够访问的虚拟地址空间中
            if ((pPci9054Info->pCtrlAddress = MmMapIoSpace(ioPhysicalBase, PCI9054_REG_SPACE, FALSE)) == NULL)
   {
                RETAILMSG(1, (TEXT("FindPci9054Hardware: Error mapping 9054 I/O Ports.\r\n")));
                return FALSE;
            }
        }
  else
  {
            pPci9054Info->pCtrlAddress = (PVOID) ioPhysicalBase.LowPart;
        }
    }
 else
 {
        RETAILMSG(1, (TEXT("FindPci9054Hardware: Error translating 9054 I/O Ports.\r\n")));
        return FALSE;
    }
 RETAILMSG(1, (TEXT(" Pci9054Address1 = 0x%x,\r\n"),pPci9054Info->pCtrlAddress));


 //OEMRequestSysIntr(*pIrq);
 if(!RequestSysIntr(*pIrq, &pPci9054Info->dwSysIntr))
 {
        RETAILMSG(1, (TEXT("FindPci9054Hardware: Error RequestSysIntr\r\n")));
        //return FALSE;
 }
 RETAILMSG(1, (TEXT("FindPci9054Hardware: Pci9054Address = 0x%x, IRQ = %d, SysIntr = %d\r\n"),
  pPci9054Info->pPci9054Address, *pIrq, pPci9054Info->dwSysIntr));

// WCHAR buf1[] = _T("PCIISR.dll");
// WCHAR buf2[] = _T("ISRHandler");
 WCHAR buf1[] = _T("giisr.dll");
 WCHAR buf2[] = _T("ISRHandler");
 wcscpy(&pPci9054Info->RegIsrDll[0], &buf1[0]);
 wcscpy(&pPci9054Info->RegIsrHandler[0], &buf2[0]);
 pPci9054Info->dwIrq = *pIrq;

 LoadISR(pPci9054Info, pciConfig);

 ConfigPci2040();
// hpi_reset();
 return TRUE;

}


BOOL LoadISR(struct PCI9054_INFO *pPci9054Info, PCI_COMMON_CONFIG pciConfig)
{
    PHYSICAL_ADDRESS    PhysicalAddress;
    unsigned long       dwAddressSpace;
    
    RETAILMSG(1, (TEXT("LoadISR::%s, %s, %d\r\n"),
        pPci9054Info->RegIsrDll, pPci9054Info->RegIsrHandler,pPci9054Info->dwIrq));
    //负责注册可安装的ISR
 pPci9054Info->hIsrHandler = LoadIntChainHandler(
                        pPci9054Info->RegIsrDll,
                        pPci9054Info->RegIsrHandler,
                        pPci9054Info->dwIrq);

    if (pPci9054Info->hIsrHandler == NULL)
    {
        RETAILMSG(1, (TEXT("LoadISR:: LoadIntChainHandler(%s, %s, %d) failed\r\n"),
            pPci9054Info->RegIsrDll, pPci9054Info->RegIsrHandler,pPci9054Info->dwIrq));
        RETAILMSG (1,(TEXT("LoadISR::failed, error code = %d\n\r"),GetLastError()));
        return FALSE;
    }                    

    //
    //  Translate the base address.
    //
    dwAddressSpace = 0x1;//0:in I/O space, 1: in memory space

 pPci9054Info->InterfaceType = PCIBus;
    PhysicalAddress.HighPart = 0x00;
    PhysicalAddress.LowPart  = pciConfig.u.type0.BaseAddresses[PCI9054_BASE_ADDR_NUM];
    //负责将物理地址映射到ISR能够访问的静态虚拟地址空间
 if (!TransBusAddrToStatic(
                pPci9054Info->InterfaceType,
                0,
                PhysicalAddress,    
                PCI9054_REG_SPACE,
                &dwAddressSpace,
                (PPVOID)&(pPci9054Info->MappedAddress)))
    {
        RETAILMSG(1, (TEXT("LoadISR::TransBusAddrToStatic Failed \r\n")));
        return FALSE;
    }
    RETAILMSG(1, (TEXT("LoadISR:: MappedAddress=0x%x\r\n"), pPci9054Info->MappedAddress));

    // Set up ISR handler
 GIISR_INFO Pci9054IsrInfo;
    Pci9054IsrInfo.SysIntr = pPci9054Info->dwSysIntr;
    Pci9054IsrInfo.CheckPort = TRUE;
    Pci9054IsrInfo.PortIsIO = FALSE;
    Pci9054IsrInfo.UseMaskReg = FALSE;
    Pci9054IsrInfo.PortAddr = pPci9054Info->MappedAddress + 0;//+offsetóD′y???y
    Pci9054IsrInfo.PortSize = sizeof(DWORD);
    Pci9054IsrInfo.Mask = 0;
 //This function is called from a driver to communicate with an interrupt handler

    if (!KernelLibIoControl(
            pPci9054Info->hIsrHandler,
            IOCTL_PCIISR_INFO,
            (LPVOID)(&Pci9054IsrInfo),
            sizeof(Pci9054IsrInfo),
            NULL,
            0x00,
            NULL))
    {  
        RETAILMSG(1, (TEXT("LoadISR:: Failed KernelLibIoControl\r\n")));
        return FALSE;
    }  
    
    RETAILMSG(1, (TEXT("LoadISR:: ok\r\n")));
    return true;

}

下面是程序执行时的一些打印语句:

Found a typical PCI device, VendorId: 0x104C, DeviceId: 0xAC60
PCI device config: Irq = 0x5, Port Base = 0xE8008000
Base address 0 = 0xe8008000
Base address 1 = 0xe8000000
 After  HalTranslateBusAddress:: Pci9054Address0.high = 0x0,low=0xe8008000, inIoSpace=0
 Pci9054Address0 = 0x60000,
 Pci9054Address1 = 0x70000,
RequestSysIntr(5) -> 18
FindPci9054Hardware: Pci9054Address = 0x60000, IRQ = 5, SysIntr = 18
LoadISR::giisr.dll, ISRHandler, 5
LoadISR:: MappedAddress=0xe8008000
LoadISR:: ok

说明:
Found a typical PCI device, VendorId: 0x104C, DeviceId: 0xAC60
PCI device config: Irq = 0x5, Port Base = 0xE8008000
Base address 0 = 0xe8008000
Base address 1 = 0xe8000000
这几句是说找到了pci2040设备,并得到了他的一些配置信息,中断号,总线地址。


After  HalTranslateBusAddress:: Pci9054Address0.high = 0x0,low=0xe8008000, inIoSpace=0
这句话是在HalTranslateBusAddress转换后打印的,是它的物理地址。

Pci9054Address0 = 0x60000,
 Pci9054Address1 = 0x70000
 这两句话是经过MmMapIoSpace映射后打印的,是驱动能够访问的虚拟地址,分别对应着pciConfig.u.type0.BaseAddresses[0]
 和pciConfig.u.type0.BaseAddresses[1].这个地址我总感觉不对,我觉得驱动能够访问的地址应该是在0x80000000以上。
 
 
 LoadISR:: MappedAddress=0xe8008000
 这句话是在经过TransBusAddrToStatic映射后打印的,是ISR能够访问的静态虚拟地址

薄荷的滋味
bohezhou
驱动牛犊
驱动牛犊
  • 注册日期2005-01-08
  • 最后登录2007-06-14
  • 粉丝0
  • 关注0
  • 积分240分
  • 威望27点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-06-07 20:03
找到问题了,映射得到的地址是以字为单位,而寄存器的偏移量却以字节为单位,所以才导致读写寄存器不对。
薄荷的滋味
bohezhou
驱动牛犊
驱动牛犊
  • 注册日期2005-01-08
  • 最后登录2007-06-14
  • 粉丝0
  • 关注0
  • 积分240分
  • 威望27点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-06-12 20:52
更正程序中的一些错误
dwAddressSpace = 0x0;//1:in I/O space, 0: in memory space

pPci9054Info->InterfaceType = PCIBus;
    PhysicalAddress.HighPart = 0x00;
    PhysicalAddress.LowPart  = pciConfig.u.type0.BaseAddresses[PCI9054_BASE_ADDR_NUM];
    //负责将物理地址映射到ISR能够访问的静态虚拟地址空间
busnum = 1;//通过扫描pci设备时得到的总线号

if (!TransBusAddrToStatic(
                pPci9054Info->InterfaceType,
                busnum ,
                PhysicalAddress,    
                PCI9054_REG_SPACE,
                &dwAddressSpace,
                (PPVOID)&(pPci9054Info->MappedAddress)))
    {
        RETAILMSG(1, (TEXT("LoadISR::TransBusAddrToStatic Failed \r\n")));
        return FALSE;
    }
    RETAILMSG(1, (TEXT("LoadISR:: MappedAddress=0x%x\r\n"), pPci9054Info->MappedAddress));

这样经过映射后得到的地址是:
LoadISR:: MappedAddress=0xc4008000
不知这个地址映射的对不对
薄荷的滋味
游客

返回顶部