c - 在 DOS 模式下实现消息信号中断

标签 c dos interrupt pci apic

我有点卡在编程设备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

  1. 我已经大致阅读了文档(第 10 章)http://download.intel.com/products/processor/manual/253668.pdf
  2. 我认为没有必要对 IO APIC 和本地 APIC 寄存器进行编程,因为 MSI 不会路由到 APIC 系统...!

当前状态:我发现系统在启用 MSIE = 1 后挂起并且设备通过 MSI 生成中断!

注意:在上面的序列中,服务例程没有安装,因为我不知道该怎么做...(这就是我的应用程序挂起的原因吗? )

谢谢!

[20120822 更新]Message Data 字段中的 vector 设置为 0x20 时,应用程序挂起...但是如果设置为 0x76,我发现应用程序没有挂起,然后我可以检查设备是否生成中断和本地 APIC 收到此中断消息如下:

  1. 对于 PCI 设备(AHCI Controller ):

    • ID(中断禁用)= 0
    • IS(中断状态)= 0
    • MSI 上限 = 09,FEE00000,00000076
  2. 对于 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是否启用

  1. 读取 CPU MSR 0x1B 并检查本地 APIC 全局启用/禁用位是否 = 1
  2. 读取本地 APIC 寄存器伪中断 vector 寄存器位 8(APIC SW 启用/禁用)=1

初始化MSI能力寄存器

  1. 配置消息控制寄存器(例如 MME...)
  2. 配置消息地址寄存器(例如目标 ID、DM 和 RH)
  3. 配置消息数据寄存器(例如触发模式、断言、传递模式和 vector )

安装自己的服务例程

  • 这取决于您使用的编译器/编程语言...
  • 以(Watcom C+Dos32a)为例,你可以在下面使用它来声明和安装服务例程
  • 使用 __interrupt __far 声明和创建 YourISR
  • 使用 DPMI 调用 0x204/0x205 获取(旧)和设置(新)中断 vector !

注释:

  1. 消息数据寄存器中的中断 vector 可以是Ex。 0x70,0x71,..., 或 0x76
  2. 在 ISR 结束和返回之前,请“写入”本地 APIC 寄存器(EOI)”,然后 LAPIC 将清除服务寄存器中的位,然后准备服务另一个中断!

启用设备通过 MSI 请求服务

  1. PCI 命令寄存器 bit10(ID) = 0
  2. 设备的中断允许位 = 1(特定于设备)
  3. 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

APIC

PCI Local Bus Specification v2.2

Access CPU MSR

DOS/32 Advanced

关于c - 在 DOS 模式下实现消息信号中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12050717/

相关文章:

java - 在Java中如何有理由地中断线程/ future /执行器?

c - C 中的数独求解器。程序在某些情况下停止,我不知道为什么

c - 数组和指针表示法

java - 在 Java 程序中在远程计算机上运行批处理文件

c - 加载exe文件并在dos中调用它们的函数

linux - softirq 和 tasklet 在哪个上下文中?

c - 如何使用 ***prof 之类的东西来查找哪个函数的计算复杂度最高?

c - 在c中使用ARM MCU保存数据

c# - C#中如何使用更多的DOS命令

java - 如果某个线程运行时间过长,我可以使用 executorservice 来终止它吗?