1

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

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

我是否必须做其他事情来确认我对 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;
}

我希望有人能帮助我。

4

1 回答 1

3

“中断线”字段(在 PCI 配置空间中的偏移量 0x03C 处)实际上什么都不做。

完整的故事

PCI 卡在 PCI 插槽上最多可以使用 4 个“PCI IRQ”;并按顺序使用它们(因此,如果您有十张 PCI 卡都具有一个 IRQ,那么它们都将使用插槽中的第一个 PCI IRQ)。

有一个棘手的“理发店”安排将“插槽上的 PCI IRQ”连接到“主机控制器上的 PCI IRQ”,旨在减少 IRQ 共享。如果您有十张 PCI 卡都具有一个 IRQ,那么它们都将使用插槽上的第一个 PCI IRQ,但每个 PCI 插槽上的第一个 IRQ 将连接到主机控制器上的不同 PCI IRQ。所有这些都是硬连线的,无法通过软件更改。

使事情更复杂;为了将 PCI IRQ(来自 PCI 主机控制器)连接到传统 PIC 芯片,添加了一个特殊的“PCI IRQ 路由器”。理论上,“PCI IRQ 路由器”的配置可以通过软件更改(如果您可以找到描述“PCI IRQ 路由器”的位置、功能和限制的表格的文档)。

如果没有固件的帮助,操作系统就不可能确定 PCI 设备实际使用的 PIC 芯片输入。出于这个原因,固件在启动过程中会计算出来,然后将“PIC芯片输入编号”存储在某个地方供操作系统查找。这就是“中断线”寄存器的含义——它只是一个 8 位寄存器,可以存储您喜欢的任何内容(BIOS/固件用来存储“PIC 芯片输入编号”)。

于 2017-12-17T21:51:54.233 回答