/*++

Copyright (c) 1993  Microsoft Corporation
Copyright (c) 1994  Digital Equipment Corporation

Module Name:

    pintolin.h

Abstract:

    This file includes the platform-dependent Pin To Line Tables

Author:

    Chao Chen    6-Sept 1994

Environment:

    Kernel mode

Revision History:


--*/

//
// These tables represent the mapping from slot number and interrupt pin
// into a PCI Interrupt Vector. 
//
// Formally, these mappings can be expressed as:
// 
//   PCIPinToLine: 
//     SlotNumber.DeviceNumber x InterruptPin -> InterruptLine 
//
//   LineToVector:
//     InterruptLine -> InterruptVector
// 
//   VectorToIRRBit:
//     InterruptVector -> InterruptRequestRegisterBit
//
//   VectorToIMRBit:
//     InterruptVector -> InterruptMaskRegisterBit
//
//   SlotNumberToIDSEL:
//     SlotNumber.DeviceNumber -> IDSEL
//
// subject to following invariants (predicates must always be true):
//
//   Slot.DeviceNumber in {0,...,15}
//
//   InterruptPin in {1, 2, 3, 4}
//
//   InterruptRequestRegisterBit in {0,...,15}
//
//   InterruptMaskRegisterBit in {0,...,15}
//
//   PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) = 
//         PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
//         (Table-lookup function initialized below)
//
//   LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
//
//   VectorToIRRBit(InterruptVector) = InterruptVector - 1
//
//   VectorToIMRBit(InterruptVector) [see below]
//
//   SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
//
// where:
// 
// SlotNumber.DeviceNumber:
//   Alpha AXP Platforms receive interrupts on local PCI buses only, which
//   are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[27]-AD[31]
//   since PCI Config space is a sparse space, requiring a five-bit shift.)
//
// InterruptPin:
//   Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
//   as per the PCI Spec. V2.0, Section 2.2.6.  (FYI, only multifunction devices
//   use INTB#, INTC#, INTD#.)   
//
//   PCI configuration space indicates which interrupt pin a device will use
//   in the InterruptPin register, which has the values:
//
//              INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
//   
//   Note that there may be up to 8 functions/device on a PCI multifunction
//   device plugged into the option slots, e.g., Slot #0.  
//   Each function has it's own PCI configuration space, addressed
//   by the SlotNumber.FunctionNumber field, and will identify which
//   interrput pin of the four it will use in it's own InterruptPin register.
//
//   If the option is a PCI-PCI bridge, interrupts across the bridge will
//   somehow be combined to appear on some combination of the four
//   interrupt pins that the bridge plugs into.
//
// InterruptLine:
//   This PCI Configuration register, unlike x86 PC's, is maintained by
//   software and represents offset into PCI interrupt vectors.
//   Whenever HalGetBusData or HalGetBusDataByOffset is called,
//   HalpPCIPinToLine() computes the correct InterruptLine register value
//   by using the HalpPCIPinToLineTable mapping.
//
// InterruptRequestRegisterBit:
//   0xff is used to mark an invalid IRR bit, hence an invalid request
//   for a vector.  Also, note that the 16 bits of the EB66 IRR must
//   be access as two 8-bit reads.
//
// InterruptMaskRegisterBit:
//   On EB66, the PinToLine table may also be find the to write the 
//   InterruptMaskRegister.  Formally, we can express this invariant as
//
//     VectorToIMRBit(InterrruptVector) = InterruptVector - 1
//
//
// IDSEL:
//   For accessing PCI configuration space on a local PCI bus (as opposed
//   to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
//   In this case, the IDSEL pin of the device to be accessed is tied to one
//   of the PCI Address lines AD[11] - AD[26].  (The function field in the 
//   PCI address is used should we be accessing a multifunction device.)
//   Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
//   so on.
//  

//
// Interrupt Vector Table Mapping for EB164.
//
// EB164 PCI interrupts are mapped to arbitrary interrupt numbers
// in the table below.  The values are a 1-1 map of the bit numbers 
// in the EB164 PCI interrupt register that are connected to PCI 
// devices.  N.B.: there are two other interrupts in this register, 
// but they are not connected to I/O devices,  so they're not 
// represented in the table.
//
// Limit init table to 14 entries, which is the
// MAX_PCI_LOCAL_DEVICES_MIKASA.
//
// We won't ever try to set an InterruptLine register of a slot
// greater than Virtual slot 13 = PCI_AD[24].
//

ULONG               *HalpPCIPinToLineTable;

ULONG               EB164PCIPinToLineTable[][4]=
{
//    Pin 1 Pin 2 Pin 3 Pin 4
//    ----- ----- ----- -----
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0  = PCI_AD[11]
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1  = PCI_AD[12]
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2  = PCI_AD[13]
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3  = PCI_AD[14]
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4  = PCI_AD[15]
    { 0x03, 0x08, 0x0c, 0x10 }, // Virtual Slot 5  = PCI_AD[16] PCI Slot 2
    { 0x01, 0x06, 0x0a, 0x0e }, // Virtual Slot 6  = PCI_AD[17] PCI Slot 0
    { 0x02, 0x07, 0x0b, 0x0f }, // Virtual Slot 7  = PCI_AD[18] PCI Slot 1
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8  = PCI_AD[19] PCI/ISA Bridge
    { 0x04, 0x09, 0x0d, 0x11 }, // Virtual Slot 9  = PCI_AD[20] PCI Slot 3
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21]
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 11 = PCI_AD[22]
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 12 = PCI_AD[23]
};

ULONG               AlphaPC164PCIPinToLineTable[][4]=
{
//    Pin 1 Pin 2 Pin 3 Pin 4
//    ----- ----- ----- -----
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0  = PCI_AD[11]
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1  = PCI_AD[12]
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2  = PCI_AD[13]
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3  = PCI_AD[14]
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4  = PCI_AD[15]
    { 0x03, 0x0a, 0x0e, 0x12 }, // Virtual Slot 5  = PCI_AD[16] PCI Slot 2
    { 0x01, 0x08, 0x0c, 0x10 }, // Virtual Slot 6  = PCI_AD[17] PCI Slot 0
    { 0x02, 0x09, 0x0d, 0x11 }, // Virtual Slot 7  = PCI_AD[18] PCI Slot 1
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8  = PCI_AD[19] PCI/ISA Bridge
    { 0x04, 0x0b, 0x0f, 0x13 }, // Virtual Slot 9  = PCI_AD[20] PCI Slot 3
    { 0x07, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21] USB
    { 0x06, 0xff, 0xff, 0xff }, // Virtual Slot 11 = PCI_AD[22] IDE
    { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 12 = PCI_AD[23]
};