Implement Message Signaled Interrupt in DOS mode

1.6k views Asked by At

I'm bit stuck at programming device MSI(Message Signaled interrupt) and any pointers welcomed...(my environment is Watcom C + DOS/32a - dos extender, in flat mode...)

@ PIC(8259) mode is ok for me...

I list what I have done as below and maybe someone can help to clarify these...Thanks !

(1) Multiple Message Enable = 0( for single MSI set this field = 0; MMC = 100b)

(2) For MSI message address register in the MSI capability

  • bit[31:20] = 0xFEE
  • bit[19:12] = 0 (Destination ID, and found Local APIC ID = 0...)
  • bit3 = 0 (Redirection hint = 0)
  • bit2 = 0 (Destination Mode, don't care because of RH = 0)

(3) For MSI message data register in the MSI capability

  • bit15 = 0 (trigger mode = edge)
  • bit14 = 0 (trigger level, ignored if trigger mode = edge)
  • bit[10:8] = 000 (delivery mode = fixed)
  • bit[7:0] = 0x20 (vector, and I choose to use 0x20)

(4) Finally enable MSI by setting MSICAP.MC.MSIE = 1

  1. I have roughly read the doc(chapter 10) http://download.intel.com/products/processor/manual/253668.pdf
  2. I think there is no need to program IO APIC and Local APIC registers because MSI does not route to APIC system...!

Current status: I found system hang after enabling MSIE = 1 and device generates interrupt via MSI !

Note: In above sequence the service routine is NOT installed because I have no idea how to do it...( is this the reason why my app hang ? )

Thanks !

[20120822 updated] When setting the vector in Message Data field to 0x20, app hang...But if set to 0x76, I found app did not hang and then I can check if device generates interrupt and Local APIC receives this interrupt message as below:

  1. For PCI device(AHCI controller):

    • ID(Interrupt Disable) = 0
    • IS(Interrupt Status) = 0
    • MSI Cap = 09,FEE00000,00000076
  2. For AHCI HBA registers:

    • PxIS = 00000023
    • PxIE = 7DC0007F
    • IS = 00000001
    • IE bit1 = 1

By 1 and 2 I think device successfully sends the message to request service because:

  • IS bit0 = 1(Port 0 has pending interrupt status)
  • IE(Interrupt Enable) = 1
  • PCI Command register bit10(ID) = 0
  • MSICAP.MC.MSIE = 1(to MSI engine)

Also I found the LAPIC receives this interrupt message because:

  • Local APIC IRR(Interrupt Request Register) bit118(=0x76) = 1
  • Local APIC ISR(In-Service register) bit118(=0x76) = 1

Thus it seems that device generates the interrupt and Local APIC receives this; even so, my service routine is NOT called !

1

There are 1 answers

0
liaoo On

To implement the MSI feature in DOS mode, you can reference below sequences:

Check if Local APIC is enabled

  1. Read CPU MSR 0x1B and check if Local APIC global enable/disable bit = 1
  2. Read Local APIC register Spurious Interrupt Vector Register bit8(APIC SW enable/disable)=1

Initialize MSI capability registers

  1. Configure Message Control register(Ex. MME...)
  2. Configure Message Address register(Ex. Destination ID, DM, and RH)
  3. Configure Message Data register(Ex. Trigger mode, Assert, Delivery mode, and vector)

Install your own service routine

  • It depends on what compiler/programming language you use...
  • Take (Watcom C+Dos32a) for example you can use below to declare and install service routine
  • Use __interrupt __far to declare and create YourISR
  • Use DPMI calls 0x204/0x205 to get(old) and set(new) interrupt vector !

Notes:

  1. The interrupt vector in Message Data register can be Ex. 0x70,0x71,..., or 0x76
  2. At the end of ISR and before return please "write" Local APIC register(EOI)" then LAPIC will clear the bit in In-Service Register and then ready to service another interrupt !

Enable device to request service via MSI by

  1. PCI Command register bit10(ID) = 0
  2. Device's Interrupt Enable bit = 1(device specific)
  3. MSICAP.MC.MSIE = 1 (interrupt routed to MSI engine)

You can check if device generates request and LAPIC receives this

  • Device will issue PCI DWORD write transaction to write 32bit data to 32bit memory address thus you can probe if this occur by LA, or you can check if (ID = 0 && Interrupt status !=0 && MSIE = 1)
  • Check LAPIC register IRR and ISR to see if request is received and serviced by LAPIC !

@ References:

Intel 64 and IA-32 Architectures Software Developer Manuals

APIC

PCI Local Bus Specification v2.2

Access CPU MSR

DOS/32 Advanced