The Place to Start for Operating System Developers
It is currently Tue Aug 21, 2018 10:33 pm

All times are UTC - 6 hours

Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: ACPICA and PCI Interrupt Routing
PostPosted: Thu Aug 27, 2015 4:09 am 
User avatar

Joined: Sat Oct 16, 2010 3:38 pm
Posts: 577
I am in the process of porting ACPICA to my kernel (just a few things to fix). Its API is pretty confusing though, and I can't figure out how to read how the PCI interrupts (INTA#, etc) are wired on the system (I'm using the I/O APIC obviously).

I looked at the ACPI specification and it defines an AML object which specifies where the pins are connected but I do not understand how to read it using ACPICA.

Has anyone achieved this? And if so, what are the steps required to do so?

Glidix: An x86_64 POSIX-compliant operating system, aiming to be as optimized as possible, especially in graphics.

 Post subject: Re: ACPICA and PCI Interrupt Routing
PostPosted: Fri Aug 28, 2015 11:28 am 

Joined: Mon Apr 09, 2007 12:10 pm
Posts: 773
Location: London, UK
The process is essentially:

1) Initialize the namespace (\\_SB_._INI) followed by all devices whose _STA method reports they are present and/or functional.

2) Execute \\_PIC(1) to inform ACPI that you are using the IOAPIC (this is required otherwise it will probably give you the wrong IRQ routing tables).

3) Find the PCI root bridge (_HID = EisaId(PNP0A03))

4) Execute its _PRT method. This will return a Package object (which is ACPI-speak for an array) containing many other package objects. Iterate through each of them and the first entry is the PCI device number in the format (dev_num << 16) | 0xffff. The second is the PCI pin number (1 = INTA#, 2 = INTB#, 3 = INTC#, 4 = INTD#). You then need to match them up with what you found during PCI enumeration (e.g. if device 5 has the interrupt pin entry of its PCI configuration space being 3, you'd look for an entry in the _PRT response with the first item being 0x0005ffff and the second being 0x3). Look up the _PRT method in the spec for further info.

5) Once you've found the correct method, then examine the third entry of the _PRT response for that device:
5a) If it is an Integer with value Zero, then the 4th entry is an Integer whose value is the Global System Interrupt that device uses. Once you know this, you find which IOAPIC it points to and the pin on that IOAPIC. To do this, iterate through the MADT table looking for an IOAPIC with its gsibase field being less than and within 24 of the value you're looking for. Typically you have only one IOAPIC with gsibase being zero. Thus a GSI of 16 means pin 16 on IOAPIC 1.

5b) If it is a string, it is the name of another object in the namespace (a PCI IRQ Link object, e.g. \\_SB_\LNKA). You need to execute the _CRS method of this object to find out what interrupt it uses. You will want to read the spec to see the layout of the response. This will typically give you an ISA IRQ to use, and you will have to parse MADT again looking for InterruptSourceOverride structures that will convert this ISA IRQ to a GSI. If there is none, then GSI = ISA IRQ.

6) Choose a free interrupt vector in a particular CPU's IDT and program the handler into it.

7) Program the appropriate pin on the appropriate IOAPIC to route to the particular vector on the particular processor.


Tysos | rpi-boot | EFI tools

Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 6 hours

Who is online

Users browsing this forum: Google [Bot] and 9 guests

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group