Chiichen b087521e07
完善设备驱动模型&调试串口驱动 (#379)
* 完成了基本架构重构,正在进行兼容

* 重构了所有 Device Driver ,还没有接上具体设备

* 基本把 Uart 接上了,还没有测试

* 初步完成系统设备初始化

* 初步重构 BlockDevice ,使其兼容新的 Device 结构

* 修改文件系统内的部分函数调用以满足重构后的接口

* 测试完 Uart 设备的功能

* 移除了自动添加的文件

* 修复了 warning 和部分格式

* 解决warning,并且修正sysfs初始化的位置

* Patch fix

* 删除了 sysinfo 的默认实现

* 删除了字符设备读写的 offset 参数

* 修复了 warning 和一些小逻辑错误

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>
2023-09-13 18:01:52 +08:00

236 lines
6.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by longjin on 2022/1/20.
//
#include "common/glib.h"
#include "common/kprint.h"
#include "common/printk.h"
#include "exception/gate.h"
#include "exception/irq.h"
#include "exception/trap.h"
#include "mm/mm.h"
#include "mm/slab.h"
#include "process/process.h"
#include "smp/smp.h"
#include "syscall/syscall.h"
#include <exception/softirq.h>
#include <libs/lib_ui/screen_manager.h>
#include <libs/lib_ui/textui.h>
#include <sched/sched.h>
#include <smp/ipi.h>
#include <filesystem/vfs/VFS.h>
#include "driver/acpi/acpi.h"
#include "driver/disk/ahci/ahci.h"
#include "driver/disk/ata.h"
#include "driver/keyboard/ps2_keyboard.h"
#include "driver/mouse/ps2_mouse.h"
#include "driver/multiboot2/multiboot2.h"
#include <driver/timers/HPET/HPET.h>
#include <driver/uart/uart.h>
#include <driver/video/video.h>
#include <time/timer.h>
#include <driver/interrupt/apic/apic_timer.h>
extern int rs_device_init();
extern int rs_tty_init();
extern void rs_softirq_init();
extern void rs_mm_init();
ul bsp_idt_size, bsp_gdt_size;
#pragma GCC push_options
#pragma GCC optimize("O0")
struct gdtr gdtp;
struct idtr idtp;
void reload_gdt()
{
gdtp.size = bsp_gdt_size - 1;
gdtp.gdt_vaddr = (ul)phys_2_virt((ul)&GDT_Table);
asm volatile("lgdt (%0) \n\t" ::"r"(&gdtp)
: "memory");
}
void reload_idt()
{
idtp.size = bsp_idt_size - 1;
idtp.idt_vaddr = (ul)phys_2_virt((ul)&IDT_Table);
// kdebug("gdtvaddr=%#018lx", p.gdt_vaddr);
// kdebug("gdt size=%d", p.size);
asm volatile("lidt (%0) \n\t" ::"r"(&idtp)
: "memory");
}
// 初始化系统各模块
void system_initialize()
{
c_uart_init(COM1, 115200);
video_init();
scm_init();
// 重新加载gdt和idt
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
_stack_start = head_stack_start; // 保存init proc的栈基地址由于之后取消了地址重映射因此必须在这里重新保存
kdebug("_stack_start=%#018lx", _stack_start);
load_TR(10); // 加载TR寄存器
set_tss64((uint *)&initial_tss[0], _stack_start, _stack_start, _stack_start, tss_item_addr, tss_item_addr,
tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr);
cpu_core_info[0].stack_start = _stack_start;
cpu_core_info[0].tss_vaddr = (uint64_t)&initial_tss[0];
// kdebug("cpu_core_info[0].tss_vaddr=%#018lx", cpu_core_info[0].tss_vaddr);
// kdebug("cpu_core_info[0].stack_start%#018lx", cpu_core_info[0].stack_start);
// 初始化中断描述符表
sys_vector_init();
// 初始化内存管理单元
// mm_init();
rs_mm_init();
// 内存管理单元初始化完毕后,需要立即重新初始化显示驱动。
// 原因是系统启动初期framebuffer被映射到48M地址处
// mm初始化完毕后若不重新初始化显示驱动将会导致错误的数据写入内存从而造成其他模块崩溃
// 对显示模块进行低级初始化不启用double buffer
io_mfence();
scm_reinit();
rs_textui_init();
// kinfo("vaddr:%#018lx", video_frame_buffer_info.vaddr);
io_mfence();
// =========== 重新设置initial_tss[0]的ist
uchar *ptr = (uchar *)kzalloc(STACK_SIZE, 0) + STACK_SIZE;
((struct process_control_block *)(ptr - STACK_SIZE))->cpu_id = 0;
initial_tss[0].ist1 = (ul)ptr;
initial_tss[0].ist2 = (ul)ptr;
initial_tss[0].ist3 = (ul)ptr;
initial_tss[0].ist4 = (ul)ptr;
initial_tss[0].ist5 = (ul)ptr;
initial_tss[0].ist6 = (ul)ptr;
initial_tss[0].ist7 = (ul)ptr;
// ===========================
acpi_init();
io_mfence();
sched_init();
io_mfence();
// 初始化中断模块
irq_init();
// softirq_init();
rs_softirq_init();
current_pcb->cpu_id = 0;
current_pcb->preempt_count = 0;
syscall_init();
io_mfence();
rs_timekeeping_init();
io_mfence();
rs_timer_init();
io_mfence();
rs_jiffies_init();
io_mfence();
vfs_init();
rs_device_init();
rs_tty_init();
io_mfence();
// 由于进程管理模块依赖于文件系统,因此必须在文件系统初始化完毕后再初始化进程管理模块
// 并且因为smp的IDLE进程的初始化依赖于进程管理模块
// 因此必须在进程管理模块初始化完毕后再初始化smp。
io_mfence();
process_init();
io_mfence();
rs_clocksource_boot_finish();
io_mfence();
cpu_init();
ps2_keyboard_init();
io_mfence();
rs_pci_init();
// 这里必须加内存屏障,否则会出错
io_mfence();
smp_init();
io_mfence();
HPET_init();
io_mfence();
HPET_measure_freq();
io_mfence();
// current_pcb->preempt_count = 0;
// kdebug("cpu_get_core_crysral_freq()=%ld", cpu_get_core_crysral_freq());
// 启用double buffer
// scm_enable_double_buffer(); // 因为时序问题, 该函数调用被移到 initial_kernel_thread
io_mfence();
HPET_enable();
io_mfence();
// 系统初始化到此结束,剩下的初始化功能应当放在初始内核线程中执行
apic_timer_init();
io_mfence();
}
// 操作系统内核从这里开始执行
void Start_Kernel(void)
{
// 获取multiboot2的信息
uint64_t mb2_info, mb2_magic;
__asm__ __volatile__("movq %%r15, %0 \n\t"
"movq %%r14, %1 \n\t"
"movq %%r13, %2 \n\t"
"movq %%r12, %3 \n\t"
: "=r"(mb2_info), "=r"(mb2_magic), "=r"(bsp_gdt_size), "=r"(bsp_idt_size)::"memory");
reload_gdt();
reload_idt();
// 重新设置TSS描述符
set_tss_descriptor(10, (void *)(&initial_tss[0]));
mb2_info &= 0xffffffff;
mb2_magic &= 0xffffffff;
multiboot2_magic = (uint)mb2_magic;
multiboot2_boot_info_addr = mb2_info + PAGE_OFFSET;
io_mfence();
system_initialize();
io_mfence();
// idle
while (1)
{
// 如果调用的时候启用了中断则hlt。否则认为是bug
if (get_rflags() & 0x200)
{
// kdebug("hlt");
hlt();
}
else
{
BUG_ON(1);
pause();
}
}
}
#pragma GCC pop_options