summaryrefslogtreecommitdiff
path: root/src/arch/i386/smp/ioapic.c
blob: d64b0ad3f3b09cdf5de07f157379b8be232818c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <console/console.h>
#include <arch/ioapic.h>

/* we have to do more than we thought. I assumed Linux would do all the
 * interesting parts, and I was wrong. 
 */
struct ioapicreg {
	unsigned int reg;
	unsigned int value_low, value_high;
};
struct ioapicreg ioapicregvalues[] = {
#define ALL		(0xff << 24)
#define NONE		(0)
#define DISABLED	(1 << 16)
#define ENABLED		(0 << 16)
#define TRIGGER_EDGE	(0 << 15)
#define TRIGGER_LEVEL	(1 << 15)
#define POLARITY_HIGH	(0 << 13)
#define POLARITY_LOW	(1 << 13)
#define PHYSICAL_DEST	(0 << 11)
#define LOGICAL_DEST	(1 << 11)
#define ExtINT		(7 << 8)
#define NMI		(4 << 8)
#define SMI		(2 << 8)
#define INT		(1 << 8)
	/* mask, trigger, polarity, destination, delivery, vector */
	{0x00, DISABLED, NONE},
	{0x01, DISABLED, NONE},
	{0x02, DISABLED, NONE},
	{0x03, DISABLED, NONE},
	{0x04, DISABLED, NONE},
	{0x05, DISABLED, NONE},
	{0x06, DISABLED, NONE},
	{0x07, DISABLED, NONE},
	{0x08, DISABLED, NONE},
	{0x09, DISABLED, NONE},
	{0x0a, DISABLED, NONE},
	{0x0b, DISABLED, NONE},
	{0x0c, DISABLED, NONE},
	{0x0d, DISABLED, NONE},
	{0x0e, DISABLED, NONE},
	{0x0f, DISABLED, NONE},
	{0x10, DISABLED, NONE},
	{0x11, DISABLED, NONE},
	{0x12, DISABLED, NONE},
	{0x13, DISABLED, NONE},
	{0x14, DISABLED, NONE},
	{0x14, DISABLED, NONE},
	{0x15, DISABLED, NONE},
	{0x16, DISABLED, NONE},
	{0x17, DISABLED, NONE},
};

void setup_ioapic(void)
{
	int i;
	unsigned long value_low, value_high;
	unsigned long ioapicaddr = 0xfec00000;
	volatile unsigned long *l;
	struct ioapicreg *a = ioapicregvalues;

	l = (unsigned long *) ioapicaddr;
#if defined(i786)
	/* For the pentium 4 and above apic deliver their interrupts
	 * on the front side bus, enable that.
	 */
	l[0] = 0x03;
	l[4] = 1;
#endif /* i786 */
	for (i = 0; i < ARRAY_SIZE(ioapicregvalues);
	     i++, a++) {
		l[0] = (a->reg * 2) + 0x10;
		l[4] = a->value_low;
		value_low = l[4];
		l[0] = (a->reg *2) + 0x11;
		l[4] = a->value_high;
		value_high = l[4];
		if ((i==0) && (value_low == 0xffffffff)) {
			printk_warning("IO APIC not responding.\n");
			return;
		}
		printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", 
			a->reg, a->value_low, a->value_high);
	}
}