PCI配置空间寄存器 - 写入值

时间:2017-12-17 18:51:14

标签: operating-system driver pci pci-bus network-driver

我正在为自制操作系统开发网络驱动程序(RTL8139),并且在向PCI配置空间寄存器写入值时遇到问题。

我想更改中断线(偏移量0x3c)的值以获取另一个IRQ编号并启用命令寄存器的总线主控(设置位2)(偏移量0x04)。
当我读回值时,我看到我的值被正确写入。但是它没有使用新的IRQ号码(在我的情况下为6),而是使用旧的值(11) DMA的总线主机也不工作(我想发送的数据包有正确的大小(由IO-Port设置)但它们没有内容(所有值都只有0,收发缓冲区在物理内存上并且没有零值)。在我仔细检查物理地址后,这总是与我的代码一致。我需要这个让网络控制器访问我的物理内存,我的缓冲区用于接收/收发。({{3 }})

我是否必须做其他事情来确认我对PCI设备的更改?

作为模拟器我使用qemu。

对于读/写,我写了以下函数:

uint16_t pci_read_word(uint16_t bus, uint16_t slot, uint16_t func, uint16_t offset)
{
 uint64_t address;
 uint64_t lbus = (uint64_t)bus;
 uint64_t lslot = (uint64_t)slot;
 uint64_t lfunc = (uint64_t)func;
 uint16_t tmp = 0;
 address = (uint64_t)((lbus << 16) | (lslot << 11) |
                   (lfunc << 8) | (offset & 0xfc) | ((uint32_t)0x80000000));
 outportl (0xCF8, address);
 tmp = (uint16_t)((inportl (0xCFC) >> ((offset & 2) * 8)) & 0xffff);
 return (tmp);
}

uint16_t pci_write_word(uint16_t bus, uint16_t slot, uint16_t func, uint16_t offset, uint16_t data)
{
 uint64_t address;
 uint64_t lbus = (uint64_t)bus;
 uint64_t lslot = (uint64_t)slot;
 uint64_t lfunc = (uint64_t)func;
 uint32_t tmp = 0;
 address = (uint64_t)((lbus << 16) | (lslot << 11) |
                   (lfunc << 8) | (offset & 0xfc) | ((uint32_t)0x80000000));
 outportl (0xCF8, address);
 tmp = (inportl (0xCFC));
 tmp &= ~(0xFFFF << ((offset & 0x2)*8)); // reset the word at the offset
 tmp |= data << ((offset & 0x2)*8); // write the data at the offset
 outportl (0xCF8, address); // set address again just to be sure
 outportl(0xCFC,tmp); // write data
 return pci_read_word(bus,slot,func,offset); // read back data;
}

我希望有人可以帮助我。

1 个答案:

答案 0 :(得分:1)

&#34;中断线&#34;字段(在PCI配置空间中偏移0x03C)字面上什么都不做。

完整故事

PCI卡最多可使用4个&#34; PCI IRQ&#34;在PCI插槽;并按顺序使用它们(所以如果你有10张PCI卡都有一个IRQ,那么它们都会在插槽中使用第一个PCI IRQ。)

这是一个棘手的理发杆&#34;安排在插槽中连接&#34; PCI IRQ&#34; to&#34;主控制器上的PCI IRQ&#34;旨在减少IRQ共享。如果您有10个PCI卡都有一个IRQ,那么它们都会在插槽中使用第一个PCI IRQ,但每个PCI插槽的第一个IRQ将连接到主机控制器上的不同PCI IRQ。所有这些都是硬接线的,无法通过软件进行更改。

使事情复杂化;连接PCI IRQ(从PCI主控制器)到传统PIC芯片,一个特殊的&#34; PCI IRQ路由器&#34;加入。从理论上讲,&#34; PCI IRQ路由器的配置&#34;可以通过软件进行更改(如果您可以找到描述表格的文档,该表格描述了&#34; PCI IRQ路由器的位置,功能和限制&#34;)。

如果没有固件的帮助,操作系统无法确定PCI设备实际使用的PIC芯片输入。出于这个原因,固件在启动时计算出来,然后存储&#34; PIC芯片输入编号&#34;操作系统找到的地方。这就是&#34;中断线&#34;寄存器是 - 它只是一个8位寄存器,可以存储您喜欢的任何内容(BIOS /固件用于存储&#34; PIC芯片输入编号&#34;)。