根据device id找到一个机器上左右该id的设备的BAR

#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/io.h>

#define PCI_DEVICE              "/sys/bus/pci/devices"
#define PCI_DEVICE_SOMEONE      "/sys/bus/pci/devices/%s"
#define PCI_DEVICE_SOMEONE_RES  "/sys/bus/pci/devices/%s/resource"
#define RES_BAR3                "%*x%*x%*x\n%*x%*x%*x\n%*x%*x%*x\n%lx"
#define RES_BAR2                "%*x%*x%*x\n%*x%*x%*x\n%lx"

vector<uint64_t> m_Bar3PhyAddVec;
vector<void*>    m_Bar3VirAddVec;

vector<uint64_t> m_Bar2PhyAddVec;
vector<void*>    m_Bar2VirAddVec;


// Function to find the Base Address Register (BAR3) of a device with matching vendor and device IDs
int CanFwDownload::findBAR(uint32_t vendorID, uint32_t deviceID, int barX)
{
   DIR *dir;
   struct dirent *entry;
   char path[PATH_MAX];

   // Open the PCI devices directory
   dir = opendir(PCI_DEVICE);
   if (dir == NULL) {
      perror("Failed to open PCI devices directory");
      return -1;
   }

   // Iterate through each directory entry in the PCI devices directory
   while ((entry = readdir(dir)) != NULL) {
      if (entry->d_type == DT_LNK) {
         // Generate the path to the current device directory
         snprintf(path, sizeof(path), PCI_DEVICE_SOMEONE, entry->d_name);

         // Check if the current device matches the vendor and device IDs
         if (isMatchingDevice(path, vendorID, deviceID)) {
            // Generate the path to the device's BAR3 file
            snprintf(path, sizeof(path), PCI_DEVICE_SOMEONE_RES, entry->d_name);

            printf("dev name:%s\n",entry->d_name);

            // Open the device's BAR3 file
            FILE *file = fopen(path, "r");
            if (file == NULL) {
               perror("Failed to open resource file");
               continue;
            }
            if (barX == BAR3) {
               // Read the BAR3 value from the file
               uint64_t bar3 = 0;
               int n = fscanf(file, RES_BAR3, &bar3);//"%*x" is read and skip a hex value,"%\n" is read and skip a line break
               if (n != 1) {
                  perror("Can not get BAR3\n");
                  fclose(file);
                  return -1;
               }
               printf("vend id:0x%0x,deice id:0x%04x,Bar3:0x%lx,d_name:%s\n",vendorID,deviceID,bar3,entry->d_name);

               m_Bar3PhyAddVec.push_back(bar3);
            }
            if (barX == BAR2) {
               // Read the BAR3 value from the file
               uint64_t bar2 = 0;
               int n = fscanf(file, RES_BAR2, &bar2);//"%*x" is read and skip a hex value,"%\n" is read and skip a line break
               if (n != 1) {
                  perror("Can not get BAR2\n");
                  fclose(file);
                  return -1;
               }
               printf("vend id:0x%0x,deice id:0x%04x,Bar2:0x%lx\n",vendorID,deviceID,bar2);

               m_Bar2PhyAddVec.push_back(bar2);
            }
            fclose(file);
         }
      }
   }

   closedir(dir);

   return Success;
}

int CanFwDownload::mapVirtualAddr(vector<uint64_t> &barXPhyAddVec,vector<void*> &barXVirAddr,int barX)
{
   void *map_base, *virt_addr;
   unsigned page_size, mapped_size, offset_in_page;
   off_t target;
   unsigned width = 8 * sizeof(int);

   int fd = open("/dev/mem", (O_RDWR | O_SYNC),0666);
   if (fd < 0) {
      printf("Can't open /dev/mem\n");
      return fd;
   }

   page_size =  getpagesize();
   mapped_size = page_size;
   printf("---pageSize:%d\n",page_size);
   //mapped_size = MAP_SIZE;

   for (auto iter = barXPhyAddVec.begin();iter < barXPhyAddVec.end();++iter) {
      target = *iter;
      //target = barXPhyAddVec[0];
      offset_in_page = (unsigned)target & (page_size - 1);

      off_t off = target & ~(off_t)(page_size - 1);

      printf("=====offset_in_page:%u,PhtAddr:0x%0lx,offset:0x%0lx\n",offset_in_page,target,off);

      if (offset_in_page + width > page_size) {
		   /* This access spans pages.
		    * Must map two pages to make it possible: */
		   mapped_size *= 2;
	   }
      //map_base = mmap(NULL,mapped_size,(PROT_READ | PROT_WRITE),MAP_SHARED,fd,target & ~(off_t)(page_size - 1));
      //map_base = mmap(NULL, getpagesize() + 8192, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 1024 * 1024);
      if (barX == BAR3) {
         map_base = mmap(NULL, FLASH_MAP_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, target & ~(off_t)(page_size - 1));
      }else if (barX == BAR2) {
         map_base = mmap(NULL, page_size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, target & ~(off_t)(page_size - 1));
      }
      
      if (map_base == MAP_FAILED){
         printf("mmap failed.errno:0x%0x\n",errno);
         return -1;
      }

      virt_addr = (char*)map_base + offset_in_page;
      barXVirAddr.push_back(virt_addr);
   }

   return 0;
}


//FwDownload deviceID FwPath
int main(int argc, char* argv[])
{
    uint32_t devId = strtoul(argv[1],NULL,16);

   printf("devid:0x%04x\n",devId);


   int ret = findBAR(VENDOR_ID, devId, BAR3);
   if (ret != Success) {
      printf("findBAR3,Some error occured!\n");
      return ret;
   }

   ret = mapVirtualAddr(m_Bar3PhyAddVec,m_Bar3VirAddVec,BAR3);

   if (ret != Success) {
      printf("mapVirtualAddr bar3,Some error occured!,errno:0x%0x\n",errno);
      return ret;
   }


   ret = findBAR(VENDOR_ID, devId, BAR2);
   if (ret != Success) {
      printf("findBAR2,Some error occured!\n");
      return ret;
   }

   ret = mapVirtualAddr(m_Bar2PhyAddVec,m_Bar2VirAddVec,BAR2);

   if (ret != Success) {
      printf("mapVirtualAddr Bar2,Some error occured!,errno:0x%0x\n",errno);
      return ret;
   }


}

注意的知识点: 

机器上插了两张卡,①和②是不同地方打印的两张卡的BAR3地址,实际上是—样的,注意观察③的地址,实际上正好和①和②相同,也就是此种情况下,mmap函数映射物理地址到操作系统虚拟地址空间时,最后一个参数offset的地址,正好是两张卡各自BAR3的物理地址。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang_anna

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值