Browse Source

:wrench: 更新了键盘驱动程序,使其适配vfs

fslongjin 2 years ago
parent
commit
832c0c7e5c

+ 2 - 1
.vscode/settings.json

@@ -98,7 +98,8 @@
         "ipi.h": "c",
         "arch.h": "c",
         "elf.h": "c",
-        "stdio.h": "c"
+        "stdio.h": "c",
+        "wait_queue.h": "c"
     },
     "C_Cpp.errorSquiggles": "Enabled",
     "esbonio.sphinx.confDir": ""

+ 5 - 9
kernel/Makefile

@@ -18,7 +18,7 @@ LD_LIST := head.o
 OBJ_LIST := head.o
 
 
-kernel_subdirs := common driver
+kernel_subdirs := common driver process
 	
 
 
@@ -33,9 +33,7 @@ entry.o: exception/entry.S
 	gcc -E exception/entry.S > exception/entry.s
 	as $(ASFLAGS) -o exception/entry.o exception/entry.s
 
-procs.o: process/proc.S
-	gcc -E process/proc.S > process/proc.s
-	as $(ASFLAGS) -o process/procs.o process/proc.s
+
 
 
 
@@ -62,8 +60,6 @@ mm.o: mm/mm.c
 slab.o: mm/slab.c
 	gcc $(CFLAGS) -c mm/slab.c -o mm/slab.o
 
-process.o: process/process.c
-	gcc $(CFLAGS) -c process/process.c -o process/process.o
 
 sched.o: sched/sched.c
 	gcc $(CFLAGS) -c sched/sched.c -o sched/sched.o
@@ -150,15 +146,15 @@ uart.o: driver/uart/uart.c
 
 all: kernel
 
-	ld -b elf64-x86-64 -z muldefs -o kernel  head.o main.o $(shell find . -name "*.o") -T link.lds
+	ld -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") -T link.lds
 	objcopy -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../bin/kernel/kernel.elf
 
-kernel: head.o entry.o procs.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o sched.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o rtc.o HPET.o softirq.o timer.o fat32.o MBR.o VFS.o $(OBJ_LIST)
+kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o sched.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o rtc.o HPET.o softirq.o timer.o fat32.o MBR.o VFS.o $(OBJ_LIST)
 	
 	@list='$(kernel_subdirs)'; for subdir in $$list; do \
     		echo "make all in $$subdir";\
     		cd $$subdir;\
-    		 $(MAKE) all CFLAGS="$(CFLAGS)";\
+    		$(MAKE) all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)";\
     		cd ..;\
 	done
 

+ 9 - 11
kernel/common/glib.h

@@ -11,8 +11,6 @@
 #include <common/miniLibc/stddef.h>
 #include <arch/arch.h>
 
-
-
 #define sti() __asm__ __volatile__("sti\n\t" :: \
                                        : "memory") //开启外部中断
 #define cli() __asm__ __volatile__("cli\n\t" :: \
@@ -105,24 +103,24 @@ static inline void list_add(struct List *entry, struct List *node)
     entry->next = node;
 }
 
+/**
+ * @brief 将node添加到给定的list的结尾(也就是当前节点的前面)
+ * @param entry 列表的入口
+ * @param node 待添加的节点
+ */
 static inline void list_append(struct List *entry, struct List *node)
 {
-    /**
-     * @brief 将node添加到给定的list的结尾(也就是当前节点的前面)
-     * @param entry 列表的入口
-     * @param node 待添加的节点
-     */
 
     struct List *tail = entry->prev;
     list_add(tail, node);
 }
 
