adc7cadf4c453a79297f36e45425bd15bf28773f
[akaros.git] / kern / arch / i686 / init.c
1 /* See COPYRIGHT for copyright information. */
2
3 #ifdef __SHARC__
4 #pragma nosharc
5 #endif
6
7 #include <smp.h>
8
9 #include <arch/rl8168.h>
10 #include <arch/ne2k.h>
11 #include <arch/e1000.h>
12 #include <arch/mptables.h>
13 #include <arch/pci.h>
14 #include <arch/ioapic.h>
15 #include <arch/console.h>
16 #include <arch/perfmon.h>
17 #include <arch/init.h>
18 #include <console.h>
19
20 struct ancillary_state x86_default_fpu;
21
22 /* irq handler for the console (kb, serial, etc) */
23 static void irq_console(struct hw_trapframe *hw_tf, void *data)
24 {
25         uint8_t c;
26         struct cons_dev *cdev = (struct cons_dev*)data;
27         assert(cdev);
28         if (cons_get_char(cdev, &c))
29                 return;
30         /* Do our work in an RKM, instead of interrupt context.  Note the RKM will
31          * cast 'c' to a char. */
32         if (c == 'G')
33                 send_kernel_message(core_id(), __run_mon, 0, 0, 0, KMSG_ROUTINE);
34         else
35                 send_kernel_message(core_id(), __cons_add_char, (long)&cons_buf,
36                                     (long)c, 0, KMSG_ROUTINE);
37 }
38
39 static void cons_irq_init(void)
40 {
41         struct cons_dev *i;
42         /* Register interrupt handlers for all console devices */
43         SLIST_FOREACH(i, &cdev_list, next) {
44                 register_interrupt_handler(interrupt_handlers, i->irq + PIC1_OFFSET,
45                                            irq_console, i);
46                 /* Route any console IRQs to core 0 */
47         #ifdef CONFIG_ENABLE_MPTABLES
48                 ioapic_route_irq(i->irq, 0);
49         #else
50                 pic_unmask_irq(i->irq);
51                 unmask_lapic_lvt(LAPIC_LVT_LINT0);
52         #endif /* CONFIG_ENABLE_MPTABLES */
53                 printd("Registered handler for IRQ %d (ISR %d)\n", i->irq,
54                        i->irq + PIC1_OFFSET);
55         }
56 }
57
58 void arch_init()
59 {
60         /* need to reinit before saving, in case boot agents used the FPU or it is
61          * o/w dirty.  had this happen on c89, which had a full FP stack after
62          * booting. */
63         asm volatile ("fninit");
64         save_fp_state(&x86_default_fpu); /* used in arch/trap.h for fpu init */
65         pci_init();
66 #ifdef CONFIG_ENABLE_MPTABLES
67         mptables_parse();
68         ioapic_init(); // MUST BE AFTER PCI/ISA INIT!
69         // TODO: move these back to regular init.  requires fixing the 
70         // CONFIG_NETWORKING inits to not need multiple cores running.
71 #endif
72         // this returns when all other cores are done and ready to receive IPIs
73         #ifdef CONFIG_SINGLE_CORE
74                 smp_percpu_init();
75         #else
76                 smp_boot();
77         #endif
78         proc_init();
79
80         /* EXPERIMENTAL NETWORK FUNCTIONALITY
81          * To enable, define CONFIG_NETWORKING in your Makelocal
82          * If enabled, will load the rl8168 driver (if device exists)
83          * and will a boot into userland matrix, so remote syscalls can be performed.
84          * If in simulation, will do some debugging information with the ne2k device
85          *
86          * Note: If you use this, you should also define the mac address of the 
87          * teathered machine via USER_MAC_ADDRESS in Makelocal.
88          *
89          * Additionally, you should have a look at the syscall server in the tools directory
90          */
91         #ifdef CONFIG_NETWORKING
92         #ifdef CONFIG_SINGLE_CORE
93                 warn("You currently can't have networking if you boot into single core mode!!\n");
94         #else
95                 rl8168_init();          
96                 ne2k_init();
97                 e1000_init();
98         #endif // CONFIG_SINGLE_CORE
99         #endif // CONFIG_NETWORKING
100
101         perfmon_init();
102         cons_irq_init();
103         check_timing_stability();
104 }