/kernel/trunk/arch/ia32/include/smp/apic.h |
---|
114,7 → 114,56 |
#define IOAPICARB 0x02 |
#define IOREDTBL 0x10 |
/** Delivery modes. */ |
#define DELMOD_FIXED 0x0 |
#define DELMOD_LOWPRI 0x1 |
#define DELMOD_SMI 0x2 |
/* 0x3 reserved */ |
#define DELMOD_NMI 0x4 |
#define DELMOD_INIT 0x5 |
/* 0x6 reserved */ |
#define DELMOD_EXTINT 0x7 |
/** Destination modes. */ |
#define DESTMOD_PHYS 0x0 |
#define DESTMOD_LOGIC 0x1 |
/** Trigger Modes. */ |
#define TRIGMOD_EDGE 0x0 |
#define TRIGMOD_LEVEL 0x1 |
/** Interrupt Input Pin Polarities. */ |
#define POLARITY_HIGH 0x0 |
#define POLARITY_LOW 0x1 |
/** I/O Redirection Register. */ |
struct io_redirection_reg { |
union { |
__u32 lo; |
struct { |
unsigned intvec : 8; /**< 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. */ |
}; |
}; |
union { |
__u32 hi; |
struct { |
unsigned : 24; /**< Reserved. */ |
unsigned dest : 8; /**< Destination Field. */ |
}; |
}; |
} __attribute__ ((packed)); |
typedef struct io_redirection_reg io_redirection_reg_t; |
extern volatile __u32 *l_apic; |
extern volatile __u32 *io_apic; |
/kernel/trunk/arch/ia32/include/smp/mps.h |
---|
120,8 → 120,6 |
extern struct smp_config_operations mps_config_operations; |
extern int mps_irq_to_pin(int irq); |
extern void mps_init(void); |
extern void kmp(void *arg); |
/kernel/trunk/arch/ia32/include/smp/smp.h |
---|
32,11 → 32,15 |
#include <arch/types.h> |
#include <typedefs.h> |
/** SMP config opertaions interface. */ |
struct smp_config_operations { |
count_t (* cpu_count)(void); |
bool (* cpu_enabled)(index_t i); |
bool (*cpu_bootstrap)(index_t i); |
__u8 (*cpu_apic_id)(index_t i); |
count_t (* cpu_count)(void); /**< Return number of detected processors. */ |
bool (* cpu_enabled)(index_t i); /**< Check whether the processor of index i is enabled. */ |
bool (*cpu_bootstrap)(index_t i); /**< Check whether the processor of index i is BSP. */ |
__u8 (*cpu_apic_id)(index_t i); /**< Return APIC ID of the processor of index i. */ |
int (*irq_to_pin)(int irq); /**< Return mapping between irq and APIC pin. */ |
}; |
extern int smp_irq_to_pin(int irq); |
#endif |
/kernel/trunk/arch/ia32/src/ia32.c |
---|
56,7 → 56,6 |
if (config.cpu_active == 1) { |
bios_init(); |
i8042_init(); /* keyboard controller */ |
i8259_init(); /* PIC */ |
i8254_init(); /* hard clock */ |
89,7 → 88,7 |
void arch_post_smp_init(void) |
{ |
trap_virtual_enable_irqs(1<<IRQ_KBD); |
i8042_init(); /* keyboard controller */ |
} |
void calibrate_delay_loop(void) |
/kernel/trunk/arch/ia32/src/smp/mps.c |
---|
89,12 → 89,14 |
static bool is_cpu_enabled(index_t i); |
static bool is_bsp(index_t i); |
static __u8 get_cpu_apic_id(index_t i); |
static int mps_irq_to_pin(int irq); |
struct smp_config_operations mps_config_operations = { |
.cpu_count = get_cpu_count, |
.cpu_enabled = is_cpu_enabled, |
.cpu_bootstrap = is_bsp, |
.cpu_apic_id = get_cpu_apic_id |
.cpu_apic_id = get_cpu_apic_id, |
.irq_to_pin = mps_irq_to_pin |
}; |
count_t get_cpu_count(void) |
/kernel/trunk/arch/ia32/src/smp/smp.c |
---|
165,4 → 165,10 |
waitq_wakeup(&kmp_completion_wq, WAKEUP_FIRST); |
} |
int smp_irq_to_pin(int irq) |
{ |
ASSERT(ops != NULL); |
return ops->irq_to_pin(irq); |
} |
#endif /* CONFIG_SMP */ |
/kernel/trunk/arch/ia32/src/smp/apic.c |
---|
40,8 → 40,7 |
#ifdef CONFIG_SMP |
/* |
* This is functional, far-from-general-enough interface to the APIC. |
* Advanced Programmable Interrupt Controller for MP systems. |
* Advanced Programmable Interrupt Controller for SMP systems. |
* Tested on: |
* Bochs 2.0.2 - Bochs 2.2 with 2-8 CPUs |
* Simics 2.0.28 - Simics 2.2.14 2-4 CPUs |
82,11 → 81,12 |
*/ |
io_apic_disable_irqs(0xffff); |
trap_register(VECTOR_CLK, l_apic_timer_interrupt); |
for (i=1; i<16; i++) { |
for (i=0; i<16; i++) { |
int pin; |
if ((pin = mps_irq_to_pin(i)) != -1) |
io_apic_change_ioredtbl(pin,0xf,IVT_IRQBASE+i,LOPRI); |
if ((pin = smp_irq_to_pin(i)) != -1) { |
io_apic_change_ioredtbl(pin,0xff,IVT_IRQBASE+i,LOPRI); |
} |
} |
352,29 → 352,31 |
void io_apic_change_ioredtbl(int signal, int dest, __u8 v, int flags) |
{ |
__u32 reglo, reghi; |
io_redirection_reg_t reg; |
int dlvr = 0; |
if (flags & LOPRI) |
dlvr = 1; |
dlvr = DELMOD_LOWPRI; |
reglo = io_apic_read(IOREDTBL + signal*2); |
reghi = io_apic_read(IOREDTBL + signal*2 + 1); |
reg.lo = io_apic_read(IOREDTBL + signal*2); |
reg.hi = io_apic_read(IOREDTBL + signal*2 + 1); |
reghi &= ~0x0f000000; |
reghi |= (dest<<24); |
reg.dest = dest; |
reg.destmod = DESTMOD_LOGIC; |
reg.trigger_mode = TRIGMOD_EDGE; |
reg.intpol = POLARITY_HIGH; |
reg.delmod = dlvr; |
reg.intvec = v; |
reglo &= (~0x1ffff) | (1<<16); /* don't touch the mask */ |
reglo |= (0<<15) | (0<<13) | (0<<11) | (dlvr<<8) | v; |
io_apic_write(IOREDTBL + signal*2, reglo); |
io_apic_write(IOREDTBL + signal*2 + 1, reghi); |
io_apic_write(IOREDTBL + signal*2, reg.lo); |
io_apic_write(IOREDTBL + signal*2 + 1, reg.hi); |
} |
void io_apic_disable_irqs(__u16 irqmask) |
{ |
int i,pin; |
__u32 reglo; |
io_redirection_reg_t reg; |
int i, pin; |
for (i=0;i<16;i++) { |
if ((irqmask>>i) & 1) { |
382,11 → 384,11 |
* Mask the signal input in IO APIC if there is a |
* mapping for the respective IRQ number. |
*/ |
pin = mps_irq_to_pin(i); |
pin = smp_irq_to_pin(i); |
if (pin != -1) { |
reglo = io_apic_read(IOREDTBL + pin*2); |
reglo |= (1<<16); |
io_apic_write(IOREDTBL + pin*2,reglo); |
reg.lo = io_apic_read(IOREDTBL + pin*2); |
reg.masked = true; |
io_apic_write(IOREDTBL + pin*2, reg.lo); |
} |
} |
395,8 → 397,8 |
void io_apic_enable_irqs(__u16 irqmask) |
{ |
int i,pin; |
__u32 reglo; |
int i, pin; |
io_redirection_reg_t reg; |
for (i=0;i<16;i++) { |
if ((irqmask>>i) & 1) { |
404,11 → 406,11 |
* Unmask the signal input in IO APIC if there is a |
* mapping for the respective IRQ number. |
*/ |
pin = mps_irq_to_pin(i); |
pin = smp_irq_to_pin(i); |
if (pin != -1) { |
reglo = io_apic_read(IOREDTBL + pin*2); |
reglo &= ~(1<<16); |
io_apic_write(IOREDTBL + pin*2,reglo); |
reg.lo = io_apic_read(IOREDTBL + pin*2); |
reg.masked = false; |
io_apic_write(IOREDTBL + pin*2, reg.lo); |
} |
} |
/kernel/trunk/arch/ia32/src/drivers/i8042.c |
---|
43,6 → 43,14 |
* It takes care of low-level keyboard functions. |
*/ |
#define i8042_DATA 0x60 |
#define i8042_STATUS 0x64 |
/** Keyboard commands. */ |
#define KBD_ENABLE 0xf4 |
#define KBD_DISABLE 0xf5 |
#define KBD_ACK 0xfa |
#define SPECIAL '?' |
#define KEY_RELEASE 0x80 |
230,6 → 238,7 |
void i8042_init(void) |
{ |
trap_register(VECTOR_KBD, i8042_interrupt); |
trap_virtual_enable_irqs(1<<IRQ_KBD); |
spinlock_initialize(&keylock); |
chardev_initialize(&kbrd, &ops); |
stdin = &kbrd; |
245,7 → 254,7 |
__u8 x; |
trap_virtual_eoi(); |
x = inb(0x60); |
x = inb(i8042_DATA); |
if (x & KEY_RELEASE) |
key_released(x ^ KEY_RELEASE); |
else |