/*
** VIPERMP.H (VIPERMP.PSD)
**
**
**  Change History
**
**  #81140 03/23/94 WHH     Wordpefect was unmasking IRQ 2 and we had coded
**                          and INT 3.
**
**/

#define PRIORITY_2ND_PIC_MASKED 0x67 // used to mask 2nd PIC IRQs   #81140
                                     // we write this to task reg.  #81140

#define STATE_43_WRITE         0x0001  // OK to write to control word
#define STATE_40_LSB_READ      0x0002
#define STATE_40_MSB_READ      0x0004
#define STATE_40_LSB_LM_READ   0x0008
#define STATE_40_MSB_LM_READ   0x0010
#define STATE_TIMER_LATCHED    0x0020
#define STATE_40_LSB_LM_WRITE  0x0040
#define STATE_40_MSB_LM_WRITE  0x0080
#define STATE_40_STATUS        0x0100


/*
 * APIC local timer defines
 */

#define APIC_TIMER_INIT_COUNT   439409
#define APIC_TIMER_CLOCK_FREQ   8000000
#define MAX_8254_INIT_COUNTER   65536
#define APIC_TIMER_VECTOR       0x98

#define APIC_TIMER_PERIODIC 0x00020000
#define APIC_TIMER_ONE_SHOT 0x00000000
#define APIC_TIMER_MASKED   0x00010000
#define APIC_TIMER_BASE_0   0x00000000
#define APIC_TIMER_BASE_1   0x00040000
#define APIC_TIMER_BASE_2   0x00080000

#define APIC_TIMER_ONE_SHOT 0x00000000

/*
 * APIC I/O structure.
 */

typedef struct apicio_s {
   ulong_t redir;
   ulong_t dest;              // Initialize this location first
   ulong_t irq;
} APICIO;

/*
 * CMOS
 */

#define CMOS_ADDR 0x70
#define CMOS_CTRL 0x0F
#define CMOS_DATA 0x71
#define CMOS_WARM 0x0B

/*
 * PLMA structure.
 */

typedef struct plma_s {
   ulong_t physical_procnum;  // Current physical processor number (0-based)
} PLMA;

/*
 * Generate delay between I/O instructions. // BUGBUG - SHOULD BE IMPORTED
 */

#define IODelay {int i; for(i = 0; i < IODelayCount; i++);}

/*
 * Miscelaneous defines.
 */

#define APIC_IO_ID_1             (0xff<<24)        // APIC I/O ID
#define BIOS_WARM_BOOT_OFFSET    ((0x40<<4)+0x67)  // 40:67
#define MAX_APIC_IO              16                // APIC I/O entries
#define MAX_EXT_IRQ              16                // External IRQ entries
#define PIC1_PORT1               0x21              // PIC1 OCW1 port
#define PIC2_PORT1               0xa1              // PIC2 OCW1 port
#define REDIR_BASE               0x10              // Redirection table base
#define RESET_VECTOR_OFFSET      ((0x40<<4)+0xd2)  // 40:d2
#define VERSION                  0x00000010

/*
 * IPI/spurious related.
 */

#define IPI_IRQ    0x1e             // IRQ level for IPIs
#define IPI_VECTOR 0xf0             // Vector number for IPIs

#define SPR_IRQ    0x1f             // IRQ level for spurious interrupts
#define SPR_VECTOR 0xff             // Vector number for spurious interrupts

/*
 * Determine if the interrupt is an IPI by checking the ISR bit.
 */

#define CHECKISRBIT(_LocalAPICMemory,_vector) \
        ( \
         *(_LocalAPICMemory + APIC_LOC_REG_ISR_31_00 + ((_vector / 32)<< 2)) \
          & \
         (1 << (_vector % 32)) \
        )

#define CHECKIRRBIT(_LocalAPICMemory,_vector) \
        ( \
         *(_LocalAPICMemory + APIC_LOC_REG_IRR_31_00 + ((_vector / 32)<< 2)) \
          & \
         (1 << (_vector % 32)) \
        )

