/*
 * hal_apic.h - APIC values (for LAPIC and IOAPIC)
 *
 * Copyright (c) 2017 Maxime Villard
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef x86_ASM
char hal_com_read();
void hal_com_send(uint8_t chan, char c);
void hal_com_init_early();

void hal_ioapic_bind_irq(uint8_t irq, uint8_t vec, uint8_t dest);
void hal_ioapic_enable_irq(uint8_t irq);
void hal_ioapic_disable_irq(uint8_t irq);

void hal_ioapic_disable_entry(uint8_t irq);
void hal_ioapic_set_entry(uint8_t irq, uint8_t vec, uint8_t dest);

uint32_t hal_lapic_gid();
void cpu_lapic_init();
void hal_apic_init();

int boot_cpuN(uint32_t gid, paddr_t pa);

#endif

/*
 *******************************************************************************
 * LAPIC
 *******************************************************************************
 */

#define	LAPIC_ID		0x020	/* ID. RW */
#	define LAPIC_ID_MASK		0xff000000
#	define LAPIC_ID_SHIFT		24

#define LAPIC_VERS		0x030	/* Version. RO */
#	define LAPIC_VERSION_MASK	0x000000ff
#	define LAPIC_VERSION_LVT_MASK	0x00ff0000
#	define LAPIC_VERSION_LVT_SHIFT	16
#	define LAPIC_VERSION_DIRECTED_EOI 0x01000000
#	define LAPIC_VERSION_EXTAPIC_SPACE 0x80000000

#define LAPIC_TPR		0x080	/* Task Prio. RW */
#	define LAPIC_TPR_MASK		0x000000ff
#	define LAPIC_TPR_INT_MASK	0x000000f0
#	define LAPIC_TPR_SUB_MASK	0x0000000f

#define LAPIC_APRI		0x090	/* Arbitration prio. RO */
#	define LAPIC_APRI_MASK		0x000000ff

#define LAPIC_PPRI		0x0a0	/* Processor prio. RO */
#define LAPIC_EOI		0x0b0	/* End Int. W */
#define LAPIC_RRR		0x0c0	/* Remote read. RO */
#define LAPIC_LDR		0x0d0	/* Logical dest. RW */

#define LAPIC_DFR		0x0e0	/* Dest. format. RW */
#	define LAPIC_DFR_MASK		0xf0000000
#	define LAPIC_DFR_FLAT		0xf0000000
#	define LAPIC_DFR_CLUSTER	0x00000000

#define LAPIC_SVR		0x0f0	/* Spurious intvec. RW */
#	define LAPIC_SVR_VECTOR_MASK	0x000000ff
#	define LAPIC_SVR_VEC_FIX	0x0000000f
#	define LAPIC_SVR_VEC_PROG	0x000000f0
#	define LAPIC_SVR_ENABLE		0x00000100
#	define LAPIC_SVR_FOCUS		0x00000200
#	define LAPIC_SVR_FDIS		0x00000200
#	define LAPIC_SVR_EOI_BC_DIS	0x00001000

#define LAPIC_ISR	0x100		/* In-Service Status RO */
#define LAPIC_TMR	0x180		/* Trigger Mode RO */
#define LAPIC_IRR	0x200		/* Interrupt Req RO */
#define LAPIC_ESR	0x280		/* Err status. RW */

#define LAPIC_LVT_CMCI	0x2f0		/* LVT CMCI RW */

#define LAPIC_ICRLO	0x300		/* Int. cmd. RW */
#	define LAPIC_DLMODE_MASK	0x00000700	/* Delivery Mode */
#	define LAPIC_DLMODE_FIXED	0x00000000
#	define LAPIC_DLMODE_LOW		0x00000100
#	define LAPIC_DLMODE_SMI		0x00000200
#	define LAPIC_DLMODE_NMI		0x00000400
#	define LAPIC_DLMODE_INIT	0x00000500
#	define LAPIC_DLMODE_STARTUP	0x00000600
#	define LAPIC_DLMODE_EXTINT	0x00000700

#	define LAPIC_DSTMODE_PHYS	0x00000000
#	define LAPIC_DSTMODE_LOG	0x00000800

#	define LAPIC_DLSTAT_BUSY	0x00001000
#	define LAPIC_DLSTAT_IDLE	0x00000000

#	define LAPIC_LEVEL_MASK		0x00004000
#	define LAPIC_LEVEL_ASSERT	0x00004000
#	define LAPIC_LEVEL_DEASSERT	0x00000000

