我正在为自我制作的操作系统开发网络驱动程序(RTL8139),并在为PCI配置空间寄存器编写值时存在问题。
我想更改中断线(Offset 0x3c)的值以获取另一个IRQ号码,并启用命令寄存器的总线主(设置位2)(Offset 0x04)。
当我回复值时,我会发现我的值正确编写。但是,而不是使用新的IRQ号码(在我的情况6中)使用旧值(11)。
我必须做其他事情以确认我对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;
}
我希望有人可以帮助我。
"中断线"字段(在PCI配置空间中的Offset 0x03c)实际上无能为力。
全文
PCI卡最多可以在PCI插槽上使用4个" PCI IRQ";并使用它们(因此,如果您有十个PCI卡,所有的PCI卡都有一个IRQ,那么它们都将在插槽中使用第一个PCI IRQ)。
有一个棘手的"理发杆"布置,可以将"插槽的pci irq"连接到"主机控制器处的pci irq",旨在减少IRQ共享。如果您有10张PCI卡,它们都有一个IRQ,则它们都将在插槽上使用第一个PCI IRQ,但是每个PCI插槽的第一个IRQ将连接到主机控制器的其他PCI IRQ。所有这些都是坚硬的,无法通过软件更改。
使事情变得更复杂;为了将PCI IRQ(从PCI主机控制器)连接到旧版PIC芯片,添加了一种特殊的" PCI IRQ路由器"。从理论上讲,可以通过软件更改" PCI IRQ路由器"的配置(如果您可以找到描述描述" PCI IRQ路由器"位置,功能和限制的表格的文档。
)。 )。如果没有固件的帮助,则操作系统将不可能找出PCI设备实际使用的PIC芯片输入。因此,该固件在启动过程中将其弄清楚,然后将" PIC芯片输入号"存储在某个地方以供操作系统找到。这就是"中断线"寄存器的内容 - 它只是一个8位寄存器,可以存储您喜欢的任何东西(BIOS/固件用于存储" PIC芯片输入号码")。