我有点卡在编程设备MSI(消息信号中断),欢迎任何指点...(我的环境是 Watcom C + DOS/32a - dos extender,在 < strong>扁平模式...)
@ PIC(8259) 模式对我来说没问题...
我在下面列出了我所做的事情,也许有人可以帮助澄清这些......谢谢!
(1) 多消息启用 = 0(对于单个 MSI 设置此字段 = 0;MMC = 100b)
(2)用于MSI能力中的MSI消息地址注册
- 位[31:20] = 0xFEE
- bit[19:12] = 0(目标 ID,发现本地 APIC ID = 0...)
- bit3 = 0(重定向提示 = 0)
- bit2 = 0(目标模式,因为 RH = 0 而不必关心)
(3)用于MSI能力中的MSI消息数据注册
- bit15 = 0(触发方式=边沿)
- bit14 = 0(触发电平,如果触发模式=边沿则忽略)
- bit[10:8] = 000(传送模式 = 固定)
- bit[7:0] = 0x20( vector ,我选择使用0x20)
(4) 最后通过设置 MSICAP.MC.MSIE = 1 启用 MSI
- 我已经大致阅读了文档(第 10 章)http://download.intel.com/products/processor/manual/253668.pdf
- 我认为没有必要对 IO APIC 和本地 APIC 寄存器进行编程,因为 MSI 不会路由到 APIC 系统...!
当前状态:我发现系统在启用 MSIE = 1 后挂起并且设备通过 MSI 生成中断!
注意:在上面的序列中,服务例程没有安装,因为我不知道该怎么做...(这就是我的应用程序挂起的原因吗? )
谢谢!
[20120822 更新] 将Message Data 字段中的 vector 设置为 0x20 时,应用程序挂起...但是如果设置为 0x76,我发现应用程序没有挂起,然后我可以检查设备是否生成中断和本地 APIC 收到此中断消息如下:
对于 PCI 设备(AHCI Controller ):
- ID(中断禁用)= 0
- IS(中断状态)= 0
- MSI 上限 = 09,FEE00000,00000076
对于 AHCI HBA 寄存器:
- PxIS = 00000023
- PxIE = 7DC0007F
- IS = 00000001
- IE 位 1 = 1
根据 1 和 2,我认为设备成功发送消息以请求服务,因为:
- IS bit0 = 1(Port 0 has pending interrupt status)
- IE(中断使能)= 1
- PCI 命令寄存器 bit10(ID) = 0
- MSICAP.MC.MSIE = 1(到 MSI 引擎)
我还发现 LAPIC 收到此中断消息是因为:
- 本地 APIC IRR(中断请求寄存器)bit118(=0x76) = 1
- 本地 APIC ISR(服务寄存器)bit118(=0x76) = 1
因此似乎设备产生了中断并且本地 APIC 接收到它;即便如此,我的服务例程没有被调用!
最佳答案
要在DOS模式下实现MSI功能,可以引用以下顺序:
检查本地APIC是否启用
- 读取 CPU MSR 0x1B 并检查本地 APIC 全局启用/禁用位是否 = 1
- 读取本地 APIC 寄存器伪中断 vector 寄存器位 8(APIC SW 启用/禁用)=1
初始化MSI能力寄存器
- 配置消息控制寄存器(例如 MME...)
- 配置消息地址寄存器(例如目标 ID、DM 和 RH)
- 配置消息数据寄存器(例如触发模式、断言、传递模式和 vector )
安装自己的服务例程
- 这取决于您使用的编译器/编程语言...
- 以(Watcom C+Dos32a)为例,你可以在下面使用它来声明和安装服务例程
- 使用 __interrupt __far 声明和创建 YourISR
- 使用 DPMI 调用 0x204/0x205 获取(旧)和设置(新)中断 vector !
注释:
- 消息数据寄存器中的中断 vector 可以是Ex。 0x70,0x71,..., 或 0x76
- 在 ISR 结束和返回之前,请“写入”本地 APIC 寄存器(EOI)”,然后 LAPIC 将清除服务寄存器中的位,然后准备服务另一个中断!
启用设备通过 MSI 请求服务
- PCI 命令寄存器 bit10(ID) = 0
- 设备的中断允许位 = 1(特定于设备)
- MSICAP.MC.MSIE = 1(中断路由到 MSI 引擎)
您可以检查设备是否生成请求以及 LAPIC 是否收到此请求
- 设备将发出 PCI DWORD 写入事务以将 32 位数据写入 32 位内存地址,因此您可以通过 LA 探测这是否发生,或者您可以检查是否 (ID = 0 && Interrupt status !=0 && MSIE = 1)<
- 检查 LAPIC 寄存器 IRR 和 ISR 以查看 LAPIC 是否收到请求并为其提供服务!
@引用:
Intel 64 and IA-32 Architectures Software Developer Manuals
关于c - 在 DOS 模式下实现消息信号中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12050717/