startup.cc 2.33 KB
Newer Older
Bernhard Heinloth's avatar
Bernhard Heinloth committed
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// vim: set et ts=4 sw=4:

/*! \file
 *  \brief Enthält Funktionen für den Systemstart, die nicht mehr in
 *  Assembler geschrieben werden müssen.
 */

#include "types.h"
#include "machine/apicsystem.h"
#include "machine/cpu.h"
#include "machine/io_port.h"

/*! \brief Die Zeiger auf die Multiboot-Strukturen wird vom Assembler-
 * startup zugewiesen.
 */
void *multiboot_addr = 0;

/*! \brief Hilfsfunktion der PIT-Initialisierung, die ein kurzes Delay
 *  verursacht.
 */
static void delay()
{
	asm volatile("nop\n\t":::"memory");
}

/*! \brief Initalisierung der PICs (Programmierbare Interrupt-Controller),
 *  damit alle 15 Hardware-Interrupts nacheinander in der idt liegen.
 */
static void initialise_pics()
{
	IO_Port p20(0x20);
	IO_Port p21(0x21);
	IO_Port pa0(0xa0);
	IO_Port pa1(0xa1);

	//ICW1: 8086 Modus mit ICW4
	p20.outb(0x11);
	delay();
	pa0.outb(0x11);
	delay();

	//ICW2 Master: IRQ # Offset (32)
	p21.outb(0x20);
	delay();

	//ICW2 Slave: IRQ # Offset (40)
	pa1.outb(0x28);
	delay();

	//ICW3 Master: Slaves an IRQs
	p21.outb(0x04);
	delay();

	//ICW3 Slave: Verbunden mit IRQ2 des Masters
	pa1.outb(0x02);
	delay();

	//ICW4: 8086 Modus und automatischer EIO
	p21.outb(0x03);
	delay();
	pa1.outb(0x03);
	delay();

	//Alle Hardware-Interrupts durch Legacy-PICs ausmaskieren.
	pa1.outb(0xff);
	delay();

	p21.outb(0xff);
}

/*! \brief Ab gcc 4.7 weitere Initialisierung globaler Objekte.
 *
 */
static void csu_init()
{
	extern void (*__init_array_start []) ();
	extern void (*__init_array_end[]) ();

	const size_t size = __init_array_end - __init_array_start;
	for (size_t i = 0; i < size; i++) {
		(*__init_array_start[i])();
	}
}

extern "C" void _init();
extern "C" void _fini();
extern "C" int main_ap() __attribute__ ((weak));
extern "C" int main();

static bool bootCPU = true;
extern "C" void kernel_init()
{

	if(bootCPU) {
		bootCPU = false;

		//initialisierung der PICs
		initialise_pics();

		//Aufruf globaler Konstruktoren
		_init();
		csu_init();

		//weitere Initialisierungen
		system.detectSystemType();
		system.setupThisProcessor();

		//Die main-Funktion
		main();

		//falls die main-Funktion zurückkehren sollte werden die Destruktoren
		//globaler Objekte aufgerufen
		_fini();
	}
	else {
		// Initialisiere diesen AP Prozessor
		system.setupThisProcessor();

		// Springe die Anwendung an.
		main_ap();
	}

	for(;;) {
		CPU::die();
	}
}