我正在爲Xilinx Virtex-6 X8 PCI Express Gen 2評估/開發套件SX315T FPGA編寫設備驅動程序。我的操作系統是openSUSE 11.3 64位。 在該設備的文檔(Virtex-6 FPGA集成塊形式PCI Express用戶指南UG517(v5.0)2010年4月19日,第219頁)中說:訪問內部Xilinx FPGA Block RAM
PIO設計是一個簡單的僅限目標的應用程序,與Endpoint的PCIe內核交易(TRN)接口連接,並作爲客戶構建自己設計的起點。在包括如下功能:
•四個使用內部的Xilinx FPGA的特定交易2 KB的目標區域框 RAM中,提供8192個字節的總目標空間
•支持單一DWORD有效載荷的讀取和寫入的PCI Express交易 32-/64位地址的存儲器空間和I /與完成的TLP支持
•利用核心的trn_rbar_hit_n O空間[6:0]信號TLP目的地之間進行區分 基地址寄存器
•提供針對32位,64位和128位TRN優化的單獨實施方案 接口
在設備中可用的BAR0和BAR2長度爲128字節。 我正嘗試訪問內部Xilinx FPGA Block RAM,以便在虛擬空間內核中映射BAR0。
struct pcie_dev {
struct pci_dev* dev;
struct cdev chr_dev;
atomic_t dev_available;
u32 IOBaseAddress;
u32 IOLastAddress;
void* __iomem bar;
void *virt_addr;
u32 length;
unsigned long sirqNum;
void *private_data; };
struct pcie_dev cur_pcie_dev;
cur_pcie_dev.IOBaseAddress = pci_resource_start(dev, 0);
cur_pcie_dev.IOLastAddress = pci_resource_end(dev, 0);
cur_pcie_dev.length=pci_resource_len(dev,0);
cur_pcie_dev.bar=pci_iomap(dev, 0,cur_pcie_dev.length);
CH365的是0xfbbfe000 IOLastAddress是0xfbbfe07f 長度= 128;
使用IOCTL我嘗試寫/讀數據。
case IOCTL_INFO_DEVICE:
{
u32 *rcslave_mem = (u32 *)pCur_dev->bar;
u32 result = 0;
u32 value = 0;
int i;
for (i = 0; i <2048 ; i++) {
printk(KERN_DEBUG "Writing 0x%08x to 0x%p.\n",
(u32)value, (void *)rcslave_mem + i);
iowrite32(value, rcslave_mem + i);
value++;
}
/* read-back loop */
value = 0;
for (i = 0; i < 2048; i++) {
result = ioread32(rcslave_mem + i);
printk(KERN_DEBUG "Wrote 0x%08x to 0x%p, but read back 0x%08x.\n",
(u32)value, (void *)rcslave_mem + i, (u32)result);
value++;
}
但事實證明,只能讀寫32個值。據我瞭解,記錄發生在BAR0(4字節* 32值= 128字節),但不在內部Xilinx內存中。我嘗試以其他方式。
cur_pcie_dev.IOBaseAddress = pci_resource_start(dev, 0);
cur_pcie_dev.IOLastAddress = pci_resource_end(dev, 0);
cur_pcie_dev.length=pci_resource_len(dev,0);
flags = pci_resource_flags(dev,0);
if (flags & IORESOURCE_MEM) {
if (request_mem_region(cur_pcie_dev.IOBaseAddress,cur_pcie_dev.length, DEVICE_NAME)== NULL) {
return -EBUSY;}
cur_pcie_dev.virt_addr=ioremap_nocache(cur_pcie_dev.IOBaseAddress,cur_pcie_dev.length);
if (cur_pcie_dev.virt_addr == NULL) {
printk(KERN_ERR "ERROR: BAR%u remapping FAILED\n",0);
return -ENOMEM;
}
printk(KERN_INFO " Allocated I/O memory range %#lx-%#lx\n", cur_pcie_dev.IOBaseAddress,(cur_pcie_dev.IOBaseAddress+cur_pcie_dev.length-1));
} else {
printk(KERN_ERR "ERROR: Invalid PCI region flags\n");
return -EIO;
}
然後
address = ((unsigned int)pCur_dev->virt_addr+pd.Address);
iowrite32(pd.Value,(unsigned int*) address);
address = ((unsigned int)pCur_dev->virt_addr+pd.Address);
pd.Value = ioread32((unsigned int *)address);
我使用求和虛擬地址和所述地址,其指定用戶。但結果是讀/寫操作也不正確。告訴我我做錯了什麼。
P.S.Sorry我的英文不好