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
RevLine 
[f761f1eb]1/*
[df4ed85]2 * Copyright (c) 2001-2004 Jakub Jermar
[deca67b]3 * Copyright (c) 2009 Jiri Svoboda
4 * Copyright (c) 2009 Martin Decky
[f761f1eb]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
[c5429fe]31/** @addtogroup kernel_ia32
[b45c443]32 * @{
33 */
34/** @file
35 */
36
[f761f1eb]37#include <arch.h>
[36df4109]38#include <arch/arch.h>
[83dab11]39#include <stdint.h>
[d8db519]40#include <errno.h>
[44a7ee5]41#include <mem.h>
[fcfac420]42#include <interrupt.h>
[41d33ac]43#include <console/console.h>
[d8db519]44#include <syscall/syscall.h>
[4c7257b]45#include <sysinfo/sysinfo.h>
[d8db519]46#include <arch/bios/bios.h>
[deca67b]47#include <arch/boot/boot.h>
[d8db519]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>
[87a5796]52#include <genarch/drivers/i8259/i8259.h>
[3296df5]53#include <genarch/drivers/ns16550/ns16550.h>
[d8db519]54#include <genarch/drivers/legacy/ia32/io.h>
55#include <genarch/fb/bfb.h>
56#include <genarch/kbrd/kbrd.h>
[3296df5]57#include <genarch/srln/srln.h>
[d8db519]58#include <genarch/multiboot/multiboot.h>
59#include <genarch/multiboot/multiboot2.h>
[2a103b5]60#include <genarch/pic/pic_ops.h>
[d6f9fff]61#include <arch/pm.h>
62#include <arch/vreg.h>
[ad36bd6]63
[26678e5]64#ifdef CONFIG_SMP
65#include <arch/smp/apic.h>
66#endif
67
[36df4109]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
[5d8d71e]84/** Perform ia32-specific initialization before main_bsp() is called.
[deca67b]85 *
[1f5c9c96]86 * @param signature Multiboot signature.
87 * @param info Multiboot information structure.
88 *
[deca67b]89 */
[36df4109]90void ia32_pre_main(uint32_t signature, void *info)
[deca67b]91{
[5d8d71e]92 /* Parse multiboot information obtained from the bootloader. */
[1f5c9c96]93 multiboot_info_parse(signature, (multiboot_info_t *) info);
94 multiboot2_info_parse(signature, (multiboot2_info_t *) info);
[a35b458]95
[deca67b]96#ifdef CONFIG_SMP
[bae43dc]97 size_t unmapped_size = (uintptr_t) unmapped_end - BOOT_OFFSET;
[deca67b]98 /* Copy AP bootstrap routines below 1 MB. */
[8a1afd2]99 memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET, unmapped_size);
[deca67b]100#endif
101}
102
[36df4109]103void ia32_pre_mm_init(void)
[f761f1eb]104{
105 pm_init();
106
107 if (config.cpu_active == 1) {
[cea12e9]108 interrupt_init();
[dba84ff]109 bios_init();
[a35b458]110
[cea12e9]111 /* PIC */
[d1cbad5]112 i8259_init((i8259_t *) I8259_PIC0_BASE,
[3daba42e]113 (i8259_t *) I8259_PIC1_BASE, IVT_IRQBASE);
[bbb99f82]114
[2a103b5]115 /* Set PIC operations. */
116 pic_ops = &i8259_pic_ops;
[f761f1eb]117 }
118}
119
[36df4109]120void ia32_post_mm_init(void)
[7eade45]121{
[d6f9fff]122 vreg_init();
123
[425913b]124 if (config.cpu_active == 1) {
[cea12e9]125 /* Initialize IRQ routing */
126 irq_init(IRQ_COUNT, IRQ_COUNT);
[a35b458]127
[cea12e9]128 /* hard clock */
129 i8254_init();
[a35b458]130
[a71c158]131#if (defined(CONFIG_FB) || defined(CONFIG_EGA))
[1f5c9c96]132 bool bfb = false;
[a71c158]133#endif
[a35b458]134
[22cf454d]135#ifdef CONFIG_FB
[1f5c9c96]136 bfb = bfb_init();
[22cf454d]137#endif
[a35b458]138
[ec944b1]139#ifdef CONFIG_EGA
[1f5c9c96]140 if (!bfb) {
[a71c158]141 outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
142 if (egadev)
143 stdout_wire(egadev);
144 }
[ec944b1]145#endif
[a35b458]146
[381465e]147 /* Merge all memory zones to 1 big zone */
148 zone_merge_all();
[babcb148]149 }
150}
151
[36df4109]152void ia32_post_cpu_init(void)
[26678e5]153{
154#ifdef CONFIG_SMP
[49eb681]155 if (config.cpu_active > 1) {
[26678e5]156 l_apic_init();
157 l_apic_debug();
158 }
159#endif
160}
161
[36df4109]162void ia32_pre_smp_init(void)
[babcb148]163{
164 if (config.cpu_active == 1) {
[f619ec11]165#ifdef CONFIG_SMP
[85bfdcc8]166 acpi_init();
[f619ec11]167#endif /* CONFIG_SMP */
[425913b]168 }
[7eade45]169}
170
[36df4109]171void ia32_post_smp_init(void)
[7453929]172{
[eff1f033]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
[2a34e4c]179#ifdef CONFIG_PC_KBD
[411b6a6]180 /*
[2a34e4c]181 * Initialize the i8042 controller. Then initialize the keyboard
182 * module and connect it to i8042. Enable keyboard interrupts.
[411b6a6]183 */
[c2417bc]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);
[2a103b5]191 pic_ops->enable_irqs(1 << IRQ_KBD);
192 pic_ops->enable_irqs(1 << IRQ_MOUSE);
[c2417bc]193 }
[2a34e4c]194 }
195#endif
[3296df5]196
[6bbe470]197#if (defined(CONFIG_NS16550) || defined(CONFIG_NS16550_OUT))
[3296df5]198 /*
[6bbe470]199 * Initialize the ns16550 controller.
[3296df5]200 */
[21b6307]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
[3bacee1]207 ns16550_instance_t *ns16550_instance =
208 ns16550_init(NS16550_BASE, 0, IRQ_NS16550, NULL, NULL,
[21b6307]209 ns16550_out_ptr);
[3296df5]210 if (ns16550_instance) {
[98a935e]211 ns16550_format_set(ns16550_instance, 38400,
212 LCR_PARITY_NONE | LCR_STOP_BIT_TWO | LCR_WORD_LEN_8);
[6bbe470]213#ifdef CONFIG_NS16550
[3296df5]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);
[2a103b5]219 pic_ops->enable_irqs(1 << IRQ_NS16550);
[3296df5]220 }
221#endif
[6bbe470]222#ifdef CONFIG_NS16550_OUT
223 if (ns16550_out) {
224 stdout_wire(ns16550_out);
225 }
226#endif
[24b06199]227 }
228#endif
[a35b458]229
[2a103b5]230 sysinfo_set_item_val(pic_ops->get_name(), NULL, true);
[7453929]231}
232
[f761f1eb]233void calibrate_delay_loop(void)
234{
235 i8254_calibrate_delay_loop();
[f701b236]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 }
[f761f1eb]243}
[281b607]244
[6da1013f]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
[149d14e5]259void arch_reboot(void)
260{
261#ifdef CONFIG_PC_KBD
262 i8042_cpu_reset((i8042_t *) I8042_BASE);
263#endif
264}
265
[3a2f8aa]266void irq_initialize_arch(irq_t *irq)
267{
268 (void) irq;
269}
270
[06e1e95]271/** @}
[b45c443]272 */
Note: See TracBrowser for help on using the repository browser.