#define CHECKISRBITREMOTE(_CPU,_vector) \
        ( RemoteRead( (APIC_LOC_REG_ISR_31_00 >> 2) + (_vector >> 5), _CPU )\
          & \
         (1 << (_vector % 32)) \
        )

#define CHECKIRRBITREMOTE(_CPU,_vector) \
        ( RemoteRead( (APIC_LOC_REG_IRR_31_00 >> 2) + (_vector >> 5), _CPU )\
          & \
         (1 << (_vector % 32)) \
        )

/*
 * To identify the HW as VIPERMP, the following data needs to be read from
 * the Chips and Technologies 4021/4025 chipset.
 */

#define CT4021_IO_PORT        0x22  // 4021 I/O address port
#define CT4021_IO_DATA        0x23  // 4021 I/O data port

#define CT4021_IO_DECODE_0    0x2b  // 4021 register address
#define CT4021_CS_1_ADDR      0x2c
#define CT4021_IO_DECODE_1    0x2f
#define CT4021_CS_ID          0xf0
#define CS_ID_MASK            0xfc  // Eliminate extraneous bits

#define VIPERMP_IO_DECODE_0   0x03  // Expected 4021 register values
#define VIPERMP_CS_1_ADDR     0x44
#define VIPERMP_IO_DECODE_1   0x93
#define VIPERMP_CS_ID         0x04

/*
 * The VIPERMP system exposes the following ports to retrieve MP-related
 * status information and configuration control.
 */

#define MP_STATUS_PORT        0x44  // VIPERMP status port
#define P1_ACTIVE             0x01  // Bit-field definitions
#define MP_CARD_PRESENT       0x80

#define MP_CONTROL_PORT       0x45  // VIPERMP control port
#define APIC_ENABLE           0x01  // Bit-field definitions
#define MP_ENABLE             0x04

/*
 * APIC related for the VIPERMP system.
 */

#define APIC_IO_PHYS_ADDR           0xFEC00000
#define APIC_IO_PHYS_ADDR_MAX       0xFEC003FF
#define APIC_IO_MEMORY_SIZE         0x1000

#define APIC_LOCAL_PHYS_ADDR        0xFEE00000
#define APIC_LOCAL_PHYS_ADDR_MAX    0xFEE003FF
#define APIC_LOCAL_MEMORY_SIZE      0x1000

/*
 * APIC I/O unit registers.
 *
 * These are DWORD OFFSETs to the DWORD registers.
 */

#define APIC_IO_REG_SELECT          (0x00 << 2)
#define APIC_IO_REG_WINDOW          (0x01 << 2)

#define APIC_IO_ID_REGISTER         0x00000000

/*
 * APIC I/O unit redirection table register bit-field definitions.
 */

#define APIC_REDIR_MASK_INTERRUPT   0x00010000  // Masked
#define APIC_REDIR_DELIVER_NMI      0x00000400  // Masked
#define APIC_REDIR_DELIVER_EXTINT   0x00000700  // ExtINT

/*
 * APIC local unit registers.
 *
 * These are DWORD OFFSETs to the DWORD registers.
 */

#define APIC_LOC_REG_UNIT_ID        (0x02 << 2)
#define APIC_LOC_REG_VERSION_ID     (0x03 << 2)
#define APIC_LOC_REG_TASK_PRI       (0x08 << 2)
#define APIC_LOC_REG_EOI            (0x0B << 2)
#define APIC_LOC_REG_REMOTE         (0x0C << 2)
#define APIC_LOC_REG_LOG_DEST       (0x0D << 2)
#define APIC_LOC_REG_DEST_FORMAT    (0x0E << 2)
#define APIC_LOC_REG_SPUR_VECTOR    (0x0F << 2)