#	define LAPIC_TRIGGER_MASK	0x00008000
#	define LAPIC_TRIGGER_EDGE	0x00000000
#	define LAPIC_TRIGGER_LEVEL	0x00008000

#	define LAPIC_DEST_MASK		0x000c0000
#	define LAPIC_DEST_DEFAULT	0x00000000
#	define LAPIC_DEST_SELF		0x00040000
#	define LAPIC_DEST_ALLINCL	0x00080000
#	define LAPIC_DEST_ALLEXCL	0x000c0000

#define LAPIC_ICRHI	0x310		/* Int. cmd. RW */

#define LAPIC_LVT_TMR	0x320		/* Loc.vec.(timer) RW */
#	define LAPIC_TMR_VEC_MASK	0x000000ff
#	define LAPIC_TMR_DS		0x00001000
#	define LAPIC_TMR_M		0x00010000
#	define LAPIC_TMR_TM		0x00020000

#define LAPIC_LVT_THM	0x330		/* Loc.vec (Thermal) RW */
#	define LAPIC_THM_MT_MASK	0x00000700
#	define LAPIC_THM_MT_FIXED	0x00000000
#	define LAPIC_THM_MT_SMI		0x00000200
#	define LAPIC_THM_MT_NMI		0x00000400
#	define LAPIC_THM_MT_INIT	0x00000500
#	define LAPIC_THM_MT_EXTINT	0x00000700
#	define LAPIC_THM_DS		0x00001000
#	define LAPIC_THM_M		0x00010000

#define LAPIC_LVT_PMC	0x340		/* Loc.vec (Perf Mon) RW */
#	define LAPIC_PMC_MT_MASK	0x00000700
#	define LAPIC_PMC_MT_FIXED	0x00000000
#	define LAPIC_PMC_MT_SMI		0x00000200
#	define LAPIC_PMC_MT_NMI		0x00000400
#	define LAPIC_PMC_MT_INIT	0x00000500
#	define LAPIC_PMC_MT_EXTINT	0x00000700
#	define LAPIC_PMC_DS		0x00001000
#	define LAPIC_PMC_M		0x00010000

#define LAPIC_LVT_LINT0	0x350		/* Loc.vec (LINT0) RW */
#define LAPIC_LVT_LINT1	0x360		/* Loc.vec (LINT1) RW */
#	define LAPIC_LINT_MT_MASK	0x00000700
#	define LAPIC_LINT_MT_FIXED	0x00000000
#	define LAPIC_LINT_MT_SMI	0x00000200
#	define LAPIC_LINT_MT_NMI	0x00000400
#	define LAPIC_LINT_MT_INIT	0x00000500
#	define LAPIC_LINT_MT_EXTINT	0x00000700
#	define LAPIC_LINT_DS		0x00001000
#	define LAPIC_LINT_RIR		0x00004000
#	define LAPIC_LINT_TGM		0x00008000
#	define LAPIC_LINT_M		0x00010000

#define LAPIC_LVT_ERR	0x370		/* Loc.vec (ERROR) RW */
#	define LAPIC_ERR_MT_MASK	0x00000700
#	define LAPIC_ERR_MT_FIXED	0x00000000
#	define LAPIC_ERR_MT_SMI		0x00000200
#	define LAPIC_ERR_MT_NMI		0x00000400
#	define LAPIC_ERR_MT_INIT	0x00000500
#	define LAPIC_ERR_MT_EXTINT	0x00000700
#	define LAPIC_ERR_DS		0x00001000
#	define LAPIC_ERR_M		0x00010000

#define LAPIC_ICR_TIMER	0x380		/* Initial count RW */
#define LAPIC_CCR_TIMER	0x390		/* Current count RO */

#define LAPIC_DCR_TIMER	0x3e0		/* Divisor config RW */
#	define LAPIC_DCRT_DIV1		0x0b
#	define LAPIC_DCRT_DIV2		0x00
#	define LAPIC_DCRT_DIV4		0x01
#	define LAPIC_DCRT_DIV8		0x02
#	define LAPIC_DCRT_DIV16		0x03
#	define LAPIC_DCRT_DIV32		0x08
#	define LAPIC_DCRT_DIV64		0x09
#	define LAPIC_DCRT_DIV128	0x0a

/*
 *******************************************************************************
 * IRQ numbers
 *******************************************************************************
 */

#define IRQ_TIMER	0
#define IRQ_KEYBOARD	1
#define IRQ_COM2	3
#define IRQ_COM1	4
#define IRQ_FLOPPY	6
#define IRQ_ATA0	14
#define IRQ_ATA1	15

