我正在编写一个设备驱动程序来访问PCIe卡上FPGA中的内存.
卡片启动并被探测/发现: -
的/ proc/IOMEM
80000000-840fffff : PCI Bus #03
80000000-83ffffff : 0000:03:00.0
84000000-840fffff : 0000:03:00.0
Run Code Online (Sandbox Code Playgroud)
所以,读LDD /等我编写了一个调用request_mem_region的80000000,并通过请求指向它的指针ioremap_nocache
1)我是否需要request_mem_region和a一样ioremap_nocache,我不能只使用后者?
/ proc/iomem insmod我的设备驱动程序后: -
80000000-840fffff : PCI Bus #03
80000000-83ffffff : 0000:03:00.0
80000000-8003ffff : fp2
84000000-840fffff : 0000:03:00.0
Run Code Online (Sandbox Code Playgroud)
2)对我来说看起来不太合适......?
无论如何,读取不起作用(它没有编码如下,它有检查等): -
#define BAR_ADDR 0x80000000
void *base = ioremap_nocache(BAR_ADDR, 0x40000);
void *address = base + KNOWN_REG_LOCATION;
int data = ioread32(address);
printk("fp2: address:0x%08x, data:0x%08x\n", address, data);
Run Code Online (Sandbox Code Playgroud)
产出: -
address:0xfd500000, data:0xffffffff
Run Code Online (Sandbox Code Playgroud)
我可以 …
我写这篇文章是因为我对DMA的行为有些怀疑.我正在阅读PCI布局以及设备驱动程序如何与卡交互,我读到了有关DMA的信息.由于我的理解,PCI卡没有DMA控制器,而不是他们要求成为总线的主控制器,然后他们能够获取DMA地址并在存储器和设备之间进行传输(通过总线).
这个DMA地址是RAM的一部分,实际上它是一个物理地址,在无所事事之前你需要将它转换成你的驱动程序可以使用的东西,比如内核虚拟内存.我用这段代码检查过:
/* Virtual kernel address */
kernel_buff = pci_alloc_consistent(dev, PAGE_SIZE, &dma_addr);
pr_info("Kernel buffer - %12p , Dma_addr - %12p\n", kernel_buff, (void *)dma_addr );
pr_info( "Kernelbuffer - dma_addr - %12p\n", kernel_buff - dma_addr);
strcpy(kernel_buff, "Test dma\n");
/* Test memory */
ptest = (void *)dma_addr;
ptest = phys_to_virt((unsigned long)ptest);
pr_info("Ptest virtual memory(%p) containts - %s\n", ptest, (char *)ptest);
Run Code Online (Sandbox Code Playgroud)
输出是:
[425971.835669] Kernel buffer - ffff8800ca70a000 , Dma_addr - ca70a000
[425971.835671] Kernelbuffer - dma_addr - ffff880000000000
[425971.835673] Ptest virtual memory(ffff8800ca70a000) containts - Test …Run Code Online (Sandbox Code Playgroud) 在几个资源中我发现: ROM 映像必须复制到 RAM 到 000C0000h 到 000DFFFFh。如果类代码表明这是 VGA 设备 ROM,则必须将其代码复制到从位置 000C0000h 开始的内存中。
1:如果我有PCI饥饿河马卡,ROM大于128KB怎么办?
2:如果我有 ROM 64KB 的常规 PCI 设备,但我有 4 个怎么办?它们是否按顺序加载到该内存范围中?如果是这样(尽管我对此表示怀疑),在 init 和 boot 阶段之间如何保存代码映像?
3:如果 BIOS 决定不遵循规范并指定不同的内存位置,会发生什么情况?为什么使用这个范围很重要?
4:普通机箱与VGA接口到底有什么不同?难道仅仅是限制造成了差异吗?
我有一个使用 UEFI 启动的小内核。我正在使用 QEMU 进行虚拟化。我想编写一个 xHCI 驱动程序来支持我的内核中的 USB 键盘。我很难找到简洁明了的信息。我在我的内核中“发现”了 xHCI。我有一个指向其 PCI 配置空间的指针。它支持 MSI-X。我想使用 MSI-X,但我无法理解它如何与 xHCI 和 USB 配合使用。
我的问题是,通常 osdev.org 提供的信息非常丰富,并且具有我需要实现某些功能的基础。就MSI-X而言,情况似乎并非如此。我很难将 osdev.org 上的所有信息与 MSI-X 功能联系起来。
基本上,我找到 MSI-X 表,然后在那里设置一些地址,告诉 xHCI PCI 设备写入该地址以触发中断。但是中断处理程序会在某个时刻被调用吗?我是否需要轮询该地址以确定是否发生中断?我本以为 MSI-X 表中的矢量控制字段可以让我设置中断矢量,但所有位都被保留。
编辑
我发现以下 stackoverflow 问答部分回答了我的问题:Question about Message Signaled Interrupts (MSI) on x86 LAPIC system。
所以基本上,数据寄存器的低字节包含要触发的向量,消息地址寄存器包含要触发的 LAPIC id。我还有一些问题。
为什么“消息地址寄存器包含固定顶部0xFEE”。
消息地址寄存器中的 RH、DM 和 XX 位是什么?
这如何与 LAPIC 配合使用?基本上,它是如何触发 LAPIC 中的中断的。这是 PCI 设备的一个特殊功能,允许它们在 LAPIC 中触发中断。或者只是 PCI 设备向 LAPIC 的内存映射寄存器写入一些触发中断的特定数据。因为通常 LAPIC 是从内核内部访问的,每个 LAPIC 的地址都相同。是来自 CPU 外部的某种处理器间中断吗?
我读过一些关于PCI和IDE/ATA的文章,现在有点糊涂了。PCI 类 0x01(大容量存储控制器)包含一个 IDE (0x01) 和一个 ATA (0x05) 子类。但是,从https://superuser.com/questions/341452/whats-the-difference-between-ata-pata-and-ide:
该标准被命名为 IBM PC/AT 的“AT 附件”(这意味着高级技术,但 ATA 不是高级技术附件)。但 IDE 和 ATA 是同义词。ATA 是一个更好的术语。
那么,如果它们相同,为什么它们有 2 个不同的子类?另外,在这篇文章中提到
两种类型的驱动器(SATA 和 PATA)都是 IDE 设备。
...但是当我在 oracle VM 中配置虚拟机时,有不同的:IDE、SATA 等...控制器。
此外,这篇文章:https : //sg.answers.yahoo.com/question/index?qid=20090723091840AA40xd6 说明 IDE 和 PCI 用于不同的连接,但我认为 ATA“控制器”已连接到 PCI公共汽车,这就是为什么我必须在那里检查它们。
它们是不同的...... PCI用于声卡视频卡等...... IDE用于CD ROMS硬盘驱动器软盘驱动器等......
在 VirtualBox 中,当我连接 IDE、软盘控制器、SCSI 或任何存储设备时,它会出现在 PCI 总线上,就像声卡和网卡一样。
我读的文章越多,我就越困惑。对它们进行一些清晰的描述会很好。
简单的问题,我正在阅读有关 PCI 的 OSDev Wiki 页面,它说了以下内容 -
“基地址寄存器(或 BAR)可用于保存设备使用的内存地址,或端口地址的偏移量。通常,内存地址 BAR 需要位于物理 RAM 中,而 I/O 空间 BAR 可以驻留在任何内存地址(甚至超出物理记忆)。”
我不明白哪里说内存地址 BAR 需要位于物理 RAM 中?MMIO 的全部意义在于,当它被分配一个内存地址时,它将被路由到设备而不是物理 RAM。它需要位于物理 RAM 中是什么意思?
难道它不只是 3GB - 4GB 地址空间之间的地址,无论安装了多少物理 RAM?
这是 OSDev 网站上的错误还是我误解了?
谢谢。
我正在做一个项目,要从pci配置空间读取设备的寄存器,为此,我需要映射空间,为此,我必须读取资源文件。但是该文件包含哪些数据。通过查看,它看起来可以保存某种地址。我搜索并阅读了这些是BAR的地方,但是最多只能有6个BAR,那么其他字段是什么?文件内容为:
0x000000000000fc00 0x000000000000fcff 0x0000000000020101
0x00000000dcff0000 0x00000000dcffffff 0x0000000000120204
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000dcf80000 0x00000000dcfbffff 0x0000000000120204
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000dc000000 0x00000000dc0fffff 0x0000000000027200
0x00000000dc500000 0x00000000dc5fffff 0x0000000000120204
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000dc100000 0x00000000dc4fffff 0x0000000000120204
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
Run Code Online (Sandbox Code Playgroud) 我对PCI有疑问.PCI有三个地址空间; PCI I/O,PCI内存和PCI配置空间.他们每个人身处何处?在PCI控制器?还是在设备中?它们中的任何一个都是系统RAM的一部分吗?
例如,当我使用带有CUDA C / C ++和GPUDirect 2.0 P2P的多GPU系统,并且使用嵌套的PCI-Express开关时,如图所示,那么我必须通过其PCI总线ID知道任意两个GPU之间有多少个开关,以优化数据的传输和分配计算。
或者,如果我已经知道具有PCIe开关的硬件PCIe拓扑,那么我必须知道,任何GPU卡都连接到板上的哪个硬件PCIe插槽。

据我所知,即使我已经知道带有PCIe交换机的硬件PCIe拓扑,这些标识符也不会硬绑定到板上的PCIe插槽,并且这些ID可能会发生变化,并且因系统运行而异:
在Windows和Linux上,通过详细的设备树和板上的PCIe插槽数量发现PCIe总线拓扑的最佳方法是什么?
我需要使用 C/C++(允许内联汇编)从 Linux 获取所有 PCI 总线设备的供应商 ID 和设备 ID,但我什至不明白从哪里开始。
请给我一些建议或代码部分。