全部博文(120)
分类: LINUX
2008-05-03 10:43:22
This article describes the requirements for PCI IRQ routing on a multiprocessor Advanced Configuration and Power Interface (ACPI) system.
The purpose of this article is to describe what is required for PCI interrupt request (IRQ) routing on a multiprocessor (MP) ACPI machine. This article contains the following information:
• | A discussion of the parts of the ACPI specification that are relevant to MP; in particular the tables and ACPI Source Language (ASL) constructs necessary for implementing ACPI on MP machines. These consist of the following:
| ||||||
• | _PRT method. | ||||||
• | A list describing how to get an MP machine to run ACPI. | ||||||
• | An example of ASL from an IBM MP machine that is successfully running ACPI (provided courtesy of IBM Corporation). |
Caution: This article shows fragments of ASL code used as examples to illustrate various concepts. The examples used are taken primarily from working machines, but is has been necessary in cases to modify the code or to use hypothetical examples. Every effort has been made to present correct ASL code, but please note that the intent of these examples is to illustrate the concepts being discussed and that it will be necessary for you to tailor the ASL code to your specific machine. Please do not take these examples as representing ready-to-compile ASL, but as guides to help make your ASL coding easier.
Note: The Advanced Configuration and Power Interface Specification, Revision 1.0b replaces the Multiprocessor Specification, Version 1.4. The table information contained in the MP specification was carried over into the ACPI Specification where appropriate. However, please note that interrupt routing is now described in the ACPI namespace using ASL. The ACPI Specification can be obtained from . The MP Specification can be obtained from Intel at http://developer.intel.com (Intel part number: 242016-002).
This section describes the tables and ASL constructs needed to implement ACPI on MP machines.
The FADT defines the fixed ACPI information that is needed by the operating system as defined in section 5.2.5 of the ACPI specification. Currently, this table provides a field for INT_MODEL, which was intended to be used to report the interrupt mode of the machine. This field is ignored by the Microsoft Windows 2000 and later operating system because the Microsoft Windows 98 operating system only supports programmable interrupt controller (PIC) mode. This forces system manufacturers (OEMs) who want to support Windows 98 to enter a "0" in the INT_MODEL field. This would then preclude using multiple processors on Windows 2000 and later versions. Because the INT_MODEL field in the FADT cannot be dynamically updated while the machine is running, it cannot be used to report the interrupt mode, and therefore it is ignored by Windows 98, and Windows 2000 and later versions.
Include the _PIC(x) method if you want your MP machine to run with I/O Advanced Programmable Interrupt Controllers (APICs) turned on. This control method is used by Windows 2000 and later versions to report the current interrupt model to the BIOS. This control method returns nothing. The argument passed into the method signifies which interrupt model the operating system has chosen: PIC mode or APIC mode. Note that calling this method is optional for the operating system. If the method is never called, the BIOS should assume PIC mode. It is important that the BIOS save the value passed in by the operating system for later use.
_PIC(x) method and interrupt model mode chosen by the operating system:
_PIC(0) | PIC Mode |
_PIC(1) | APIC Mode |
_PIC(2-n) | Reserved |
Example: Name(\PICM, 0) // Initialize to 8259 mode Method(\_PIC,1) { Store(Arg0, \PICM) } // Control method _PIC
The FADT also contains the SCI_INT field. It reports which physical pin the system control interrupt (SCI) is wired to when the machine is in PIC mode. On most machines, the SCI interrupt is wired to IRQ 9 when the machine is in PIC mode. In APIC mode, SCI_INT is also used, but additional ISA vector override entries in the MAPIC table may be necessary. This will be explained in detail later in this article.
The following rules apply to the information provided in this article:
1. | INT_MODEL is no longer used by the operating system. |
2. | The _PIC method is now used to report to the BIOS the current interrupt mode. |
3. | SCI_INT provides the value of the SCI IRQ in PIC mode. |
The MAPIC table is the structure used by ACPI to describe the interrupt routing on a particular machine to the operating system. The MAPIC table is required for any machine using the APIC to route interrupts. The MAPIC table must have the following components:
A local APIC entry for each processor in the system, as described in section 5.2.8.1 of the ACPI specification.
The following is the format for the local APIC entry:
0 | Type= 0 | 8 bits | Processor Local APIC Structure (1 per CPU) |
1 | Length=8 | 8 bits |
|
2 | CPU_ID | 8 bits | Must match ID declared in namespace under _PR |
3 | Local APIC ID | 8 bits | For this CPU_ID |
4 | Flags | 32 bits | Flags.0=0 indicates this CPU is unusable |
An entry for each I/O APIC in the system, as described in section 5.2.8.2 of the ACPI specification.
The following is the format for the I/O APIC entry:
0 | Type=1 | 8 bits | I/O APIC Structure (1 Per I/O APIC) |
1 | Length=12 | 8 bits |
|
2 | I/O APIC ID | 8 bits | For this I/O APIC |
3 | Reserved | 8 bits |
|
4 | I/O APIC address | 32 bits | Memory address where this I/O APIC lives (flat) |
8 | System vector base | 32 bits | ACPI Plug and Play IRQ # number where this I/O APIC's INTI lines start |
One entry for each ISA vector override as necessary, as described in section 5.2.8.3.1 of the ACPI specification.
It
is assumed that the ISA interrupt vectors will usually be
identity-mapped into the first 16 I/O APIC sources. Most existing APIC
designs, however, will contain at least one exception to this
assumption. It is not necessary to provide an interrupt source override
for every ISA interrupt. It is only necessary to describe those that
are not identity-mapped onto the APIC interrupt space.
An example would be a machine that has the ISA Programmable Interrupt Timer (PIT) connected to ISA IRQ 0, but in APIC mode, it triggers I/O APIC source 2. In this case, you need an Interrupt Source Override where the source entry is "0" and the Global System Interrupt Vector is "2."
The ISA vector overrides are also necessary in cases in which the ISA interrupts vectors are identity mapped, but the polarity differs. The flags field in the entry allows you to specify this.
The following is the format for the interrupt source override field.
0 | Type=2 | 8 bits | Interrupt Source Override Structure | ||||||||||||||||
1 | Length=10 | 8 bits |
| ||||||||||||||||
2 | BUS=0 | 8 bits | ISA | ||||||||||||||||
3 | Source | 8 bits | Bus relative interrupt source (ISA IRQ #) | ||||||||||||||||
4 | Global system interrupt vector | 32 bits | ACPI Plug and Play IRQ # associated with the I/O APIC's INTI line | ||||||||||||||||
8 | Flags | 16 bits | Bit[15:4] - Reserved Bit[3:2] - Trigger mode of the I/O APIC input signals
Bit[1:0] - Polarity of the I/O APIC input signals:
|
Note: You must have an ISA vector override entry for the IRQ mapped to the SCI interrupt if this IRQ is not identity-mapped. This entry will override the value in SCI_INT in FADT. For example, if SCI is connected to IRQ 9 in PIC mode, and IRQ 9 is connected to INTIN11 in APIC mode, there should be a value of 9 entered in SCI_INT in the FADT and an ISA vector override entry mapping IRQ 9 to INTIN11.
An entry for nonmaskable interrupt (NMI).
This
structure allows a platform designer to stipulate which I/O APIC
sources should be enabled as nonmaskable. Any source that is
nonmaskable will not be available for use by devices. In effect, this
entry tells the operating system not to use the global system interrupt
vector described in the entry.
0 | Type = 3 | 8 bits | Nonmaskable I/O Interrupt Source Structure | ||||||||||||||||
1 | Length=8 | 8 bits |
| ||||||||||||||||
2 | Flags | 16 bits | Bit[15:4] - Reserved Bit[3:2] - Trigger mode of the I/O APIC input signals
Bit[1:0] - Polarity of the I/O APIC input signals:
| ||||||||||||||||
4 | Global system interrupt vector | 32 bits | ACPI Plug and Play IRQ # associated with the I/O APIC's INTI line |
Structure describing the connectivity of NMI to Local APIC INTI (LINTIN) pins.
This
structure describes which LINTIN pin is NMI-connected for each of the
processors in the system where such a connection exists. An entry is
needed for each NMI connection. This information is needed by the
operating system to enable the appropriate local APIC entry.
0 | Type = 4 | 8 bits | Local Nonmaskable Interrupt Structure | ||||||||||||||||
1 | Length=6 | 8 bits |
| ||||||||||||||||
2 | ACPI processor ID | 8 bits | Processor ID for which processor is listed in ACPI _PR object. (A value of 0xff signifies that this NMI source is connected to all the processors in the system.) | ||||||||||||||||
3 | Flags | 16 bits | Bit[15:4] - Reserved Bit[3:2] - Trigger mode of the I/O APIC input signals
Bit[1:0] - Polarity of the I/O APIC input signals:
| ||||||||||||||||
5 | Local APIC INTIN# | 8 bits | Identifies the LINTIN# pin to which the signal is connected (0 or 1) |
For example, if the platform has four processors with the ID 0-3, and NMI is connected LINTIN1 for processors 2 and 3, two entries would be needed in the MAPIC table.
For reasons that will become clear from the discussion below, the _PRT for an MP machine may be different in PIC mode than in APIC mode, based on how the PCI interrupts are routed on the machine. It is important to return the correct _PRT based on the interrupt model of the machine. You should use the variable set in the _PIC method to return the appropriate _PRT.
The following is true for the _PRT in PIC mode.
• | The interrupts are active low and level triggered. |
• | Each entry in the _PRT points to a link node. The link node is required for Windows 98.
|
A more detailed example of this is provided later in this article.
The following is true for the _PRT in APIC mode:
• | Interrupts
can be presented to the I/O APIC as active high or active low. Extended
interrupt descriptors (section 6.4.3.6 of the ACPI Specification) must be used to describe active high interrupts.
|
• | The _PRT entry can point to either a static source or a link node.
|
The following snippet of ASL shows an example of how bimodal _PRT can be implemented in a machine:
Name(\PICM,0)
Method(\_PIC,1) { Store(Arg0, \PICM) }
Device(PCI0) {
Name(_HID, EISAID("PNP0A03"))
Name(_ADR, 0x00000000)
Name(_CRS, ResourceTemplate () {(.)})
Method(_PRT) {
If (LEqual(\PICM, Zero) ) {
Return(
Package(
Package(){0x0010ffff, 0, \_SB.LNKB, 0}, // Device 10,Int A
Package(){0x0010ffff, 1, \_SB.LNKC, 0}, // Device 10,Int B
Package(){0x0011ffff, 1, \_SB.LNKD, 0}, // Device 11,Int B
Package(){0x0012ffff, 2, \_SB.LNKB, 0}, // Device 12,Int C
Package(){0x0012ffff, 3, \_SB.LNKC, 0}, // Device 12,Int D
} // end Package
) // end Return
} // end If
Return(
Package(){
Package(){0x0010ffff, 0, 0, 51}, // Slot 10 IntA
Package(){0x0010ffff, 1, IR1, 0}, // Slot 10 IntB
Package(){0x0011ffff, 1, 0, 51}, // Slot 11 IntB
Package(){0x0011ffff, 2, IR1, 0}, // Slot 11 IntC
Package(){0x0012ffff, 2, 0, 51}, // Slot 12 IntC
Package(){0x0012ffff, 3, IR1, 0} // Slot 12 IntD
}
)
} // end Method
Device(IR1) {
Name(_HID, EISAID("PNP0C0F"))
Name(_UID, 1)
Name(_PRS, ResourceTemplate() {
Interrupt (ResourceConsumer, ... ) (23,39,55) } )
Name(_DIS) { }
Name(_CRS) { }
Name(_SRS) { }
}
Device(LNKB) {
Name(_HID, EISAID("PNP0C0F"))
Name(_UID, 2)
Name(_PRS, ResourceTemplate() {
IRQ (Level, ActiveLow, Shared, , ... ) {5,7} } )
Name(_DIS) { }
Name(_CRS) { }
Name(_SRS) { }
}
Device(LNKC) {
Name(_HID, EISAID("PNP0C0F"))
Name(_UID, 2)
Name(_PRS, ResourceTemplate() {
IRQ (Level, ActiveLow, Shared, , ... ) {3,11} } )
Name(_DIS) { }
Name(_CRS) { }
Name(_SRS) { }
}
Device(LNKD) {
Name(_HID, EISAID("PNP0C0F"))
Name(_UID, 3)
Name(_PRS, ResourceTemplate() {
IRQ (Level, ActiveLow, Shared, , ... ) {8,15} } )
Name(_DIS) { }
Name(_CRS) { }
Name(_SRS) { }
}
Earlier sections of this article describe the sections of the ACPI Specification relevant to MP machines. This material should provide the background needed to implement the appropriate ASL and tables for an MP machine to run ACPI. The following section discusses some of the issues crucial to running ACPI successfully on an MP machine.
The first, and most important, step is to understand the hardware details of the machine in question. As stated earlier, the details of the interrupt routing on the machine must be clearly understood. Once you have this information, ask the following questions to ensure an MP machine is correctly running ACPI:
How is IRQ 0 connected in APIC mode? In most systems, IRQ 0 is not connected to INTIN0, but to INTIN2 on the I/O APIC. If this is the case, an ISA vector override must be added to the MAPIC table to describe the mapping of IRQ 0. If, however, IRQ 0 is connected to INTIN0, no action is necessary.
Is the real-time clock (RTC) IRQ (IRQ 8) active high? The active level of this signal must be examined at the input to the I/O APIC. That is, be sure to account for any inversions along the way to the I/O APIC. If the signal is active high, no action is necessary. If the signal is active low, an ISA vector override must be added to the MAPIC table to specify the polarity.
What interrupt does the SCI map to in APIC mode? If the polarity and the mapping of the IRQ for the SCI are the same in APIC mode as in PIC mode, no action is necessary. Otherwise, an ISA vector override must be added to the MAPIC table to provide this information to the operating system. Once again, be careful to note the polarity of the interrupt at the input to the I/O APIC.
Are the PCI interrupts active low at the I/O APIC?
Notice that in the following discussion, the _PRT refers to the APIC part of the _PRT described earlier in this article.
If the answer to this question is "yes" and if your interrupts are
statically routed, you can use the simple form _PRT, that is, one
without link nodes. The following example is a simple form entry taken
from the example given earlier in this article where interrupts are
statically routed:
Example: Simple form entry for statistically routed interrupts
Package(){0x0010ffff, 0, 0, 51}, // Slot 10 IntAOtherwise,
you must use a complex form _PRT with link nodes, with extended
interrupt descriptors required for the link nodes using the interrupt
macro, not the IRQ macro.
Notice that the preceding four issues represent only a few of the details that designers need to pay attention to. It is still necessary to implement all the MP-related ACPI structures described earlier in this article.
This section contains ASL excerpts that have been taken from a working MP machine running Windows 2000 with ACPI enabled. The ASL code is presented courtesy of IBM Corporation. Only the parts of the ASL that are relevant to the topics discussed in this article are reproduced. The code shown here has been compiled and IBM engineers have successfully run ACPI on Windows 2000 on this machine with more than one processor. Special thanks to IBM for making this code available for this article.
Note: In the following example, bimodal link nodes are used instead of bimodal _PRTs, that is, the link nodes use either standard interrupt descriptors (IRQ macro) or extended interrupt descriptors (Interrupt macro) based on the mode in which the machine is executing.
//
// This code snippet is provided for illustrative purposes only, in order to demonstrate
// how ACPI Methods may be used to support dynamically routable interrupts
//
Scope (\) {
. . .
Name (PICF , 0) // Global PIC Flag indicating PIC\APIC mode
. . .
Method ( _PIC,1) { // Set Global PIC/APIC flag
Store( Arg0 , PICF)
}
. . .
} // end of scope
Scope (\_SB.PCI0) {
Name(PRSP, // _PRS for PIC mode
ResourceTemplate() {
// IRQ descriptor, level, low
IRQ(Level, ActiveLow, Shared) {
5, 7, 10, 11, 14, 15 // Possible IRQs
}
}
)
Name(PRSA,
ResourceTemplate() { // _PRS for APIC Mode
// Extended IRQ descriptor. Necessary to indicate Level &
// Active High properties
Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) {
5, 7, 10, 11, 14, 15
}
}
)
// Typical PCI Interrupt Link Node:
Device(LK6A) { // PCI Slot 6 / INTA
Name(_HID, EISAID("PNP0C0F")) // PCI Interrupt Link Device
Name(_UID, 61)
Method(_STA, 0) {
If (LEqual (MX6A, 2)){ // 0010b indicates IMUX is disabled
Return(0x09) // Present, disabled, no UI
}
Else {
Return(0x0B) // Present, enabled, functioning
}
}
Method(_PRS,0) {
If (LNot (PICF)) { // Depending on whether we are
return(PRSP) // running in PIC or APIC mode
} Else { // select appropriate _PRS
return(PRSA)
}
}
Method(_DIS) { // We disable INT by writing 0010b
Store(2, MX6A) // to corresponding IMUX
}
Method(_CRS, 0) {
If (LNot (PICF)) {
Name( B6AP,
ResourceTemplate() {
IRQ(Level, ActiveLow, Shared, I6AP) {}
}
)
CreateWordField( B6AP, I6AP._INT, M6AP) //Interrupt Mask
If (LNotEqual(MX6A, 0x2)) {
Store( ShiftLeft(One, MX6A), M6AP)
}
Return(B6AP)
} Else {
Name( B6AA,
ResourceTemplate() {
Interrupt(ResourceConsumer,Level,ActiveHigh,Shared,,,I6AA) {0}
}
)
CreateByteField( B6AA, I6AA._INT, M6AA) //Interrupt Mask
If (LNotEqual(MX6A , 0x2)) {
Store(MX6A, M6AA)
}
Return(B6AA)
}
}
Method(_SRS, 1) {
If (LNot (PICF)) {
CreateWordField( Arg0, 0x01, P6A2 )
FindSetRightBit( P6A2, Local0)
Store( Decrement( Local0 ), MX6A )
TRIG( Local0) // Set Triggering
} Else {
CreateByteField( Arg0, 0x05, A6A2 )
Store( A6A2, MX6A)
TRIG(A6A2)
}
}
}
. . .
. . .
Device(LK5D) {
Name(_HID, EISAID("PNP0C0F"))
Name(_UID, 54)
Method(_STA, 0) {
If (LEqual (MX5D, 2)) {
Return(0x09) // Present, disabled, no UI
}
Else {
Return(0x0B) // Present, enabled, functioning
}
}
Method(_PRS,0) {
If (LNot (PICF)) {
return(PRSP)
} Else {
return(PRSA)
}
}
Method(_DIS) {
// 0010: no interrupt
Store(2, MX5D)
}
Method(_CRS, 0) {
If (LNot (PICF)) {
Name( B5DP,
ResourceTemplate() {
IRQ(Level, ActiveLow, Shared, I5DP) {}
}
)
CreateWordField( B5DP, I5DP._INT, M5DP) //Interrupt Mask
If (LNotEqual(MX5D , 0x2)) {
Store( ShiftLeft( One, MX5D), M5DP)
}
Return(B5DP)
} Else {
Name( B5DA,
ResourceTemplate() {
Interrupt(ResourceConsumer,Level,ActiveHigh,Shared,,,I5DA){0}
}
)
CreateByteField( B5DA, I5DA._INT, M5DA) //Interrupt Mask
If (LNotEqual(MX5D , 0x2)) {
Store(MX5D, M5DA)
}
Return(B5DA)
}
}
Method(_SRS, 1) {
If (LNot (PICF)) {
CreateWordField( Arg0, 0x01, P5D2 )
FindSetRightBit( P5D2, Local0)
Store( Decrement( Local0 ), MX5D )
TRIG( Local0) // Set Triggering
} Else {
CreateByteField( Arg0, 0x05, A5D2 )
Store( A5D2, MX5D)
TRIG(A5D2)
}
}
}
. . .
//
// The Triggering Imux is set up the following way:
//
// Offset written to
// Address Port 0xEA Writing to Data Port 0xEB
// Offset Controls triggering of:
// ----------------------+-----------------------------------------
// 10h bits 0-3 = IRQ 3 triggering
// bits 4-7 = IRQ 4 triggering
// 11h bits 0-3 = IRQ 5 triggering
// bits 4-7 = IRQ 7 triggering
// 12h bits 0-3 = IRQ 9 triggering
// bits 4-7 = IRQ 10 triggering
// 13h bits 0-3 = IRQ 11 triggering
// bits 4-7 = IRQ 12 triggering
// 14h bits 0-3 = IRQ 14 triggering
// bits 4-7 = IRQ 15 triggering
//
// A value of 0010b written to the Trig. Imux Data Port sets it's
// corresponding IRQ to Level, while the table below indicates the
// value necessary to set the IRQ to Edge
// Offset : Value for Edge
// 10h : 43h => IRQ 4 and 3
// 11h : 75h => IRQ 7 and 5
// 12h : A9h => IRQ 10 and 9
// 13h : CBh => IRQ 12 and 11
// 14h : FEh => IRQ 15 and 14
//
// At chipset initialization of the Imux, POST sets the values listed above
// which sets each of the corresponding IRQs to an ISA edge signal. During
// ACPI, Service Processor, and PCI IRQ assignment (which are all level
// signals) we change the corresponding nibble in Triggering Imux to a
// value of 2h which changes the corresponding Imux output to level.
//
// So, to change IRQ 5 and 7 to level, simply set its corresponding
// location in the Triggering Imux to a 2:
// 0xEA <- 0x11
// 0xEB <- 0x22
// To change a level IRQ 5 and 7 back to edge simply set the IRQ's
// corresponding location in Triggering
// Imux to the value of the interrupt:
// 0xEA <- 0x11
// 0xEB <- 0x75
//
Method(TRIG,1) {
If (LEqual (5, Arg0))
{Store(2, MT05)}
Else {If (LEqual (7, Arg0))
{Store(2, MT07)}
Else {If (LEqual (10, Arg0))
{Store(2,MT10)}
Else {If (LEqual (11, Arg0))
{Store(2,MT11)}
Else {If (LEqual (14, Arg0))
{Store(2,MT14)}
Else {If (LEqual (15, Arg0))
{Store(2,MT15)}
}
}
-
}
}
-
}
-
}
. . .
// These Interrupt Multiplexers (IMUXs) take the PCI interrupts from each
// slot and individually route each of them to a particular interrupt
// controller input
// We write an address in the IMUX address port (0xEA) to access a
// particular MUX. We then read/write the corresponding IMUX data port
// 0xEB) to access it's routing info.
//
// IMUX Address Port IMUX Data Port
// I/O Address 0xEA I/O Address 0xEB
// ----------------------+--------------------------------------------
// 00 Bits 0-3 = muxing of PCI Card Slot 6 IntA
// Bits 0-3 = muxing of PCI Card Slot 6 IntB
// 01 Bits 0-3 = muxing of PCI Card Slot 6 IntC
// Bits 0-3 = muxing of PCI Card Slot 6 IntD
//
// 02 Bits 0-3 = muxing of PCI Card Slot 5 IntA
// Bits 0-3 = muxing of PCI Card Slot 5 IntB
// 03 Bits 0-3 = muxing of PCI Card Slot 5 IntC
// Bits 0-3 = muxing of PCI Card Slot 5 IntD
. . .
// IMUX Data Bits Connected to Interrupt
// read/written to 0xEB
// -----------------------+---------------------------
// . . .
// 0010 NO INTERRUPT - DISCONNECT
// 0011 IRQ-3 (PIC) / INTIN3 (IOAPIC)
// 0100 IRQ-4 (PIC) / INTIN4 (IOAPIC)
// . . .
//
// PCI +------+ +-----+
// Device ->| IMUX +-+->| PIC +----+
// INT +------+ | +-----+ | +----+
// | +-->|CPUs|
// | +--------+ | +----+
// +->| IOAPIC |-+
// +--------+
//
//
// Define Interrupt IMUXs (in I/O Space)
// IMUX Address Port: 0xEA
// Data Port : 0xEB
//
OperationRegion(IMUX, SystemIO, 0xEA, 2)
Field(IMUX, ByteAcc, NoLock, Preserve) {
MXAD, 8,
MXDT, 8
}
IndexField(MXAD, MXDT, ByteAcc, NoLock, Preserve) { //
//
MX6A, 4, MX6B, 4, // EA: 00
MX6C, 4, MX6D, 4, // 01
MX5A, 4, MX5B, 4, // 02
MX5C, 4, MX5D, 4, // 03
MX4A, 4, MX4B, 4, // 04
MX4C, 4, MX4D, 4, // 05
. . .
, 4, , 4, // 0F
MT03, 4, MT04, 4, // MUX3: 10 - 14 controls int trigger
MT05, 4, MT07, 4, //
MT09, 4, MT10, 4, //
MT11, 4, MT12, 4, //
MT14, 4, MT15, 4 //
}
}
Scope (\_SB.PCI0){ // Primary PCI bus 0
Name(_PRT ,Package(){ // Single _PRT used for both PIC\APIC Mode
. . .
// Device#5 / AD16 / Slot#5:
Package() {0x0005ffff, 0, LK5A , 0} , // INT A
Package() {0x0005ffff, 1, LK5B , 0} , // INT B
Package() {0x0005ffff, 2, LK5C , 0} , // INT C
Package() {0x0005ffff, 3, LK5D , 0} , // INT D
// Device#6 / AD17 / Slot#6:
Package() {0x0006ffff, 0, LK6A , 0} , // INT A
Package() {0x0006ffff, 1, LK6B , 0} , // INT B
Package() {0x0006ffff, 2, LK6C , 0} , // INT C
Package() {0x0006ffff, 3, LK6D , 0} , // INT D
. . .
) //End _PRT
} // end of scope