#define APIC_LOC_REG_ISR_31_00      (0x10 << 2)
#define APIC_LOC_REG_ISR_63_32      (0x11 << 2)
#define APIC_LOC_REG_ISR_95_64      (0x12 << 2)
#define APIC_LOC_REG_ISR_127_96     (0x13 << 2)
#define APIC_LOC_REG_ISR_159_128    (0x14 << 2)
#define APIC_LOC_REG_ISR_191_160    (0x15 << 2)
#define APIC_LOC_REG_ISR_223_192    (0x16 << 2)
#define APIC_LOC_REG_ISR_255_224    (0x17 << 2)
#define APIC_LOC_REG_TMR_31_00      (0x18 << 2)
#define APIC_LOC_REG_TMR_63_32      (0x19 << 2)
#define APIC_LOC_REG_TMR_95_64      (0x1A << 2)
#define APIC_LOC_REG_TMR_127_96     (0x1B << 2)
#define APIC_LOC_REG_TMR_159_128    (0x1C << 2)
#define APIC_LOC_REG_TMR_191_160    (0x1D << 2)
#define APIC_LOC_REG_TMR_223_192    (0x1E << 2)
#define APIC_LOC_REG_TMR_255_224    (0x1F << 2)

#define APIC_LOC_REG_IRR_31_00      (0x20 << 2)
#define APIC_LOC_REG_IRR_63_32      (0x21 << 2)
#define APIC_LOC_REG_IRR_95_64      (0x22 << 2)
#define APIC_LOC_REG_IRR_127_96     (0x23 << 2)
#define APIC_LOC_REG_IRR_159_128    (0x24 << 2)
#define APIC_LOC_REG_IRR_191_160    (0x25 << 2)
#define APIC_LOC_REG_IRR_223_192    (0x26 << 2)
#define APIC_LOC_REG_IRR_255_224    (0x27 << 2)

#define APIC_LOC_REG_INTCMD_31_0    (0x30 << 2)
#define APIC_LOC_REG_INTCMD_63_32   (0x31 << 2)
#define APIC_LOC_REG_VECT_TMR       (0x32 << 2)
#define APIC_LOC_REG_VECT_INT0      (0x35 << 2)
#define APIC_LOC_REG_VECT_INT1      (0x36 << 2)
#define APIC_LOC_REG_INIT_COUNT     (0x38 << 2)
#define APIC_LOC_REG_CURR_COUNT     (0x39 << 2)
#define APIC_LOC_REG_DIVIDER        (0x3E << 2)

/*
 * APIC local unit register bit-field definitions.
 */

#define APIC_LOC_ENABLE             0x000000100

/*
 * Local APIC ICR register bit-field definitions.
 */

#define APIC_ICR_DEL_MODE_FIXED     0x000
#define APIC_ICR_DEL_MODE_LOWEST    0x100
#define APIC_ICR_DEL_MODE_REM_READ  0x300
#define APIC_ICR_DEL_MODE_NMI       0x400
#define APIC_ICR_DEL_MODE_RESET     0x500
#define APIC_ICR_DEL_MODE_EXTINT    0x700

#define APIC_ICR_DEST_MODE_PHYS     0x00000000
#define APIC_ICR_DEST_MODE_LOGIC    0x00000800

#define APIC_ICR_DEL_STATUS_IDLE    0x00000000  // No activity
#define APIC_ICR_DEL_STATUS_PEND    0x00001000  // Interrupt has been injected.

#define APIC_ICR_LEVEL_DEASSERT     0x00000000  // Deassert (Trigger = Level)
#define APIC_ICR_LEVEL_ASSERT       0x00004000  // Assert   (Trigger = Level)

#define APIC_ICR_TRIGGER_EDGE       0x00000000  // Edge
#define APIC_ICR_TRIGGER_LEVEL      0x00008000  // Level

#define APIC_ICR_REM_READ_INVALID   0x00000000  // Remote APIC unable to deliver.
#define APIC_ICR_REM_READ_IN_PROG   0x00010000  // RR is in progress.
#define APIC_ICR_REM_READ_VALID     0x00020000  // Most recent RR completed.
#define APIC_ICR_REM_READ_RSVD      0x00030000  // Reserved.

#define APIC_ICR_DEST_SH_DEST       0x00000000  // Dest field is used.
#define APIC_ICR_DEST_SH_SELF       0x00040000  // Dest is only self.
#define APIC_ICR_DEST_SH_ALL_SELF   0x00080000  // Dest is all, include self.
#define APIC_ICR_DEST_SH_ALL_NOSELF 0x000C0000  // Dest is all, exclude self.