+/**
+ * @brief 从列表中删除节点
+ * @param entry 待删除的节点
+ */
 static inline void list_del(struct List *entry)
 {
-    /**
-     * @brief 从列表中删除节点
-     * @param entry 待删除的节点
-     */
 
     entry->next->prev = entry->prev;
     entry->prev->next = entry->next;

+ 2 - 1
kernel/driver/disk/ahci/ahci.c

@@ -465,7 +465,8 @@ static struct ahci_request_packet_t *ahci_make_request(long cmd, uint64_t base_a
 void ahci_end_request()
 {
     ahci_req_queue.in_service->wait_queue.pcb->state = PROC_RUNNING;
-    ahci_req_queue.in_service->wait_queue.pcb->flags |= PF_NEED_SCHED;
+    // ahci_req_queue.in_service->wait_queue.pcb->flags |= PF_NEED_SCHED;
+    // current_pcb->flags |= PF_NEED_SCHED;
     kfree((uint64_t *)ahci_req_queue.in_service);
     ahci_req_queue.in_service = NULL;
 

+ 137 - 1
kernel/driver/keyboard/ps2_keyboard.c

@@ -3,14 +3,32 @@
 #include "../../mm/mm.h"
 #include "../../mm/slab.h"
 #include "../../common/printk.h"
+#include <filesystem/VFS/VFS.h>
+#include <process/wait_queue.h>
 
+// 键盘输入缓冲区
 static struct ps2_keyboard_input_buffer *kb_buf_ptr = NULL;
+// 缓冲区等待队列
+static wait_queue_node_t ps2_keyboard_wait_queue;
 
 // 功能键标志变量
 static bool shift_l, shift_r, ctrl_l, ctrl_r, alt_l, alt_r;
 static bool gui_l, gui_r, apps, insert, home, pgup, del, end, pgdn, arrow_u, arrow_l, arrow_d, arrow_r;
 static bool kp_forward_slash, kp_en;
 
+/**
+ * @brief 重置ps2键盘输入缓冲区
+ *
+ * @param kbp 缓冲区对象指针
+ */
+static void ps2_keyboard_reset_buffer(struct ps2_keyboard_input_buffer *kbp)
+{
+    kbp->ptr_head = kb_buf_ptr->buffer;
+    kbp->ptr_tail = kb_buf_ptr->buffer;
+    kbp->count = 0;
+    // 清空输入缓冲区
+    memset(kbp->buffer, 0, ps2_keyboard_buffer_size);
+}
 struct apic_IO_APIC_RTE_entry entry;
 
 hardware_intr_controller ps2_keyboard_intr_controller =
@@ -23,6 +41,120 @@ hardware_intr_controller ps2_keyboard_intr_controller =
 
 };
 
+/**
+ * @brief 打开键盘文件
+ *
+ * @param inode 所在的inode
+ * @param filp 文件指针
+ * @return long
+ */
+long ps2_keyboard_open(struct vfs_index_node_t *inode, struct vfs_file_t *filp)
+{
+    filp->private_data = (void *)kb_buf_ptr;
+    ps2_keyboard_reset_buffer(kb_buf_ptr);
+    return 0;
+}
+
+/**
+ * @brief 关闭键盘文件
+ *
+ * @param inode 所在的inode
+ * @param filp 文件指针
+ * @return long
+ */
+long ps2_keyboard_close(struct vfs_index_node_t *inode, struct vfs_file_t *filp)
+{
+    filp->private_data = NULL;
+    ps2_keyboard_reset_buffer(kb_buf_ptr);
+    return 0;
+}
+
+/**
+ * @brief 键盘io控制接口
+ *
+ * @param inode 所在的inode
+ * @param filp 键盘文件指针
+ * @param cmd 命令
+ * @param arg 参数
+ * @return long
+ */
+long ps2_keyboard_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *filp, uint64_t cmd, uint64_t arg)
+{
+    switch (cmd)
+    {
+    case KEYBOARD_CMD_RESET_BUFFER:
+        ps2_keyboard_reset_buffer(kb_buf_ptr);
+        break;
+
+    default:
+        break;
+    }
+    return 0;
+}
+
+/**
+ * @brief 读取键盘文件的操作接口
+ *
+ * @param filp 文件指针
+ * @param buf 输出缓冲区
+ * @param count 要读取的字节数
+ * @param position 读取的位置
+ * @return long 读取的字节数
+ */
+long ps2_keyboard_read(struct vfs_file_t *filp, char *buf, int64_t count, long *position)
+{
+    // 缓冲区为空则等待
+    if (kb_buf_ptr->count == 0)
+        wait_queue_sleep_on(&ps2_keyboard_wait_queue);
+
+    long counter = kb_buf_ptr->count >= count ? count : kb_buf_ptr->count;
+
+    uint8_t *tail = kb_buf_ptr->ptr_tail;
+
+    // 要读取的部分没有越过缓冲区末尾
+    if (counter <= (kb_buf_ptr->buffer + ps2_keyboard_buffer_size - tail))
+    {
+        copy_to_user(buf, tail, counter);
+        kb_buf_ptr->ptr_tail += counter;
+    }
+    else // 要读取的部分越过了缓冲区的末尾,进行循环
+    {
+        uint64_t tmp = (kb_buf_ptr->buffer + ps2_keyboard_buffer_size - tail);
+        copy_to_user(buf, tail, tmp);
+        copy_to_user(buf, kb_buf_ptr->ptr_head, counter - tmp);
+        kb_buf_ptr->ptr_tail = kb_buf_ptr->ptr_head + (counter - tmp);
+    }
+
+    kb_buf_ptr->count -= counter;
+    return counter;
+}
+
+/**
+ * @brief 键盘文件写入接口(无作用,空)
+ *
+ * @param filp
+ * @param buf
+ * @param count
+ * @param position
+ * @return long
+ */
+long ps2_keyboard_write(struct vfs_file_t *filp, char *buf, int64_t count, long *position)
+{
+    return 0;
+}
+/**
+ * @brief ps2键盘驱动的虚拟文件接口
+ *
+ */
+struct vfs_file_operations_t ps2_keyboard_fops =
+    {
+        .open = ps2_keyboard_open,
+        .close = ps2_keyboard_close,
+        .ioctl = ps2_keyboard_ioctl,
+        .read = ps2_keyboard_read,
+        .write = ps2_keyboard_write,
+};
+
 /**
  * @brief 键盘中断处理函数(中断上半部)
  *  将数据存入缓冲区
@@ -49,6 +181,8 @@ void ps2_keyboard_handler(ul irq_num, ul param, struct pt_regs *regs)
     *kb_buf_ptr->ptr_head = x;
     ++(kb_buf_ptr->count);
     ++(kb_buf_ptr->ptr_head);
+
+    wait_queue_wakeup(&ps2_keyboard_wait_queue, PROC_UNINTERRUPTIBLE);
 }
 /**
  * @brief 初始化键盘驱动程序的函数
@@ -56,7 +190,7 @@ void ps2_keyboard_handler(ul irq_num, ul param, struct pt_regs *regs)
  */
 void ps2_keyboard_init()
 {
-    
+
     // ======= 初始化键盘循环队列缓冲区 ===========
 
     // 申请键盘循环队列缓冲区的内存
@@ -102,6 +236,8 @@ void ps2_keyboard_init()
     alt_l = false;
     alt_r = false;
 
+    wait_queue_init(&ps2_keyboard_wait_queue, NULL);
+    
     // 注册中断处理程序
     irq_register(PS2_KEYBOARD_INTR_VECTOR, &entry, &ps2_keyboard_handler, (ul)kb_buf_ptr, &ps2_keyboard_intr_controller, "ps/2 keyboard");
     kdebug("kb registered.");

+ 2 - 0
kernel/driver/keyboard/ps2_keyboard.h

@@ -7,6 +7,8 @@
 // 定义键盘循环队列缓冲区大小为100bytes
 #define ps2_keyboard_buffer_size 100
 
+#define KEYBOARD_CMD_RESET_BUFFER 1
+
 /**
  * @brief 键盘循环队列缓冲区结构体
  *

+ 1 - 1
kernel/driver/video/video.c

@@ -87,7 +87,7 @@ int video_init(bool level)
     if (level)
     {
         // 启用双缓冲后,使能printk滚动动画
-        printk_enable_animation();
+        // printk_enable_animation();
         // 初始化第一个屏幕刷新任务
         struct timer_func_list_t *tmp = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0);
         timer_func_init(tmp, &video_refresh_framebuffer, NULL, REFRESH_INTERVAL);

+ 16 - 0
kernel/process/Makefile

@@ -0,0 +1,16 @@
+
+all: procs.o process.o wait_queue.o
+
+CFLAGS += -I .
+
+
+
+procs.o: proc.S
+	gcc -E proc.S > proc.s
+	as $(ASFLAGS) -o procs.o proc.s
+
+process.o: process.c
+	gcc $(CFLAGS) -c process.c -o process.o
+
+wait_queue.o: wait_queue.c
+	gcc $(CFLAGS) -c wait_queue.c -o wait_queue.o

+ 4 - 7
kernel/process/process.c

@@ -18,12 +18,7 @@ long process_global_pid = 1;              // 系统中最大的pid
 extern void system_call(void);
 extern void kernel_thread_func(void);
 
-/**
- * @brief 将进程加入到调度器的就绪队列中
- *
- * @param pcb 进程的pcb
- */
-static inline void process_wakeup(struct process_control_block *pcb);
+
 
 ul _stack_start; // initial proc的栈基地址(虚拟地址)
 struct mm_struct initial_mm = {0};
@@ -820,10 +815,12 @@ struct process_control_block *process_get_pcb(long pid)
  *
  * @param pcb 进程的pcb
  */
-static inline void process_wakeup(struct process_control_block *pcb)
+void process_wakeup(struct process_control_block *pcb)
 {
     pcb->state = PROC_RUNNING;
     sched_cfs_enqueue(pcb);
+    // 将当前进程标志为需要调度,缩短新进程被wakeup的时间
+    current_pcb->flags |= PF_NEED_SCHED;
 }
 
 /**

+ 7 - 0
kernel/process/process.h

@@ -273,6 +273,13 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
  */
 struct process_control_block *process_get_pcb(long pid);
 
+/**
+ * @brief 将进程加入到调度器的就绪队列中
+ *
+ * @param pcb 进程的pcb
+ */
+void process_wakeup(struct process_control_block *pcb);
+
 /**
  * @brief 切换页表
  * @param prev 前一个进程的pcb

+ 3 - 21
kernel/process/semaphore.h

@@ -14,28 +14,8 @@
 
 #include <process/process.h>
 #include <sched/sched.h>
+#include "wait_queue.h"
 
-/**
- * @brief 信号量的等待队列
- *
- */
-typedef struct
-{
-    struct List wait_list;
-    struct process_control_block *pcb;
-} wait_queue_node_t;
-
-/**
- * @brief 初始化信号量的等待队列
- *
- * @param wait_queue 等待队列
- * @param pcb pcb
- */
-void wait_queue_init(wait_queue_node_t *wait_queue, struct process_control_block *pcb)
-{
-    list_init(&wait_queue->wait_list);
-    wait_queue->pcb = pcb;
-}
 
 /**
  * @brief 信号量的结构体
@@ -97,5 +77,7 @@ void semaphore_up(semaphore_t *sema)
 
         wq->pcb->state = PROC_RUNNING;
         sched_cfs_enqueue(wq->pcb);
+        // 当前进程缺少需要的资源,立即标为需要被调度
+        current_pcb->flags |= PF_NEED_SCHED;
     }
 }

+ 65 - 0
kernel/process/wait_queue.c

@@ -0,0 +1,65 @@
+#include "wait_queue.h"
+#include <sched/sched.h>
+#include <process/process.h>
+
+/**
+ * @brief 初始化等待队列
+ *
+ * @param wait_queue 等待队列
+ * @param pcb pcb
+ */
+void wait_queue_init(wait_queue_node_t *wait_queue, struct process_control_block *pcb)
+{
+    list_init(&wait_queue->wait_list);
+    wait_queue->pcb = pcb;
+}
+
+/**
+ * @brief 在等待队列上进行等待
+ *
+ * @param wait_queue_head 队列头指针
+ */
+void wait_queue_sleep_on(wait_queue_node_t *wait_queue_head)
+{
+    wait_queue_node_t wait;
+    wait_queue_init(&wait, current_pcb);
+    current_pcb->state = PROC_UNINTERRUPTIBLE;
+    list_append(&wait_queue_head->wait_list, &wait.wait_list);
+
+    sched_cfs();
+}
+
+/**
+ * @brief 在等待队列上进行等待(允许中断)
+ * 
+ * @param wait_queue_head 队列头指针
+ */
+void wait_queue_sleep_on_interriptible(wait_queue_node_t * wait_queue_head)
+{
+    wait_queue_node_t wait;
+    wait_queue_init(&wait, current_pcb);
+    current_pcb->state = PROC_INTERRUPTIBLE;
+    list_append(&wait_queue_head->wait_list, &wait.wait_list);
+
+    sched_cfs();
+}
+
+/**
+ * @brief 唤醒在等待队列的头部的进程
+ * 
+ * @param wait_queue_head 
+ * @param state 
+ */
+void wait_queue_wakeup(wait_queue_node_t * wait_queue_head, int64_t state)
+{
+    if(list_empty(&wait_queue_head->wait_list))
+        return;
+    wait_queue_node_t * wait = container_of(list_next(&wait_queue_head->wait_list), wait_queue_node_t, wait_list);
+
+    // 符合唤醒条件
+    if(wait->pcb->state & state)
+    {
+        list_del(&wait->wait_list);
+        process_wakeup(wait->pcb);
+    }
+}

+ 42 - 0
kernel/process/wait_queue.h

@@ -0,0 +1,42 @@
+#pragma once
+#include <common/glib.h>
+#include <process/process.h>
+/**
+ * @brief 信号量的等待队列
+ *
+ */
+typedef struct
+{
+    struct List wait_list;
+    struct process_control_block *pcb;
+} wait_queue_node_t;
+
+/**
+ * @brief 初始化等待队列
+ *
+ * @param wait_queue 等待队列
+ * @param pcb pcb
+ */
+void wait_queue_init(wait_queue_node_t *wait_queue, struct process_control_block *pcb);
+
+/**
+ * @brief 在等待队列上进行等待
+ * 
+ * @param wait_queue_head 队列头指针
+ */
+void wait_queue_sleep_on(wait_queue_node_t * wait_queue_head);
+
+/**
+ * @brief 在等待队列上进行等待(允许中断)
+ * 
+ * @param wait_queue_head 队列头指针
+ */
+void wait_queue_sleep_on_interriptible(wait_queue_node_t * wait_queue_head);
+
+/**
+ * @brief 唤醒在等待队列的头部的进程
+ * 
+ * @param wait_queue_head 队列头
+ * @param state 要唤醒的进程的状态
+ */
+void wait_queue_wakeup(wait_queue_node_t * wait_queue_head, int64_t state);