source: mainline/kernel/arch/ia32/src/ia32.c@ c89ae25

topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c89ae25 was 98a935e, checked in by jxsvoboda <5887334+jxsvoboda@…>, 4 years ago

Configure NS16550 transmission format settings on initialization on PCs.

Currently, the NS116550 serial line controller is left with its
settings as it was left by the boot firmware and/or bootloader.
On my computer, this was an invalid configuration, and it left me
with a really slow booting system, since each output character
had to go through the full timeout loop in ns16550_sendb().

This patch adds the necessary bit and register descriptions to configure
the baud rate and transmission settings, as well as configuring them on
post-SMP initialization on ia32 and amd64, currently with values matching
the ns8250 userspace character device driver (38400 baud, 8-bit words,
2 stop bits, no parity).

This could perhaps be changed to be adjustable with a kernel command-line
argument, or through the configuration system.

This change does not affect emulators, since those largely ignore these
settings.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Jakub Jermar
3 * Copyright (c) 2009 Jiri Svoboda
4 * Copyright (c) 2009 Martin Decky
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * - The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/** @addtogroup kernel_ia32
32 * @{
33 */
34/** @file
35 */
36
37#include <arch.h>
38#include <arch/arch.h>
39#include <stdint.h>
40#include <errno.h>
41#include <mem.h>
42#include <interrupt.h>
43#include <console/console.h>
44#include <syscall/syscall.h>
45#include <sysinfo/sysinfo.h>
46#include <arch/bios/bios.h>
47#include <arch/boot/boot.h>
48#include <arch/drivers/i8254.h>
49#include <genarch/acpi/acpi.h>
50#include <genarch/drivers/ega/ega.h>
51#include <genarch/drivers/i8042/i8042.h>
52#include <genarch/drivers/i8259/i8259.h>
53#include <genarch/drivers/ns16550/ns16550.h>
54#include <genarch/drivers/legacy/ia32/io.h>
55#include <genarch/fb/bfb.h>
56#include <genarch/kbrd/kbrd.h>
57#include <genarch/srln/srln.h>
58#include <genarch/multiboot/multiboot.h>
59#include <genarch/multiboot/multiboot2.h>
60#include <genarch/pic/pic_ops.h>
61#include <arch/pm.h>
62#include <arch/vreg.h>
63
64#ifdef CONFIG_SMP
65#include <arch/smp/apic.h>
66#endif
67
68static void ia32_pre_mm_init(void);
69static void ia32_post_mm_init(void);
70static void ia32_post_cpu_init(void);
71static void ia32_pre_smp_init(void);
72static void ia32_post_smp_init(void);
73
74arch_ops_t ia32_ops = {
75 .pre_mm_init = ia32_pre_mm_init,
76 .post_mm_init = ia32_post_mm_init,
77 .post_cpu_init = ia32_post_cpu_init,
78 .pre_smp_init = ia32_pre_smp_init,
79 .post_smp_init = ia32_post_smp_init,
80};
81
82arch_ops_t *arch_ops = &ia32_ops;
83
84/** Perform ia32-specific initialization before main_bsp() is called.
85 *
86 * @param signature Multiboot signature.
87 * @param info Multiboot information structure.
88 *
89 */
90void ia32_pre_main(uint32_t signature, void *info)
91{
92 /* Parse multiboot information obtained from the bootloader. */
93 multiboot_info_parse(signature, (multiboot_info_t *) info);
94 multiboot2_info_parse(signature, (multiboot2_info_t *) info);
95
96#ifdef CONFIG_SMP
97 size_t unmapped_size = (uintptr_t) unmapped_end - BOOT_OFFSET;
98 /* Copy AP bootstrap routines below 1 MB. */
99 memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET, unmapped_size);
100#endif
101}
102
103void ia32_pre_mm_init(void)
104{
105 pm_init();
106
107 if (config.cpu_active == 1) {
108 interrupt_init();
109 bios_init();
110
111 /* PIC */
112 i8259_init((i8259_t *) I8259_PIC0_BASE,
113 (i8259_t *) I8259_PIC1_BASE, IVT_IRQBASE);
114
115 /* Set PIC operations. */
116 pic_ops = &i8259_pic_ops;
117 }
118}
119
120void ia32_post_mm_init(void)
121{
122 vreg_init();
123
124 if (config.cpu_active == 1) {
125 /* Initialize IRQ routing */
126 irq_init(IRQ_COUNT, IRQ_COUNT);
127
128 /* hard clock */
129 i8254_init();
130
131#if (defined(CONFIG_FB) || defined(CONFIG_EGA))
132 bool bfb = false;
133#endif
134
135#ifdef CONFIG_FB
136 bfb = bfb_init();
137#endif
138
139#ifdef CONFIG_EGA
140 if (!bfb) {
141 outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
142 if (egadev)
143 stdout_wire(egadev);
144 }
145#endif
146
147 /* Merge all memory zones to 1 big zone */
148 zone_merge_all();
149 }
150}
151
152void ia32_post_cpu_init(void)
153{
154#ifdef CONFIG_SMP
155 if (config.cpu_active > 1) {
156 l_apic_init();
157 l_apic_debug();
158 }
159#endif
160}
161
162void ia32_pre_smp_init(void)
163{
164 if (config.cpu_active == 1) {
165#ifdef CONFIG_SMP
166 acpi_init();
167#endif /* CONFIG_SMP */
168 }
169}
170
171void ia32_post_smp_init(void)
172{
173 /* Currently the only supported platform for ia32 is 'pc'. */
174 static const char *platform = "pc";
175
176 sysinfo_set_item_data("platform", NULL, (void *) platform,
177 str_size(platform));
178
179#ifdef CONFIG_PC_KBD
180 /*
181 * Initialize the i8042 controller. Then initialize the keyboard
182 * module and connect it to i8042. Enable keyboard interrupts.
183 */
184 i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
185 if (i8042_instance) {
186 kbrd_instance_t *kbrd_instance = kbrd_init();
187 if (kbrd_instance) {
188 indev_t *sink = stdin_wire();
189 indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
190 i8042_wire(i8042_instance, kbrd);
191 pic_ops->enable_irqs(1 << IRQ_KBD);
192 pic_ops->enable_irqs(1 << IRQ_MOUSE);
193 }
194 }
195#endif
196
197#if (defined(CONFIG_NS16550) || defined(CONFIG_NS16550_OUT))
198 /*
199 * Initialize the ns16550 controller.
200 */
201#ifdef CONFIG_NS16550_OUT
202 outdev_t *ns16550_out;
203 outdev_t **ns16550_out_ptr = &ns16550_out;
204#else
205 outdev_t **ns16550_out_ptr = NULL;
206#endif
207 ns16550_instance_t *ns16550_instance =
208 ns16550_init(NS16550_BASE, 0, IRQ_NS16550, NULL, NULL,
209 ns16550_out_ptr);
210 if (ns16550_instance) {
211 ns16550_format_set(ns16550_instance, 38400,
212 LCR_PARITY_NONE | LCR_STOP_BIT_TWO | LCR_WORD_LEN_8);
213#ifdef CONFIG_NS16550
214 srln_instance_t *srln_instance = srln_init();
215 if (srln_instance) {
216 indev_t *sink = stdin_wire();
217 indev_t *srln = srln_wire(srln_instance, sink);
218 ns16550_wire(ns16550_instance, srln);
219 pic_ops->enable_irqs(1 << IRQ_NS16550);
220 }
221#endif
222#ifdef CONFIG_NS16550_OUT
223 if (ns16550_out) {
224 stdout_wire(ns16550_out);
225 }
226#endif
227 }
228#endif
229
230 sysinfo_set_item_val(pic_ops->get_name(), NULL, true);
231}
232
233void calibrate_delay_loop(void)
234{
235 i8254_calibrate_delay_loop();
236 if (config.cpu_active == 1) {
237 /*
238 * This has to be done only on UP.
239 * On SMP, i8254 is not used for time keeping and its interrupt pin remains masked.
240 */
241 i8254_normal_operation();
242 }
243}
244
245/** Construct function pointer
246 *
247 * @param fptr function pointer structure
248 * @param addr function address
249 * @param caller calling function address
250 *
251 * @return address of the function pointer
252 *
253 */
254void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
255{
256 return addr;
257}
258
259void arch_reboot(void)
260{
261#ifdef CONFIG_PC_KBD
262 i8042_cpu_reset((i8042_t *) I8042_BASE);
263#endif
264}
265
266void irq_initialize_arch(irq_t *irq)
267{
268 (void) irq;
269}
270
271/** @}
272 */
Note: See TracBrowser for help on using the repository browser.