/*
* Copyright (c) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @addtogroup ia32
* @{
*/
/** @file
*/
#ifndef KERN_ia32_APIC_H_
#define KERN_ia32_APIC_H_
#include <arch/types.h>
#include <cpu.h>
#define FIXED (0<<0)
#define LOPRI (1<<0)
#define APIC_ID_COUNT 16
/* local APIC macros */
#define IPI_INIT 0
#define IPI_STARTUP 0
/** Delivery modes. */
#define DELMOD_FIXED 0x0
#define DELMOD_LOWPRI 0x1
#define DELMOD_SMI 0x2
/* 0x3 reserved */
#define DELMOD_NMI 0x4
#define DELMOD_INIT 0x5
#define DELMOD_STARTUP 0x6
#define DELMOD_EXTINT 0x7
/** Destination modes. */
#define DESTMOD_PHYS 0x0
#define DESTMOD_LOGIC 0x1
/** Trigger Modes. */
#define TRIGMOD_EDGE 0x0
#define TRIGMOD_LEVEL 0x1
/** Levels. */
#define LEVEL_DEASSERT 0x0
#define LEVEL_ASSERT 0x1
/** Destination Shorthands. */
#define SHORTHAND_NONE 0x0
#define SHORTHAND_SELF 0x1
#define SHORTHAND_ALL_INCL 0x2
#define SHORTHAND_ALL_EXCL 0x3
/** Interrupt Input Pin Polarities. */
#define POLARITY_HIGH 0x0
#define POLARITY_LOW 0x1
/** Divide Values. (Bit 2 is always 0) */
#define DIVIDE_2 0x0
#define DIVIDE_4 0x1
#define DIVIDE_8 0x2
#define DIVIDE_16 0x3
#define DIVIDE_32 0x8
#define DIVIDE_64 0x9
#define DIVIDE_128 0xa
#define DIVIDE_1 0xb
/** Timer Modes. */
#define TIMER_ONESHOT 0x0
#define TIMER_PERIODIC 0x1
/** Delivery status. */
#define DELIVS_IDLE 0x0
#define DELIVS_PENDING 0x1
/** Destination masks. */
#define DEST_ALL 0xff
/** Dest format models. */
#define MODEL_FLAT 0xf
#define MODEL_CLUSTER 0x0
/** Interrupt Command Register. */
#define ICRlo (0x300 / sizeof(uint32_t))
#define ICRhi (0x310 / sizeof(uint32_t))
typedef struct {
union {
uint32_t lo;
struct {
uint8_t vector; /**< Interrupt Vector. */
unsigned delmod : 3; /**< Delivery Mode. */
unsigned destmod : 1; /**< Destination Mode. */
unsigned delivs : 1; /**< Delivery status (RO). */
unsigned : 1; /**< Reserved. */
unsigned level : 1; /**< Level. */
unsigned trigger_mode : 1; /**< Trigger Mode. */
unsigned : 2; /**< Reserved. */
unsigned shorthand : 2; /**< Destination Shorthand. */
unsigned : 12; /**< Reserved. */
} __attribute__ ((packed));
};
union {
uint32_t hi;
struct {
unsigned : 24; /**< Reserved. */
uint8_t dest; /**< Destination field. */
} __attribute__ ((packed));
};
} __attribute__ ((packed)) icr_t;
/* End Of Interrupt. */
#define EOI (0x0b0 / sizeof(uint32_t))
/** Error Status Register. */
#define ESR (0x280 / sizeof(uint32_t))
typedef union {
uint32_t value;
uint8_t err_bitmap;
struct {
unsigned send_checksum_error : 1;
unsigned receive_checksum_error : 1;
unsigned send_accept_error : 1;
unsigned receive_accept_error : 1;
unsigned : 1;
unsigned send_illegal_vector : 1;
unsigned received_illegal_vector : 1;
unsigned illegal_register_address : 1;
unsigned : 24;
} __attribute__ ((packed));
} esr_t;
/* Task Priority Register */
#define TPR (0x080 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
unsigned pri_sc : 4; /**< Task Priority Sub-Class. */
unsigned pri : 4; /**< Task Priority. */
} __attribute__ ((packed));
} tpr_t;
/** Spurious-Interrupt Vector Register. */
#define SVR (0x0f0 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
uint8_t vector; /**< Spurious Vector. */
unsigned lapic_enabled : 1; /**< APIC Software Enable/Disable. */
unsigned focus_checking : 1; /**< Focus Processor Checking. */
unsigned : 22; /**< Reserved. */
} __attribute__ ((packed));
} svr_t;
/** Time Divide Configuration Register. */
#define TDCR (0x3e0 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
unsigned div_value : 4; /**< Divide Value, bit 2 is always 0. */
unsigned : 28; /**< Reserved. */
} __attribute__ ((packed));
} tdcr_t;
/* Initial Count Register for Timer */
#define ICRT (0x380 / sizeof(uint32_t))
/* Current Count Register for Timer */
#define CCRT (0x390 / sizeof(uint32_t))
/** LVT Timer register. */
#define LVT_Tm (0x320 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
uint8_t vector; /**< Local Timer Interrupt vector. */
unsigned : 4; /**< Reserved. */
unsigned delivs : 1; /**< Delivery status (RO). */
unsigned : 3; /**< Reserved. */
unsigned masked : 1; /**< Interrupt Mask. */
unsigned mode : 1; /**< Timer Mode. */
unsigned : 14; /**< Reserved. */
} __attribute__ ((packed));
} lvt_tm_t;
/** LVT LINT registers. */
#define LVT_LINT0 (0x350 / sizeof(uint32_t))
#define LVT_LINT1 (0x360 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
uint8_t vector; /**< LINT Interrupt vector. */
unsigned delmod : 3; /**< Delivery Mode. */
unsigned : 1; /**< Reserved. */
unsigned delivs : 1; /**< Delivery status (RO). */
unsigned intpol : 1; /**< Interrupt Input Pin Polarity. */
unsigned irr : 1; /**< Remote IRR (RO). */
unsigned trigger_mode : 1; /**< Trigger Mode. */
unsigned masked : 1; /**< Interrupt Mask. */
unsigned : 15; /**< Reserved. */
} __attribute__ ((packed));
} lvt_lint_t;
/** LVT Error register. */
#define LVT_Err (0x370 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
uint8_t vector; /**< Local Timer Interrupt vector. */
unsigned : 4; /**< Reserved. */
unsigned delivs : 1; /**< Delivery status (RO). */
unsigned : 3; /**< Reserved. */
unsigned masked : 1; /**< Interrupt Mask. */
unsigned : 15; /**< Reserved. */
} __attribute__ ((packed));
} lvt_error_t;
/** Local APIC ID Register. */
#define L_APIC_ID (0x020 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
unsigned : 24; /**< Reserved. */
uint8_t apic_id; /**< Local APIC ID. */
} __attribute__ ((packed));
} l_apic_id_t;
/** Local APIC Version Register */
#define LAVR (0x030 / sizeof(uint32_t))
#define LAVR_Mask 0xff
#define is_local_apic(x) (((x) & LAVR_Mask & 0xf0) == 0x1)
#define is_82489DX_apic(x) ((((x) & LAVR_Mask & 0xf0) == 0x0))
#define is_local_xapic(x) (((x) & LAVR_Mask) == 0x14)
/** Logical Destination Register. */
#define LDR (0x0d0 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
unsigned : 24; /**< Reserved. */
uint8_t id; /**< Logical APIC ID. */
} __attribute__ ((packed));
} ldr_t;
/** Destination Format Register. */
#define DFR (0x0e0 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
unsigned : 28; /**< Reserved, all ones. */
unsigned model : 4; /**< Model. */
} __attribute__ ((packed));
} dfr_t;
/* IO APIC */
#define IOREGSEL (0x00 / sizeof(uint32_t))
#define IOWIN (0x10 / sizeof(uint32_t))
#define IOAPICID 0x00
#define IOAPICVER 0x01
#define IOAPICARB 0x02
#define IOREDTBL 0x10
/** I/O Register Select Register. */
typedef union {
uint32_t value;
struct {
uint8_t reg_addr; /**< APIC Register Address. */
unsigned : 24; /**< Reserved. */
} __attribute__ ((packed));
} io_regsel_t;
/** I/O Redirection Register. */
typedef struct io_redirection_reg {
union {
uint32_t lo;
struct {
uint8_t intvec; /**< Interrupt Vector. */
unsigned delmod : 3; /**< Delivery Mode. */
unsigned destmod : 1; /**< Destination mode. */
unsigned delivs : 1; /**< Delivery status (RO). */
unsigned intpol : 1; /**< Interrupt Input Pin Polarity. */
unsigned irr : 1; /**< Remote IRR (RO). */
unsigned trigger_mode : 1; /**< Trigger Mode. */
unsigned masked : 1; /**< Interrupt Mask. */
unsigned : 15; /**< Reserved. */
} __attribute__ ((packed));
};
union {
uint32_t hi;
struct {
unsigned : 24; /**< Reserved. */
uint8_t dest : 8; /**< Destination Field. */
} __attribute__ ((packed));
};
} __attribute__ ((packed)) io_redirection_reg_t;
/** IO APIC Identification Register. */
typedef union {
uint32_t value;
struct {
unsigned : 24; /**< Reserved. */
unsigned apic_id : 4; /**< IO APIC ID. */
unsigned : 4; /**< Reserved. */
} __attribute__ ((packed));
} io_apic_id_t;
extern volatile uint32_t *l_apic;
extern volatile uint32_t *io_apic;
extern uint32_t apic_id_mask;
extern void apic_init(void);
extern void l_apic_init(void);
extern void l_apic_eoi(void);
extern int l_apic_broadcast_custom_ipi(uint8_t vector);
extern int l_apic_send_init_ipi(uint8_t apicid);
extern void l_apic_debug(void);
extern uint8_t l_apic_id(void);
extern uint32_t io_apic_read(uint8_t address);
extern void io_apic_write(uint8_t address , uint32_t x);
extern void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t v, int flags);
extern void io_apic_disable_irqs(uint16_t irqmask);
extern void io_apic_enable_irqs(uint16_t irqmask);
#endif
/** @}
*/